Skip to content

Commit 42ada66

Browse files
committed
ZIP Exports: Added core logic for books/chapters
1 parent f732ef0 commit 42ada66

File tree

7 files changed

+195
-9
lines changed

7 files changed

+195
-9
lines changed

app/Entities/Models/Chapter.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public function defaultTemplate(): BelongsTo
6060

6161
/**
6262
* Get the visible pages in this chapter.
63+
* @returns Collection<Page>
6364
*/
6465
public function getVisiblePages(): Collection
6566
{
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
3+
namespace BookStack\Exports\ZipExports\Models;
4+
5+
use BookStack\Entities\Models\Book;
6+
use BookStack\Entities\Models\Chapter;
7+
use BookStack\Entities\Models\Page;
8+
use BookStack\Exports\ZipExports\ZipExportFiles;
9+
10+
class ZipExportBook extends ZipExportModel
11+
{
12+
public ?int $id = null;
13+
public string $name;
14+
public ?string $description_html = null;
15+
public ?string $cover = null;
16+
/** @var ZipExportChapter[] */
17+
public array $chapters = [];
18+
/** @var ZipExportPage[] */
19+
public array $pages = [];
20+
/** @var ZipExportTag[] */
21+
public array $tags = [];
22+
23+
public static function fromModel(Book $model, ZipExportFiles $files): self
24+
{
25+
$instance = new self();
26+
$instance->id = $model->id;
27+
$instance->name = $model->name;
28+
$instance->description_html = $model->descriptionHtml();
29+
30+
if ($model->cover) {
31+
$instance->cover = $files->referenceForImage($model->cover);
32+
}
33+
34+
$instance->tags = ZipExportTag::fromModelArray($model->tags()->get()->all());
35+
36+
$chapters = [];
37+
$pages = [];
38+
39+
$children = $model->getDirectVisibleChildren()->all();
40+
foreach ($children as $child) {
41+
if ($child instanceof Chapter) {
42+
$chapters[] = $child;
43+
} else if ($child instanceof Page) {
44+
$pages[] = $child;
45+
}
46+
}
47+
48+
$instance->pages = ZipExportPage::fromModelArray($pages, $files);
49+
$instance->chapters = ZipExportChapter::fromModelArray($chapters, $files);
50+
51+
return $instance;
52+
}
53+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
namespace BookStack\Exports\ZipExports\Models;
4+
5+
use BookStack\Entities\Models\Chapter;
6+
use BookStack\Entities\Models\Page;
7+
use BookStack\Exports\ZipExports\ZipExportFiles;
8+
9+
class ZipExportChapter extends ZipExportModel
10+
{
11+
public ?int $id = null;
12+
public string $name;
13+
public ?string $description_html = null;
14+
public ?int $priority = null;
15+
/** @var ZipExportPage[] */
16+
public array $pages = [];
17+
/** @var ZipExportTag[] */
18+
public array $tags = [];
19+
20+
public static function fromModel(Chapter $model, ZipExportFiles $files): self
21+
{
22+
$instance = new self();
23+
$instance->id = $model->id;
24+
$instance->name = $model->name;
25+
$instance->description_html = $model->descriptionHtml();
26+
$instance->priority = $model->priority;
27+
$instance->tags = ZipExportTag::fromModelArray($model->tags()->get()->all());
28+
29+
$pages = $model->getVisiblePages()->filter(fn (Page $page) => !$page->draft)->all();
30+
$instance->pages = ZipExportPage::fromModelArray($pages, $files);
31+
32+
return $instance;
33+
}
34+
35+
/**
36+
* @param Chapter[] $chapterArray
37+
* @return self[]
38+
*/
39+
public static function fromModelArray(array $chapterArray, ZipExportFiles $files): array
40+
{
41+
return array_values(array_map(function (Chapter $chapter) use ($files) {
42+
return self::fromModel($chapter, $files);
43+
}, $chapterArray));
44+
}
45+
}

app/Exports/ZipExports/Models/ZipExportPage.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ public static function fromModel(Page $model, ZipExportFiles $files): self
2626
$instance->id = $model->id;
2727
$instance->name = $model->name;
2828
$instance->html = (new PageContent($model))->render();
29+
$instance->priority = $model->priority;
2930

3031
if (!empty($model->markdown)) {
3132
$instance->markdown = $model->markdown;
@@ -36,4 +37,15 @@ public static function fromModel(Page $model, ZipExportFiles $files): self
3637

3738
return $instance;
3839
}
40+
41+
/**
42+
* @param Page[] $pageArray
43+
* @return self[]
44+
*/
45+
public static function fromModelArray(array $pageArray, ZipExportFiles $files): array
46+
{
47+
return array_values(array_map(function (Page $page) use ($files) {
48+
return self::fromModel($page, $files);
49+
}, $pageArray));
50+
}
3951
}

app/Exports/ZipExports/ZipExportBuilder.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
namespace BookStack\Exports\ZipExports;
44

5+
use BookStack\Entities\Models\Book;
6+
use BookStack\Entities\Models\Chapter;
57
use BookStack\Entities\Models\Page;
68
use BookStack\Exceptions\ZipExportException;
9+
use BookStack\Exports\ZipExports\Models\ZipExportBook;
10+
use BookStack\Exports\ZipExports\Models\ZipExportChapter;
711
use BookStack\Exports\ZipExports\Models\ZipExportPage;
812
use ZipArchive;
913

@@ -30,6 +34,32 @@ public function buildForPage(Page $page): string
3034
return $this->build();
3135
}
3236

