]> BookStack Code Mirror - bookstack/commitdiff
Imports: Fixed drawing IDs not being updated in content
authorDan Brown <redacted>
Sun, 24 Aug 2025 13:02:21 +0000 (14:02 +0100)
committerDan Brown <redacted>
Sun, 24 Aug 2025 13:02:21 +0000 (14:02 +0100)
Would leave imported content with inaccessible images in many cases (or
wrong references) although the drawing was still being uploaded &
related to the page.
Added test to cover.

For #5761

app/Exports/ZipExports/ZipImportReferences.php
tests/Exports/ZipImportRunnerTest.php

index da0581df6f543ce33c79b0fc7085fd819bf35f77..662dfdf6c5b5724ee52b084f96bcda95c6532621 100644 (file)
@@ -29,7 +29,10 @@ class ZipImportReferences
     /** @var Image[] */
     protected array $images = [];
 
-    /** @var array<string, Model> */
+    /**
+     * Mapping keyed by "type:old-reference-id" with values being the new imported equivalent model.
+     * @var array<string, Model>
+     */
     protected array $referenceMap = [];
 
     /** @var array<int, ZipExportPage> */
@@ -108,6 +111,22 @@ class ZipImportReferences
         return null;
     }
 
+    protected function replaceDrawingIdReferences(string $content): string
+    {
+        $referenceRegex = '/\sdrawio-diagram=[\'"](\d+)[\'"]/';
+
+        $result = preg_replace_callback($referenceRegex, function ($matches) {
+            $key = 'image:' . $matches[1];
+            $model = $this->referenceMap[$key] ?? null;
+            if ($model instanceof Image && $model->type === 'drawio') {
+                return ' drawio-diagram="' . $model->id . '"';
+            }
+            return $matches[0];
+        }, $content);
+
+        return $result ?: $content;
+    }
+
     public function replaceReferences(): void
     {
         foreach ($this->books as $book) {
@@ -134,7 +153,9 @@ class ZipImportReferences
             $exportPage = $this->zipExportPageMap[$page->id];
             $contentType = $exportPage->markdown ? 'markdown' : 'html';
             $content = $exportPage->markdown ?: ($exportPage->html ?: '');
+
             $parsed = $this->parser->parseReferences($content, $this->handleReference(...));
+            $parsed = $this->replaceDrawingIdReferences($parsed);
 
             $this->pageRepo->setContentFromInput($page, [
                 $contentType => $parsed,
index d3af6df76a604b9e4aa56f06b85d7bd6ace810d2..68ffb4231bd2493de2e47222daa0e2e2e0b4b33a 100644 (file)
@@ -393,4 +393,42 @@ class ZipImportRunnerTest extends TestCase
 
         ZipTestHelper::deleteZipForImport($import);
     }
+
+    public function test_drawing_references_are_updated_within_content()
+    {
+        $testImagePath = $this->files->testFilePath('test-image.png');
+        $parent = $this->entities->chapter();
+
+        $import = ZipTestHelper::importFromData([], [
+            'page' => [
+                'name' => 'Page A',
+                'html' => '<div drawio-diagram="1125"><img src="[[bsexport:image:1125]]"></div>',
+                'images' => [
+                    [
+                        'id' => 1125,
+                        'name' => 'Cat',
+                        'type' => 'drawio',
+                        'file' => 'my_drawing'
+                    ]
+                ],
+            ],
+        ], [
+            'my_drawing' => $testImagePath,
+        ]);
+
+        $this->asAdmin();
+        /** @var Page $page */
+        $page = $this->runner->run($import, $parent);
+
+        $pageImages = Image::where('uploaded_to', '=', $page->id)->whereIn('type', ['gallery', 'drawio'])->get();
+        $this->assertCount(1, $pageImages);
+        $this->assertEquals('drawio', $pageImages[0]->type);
+
+        $drawingId = $pageImages[0]->id;
+        $this->assertStringContainsString("drawio-diagram=\"{$drawingId}\"", $page->html);
+        $this->assertStringNotContainsString('[[bsexport:image:1125]]', $page->html);
+        $this->assertStringNotContainsString('drawio-diagram="1125"', $page->html);
+
+        ZipTestHelper::deleteZipForImport($import);
+    }
 }