8000 Merge branch '3.2' · symfony/symfony@a399e75 · GitHub
[go: up one dir, main page]

Skip to content

Commit a399e75

Browse files
committed
Merge branch '3.2'
* 3.2: [DependencyInjection] Fix using autowiring types when there are more than 2 services [DependencyInjection] Fix autowiring collisions detection [DI] Bug in autowiring collisions detection
2 parents 64ec5c5 + 043c9ad commit a399e75

File tree

2 files changed

+85
-0
lines changed

2 files changed

+85
-0
lines changed

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

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class AutowirePass extends AbstractRecursivePass
3737
private $definedTypes = array();
3838
private $types;
3939
private $ambiguousServiceTypes = array();
40+
private $usedTypes = array();
4041

4142
/**
4243
* {@inheritdoc}
@@ -45,11 +46,27 @@ public function process(ContainerBuilder $container)
4546
{
4647
try {
4748
parent::process($container);
49+
50+
foreach ($this->usedTypes as $type => $id) {
51+
if (!isset($this->usedTypes[$type]) || !isset($this->ambiguousServiceTypes[$type])) {
52+
continue;
53+
}
54+
55+
if ($container->has($type) && !$container->findDefinition($type)->isAbstract()) {
56+
continue;
57+
}
58+
59+
$classOrInterface = class_exists($type) ? 'class' : 'interface';
60+
$matchingServices = implode(', ', $this->ambiguousServiceTypes[$type]);
61+
62+
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));
63+
}
4864
} finally {
4965
// Free memory
5066
$this->definedTypes = array();
5167
$this->types = null;
5268
$this->ambiguousServiceTypes = array();
69+
$this->usedTypes = array();
5370
}
5471
}
5572

@@ -271,10 +288,12 @@ private function autowireMethod(\ReflectionMethod $reflectionMethod, array $argu
271288
if (isset($this->types[$typeName])) {
272289
$value = new Reference($this->types[$typeName]);
273290
$didAutowire = true;
291+
$this->usedTypes[$typeName] = $this->currentId;
274292
} elseif ($typeHint = $this->container->getReflectionClass($typeName, true)) {
275293
try {
276294
$value = $this->createAutowiredDefinition($typeHint);
277295
$didAutowire = true;
296+
$this->usedTypes[$typeName] = $this->currentId;
278297
} catch (RuntimeException $e) {
279298
if ($parameter->allowsNull()) {
280299
$value = null;
@@ -354,13 +373,18 @@ private function autowireOverridenGetters(array $overridenGetters, array $autowi
354373
try {
355374
$value = $this->createAutowiredDefinition($returnType);
356375
} catch (RuntimeException $e) {
376+
if (1 === $e->getCode()) {
377+
throw $e;
378+
}
379+
357380
continue;
358381
}
359382
} else {
360383
continue;
361384
}
362385

363386
$overridenGetters[$lcMethod] = $value;
387+
$this->usedTypes[$typeName] = $this->currentId;
364388
}
365389

366390
return $overridenGetters;
@@ -394,6 +418,7 @@ private function populateAvailableType($id, Definition $definition)
394418
foreach ($definition->getAutowiringTypes(false) as $type) {
395419
$this->definedTypes[$type] = true;
396420
$this->types[$type] = $id;
421+
unset($this->ambiguousServiceTypes[$type]);
397422
}
398423

399424
if (!$reflectionClass = $this->container->getReflectionClass($definition->getClass(), true)) {

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

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ public function testTypeNotGuessableWithTypeSet()
192192
$container = new ContainerBuilder();
193193

194194
$container->register('a1', __NAMESPACE__.'\Foo');
195+
$container->register('a2', __NAMESPACE__.'\Foo');
195196
$container->register(Foo::class, Foo::class);
196197
$aDefinition = $container->register('a', __NAMESPACE__.'\NotGuessableArgument');
197198
$aDefinition->setAutowired(true);
@@ -542,6 +543,26 @@ public function testGetterOverriding()
542543
), $overridenGetters);
543544
}
544545

546+
/**
547+
* @requires PHP 7.1
548+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
549+
* @expectedExceptionMessage Unable to autowire argument of type "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" for the service "getter_overriding". Multiple services exist for this class (a1, a2).
550+
*/
551+
public function testGetterOverridingWithAmbiguousServices()
552+
{
553+
$container = new ContainerBuilder();
554+
$container->register('a1', Foo::class);
555+
$container->register('a2', Foo::class);
556+
557+
$container
558+
->register('getter_overriding', GetterOverriding::class)
559+
->setAutowiredCalls(array('getFoo'))
560+
;
561+
562+
$pass = new AutowirePass();
563+
$pass->process($container);
564+
}
565+
545566
/**
546567
* @dataProvider getCreateResourceTests
547568
* @group legacy
@@ -637,6 +658,31 @@ public function testEmptyStringIsKept()
637658

638659
$this->assertEquals(array(new Reference('a'), '', new Reference('lille')), $container->getDefinition('foo')->getArguments());
639660
}
661+
662+
/**
663+
* @dataProvider provideAutodiscoveredAutowiringOrder
664+
*
665+
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
666+
* @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).
667+
*/
668+
public function testAutodiscoveredAutowiringOrder($class)
669+
{
670+
$container = new ContainerBuilder();
671+
672+
$container->register('a', __NAMESPACE__.'\\'.$class)
673+
->setAutowired(true);
674+
675+
$pass = new AutowirePass();
676+
$pass->process($container);
677+
}
678+
679+
public function provideAutodiscoveredAutowiringOrder()
680+
{
681+
return array(
682+
array('CannotBeAutowiredForwardOrder'),
683+
array('CannotBeAutowiredReverseOrder'),
684+
);
685+
}
640686
}
641687

642688
class Foo
@@ -718,6 +764,20 @@ public function __construct(CollisionInterface $collision)
718764
}
719765
}
720766

767+
class CannotBeAutowiredForwardOrder
768+
{
769+
public function __construct(CollisionA $a, CollisionInterface $b, CollisionB $c)
770+
{
771+
}
772+
}
773+
774+
class CannotBeAutowiredReverseOrder
775+
{
776+
public function __construct(CollisionA $a, CollisionB $c, CollisionInterface $b)
777+
{
778+
}
779+
}
780+
721781
class Lille
722782
{
723783
}

0 commit comments

Comments
 (0)
0