[DI] Autowiring exception thrown when inlined service is removed

This commit is contained in:
Ryan Weaver 2017-05-31 10:32:39 -04:00 committed by Fabien Potencier
parent 5473373473
commit 793b9a001f
4 changed files with 62 additions and 9 deletions

View File

@ -44,9 +44,23 @@ class AutowireExceptionPass implements CompilerPassInterface
$this->inlineServicePass = null;
foreach ($exceptions as $exception) {
if ($container->hasDefinition($exception->getServiceId()) || in_array($exception->getServiceId(), $inlinedIds)) {
if ($this->doesServiceExistInTheContainer($exception->getServiceId(), $container, $inlinedIds)) {
throw $exception;
}
}
}
private function doesServiceExistInTheContainer($serviceId, ContainerBuilder $container, array $inlinedIds)
{
if ($container->hasDefinition($serviceId)) {
return true;
}
// was the service inlined? Of so, does its parent service exist?
if (isset($inlinedIds[$serviceId])) {
return $this->doesServiceExistInTheContainer($inlinedIds[$serviceId], $container, $inlinedIds);
}
return false;
}
}

View File

@ -36,7 +36,9 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass implements Repe
/**
* Returns an array of all services inlined by this pass.
*
* @return array Service id strings
* The key is the inlined service id and its value is the service it was inlined into.
*
* @return array
*/
public function getInlinedServiceIds()
{
@ -57,7 +59,7 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass implements Repe
if ($this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) {
$this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId));
$this->inlinedServiceIds[] = $id;
$this->inlinedServiceIds[$id] = $this->currentId;
if ($definition->isShared()) {
return $definition;

View File

@ -54,7 +54,7 @@ class AutowireExceptionPassTest extends TestCase
$autowirePass = $this->getMockBuilder(AutowirePass::class)
->getMock();
$autowireException = new AutowiringFailedException('foo_service_id', 'An autowiring exception message');
$autowireException = new AutowiringFailedException('a_service', 'An autowiring exception message');
$autowirePass->expects($this->any())
->method('getAutowiringExceptions')
->will($this->returnValue(array($autowireException)));
@ -63,10 +63,16 @@ class AutowireExceptionPassTest extends TestCase
->getMock();
$inlinePass->expects($this->any())
->method('getInlinedServiceIds')
->will($this->returnValue(array('foo_service_id')));
->will($this->returnValue(array(
// a_service inlined into b_service
'a_service' => 'b_service',
// b_service inlined into c_service
'b_service' => 'c_service',
)));
// don't register the foo_service_id service
$container = new ContainerBuilder();
// ONLY register c_service in the final container
$container->register('c_service', 'stdClass');
$pass = new AutowireExceptionPass($autowirePass, $inlinePass);
@ -78,6 +84,37 @@ class AutowireExceptionPassTest extends TestCase
}
}
public function testDoNotThrowExceptionIfServiceInlinedButRemoved()
{
$autowirePass = $this->getMockBuilder(AutowirePass::class)
->getMock();
$autowireException = new AutowiringFailedException('a_service', 'An autowiring exception message');
$autowirePass->expects($this->any())
->method('getAutowiringExceptions')
->will($this->returnValue(array($autowireException)));
$inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class)
->getMock();
$inlinePass->expects($this->any())
->method('getInlinedServiceIds')
->will($this->returnValue(array(
// a_service inlined into b_service
'a_service' => 'b_service',
// b_service inlined into c_service
'b_service' => 'c_service',
)));
// do NOT register c_service in the container
$container = new ContainerBuilder();
$pass = new AutowireExceptionPass($autowirePass, $inlinePass);
$pass->process($container);
// mark the test as passed
$this->assertTrue(true);
}
public function testNoExceptionIfServiceRemoved()
{
$autowirePass = $this->getMockBuilder(AutowirePass::class)

View File

@ -252,7 +252,7 @@ class InlineServiceDefinitionsPassTest extends TestCase
$this->assertSame('inline', (string) $values[0]);
}
public function testGetInlinedServiceIds()
public function testGetInlinedServiceIdData()
{
$container = new ContainerBuilder();
$container
@ -265,7 +265,7 @@ class InlineServiceDefinitionsPassTest extends TestCase
;
$container
->register('service')
->register('other_service')
->setArguments(array(new Reference('inlinable.service')))
;
@ -273,7 +273,7 @@ class InlineServiceDefinitionsPassTest extends TestCase
$repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), $inlinePass));
$repeatedPass->process($container);
$this->assertEquals(array('inlinable.service'), $inlinePass->getInlinedServiceIds());
$this->assertEquals(array('inlinable.service' => 'other_service'), $inlinePass->getInlinedServiceIds());
}
protected function process(ContainerBuilder $container)