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
-------
4e92d10b40
[DI] fix analyzing lazy refs involved in circular loops
This commit is contained in:
commit
98d7a9518d
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -97,7 +99,7 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
|
|||
$targetId,
|
||||
$targetDefinition,
|
||||
$value,
|
||||
$this->lazy || ($targetDefinition && $targetDefinition->isLazy()),
|
||||
$this->lazy || ($this->hasProxyDumper && $targetDefinition && $targetDefinition->isLazy()),
|
||||
ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()
|
||||
);
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
|
|||
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;
|
||||
|
@ -139,29 +140,19 @@ class PhpDumper extends Dumper
|
|||
$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) {
|
||||
|
@ -367,7 +358,7 @@ EOTXT;
|
|||
$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) {
|
||||
|
|
|
@ -538,7 +538,7 @@ class PhpDumperTest extends TestCase
|
|||
|
||||
$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);
|
||||
|
|
Reference in New Issue