8000 bug #24828 [DI] Fix the "almost-circular refs" fix (nicolas-grekas) · symfony/symfony@0ed62cf · GitHub
[go: up one dir, main page]

Skip to content

Commit 0ed62cf

Browse files
bug #24828 [DI] Fix the "almost-circular refs" fix (nicolas-grekas)
This PR was merged into the 3.4 branch. Discussion ---------- [DI] Fix the "almost-circular refs" fix | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - Inlining adds to the complexity, now properly handled. Commits ------- db12a98 [DI] Fix the "almost-circular refs" fix
2 parents e81005e + db12a98 commit 0ed62cf

File tree

6 files changed

+148
-40
lines changed

6 files changed

+148
-40
lines changed

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

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,29 +1490,37 @@ private function hasReference($id, array $arguments, $deep = false, array &$visi
14901490
if ($this->hasReference($id, $argument, $deep, $visited)) {
14911491
return true;
14921492
}
1493+
1494+
continue;
14931495
} elseif ($argument instanceof Reference) {
14941496
$argumentId = (string) $argument;
14951497
if ($id === $argumentId) {
14961498
return true;
14971499
}
14981500

1499-
if ($deep && !isset($visited[$argumentId]) && 'service_container' !== $argumentId) {
1500-
$visited[$argumentId] = true;
1501+
if (!$deep || isset($visited[$argumentId]) || 'service_container' === $argumentId) {
1502+
continue;
1503+
}
15011504

1502-
$service = $this->container->getDefinition($argumentId);
1505+
$visited[$argumentId] = true;
15031506

1504-
// if the proxy manager is enabled, disable searching for references in lazy services,
1505-
// as these services will be instantiated lazily and don't have direct related references.
1506-
if ($service->isLazy() && !$this->getProxyDumper() instanceof NullDumper) {
1507-
continue;
1508-
}
1507+
$service = $this->container->getDefinition($argumentId);
1508+
} elseif ($argument instanceof Definition) {
1509+
$service = $argument;
1510+
} else {
1511+
continue;
1512+
}
15091513

1510-
$arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties());
1514+
// if the proxy manager is enabled, disable searching for references in lazy services,
1515+
// as these services will be instantiated lazily and don't have direct related references.
1516+
if ($service->isLazy() && !$this->getProxyDumper() instanceof NullDumper) {
1517+
continue;
1518+
}
15111519

1512-
if ($this->hasReference($id, $arguments, $deep, $visited)) {
1513-
return true;
1514-
}
1515-
}
1520+
$arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties());
1521+
1522+
if ($this->hasReference($id, $arguments, $deep, $visited)) {
1523+
return true;
15161524
}
15171525
}
15181526

src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1203,8 +1203,19 @@ public function testUninitializedReference()
12031203
$this->assertEquals(array('foo1' => new \stdClass(), 'foo3' => new \stdClass()), iterator_to_array($bar->iter));
12041204
}
12051205

1206-
public function testAlmostCircular()
1206+
public function testAlmostCircularPrivate()
12071207
{
1208+
$public = false;
1209+
$container = include __DIR__.'/Fixtures/containers/container_almost_circular.php';
1210+
1211+
$foo = $container->get('foo');
1212+
1213+
$this->assertSame($foo, $foo->bar->foobar->foo);
1214+
}
1215+
1216+
public function testAlmostCircularPublic()
1217+
{
1218+
$public = true;
12081219
$container = include __DIR__.'/Fixtures/containers/container_almost_circular.php';
12091220

12101221
$foo = $container->get('foo');

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

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -764,17 +764,35 @@ public function testUninitializedReference()
764764
$this->assertEquals(array('foo1' => new \stdClass(), 'foo3' => new \stdClass()), iterator_to_array($bar->iter));
765765
}
766766

767-
public function testAlmostCircular()
767+
public function testAlmostCircularPrivate()
768768
{
769+
$public = false;
769770
$container = include self::$fixturesPath.'/containers/container_almost_circular.php';
770771
$container->compile();
771772
$dumper = new PhpDumper($container);
772773

773-
$this->assertStringEqualsFile(self::$fixturesPath.'/php/container_almost_circular.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Almost_Circular')));
774+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/container_almost_circular_private.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Almost_Circular_Private')));
774775

775-
require self::$fixturesPath.'/php/container_almost_circular.php';
776+
require self::$fixturesPath.'/php/container_almost_circular_private.php';
776777

