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

Skip to content

Commit dd16390

Browse files
committed
Try to implement resolving named arguments for autowire inline
1 parent 6a7e3fc commit dd16390

File tree

5 files changed

+149
-2
lines changed

5 files changed

+149
-2
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,8 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a
321321
}
322322

323323
if ($attribute instanceof AutowireInline) {
324-
$value = $attribute->buildDefinition($value, $type, $parameter);
325-
$value = $this->doProcessValue($value);
324+
$value = $this->container->getDefinition(ContainerBuilder::hash($attribute));
325+
$value = $this->processValue($value);
326326
} elseif ($lazy = $attribute->lazy) {
327327
$definition = (new Definition($type))
328328
->setFactory('current')

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public function __construct()
6666
new ServiceLocatorTagPass(),
6767
new DecoratorServicePass(),
6868
new CheckDefinitionValidityPass(),
69+
new ResolveAutowireInlineAttributesPass(),
6970
new AutowirePass(false),
7071
new ServiceLocatorTagPass(),
7172
new ResolveTaggedIteratorArgumentPass(),
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\Attribute\AutowireInline;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Definition;
17+
use Symfony\Component\VarExporter\ProxyHelper;
18+
19+
/**
20+
* Inspects existing autowired services for {@see AutowireInline} attribute and registers the definitions for reuse.
21+
*
22+
* @author Ismail Özgün Turan <[email protected]>
23+
*/
24+
class ResolveAutowireInlineAttributesPass extends AbstractRecursivePass
25+
{
26+
protected bool $skipScalars = true;
27+
28+
protected function processValue(mixed $value, bool $isRoot = false): mixed
29+
{
30+
$value = parent::processValue($value, $isRoot);
31+
32+
if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) {
33+
return $value;
34+
}
35+
36+
if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) {
37+
$this->container->log($this, sprintf('Skipping service "%s": Class or interface "%s" cannot be loaded.', $this->currentId, $value->getClass()));
38+
39+
return $value;
40+
}
41+
42+
$constructorReflectionMethod = $reflectionClass->getConstructor();
43+
if ($constructorReflectionMethod === null) {
44+
return $value;
45+
}
46+
47+
$reflectionParameters = $constructorReflectionMethod->getParameters();
48+
foreach ($reflectionParameters as $reflectionParameter) {
49+
$autowireInlineAttributes = $reflectionParameter->getAttributes(AutowireInline::class);
50+
if ($autowireInlineAttributes === []) {
51+
continue;
52+
}
53+
54+
foreach ($autowireInlineAttributes as $autowireInlineAttribute) {
55+
/** @var AutowireInline $autowireInlineAttributeInstance */
56+
$autowireInlineAttributeInstance = $autowireInlineAttribute->newInstance();
57+
58+
$type = ProxyHelper::exportType($reflectionParameter, true);
59+
$definition = $autowireInlineAttributeInstance->buildDefinition($autowireInlineAttributeInstance->value, $type, $reflectionParameter);
60+
61+
$this->container->setDefinition(ContainerBuilder::hash($autowireInlineAttributeInstance), $definition);
62+
}
63+
}
64+
65+
return $value;
66+
}
67+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
13+
14+
use PHPUnit\Framework\TestCase;
15+
use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
16+
use Symfony\Component\DependencyInjection\Compiler\ResolveAutowireInlineAttributesPass;
17+
use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass;
18+
use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass;
19+
use Symfony\Component\DependencyInjection\Compiler\ResolveNamedArgumentsPass;
20+
use Symfony\Component\DependencyInjection\ContainerBuilder;
21+
22+
require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php';
23+
24+
class ResolveAutowireInlineAttributesPassTest extends TestCase
25+
{
26+
public function testAttribute()
27+
{
28+
$container = new ContainerBuilder();
29+
$container->register(Foo::class)->setAutowired(true);
30+
31+
$container->register('autowire_inline1', AutowireInlineAttributes1::class)
32+
->setAutowired(true);
33+
34+
$container->register('autowire_inline2', AutowireInlineAttributes2::class)
35+
->setAutowired(true);
36+
37+
(new ResolveNamedArgumentsPass())->process($container);
38+
(new ResolveClassPass())->process($container);
39+
(new ResolveChildDefinitionsPass())->process($container);
40+
(new ResolveAutowireInlineAttributesPass())->process($container);
41+
(new AutowirePass())->process($container);
42+
43+
$autowireInlineAttributes1 = $container->get('autowire_inline1');
44+
self::assertInstanceOf(AutowireInlineAttributes1::class, $autowireInlineAttributes1);
45+
46+
$autowireInlineAttributes2 = $container->get('autowire_inline2');
47+
self::assertInstanceOf(AutowireInlineAttributes2::class, $autowireInlineAttributes2);
48+
}
49+
}

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

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Symfony\Component\DependencyInjection\Attribute\AsDecorator;
66
use Symfony\Component\DependencyInjection\Attribute\Autowire;
77
use Symfony\Component\DependencyInjection\Attribute\AutowireDecorated;
8+
use Symfony\Component\DependencyInjection\Attribute\AutowireInline;
89
use Symfony\Component\DependencyInjection\Attribute\Lazy;
910
use Symfony\Component\DependencyInjection\Attribute\TaggedIterator;
1011
use Symfony\Component\DependencyInjection\Attribute\TaggedLocator;
@@ -140,3 +141,32 @@ public function __construct(#[Lazy, Autowire(lazy: true)] A $a)
140141
{
141142
}
142143
}
144+
145+
class AutowireInlineAttributesBar {
146+
public function __construct(Foo $foo, string $someString)
147+
{
148+
}
149+
}
150+
151+
class AutowireInlineAttributes1
152+
{
153+
public function __construct(
154+
#[AutowireInline(AutowireInlineAttributesBar::class, [
155+
'$foo' => Foo::class,
156+
'$someString' => 'testString',
157+
])]
158+
public AutowireInlineAttributesBar $inlined,
159+
) {
160+
}
161+
}
162+
163+
class AutowireInlineAttributes2
164+
{
165+
public function __construct(
166+
#[AutowireInline(AutowireInlineAttributesBar::class, [
167+
'$someString' => 'testString',
168+
])]
169+
public AutowireInlineAttributesBar $inlined,
170+
) {
171+
}
172+
}

0 commit comments

Comments
 (0)