diff --git a/app/Entities/Tools/Cloner.php b/app/Entities/Tools/Cloner.php index ff42ae6e4..916ce42c5 100644 --- a/app/Entities/Tools/Cloner.php +++ b/app/Entities/Tools/Cloner.php @@ -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 index 000000000..df3028b93 --- /dev/null +++ b/app/References/ReferenceChangeContext.php @@ -0,0 +1,19 @@ + + */ + protected array $changes = []; + + public function add(Entity $oldEntity, Entity $newEntity): void + { + $this->changes[] = [$oldEntity, $newEntity]; + } +} diff --git a/app/References/ReferenceUpdater.php b/app/References/ReferenceUpdater.php index 06b3389ba..3a6db05ef 100644 --- a/app/References/ReferenceUpdater.php +++ b/app/References/ReferenceUpdater.php @@ -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[] */