777-
$container = new \Symfony_DI_PhpDumper_Test_Almost_Circular();
778+
$container = new \Symfony_DI_PhpDumper_Test_Almost_Circular_Private();
779+
$foo = $container->get('foo');
780+
781+
$this->assertSame($foo, $foo->bar->foobar->foo);
782+
}
783+
784+
public function testAlmostCircularPublic()
785+
{
786+
$public = true;
787+
$container = include self::$fixturesPath.'/containers/container_almost_circular.php';
788+
$container->compile();
789+
$dumper = new PhpDumper($container);
790+
791+
$this->assertStringEqualsFile(self::$fixturesPath.'/php/container_almost_circular_public.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Almost_Circular_Public')));
792+
793+
require self::$fixturesPath.'/php/container_almost_circular_public.php';
794+
795+
$container = new \Symfony_DI_PhpDumper_Test_Almost_Circular_Public();
778796
$foo = $container->get('foo');
779797

780798
$this->assertSame($foo, $foo->bar->foobar->foo);

src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
$container->register('foo', FooCircular::class)->setPublic(true)
1111
->addArgument(new Reference('bar'));
1212

13-
$container->register('bar', BarCircular::class)
13+
$container->register('bar', BarCircular::class)->setPublic($public)
1414
->addMethodCall('addFoobar', array(new Reference('foobar')));
1515

16-
$container->register('foobar', FoobarCircular::class)
16+
$container->register('foobar', FoobarCircular::class)->setPublic($public)
1717
->addArgument(new Reference('foo'));
1818

1919
return $container;
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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 Symfony_DI_PhpDumper_Test_Almost_Circular_Private 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+
'foo' => 'getFooService',
27+
);
28+
29+
$this->aliases = array();
30+
}
31+
32+
public function getRemovedIds()
33+
{
34+
return array(
35+
'Psr\\Container\\ContainerInterface' => true,
36+
'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true,
37+
'bar' => true,
38+
'foobar' => true,
39+
);
40+
}
41+
42+
public function compile()
43+
{
44+
throw new LogicException('You cannot compile a dumped container that was already compiled.');
45+
}
46+
47+
public function isCompiled()
48+
{
49+
return true;
50+
}
51+
52+
public function isFrozen()
53+
{
54+
@trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED);
55+
56+
return true;
57+
}
58+
59+
/**
60+
* Gets the public 'foo' shared service.
61+
*
62+
* @return \FooCircular
63+
*/
64+
protected function getFooService()
65+
{
66+
$a = new \BarCircular();
67+
68+
$this->services['foo'] = $instance = new \FooCircular($a);
69+
70+
$a->addFoobar(new \FoobarCircular($instance));
71+
72+
73+
return $instance;
74+
}
75+
}

src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_almost_circular.php renamed to src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_almost_circular_public.php

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
*
1515
* @final since Symfony 3.3
1616
*/
17-
class Symfony_DI_PhpDumper_Test_Almost_Circular extends Container
17+
class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container
1818
{
1919
private $parameters;
2020
private $targetDirs = array();
@@ -27,10 +27,6 @@ public function __construct()
2727
'foo' => 'getFooService',
2828
'foobar' => 'getFoobarService',
2929
);
30-
$this->privates = array(
31-
'bar' => true,
32-
'foobar' => true,
33-
);
3430

3531
$this->aliases = array();
3632
}
@@ -61,37 +57,37 @@ public function isFrozen()
6157
}
6258

6359
/**
64-
* Gets the public 'foo' shared service.
60+
* Gets the public 'bar' shared service.
6561
*
66-
* @return \FooCircular
62+
* @return \BarCircular
6763
*/
68-
protected function getFooService()
64+
protected function getBarService()
6965
{
70-
$a = ${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->getBarService()) && false ?: '_'};
66+
$this->services['bar'] = $instance = new \BarCircular();
7167

72-
if (isset($this->services['foo'])) {
73-
return $this->services['foo'];
74-
}
68+
$instance->addFoobar(${($_ = isset($this->services['foobar']) ? $this->services['foobar'] : $this->getFoobarService()) && false ?: '_'});
7569

76-
return $this->services['foo'] = new \FooCircular($a);
70+
return $instance;
7771
}
7872

7973
/**
80-
* Gets the private 'bar' shared service.
74+
* Gets the public 'foo' shared service.
8175
*
82-
* @return \BarCircular
76+
* @return \FooCircular
8377
*/
84-
protected function getBarService()
78+
protected function getFooService()
8579
{
86-
$this->services['bar'] = $instance = new \BarCircular();
80+
$a = ${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->getBarService()) && false ?: '_'};
8781

88-
$instance->addFoobar(${($_ = isset($this->services['foobar']) ? $this->services['foobar'] : $this->getFoobarService()) && false ?: '_'});
82+
if (isset($this->services['foo'])) {
83+
return $this->services['foo'];
84+
}
8985

90-
return $instance;
86+
return $this->services['foo'] = new \FooCircular($a);
9187
}
9288

9389
/**
94-
* Gets the private 'foobar' shared service.
90+
* Gets the public 'foobar' shared service.
9591
*
9692
* @return \FoobarCircular
9793
*/

0 commit comments

Comments
 (0)
0