Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
minor #28160 [DI] fix analyzing lazy refs involved in circular loops …
…(nicolas-grekas)

This PR was merged into the 3.4 branch.

Discussion
----------

[DI] fix analyzing lazy refs involved in circular loops

| 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        | -

Follow up of #28060 to fix "deps=high" jobs.

Commits
-------

4e92d10 [DI] fix analyzing lazy refs involved in circular loops
  • Loading branch information
nicolas-grekas committed Aug 8, 2018
2 parents ba31bab + 4e92d10 commit 98d7a95
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 23 deletions.
Expand Up @@ -34,15 +34,17 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
private $graph;
private $currentDefinition;
private $onlyConstructorArguments;
private $hasProxyDumper;
private $lazy;
private $expressionLanguage;

/**
* @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
*/
public function __construct($onlyConstructorArguments = false)
public function __construct($onlyConstructorArguments = false, $hasProxyDumper = true)
{
$this->onlyConstructorArguments = (bool) $onlyConstructorArguments;
$this->hasProxyDumper = (bool) $hasProxyDumper;
}

/**
Expand Down Expand Up @@ -97,7 +99,7 @@ protected function processValue($value, $isRoot = false)
$targetId,
$targetDefinition,
$value,
$this->lazy || ($targetDefinition && $targetDefinition->isLazy()),
$this->lazy || ($this->hasProxyDumper && $targetDefinition && $targetDefinition->isLazy()),
ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()
);

Expand Down
31 changes: 11 additions & 20 deletions src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
Expand Up @@ -15,6 +15,7 @@
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass;
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\ContainerInterface;
Expand Down Expand Up @@ -139,29 +140,19 @@ public function dump(array $options = array())
$this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass);

if ($this->getProxyDumper() instanceof NullDumper) {
(new AnalyzeServiceReferencesPass(true))->process($this->container);
$this->circularReferences = array();
$checkedNodes = array();
foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) {
$currentPath = array($id => $id);
$this->analyzeCircularReferences($node->getOutEdges(), $checkedNodes, $currentPath);
}
foreach ($this->circularReferences as $parent => $ids) {
$path = array($parent);
while (!isset($ids[$parent])) {
foreach ($ids as $id) {
$path[] = $id;
$ids = $this->circularReferences[$id];
break;
}
}
$path[] = $parent.'". Try running "composer require symfony/proxy-manager-bridge';
(new AnalyzeServiceReferencesPass(true, false))->process($this->container);
try {
(new CheckCircularReferencesPass())->process($this->container);
} catch (ServiceCircularReferenceException $e) {
$path = $e->getPath();
end($path);
$path[key($path)] .= '". Try running "composer require symfony/proxy-manager-bridge';

throw new ServiceCircularReferenceException($parent, $path);
throw new ServiceCircularReferenceException($e->getServiceId(), $path);
}
}

(new AnalyzeServiceReferencesPass())->process($this->container);
(new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container);
$this->circularReferences = array();
$checkedNodes = array();
foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) {
Expand Down Expand Up @@ -367,7 +358,7 @@ private function analyzeCircularReferences(array $edges, &$checkedNodes, &$curre
$node = $edge->getDestNode();
$id = $node->getId();

if ($node->getValue() && (($edge->isLazy() && !$this->getProxyDumper() instanceof NullDumper) || $edge->isWeak())) {
if ($node->getValue() && ($edge->isLazy() || $edge->isWeak())) {
// no-op
} elseif (isset($currentPath[$id])) {
foreach (array_reverse($currentPath) as $parentId) {
Expand Down
Expand Up @@ -538,7 +538,7 @@ public function testCircularReferenceAllowanceForLazyServices()

$dumper = new PhpDumper($container);

$message = 'Circular reference detected for service "bar", path: "bar -> foo -> bar". Try running "composer require symfony/proxy-manager-bridge".';
$message = 'Circular reference detected for service "foo", path: "foo -> bar -> foo". Try running "composer require symfony/proxy-manager-bridge".';
if (method_exists($this, 'expectException')) {
$this->expectException(ServiceCircularReferenceException::class);
$this->expectExceptionMessage($message);
Expand Down

0 comments on commit 98d7a95

Please sign in to comment.