From 986e8585614cecb78d7374a1b5b558d3da0bd680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20L=C3=B8vgaard?= Date: Tue, 26 Jul 2022 15:44:15 +0200 Subject: [PATCH] Handle scenarios where two unique tags are added and we have to decide which one to keep --- src/TagBag.php | 55 +++++++++++++++++++++++++++++++++++++++----- tests/TagBagTest.php | 15 ++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) diff --git a/src/TagBag.php b/src/TagBag.php index 01ebb91..b54fc71 100644 --- a/src/TagBag.php +++ b/src/TagBag.php @@ -53,8 +53,8 @@ public function add(TagInterface $tag): void try { $renderedValue = $this->renderer->render($tag); $fingerprint = $tag->getFingerprint() ?? $this->fingerprintGenerator->generate($tag, $renderedValue); - $existingTag = $this->findTagByFingerprint($fingerprint); - if (null !== $existingTag && ($existingTag->unique || $tag->isUnique())) { + + if (!$this->handleExistingTag($tag, $fingerprint)) { return; } @@ -89,6 +89,46 @@ public function renderSection(string $section): string return $value; } + /** + * Returns true if the tag should be added + */ + private function handleExistingTag(TagInterface $tag, string $fingerprint): bool + { + $search = $this->findTagByFingerprint($fingerprint); + + // if no existing tag exists we should add the tag + if (null === $search) { + return true; + } + + [$section, $idx, $existingTag] = $search; + + // if both tags are unique + if ($existingTag->unique && $tag->isUnique()) { + // ... we check the priority and if the priority of the new tag is higher than the existing tag + if ($existingTag->priority >= $tag->getPriority()) { + return false; + } + + // ... we will remove the old tag and add the new tag + unset($this->tags[$section][$idx]); + + return true; + } + + // if the old tag is unique, but the new tag isn't, we will not add the new tag + if ($existingTag->unique) { + return false; + } + + // if the old tag is not unique, but the new tag is, we will remove the old tag and add the new tag + if ($tag->isUnique()) { + unset($this->tags[$section][$idx]); + } + + return true; + } + /** * @param list $tags */ @@ -183,12 +223,15 @@ private function dispatch(object $event): void $this->eventDispatcher->dispatch($event); } - private function findTagByFingerprint(string $fingerprint): ?RenderedTag + /** + * @return array{0: string, 1: int, 2: RenderedTag}|null + */ + private function findTagByFingerprint(string $fingerprint): ?array { - foreach ($this->tags as $section) { - foreach ($section as $tag) { + foreach ($this->tags as $section => $sectionTags) { + foreach ($sectionTags as $idx => $tag) { if ($tag->fingerprint === $fingerprint) { - return $tag; + return [$section, $idx, $tag]; } } } diff --git a/tests/TagBagTest.php b/tests/TagBagTest.php index 4a83c04..ff5383c 100644 --- a/tests/TagBagTest.php +++ b/tests/TagBagTest.php @@ -215,6 +215,21 @@ public function it_does_not_ignore_fingerprint_when_one_of_the_tags_is_unique(): self::assertSame('content', $tagBag->renderAll()); } + /** + * @test + */ + public function it_replaces_unique_tag_with_new_one_with_higher_priority(): void + { + $tag1 = $this->getTag('tag1')->unique()->withPriority(10)->withFingerprint('tag'); + $tag2 = $this->getTag('tag2')->unique()->withPriority(20)->withFingerprint('tag'); + + $tagBag = $this->getTagBag(); + $tagBag->add($tag1); + $tagBag->add($tag2); + + self::assertSame('tag2', $tagBag->renderAll()); + } + private function getTag( string $content = 'content', string $section = null,