Chris@14: Chris@14: * Chris@14: * For the full copyright and license information, please view the LICENSE Chris@14: * file that was distributed with this source code. Chris@14: */ Chris@14: Chris@14: namespace Symfony\Component\DependencyInjection\Compiler; Chris@14: Chris@14: use Symfony\Component\DependencyInjection\Definition; Chris@14: use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; Chris@14: use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; Chris@14: use Symfony\Component\DependencyInjection\Reference; Chris@14: Chris@14: /** Chris@14: * Resolves named arguments to their corresponding numeric index. Chris@14: * Chris@14: * @author Kévin Dunglas Chris@14: */ Chris@14: class ResolveNamedArgumentsPass extends AbstractRecursivePass Chris@14: { Chris@14: /** Chris@14: * {@inheritdoc} Chris@14: */ Chris@14: protected function processValue($value, $isRoot = false) Chris@14: { Chris@14: if (!$value instanceof Definition) { Chris@14: return parent::processValue($value, $isRoot); Chris@14: } Chris@14: Chris@14: $calls = $value->getMethodCalls(); Chris@17: $calls[] = ['__construct', $value->getArguments()]; Chris@14: Chris@14: foreach ($calls as $i => $call) { Chris@14: list($method, $arguments) = $call; Chris@14: $parameters = null; Chris@17: $resolvedArguments = []; Chris@14: Chris@14: foreach ($arguments as $key => $argument) { Chris@17: if (\is_int($key)) { Chris@14: $resolvedArguments[$key] = $argument; Chris@14: continue; Chris@14: } Chris@14: Chris@14: if (null === $parameters) { Chris@14: $r = $this->getReflectionMethod($value, $method); Chris@14: $class = $r instanceof \ReflectionMethod ? $r->class : $this->currentId; Chris@17: $method = $r->getName(); Chris@14: $parameters = $r->getParameters(); Chris@14: } Chris@14: Chris@14: if (isset($key[0]) && '$' === $key[0]) { Chris@14: foreach ($parameters as $j => $p) { Chris@14: if ($key === '$'.$p->name) { Chris@14: $resolvedArguments[$j] = $argument; Chris@14: Chris@14: continue 2; Chris@14: } Chris@14: } Chris@14: Chris@14: throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument named "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); Chris@14: } Chris@14: Chris@14: if (null !== $argument && !$argument instanceof Reference && !$argument instanceof Definition) { Chris@17: throw new InvalidArgumentException(sprintf('Invalid service "%s": the value of argument "%s" of method "%s()" must be null, an instance of %s or an instance of %s, %s given.', $this->currentId, $key, $class !== $this->currentId ? $class.'::'.$method : $method, Reference::class, Definition::class, \gettype($argument))); Chris@14: } Chris@14: Chris@14: $typeFound = false; Chris@14: foreach ($parameters as $j => $p) { Chris@18: if (!\array_key_exists($j, $resolvedArguments) && ProxyHelper::getTypeHint($r, $p, true) === $key) { Chris@14: $resolvedArguments[$j] = $argument; Chris@14: $typeFound = true; Chris@14: } Chris@14: } Chris@14: Chris@14: if (!$typeFound) { Chris@14: throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument type-hinted as "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); Chris@14: } Chris@14: } Chris@14: Chris@14: if ($resolvedArguments !== $call[1]) { Chris@14: ksort($resolvedArguments); Chris@14: $calls[$i][1] = $resolvedArguments; Chris@14: } Chris@14: } Chris@14: Chris@14: list(, $arguments) = array_pop($calls); Chris@14: Chris@14: if ($arguments !== $value->getArguments()) { Chris@14: $value->setArguments($arguments); Chris@14: } Chris@14: if ($calls !== $value->getMethodCalls()) { Chris@14: $value->setMethodCalls($calls); Chris@14: } Chris@14: Chris@14: return parent::processValue($value, $isRoot); Chris@14: } Chris@14: }