feature #16464 [DependencyInjection] Fix some edge cases with autowiring (dunglas)

This PR was merged into the 2.8 branch.

Discussion
----------

[DependencyInjection] Fix some edge cases with autowiring

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | no
| BC breaks?    | no
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | n/a
| License       | MIT
| Doc PR        | n/a

Enhance the autowiring system:

- Works with parent definitions and decorator
- Always exclude parent definitions

It allows to autowire major services of the standard edition (tested with Swift Mailer, Monolog, Doctrine and Twig).

Commits
-------

faefc60 [DependencyInjection] Autowing: exclude abstract definitons
71d502a [DependencyInjection] Autowiring: support parent/decorators
This commit is contained in:
Fabien Potencier 2015-11-07 09:14:48 +01:00
commit 0e66da8abb
4 changed files with 49 additions and 2 deletions

View File

@ -138,7 +138,8 @@ class AutowirePass implements CompilerPassInterface
*/
private function populateAvailableType($id, Definition $definition)
{
if (!$definition->getClass()) {
// Never use abstract services
if ($definition->isAbstract()) {
return;
}
@ -147,6 +148,11 @@ class AutowirePass implements CompilerPassInterface
$this->types[$type] = $id;
}
// Cannot use reflection if the class isn't set
if (!$definition->getClass()) {
return;
}
if ($reflectionClass = $this->getReflectionClass($id, $definition)) {
$this->extractInterfaces($id, $reflectionClass);
$this->extractAncestors($id, $reflectionClass);

View File

@ -118,6 +118,7 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
$def->setArguments($parentDef->getArguments());
$def->setMethodCalls($parentDef->getMethodCalls());
$def->setProperties($parentDef->getProperties());
$def->setAutowiringTypes($parentDef->getAutowiringTypes());
if ($parentDef->getFactoryClass(false)) {
$def->setFactoryClass($parentDef->getFactoryClass(false));
}
@ -202,6 +203,11 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
}
// merge autowiring types
foreach ($definition->getAutowiringTypes() as $autowiringType) {
$def->addAutowiringType($autowiringType);
}
// these attributes are always taken from the child
$def->setAbstract($definition->isAbstract());
$def->setScope($definition->getScope(false), false);

View File

@ -189,7 +189,7 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
$this->assertEquals('foo', $definition->getArgument(2));
}
public function testDontTriggeruAutowiring()
public function testDontTriggerAutowiring()
{
$container = new ContainerBuilder();
@ -216,6 +216,21 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
$pass = new AutowirePass();
$pass->process($container);
}
public function testDontUseAbstractServices()
{
$container = new ContainerBuilder();
$container->register('abstract_foo', __NAMESPACE__.'\Foo')->setAbstract(true);
$container->register('foo', __NAMESPACE__.'\Foo');
$container->register('bar', __NAMESPACE__.'\Bar')->setAutowired(true);
$pass = new AutowirePass();
$pass->process($container);
$arguments = $container->getDefinition('bar')->getArguments();
$this->assertSame('foo', (string) $arguments[0]);
}
}
class Foo

View File

@ -274,6 +274,26 @@ class ResolveDefinitionTemplatesPassTest extends \PHPUnit_Framework_TestCase
$this->assertFalse($container->getDefinition('decorated_deprecated_parent')->isDeprecated());
}
public function testProcessMergeAutowiringTypes()
{
$container = new ContainerBuilder();
$container
->register('parent')
->addAutowiringType('Foo')
;
$container
->setDefinition('child', new DefinitionDecorator('parent'))
->addAutowiringType('Bar')
;
$this->process($container);
$def = $container->getDefinition('child');
$this->assertEquals(array('Foo', 'Bar'), $def->getAutowiringTypes());
}
protected function process(ContainerBuilder $container)
{
$pass = new ResolveDefinitionTemplatesPass();