diff --git a/app/Exports/ZipExports/ZipImportReferences.php b/app/Exports/ZipExports/ZipImportReferences.php index b23d5e72b..da0581df6 100644 --- a/app/Exports/ZipExports/ZipImportReferences.php +++ b/app/Exports/ZipExports/ZipImportReferences.php @@ -97,10 +97,12 @@ class ZipImportReferences } else if ($model instanceof Image) { if ($model->type === 'gallery') { $this->imageResizer->loadGalleryThumbnailsForImage($model, false); - return $model->thumbs['gallery'] ?? $model->url; + return $model->thumbs['display'] ?? $model->url; } return $model->url; + } else if ($model instanceof Attachment) { + return $model->getUrl(false); } return null; diff --git a/app/Exports/ZipExports/ZipImportRunner.php b/app/Exports/ZipExports/ZipImportRunner.php index c5b9da319..27d859e59 100644 --- a/app/Exports/ZipExports/ZipImportRunner.php +++ b/app/Exports/ZipExports/ZipImportRunner.php @@ -233,6 +233,10 @@ class ZipImportRunner $file, $exportImage->type, $page->id, + null, + null, + true, + $exportImage->name, ); $this->references->addImage($image, $exportImage->id); diff --git a/app/Uploads/ImageService.php b/app/Uploads/ImageService.php index 5c455cf86..038e6aa41 100644 --- a/app/Uploads/ImageService.php +++ b/app/Uploads/ImageService.php @@ -33,9 +33,10 @@ class ImageService int $uploadedTo = 0, int $resizeWidth = null, int $resizeHeight = null, - bool $keepRatio = true + bool $keepRatio = true, + string $imageName = '', ): Image { - $imageName = $uploadedFile->getClientOriginalName(); + $imageName = $imageName ?: $uploadedFile->getClientOriginalName(); $imageData = file_get_contents($uploadedFile->getRealPath()); if ($resizeWidth !== null || $resizeHeight !== null) { diff --git a/tests/Exports/ZipImportRunnerTest.php b/tests/Exports/ZipImportRunnerTest.php index 7bdd8ecbb..f07b3f41b 100644 --- a/tests/Exports/ZipImportRunnerTest.php +++ b/tests/Exports/ZipImportRunnerTest.php @@ -2,7 +2,10 @@ namespace Tests\Exports; +use BookStack\Entities\Models\Book; +use BookStack\Entities\Models\Page; use BookStack\Exports\ZipExports\ZipImportRunner; +use BookStack\Uploads\Image; use Tests\TestCase; class ZipImportRunnerTest extends TestCase @@ -15,6 +18,155 @@ class ZipImportRunnerTest extends TestCase $this->runner = app()->make(ZipImportRunner::class); } + public function test_book_import() + { + $testImagePath = $this->files->testFilePath('test-image.png'); + $testFilePath = $this->files->testFilePath('test-file.txt'); + $import = ZipTestHelper::importFromData([], [ + 'book' => [ + 'id' => 5, + 'name' => 'Import test', + 'cover' => 'book_cover_image', + 'description_html' => '
', + 'tags' => [ + ['name' => 'Animal', 'value' => 'Cat'], + ['name' => 'Category', 'value' => 'Test'], + ], + 'chapters' => [ + [ + 'id' => 6, + 'name' => 'Chapter A', + 'description_html' => '', + 'priority' => 1, + 'tags' => [ + ['name' => 'Reviewed'], + ['name' => 'Category', 'value' => 'Test Chapter'], + ], + 'pages' => [ + [ + 'id' => 3, + 'name' => 'Page A', + 'priority' => 6, + 'html' => ' + + +', + 'tags' => [ + ['name' => 'Unreviewed'], + ], + 'attachments' => [ + [ + 'id' => 4, + 'name' => 'Text attachment', + 'file' => 'file_attachment' + ], + [ + 'name' => 'Cats', + 'link' => 'https://example.com/cats', + ] + ], + 'images' => [ + [ + 'id' => 1, + 'name' => 'Cat', + 'type' => 'gallery', + 'file' => 'cat_image' + ], + [ + 'id' => 2, + 'name' => 'Dog Drawing', + 'type' => 'drawio', + 'file' => 'dog_image' + ] + ], + ], + ], + ], + [ + 'name' => 'Chapter child B', + 'priority' => 5, + ] + ], + 'pages' => [ + [ + 'name' => 'Page C', + 'markdown' => '[Link to text]([[bsexport:attachment:4]]?scale=big)', + 'priority' => 3, + ] + ], + ], + ], [ + 'book_cover_image' => $testImagePath, + 'file_attachment' => $testFilePath, + 'cat_image' => $testImagePath, + 'dog_image' => $testImagePath, + ]); + + $this->asAdmin(); + /** @var Book $book */ + $book = $this->runner->run($import); + + // Book checks + $this->assertEquals('Import test', $book->name); + $this->assertFileExists(public_path($book->cover->path)); + $this->assertCount(2, $book->tags); + $this->assertEquals('Cat', $book->tags()->first()->value); + $this->assertCount(2, $book->chapters); + $this->assertEquals(1, $book->directPages()->count()); + + // Chapter checks + $chapterA = $book->chapters()->where('name', 'Chapter A')->first(); + $this->assertCount(2, $chapterA->tags); + $firstChapterTag = $chapterA->tags()->first(); + $this->assertEquals('Reviewed', $firstChapterTag->name); + $this->assertEquals('', $firstChapterTag->value); + $this->assertCount(1, $chapterA->pages); + + // Page checks + /** @var Page $pageA */ + $pageA = $chapterA->pages->first(); + $this->assertEquals('Page A', $pageA->name); + $this->assertCount(1, $pageA->tags); + $firstPageTag = $pageA->tags()->first(); + $this->assertEquals('Unreviewed', $firstPageTag->name); + $this->assertCount(2, $pageA->attachments); + $firstAttachment = $pageA->attachments->first(); + $this->assertEquals('Text attachment', $firstAttachment->name); + $this->assertFileEquals($testFilePath, storage_path($firstAttachment->path)); + $this->assertFalse($firstAttachment->external); + $secondAttachment = $pageA->attachments->last(); + $this->assertEquals('Cats', $secondAttachment->name); + $this->assertEquals('https://example.com/cats', $secondAttachment->path); + $this->assertTrue($secondAttachment->external); + $pageAImages = Image::where('uploaded_to', '=', $pageA->id)->whereIn('type', ['gallery', 'drawio'])->get(); + $this->assertCount(2, $pageAImages); + $this->assertEquals('Cat', $pageAImages[0]->name); + $this->assertEquals('gallery', $pageAImages[0]->type); + $this->assertFileEquals($testImagePath, public_path($pageAImages[0]->path)); + $this->assertEquals('Dog Drawing', $pageAImages[1]->name); + $this->assertEquals('drawio', $pageAImages[1]->type); + + // Book order check + $children = $book->getDirectVisibleChildren()->values()->all(); + $this->assertEquals($children[0]->name, 'Chapter A'); + $this->assertEquals($children[1]->name, 'Page C'); + $this->assertEquals($children[2]->name, 'Chapter child B'); + + // Reference checks + $textAttachmentUrl = $firstAttachment->getUrl(); + $this->assertStringContainsString($pageA->getUrl(), $book->description_html); + $this->assertStringContainsString($book->getUrl(), $chapterA->description_html); + $this->assertStringContainsString($pageA->getUrl(), $pageA->html); + $this->assertStringContainsString($pageAImages[0]->getThumb(1680, null, true), $pageA->html); + $this->assertStringContainsString($firstAttachment->getUrl(), $pageA->html); + + // Reference in converted markdown + $pageC = $children[1]; + $this->assertStringContainsString("href=\"{$textAttachmentUrl}?scale=big\"", $pageC->html); + + ZipTestHelper::deleteZipForImport($import); + } + // TODO - Test full book import // TODO - Test full chapter import // TODO - Test full page import diff --git a/tests/Exports/ZipTestHelper.php b/tests/Exports/ZipTestHelper.php index 3a9b34354..2196f361c 100644 --- a/tests/Exports/ZipTestHelper.php +++ b/tests/Exports/ZipTestHelper.php @@ -8,7 +8,7 @@ use ZipArchive; class ZipTestHelper { - public static function importFromData(array $importData, array $zipData): Import + public static function importFromData(array $importData, array $zipData, array $files = []): Import { if (isset($zipData['book'])) { $importData['type'] = 'book'; @@ -19,7 +19,7 @@ class ZipTestHelper } $import = Import::factory()->create($importData); - $zip = static::zipUploadFromData($zipData); + $zip = static::zipUploadFromData($zipData, $files); rename($zip->getRealPath(), storage_path($import->path)); return $import; @@ -33,13 +33,18 @@ class ZipTestHelper } } - public static function zipUploadFromData(array $data): UploadedFile + public static function zipUploadFromData(array $data, array $files = []): UploadedFile { $zipFile = tempnam(sys_get_temp_dir(), 'bstest-'); $zip = new ZipArchive(); $zip->open($zipFile, ZipArchive::CREATE); $zip->addFromString('data.json', json_encode($data)); + + foreach ($files as $name => $file) { + $zip->addFile($file, "files/$name"); + } + $zip->close(); return new UploadedFile($zipFile, 'upload.zip', 'application/zip', null, true);