8000 [DI] Fix circular reference when using setters · symfony/symfony@de5eecc · GitHub
[go: up one dir, main page]

Skip to content

Commit de5eecc

Browse files
[DI] Fix circular reference when using setters
1 parent f74eced commit de5eecc

11 files changed

+404
-284
lines changed

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines 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