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 d90a3b5

Browse filesBrowse files
bug #25180 [DI] Fix circular reference when using setters (nicolas-grekas)
This PR was merged into the 3.4 branch. Discussion ---------- [DI] Fix circular reference when using setters | 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 | - I did not manage to make a reproducing test case, yet @deguif provided me an app that I could play with to debug and fix. Commits ------- de5eecc [DI] Fix circular reference when using setters
2 parents ad3ddeb + de5eecc commit d90a3b5
Copy full SHA for d90a3b5

11 files changed

+404
-284
lines changed

‎src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Copy file name to clipboardExpand all lines: src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+31-31Lines changed: 31 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -570,10 +570,13 @@ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INV
570570
return $this->doGet($id, $invalidBehavior);
571571
}
572572

573-
private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE)
573+
private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, array &$inlineServices = array())
574574
{
575575
$id = $this->normalizeId($id);
576576

577+
if (isset($inlineServices[$id])) {
578+
return $inlineServices[$id];
579+
}
577580
if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) {
578581
return parent::get($id, $invalidBehavior);
579582
}
@@ -582,7 +585,7 @@ private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_
582585
}
583586

584587
if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) {
585-
return $this->doGet((string) $this->aliasDefinitions[$id], $invalidBehavior);
588+
return $this->doGet((string) $this->aliasDefinitions[$id], $invalidBehavior, $inlineServices);
586589
}
587590

588591
try {
@@ -599,7 +602,7 @@ private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_
599602
$this->{$loading}[$id] = true;
600603

601604
try {
602-
$service = $this->createService($definition, new \SplObjectStorage(), $id);
605+
$service = $this->createService($definition, $inlineServices, $id);
603606
} finally {
604607
unset($this->{$loading}[$id]);
605608
}
@@ -1054,10 +1057,10 @@ public function findDefinition($id)
10541057
* @throws RuntimeException When the service is a synthetic service
10551058
* @throws InvalidArgumentException When configure callable is not callable
10561059
*/
1057-
private function createService(Definition $definition, \SplObjectStorage $inlinedDefinitions, $id = null, $tryProxy = true)
1060+
private function createService(Definition $definition, array &$inlineServices, $id = null, $tryProxy = true)
10581061
{
1059-
if (null === $id && isset($inlinedDefinitions[$definition])) {
1060-
return $inlinedDefinitions[$definition];
1062+
if (null === $id && isset($inlineServices[$h = spl_object_hash($definition)])) {
1063+
return $inlineServices[$h];
10611064
}
10621065

10631066
if ($definition instanceof ChildDefinition) {
@@ -1078,11 +1081,11 @@ private function createService(Definition $definition, \SplObjectStorage $inline
10781081
->instantiateProxy(
10791082
$this,
10801083
$definition,
1081-
$id, function () use ($definition, $inlinedDefinitions, $id) {
1082-
return $this->createService($definition, $inlinedDefinitions, $id, false);
1084+
$id, function () use ($definition, &$inlineServices, $id) {
1085+
return $this->createService($definition, $inlineServices, $id, false);
10831086
}
10841087
);
1085-
$this->shareService($definition, $proxy, $id, $inlinedDefinitions);
1088+
$this->shareService($definition, $proxy, $id, $inlineServices);
10861089

10871090
return $proxy;
10881091
}
@@ -1093,15 +1096,15 @@ private function createService(Definition $definition, \SplObjectStorage $inline
10931096
require_once $parameterBag->resolveValue($definition->getFile());
10941097
}
10951098

1096-
$arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlinedDefinitions);
1099+
$arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlineServices);
10971100

10981101
if (null !== $id && $definition->isShared() && isset($this->services[$id]) && ($tryProxy || !$definition->isLazy())) {
10991102
return $this->services[$id];
11001103
}
11011104

11021105
if (null !== $factory = $definition->getFactory()) {
11031106
if (is_array($factory)) {
1104-
$factory = array($this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlinedDefinitions), $factory[1]);
1107+
$factory = array($this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlineServices), $factory[1]);
11051108
} elseif (!is_string($factory)) {
11061109
throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id));
11071110
}
@@ -1130,26 +1133,26 @@ private function createService(Definition $definition, \SplObjectStorage $inline
11301133

11311134
if ($tryProxy || !$definition->isLazy()) {
11321135
// share only if proxying failed, or if not a proxy
1133-
$this->shareService($definition, $service, $id, $inlinedDefinitions);
1136+
$this->shareService($definition, $service, $id, $inlineServices);
11341137
}
11351138

1136-
$properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlinedDefinitions);
1139+
$properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlineServices);
11371140
foreach ($properties as $name => $value) {
11381141
$service->$name = $value;
11391142
}
11401143

