8000 [DI] Fix dumping some complex service graphs · symfony/symfony@b7d16f6 · GitHub
[go: up one dir, main page]

Skip to content

Commit b7d16f6

Browse files
[DI] Fix dumping some complex service graphs
1 parent edbd869 commit b7d16f6

File tree

5 files changed

+151
-5
lines changed

5 files changed

+151
-5
lines changed

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,7 @@ private function addServiceInlinedDefinitions($id, Definition $definition, \SplO
516516

517517
$code .= $this->addNewInstance($def, '$'.$name, ' = ', $id);
518518

519-
if (!$this->hasReference($id, array($def->getProperties(), $def->getMethodCalls(), $def->getConfigurator()), true)) {
519+
if (!$this->hasReference($id, array($def->getProperties(), $def->getMethodCalls(), $def->getConfigurator()), true, $inlinedDefinitions)) {
520520
$code .= $this->addServiceProperties($def, $name);
521521
$code .= $this->addServiceMethodCalls($def, $name);
522522
$code .= $this->addServiceConfigurator($def, $name);
@@ -669,7 +669,7 @@ private function addServiceInlinedDefinitionsSetup($id, Definition $definition,
669669
{
670670
$code = '';
671671
foreach ($inlinedDefinitions as $def) {
672-
if ($definition === $def || !$this->hasReference($id, array($def->getProperties(), $def->getMethodCalls(), $def->getConfigurator()), true)) {
672+
if ($definition === $def || !$this->hasReference($id, array($def->getProperties(), $def->getMethodCalls(), $def->getConfigurator()), true, $inlinedDefinitions)) {
673673
continue;
674674
}
675675

@@ -812,6 +812,7 @@ protected function {$methodName}($lazyInitialization)
812812

813813
$inlinedDefinitions = $this->getDefinitionsFromArguments(array($definition));
814814
$constructorDefinitions = $this->getDefinitionsFromArguments(array($definition->getArguments(), $definition->getFactory()));
815+
unset($constructorDefinitions[$definition]); // ensures $definition will be last
815816
$otherDefinitions = new \SplObjectStorage();
816817
$serviceCalls = array();
817818

@@ -1635,15 +1636,15 @@ private function getDefinitionsFromArguments(array $arguments, $isConstructorArg
16351636
*
16361637
* @return bool
16371638
*/
1638-
private function hasReference($id, array $arguments, $deep = false, array &$visited = array())
1639+
private function hasReference($id, array $arguments, $deep = false, \SplObjectStorage $inlinedDefinitions = null, array &$visited = array())
16391640
{
16401641
if (!isset($this->circularReferences[$id])) {
16411642
return false;
16421643
}
16431644

16441645
foreach ($arguments as $argument) {
16451646
if (\is_array($argument)) {
1646-
if ($this->hasReference($id, $argument, $deep, $visited)) {
1647+
if ($this->hasReference($id, $argument, $deep, $inlinedDefinitions, $visited)) {
16471648
return true;
16481649
}
16491650

@@ -1662,6 +1663,9 @@ private function hasReference($id, array $arguments, $deep = false, array &$visi
16621663

16631664
$service = $this->container->getDefinition($argumentId);
16641665
} elseif ($argument instanceof Definition) {
1666+
if (isset($inlinedDefinitions[$argument])) {
1667+
return true;
1668+
}
16651669
$service = $argument;
16661670
} else {
16671671
continue;
@@ -1673,7 +1677,7 @@ private function hasReference($id, array $arguments, $deep = false, array &$visi
16731677
continue;
16741678
}
16751679

1676-
if ($this->hasReference($id, array($service->getArguments(), $service->getFactory(), $service->getProperties(), $service->getMethodCalls(), $service->getConfigurator()), $deep, $visited)) {
1680+
if ($this->hasReference($id, array($service->getArguments(), $service->getFactory(), $service->getProperties(), $service->getMethodCalls(), $service->getConfigurator()), $deep, $inlinedDefinitions, $visited)) {
28BE
16771681
return true;
16781682
}
16791683
}

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -838,6 +838,21 @@ public function provideAlmostCircular()
838838
yield array('private');
839839
}
840840

841+
public function testDeepServiceGraph()
842+
{
843+
$container = new ContainerBuilder();
844+
845+
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
846+
$loader->load('services_deep_graph.yml');
847+
848+
$container->compile();
849+
850+
$dumper = new PhpDumper($container);
851+
$dumper->dump();
852+
853+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/services_deep_graph.php', $dumper->dump());
854+
}
855+
841856
public function testHotPathOptimizations()
842857
{
843858
$container = include self::$fixturesPath.'/containers/container_inline_requires.php';
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
<?php
2+
3+
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
4+
use Symfony\Component\DependencyInjection\ContainerInterface;
5+
use Symfony\Component\DependencyInjection\Container;
6+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
7+
use Symfony\Component\DependencyInjection\Exception\LogicException;
8+
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
9+
use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
10+
11+
/**
12+
* This class has been auto-generated
13+
* by the Symfony Dependency Injection Component.
14+
*
15+
* @final since Symfony 3.3
16+
*/
17+
class ProjectServiceContainer extends Container
18+
{
19+
private $parameters;
20+
private $targetDirs = array();
21+
22+
public function __construct()
23+
{
24+
$this->services = array();
25+
$this->methodMap = array(
26+
'bar' => 'getBarService',
27+
'foo' => 'getFooService',
28+
);
29+
30+
$this->aliases = array();
31+
}
32+
33+
public function getRemovedIds()
34+
{
35+
return array(
36+
'1_c2d83go6s' => true,
37+
'2_c3d83go6s' => true,
38+
'3_c4d83go6s' => true,
39+
'4_c6d83go6s' => true,
40+
'Psr\\Container\\ContainerInterface' => true,
41+
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
42+
);
43+
}
44+
45+
public function compile()
46+
{
47+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
48+
}
49+
50+
public function isCompiled()
51+
{
52+
return true;
53+
}
54+
55+
public function isFrozen()
56+
{
57+
@trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
58+
59+
return true;
60+
}
61+
62+
/**
63+
* Gets the public 'bar' shared service.
64+
*
65+
* @return \c5
66+
*/
67+
protected function getBarService()
68+
{
69+
$this->services['bar'] = $instance = new \c5();
70+
71+
$instance->p5 = new \c6(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->getFooService()) && false ?: '_'});
72+
73+
return $instance;
74+
}
75+
76+
/**
77+
* Gets the public 'foo' shared service.
78+
*
79+
* @return \c1
80+
*/
81+
protected function getFooService()
82+
{
83+
$a = ${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->getBarService()) && false ?: '_'};
84+
85+
if (isset($this->services['foo'])) {
86+
return $this->services['foo'];
87+
}
88+
89+
$b = new \c2();
90+
91+
$this->services['foo'] = $instance = new \c1($a, $b);
92+
93+
$c = new \c3();
94+
95+
$c->p3 = new \c4();
96+
$b->p2 = $c;
97 9E7A +
98+
return $instance;
99+
}
100+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
2+
services:
3+
foo:
4+
class: c1
5+
public: true
6+
arguments:
7+
- '@bar'
8+
- !service
9+
class: c2
10+
properties:
11+
p2: !service
12+
class: c3
13+
properties:
14+
p3: !service
15+
class: c4
16+
17+
bar:
18+
class: c5
19+
public: true
20+
properties:
21+
p5: !service
22+
class: c6
23+
arguments: ['@foo']
24+

src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
use Symfony\Component\Config\Resource\GlobResource;
1919
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
2020
use Symfony\Component\DependencyInjection\ContainerBuilder;
21+
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
22+
use Symfony\Component\DependencyInjection\Dumper\YamlDumper;
23+
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
2124
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
2225
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
2326
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

0 commit comments

Comments
 (0)
0