From abfca18ad2df045735bcde3b0840dc34a40176c0 Mon Sep 17 00:00:00 2001 From: Romain Canon Date: Mon, 18 Nov 2024 13:37:50 +0100 Subject: [PATCH] fix: properly handle array arguments during attributes compilation --- .../Cache/Compiler/AttributesCompiler.php | 36 ++++++++++--------- .../Attribute/AttributeWithArguments.php | 6 +++- tests/Fixture/Object/ObjectWithAttributes.php | 2 +- .../Cache/Compiler/AttributesCompilerTest.php | 2 ++ 4 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/Definition/Repository/Cache/Compiler/AttributesCompiler.php b/src/Definition/Repository/Cache/Compiler/AttributesCompiler.php index 990c2620..9a7b4498 100644 --- a/src/Definition/Repository/Cache/Compiler/AttributesCompiler.php +++ b/src/Definition/Repository/Cache/Compiler/AttributesCompiler.php @@ -6,6 +6,7 @@ use CuyZ\Valinor\Definition\Attributes; +use function array_map; use function count; use function implode; use function is_array; @@ -36,7 +37,15 @@ private function compileAttributes(Attributes $attributes): string foreach ($attributes as $attribute) { $class = $this->classDefinitionCompiler->compile($attribute->class); - $arguments = $this->compileAttributeArguments($attribute->arguments); + + if ($attribute->arguments === []) { + $arguments = ''; + } else { + $arguments = implode(', ', array_map( + fn (mixed $argument) => $this->compileAttributeArguments($argument), + $attribute->arguments, + )); + } $attributesListCode[] = << $arguments - */ - private function compileAttributeArguments(array $arguments): string + private function compileAttributeArguments(mixed $value): string { - if (count($arguments) === 0) { - return ''; + if (is_object($value)) { + return 'unserialize(' . var_export(serialize($value), true) . ')'; } - $argumentsCode = []; + if (is_array($value)) { + $parts = []; - foreach ($arguments as $argument) { - if (is_object($argument)) { - $argumentsCode[] = 'unserialize(' . var_export(serialize($argument), true) . ')'; - } elseif (is_array($argument)) { - $argumentsCode[] = '[' . $this->compileAttributeArguments($argument) . ']'; - } else { - $argumentsCode[] = var_export($argument, true); + foreach ($value as $key => $subValue) { + $parts[] = var_export($key, true) . ' => ' . $this->compileAttributeArguments($subValue); } + + return '[' . implode(', ', $parts) . ']'; } - return implode(', ', $argumentsCode); + return var_export($value, true); } } diff --git a/tests/Fixture/Attribute/AttributeWithArguments.php b/tests/Fixture/Attribute/AttributeWithArguments.php index 7a7c90ba..f8745f8f 100644 --- a/tests/Fixture/Attribute/AttributeWithArguments.php +++ b/tests/Fixture/Attribute/AttributeWithArguments.php @@ -5,12 +5,16 @@ namespace CuyZ\Valinor\Tests\Fixture\Attribute; use Attribute; +use CuyZ\Valinor\Tests\Fixture\Object\StringableObject; #[Attribute] final class AttributeWithArguments { public function __construct( public string $foo, - public string $bar + public string $bar, + public StringableObject $object = new StringableObject('foo'), + /** @var array */ + public array $array = ['foo' => 'bar'], ) {} } diff --git a/tests/Fixture/Object/ObjectWithAttributes.php b/tests/Fixture/Object/ObjectWithAttributes.php index a506fae2..e58da0de 100644 --- a/tests/Fixture/Object/ObjectWithAttributes.php +++ b/tests/Fixture/Object/ObjectWithAttributes.php @@ -9,7 +9,7 @@ use CuyZ\Valinor\Tests\Fixture\Attribute\PropertyTargetAttribute; #[BasicAttribute] -#[AttributeWithArguments('foo', 'bar')] +#[AttributeWithArguments('foo', 'bar', new StringableObject('bar'), ['baz' => 'fiz'])] final class ObjectWithAttributes { #[BasicAttribute] diff --git a/tests/Functional/Definition/Repository/Cache/Compiler/AttributesCompilerTest.php b/tests/Functional/Definition/Repository/Cache/Compiler/AttributesCompilerTest.php index 77abc7eb..1e03bb2d 100644 --- a/tests/Functional/Definition/Repository/Cache/Compiler/AttributesCompilerTest.php +++ b/tests/Functional/Definition/Repository/Cache/Compiler/AttributesCompilerTest.php @@ -53,6 +53,8 @@ public function test_compiles_attributes_for_class_with_attributes(): void /** @var AttributeWithArguments $attribute */ self::assertSame('foo', $attribute->foo); self::assertSame('bar', $attribute->bar); + self::assertSame('bar', $attribute->object->__toString()); + self::assertSame(['baz' => 'fiz'], $attribute->array); } public function test_compiles_attributes_for_class_without_attributes(): void