Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 309c141

Browse files
bug #48958 [DependencyInjection] fixes validation of non-scalar attribute values (ju1ius)
This PR was squashed before being merged into the 6.2 branch. Discussion ---------- [DependencyInjection] fixes validation of non-scalar attribute values | Q | A | ------------- | --- | Branch? | 6.2 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #48956 | License | MIT | Doc PR | None As a follow-up to #47364, this PR updates the `CheckDefinitionValidityPass` to allow (possibly nested) arrays of scalars in service tags attribute values. Please see #48956 for context. Commits ------- 88b3e15 [DependencyInjection] fixes validation of non-scalar attribute values
2 parents 01611cf + 88b3e15 commit 309c141

File tree

5 files changed

+56
-20
lines changed

5 files changed

+56
-20
lines changed

src/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php

+13-5
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,7 @@ public function process(ContainerBuilder $container)
6262
// tag attribute values must be scalars
6363
foreach ($definition->getTags() as $name => $tags) {
6464
foreach ($tags as $attributes) {
65-
foreach ($attributes as $attribute => $value) {
66-
if (!\is_scalar($value) && null !== $value) {
67-
throw new RuntimeException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $name, $attribute));
68-
}
69-
}
65+
$this->validateAttributes($id, $name, $attributes);
7066
}
7167
}
7268

@@ -87,4 +83,16 @@ public function process(ContainerBuilder $container)
8783
}
8884
}
8985
}
86+
87+
private function validateAttributes(string $id, string $tag, array $attributes, array $path = []): void
88+
{
89+
foreach ($attributes as $name => $value) {
90+
if (\is_array($value)) {
91+
$this->validateAttributes($id, $tag, $value, [...$path, $name]);
92+
} elseif (!\is_scalar($value) && null !== $value) {
93+
$name = implode('.', [...$path, $name]);
94+
throw new RuntimeException(sprintf('A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $id, $tag, $name));
95+
}
96+
}
97+
}
9098
}

src/Symfony/Component/DependencyInjection/Loader/Configurator/DefaultsConfigurator.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -63,13 +63,14 @@ final public function instanceof(string $fqcn): InstanceofConfigurator
6363
return $this->parent->instanceof($fqcn);
6464
}
6565

66-
private function validateAttributes(string $tagName, array $attributes, string $prefix = ''): void
66+
private function validateAttributes(string $tag, array $attributes, array $path = []): void
6767
{
68-
foreach ($attributes as $attribute => $value) {
68+
foreach ($attributes as $name => $value) {
6969
if (\is_array($value)) {
70-
$this->validateAttributes($tagName, $value, $attribute.'.');
70+
$this->validateAttributes($tag, $value, [...$path, $name]);
7171
} elseif (!\is_scalar($value ?? '')) {
72-
throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type or an array of scalar-type.', $tagName, $prefix.$attribute));
72+
$name = implode('.', [...$path, $name]);
73+
throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type or an array of scalar-type.', $tag, $name));
7374
}
7475
}
7576
}

src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/TagTrait.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,14 @@ final public function tag(string $name, array $attributes = []): static
3333
return $this;
3434
}
3535

36-
private function validateAttributes(string $tagName, array $attributes, string $prefix = ''): void
36+
private function validateAttributes(string $tag, array $attributes, array $path = []): void
3737
{
38-
foreach ($attributes as $attribute => $value) {
38+
foreach ($attributes as $name => $value) {
3939
if (\is_array($value)) {
40-
$this->validateAttributes($tagName, $value, $attribute.'.');
40+
$this->validateAttributes($tag, $value, [...$path, $name]);
4141
} elseif (!\is_scalar($value ?? '')) {
42-
throw new InvalidArgumentException(sprintf('A tag attribute must be of a scalar-type or an array of scalar-types for service "%s", tag "%s", attribute "%s".', $this->id, $tagName, $prefix.$attribute));
42+
$name = implode('.', [...$path, $name]);
43+
throw new InvalidArgumentException(sprintf('A tag attribute must be of a scalar-type or an array of scalar-types for service "%s", tag "%s", attribute "%s".', $this->id, $tag, $name));
4344
}
4445
}
4546
}

src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php

+5-4
Original file line numberDiff line numberDiff line change
@@ -937,13 +937,14 @@ private function checkDefinition(string $id, array $definition, string $file)
937937
}
938938
}
939939

940-
private function validateAttributes(string $message, array $attributes, string $prefix = ''): void
940+
private function validateAttributes(string $message, array $attributes, array $path = []): void
941941
{
942-
foreach ($attributes as $attribute => $value) {
942+
foreach ($attributes as $name => $value) {
943943
if (\is_array($value)) {
944-
$this->validateAttributes($message, $value, $attribute.'.');
944+
$this->validateAttributes($message, $value, [...$path, $name]);
945945
} elseif (!\is_scalar($value ?? '')) {
946-
throw new InvalidArgumentException(sprintf($message, $prefix.$attribute));
946+
$name = implode('.', [...$path, $name]);
947+
throw new InvalidArgumentException(sprintf($message, $name));
947948
}
948949
}
949950
}

src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckDefinitionValidityPassTest.php

+28-3
Original file line numberDiff line numberDiff line change
@@ -80,21 +80,46 @@ public function testValidTags()
8080
$container->register('b', 'class')->addTag('foo', ['bar' => null]);
8181
$container->register('c', 'class')->addTag('foo', ['bar' => 1]);
8282
$container->register('d', 'class')->addTag('foo', ['bar' => 1.1]);
83+
$container->register('d', 'class')->addTag('foo', ['bar' => ['baz' => 'baz']]);
84+
$container->register('e', 'class')->addTag('foo', ['deep' => ['foo' => ['bar' => 'baz']]]);
8385

8486
$this->process($container);
8587

8688
$this->addToAssertionCount(1);
8789
}
8890

89-
public function testInvalidTags()
91+
/**
92+
* @dataProvider provideInvalidTags
93+
*/
94+
public function testInvalidTags(string $name, array $attributes, string $message)
9095
{
9196
$this->expectException(RuntimeException::class);
97+
$this->expectExceptionMessage($message);
9298
$container = new ContainerBuilder();
93-
$container->register('a', 'class')->addTag('foo', ['bar' => ['baz' => 'baz']]);
94-
99+
$container->register('a', 'class')->addTag($name, $attributes);
95100
$this->process($container);
96101
}
97102

103+
public static function provideInvalidTags(): iterable
104+
{
105+
$message = 'A "tags" attribute must be of a scalar-type for service "a", tag "%s", attribute "%s".';
106+
yield 'object attribute value' => [
107+
'foo',
108+
['bar' => new class() {}],
109+
sprintf($message, 'foo', 'bar'),
110+
];
111+
yield 'nested object attribute value' => [
112+
'foo',
113+
['bar' => ['baz' => new class() {}]],
114+
sprintf($message, 'foo', 'bar.baz'),
115+
];
116+
yield 'deeply nested object attribute value' => [
117+
'foo',
118+
['bar' => ['baz' => ['qux' => new class() {}]]],
119+
sprintf($message, 'foo', 'bar.baz.qux'),
120+
];
121+
}
122+
98123
public function testDynamicPublicServiceName()
99124
{
100125
$this->expectException(EnvParameterException::class);

0 commit comments

Comments
 (0)