]> BookStack Code Mirror - bookstack/commitdiff
Copying: Added reference change context tracking
authorDan Brown <redacted>
Tue, 25 Nov 2025 14:46:36 +0000 (14:46 +0000)
committerDan Brown <redacted>
Tue, 25 Nov 2025 14:46:36 +0000 (14:46 +0000)
Added core wiring in the cloning logic, just need to implement core
logic in the updater now.

app/Entities/Tools/Cloner.php
app/References/ReferenceChangeContext.php [new file with mode: 0644]
app/References/ReferenceUpdater.php

index ff42ae6e41b8cb53d1cf649f80e3469697b0010b..916ce42c572bccf281e244a05decf38365e9725d 100644 (file)
@@ -13,30 +13,47 @@ use BookStack\Entities\Repos\BookRepo;
 use BookStack\Entities\Repos\ChapterRepo;
 use BookStack\Entities\Repos\PageRepo;
 use BookStack\Permissions\Permission;
+use BookStack\References\ReferenceChangeContext;
+use BookStack\References\ReferenceUpdater;
 use BookStack\Uploads\Image;
 use BookStack\Uploads\ImageService;
 use Illuminate\Http\UploadedFile;
 
 class Cloner
 {
+    protected ReferenceChangeContext $referenceChangeContext;
+
     public function __construct(
         protected PageRepo $pageRepo,
         protected ChapterRepo $chapterRepo,
         protected BookRepo $bookRepo,
         protected ImageService $imageService,
+        protected ReferenceUpdater $referenceUpdater,
     ) {
+        $this->referenceChangeContext = new ReferenceChangeContext();
     }
 
     /**
      * Clone the given page into the given parent using the provided name.
      */
     public function clonePage(Page $original, Entity $parent, string $newName): Page
+    {
+        $context = $this->newReferenceChangeContext();
+        $page = $this->createPageClone($original, $parent, $newName);
+        $this->referenceUpdater->changeReferencesUsingContext($context);
+        return $page;
+    }
+
+    protected function createPageClone(Page $original, Entity $parent, string $newName): Page
     {
         $copyPage = $this->pageRepo->getNewDraftPage($parent);
         $pageData = $this->entityToInputData($original);
         $pageData['name'] = $newName;
 
-        return $this->pageRepo->publishDraft($copyPage, $pageData);
+        $newPage = $this->pageRepo->publishDraft($copyPage, $pageData);
+        $this->referenceChangeContext->add($original, $newPage);
+
+        return $newPage;
     }
 
     /**
@@ -44,6 +61,14 @@ class Cloner
      * Clones all child pages.
      */
     public function cloneChapter(Chapter $original, Book $parent, string $newName): Chapter
+    {
+        $context = $this->newReferenceChangeContext();
+        $chapter = $this->createChapterClone($original, $parent, $newName);
+        $this->referenceUpdater->changeReferencesUsingContext($context);
+        return $chapter;
+    }
+
+    protected function createChapterClone(Chapter $original, Book $parent, string $newName): Chapter
     {
         $chapterDetails = $this->entityToInputData($original);
         $chapterDetails['name'] = $newName;
@@ -65,6 +90,14 @@ class Cloner
      * Clones all child chapters and pages.
      */
     public function cloneBook(Book $original, string $newName): Book
+    {
+        $context = $this->newReferenceChangeContext();
+        $book = $this->createBookClone($original, $newName);
+        $this->referenceUpdater->changeReferencesUsingContext($context);
+        return $book;
+    }
+
+    protected function createBookClone(Book $original, string $newName): Book
     {
         $bookDetails = $this->entityToInputData($original);
         $bookDetails['name'] = $newName;
@@ -155,4 +188,10 @@ class Cloner
 
         return $tags;
     }
+
+    protected function newReferenceChangeContext(): ReferenceChangeContext
+    {
+        $this->referenceChangeContext = new ReferenceChangeContext();
+        return $this->referenceChangeContext;
+    }
 }
diff --git a/app/References/ReferenceChangeContext.php b/app/References/ReferenceChangeContext.php
new file mode 100644 (file)
index 0000000..df3028b
--- /dev/null
@@ -0,0 +1,19 @@
+<?php
+
+namespace BookStack\References;
+
+use BookStack\Entities\Models\Entity;
+
+class ReferenceChangeContext
+{
+    /**
+     * Entity pairs where the first is the old entity and the second is the new entity.
+     * @var array<array{0: Entity, 1: Entity}>
+     */
+    protected array $changes = [];
+
+    public function add(Entity $oldEntity, Entity $newEntity): void
+    {
+        $this->changes[] = [$oldEntity, $newEntity];
+    }
+}
index 06b3389bae527e342a36ad7197ff5cfea2dfed53..3a6db05ef394d8b294153cd7bef8c3fa2853b727 100644 (file)
@@ -30,6 +30,14 @@ class ReferenceUpdater
         }
     }
 
+    public function changeReferencesUsingContext(ReferenceChangeContext $context): void
+    {
+        // TODO
+
+        // We should probably have references by this point, so we could use those for efficient
+        // discovery instead of scanning each item within the context.
+    }
+
     /**
      * @return Reference[]
      */