ZIP Exports: Added core logic for books/chapters

This commit is contained in:
Dan Brown 2024-10-23 11:30:32 +01:00
parent f732ef05d5
commit 42ada66fdd
No known key found for this signature in database
GPG Key ID: 46D9F943C24A2EF9
7 changed files with 195 additions and 9 deletions

View File

@ -60,6 +60,7 @@ class Chapter extends BookChild
/**
* Get the visible pages in this chapter.
* @returns Collection<Page>
*/
public function getVisiblePages(): Collection
{

View File

@ -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;
}
}

View File

@ -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));
}
}

View 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));
}
}

View 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
*/

View 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
{
$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 = function (Model $model) use ($files, $page) {
return $this->handleModelReference($model, $page, $files);
};
$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

View 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.