Skip to content

Commit 64b715b

Browse files
committed
bug symfony#22386 [DI] Fix inheriting defaults with instanceof conditionals (nicolas-grekas)
This PR was merged into the 3.3-dev branch. Discussion ---------- [DI] Fix inheriting defaults with instanceof conditionals | Q | A | ------------- | --- | Branch? | 3.3 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - Commits ------- 168765d [DI] Fix inheriting defaults with instanceof conditionals
2 parents 8596b19 + 168765d commit 64b715b

File tree

2 files changed

+39
-22
lines changed

2 files changed

+39
-22
lines changed

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

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,12 @@ class ResolveInstanceofConditionalsPass implements CompilerPassInterface
2727
*/
2828
public function process(ContainerBuilder $container)
2929
{
30-
$didProcess = false;
3130
foreach ($container->getDefinitions() as $id => $definition) {
3231
if ($definition instanceof ChildDefinition) {
3332
// don't apply "instanceof" to children: it will be applied to their parent
3433
continue;
3534
}
36-
if ($definition !== $processedDefinition = $this->processDefinition($container, $id, $definition)) {
37-
$didProcess = true;
38-
$container->setDefinition($id, $processedDefinition);
39-
}
40-
}
41-
if ($didProcess) {
42-
$container->register('abstract.'.__CLASS__, '')->setAbstract(true);
35+
$container->setDefinition($id, $this->processDefinition($container, $id, $definition));
4336
}
4437
}
4538

@@ -53,37 +46,56 @@ private function processDefinition(ContainerBuilder $container, $id, Definition
5346
}
5447

5548
$definition->setInstanceofConditionals(array());
56-
$instanceofParent = null;
57-
$parent = 'abstract.'.__CLASS__;
58-
$shared = null;
49+
$parent = $shared = null;
50+
$instanceofTags = array();
5951

6052
foreach ($instanceofConditionals as $interface => $instanceofDef) {
6153
if ($interface !== $class && (!$container->getReflectionClass($interface) || !$container->getReflectionClass($class))) {
6254
continue;
6355
}
6456
if ($interface === $class || is_subclass_of($class, $interface)) {
65-
$instanceofParent = clone $instanceofDef;
66-
$instanceofParent->setAbstract(true)->setInheritTags(true)->setParent($parent);
57+
$instanceofDef = clone $instanceofDef;
58+
$instanceofDef->setAbstract(true)->setInheritTags(false)->setParent($parent ?: 'abstract.instanceof.'.$id);
6759
$parent = 'instanceof.'.$interface.'.'.$id;
68-
$container->setDefinition($parent, $instanceofParent);
60+
$container->setDefinition($parent, $instanceofDef);
61+
$instanceofTags[] = $instanceofDef->getTags();
62+
$instanceofDef->setTags(array());
6963

70-
if (isset($instanceofParent->getChanges()['shared'])) {
71-
$shared = $instanceofParent->isShared();
64+
if (isset($instanceofDef->getChanges()['shared'])) {
65+
$shared = $instanceofDef->isShared();
7266
}
7367
}
7468
}
7569

76-
if ($instanceofParent) {
70+
if ($parent) {
71+
$abstract = $container->setDefinition('abstract.instanceof.'.$id, $definition);
72+
7773
// cast Definition to ChildDefinition
7874
$definition = serialize($definition);
7975
$definition = substr_replace($definition, '53', 2, 2);
8076
$definition = substr_replace($definition, 'Child', 44, 0);
8177
$definition = unserialize($definition);
82-
$definition->setInheritTags(true)->setParent($parent);
78+
$definition->setParent($parent);
8379

8480
if (null !== $shared && !isset($definition->getChanges()['shared'])) {
8581
$definition->setShared($shared);
8682
}
83+
84+
$i = count($instanceofTags);
85+
while (0 <= --$i) {
86+
foreach ($instanceofTags[$i] as $k => $v) {
87+
foreach ($v as $v) {
88+
$definition->addTag($k, $v);
89+
}
90+
}
91+
}
92+
93+
// reset fields with "merge" behavior
94+
$abstract
95+
->setArguments(array())
96+
->setMethodCalls(array())
97+
->setTags(array())
98+
->setAbstract(true);
8799
}
88100

89101
return $definition;

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

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ class ResolveInstanceofConditionalsPassTest extends TestCase
2222
public function testProcess()
2323
{
2424
$container = new ContainerBuilder();
25-
$def = $container->register('foo', self::class);
25+
$def = $container->register('foo', self::class)->addTag('tag')->setAutowired(true)->setChanges(array());
2626
$def->setInstanceofConditionals(array(
27-
parent::class => (new ChildDefinition(''))->setProperty('foo', 'bar'),
27+
parent::class => (new ChildDefinition(''))->setProperty('foo', 'bar')->addTag('baz', array('attr' => 123)),
2828
));
2929

3030
(new ResolveInstanceofConditionalsPass())->process($container);
@@ -33,9 +33,14 @@ public function testProcess()
3333
$def = $container->getDefinition('foo');
3434
$this->assertEmpty($def->getInstanceofConditionals());
3535
$this->assertInstanceof(ChildDefinition::class, $def);
36-
$this->assertTrue($def->getInheritTags());
36+
$this->assertTrue($def->isAutowired());
37+
$this->assertFalse($def->getInheritTags());
3738
$this->assertSame($parent, $def->getParent());
38-
$this->assertEquals(array('foo' => 'bar'), $container->getDefinition($parent)->getProperties());
39+
$this->assertSame(array('tag' => array(array()), 'baz' => array(array('attr' => 123))), $def->getTags());
40+
41+
$parent = $container->getDefinition($parent);
42+
$this->assertSame(array('foo' => 'bar'), $parent->getProperties());
43+
$this->assertSame(array(), $parent->getTags());
3944
}
4045

4146
public function testProcessInheritance()

0 commit comments

Comments
 (0)