Skip to content

Commit 38ddcef

Browse files
Merge branch '3.4' into 4.0
* 3.4: [Form] Fixed ContextErrorException in FileType [DI] Fix handling of inlined definitions by ContainerBuilder [DI] Fix infinite loop when analyzing references
2 parents 9fbcfd2 + 6fc5967 commit 38ddcef

File tree

6 files changed

+80
-22
lines changed

6 files changed

+80
-22
lines changed

src/Symfony/Component/DependencyInjection/ContainerBuilder.php

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INV
544544
$this->{$loading}[$id] = true;
545545

546546
try {
547-
$service = $this->createService($definition, $id);
547+
$service = $this->createService($definition, new \SplObjectStorage(), $id);
548548
} finally {
549549
unset($this->{$loading}[$id]);
550550
}
@@ -978,8 +978,12 @@ public function findDefinition($id)
978978
* @throws RuntimeException When the service is a synthetic service
979979
* @throws InvalidArgumentException When configure callable is not callable
980980
*/
981-
private function createService(Definition $definition, $id, $tryProxy = true)
981+
private function createService(Definition $definition, \SplObjectStorage $inlinedDefinitions, $id = null, $tryProxy = true)
982982
{
983+
if (null === $id && isset($inlinedDefinitions[$definition])) {
984+
return $inlinedDefinitions[$definition];
985+
}
986+
983987
if ($definition instanceof ChildDefinition) {
984988
throw new RuntimeException(sprintf('Constructing service "%s" from a parent definition is not supported at build time.', $id));
985989
}
@@ -998,11 +1002,11 @@ private function createService(Definition $definition, $id, $tryProxy = true)
9981002
->instantiateProxy(
9991003
$this,
10001004
$definition,
1001-
$id, function () use ($definition, $id) {
1002-
return $this->createService($definition, $id, false);
1005+
$id, function () use ($definition, $inlinedDefinitions, $id) {
1006+
return $this->createService($definition, $inlinedDefinitions, $id, false);
10031007
}
10041008
);
1005-
$this->shareService($definition, $proxy, $id);
1009+
$this->shareService($definition, $proxy, $id, $inlinedDefinitions);
10061010

10071011
return $proxy;
10081012
}
@@ -1013,15 +1017,15 @@ private function createService(Definition $definition, $id, $tryProxy = true)
10131017
require_once $parameterBag->resolveValue($definition->getFile());
10141018
}
10151019

1016-
$arguments = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())));
1020+
$arguments = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getArguments())), $inlinedDefinitions);
10171021

10181022
if (null !== $id && $definition->isShared() && isset($this->services[$id]) && ($tryProxy || !$definition->isLazy())) {
10191023
return $this->services[$id];
10201024
}
10211025

10221026
if (null !== $factory = $definition->getFactory()) {
10231027
if (is_array($factory)) {
1024-
$factory = array($this->resolveServices($parameterBag->resolveValue($factory[0])), $factory[1]);
1028+
$factory = array($this->doResolveServices($parameterBag->resolveValue($factory[0]), $inlinedDefinitions), $factory[1]);
10251029
} elseif (!is_string($factory)) {
10261030
throw new RuntimeException(sprintf('Cannot create service "%s" because of invalid factory', $id));
10271031
}
@@ -1047,16 +1051,16 @@ private function createService(Definition $definition, $id, $tryProxy = true)
10471051

10481052
if ($tryProxy || !$definition->isLazy()) {
10491053
// share only if proxying failed, or if not a proxy
1050-
$this->shareService($definition, $service, $id);
1054+
$this->shareService($definition, $service, $id, $inlinedDefinitions);
10511055
}
10521056

1053-
$properties = $this->resolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())));
1057+
$properties = $this->doResolveServices($parameterBag->unescapeValue($parameterBag->resolveValue($definition->getProperties())), $inlinedDefinitions);
10541058
foreach ($properties as $name => $value) {
10551059
$service->$name = $value;
10561060
}
10571061

10581062
foreach ($definition->getMethodCalls() as $call) {
1059-
$this->callMethod($service, $call);
1063+
$this->callMethod($service, $call, $inlinedDefinitions);
10601064
}
10611065

10621066
if ($callable = $definition->getConfigurator()) {
@@ -1066,7 +1070,7 @@ private function createService(Definition $definition, $id, $tryProxy = true)
10661070
if ($callable[0] instanceof Reference) {
10671071
$callable[0] = $this->get((string) $callable[0], $callable[0]->getInvalidBehavior());
10681072
} elseif ($callable[0] instanceof Definition) {
1069-
$callable[0] = $this->createService($callable[0], null);
1073+
$callable[0] = $this->createService($callable[0], $inlinedDefinitions);
10701074
}
10711075
}
10721076

@@ -1089,10 +1093,15 @@ private function createService(Definition $definition, $id, $tryProxy = true)
10891093
* the real service instances and all expressions evaluated
10901094
*/
10911095
public function resolveServices($value)
1096+
{
1097+
return $this->doResolveServices($value, new \SplObjectStorage());
1098+
}
1099+
1100+
private function doResolveServices($value, \SplObjectStorage $inlinedDefinitions)
10921101
{
10931102
if (is_array($value)) {
10941103
foreach ($value as $k => $v) {
1095-
$value[$k] = $this->resolveServices($v);
1104+
$value[$k] = $this->doResolveServices($v, $inlinedDefinitions);
10961105
}
10971106
} elseif ($value instanceof ServiceClosureArgument) {
10981107
$reference = $value->getValues()[0];
@@ -1137,7 +1146,7 @@ public function resolveServices($value)
11371146
} elseif ($value instanceof Reference) {
11381147
$value = $this->get((string) $value, $value->getInvalidBehavior());
11391148
} elseif ($value instanceof Definition) {
1140-
$value = $this->createService($value, null);
1149+
$value = $this->createService($value, $inlinedDefinitions);
11411150
} elseif ($value instanceof Expression) {
11421151
$value = $this->getExpressionLanguage()->evaluate($value, array('container' => $this));
11431152
}
@@ -1434,7 +1443,7 @@ private function getProxyInstantiator(): InstantiatorInterface
14341443
return $this->proxyInstantiator;
14351444
}
14361445

