bug #19643 [DependencyInjection] Fix service autowiring inheritance (chalasr)

This PR was merged into the 2.8 branch.

Discussion
----------

[DependencyInjection] Fix service autowiring inheritance

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

This makes services inherit the `autowire` attribute from their parent and fix the ability to override it from the child.

Fixed cases:

- Simple inheritance
```yaml
parent:
    class: Foo
    abstract: true
    autowire: true

child:
    class: Foo
```

- Set in the child (only)
```yaml
parent:
    class: Foo
    abstract: true

child:
    class: Foo
    autowire: true
```

- Set in the parent, changed in the child
```yaml
parent:
    class: Foo
    abstract: true
    autowire: true

child:
    class: Foo
    autowire: false
```

Commits
-------

fb95bdc [DIC] Fix service autowiring inheritance
This commit is contained in:
Fabien Potencier 2016-08-19 08:59:07 -07:00
commit fc483cf432
4 changed files with 54 additions and 0 deletions

View File

@ -136,6 +136,7 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
$def->setFile($parentDef->getFile());
$def->setPublic($parentDef->isPublic());
$def->setLazy($parentDef->isLazy());
$def->setAutowired($parentDef->isAutowired());
// overwrite with values specified in the decorator
$changes = $definition->getChanges();
@ -169,6 +170,9 @@ class ResolveDefinitionTemplatesPass implements CompilerPassInterface
if (isset($changes['deprecated'])) {
$def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
}
if (isset($changes['autowire'])) {
$def->setAutowired($definition->isAutowired());
}
if (isset($changes['decorated_service'])) {
$decoratedService = $definition->getDecoratedService();
if (null === $decoratedService) {

View File

@ -164,6 +164,16 @@ class DefinitionDecorator extends Definition
return parent::setDeprecated($boolean, $template);
}
/**
* {@inheritdoc}
*/
public function setAutowired($autowired)
{
$this->changes['autowire'] = true;
return parent::setAutowired($autowired);
}
/**
* Gets an argument to pass to the service constructor/factory method.
*

View File

@ -233,6 +233,36 @@ class ResolveDefinitionTemplatesPassTest extends \PHPUnit_Framework_TestCase
$this->assertTrue($container->getDefinition('child1')->isLazy());
}
public function testSetAutowiredOnServiceHasParent()
{
$container = new ContainerBuilder();
$container->register('parent', 'stdClass');
$container->setDefinition('child1', new DefinitionDecorator('parent'))
->setAutowired(true)
;
$this->process($container);
$this->assertTrue($container->getDefinition('child1')->isAutowired());
}
public function testSetAutowiredOnServiceIsParent()
{
$container = new ContainerBuilder();
$container->register('parent', 'stdClass')
->setAutowired(true)
;
$container->setDefinition('child1', new DefinitionDecorator('parent'));
$this->process($container);
$this->assertTrue($container->getDefinition('child1')->isAutowired());
}
public function testDeepDefinitionsResolving()
{
$container = new ContainerBuilder();

View File

@ -95,6 +95,16 @@ class DefinitionDecoratorTest extends \PHPUnit_Framework_TestCase
$this->assertEquals(array('lazy' => true), $def->getChanges());
}
public function testSetAutowired()
{
$def = new DefinitionDecorator('foo');
$this->assertFalse($def->isAutowired());
$this->assertSame($def, $def->setAutowired(false));
$this->assertFalse($def->isAutowired());
$this->assertEquals(array('autowire' => true), $def->getChanges());
}
public function testSetArgument()
{
$def = new DefinitionDecorator('foo');