8000 [DI] Rework config hierarchy: defaults > instanceof > service config · symfony/symfony@a301f86 · GitHub
[go: up one dir, main page]

Skip to content

Commit a301f86

Browse files
[DI] Rework config hierarchy: defaults > instanceof > service config
1 parent a1a45cf commit a301f86

8 files changed

+294
-275
lines changed

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ public function __construct()
4242
$this->beforeOptimizationPasses = array(
4343
100 => array(
4444
$resolveClassPass = new ResolveClassPass(),
45-
new ResolveDefinitionInheritancePass(),
45+
new ResolveInstanceofConditionalsPass(),
46+
new ResolveTagsInheritancePass(),
4647
),
4748
);
4849

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

Lines changed: 0 additions & 99 deletions
This file was deleted.

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

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -102,26 +102,6 @@ private function doResolveDefinition(ChildDefinition $definition)
102102
$def->setLazy($parentDef->isLazy());
103103
$def->setAutowired($parentDef->isAutowired());
104104

105-
self::mergeDefinition($def, $definition);
106-
107-
// merge autowiring types
108-
foreach ($definition->getAutowiringTypes(false) as $autowiringType) {
109-
$def->addAutowiringType($autowiringType);
110-
}
111-
112-
// these attributes are always taken from the child
113-
$def->setAbstract($definition->isAbstract());
114-
$def->setShared($definition->isShared());
115-
$def->setTags($definition->getTags());
116-
117-
return $def;
118-
}
119-
120-
/**
121-
* @internal
122-
*/
123-
public static function mergeDefinition(Definition $def, ChildDefinition $definition)
124-
{
125105
// overwrite with values specified in the decorator
126106
$changes = $definition->getChanges();
127107
if (isset($changes['class'])) {
@@ -182,5 +162,17 @@ public static function mergeDefinition(Definition $def, ChildDefinition $definit
182162
if ($calls = $definition->getMethodCalls()) {
183163
$def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
184164
}
165+
166+
// merge autowiring types
167+
foreach ($definition->getAutowiringTypes(false) as $autowiringType) {
168+
$def->addAutowiringType($autowiringType);
169+
}
170+
171+
// these attributes are always taken from the child
172+
$def->setAbstract($definition->isAbstract());
173+
$def->setShared($definition->isShared());
174+
$def->setTags($definition->getTags());
175+
176+
return $def;
185177
}
186178
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\ChildDefinition;
15+
use Symfony\Component\DependencyInjection\ContainerBuilder;
16+
use Symfony\Component\DependencyInjection\Definition;
17+
18+
/**
19+
* Applies instanceof conditionals to definitions.
20+
*
21+
* @author Nicolas Grekas <p@tchwork.com>
22+
*/
23+
class ResolveInstanceofConditionalsPass implements CompilerPassInterface
24+
{
25+
/**
26+
* {@inheritdoc}
27+
*/
28+
public function process(ContainerBuilder $container)
29+
{
30+
$didProcess = false;
31+
foreach ($container->getDefinitions() as $id => $definition) {
32+
if ($definition instanceof ChildDefinition) {
33+
continue;
34+
}
35+
if ($definition !== $processedDefinition = $this->processDefinition($container, $id, $definition)) {
36+
$didProcess = true;
37+
$container->setDefinition($id, $processedDefinition);
38+
}
39+
}
40+
if ($didProcess) {
41+
$container->register('abstract.'.__CLASS__, '')->setAbstract(true);
42+
}
43+
}
44+
45+
private function processDefinition(ContainerBuilder $container, $id, Definition $definition)
46+
{
47+
if (!$instanceofConditionals = $definition->getInstanceofConditionals()) {
48+
return $definition;
49+
}
50+
if (!$class = $container->getParameterBag()->resolveValue($definition->getClass())) {
51+
return $definition;
52+
}
53+
54+
$definition->setInstanceofConditionals(array());
55+
$instanceofParent = null;
56+
$parent = 'abstract.'.__CLASS__;
57+
$shared = null;
58+
59+
foreach ($instanceofConditionals as $interface => $instanceofDef) {
60+
if ($interface !== $class && (!$container->getReflectionClass($interface) || !$container->getReflectionClass($class))) {
61+
continue;
62+
}
63+
if ($interface === $class || is_subclass_of($class, $interface)) {
64+
$instanceofParent = clone $instanceofDef;
65+
$instanceofParent->setAbstract(true)->setInheritTags(true)->setParent($parent);
66+
$parent = 'instanceof.'.$interface.'.'.$id;
67+
$container->setDefinition($parent, $instanceofParent);
68+
69+
if (isset($instanceofParent->getChanges()['shared'])) {
70+
$shared = $instanceofParent->isShared();
71+
}
72+
}
73+
}
74+
75+
if ($instanceofParent) {
76+
// cast Definition to ChildDefinition
77+
$definition = serialize($definition);
78+
$definition = substr_replace($definition, '53', 2, 2);
79+
$definition = substr_replace($definition, 'Child', 44, 0);
80+
$definition = unserialize($definition);
81+
$definition->setInheritTags(true)->setParent($parent);
82+
83+
if (null !== $shared && !isset($definition->getChanges()['shared'])) {
84+
$definition->setShared($shared);
85+
}
86+
}
87+
88+
return $definition;
89+
}
90+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\DependencyInjection\Compiler;
13+
14+
use Symfony\Component\DependencyInjection\ChildDefinition;
15+
use Symfony\Component\DependencyInjection\Definition;
16+
17+
/**
18+
* Applies tags inheritance to definitions.
19+
*
20+
* @author Nicolas Grekas <p@tchwork.com>
21+
*/
22+
class ResolveTagsInheritancePass extends AbstractRecursivePass
23+
{
24+
/**
25+
* {@inheritdoc}
26+
*/
27+
protected function processValue($value, $isRoot = false)
28+
{
29+
if (!$value instanceof ChildDefinition || !$value->getInheritTags()) {
30+
return parent::processValue($value, $isRoot);
31+
}
32+
$value->setInheritTags(false);
33+
34+
if (!$this->container->has($parent = $value->getParent())) {
35+
return parent::processValue($value, $isRoot);
36+
}
37+
38+
$parentDef = $this->container->findDefinition($parent);
39+
40+
if ($parentDef instanceof ChildDefinition) {
41+
$this->processValue($parentDef);
42+
}
43+
44+
foreach ($parentDef->getTags() as $k => $v) {
45+
foreach ($v as $v) {
46+
$value->addTag($k, $v);
47+
}
48+
}
49+
50+
return parent::processValue($value, $isRoot);
51+
}
52+
}

0 commit comments

Comments
 (0)
0