]> BookStack Code Mirror - bookstack/blob - app/Exports/ZipExports/ZipExportReader.php
c3e47da048da26c5988fb9d26aea27cb442b8f3c
[bookstack] / app / Exports / ZipExports / ZipExportReader.php
1 <?php
2
3 namespace BookStack\Exports\ZipExports;
4
5 use BookStack\Exceptions\ZipExportException;
6 use BookStack\Exports\ZipExports\Models\ZipExportBook;
7 use BookStack\Exports\ZipExports\Models\ZipExportChapter;
8 use BookStack\Exports\ZipExports\Models\ZipExportModel;
9 use BookStack\Exports\ZipExports\Models\ZipExportPage;
10 use ZipArchive;
11
12 class ZipExportReader
13 {
14     protected ZipArchive $zip;
15     protected bool $open = false;
16
17     public function __construct(
18         protected string $zipPath,
19     ) {
20         $this->zip = new ZipArchive();
21     }
22
23     /**
24      * @throws ZipExportException
25      */
26     protected function open(): void
27     {
28         if ($this->open) {
29             return;
30         }
31
32         // Validate file exists
33         if (!file_exists($this->zipPath) || !is_readable($this->zipPath)) {
34             throw new ZipExportException(trans('errors.import_zip_cant_read'));
35         }
36
37         // Validate file is valid zip
38         $opened = $this->zip->open($this->zipPath, ZipArchive::RDONLY);
39         if ($opened !== true) {
40             throw new ZipExportException(trans('errors.import_zip_cant_read'));
41         }
42
43         $this->open = true;
44     }
45
46     public function close(): void
47     {
48         if ($this->open) {
49             $this->zip->close();
50             $this->open = false;
51         }
52     }
53
54     /**
55      * @throws ZipExportException
56      */
57     public function readData(): array
58     {
59         $this->open();
60
61         // Validate json data exists, including metadata
62         $jsonData = $this->zip->getFromName('data.json') ?: '';
63         $importData = json_decode($jsonData, true);
64         if (!$importData) {
65             throw new ZipExportException(trans('errors.import_zip_cant_decode_data'));
66         }
67
68         return $importData;
69     }
70
71     public function fileExists(string $fileName): bool
72     {
73         return $this->zip->statName("files/{$fileName}") !== false;
74     }
75
76     /**
77      * @throws ZipExportException
78      */
79     public function decodeDataToExportModel(): ZipExportBook|ZipExportChapter|ZipExportPage
80     {
81         $data = $this->readData();
82         if (isset($data['book'])) {
83             return ZipExportBook::fromArray($data['book']);
84         } else if (isset($data['chapter'])) {
85             return ZipExportChapter::fromArray($data['chapter']);
86         } else if (isset($data['page'])) {
87             return ZipExportPage::fromArray($data['page']);
88         }
89
90         throw new ZipExportException("Could not identify content in ZIP file data.");
91     }
92 }