12
12
use BookStack \Exceptions \ZipExportException ;
13
13
use BookStack \Exceptions \ZipImportException ;
14
14
use BookStack \Exports \Import ;
15
+ use BookStack \Exports \ZipExports \Models \ZipExportAttachment ;
15
16
use BookStack \Exports \ZipExports \Models \ZipExportBook ;
16
17
use BookStack \Exports \ZipExports \Models \ZipExportChapter ;
18
+ use BookStack \Exports \ZipExports \Models \ZipExportImage ;
17
19
use BookStack \Exports \ZipExports \Models \ZipExportPage ;
18
20
use BookStack \Exports \ZipExports \Models \ZipExportTag ;
21
+ use BookStack \Uploads \Attachment ;
22
+ use BookStack \Uploads \AttachmentService ;
19
23
use BookStack \Uploads \FileStorage ;
24
+ use BookStack \Uploads \Image ;
20
25
use BookStack \Uploads \ImageService ;
21
26
use Illuminate \Http \UploadedFile ;
22
27
23
28
class ZipImportRunner
24
29
{
25
- protected array $ tempFilesToCleanup = []; // TODO
30
+ protected array $ tempFilesToCleanup = [];
26
31
27
32
public function __construct (
28
33
protected FileStorage $ storage ,
29
34
protected PageRepo $ pageRepo ,
30
35
protected ChapterRepo $ chapterRepo ,
31
36
protected BookRepo $ bookRepo ,
32
37
protected ImageService $ imageService ,
38
+ protected AttachmentService $ attachmentService ,
33
39
protected ZipImportReferences $ references ,
34
40
) {
35
41
}
36
42
37
43
/**
44
+ * Run the import.
45
+ * Performs re-validation on zip, validation on parent provided, and permissions for importing
46
+ * the planned content, before running the import process.
47
+ * Returns the top-level entity item which was imported.
38
48
* @throws ZipImportException
39
49
*/
40
- public function run (Import $ import , ?Entity $ parent = null ): void
50
+ public function run (Import $ import , ?Entity $ parent = null ): ? Entity
41
51
{
42
52
$ zipPath = $ this ->getZipPath ($ import );
43
53
$ reader = new ZipExportReader ($ zipPath );
@@ -63,15 +73,40 @@ public function run(Import $import, ?Entity $parent = null): void
63
73
}
64
74
65
75
$ this ->ensurePermissionsPermitImport ($ exportModel );
76
+ $ entity = null ;
77
+
78
+ if ($ exportModel instanceof ZipExportBook) {
79
+ $ entity = $ this ->importBook ($ exportModel , $ reader );
80
+ } else if ($ exportModel instanceof ZipExportChapter) {
81
+ $ entity = $ this ->importChapter ($ exportModel , $ parent , $ reader );
82
+ } else if ($ exportModel instanceof ZipExportPage) {
83
+ $ entity = $ this ->importPage ($ exportModel , $ parent , $ reader );
84
+ }
66
85
67
- // TODO - Run import
68
86
// TODO - In transaction?
69
87
// TODO - Revert uploaded files if goes wrong
70
88
// TODO - Attachments
71
89
// TODO - Images
72
90
// (Both listed/stored in references)
73
91
74
92
$ this ->references ->replaceReferences ();
93
+
94
+ $ reader ->close ();
95
+ $ this ->cleanup ();
96
+
97
+ dd ('stop ' );
98
+
99
+ // TODO - Delete import/zip after import?
100
+ // Do this in parent repo?
101
+
102
+ return $ entity ;
103
+ }
104
+
105
+ protected function cleanup ()
106
+ {
107
+ foreach ($ this ->tempFilesToCleanup as $ file ) {
108
+ unlink ($ file );
109
+ }
75
110
}
76
111
77
112
protected function importBook (ZipExportBook $ exportBook , ZipExportReader $ reader ): Book
@@ -83,17 +118,26 @@ protected function importBook(ZipExportBook $exportBook, ZipExportReader $reader
83
118
'tags ' => $ this ->exportTagsToInputArray ($ exportBook ->tags ?? []),
84
119
]);
85
120
86
- // TODO - Parse/format description_html references
87
-
88
121
if ($ book ->cover ) {
89
122
$ this ->references ->addImage ($ book ->cover , null );
90
123
}
91
124
92
- // TODO - Pages
93
- foreach ($ exportBook ->chapters as $ exportChapter ) {
94
- $ this ->importChapter ($ exportChapter , $ book , $ reader );
125
+ $ children = [
126
+ ...$ exportBook ->chapters ,
127
+ ...$ exportBook ->pages ,
128
+ ];
129
+
130
+ usort ($ children , function (ZipExportPage |ZipExportChapter $ a , ZipExportPage |ZipExportChapter $ b ) {
131
+ return ($ a ->priority ?? 0 ) - ($ b ->priority ?? 0 );
132
+ });
133
+
134
+ foreach ($ children as $ child ) {
135
+ if ($ child instanceof ZipExportChapter) {
136
+ $ this ->importChapter ($ child , $ book , $ reader );
137
+ } else if ($ child instanceof ZipExportPage) {
138
+ $ this ->importPage ($ child , $ book , $ reader );
139
+ }
95
140
}
96
- // TODO - Sort chapters/pages by order
97
141
98
142
$ this ->references ->addBook ($ book , $ exportBook );
99
143
@@ -108,17 +152,14 @@ protected function importChapter(ZipExportChapter $exportChapter, Book $parent,
108
152
'tags ' => $ this ->exportTagsToInputArray ($ exportChapter ->tags ?? []),
109
153
], $ parent );
110
154
111
- // TODO - Parse/format description_html references
112
-
113
155
$ exportPages = $ exportChapter ->pages ;
114
156
usort ($ exportPages , function (ZipExportPage $ a , ZipExportPage $ b ) {
115
157
return ($ a ->priority ?? 0 ) - ($ b ->priority ?? 0 );
116
158
});
117
159
118
160
foreach ($ exportPages as $ exportPage ) {
119
- //
161
+ $ this -> importPage ( $ exportPage , $ chapter , $ reader );
120
162
}
121
- // TODO - Pages
122
163
123
164
$ this ->references ->addChapter ($ chapter , $ exportChapter );
124
165
@@ -129,11 +170,13 @@ protected function importPage(ZipExportPage $exportPage, Book|Chapter $parent, Z
129
170
{
130
171
$ page = $ this ->pageRepo ->getNewDraftPage ($ parent );
131
172
132
- // TODO - Import attachments
133
- // TODO - Add attachment references
134
- // TODO - Import images
135
- // TODO - Add image references
136
- // TODO - Parse/format HTML
173
+ foreach ($ exportPage ->attachments as $ exportAttachment ) {
174
+ $ this ->importAttachment ($ exportAttachment , $ page , $ reader );
175
+ }
176
+
177
+ foreach ($ exportPage ->images as $ exportImage ) {
178
+ $ this ->importImage ($ exportImage , $ page , $ reader );
179
+ }
137
180
138
181
$ this ->pageRepo ->publishDraft ($ page , [
139
182
'name ' => $ exportPage ->name ,
@@ -147,6 +190,40 @@ protected function importPage(ZipExportPage $exportPage, Book|Chapter $parent, Z
147
190
return $ page ;
148
191
}
149
192
193
+ protected function importAttachment (ZipExportAttachment $ exportAttachment , Page $ page , ZipExportReader $ reader ): Attachment
194
+ {
195
+ if ($ exportAttachment ->file ) {
196
+ $ file = $ this ->zipFileToUploadedFile ($ exportAttachment ->file , $ reader );
197
+ $ attachment = $ this ->attachmentService ->saveNewUpload ($ file , $ page ->id );
198
+ $ attachment ->name = $ exportAttachment ->name ;
199
+ $ attachment ->save ();
200
+ } else {
201
+ $ attachment = $ this ->attachmentService ->saveNewFromLink (
202
+ $ exportAttachment ->name ,
203
+ $ exportAttachment ->link ?? '' ,
204
+ $ page ->id ,
205
+ );
206
+ }
207
+
208
+ $ this ->references ->addAttachment ($ attachment , $ exportAttachment ->id );
209
+
210
+ return $ attachment ;
211
+ }
212
+
213
+ protected function importImage (ZipExportImage $ exportImage , Page $ page , ZipExportReader $ reader ): Image
214
+ {
215
+ $ file = $ this ->zipFileToUploadedFile ($ exportImage ->file , $ reader );
216
+ $ image = $ this ->imageService ->saveNewFromUpload (
217
+ $ file ,
218
+ $ exportImage ->type ,
219
+ $ page ->id ,
220
+ );
221
+
222
+ $ this ->references ->addImage ($ image , $ exportImage ->id );
223
+
224
+ return $ image ;
225
+ }
226
+
150
227
protected function exportTagsToInputArray (array $ exportTags ): array
151
228
{
152
229
$ tags = [];
@@ -235,7 +312,7 @@ protected function ensurePermissionsPermitImport(ZipExportPage|ZipExportChapter|
235
312
}
236
313
237
314
if (count ($ attachments ) > 0 ) {
238
- if (userCan ('attachment-create-all ' )) {
315
+ if (! userCan ('attachment-create-all ' )) {
239
316
$ errors [] = 'You are lacking the required permissions to create attachments. ' ;
240
317
}
241
318
}
@@ -257,6 +334,8 @@ protected function getZipPath(Import $import): string
257
334
stream_copy_to_stream ($ stream , $ tempFile );
258
335
fclose ($ tempFile );
259
336
337
+ $ this ->tempFilesToCleanup [] = $ tempFilePath ;
338
+
260
339
return $ tempFilePath ;
261
340
}
262
341
}
0 commit comments