From 5e6ffb791ca9beb88e3f19876a948c02e50f2e65 Mon Sep 17 00:00:00 2001 From: Simon Praetorius Date: Mon, 4 Mar 2024 16:22:54 +0100 Subject: [PATCH] [BUGFIX] Prevent php warning when passing array as tag attribute TagBuilder::addAttribute() allows both strings and array/traversables as attribute value. However, in the implementation only "data" and "aria" are properly handled as arrays. For other attribute names, this leads to a type conversion warning. With this patch, that edge case is properly handled with an exception. Also, test coverage is added both for data/aria and the exception. Resolves: #857 --- src/Core/ViewHelper/TagBuilder.php | 16 +++++++++---- tests/Unit/Core/ViewHelper/TagBuilderTest.php | 23 +++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/Core/ViewHelper/TagBuilder.php b/src/Core/ViewHelper/TagBuilder.php index 6dabac9e2..943ab430d 100644 --- a/src/Core/ViewHelper/TagBuilder.php +++ b/src/Core/ViewHelper/TagBuilder.php @@ -181,7 +181,10 @@ public function ignoreEmptyAttributes($ignoreEmptyAttributes) * Adds an attribute to the $attributes-collection * * @param string $attributeName name of the attribute to be added to the tag - * @param string|\Traversable|array|null $attributeValue attribute value + * @param string|\Traversable|array|null $attributeValue attribute value, can only be array or traversable + * if the attribute name is either "data" or "area". In + * that special case, multiple attributes will be created + * with either "data-" or "area-" as prefix * @param bool $escapeSpecialCharacters apply htmlspecialchars to attribute value * @api */ @@ -190,9 +193,14 @@ public function addAttribute($attributeName, $attributeValue, $escapeSpecialChar if ($escapeSpecialCharacters) { $attributeName = htmlspecialchars($attributeName); } - if (in_array($attributeName, ['data', 'aria'], true) - && (is_array($attributeValue) || $attributeValue instanceof \Traversable) - ) { + if (is_array($attributeValue) || $attributeValue instanceof \Traversable) { + if (!in_array($attributeName, ['data', 'aria'], true)) { + throw new \InvalidArgumentException( + sprintf('Value of tag attribute "%s" cannot be of type array.', $attributeName), + 1709565127 + ); + } + foreach ($attributeValue as $name => $value) { $this->addAttribute($attributeName . '-' . $name, $value, $escapeSpecialCharacters); } diff --git a/tests/Unit/Core/ViewHelper/TagBuilderTest.php b/tests/Unit/Core/ViewHelper/TagBuilderTest.php index ac5b344a7..52bbbd5f5 100644 --- a/tests/Unit/Core/ViewHelper/TagBuilderTest.php +++ b/tests/Unit/Core/ViewHelper/TagBuilderTest.php @@ -121,6 +121,29 @@ public function attributesAreProperlyRendered(): void self::assertEquals('', $tagBuilder->render()); } + /** + * @test + */ + public function arrayAttributesAreProperlyRendered(): void + { + $tagBuilder = new TagBuilder('tag'); + $tagBuilder->addAttribute('data', ['attribute1' => 'data1', 'attribute2' => 'data2']); + $tagBuilder->addAttribute('aria', ['attribute1' => 'aria1']); + self::assertEquals('', $tagBuilder->render()); + } + + /** + * @test + */ + public function customArrayAttributesThrowException(): void + { + self::expectException(\InvalidArgumentException::class); + self::expectExceptionCode(1709565127); + self::expectExceptionMessage('Value of tag attribute "custom" cannot be of type array.'); + $tagBuilder = new TagBuilder('tag'); + $tagBuilder->addAttribute('custom', ['attribute1' => 'data1', 'attribute2' => 'data2']); + } + /** * @test */