Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 595a978

Browse filesBrowse files
[DependencyInjection] PhpDumper.php: hasReference() should not search references in lazy service arguments.
1 parent 777cdfc commit 595a978
Copy full SHA for 595a978

File tree

4 files changed

+99
-6
lines changed
Filter options

4 files changed

+99
-6
lines changed

‎src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php
+11-6Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,19 @@ private function checkOutEdges(array $edges)
6060
$id = $node->getId();
6161

6262
if (empty($this->checkedNodes[$id])) {
63-
$searchKey = array_search($id, $this->currentPath);
64-
$this->currentPath[] = $id;
6563

66-
if (false !== $searchKey) {
67-
throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey));
68-
}
64+
// * don't check circular dependencies in lazy services.
65+
$isLazy = $node->getValue() && $node->getValue()->isLazy();
66+
if (!$isLazy) {
67+
$searchKey = array_search($id, $this->currentPath);
68+
$this->currentPath[] = $id;
69+
70+
if (false !== $searchKey) {
71+
throw new ServiceCircularReferenceException($id, array_slice($this->currentPath, $searchKey));
72+
}
6973

70-
$this->checkOutEdges($node->getOutEdges());
74+
$this->checkOutEdges($node->getOutEdges());
75+
}
7176

7277
$this->checkedNodes[$id] = true;
7378
array_pop($this->currentPath);

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+7Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,13 @@ private function hasReference($id, array $arguments, $deep = false, array &$visi
12931293
$visited[$argumentId] = true;
12941294

12951295
$service = $this->container->getDefinition($argumentId);
1296+
1297+
// if exists proxy dumper (proxy-manager) don't search references in lazy services.
1298+
// As these services will be instantiated lazily and don't have direct related references.
1299+
if ($service->isLazy() && !($this->getProxyDumper() instanceof NullDumper)) {
1300+
continue;
1301+
}
1302+
12961303
$arguments = array_merge($service->getMethodCalls(), $service->getArguments(), $service->getProperties());
12971304

12981305
if ($this->hasReference($id, $arguments, $deep, $visited)) {

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

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php
+51Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Component\DependencyInjection\Tests\Dumper;
1313

14+
use DummyProxyDumper;
1415
use Symfony\Component\DependencyInjection\ContainerBuilder;
1516
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
1617
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
@@ -19,6 +20,8 @@
1920
use Symfony\Component\DependencyInjection\Variable;
2021
use Symfony\Component\ExpressionLanguage\Expression;
2122

23+
require_once __DIR__.'/../Fixtures/includes/classes.php';
24+
2225
class PhpDumperTest extends \PHPUnit_Framework_TestCase
2326
{
2427
protected static $fixturesPath;
@@ -286,4 +289,52 @@ public function testInitializePropertiesBeforeMethodCalls()
286289
$container = new \Symfony_DI_PhpDumper_Test_Properties_Before_Method_Calls();
287290
$this->assertTrue($container->get('bar')->callPassed(), '->dump() initializes properties before method calls');
288291
}
292+
293+
public function testCircularReferenceAllowanceForLazyServices()
294+
{
295+
$container = new ContainerBuilder();
296+
$container->register('foo', 'stdClass')->addArgument(new Reference('bar'));
297+
$container->register('bar', 'stdClass')->setLazy(true)->addArgument(new Reference('foo'));
298+
$container->compile();
299+
300+
$dumper = new PhpDumper($container);
301+
$dumper->dump();
302+
}
303+
304+
public function testCircularReferenceAllowanceForInlinedDefinitionsForLazyServices()
305+
{
306+
/*
307+
* test graph:
308+
* [connection] -> [event_manager] --> [entity_manager](lazy)
309+
* |
310+
* --(call)- addEventListener ("@lazy_service")
311+
*
312+
* [lazy_service](lazy) -> [entity_manager](lazy)
313+
*
314+
*/
315+
316+
$container = new ContainerBuilder();
317+
318+
$eventManagerDefinition = new Definition('stdClass');
319+
320+
$connectionDefinition = $container->register('connection', 'stdClass');
321+
$connectionDefinition->addArgument($eventManagerDefinition);
322+
323+
$container->register('entity_manager', 'stdClass')
324+
->setLazy(true)
325+
->addArgument(new Reference('connection'));
326+
327+
$lazyServiceDefinition = $container->register('lazy_service', 'stdClass');
328+
$lazyServiceDefinition->setLazy(true);
329+
$lazyServiceDefinition->addArgument(new Reference('entity_manager'));
330+
331+
$eventManagerDefinition->addMethodCall('addEventListener', array(new Reference('lazy_service')));
332+
333+
$container->compile();
334+
335+
$dumper = new PhpDumper($container);
336+
337+
$dumper->setProxyDumper(new DummyProxyDumper());
338+
$dumper->dump();
339+
}
289340
}

‎src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php
+30Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
<?php
22

3+
use Symfony\Component\DependencyInjection\Definition;
4+
use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper;
5+
36
function sc_configure($instance)
47
{
58
$instance->configure();
@@ -76,3 +79,30 @@ public function callPassed()
7679
return $this->callPassed;
7780
}
7881
}
82+
83+
class DummyProxyDumper implements ProxyDumper
84+
{
85+
/**
86+
* {@inheritdoc}
87+
*/
88+
public function isProxyCandidate(Definition $definition)
89+
{
90+
return false;
91+
}
92+
93+
/**
94+
* {@inheritdoc}
95+
*/
96+
public function getProxyFactoryCode(Definition $definition, $id)
97+
{
98+
return '';
99+
}
100+
101+
/**
102+
* {@inheritdoc}
103+
*/
104+
public function getProxyCode(Definition $definition)
105+
{
106+
return '';
107+
}
108+
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.