37+
/**
38+
* @throws ZipExportException
39+
*/
40+
public function buildForChapter(Chapter $chapter): string
41+
{
42+
$exportChapter = ZipExportChapter::fromModel($chapter, $this->files);
43+
$this->data['chapter'] = $exportChapter;
44+
45+
$this->references->addChapter($exportChapter);
46+
47+
return $this->build();
48+
}
49+
50+
/**
51+
* @throws ZipExportException
52+
*/
53+
public function buildForBook(Book $book): string
54+
{
55+
$exportBook = ZipExportBook::fromModel($book, $this->files);
56+
$this->data['book'] = $exportBook;
57+
58+
$this->references->addBook($exportBook);
59+
60+
return $this->build();
61+
}
62+
3363
/**
3464
* @throws ZipExportException
3565
*/

app/Exports/ZipExports/ZipExportReferences.php

Lines changed: 53 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use BookStack\App\Model;
66
use BookStack\Exports\ZipExports\Models\ZipExportAttachment;
7+
use BookStack\Exports\ZipExports\Models\ZipExportBook;
8+
use BookStack\Exports\ZipExports\Models\ZipExportChapter;
79
use BookStack\Exports\ZipExports\Models\ZipExportImage;
810
use BookStack\Exports\ZipExports\Models\ZipExportModel;
911
use BookStack\Exports\ZipExports\Models\ZipExportPage;
@@ -14,8 +16,10 @@ class ZipExportReferences
1416
{
1517
/** @var ZipExportPage[] */
1618
protected array $pages = [];
17-
protected array $books = [];
19+
/** @var ZipExportChapter[] */
1820
protected array $chapters = [];
21+
/** @var ZipExportBook[] */
22+
protected array $books = [];
1923

2024
/** @var ZipExportAttachment[] */
2125
protected array $attachments = [];
@@ -41,23 +45,64 @@ public function addPage(ZipExportPage $page): void
4145
}
4246
}
4347

48+
public function addChapter(ZipExportChapter $chapter): void
49+
{
50+
if ($chapter->id) {
51+
$this->chapters[$chapter->id] = $chapter;
52+
}
53+
54+
foreach ($chapter->pages as $page) {
55+
$this->addPage($page);
56+
}
57+
}
58+
59+
public function addBook(ZipExportBook $book): void
60+
{
61+
if ($book->id) {
62+
$this->chapters[$book->id] = $book;
63+
}
64+
65+
foreach ($book->pages as $page) {
66+
$this->addPage($page);
67+
}
68+
69+
foreach ($book->chapters as $chapter) {
70+
$this->addChapter($chapter);
71+
}
72+
}
73+
4474
public function buildReferences(ZipExportFiles $files): void
4575
{
46-
// Parse page content first
47-
foreach ($this->pages as $page) {
48-
$handler = function (Model $model) use ($files, $page) {
49-
return $this->handleModelReference($model, $page, $files);
76+
$createHandler = function (ZipExportModel $zipModel) use ($files) {
77+
return function (Model $model) use ($files, $zipModel) {
78+
return $this->handleModelReference($model, $zipModel, $files);
5079
};
80+
};
5181

82+
// Parse page content first
83+
foreach ($this->pages as $page) {
84+
$handler = $createHandler($page);
5285
$page->html = $this->parser->parse($page->html ?? '', $handler);
5386
if ($page->markdown) {
5487
$page->markdown = $this->parser->parse($page->markdown, $handler);
5588
}
5689
}
5790

58-
// dd('end');
59-
// TODO - Parse chapter desc html
60-
// TODO - Parse book desc html
91+
// Parse chapter description HTML
92+
foreach ($this->chapters as $chapter) {
93+
if ($chapter->description_html) {
94+
$handler = $createHandler($chapter);
95+
$chapter->description_html = $this->parser->parse($chapter->description_html, $handler);
96+
}
97+
}
98+
99+
// Parse book description HTML
100+
foreach ($this->books as $book) {
101+
if ($book->description_html) {
102+
$handler = $createHandler($book);
103+
$book->description_html = $this->parser->parse($book->description_html, $handler);
104+
}
105+
}
61106
}
62107

63108
protected function handleModelReference(Model $model, ZipExportModel $exportModel, ZipExportFiles $files): ?string

dev/docs/portable-zip-file-format.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ The `id_ciphertext` is the ciphertext of encrypting the text `bookstack`. This i
8787
- `id` - Number, optional, original ID for the book from exported system.
8888
- `name` - String, required, name/title of the book.
8989
- `description_html` - String, optional, HTML description content.
90-
- `cover` - String reference, options, reference to book cover image.
90+
- `cover` - String reference, optional, reference to book cover image.
9191
- `chapters` - [Chapter](#chapter) array, optional, chapters within this book.
9292
- `pages` - [Page](#page) array, optional, direct child pages for this book.
9393
- `tags` - [Tag](#tag) array, optional, tags assigned to this book.

0 commit comments

Comments
 (0)