Skip to content

Commit 8645aea

Browse files
committed
ZIP Imports: Started testing core import logic
Fixed image size handling, and lack of attachment reference replacements during testing.
1 parent 7681e32 commit 8645aea

File tree

5 files changed

+170
-6
lines changed

5 files changed

+170
-6
lines changed

app/Exports/ZipExports/ZipImportReferences.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,12 @@ protected function handleReference(string $type, int $id): ?string
9797
} else if ($model instanceof Image) {
9898
if ($model->type === 'gallery') {
9999
$this->imageResizer->loadGalleryThumbnailsForImage($model, false);
100-
return $model->thumbs['gallery'] ?? $model->url;
100+
return $model->thumbs['display'] ?? $model->url;
101101
}
102102

103103
return $model->url;
104+
} else if ($model instanceof Attachment) {
105+
return $model->getUrl(false);
104106
}
105107

106108
return null;

app/Exports/ZipExports/ZipImportRunner.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,10 @@ protected function importImage(ZipExportImage $exportImage, Page $page, ZipExpor
233233
$file,
234234
$exportImage->type,
235235
$page->id,
236+
null,
237+
null,
238+
true,
239+
$exportImage->name,
236240
);
237241

238242
$this->references->addImage($image, $exportImage->id);

app/Uploads/ImageService.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,10 @@ public function saveNewFromUpload(
3333
int $uploadedTo = 0,
3434
int $resizeWidth = null,
3535
int $resizeHeight = null,
36-
bool $keepRatio = true
36+
bool $keepRatio = true,
37+
string $imageName = '',
3738
): Image {
38-
$imageName = $uploadedFile->getClientOriginalName();
39+
$imageName = $imageName ?: $uploadedFile->getClientOriginalName();
3940
$imageData = file_get_contents($uploadedFile->getRealPath());
4041

4142
if ($resizeWidth !== null || $resizeHeight !== null) {

tests/Exports/ZipImportRunnerTest.php

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
namespace Tests\Exports;
44

5+
use BookStack\Entities\Models\Book;
6+
use BookStack\Entities\Models\Page;
57
use BookStack\Exports\ZipExports\ZipImportRunner;
8+
use BookStack\Uploads\Image;
69
use Tests\TestCase;
710

811
class ZipImportRunnerTest extends TestCase
@@ -15,6 +18,155 @@ protected function setUp(): void
1518
$this->runner = app()->make(ZipImportRunner::class);
1619
}
1720

21+
public function test_book_import()
22+
{
23+
$testImagePath = $this->files->testFilePath('test-image.png');
24+
$testFilePath = $this->files->testFilePath('test-file.txt');
25+
$import = ZipTestHelper::importFromData([], [
26+
'book' => [
27+
'id' => 5,
28+
'name' => 'Import test',
29+
'cover' => 'book_cover_image',
30+
'description_html' => '<p><a href="[[bsexport:page:3]]">Link to chapter page</a></p>',
31+
'tags' => [
32+
['name' => 'Animal', 'value' => 'Cat'],
33+
['name' => 'Category', 'value' => 'Test'],
34+
],
35+
'chapters' => [
36+
[
37+
'id' => 6,
38+
'name' => 'Chapter A',
39+
'description_html' => '<p><a href="[[bsexport:book:5]]">Link to book</a></p>',
40+
'priority' => 1,
41+
'tags' => [
42+
['name' => 'Reviewed'],
43+
['name' => 'Category', 'value' => 'Test Chapter'],
44+
],
45+
'pages' => [
46+
[
47+
'id' => 3,
48+
'name' => 'Page A',
49+
'priority' => 6,
50+
'html' => '
51+
<p><a href="[[bsexport:page:3]]">Link to self</a></p>
52+
<p><a href="[[bsexport:image:1]]">Link to cat image</a></p>
53+
<p><a href="[[bsexport:attachment:4]]">Link to text attachment</a></p>',
54+
'tags' => [
55+
['name' => 'Unreviewed'],
56+
],
57+
'attachments' => [
58+
[
59+
'id' => 4,
60+
'name' => 'Text attachment',
61+
'file' => 'file_attachment'
62+
],
63+
[
64+
'name' => 'Cats',
65+
'link' => 'https://example.com/cats',
66+
]
67+
],
68+
'images' => [
69+
[
70+
'id' => 1,
71+
'name' => 'Cat',
72+
'type' => 'gallery',
73+
'file' => 'cat_image'
74+
],
75+
[
76+
'id' => 2,
77+
'name' => 'Dog Drawing',
78+
'type' => 'drawio',
79+
'file' => 'dog_image'
80+
]
81+
],
82+
],
83+
],
84+
],
85+
[
86+
'name' => 'Chapter child B',
87+
'priority' => 5,
88+
]
89+
],
90+
'pages' => [
91+
[
92+
'name' => 'Page C',
93+
'markdown' => '[Link to text]([[bsexport:attachment:4]]?scale=big)',
94+
'priority' => 3,
95+
]
96+
],
97+
],
98+
], [
99+
'book_cover_image' => $testImagePath,
100+
'file_attachment' => $testFilePath,
101+
'cat_image' => $testImagePath,
102+
'dog_image' => $testImagePath,
103+
]);
104+
105+
$this->asAdmin();
106+
/** @var Book $book */
107+
$book = $this->runner->run($import);
108+
109+
// Book checks
110+
$this->assertEquals('Import test', $book->name);
111+
$this->assertFileExists(public_path($book->cover->path));
112+
$this->assertCount(2, $book->tags);
113+
$this->assertEquals('Cat', $book->tags()->first()->value);
114+
$this->assertCount(2, $book->chapters);
115+
$this->assertEquals(1, $book->directPages()->count());
116+
117+
// Chapter checks
118+
$chapterA = $book->chapters()->where('name', 'Chapter A')->first();
119+
$this->assertCount(2, $chapterA->tags);
120+
$firstChapterTag = $chapterA->tags()->first();
121+
$this->assertEquals('Reviewed', $firstChapterTag->name);
122+
$this->assertEquals('', $firstChapterTag->value);
123+
$this->assertCount(1, $chapterA->pages);
124+
125+
// Page checks
126+
/** @var Page $pageA */
127+
$pageA = $chapterA->pages->first();
128+
$this->assertEquals('Page A', $pageA->name);
129+
$this->assertCount(1, $pageA->tags);
130+
$firstPageTag = $pageA->tags()->first();
131+
$this->assertEquals('Unreviewed', $firstPageTag->name);
132+
$this->assertCount(2, $pageA->attachments);
133+
$firstAttachment = $pageA->attachments->first();
134+
$this->assertEquals('Text attachment', $firstAttachment->name);
135+
$this->assertFileEquals($testFilePath, storage_path($firstAttachment->path));
136+
$this->assertFalse($firstAttachment->external);
137+
$secondAttachment = $pageA->attachments->last();
138+
$this->assertEquals('Cats', $secondAttachment->name);
139+
$this->assertEquals('https://example.com/cats', $secondAttachment->path);
140+
$this->assertTrue($secondAttachment->external);
141+
$pageAImages = Image::where('uploaded_to', '=', $pageA->id)->whereIn('type', ['gallery', 'drawio'])->get();
142+
$this->assertCount(2, $pageAImages);
143+
$this->assertEquals('Cat', $pageAImages[0]->name);
144+
$this->assertEquals('gallery', $pageAImages[0]->type);
145+
$this->assertFileEquals($testImagePath, public_path($pageAImages[0]->path));
146+
$this->assertEquals('Dog Drawing', $pageAImages[1]->name);
147+
$this->assertEquals('drawio', $pageAImages[1]->type);
148+
149+
// Book order check
150+
$children = $book->getDirectVisibleChildren()->values()->all();
151+
$this->assertEquals($children[0]->name, 'Chapter A');
152+
$this->assertEquals($children[1]->name, 'Page C');
153+
$this->assertEquals($children[2]->name, 'Chapter child B');
154+
155+
// Reference checks
156+
$textAttachmentUrl = $firstAttachment->getUrl();
157+
$this->assertStringContainsString($pageA->getUrl(), $book->description_html);
158+
$this->assertStringContainsString($book->getUrl(), $chapterA->description_html);
159+
$this->assertStringContainsString($pageA->getUrl(), $pageA->html);
160+
$this->assertStringContainsString($pageAImages[0]->getThumb(1680, null, true), $pageA->html);
161+
$this->assertStringContainsString($firstAttachment->getUrl(), $pageA->html);
162+
163+
// Reference in converted markdown
164+
$pageC = $children[1];
165+
$this->assertStringContainsString("href=\"{$textAttachmentUrl}?scale=big\"", $pageC->html);
166+
167+
ZipTestHelper::deleteZipForImport($import);
168+
}
169+
18170
// TODO - Test full book import
19171
// TODO - Test full chapter import
20172
// TODO - Test full page import

tests/Exports/ZipTestHelper.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
class ZipTestHelper
1010
{
11-
public static function importFromData(array $importData, array $zipData): Import
11+
public static function importFromData(array $importData, array $zipData, array $files = []): Import
1212
{
1313
if (isset($zipData['book'])) {
1414
$importData['type'] = 'book';
@@ -19,7 +19,7 @@ public static function importFromData(array $importData, array $zipData): Import
1919
}
2020

2121
$import = Import::factory()->create($importData);
22-
$zip = static::zipUploadFromData($zipData);
22+
$zip = static::zipUploadFromData($zipData, $files);
2323
rename($zip->getRealPath(), storage_path($import->path));
2424

2525
return $import;
@@ -33,13 +33,18 @@ public static function deleteZipForImport(Import $import): void
3333
}
3434
}
3535

36-
public static function zipUploadFromData(array $data): UploadedFile
36+
public static function zipUploadFromData(array $data, array $files = []): UploadedFile
3737
{
3838
$zipFile = tempnam(sys_get_temp_dir(), 'bstest-');
3939

4040
$zip = new ZipArchive();
4141
$zip->open($zipFile, ZipArchive::CREATE);
4242
$zip->addFromString('data.json', json_encode($data));
43+
44+
foreach ($files as $name => $file) {
45+
$zip->addFile($file, "files/$name");
46+
}
47+
4348
$zip->close();
4449

4550
return new UploadedFile($zipFile, 'upload.zip', 'application/zip', null, true);

0 commit comments

Comments
 (0)