Skip to content

Commit

Permalink
fix: properly handle array arguments during attributes compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
romm committed Nov 18, 2024
1 parent b15d1a5 commit abfca18
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 18 deletions.
36 changes: 20 additions & 16 deletions src/Definition/Repository/Cache/Compiler/AttributesCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use CuyZ\Valinor\Definition\Attributes;

use function array_map;
use function count;
use function implode;
use function is_array;
Expand Down Expand Up @@ -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[] = <<<PHP
new \CuyZ\Valinor\Definition\AttributeDefinition(
Expand All @@ -49,27 +58,22 @@ private function compileAttributes(Attributes $attributes): string
return implode(', ', $attributesListCode);
}

/**
* @param array<mixed> $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);
}
}
6 changes: 5 additions & 1 deletion tests/Fixture/Attribute/AttributeWithArguments.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<scalar> */
public array $array = ['foo' => 'bar'],
) {}
}
2 changes: 1 addition & 1 deletion tests/Fixture/Object/ObjectWithAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit abfca18

Please sign in to comment.