Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 00e8b49

Browse files
Merge branch '4.1'
* 4.1: [DI] fix analyzing lazy refs involved in circular loops [DI] Fix autowire inner service
2 parents 13dc341 + 441322f commit 00e8b49

File tree

6 files changed

+50
-26
lines changed

6 files changed

+50
-26
lines changed

src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,18 @@ class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements Repe
3232
private $graph;
3333
private $currentDefinition;
3434
private $onlyConstructorArguments;
35+
private $hasProxyDumper;
3536
private $lazy;
3637
private $definitions;
3738
private $aliases;
3839

3940
/**
4041
* @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
4142
*/
42-
public function __construct(bool $onlyConstructorArguments = false)
43+
public function __construct(bool $onlyConstructorArguments = false, bool $hasProxyDumper = true)
4344
{
4445
$this->onlyConstructorArguments = $onlyConstructorArguments;
46+
$this->hasProxyDumper = $hasProxyDumper;
4547
$this->enableExpressionProcessing();
4648
}
4749

@@ -98,7 +100,7 @@ protected function processValue($value, $isRoot = false, bool $inExpression = fa
98100
$targetId,
99101
$targetDefinition,
100102
$value,
101-
$this->lazy || ($targetDefinition && $targetDefinition->isLazy()),
103+
$this->lazy || ($this->hasProxyDumper && $targetDefinition && $targetDefinition->isLazy()),
102104
ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()
103105
);
104106

src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,12 @@ private function doProcessValue($value, $isRoot = false)
144144
*/
145145
private function autowireCalls(\ReflectionClass $reflectionClass, bool $isRoot): array
146146
{
147+
$this->decoratedId = null;
148+
$this->decoratedClass = null;
149+
$this->getPreviousValue = null;
150+
147151
if ($isRoot && ($definition = $this->container->getDefinition($this->currentId)) && $this->container->has($this->decoratedId = $definition->innerServiceId)) {
148152
$this->decoratedClass = $this->container->findDefinition($this->decoratedId)->getClass();
149-
} else {
150-
$this->decoratedId = null;
151-
$this->decoratedClass = null;
152153
}
153154

154155
foreach ($this->methodCalls as $i => $call) {

src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php

Lines changed: 11 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use Symfony\Component\DependencyInjection\Argument\ServiceLocator;
1818
use Symfony\Component\DependencyInjection\Argument\ServiceLocatorArgument;
1919
use Symfony\Component\DependencyInjection\Compiler\AnalyzeServiceReferencesPass;
20+
use Symfony\Component\DependencyInjection\Compiler\CheckCircularReferencesPass;
2021
use Symfony\Component\DependencyInjection\Compiler\ServiceReferenceGraphNode;
2122
use Symfony\Component\DependencyInjection\Container;
2223
use Symfony\Component\DependencyInjection\ContainerBuilder;
@@ -152,29 +153,19 @@ public function dump(array $options = array())
152153
$this->initializeMethodNamesMap('Container' === $baseClass ? Container::class : $baseClass);
153154

154155
if ($this->getProxyDumper() instanceof NullDumper) {
155-
(new AnalyzeServiceReferencesPass(true))->process($this->container);
156-
$this->circularReferences = array();
157-
$checkedNodes = array();
158-
foreach ($this->container->getCompiler()->getServiceReferenceGraph()->getNodes() as $id => $node) {
159-
$currentPath = array($id => $id);
160-
$this->analyzeCircularReferences($node->getOutEdges(), $checkedNodes, $currentPath);
161-
}
162-
foreach ($this->circularReferences as $parent => $ids) {
163-
$path = array($parent);
164-
while (!isset($ids[$parent])) {
165-
foreach ($ids as $id) {
166-
$path[] = $id;
167-
$ids = $this->circularReferences[$id];
168-
break;
169-
}
170-
}
171-
$path[] = $parent.'". Try running "composer require symfony/proxy-manager-bridge';
156+
(new AnalyzeServiceReferencesPass(true, false))->process($this->container);
157+
try {
158+
(new CheckCircularReferencesPass())->process($this->container);
159+
} catch (ServiceCircularReferenceException $e) {
160+
$path = $e->getPath();
161+
end($path);
162+
$path[key($path)] .= '". Try running "composer require symfony/proxy-manager-bridge';
172163

173-
throw new ServiceCircularReferenceException($parent, $path);
164+
throw new ServiceCircularReferenceException($e->getServiceId(), $path);
174165
}
175166
}
176167

177-
(new AnalyzeServiceReferencesPass())->process($this->container);
168+
(new AnalyzeServiceReferencesPass(false, !$this->getProxyDumper() instanceof NullDumper))->process($this->container);
178169
$this->circularReferences = array();
179170
$this->singleUsePrivateIds = array();
180171
$checkedNodes = array();
@@ -386,7 +377,7 @@ private function analyzeCircularReferences(array $edges, &$checkedNodes, &$curre
386377
$node = $edge->getDestNode();
387378
$id = $node->getId();
388379

389-
if ($node->getValue() && (($edge->isLazy() && !$this->getProxyDumper() instanceof NullDumper) || $edge->isWeak())) {
380+
if ($node->getValue() && ($edge->isLazy() || $edge->isWeak())) {
390381
// no-op
391382
} elseif (isset($currentPath[$id])) {
392383
foreach (array_reverse($currentPath) as $parentId) {

src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -834,6 +834,29 @@ public function testAutowireDecorator()
834834
$this->assertSame(Decorator::class.'.inner', (string) $definition->getArgument(1));
835835
}
836836

837+
public function testAutowireDecoratorChain()
838+
{
839+
$container = new ContainerBuilder();
840+
$container->register(LoggerInterface::class, NullLogger::class);
841+
$container->register(Decorated::class, Decorated::class);
842+
$container
843+
->register(Decorator::class, Decorator::class)
844+
->setDecoratedService(Decorated::class)
845+
->setAutowired(true)
846+
;
847+
$container
848+
->register(DecoratedDecorator::class, DecoratedDecorator::class)
849+
->setDecoratedService(Decorated::class)
850+
->setAutowired(true)
851+
;
852+
853+
(new DecoratorServicePass())->process($container);
854+
(new AutowirePass())->process($container);
855+
856+
$definition = $container->getDefinition(DecoratedDecorator::class);
857+
$this->assertSame(DecoratedDecorator::class.'.inner', (string) $definition->getArgument(0));
858+
}
859+
837860
public function testAutowireDecoratorRenamedId()
838861
{
839862
$container = new ContainerBuilder();

src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -585,7 +585,7 @@ public function testCircularReferenceAllowanceForLazyServices()
585585

586586
$dumper = new PhpDumper($container);
587587

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

src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,13 @@ public function __construct(LoggerInterface $logger, DecoratorInterface $decorat
373373
}
374374
}
375375

376+
class DecoratedDecorator implements DecoratorInterface
377+
{
378+
public function __construct(DecoratorInterface $decorator)
379+
{
380+
}
381+
}
382+
376383
class NonAutowirableDecorator implements DecoratorInterface
377384
{
378385
public function __construct(LoggerInterface $logger, DecoratorInterface $decorated1, DecoratorInterface $decorated2)

0 commit comments

Comments
 (0)