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

Skip to content

Commit be1dfc7

Browse files
feature #48710 [DependencyInjection] Add support for nesting autowiring-related attributes into #[Autowire(...)] (nicolas-grekas)
This PR was merged into the 6.3 branch. Discussion ---------- [DependencyInjection] Add support for nesting autowiring-related attributes into `#[Autowire(...)]` | Q | A | ------------- | --- | Branch? | 6.3 | Bug fix? | no | New feature? | yes | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - Commits ------- 55c7ce4 [DependencyInjection] Add support for nesting autowiring-related attributes into `#[Autowire(...)]`
2 parents b23a087 + 55c7ce4 commit be1dfc7

File tree

4 files changed

+63
-11
lines changed

4 files changed

+63
-11
lines changed

src/Symfony/Component/DependencyInjection/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ CHANGELOG
77
* Add options `inline_factories` and `inline_class_loader` to `PhpDumper::dump()`
88
* Deprecate `PhpDumper` options `inline_factories_parameter` and `inline_class_loader_parameter`
99
* Add `RemoveBuildParametersPass`, which removes parameters starting with a dot during compilation
10+
* Add support for nesting autowiring-related attributes into `#[Autowire(...)]`
1011

1112
6.2
1213
---

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

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,24 @@ public function process(ContainerBuilder $container)
8383

8484
protected function processValue(mixed $value, bool $isRoot = false): mixed
8585
{
86+
if ($value instanceof Autowire) {
87+
return $this->processValue($this->container->getParameterBag()->resolveValue($value->value));
88+
}
89+
90+
if ($value instanceof TaggedIterator) {
91+
return new TaggedIteratorArgument($value->tag, $value->indexAttribute, $value->defaultIndexMethod, false, $value->defaultPriorityMethod, (array) $value->exclude);
92+
}
93+
94+
if ($value instanceof TaggedLocator) {
95+
return new ServiceLocatorArgument(new TaggedIteratorArgument($value->tag, $value->indexAttribute, $value->defaultIndexMethod, true, $value->defaultPriorityMethod, (array) $value->exclude));
96+
}
97+
98+
if ($value instanceof MapDecorated) {
99+
$definition = $this->container->getDefinition($this->currentId);
100+
101+
return new Reference($definition->innerServiceId ?? $this->currentId.'.inner', $definition->decorationOnInvalid ?? ContainerInterface::NULL_ON_INVALID_REFERENCE);
102+
}
103+
86104
try {
87105
return $this->doProcessValue($value, $isRoot);
88106
} catch (AutowiringFailedException $e) {
@@ -170,20 +188,14 @@ private function processAttribute(object $attribute, bool $isOptional = false):
170188
{
171189
switch (true) {
172190
case $attribute instanceof Autowire:
173-
$value = $this->container->getParameterBag()->resolveValue($attribute->value);
174-
175-
return $value instanceof Reference && $isOptional ? new Reference($value, ContainerInterface::NULL_ON_INVALID_REFERENCE) : $value;
176-
191+
if ($isOptional && $attribute->value instanceof Reference) {
192+
return new Reference($attribute->value, ContainerInterface::NULL_ON_INVALID_REFERENCE);
193+
}
194+
// no break
177195
case $attribute instanceof TaggedIterator:
178-
return new TaggedIteratorArgument($attribute->tag, $attribute->indexAttribute, $attribute->defaultIndexMethod, false, $attribute->defaultPriorityMethod, (array) $attribute->exclude);
179-
180196
case $attribute instanceof TaggedLocator:
181-
return new ServiceLocatorArgument(new TaggedIteratorArgument($attribute->tag, $attribute->indexAttribute, $attribute->defaultIndexMethod, true, $attribute->defaultPriorityMethod, (array) $attribute->exclude));
182-
183197
case $attribute instanceof MapDecorated:
184-
$definition = $this->container->getDefinition($this->currentId);
185-
186-
return new Reference($definition->innerServiceId ?? $this->currentId.'.inner', $definition->decorationOnInvalid ?? ContainerInterface::NULL_ON_INVALID_REFERENCE);
198+
return $this->processValue($attribute);
187199
}
188200

189201
throw new AutowiringFailedException($this->currentId, sprintf('"%s" is an unsupported attribute.', $attribute::class));

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
use Psr\Log\LoggerInterface;
1616
use Psr\Log\NullLogger;
1717
use Symfony\Component\Config\FileLocator;
18+
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
19+
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
1820
use Symfony\Component\DependencyInjection\Compiler\AutowireAsDecoratorPass;
1921
use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
2022
use Symfony\Component\DependencyInjection\Compiler\AutowireRequiredMethodsPass;
@@ -1254,4 +1256,25 @@ public function testTypeNamespaceExcluded()
12541256
$this->assertSame('Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgument::__construct()" needs an instance of "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but this type has been excluded from autowiring.', (string) $e->getMessage());
12551257
}
12561258
}
1259+
1260+
public function testNestedAttributes()
1261+
{
1262+
$container = new ContainerBuilder();
1263+
1264+
$container->register(AsDecoratorFoo::class);
1265+
$container->register(AutowireNestedAttributes::class)->setAutowired(true);
1266+
1267+
(new ResolveClassPass())->process($container);
1268+
(new AutowireAsDecoratorPass())->process($container);
1269+
(new DecoratorServicePass())->process($container);
1270+
(new AutowirePass())->process($container);
1271+
1272+
$expected = [
1273+
'decorated' => new Reference(AutowireNestedAttributes::class.'.inner'),
1274+
'iterator' => new TaggedIteratorArgument('foo'),
1275+
'locator' => new ServiceLocatorArgument(new TaggedIteratorArgument('foo', needsIndexes: true)),
1276+
'service' => new Reference('bar'),
1277+
];
1278+
$this->assertEquals($expected, $container->getDefinition(AutowireNestedAttributes::class)->getArgument(0));
1279+
}
12571280
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes_80.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
66
use Symfony\Component\DependencyInjection\Attribute\Autowire;
77
use Symfony\Component\DependencyInjection\Attribute\MapDecorated;
8+
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
9+
use Symfony\Component\DependencyInjection\Attribute\TaggedLocator;
810
use Symfony\Component\DependencyInjection\ContainerInterface;
911
use Symfony\Contracts\Service\Attribute\Required;
1012

@@ -85,3 +87,17 @@ public function __construct(#[MapDecorated] AsDecoratorInterface $inner = null)
8587
{
8688
}
8789
}
90+
91+
#[AsDecorator(decorates: AsDecoratorFoo::class)]
92+
class AutowireNestedAttributes implements AsDecoratorInterface
93+
{
94+
public function __construct(
95+
#[Autowire([
96+
'decorated' => new MapDecorated(),
97+
'iterator' => new TaggedIterator('foo'),
98+
'locator' => new TaggedLocator('foo'),
99+
'service' => new Autowire(service: 'bar')
100+
])] array $options)
101+
{
102+
}
103+
}

0 commit comments

Comments
 (0)