diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 7f3a1984f6..62d3e2bbd3 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1490,29 +1490,37 @@ EOF; if ($this->hasReference($id, $argument, $deep, $visited)) { return true; } + + continue; } elseif ($argument instanceof Reference) { $argumentId = (string) $argument; if ($id === $argumentId) { return true; } - if ($deep && !isset($visited[$argumentId]) && 'service_container' !== $argumentId) { - $visited[$argumentId] = true; - - $service = $this->container->getDefinition($argumentId); - - // if the proxy manager is enabled, disable searching for references in lazy services, - // as these services will be instantiated lazily and don't have direct related references. - if ($service->isLazy() && !$this->getProxyDumper() instanceof NullDumper) { - continue; - } - - $arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties()); - - if ($this->hasReference($id, $arguments, $deep, $visited)) { - return true; - } + if (!$deep || isset($visited[$argumentId]) || 'service_container' === $argumentId) { + continue; } + + $visited[$argumentId] = true; + + $service = $this->container->getDefinition($argumentId); + } elseif ($argument instanceof Definition) { + $service = $argument; + } else { + continue; + } + + // if the proxy manager is enabled, disable searching for references in lazy services, + // as these services will be instantiated lazily and don't have direct related references. + if ($service->isLazy() && !$this->getProxyDumper() instanceof NullDumper) { + continue; + } + + $arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties()); + + if ($this->hasReference($id, $arguments, $deep, $visited)) { + return true; } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index dd6e19c5d8..ac73138a9d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1203,8 +1203,19 @@ class ContainerBuilderTest extends TestCase $this->assertEquals(array('foo1' => new \stdClass(), 'foo3' => new \stdClass()), iterator_to_array($bar->iter)); } - public function testAlmostCircular() + public function testAlmostCircularPrivate() { + $public = false; + $container = include __DIR__.'/Fixtures/containers/container_almost_circular.php'; + + $foo = $container->get('foo'); + + $this->assertSame($foo, $foo->bar->foobar->foo); + } + + public function testAlmostCircularPublic() + { + $public = true; $container = include __DIR__.'/Fixtures/containers/container_almost_circular.php'; $foo = $container->get('foo'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 9268d5cf30..3c330620c8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -764,17 +764,35 @@ class PhpDumperTest extends TestCase $this->assertEquals(array('foo1' => new \stdClass(), 'foo3' => new \stdClass()), iterator_to_array($bar->iter)); } - public function testAlmostCircular() + public function testAlmostCircularPrivate() { + $public = false; $container = include self::$fixturesPath.'/containers/container_almost_circular.php'; $container->compile(); $dumper = new PhpDumper($container); - $this->assertStringEqualsFile(self::$fixturesPath.'/php/container_almost_circular.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Almost_Circular'))); + $this->assertStringEqualsFile(self::$fixturesPath.'/php/container_almost_circular_private.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Almost_Circular_Private'))); - require self::$fixturesPath.'/php/container_almost_circular.php'; + require self::$fixturesPath.'/php/container_almost_circular_private.php'; - $container = new \Symfony_DI_PhpDumper_Test_Almost_Circular(); + $container = new \Symfony_DI_PhpDumper_Test_Almost_Circular_Private(); + $foo = $container->get('foo'); + + $this->assertSame($foo, $foo->bar->foobar->foo); + } + + public function testAlmostCircularPublic() + { + $public = true; + $container = include self::$fixturesPath.'/containers/container_almost_circular.php'; + $container->compile(); + $dumper = new PhpDumper($container); + + $this->assertStringEqualsFile(self::$fixturesPath.'/php/container_almost_circular_public.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Almost_Circular_Public'))); + + require self::$fixturesPath.'/php/container_almost_circular_public.php'; + + $container = new \Symfony_DI_PhpDumper_Test_Almost_Circular_Public(); $foo = $container->get('foo'); $this->assertSame($foo, $foo->bar->foobar->foo); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php index f4219187a5..eaef674a3e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_almost_circular.php @@ -10,10 +10,10 @@ $container = new ContainerBuilder(); $container->register('foo', FooCircular::class)->setPublic(true) ->addArgument(new Reference('bar')); -$container->register('bar', BarCircular::class) +$container->register('bar', BarCircular::class)->setPublic($public) ->addMethodCall('addFoobar', array(new Reference('foobar'))); -$container->register('foobar', FoobarCircular::class) +$container->register('foobar', FoobarCircular::class)->setPublic($public) ->addArgument(new Reference('foo')); return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_almost_circular_private.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_almost_circular_private.php new file mode 100644 index 0000000000..055f409a53 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_almost_circular_private.php @@ -0,0 +1,75 @@ +services = array(); + $this->methodMap = array( + 'foo' => 'getFooService', + ); + + $this->aliases = array(); + } + + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'bar' => true, + 'foobar' => true, + ); + } + + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + public function isCompiled() + { + return true; + } + + public function isFrozen() + { + @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); + + return true; + } + + /** + * Gets the public 'foo' shared service. + * + * @return \FooCircular + */ + protected function getFooService() + { + $a = new \BarCircular(); + + $this->services['foo'] = $instance = new \FooCircular($a); + + $a->addFoobar(new \FoobarCircular($instance)); + + + return $instance; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_almost_circular.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_almost_circular_public.php similarity index 91% rename from src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_almost_circular.php rename to src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_almost_circular_public.php index b2913295f9..5c4057d7fa 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_almost_circular.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/container_almost_circular_public.php @@ -14,7 +14,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; * * @final since Symfony 3.3 */ -class Symfony_DI_PhpDumper_Test_Almost_Circular extends Container +class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container { private $parameters; private $targetDirs = array(); @@ -27,10 +27,6 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular extends Container 'foo' => 'getFooService', 'foobar' => 'getFoobarService', ); - $this->privates = array( - 'bar' => true, - 'foobar' => true, - ); $this->aliases = array(); } @@ -60,6 +56,20 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular extends Container return true; } + /** + * Gets the public 'bar' shared service. + * + * @return \BarCircular + */ + protected function getBarService() + { + $this->services['bar'] = $instance = new \BarCircular(); + + $instance->addFoobar(${($_ = isset($this->services['foobar']) ? $this->services['foobar'] : $this->getFoobarService()) && false ?: '_'}); + + return $instance; + } + /** * Gets the public 'foo' shared service. * @@ -77,21 +87,7 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular extends Container } /** - * Gets the private 'bar' shared service. - * - * @return \BarCircular - */ - protected function getBarService() - { - $this->services['bar'] = $instance = new \BarCircular(); - - $instance->addFoobar(${($_ = isset($this->services['foobar']) ? $this->services['foobar'] : $this->getFoobarService()) && false ?: '_'}); - - return $instance; - } - - /** - * Gets the private 'foobar' shared service. + * Gets the public 'foobar' shared service. * * @return \FoobarCircular */