8000 [DI] Fix invalid callables dumped for ArgumentInterface objects · symfony/symfony@8783602 · GitHub
[go: up one dir, main page]

Skip to content

Commit 8783602

Browse files
[DI] Fix invalid callables dumped for ArgumentInterface objects
1 parent b9e19f6 commit 8783602

File tree

2 files changed

+70
-53
lines changed

2 files changed

+70
-53
lines changed

src/Symfony/Component/DependencyInjection/Argument/ClosureProxyArgument.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
namespace Symfony\Component\DependencyInjection\Argument;
1313

1414
use Symfony\Component\DependencyInjection\ContainerInterface;
15+
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
1516
use Symfony\Component\DependencyInjection\Reference;
1617

1718
/**
@@ -41,6 +42,9 @@ public function getValues()
4142
*/
4243
public function setValues(array $values)
4344
{
45+
if (!$values[0] instanceof Reference) {
46+
throw new InvalidArgumentException(sprintf('A ClosureProxyArgument must hold a Reference, "%s" given.', is_object($values[0]) ? get_class($values[0]) : gettype($values[0])));
47+
}
4448
list($this->reference, $this->method) = $values;
4549
}
4650
}

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

Lines changed: 66 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1410,40 +1410,79 @@ private function dumpValue($value, $interpolate = true)
14101410
}
14111411

