X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/b86ee6d252b301a94796043f333abdb6603c304c..refs/pull/5721/head:/app/References/ReferenceUpdater.php diff --git a/app/References/ReferenceUpdater.php b/app/References/ReferenceUpdater.php index 15619bc31..db355f211 100644 --- a/app/References/ReferenceUpdater.php +++ b/app/References/ReferenceUpdater.php @@ -2,37 +2,83 @@ namespace BookStack\References; +use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Entity; +use BookStack\Entities\Models\HasHtmlDescription; use BookStack\Entities\Models\Page; use BookStack\Entities\Repos\RevisionRepo; -use DOMDocument; -use DOMXPath; +use BookStack\Util\HtmlDocument; class ReferenceUpdater { - protected ReferenceFetcher $referenceFetcher; - protected RevisionRepo $revisionRepo; + public function __construct( + protected ReferenceFetcher $referenceFetcher, + protected RevisionRepo $revisionRepo, + ) { + } - public function __construct(ReferenceFetcher $referenceFetcher, RevisionRepo $revisionRepo) + public function updateEntityReferences(Entity $entity, string $oldLink): void { - $this->referenceFetcher = $referenceFetcher; - $this->revisionRepo = $revisionRepo; + $references = $this->getReferencesToUpdate($entity); + $newLink = $entity->getUrl(); + + foreach ($references as $reference) { + /** @var Entity $entity */ + $entity = $reference->from; + $this->updateReferencesWithinEntity($entity, $oldLink, $newLink); + } } - public function updateEntityPageReferences(Entity $entity, string $oldLink) + /** + * @return Reference[] + */ + protected function getReferencesToUpdate(Entity $entity): array { - $references = $this->referenceFetcher->getPageReferencesToEntity($entity); - $newLink = $entity->getUrl(); + /** @var Reference[] $references */ + $references = $this->referenceFetcher->getReferencesToEntity($entity)->values()->all(); + + if ($entity instanceof Book) { + $pages = $entity->pages()->get(['id']); + $chapters = $entity->chapters()->get(['id']); + $children = $pages->concat($chapters); + foreach ($children as $bookChild) { + /** @var Reference[] $childRefs */ + $childRefs = $this->referenceFetcher->getReferencesToEntity($bookChild)->values()->all(); + array_push($references, ...$childRefs); + } + } - /** @var Reference $reference */ + $deduped = []; foreach ($references as $reference) { - /** @var Page $page */ - $page = $reference->from; - $this->updateReferencesWithinPage($page, $oldLink, $newLink); + $key = $reference->from_id . ':' . $reference->from_type; + $deduped[$key] = $reference; + } + + return array_values($deduped); + } + + protected function updateReferencesWithinEntity(Entity $entity, string $oldLink, string $newLink): void + { + if ($entity instanceof Page) { + $this->updateReferencesWithinPage($entity, $oldLink, $newLink); + return; } + + if (in_array(HasHtmlDescription::class, class_uses($entity))) { + $this->updateReferencesWithinDescription($entity, $oldLink, $newLink); + } + } + + protected function updateReferencesWithinDescription(Entity $entity, string $oldLink, string $newLink): void + { + /** @var HasHtmlDescription&Entity $entity */ + $entity = (clone $entity)->refresh(); + $html = $this->updateLinksInHtml($entity->description_html ?: '', $oldLink, $newLink); + $entity->description_html = $html; + $entity->save(); } - protected function updateReferencesWithinPage(Page $page, string $oldLink, string $newLink) + protected function updateReferencesWithinPage(Page $page, string $oldLink, string $newLink): void { $page = (clone $page)->refresh(); $html = $this->updateLinksInHtml($page->html, $oldLink, $newLink); @@ -68,13 +114,8 @@ class ReferenceUpdater return $html; } - $html = '' . $html . ''; - libxml_use_internal_errors(true); - $doc = new DOMDocument(); - $doc->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); - - $xPath = new DOMXPath($doc); - $anchors = $xPath->query('//a[@href]'); + $doc = new HtmlDocument($html); + $anchors = $doc->queryXPath('//a[@href]'); /** @var \DOMElement $anchor */ foreach ($anchors as $anchor) { @@ -83,12 +124,6 @@ class ReferenceUpdater $anchor->setAttribute('href', $updated); } - $html = ''; - $topElems = $doc->documentElement->childNodes->item(0)->childNodes; - foreach ($topElems as $child) { - $html .= $doc->saveHTML($child); - } - - return $html; + return $doc->getBodyInnerHtml(); } -} \ No newline at end of file +}