2024-10-15 23:14:11 +08:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace BookStack\Exports;
|
|
|
|
|
2024-10-19 22:41:07 +08:00
|
|
|
use BookStack\Activity\Models\Tag;
|
2024-10-15 23:14:11 +08:00
|
|
|
use BookStack\Entities\Models\Page;
|
|
|
|
use BookStack\Exceptions\ZipExportException;
|
2024-10-19 22:41:07 +08:00
|
|
|
use BookStack\Uploads\Attachment;
|
2024-10-15 23:14:11 +08:00
|
|
|
use ZipArchive;
|
|
|
|
|
|
|
|
class ZipExportBuilder
|
|
|
|
{
|
|
|
|
protected array $data = [];
|
|
|
|
|
2024-10-19 22:41:07 +08:00
|
|
|
public function __construct(
|
|
|
|
protected ZipExportFiles $files
|
|
|
|
) {
|
|
|
|
}
|
|
|
|
|
2024-10-15 23:14:11 +08:00
|
|
|
/**
|
|
|
|
* @throws ZipExportException
|
|
|
|
*/
|
|
|
|
public function buildForPage(Page $page): string
|
|
|
|
{
|
2024-10-19 22:41:07 +08:00
|
|
|
$this->data['page'] = $this->convertPage($page);
|
|
|
|
return $this->build();
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function convertPage(Page $page): array
|
|
|
|
{
|
|
|
|
$tags = array_map($this->convertTag(...), $page->tags()->get()->all());
|
|
|
|
$attachments = array_map($this->convertAttachment(...), $page->attachments()->get()->all());
|
|
|
|
|
|
|
|
return [
|
|
|
|
'id' => $page->id,
|
|
|
|
'name' => $page->name,
|
|
|
|
'html' => '', // TODO
|
|
|
|
'markdown' => '', // TODO
|
|
|
|
'priority' => $page->priority,
|
|
|
|
'attachments' => $attachments,
|
|
|
|
'images' => [], // TODO
|
|
|
|
'tags' => $tags,
|
2024-10-15 23:14:11 +08:00
|
|
|
];
|
2024-10-19 22:41:07 +08:00
|
|
|
}
|
2024-10-15 23:14:11 +08:00
|
|
|
|
2024-10-19 22:41:07 +08:00
|
|
|
protected function convertAttachment(Attachment $attachment): array
|
|
|
|
{
|
|
|
|
$data = [
|
|
|
|
'name' => $attachment->name,
|
|
|
|
'order' => $attachment->order,
|
|
|
|
];
|
|
|
|
|
|
|
|
if ($attachment->external) {
|
|
|
|
$data['link'] = $attachment->path;
|
|
|
|
} else {
|
|
|
|
$data['file'] = $this->files->referenceForAttachment($attachment);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $data;
|
|
|
|
}
|
|
|
|
|
|
|
|
protected function convertTag(Tag $tag): array
|
|
|
|
{
|
|
|
|
return [
|
|
|
|
'name' => $tag->name,
|
|
|
|
'value' => $tag->value,
|
|
|
|
'order' => $tag->order,
|
|
|
|
];
|
2024-10-15 23:14:11 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @throws ZipExportException
|
|
|
|
*/
|
|
|
|
protected function build(): string
|
|
|
|
{
|
|
|
|
$this->data['exported_at'] = date(DATE_ATOM);
|
|
|
|
$this->data['instance'] = [
|
2024-10-19 22:41:07 +08:00
|
|
|
'version' => trim(file_get_contents(base_path('version'))),
|
2024-10-15 23:14:11 +08:00
|
|
|
'id_ciphertext' => encrypt('bookstack'),
|
|
|
|
];
|
|
|
|
|
|
|
|
$zipFile = tempnam(sys_get_temp_dir(), 'bszip-');
|
|
|
|
$zip = new ZipArchive();
|
|
|
|
$opened = $zip->open($zipFile, ZipArchive::CREATE);
|
|
|
|
if ($opened !== true) {
|
|
|
|
throw new ZipExportException('Failed to create zip file for export.');
|
|
|
|
}
|
|
|
|
|
|
|
|
$zip->addFromString('data.json', json_encode($this->data));
|
|
|
|
$zip->addEmptyDir('files');
|
|
|
|
|
2024-10-19 22:41:07 +08:00
|
|
|
$toRemove = [];
|
|
|
|
$this->files->extractEach(function ($filePath, $fileRef) use ($zip, &$toRemove) {
|
|
|
|
$zip->addFile($filePath, "files/$fileRef");
|
|
|
|
$toRemove[] = $filePath;
|
|
|
|
});
|
|
|
|
|
|
|
|
$zip->close();
|
|
|
|
|
|
|
|
foreach ($toRemove as $file) {
|
|
|
|
unlink($file);
|
|
|
|
}
|
|
|
|
|
2024-10-15 23:14:11 +08:00
|
|
|
return $zipFile;
|
|
|
|
}
|
|
|
|
}
|