14121412
return sprintf('array(%s)', implode(', ', $code));
1413-
} elseif ($value instanceof ServiceClosureArgument) {
1414-
$value = $value->getValues()[0];
1415-
$code = $this->dumpValue($value, $interpolate);
1416-
1417-
if ($value instanceof TypedReference) {
1418-
$code = sprintf('$f = function (\\%s $v%s) { return $v; }; return $f(%s);', $value->getType(), ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $value->getInvalidBehavior() ? ' = null' : '', $code);
1419-
} else {
1420-
$code = sprintf('return %s;', $code);
1421-
}
1413+
} elseif ($value instanceof ArgumentInterface) {
1414+
$scope = array($this->definitionVariables, $this->referenceVariables, $this->variableCount);
1415+
$this->definitionVariables = $this->referenceVariables = null;
1416+
1417+
try {
1418+
if ($value instanceof ServiceClosureArgument) {
1419+
$value = $value->getValues()[0];
1420+
$code = $this->dumpValue($value, $interpolate);
1421+
1422+
if ($value instanceof TypedReference) {
1423+
$code = sprintf('$f = function (\\%s $v%s) { return $v; }; return $f(%s);', $value->getType(), ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $value->getInvalidBehavior() ? ' = null' : '', $code);
1424+
} else {
1425+
$code = sprintf('return %s;', $code);
1426+
}
14221427

1423-
return sprintf("function () {\n %s\n }", $code);
1424-
} elseif ($value instanceof IteratorArgument) {
1425-
$countCode = array();
1426-
$countCode[] = 'function () {';
1427-
$operands = array(0);
1428+
return sprintf("function () {\n %s\n }", $code);
1429+
}
14281430

1429-
$code = array();
1430-
$code[] = 'new RewindableGenerator(function () {';
1431-
foreach ($value->getValues() as $k => $v) {
1432-
($c = $this->getServiceConditionals($v)) ? $operands[] = "(int) ($c)" : ++$operands[0];
1433-
$v = $this->wrapServiceConditionals($v, sprintf(" yield %s => %s;\n", $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)));
1434-
foreach (explode("\n", $v) as $v) {
1435-
if ($v) {
1436-
$code[] = ' '.$v;
1431+
if ($value instanceof IteratorArgument) {
1432+
$countCode = array();
1433+
$countCode[] = 'function () {';
1434+
$operands = array(0);
1435+
1436+
$code = array();
1437+
$code[] = 'new RewindableGenerator(function () {';
1438+
foreach ($value->getValues() as $k => $v) {
1439+
($c = $this->getServiceConditionals($v)) ? $operands[] = "(int) ($c)" : ++$operands[0];
1440+
$v = $this->wrapServiceConditionals($v, sprintf(" yield %s => %s;\n", $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)));
1441+
foreach (explode("\n", $v) as $v) {
1442+
if ($v) {
1443+
$code[] = ' '.$v;
1444+
}
1445+
}
14371446
}
1447+
1448+
$countCode[] = sprintf(' return %s;', implode(' + ', $operands));
1449+
$countCode[] = ' }';
1450+
1451+
$code[] = sprintf(' }, %s)', count($operands) > 1 ? implode("\n", $countCode) : $operands[0]);
1452+
1453+
return implode("\n", $code);
14381454
}
1439-
}
14401455

1441-
$countCode[] = sprintf(' return %s;', implode(' + ', $operands));
1442-
$countCode[] = ' }';
1456+
if ($value instanceof ClosureProxyArgument) {
1457+
list($reference, $method) = $value->getValues();
1458+
$method = substr($this->dumpLiteralClass($this->dumpValue($method)), 1);
1459+
1460+
if ('service_container' === (string) $reference) {
1461+
$class = $this->baseClass;
1462+
} elseif (!$this->container->hasDefinition((string) $reference) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
1463+
return 'null';
1464+
} else {
1465+
$class = substr($this->dumpLiteralClass($this->dumpValue($this->container->findDefinition((string) $reference)->getClass())), 1);
1466+
}
1467+
if (false !== strpos($class, '$') || false !== strpos($method, '$')) {
1468+
throw new RuntimeException(sprintf('Cannot dump definition for service "%s": dynamic class names or methods, and closure-proxies are incompatible with each other.', $reference));
1469+
}
1470+
if (!method_exists($class, $method)) {
1471+
throw new InvalidArgumentException(sprintf('Cannot create closure-proxy for service "%s": method "%s::%s" does not exist.', $reference, $class, $method));
1472+
}
1473+
$r = $this->container->getReflectionClass($class)->getMethod($method);
1474+
if (!$r->isPublic()) {
1475+
throw new InvalidArgumentException(sprintf('Cannot create closure-proxy for service "%s": method "%s::%s" must be public.', $reference, $class, $method));
1476+
}
1477+
$signature = preg_replace('/^(&?)[^(]*/', '$1', ProxyHelper::getSignature($r, $call));
14431478

1444-
$code[] = sprintf(' }, %s)', count($operands) > 1 ? implode("\n", $countCode) : $operands[0]);
1479+
$return = 'void' !== ProxyHelper::getTypeHint($r);
14451480

1446-
return implode("\n", $code);
1481+
return sprintf("/** @closure-proxy %s::%s */ function %s {\n %s%s->%s;\n }", $class, $method, $signature, $return ? 'return ' : '', $this->dumpValue($reference), $call);
1482+
}
1483+
} finally {
1484+
list($this->definitionVariables, $this->referenceVariables, $this->variableCount) = $scope;
1485+
}
14471486
} elseif ($value instanceof Definition) {
14481487
if (null !== $this->definitionVariables && $this->definitionVariables->contains($value)) {
14491488
return $this->dumpValue($this->definitionVariables->offsetGet($value), $interpolate);
@@ -1497,32 +1536,6 @@ private function dumpValue($value, $interpolate = true)
14971536
}
14981537

14991538
return sprintf('new %s(%s)', $this->dumpLiteralClass($this->dumpValue($class)), implode(', ', $arguments));
1500-
} elseif ($value instanceof ClosureProxyArgument) {
1501-
list($reference, $method) = $value->getValues();
1502-
$method = substr($this->dumpLiteralClass($this->dumpValue($method)), 1);
1503-
1504-
if ('service_container' === (string) $reference) {
1505-
$class = $this->baseClass;
1506-
} elseif (!$this->container->hasDefinition((string) $reference) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) {
1507-
return 'null';
1508-
} else {
1509-
$class = substr($this->dumpLiteralClass($this->dumpValue($this->container->findDefinition((string) $reference)->getClass())), 1);
1510-
}
1511-
if (false !== strpos($class, '$') || false !== strpos($method, '$')) {
1512-
throw new RuntimeException(sprintf('Cannot dump definition for service "%s": dynamic class names or methods, and closure-proxies are incompatible with each other.', $reference));
1513-
}
1514-
if (!method_exists($class, $method)) {
1515-
throw new InvalidArgumentException(sprintf('Cannot create closure-proxy for service "%s": method "%s::%s" does not exist.', $reference, $class, $method));
1516-
}
1517-
$r = $this->container->getReflectionClass($class)->getMethod($method);
1518-
if (!$r->isPublic()) {
1519-
throw new InvalidArgumentException(sprintf('Cannot create closure-proxy for service "%s": method "%s::%s" must be public.', $reference, $class, $method));
1520-
}
1521-
$signature = preg_replace('/^(&?)[^(]*/', '$1', ProxyHelper::getSignature($r, $call));
1522-
1523-
$return = 'void' !== ProxyHelper::getTypeHint($r);
1524-
1525-
return sprintf("/** @closure-proxy %s::%s */ function %s {\n %s%s->%s;\n }", $class, $method, $signature, $return ? 'return ' : '', $this->dumpValue($reference), $call);
15261539
} elseif ($value instanceof Variable) {
15271540
return '$'.$value;
15281541
} elseif ($value instanceof Reference) {

0 commit comments

Comments
 (0)
0