diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php index 7e865b13ce19d..26856e69f2c54 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php @@ -112,7 +112,7 @@ protected function processValue($value, $isRoot = false) $targetId, $targetDefinition, $value, - $this->lazy || ($targetDefinition && $targetDefinition->isLazy()), + $this->lazy || ($this->hasProxyDumper && $targetDefinition && $targetDefinition->isLazy()), true ); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index eb89a2a40d2d2..ff7e04587d928 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -191,7 +191,7 @@ private function isInlineableDefinition($id, Definition $definition) foreach ($this->graph->getNode($id)->getInEdges() as $edge) { $srcId = $edge->getSourceNode()->getId(); $this->connectedIds[$srcId] = true; - if ($edge->isWeak()) { + if ($edge->isWeak() || (($v = $edge->getSourceNode()->getValue()) instanceof Definition && $v->isLazy() && $this->graph->getNode($id)->getOutEdges())) { return false; } $srcIds[$srcId] = true; diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 3649ef780cdc9..b624557f4f899 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -170,13 +170,17 @@ public function dump(array $options = array()) } } - (new AnalyzeServiceReferencesPass(false))->process($this->container); + (new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container); $this->circularReferences = array(); $this->singleUsePrivateIds = array(); $checkedNodes = array(); foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) { + if (!$node->getValue() instanceof Definition) { + continue; + } + $checkedNodes[$id] = true; $currentPath = array($id => $id); - $this->analyzeCircularReferences($node->getOutEdges(), $checkedNodes, $currentPath); + $this->analyzeCircularReferences($node->getOutEdges(), $checkedNodes, $currentPath, $id); if ($this->isSingleUsePrivateNode($node)) { $this->singleUsePrivateIds[$id] = $id; } @@ -333,13 +337,13 @@ private function getProxyDumper(): ProxyDumper return $this->proxyDumper; } - private function analyzeCircularReferences(array $edges, &$checkedNodes, &$currentPath) + private function analyzeCircularReferences(array $edges, &$checkedNodes, &$currentPath, $sourceId) { foreach ($edges as $edge) { $node = $edge->getDestNode(); $id = $node->getId(); - if ($node->getValue() && ($edge->isLazy() || $edge->isWeak())) { + if (!$node->getValue() instanceof Definition || $sourceId === $id || $edge->isLazy() || $edge->isWeak()) { // no-op } elseif (isset($currentPath[$id])) { $currentId = $id; @@ -353,7 +357,7 @@ private function analyzeCircularReferences(array $edges, &$checkedNodes, &$curre } elseif (!isset($checkedNodes[$id])) { $checkedNodes[$id] = true; $currentPath[$id] = $id; - $this->analyzeCircularReferences($node->getOutEdges(), $checkedNodes, $currentPath); + $this->analyzeCircularReferences($node->getOutEdges(), $checkedNodes, $currentPath, $id); unset($currentPath[$id]); } } @@ -695,8 +699,14 @@ private function addInlineVariables(string $id, Definition $definition, array $a private function addInlineReference(string $id, Definition $definition, string $targetId, bool $forConstructor): string { + list($callCount, $behavior) = $this->serviceCalls[$targetId]; + + while ($this->container->hasAlias($targetId)) { + $targetId = (string) $this->container->getAlias($targetId); + } + if ($id === $targetId) { - return $this->addInlineService($id, $definition, $definition, $forConstructor); + return $this->addInlineService($id, $definition, $definition); } if ('service_container' === $targetId || isset($this->referenceVariables[$targetId])) { @@ -705,9 +715,7 @@ private function addInlineReference(string $id, Definition $definition, string $ $hasSelfRef = isset($this->circularReferences[$id][$targetId]); $forConstructor = $forConstructor && !isset($this->definitionVariables[$definition]); - list($callCount, $behavior) = $this->serviceCalls[$targetId]; - - $code = $hasSelfRef && !$forConstructor ? $this->addInlineService($id, $definition, $definition, $forConstructor) : ''; + $code = $hasSelfRef && !$forConstructor ? $this->addInlineService($id, $definition, $definition) : ''; if (isset($this->referenceVariables[$targetId]) || (2 > $callCount && (!$hasSelfRef || !$forConstructor))) { return $code; 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 4aea8f6c57383..251f2f5e2ef06 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 @@ -151,11 +151,16 @@ protected function getBaz6Service() */ protected function getConnectionService() { - $a = new \stdClass(); + $a = ($this->services['dispatcher'] ?? $this->getDispatcherService()); + + if (isset($this->services['connection'])) { + return $this->services['connection']; + } + $b = new \stdClass(); - $this->services['connection'] = $instance = new \stdClass(($this->services['dispatcher'] ?? $this->getDispatcherService()), $a); + $this->services['connection'] = $instance = new \stdClass($a, $b); - $a->logger = ($this->services['logger'] ?? $this->getLoggerService()); + $b->logger = ($this->services['logger'] ?? $this->getLoggerService()); return $instance; } @@ -167,14 +172,19 @@ protected function getConnectionService() */ protected function getConnection2Service() { - $a = new \stdClass(); + $a = ($this->services['dispatcher2'] ?? $this->getDispatcher2Service()); - $this->services['connection2'] = $instance = new \stdClass(($this->services['dispatcher2'] ?? $this->getDispatcher2Service()), $a); + if (isset($this->services['connection2'])) { + return $this->services['connection2']; + } + $b = new \stdClass(); + + $this->services['connection2'] = $instance = new \stdClass($a, $b); - $b = new \stdClass($instance); - $b->handler2 = new \stdClass(($this->services['manager2'] ?? $this->getManager2Service())); + $c = new \stdClass($instance); + $c->handler2 = new \stdClass(($this->services['manager2'] ?? $this->getManager2Service())); - $a->logger2 = $b; + $b->logger2 = $c; return $instance; } @@ -202,7 +212,7 @@ protected function getDispatcher2Service($lazyLoad = true) { $this->services['dispatcher2'] = $instance = new \stdClass(); - $instance->subscriber2 = new \stdClass(($this->services['manager2'] ?? $this->getManager2Service())); + $instance->subscriber2 = $this->getSubscriber2Service(); return $instance; } @@ -414,7 +424,13 @@ protected function getRootService() */ protected function getSubscriberService() { - return $this->services['subscriber'] = new \stdClass(($this->services['manager'] ?? $this->getManagerService())); + $a = ($this->services['manager'] ?? $this->getManagerService()); + + if (isset($this->services['subscriber'])) { + return $this->services['subscriber']; + } + + return $this->services['subscriber'] = new \stdClass($a); } /** @@ -448,4 +464,20 @@ protected function getLevel5Service() return $instance; } + + /** + * Gets the private 'subscriber2' shared service. + * + * @return \stdClass + */ + protected function getSubscriber2Service() + { + $a = ($this->services['manager2'] ?? $this->getManager2Service()); + + if (isset($this->privates['subscriber2'])) { + return $this->privates['subscriber2']; + } + + return new \stdClass($a); + } }