3 namespace BookStack\Exports\ZipExports;
5 use BookStack\Entities\Models\Book;
6 use BookStack\Entities\Models\Chapter;
7 use BookStack\Entities\Models\Page;
8 use BookStack\Exceptions\ZipExportException;
9 use BookStack\Exports\ZipExports\Models\ZipExportBook;
10 use BookStack\Exports\ZipExports\Models\ZipExportChapter;
11 use BookStack\Exports\ZipExports\Models\ZipExportPage;
14 class ZipExportBuilder
16 protected array $data = [];
18 public function __construct(
19 protected ZipExportFiles $files,
20 protected ZipExportReferences $references,
25 * @throws ZipExportException
27 public function buildForPage(Page $page): string
29 $exportPage = ZipExportPage::fromModel($page, $this->files);
30 $this->data['page'] = $exportPage;
32 $this->references->addPage($exportPage);
34 return $this->build();
38 * @throws ZipExportException
40 public function buildForChapter(Chapter $chapter): string
42 $exportChapter = ZipExportChapter::fromModel($chapter, $this->files);
43 $this->data['chapter'] = $exportChapter;
45 $this->references->addChapter($exportChapter);
47 return $this->build();
51 * @throws ZipExportException
53 public function buildForBook(Book $book): string
55 $exportBook = ZipExportBook::fromModel($book, $this->files);
56 $this->data['book'] = $exportBook;
58 $this->references->addBook($exportBook);
60 return $this->build();
64 * @throws ZipExportException
66 protected function build(): string
68 $this->references->buildReferences($this->files);
70 $this->data['exported_at'] = date(DATE_ATOM);
71 $this->data['instance'] = [
72 'id' => setting('instance-id', ''),
73 'version' => trim(file_get_contents(base_path('version'))),
76 $zipFile = tempnam(sys_get_temp_dir(), 'bszip-');
77 $zip = new ZipArchive();
78 $opened = $zip->open($zipFile, ZipArchive::CREATE);
79 if ($opened !== true) {
80 throw new ZipExportException('Failed to create zip file for export.');
83 $zip->addFromString('data.json', json_encode($this->data));
84 $zip->addEmptyDir('files');
90 $this->files->extractEach(function ($filePath, $fileRef) use ($zip, &$toRemove, &$addedNames) {
91 $entryName = "files/$fileRef";
92 $zip->addFile($filePath, $entryName);
93 $toRemove[] = $filePath;
94 $addedNames[] = $entryName;
96 } catch (\Exception $exception) {
97 // Cleanup the files we've processed so far and respond back with error
98 foreach ($toRemove as $file) {
101 foreach ($addedNames as $name) {
102 $zip->deleteName($name);
106 throw new ZipExportException("Failed to add files for ZIP export, received error: " . $exception->getMessage());
111 foreach ($toRemove as $file) {