1437-
private function callMethod($service, $call)
1446+
private function callMethod($service, $call, \SplObjectStorage $inlinedDefinitions)
14381447
{
14391448
foreach (self::getServiceConditionals($call[1]) as $s) {
14401449
if (!$this->has($s)) {
@@ -1447,7 +1456,7 @@ private function callMethod($service, $call)
14471456
}
14481457
}
14491458

1450-
call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1]))));
1459+
call_user_func_array(array($service, $call[0]), $this->doResolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])), $inlinedDefinitions));
14511460
}
14521461

14531462
/**
@@ -1457,9 +1466,14 @@ private function callMethod($service, $call)
14571466
* @param object $service
14581467
* @param string|null $id
14591468
*/
1460-
private function shareService(Definition $definition, $service, $id)
1469+
private function shareService(Definition $definition, $service, $id, \SplObjectStorage $inlinedDefinitions)
14611470
{
1462-
if (null !== $id && $definition->isShared()) {
1471+
if (!$definition->isShared()) {
1472+
return;
1473+
}
1474+
if (null === $id) {
1475+
$inlinedDefinitions[$definition] = $service;
1476+
} else {
14631477
$this->services[$id] = $service;
14641478
unset($this->loading[$id], $this->alreadyLoading[$id]);
14651479
}

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ private function analyzeCircularReferences(array $edges, &$checkedNodes, &$curre
353353
if (isset($checkedNodes[$id])) {
354354
continue;
355355
}
356+
$checkedNodes[$id] = true;
356357

357358
if ($node->getValue() && ($edge->isLazy() || $edge->isWeak())) {
358359
// no-op
@@ -364,10 +365,8 @@ private function analyzeCircularReferences(array $edges, &$checkedNodes, &$curre
364365
} else {
365366
$currentPath[$id] = $id;
366367
$this->analyzeCircularReferences($node->getOutEdges(), $checkedNodes, $currentPath);
368+
array_pop($currentPath);
367369
}
368-
369-
$checkedNodes[$id] = true;
370-
array_pop($currentPath);
371370
}
372371
}
373372

src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,6 +1051,28 @@ public function testLazyLoadedService()
10511051
$this->assertTrue($classInList);
10521052
}
10531053

1054+
public function testInlinedDefinitions()
1055+
{
1056+
$container = new ContainerBuilder();
1057+
1058+
$definition = new Definition('BarClass');
1059+
1060+
$container->register('bar_user', 'BarUserClass')
1061+
->addArgument($definition)
1062+
->setProperty('foo', $definition);
1063+
1064+
$container->register('bar', 'BarClass')
1065+
->setProperty('foo', $definition)
1066+
->addMethodCall('setBaz', array($definition));
1067+
1068+
$barUser = $container->get('bar_user');
1069+
$bar = $container->get('bar');
1070+
1071+
$this->assertSame($barUser->foo, $barUser->bar);
1072+
$this->assertSame($bar->foo, $bar->getBaz());
1073+
$this->assertNotSame($bar->foo, $barUser->foo);
1074+
}
1075+
10541076
public function testInitializePropertiesBeforeMethodCalls()
10551077
{
10561078
$container = new ContainerBuilder();

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ function sc_configure($instance)
99
$instance->configure();
1010
}
1111

12-
class BarClass
12+
class BarClass extends BazClass
1313
{
1414
protected $baz;
1515
public $foo = 'foo';

src/Symfony/Component/Form/Extension/Core/Type/FileType.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,13 @@ public function buildForm(FormBuilderInterface $builder, array $options)
3434

3535
if ($options['multiple']) {
3636
$data = array();
37+
$files = $event->getData();
3738

38-
foreach ($event->getData() as $file) {
39+
if (!is_array($files)) {
40+
$files = array();
41+
}
42+
43+
foreach ($files as $file) {
3944
if ($requestHandler->isFileUpload($file)) {
4045
$data[] = $file;
4146
}

src/Symfony/Component/Form/Tests/Extension/Core/Type/FileTypeTest.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,24 @@ public function testMultipleSubmittedFilePathsAreDropped(RequestHandlerInterface
159159
$this->assertCount(1, $form->getData());
160160
}
161161

162+
/**
163+
* @dataProvider requestHandlerProvider
164+
*/
165+
public function testSubmitNonArrayValueWhenMultiple(RequestHandlerInterface $requestHandler)
166+
{
167+
$form = $this->factory
168+
->createBuilder(static::TESTED_TYPE, null, array(
169+
'multiple' => true,
170+
))
171+
->setRequestHandler($requestHandler)
172+
->getForm();
173+
$form->submit(null);
174+
175+
$this->assertSame(array(), $form->getData());
176+
$this->assertSame(array(), $form->getNormData());
177+
$this->assertSame(array(), $form->getViewData());
178+
}
179+
162180
public function requestHandlerProvider()
163181
{
164182
return array(

0 commit comments

Comments
 (0)