]> BookStack Code Mirror - bookstack/commitdiff
ZIP Exports: Added core logic for books/chapters
authorDan Brown <redacted>
Wed, 23 Oct 2024 10:30:32 +0000 (11:30 +0100)
committerDan Brown <redacted>
Wed, 23 Oct 2024 10:30:32 +0000 (11:30 +0100)
app/Entities/Models/Chapter.php
app/Exports/ZipExports/Models/ZipExportBook.php [new file with mode: 0644]
app/Exports/ZipExports/Models/ZipExportChapter.php [new file with mode: 0644]
app/Exports/ZipExports/Models/ZipExportPage.php
app/Exports/ZipExports/ZipExportBuilder.php
app/Exports/ZipExports/ZipExportReferences.php
dev/docs/portable-zip-file-format.md

index c926aaa647a7d75501b55880e1cd2c834990f8fc..088d199da675286af90ea73c3f24ca396ede2347 100644 (file)
@@ -60,6 +60,7 @@ class Chapter extends BookChild
 
     /**
      * Get the visible pages in this chapter.
+     * @returns Collection<Page>
      */
     public function getVisiblePages(): Collection
     {
diff --git a/app/Exports/ZipExports/Models/ZipExportBook.php b/app/Exports/ZipExports/Models/ZipExportBook.php
new file mode 100644 (file)
index 0000000..5a0c580
--- /dev/null
@@ -0,0 +1,53 @@
+<?php
+
+namespace BookStack\Exports\ZipExports\Models;
+
+use BookStack\Entities\Models\Book;
+use BookStack\Entities\Models\Chapter;
+use BookStack\Entities\Models\Page;
+use BookStack\Exports\ZipExports\ZipExportFiles;
+
+class ZipExportBook extends ZipExportModel
+{
+    public ?int $id = null;
+    public string $name;
+    public ?string $description_html = null;
+    public ?string $cover = null;
+    /** @var ZipExportChapter[] */
+    public array $chapters = [];
+    /** @var ZipExportPage[] */
+    public array $pages = [];
+    /** @var ZipExportTag[] */
+    public array $tags = [];
+
+    public static function fromModel(Book $model, ZipExportFiles $files): self
+    {
+        $instance = new self();
+        $instance->id = $model->id;
+        $instance->name = $model->name;
+        $instance->description_html = $model->descriptionHtml();
+
+        if ($model->cover) {
+            $instance->cover = $files->referenceForImage($model->cover);
+        }
+
+        $instance->tags = ZipExportTag::fromModelArray($model->tags()->get()->all());
+
+        $chapters = [];
+        $pages = [];
+
+        $children = $model->getDirectVisibleChildren()->all();
+        foreach ($children as $child) {
+            if ($child instanceof Chapter) {
+                $chapters[] = $child;
+            } else if ($child instanceof Page) {
+                $pages[] = $child;
+            }
+        }
+
+        $instance->pages = ZipExportPage::fromModelArray($pages, $files);
+        $instance->chapters = ZipExportChapter::fromModelArray($chapters, $files);
+
+        return $instance;
+    }
+}
diff --git a/app/Exports/ZipExports/Models/ZipExportChapter.php b/app/Exports/ZipExports/Models/ZipExportChapter.php
new file mode 100644 (file)
index 0000000..cd5765f
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+
+namespace BookStack\Exports\ZipExports\Models;
+
+use BookStack\Entities\Models\Chapter;
+use BookStack\Entities\Models\Page;
+use BookStack\Exports\ZipExports\ZipExportFiles;
+
+class ZipExportChapter extends ZipExportModel
+{
+    public ?int $id = null;
+    public string $name;
+    public ?string $description_html = null;
+    public ?int $priority = null;
+    /** @var ZipExportPage[] */
+    public array $pages = [];
+    /** @var ZipExportTag[] */
+    public array $tags = [];
+
+    public static function fromModel(Chapter $model, ZipExportFiles $files): self
+    {
+        $instance = new self();
+        $instance->id = $model->id;
+        $instance->name = $model->name;
+        $instance->description_html = $model->descriptionHtml();
+        $instance->priority = $model->priority;
+        $instance->tags = ZipExportTag::fromModelArray($model->tags()->get()->all());
+
+        $pages = $model->getVisiblePages()->filter(fn (Page $page) => !$page->draft)->all();
+        $instance->pages = ZipExportPage::fromModelArray($pages, $files);
+
+        return $instance;
+    }
+
+    /**
+     * @param Chapter[] $chapterArray
+     * @return self[]
+     */
+    public static function fromModelArray(array $chapterArray, ZipExportFiles $files): array
+    {
+        return array_values(array_map(function (Chapter $chapter) use ($files) {
+            return self::fromModel($chapter, $files);
+        }, $chapterArray));
+    }
+}
index bae46ca8225c96dd4b362f75d1961dd5ce19551d..8075595f228606b00701e91d4d883f41cc3d0f73 100644 (file)
@@ -26,6 +26,7 @@ class ZipExportPage extends ZipExportModel
         $instance->id = $model->id;
         $instance->name = $model->name;
         $instance->html = (new PageContent($model))->render();
+        $instance->priority = $model->priority;
 
         if (!empty($model->markdown)) {
             $instance->markdown = $model->markdown;
@@ -36,4 +37,15 @@ class ZipExportPage extends ZipExportModel
 
         return $instance;
     }
+
+    /**
+     * @param Page[] $pageArray
+     * @return self[]
+     */
+    public static function fromModelArray(array $pageArray, ZipExportFiles $files): array
+    {
+        return array_values(array_map(function (Page $page) use ($files) {
+            return self::fromModel($page, $files);
+        }, $pageArray));
+    }
 }
