diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 2f9d7d0a00..def656ee13 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1220,7 +1220,7 @@ class ContainerBuilder extends Container implements TaggedContainerInterface return $this->resolveServices($reference); }; } elseif ($value instanceof IteratorArgument) { - $value = new RewindableGenerator(function () use ($value) { + $value = new RewindableGenerator(function () use ($value, &$inlineServices) { foreach ($value->getValues() as $k => $v) { foreach (self::getServiceConditionals($v) as $s) { if (!$this->has($s)) { @@ -1228,12 +1228,12 @@ class ContainerBuilder extends Container implements TaggedContainerInterface } } foreach (self::getInitializedConditionals($v) as $s) { - if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { + if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) { continue 2; } } - yield $k => $this->resolveServices($v); + yield $k => $this->doResolveServices($v, $inlineServices); } }, function () use ($value): int { $count = 0; diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index fcc0ad33e1..584eff5fd1 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -451,7 +451,7 @@ EOF; foreach ($edges as $edge) { $node = $edge->getDestNode(); $id = $node->getId(); - if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isLazy() || $edge->isWeak()) { + if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isWeak()) { continue; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index ba664f767b..b78fbd72ea 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1372,6 +1372,10 @@ class ContainerBuilderTest extends TestCase public function testAlmostCircular($visibility) { $container = include __DIR__.'/Fixtures/containers/container_almost_circular.php'; + $container->compile(); + + $logger = $container->get('monolog.logger'); + $this->assertEquals(new \stdClass(), $logger->handler); $foo = $container->get('foo'); $this->assertSame($foo, $foo->bar->foobar->foo); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 5875253d86..663e3fe66d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -1054,6 +1054,9 @@ class PhpDumperTest extends TestCase $container = new $container(); + $logger = $container->get('monolog.logger'); + $this->assertEquals(new \stdClass(), $logger->handler); + $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 a1f885399b..96c714493e 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 @@ -1,5 +1,6 @@ register('monolog.logger', 'stdClass')->setPublic(true) + ->setProperty('handler', new Reference('mailer.transport')); + +$container->register('mailer.transport', 'stdClass')->setPublic($public) + ->setFactory([new Reference('mailer.transport_factory'), 'create']); + +$container->register('mailer.transport_factory', FactoryCircular::class)->setPublic($public) + ->addArgument(new TaggedIteratorArgument('mailer.transport')); + +$container->register('mailer.transport_factory.amazon', 'stdClass')->setPublic($public) + ->addArgument(new Reference('monolog.logger_2')) + ->addTag('mailer.transport'); + +$container->register('monolog.logger_2', 'stdClass')->setPublic($public) + ->setProperty('handler', new Reference('mailer.transport')); + // same visibility for deps $container->register('foo', FooCircular::class)->setPublic(true) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php index f3a490691a..46efa450ac 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php @@ -111,6 +111,23 @@ class LazyContext } } +class FactoryCircular +{ + public $services; + + public function __construct($services) + { + $this->services = $services; + } + + public function create() + { + foreach ($this->services as $service) { + return $service; + } + } +} + class FoobarCircular { public function __construct(FooCircular $foo) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php index 7df41fb810..069878fff8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_private.php @@ -39,6 +39,7 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Private extends Container 'manager' => 'getManagerService', 'manager2' => 'getManager2Service', 'manager3' => 'getManager3Service', + 'monolog.logger' => 'getMonolog_LoggerService', 'root' => 'getRootService', 'subscriber' => 'getSubscriberService', ]; @@ -80,7 +81,11 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Private extends Container 'level5' => true, 'level6' => true, 'logger2' => true, + 'mailer.transport' => true, + 'mailer.transport_factory' => true, + 'mailer.transport_factory.amazon' => true, 'manager4' => true, + 'monolog.logger_2' => true, 'multiuse1' => true, 'subscriber2' => true, ]; @@ -355,6 +360,20 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Private extends Container return $this->services['manager3'] = new \stdClass($b); } + /** + * Gets the public 'monolog.logger' shared service. + * + * @return \stdClass + */ + protected function getMonolog_LoggerService() + { + $this->services['monolog.logger'] = $instance = new \stdClass(); + + $instance->handler = ($this->privates['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + /** * Gets the public 'root' shared service. * @@ -419,6 +438,34 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Private extends Container return $instance; } + /** + * Gets the private 'mailer.transport' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportService() + { + return $this->privates['mailer.transport'] = (new \FactoryCircular(new RewindableGenerator(function () { + yield 0 => ($this->privates['mailer.transport_factory.amazon'] ?? $this->getMailer_TransportFactory_AmazonService()); + }, 1)))->create(); + } + + /** + * Gets the private 'mailer.transport_factory.amazon' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportFactory_AmazonService() + { + $a = new \stdClass(); + + $this->privates['mailer.transport_factory.amazon'] = $instance = new \stdClass($a); + + $a->handler = ($this->privates['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + /** * Gets the private 'manager4' shared service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php index dda3f7b497..e42560198a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_almost_circular_public.php @@ -45,9 +45,14 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container 'listener3' => 'getListener3Service', 'listener4' => 'getListener4Service', 'logger' => 'getLoggerService', + 'mailer.transport' => 'getMailer_TransportService', + 'mailer.transport_factory' => 'getMailer_TransportFactoryService', + 'mailer.transport_factory.amazon' => 'getMailer_TransportFactory_AmazonService', 'manager' => 'getManagerService', 'manager2' => 'getManager2Service', 'manager3' => 'getManager3Service', + 'monolog.logger' => 'getMonolog_LoggerService', + 'monolog.logger_2' => 'getMonolog_Logger2Service', 'root' => 'getRootService', 'subscriber' => 'getSubscriberService', ]; @@ -433,6 +438,50 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container return $instance; } + /** + * Gets the public 'mailer.transport' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportService() + { + $a = ($this->services['mailer.transport_factory'] ?? $this->getMailer_TransportFactoryService()); + + if (isset($this->services['mailer.transport'])) { + return $this->services['mailer.transport']; + } + + return $this->services['mailer.transport'] = $a->create(); + } + + /** + * Gets the public 'mailer.transport_factory' shared service. + * + * @return \FactoryCircular + */ + protected function getMailer_TransportFactoryService() + { + return $this->services['mailer.transport_factory'] = new \FactoryCircular(new RewindableGenerator(function () { + yield 0 => ($this->services['mailer.transport_factory.amazon'] ?? $this->getMailer_TransportFactory_AmazonService()); + }, 1)); + } + + /** + * Gets the public 'mailer.transport_factory.amazon' shared service. + * + * @return \stdClass + */ + protected function getMailer_TransportFactory_AmazonService() + { + $a = ($this->services['monolog.logger_2'] ?? $this->getMonolog_Logger2Service()); + + if (isset($this->services['mailer.transport_factory.amazon'])) { + return $this->services['mailer.transport_factory.amazon']; + } + + return $this->services['mailer.transport_factory.amazon'] = new \stdClass($a); + } + /** * Gets the public 'manager' shared service. * @@ -481,6 +530,34 @@ class Symfony_DI_PhpDumper_Test_Almost_Circular_Public extends Container return $this->services['manager3'] = new \stdClass($a); } + /** + * Gets the public 'monolog.logger' shared service. + * + * @return \stdClass + */ + protected function getMonolog_LoggerService() + { + $this->services['monolog.logger'] = $instance = new \stdClass(); + + $instance->handler = ($this->services['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + + /** + * Gets the public 'monolog.logger_2' shared service. + * + * @return \stdClass + */ + protected function getMonolog_Logger2Service() + { + $this->services['monolog.logger_2'] = $instance = new \stdClass(); + + $instance->handler = ($this->services['mailer.transport'] ?? $this->getMailer_TransportService()); + + return $instance; + } + /** * Gets the public 'root' shared service. *