11411144
foreach ($definition->getMethodCalls() as $call) {
1142-
$this->callMethod($service, $call, $inlinedDefinitions);
1145+
$this->callMethod($service, $call, $inlineServices);
11431146
}
11441147

11451148
if ($callable = $definition->getConfigurator()) {
11461149
if (is_array($callable)) {
11471150
$callable[0] = $parameterBag->resolveValue($callable[0]);
11481151

11491152
if ($callable[0] instanceof Reference) {
1150-
$callable[0] = $this->doGet((string) $callable[0], $callable[0]->getInvalidBehavior());
1153+
$callable[0] = $this->doGet((string) $callable[0], $callable[0]->getInvalidBehavior(), $inlineServices);
11511154
} elseif ($callable[0] instanceof Definition) {
1152-
$callable[0] = $this->createService($callable[0], $inlinedDefinitions);
1155+
$callable[0] = $this->createService($callable[0], $inlineServices);
11531156
}
11541157
}
11551158

@@ -1173,14 +1176,14 @@ private function createService(Definition $definition, \SplObjectStorage $inline
11731176
*/
11741177
public function resolveServices($value)
11751178
{
1176-
return $this->doResolveServices($value, new \SplObjectStorage());
1179+
return $this->doResolveServices($value);
11771180
}
11781181

1179-
private function doResolveServices($value, \SplObjectStorage $inlinedDefinitions)
1182+
private function doResolveServices($value, array &$inlineServices = array())
11801183
{
11811184
if (is_array($value)) {
11821185
foreach ($value as $k => $v) {
1183-
$value[$k] = $this->doResolveServices($v, $inlinedDefinitions);
1186+
$value[$k] = $this->doResolveServices($v, $inlineServices);
11841187
}
11851188
} elseif ($value instanceof ServiceClosureArgument) {
11861189
$reference = $value->getValues()[0];
@@ -1223,9 +1226,9 @@ private function doResolveServices($value, \SplObjectStorage $inlinedDefinitions
12231226
return $count;
12241227
});
12251228
} elseif ($value instanceof Reference) {
1226-
$value = $this->doGet((string) $value, $value->getInvalidBehavior());
1229+
$value = $this->doGet((string) $value, $value->getInvalidBehavior(), $inlineServices);
12271230
} elseif ($value instanceof Definition) {
1228-
$value = $this->createService($value, $inlinedDefinitions);
1231+
$value = $this->createService($value, $inlineServices);
12291232
} elseif ($value instanceof Expression) {
12301233
$value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this));
12311234
}
@@ -1540,20 +1543,20 @@ private function getProxyInstantiator()
15401543
return $this->proxyInstantiator;
15411544
}
15421545

1543-
private function callMethod($service, $call, \SplObjectStorage $inlinedDefinitions)
1546+
private function callMethod($service, $call, array &$inlineServices)
15441547
{
15451548
foreach (self::getServiceConditionals($call[1]) as $s) {
15461549
if (!$this->has($s)) {
15471550
return;
15481551
}
15491552
}
15501553
foreach (self::getInitializedConditionals($call[1]) as $s) {
1551-
if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) {
1554+
if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE, $inlineServices)) {
15521555
return;
15531556
}
15541557
}
15551558

1556-
call_user_func_array(array($service, $call[0]), $this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlinedDefinitions));
1559+
call_user_func_array(array($service, $call[0]), $this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlineServices));
15571560
}
15581561

15591562
/**
@@ -1563,14 +1566,11 @@ private function callMethod($service, $call, \SplObjectStorage $inlinedDefinitio
15631566
* @param object $service
15641567
* @param string|null $id
15651568
*/
1566-
private function shareService(Definition $definition, $service, $id, \SplObjectStorage $inlinedDefinitions)
1569+
private function shareService(Definition $definition, $service, $id, array &$inlineServices)
15671570
{
1568-
if (!$definition->isShared()) {
1569-
return;
1570-
}
1571-
if (null === $id) {
1572-
$inlinedDefinitions[$definition] = $service;
1573-
} else {
1571+
$inlineServices[null !== $id ? $id : spl_object_hash($definition)] = $service;
1572+
1573+
if (null !== $id && $definition->isShared()) {
15741574
$this->services[$id] = $service;
15751575
unset($this->loading[$id], $this->alreadyLoading[$id]);
15761576
}

0 commit comments

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