Merge branch '2.8' into 3.2
* 2.8: [DependencyInjection] Fix using autowiring types when there are more than 2 services [DependencyInjection] Fix autowiring collisions detection [DI] Bug in autowiring collisions detection
This commit is contained in:
commit
043c9ad7ef
@ -29,6 +29,7 @@ class AutowirePass implements CompilerPassInterface
|
||||
private $definedTypes = array();
|
||||
private $types;
|
||||
private $ambiguousServiceTypes = array();
|
||||
private $usedTypes = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
@ -45,6 +46,15 @@ class AutowirePass implements CompilerPassInterface
|
||||
$this->completeDefinition($id, $definition);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->usedTypes as $type => $id) {
|
||||
if (isset($this->usedTypes[$type]) && isset($this->ambiguousServiceTypes[$type])) {
|
||||
$classOrInterface = class_exists($type) ? 'class' : 'interface';
|
||||
$matchingServices = implode(', ', $this->ambiguousServiceTypes[$type]);
|
||||
|
||||
throw new RuntimeException(sprintf('Unable to autowire argument of type "%s" for the service "%s". Multiple services exist for this %s (%s).', $type, $id, $classOrInterface, $matchingServices));
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
spl_autoload_unregister($throwingAutoloader);
|
||||
|
||||
@ -54,6 +64,7 @@ class AutowirePass implements CompilerPassInterface
|
||||
$this->definedTypes = array();
|
||||
$this->types = null;
|
||||
$this->ambiguousServiceTypes = array();
|
||||
$this->usedTypes = array();
|
||||
}
|
||||
}
|
||||
|
||||
@ -128,9 +139,11 @@ class AutowirePass implements CompilerPassInterface
|
||||
|
||||
if (isset($this->types[$typeHint->name])) {
|
||||
$value = new Reference($this->types[$typeHint->name]);
|
||||
$this->usedTypes[$typeHint->name] = $id;
|
||||
} else {
|
||||
try {
|
||||
$value = $this->createAutowiredDefinition($typeHint, $id);
|
||||
$this->usedTypes[$typeHint->name] = $id;
|
||||
} catch (RuntimeException $e) {
|
||||
if ($parameter->allowsNull()) {
|
||||
$value = null;
|
||||
@ -188,6 +201,7 @@ class AutowirePass implements CompilerPassInterface
|
||||
foreach ($definition->getAutowiringTypes() as $type) {
|
||||
$this->definedTypes[$type] = true;
|
||||
$this->types[$type] = $id;
|
||||
unset($this->ambiguousServiceTypes[$type]);
|
||||
}
|
||||
|
||||
if (!$reflectionClass = $this->getReflectionClass($id, $definition)) {
|
||||
|
@ -191,7 +191,8 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
|
||||
$container = new ContainerBuilder();
|
||||
|
||||
$container->register('a1', __NAMESPACE__.'\Foo');
|
||||
$container->register('a2', __NAMESPACE__.'\Foo')->addAutowiringType(__NAMESPACE__.'\Foo');
|
||||
$container->register('a2', __NAMESPACE__.'\Foo');
|
||||
$container->register('a3', __NAMESPACE__.'\Foo')->addAutowiringType(__NAMESPACE__.'\Foo');
|
||||
$aDefinition = $container->register('a', __NAMESPACE__.'\NotGuessableArgument');
|
||||
$aDefinition->setAutowired(true);
|
||||
|
||||
@ -199,7 +200,7 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
|
||||
$pass->process($container);
|
||||
|
||||
$this->assertCount(1, $container->getDefinition('a')->getArguments());
|
||||
$this->assertEquals('a2', (string) $container->getDefinition('a')->getArgument(0));
|
||||
$this->assertEquals('a3', (string) $container->getDefinition('a')->getArgument(0));
|
||||
}
|
||||
|
||||
public function testWithTypeSet()
|
||||
@ -510,6 +511,31 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$this->assertEquals(array(new Reference('a'), '', new Reference('lille')), $container->getDefinition('foo')->getArguments());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideAutodiscoveredAutowiringOrder
|
||||
*
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||
* @expectedExceptionMEssage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" for the service "a". Multiple services exist for this interface (autowired.Symfony\Component\DependencyInjection\Tests\Compiler\CollisionA, autowired.Symfony\Component\DependencyInjection\Tests\Compiler\CollisionB).
|
||||
*/
|
||||
public function testAutodiscoveredAutowiringOrder($class)
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
|
||||
$container->register('a', __NAMESPACE__.'\\'.$class)
|
||||
->setAutowired(true);
|
||||
|
||||
$pass = new AutowirePass();
|
||||
$pass->process($container);
|
||||
}
|
||||
|
||||
public function provideAutodiscoveredAutowiringOrder()
|
||||
{
|
||||
return array(
|
||||
array('CannotBeAutowiredForwardOrder'),
|
||||
array('CannotBeAutowiredReverseOrder'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Foo
|
||||
@ -591,6 +617,20 @@ class CannotBeAutowired
|
||||
}
|
||||
}
|
||||
|
||||
class CannotBeAutowiredForwardOrder
|
||||
{
|
||||
public function __construct(CollisionA $a, CollisionInterface $b, CollisionB $c)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class CannotBeAutowiredReverseOrder
|
||||
{
|
||||
public function __construct(CollisionA $a, CollisionB $c, CollisionInterface $b)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class Lille
|
||||
{
|
||||
}
|
||||
|
Reference in New Issue
Block a user