]> BookStack Code Mirror - bookstack/blob - app/Exports/ImportRepo.php
ZIP Imports: Finished off core import logic
[bookstack] / app / Exports / ImportRepo.php
1 <?php
2
3 namespace BookStack\Exports;
4
5 use BookStack\Entities\Models\Entity;
6 use BookStack\Entities\Queries\EntityQueries;
7 use BookStack\Exceptions\FileUploadException;
8 use BookStack\Exceptions\ZipExportException;
9 use BookStack\Exceptions\ZipImportException;
10 use BookStack\Exceptions\ZipValidationException;
11 use BookStack\Exports\ZipExports\Models\ZipExportBook;
12 use BookStack\Exports\ZipExports\Models\ZipExportChapter;
13 use BookStack\Exports\ZipExports\Models\ZipExportPage;
14 use BookStack\Exports\ZipExports\ZipExportReader;
15 use BookStack\Exports\ZipExports\ZipExportValidator;
16 use BookStack\Exports\ZipExports\ZipImportRunner;
17 use BookStack\Uploads\FileStorage;
18 use Illuminate\Database\Eloquent\Collection;
19 use Symfony\Component\HttpFoundation\File\UploadedFile;
20
21 class ImportRepo
22 {
23     public function __construct(
24         protected FileStorage $storage,
25         protected ZipImportRunner $importer,
26         protected EntityQueries $entityQueries,
27     ) {
28     }
29
30     /**
31      * @return Collection<Import>
32      */
33     public function getVisibleImports(): Collection
34     {
35         $query = Import::query();
36
37         if (!userCan('settings-manage')) {
38             $query->where('created_by', user()->id);
39         }
40
41         return $query->get();
42     }
43
44     public function findVisible(int $id): Import
45     {
46         $query = Import::query();
47
48         if (!userCan('settings-manage')) {
49             $query->where('created_by', user()->id);
50         }
51
52         return $query->findOrFail($id);
53     }
54
55     /**
56      * @throws FileUploadException
57      * @throws ZipValidationException
58      * @throws ZipExportException
59      */
60     public function storeFromUpload(UploadedFile $file): Import
61     {
62         $zipPath = $file->getRealPath();
63         $reader = new ZipExportReader($zipPath);
64
65         $errors = (new ZipExportValidator($reader))->validate();
66         if ($errors) {
67             throw new ZipValidationException($errors);
68         }
69
70         $exportModel = $reader->decodeDataToExportModel();
71
72         $import = new Import();
73         $import->type = match (get_class($exportModel)) {
74             ZipExportPage::class => 'page',
75             ZipExportChapter::class => 'chapter',
76             ZipExportBook::class => 'book',
77         };
78
79         $import->name = $exportModel->name;
80         $import->created_by = user()->id;
81         $import->size = filesize($zipPath);
82
83         $exportModel->metadataOnly();
84         $import->metadata = json_encode($exportModel);
85
86         $path = $this->storage->uploadFile(
87             $file,
88             'uploads/files/imports/',
89             '',
90             'zip'
91         );
92
93         $import->path = $path;
94         $import->save();
95
96         return $import;
97     }
98
99     /**
100      * @throws ZipValidationException|ZipImportException
101      */
102     public function runImport(Import $import, ?string $parent = null): ?Entity
103     {
104         $parentModel = null;
105         if ($import->type === 'page' || $import->type === 'chapter') {
106             $parentModel = $parent ? $this->entityQueries->findVisibleByStringIdentifier($parent) : null;
107         }
108
109         return $this->importer->run($import, $parentModel);
110     }
111
112     public function deleteImport(Import $import): void
113     {
114         $this->storage->delete($import->path);
115         $import->delete();
116     }
117 }