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

Skip to content

Commit 4bcef3d

Browse files
weaverryannicolas-grekas
authored andcommitted
[DI] Fix autowire error for inlined services
1 parent 82ec56b commit 4bcef3d

File tree

5 files changed

+99
-7
lines changed

5 files changed

+99
-7
lines changed

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,30 @@
2121
class AutowireExceptionPass implements CompilerPassInterface
2222
{
2323
private $autowirePass;
24+
private $inlineServicePass;
2425

25-
public function __construct(AutowirePass $autowirePass)
26+
public function __construct(AutowirePass $autowirePass, InlineServiceDefinitionsPass $inlineServicePass)
2627
{
2728
$this->autowirePass = $autowirePass;
29+
$this->inlineServicePass = $inlineServicePass;
2830
}
2931

3032
public function process(ContainerBuilder $container)
3133
{
32-
foreach ($this->autowirePass->getAutowiringExceptions() as $exception) {
33-
if ($container->hasDefinition($exception->getServiceId())) {
34+
// the pass should only be run once
35+
if (null === $this->autowirePass || null === $this->inlineServicePass) {
36+
return;
37+
}
38+
39+
$inlinedIds = $this->inlineServicePass->getInlinedServiceIds();
40+
$exceptions = $this->autowirePass->getAutowiringExceptions();
41+
42+
// free up references
43+
$this->autowirePass = null;
44+
$this->inlineServicePass = null;
45+
46+
foreach ($exceptions as $exception) {
47+
if ($container->hasDefinition($exception->getServiceId()) || in_array($exception->getServiceId(), $inlinedIds)) {
3448
throw $exception;
3549
}
3650
}

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
class InlineServiceDefinitionsPass extends AbstractRecursivePass implements RepeatablePassInterface
2424
{
2525
private $repeatedPass;
26+
private $inlinedServiceIds = array();
2627

2728
/**
2829
* {@inheritdoc}
@@ -32,6 +33,16 @@ public function setRepeatedPass(RepeatedPass $repeatedPass)
3233
$this->repeatedPass = $repeatedPass;
3334
}
3435

36+
/**
37+
* Returns an array of all services inlined by this pass.
38+
*
39+
* @return array Service id strings
40+
*/
41+
public function getInlinedServiceIds()
42+
{
43+
return $this->inlinedServiceIds;
44+
}
45+
3546
/**
3647
* {@inheritdoc}
3748
*/
@@ -46,6 +57,7 @@ protected function processValue($value, $isRoot = false)
4657

4758
if ($this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) {
4859
$this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId));
60+
$this->inlinedServiceIds[] = $id;
4961

5062
if ($definition->isShared()) {
5163
return $definition;

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,11 @@ public function __construct()
7373
new RemoveAbstractDefinitionsPass(),
7474
new RepeatedPass(array(
7575
new AnalyzeServiceReferencesPass(),
76-
new InlineServiceDefinitionsPass(),
76+
$inlinedServicePass = new InlineServiceDefinitionsPass(),
7777
new AnalyzeServiceReferencesPass(),
7878
new RemoveUnusedDefinitionsPass(),
7979
)),
80-
new AutowireExceptionPass($autowirePass),
80+
new AutowireExceptionPass($autowirePass, $inlinedServicePass),
8181
new CheckExceptionOnInvalidReferenceBehaviorPass(),
8282
));
8383
}

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

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use PHPUnit\Framework\TestCase;
1515
use Symfony\Component\DependencyInjection\Compiler\AutowireExceptionPass;
1616
use Symfony\Component\DependencyInjection\Compiler\AutowirePass;
17+
use Symfony\Component\DependencyInjection\Compiler\InlineServiceDefinitionsPass;
1718
use Symfony\Component\DependencyInjection\ContainerBuilder;
1819
use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException;
1920

@@ -29,10 +30,45 @@ public function testThrowsException()
2930
->method('getAutowiringExceptions')
3031
->will($this->returnValue(array($autowireException)));
3132

33+
$inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class)
34+
->getMock();
35+
$inlinePass->expects($this->any())
36+
->method('getInlinedServiceIds')
37+
->will($this->returnValue(array()));
38+
3239
$container = new ContainerBuilder();
3340
$container->register('foo_service_id');
3441

35-
$pass = new AutowireExceptionPass($autowirePass);
42+
$pass = new AutowireExceptionPass($autowirePass, $inlinePass);
43+
44+
try {
45+
$pass->process($container);
46+
$this->fail('->process() should throw the exception if the service id exists');
47+
} catch (\Exception $e) {
48+
$this->assertSame($autowireException, $e);
49+
}
50+
}
51+
52+
public function testThrowExceptionIfServiceInlined()
53+
{
54+
$autowirePass = $this->getMockBuilder(AutowirePass::class)
55+
->getMock();
56+
57+
$autowireException = new AutowiringFailedException('foo_service_id', 'An autowiring exception message');
58+
$autowirePass->expects($this->any())
59+
->method('getAutowiringExceptions')
60+
->will($this->returnValue(array($autowireException)));
61+
62+
$inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class)
63+
->getMock();
64+
$inlinePass->expects($this->any())
65+
->method('getInlinedServiceIds')
66+
->will($this->returnValue(array('foo_service_id')));
67+
68+
// don't register the foo_service_id service
69+
$container = new ContainerBuilder();
70+
71+
$pass = new AutowireExceptionPass($autowirePass, $inlinePass);
3672

3773
try {
3874
$pass->process($container);
@@ -52,9 +88,15 @@ public function testNoExceptionIfServiceRemoved()
5288
->method('getAutowiringExceptions')
5389
->will($this->returnValue(array($autowireException)));
5490

91+
$inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class)
92+
->getMock();
93+
$inlinePass->expects($this->any())
94+
->method('getInlinedServiceIds')
95+
->will($this->returnValue(array()));
96+
5597
$container = new ContainerBuilder();
5698

57-
$pass = new AutowireExceptionPass($autowirePass);
99+
$pass = new AutowireExceptionPass($autowirePass, $inlinePass);
58100

59101
$pass->process($container);
60102
// mark the test as passed

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

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,30 @@ public function testProcessDoesNotSetLazyArgumentValuesAfterInlining()
252252
$this->assertSame('inline', (string) $values[0]);
253253
}
254254

255+
public function testGetInlinedServiceIds()
256+
{
257+
$container = new ContainerBuilder();
258+
$container
259+
->register('inlinable.service')
260+
->setPublic(false)
261+
;
262+
$container
263+
->register('non_inlinable.service')
264+
->setPublic(true)
265+
;
266+
267+
$container
268+
->register('service')
269+
->setArguments(array(new Reference('inlinable.service')))
270+
;
271+
272+
$inlinePass = new InlineServiceDefinitionsPass();
273+
$repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), $inlinePass));
274+
$repeatedPass->process($container);
275+
276+
$this->assertEquals(array('inlinable.service'), $inlinePass->getInlinedServiceIds());
277+
}
278+
255279
protected function process(ContainerBuilder $container)
256280
{
257281
$repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass()));

0 commit comments

Comments
 (0)