index 15edebea574fb344f3440e3e6cb6951fdab51b03..42fb03541c014a3c5a38ea18aaf05d3b63fddc6b 100644 (file)
@@ -2,8 +2,12 @@
 
 namespace BookStack\Exports\ZipExports;
 
+use BookStack\Entities\Models\Book;
+use BookStack\Entities\Models\Chapter;
 use BookStack\Entities\Models\Page;
 use BookStack\Exceptions\ZipExportException;
+use BookStack\Exports\ZipExports\Models\ZipExportBook;
+use BookStack\Exports\ZipExports\Models\ZipExportChapter;
 use BookStack\Exports\ZipExports\Models\ZipExportPage;
 use ZipArchive;
 
@@ -30,6 +34,32 @@ class ZipExportBuilder
         return $this->build();
     }
 
+    /**
+     * @throws ZipExportException
+     */
+    public function buildForChapter(Chapter $chapter): string
+    {
+        $exportChapter = ZipExportChapter::fromModel($chapter, $this->files);
+        $this->data['chapter'] = $exportChapter;
+
+        $this->references->addChapter($exportChapter);
+
+        return $this->build();
+    }
+
+    /**
+     * @throws ZipExportException
+     */
+    public function buildForBook(Book $book): string
+    {
+        $exportBook = ZipExportBook::fromModel($book, $this->files);
+        $this->data['book'] = $exportBook;
+
+        $this->references->addBook($exportBook);
+
+        return $this->build();
+    }
+
     /**
      * @throws ZipExportException
      */
index c3565aaa38347e9a53e363b3cff90df699cb639f..1fce0fc972eb72c631217bfc277b77f4ecd2d210 100644 (file)
@@ -4,6 +4,8 @@ namespace BookStack\Exports\ZipExports;
 
 use BookStack\App\Model;
 use BookStack\Exports\ZipExports\Models\ZipExportAttachment;
+use BookStack\Exports\ZipExports\Models\ZipExportBook;
+use BookStack\Exports\ZipExports\Models\ZipExportChapter;
 use BookStack\Exports\ZipExports\Models\ZipExportImage;
 use BookStack\Exports\ZipExports\Models\ZipExportModel;
 use BookStack\Exports\ZipExports\Models\ZipExportPage;
@@ -14,8 +16,10 @@ class ZipExportReferences
 {
     /** @var ZipExportPage[] */
     protected array $pages = [];
-    protected array $books = [];
+    /** @var ZipExportChapter[] */
     protected array $chapters = [];
+    /** @var ZipExportBook[] */
+    protected array $books = [];
 
     /** @var ZipExportAttachment[] */
     protected array $attachments = [];
@@ -41,23 +45,64 @@ class ZipExportReferences
         }
     }
 
+    public function addChapter(ZipExportChapter $chapter): void
+    {
+        if ($chapter->id) {
+            $this->chapters[$chapter->id] = $chapter;
+        }
+
+        foreach ($chapter->pages as $page) {
+            $this->addPage($page);
+        }
+    }
+
+    public function addBook(ZipExportBook $book): void
+    {
+        if ($book->id) {
+            $this->chapters[$book->id] = $book;
+        }
+
+        foreach ($book->pages as $page) {
+            $this->addPage($page);
+        }
+
+        foreach ($book->chapters as $chapter) {
+            $this->addChapter($chapter);
+        }
+    }
+
     public function buildReferences(ZipExportFiles $files): void
     {
-        // Parse page content first
-        foreach ($this->pages as $page) {
-            $handler = function (Model $model) use ($files, $page) {
-                return $this->handleModelReference($model, $page, $files);
+        $createHandler = function (ZipExportModel $zipModel) use ($files) {
+            return function (Model $model) use ($files, $zipModel) {
+                return $this->handleModelReference($model, $zipModel, $files);
             };
+        };
 
+        // Parse page content first
+        foreach ($this->pages as $page) {
+            $handler = $createHandler($page);
             $page->html = $this->parser->parse($page->html ?? '', $handler);
             if ($page->markdown) {
                 $page->markdown = $this->parser->parse($page->markdown, $handler);
             }
         }
 
-//        dd('end');
-        // TODO - Parse chapter desc html
-        // TODO - Parse book desc html
+        // Parse chapter description HTML
+        foreach ($this->chapters as $chapter) {
+            if ($chapter->description_html) {
+                $handler = $createHandler($chapter);
+                $chapter->description_html = $this->parser->parse($chapter->description_html, $handler);
+            }
+        }
+
+        // Parse book description HTML
+        foreach ($this->books as $book) {
+            if ($book->description_html) {
+                $handler = $createHandler($book);
+                $book->description_html = $this->parser->parse($book->description_html, $handler);
+            }
+        }
     }
 
     protected function handleModelReference(Model $model, ZipExportModel $exportModel, ZipExportFiles $files): ?string
index 1ba5872018c92175de757f764b9e29156cde7cc1..6cee7356d2360370ca90be351e27a3ba51c9e350 100644 (file)
@@ -87,7 +87,7 @@ The `id_ciphertext` is the ciphertext of encrypting the text `bookstack`. This i
 - `id` - Number, optional, original ID for the book from exported system.
 - `name` - String, required, name/title of the book.
 - `description_html` - String, optional, HTML description content.
-- `cover` - String reference, options, reference to book cover image.
+- `cover` - String reference, optional, reference to book cover image.
 - `chapters` - [Chapter](#chapter) array, optional, chapters within this book.
 - `pages` - [Page](#page) array, optional, direct child pages for this book.
 - `tags` - [Tag](#tag) array, optional, tags assigned to this book.
Morty Proxy This is a proxified and sanitized view of the page, visit original site.