diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php index 11a2197d04b8e..799a5db681181 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php @@ -20,6 +20,9 @@ */ abstract class AbstractRecursivePass implements CompilerPassInterface { + /** + * @var ContainerBuilder + */ protected $container; protected $currentId; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 47402b8ad8a90..5411c8f2a5c4d 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -57,6 +57,7 @@ public function __construct() new CheckDefinitionValidityPass(), new RegisterServiceSubscribersPass(), new ResolveNamedArgumentsPass(), + new ResolveArrayIterablesPass(), new AutowirePass(), new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveArrayIterablesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveArrayIterablesPass.php new file mode 100644 index 0000000000000..1c9e147753860 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveArrayIterablesPass.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; + +/** + * Resolves iterator arguments needed to be an array by definition. + * + * @author Roland Franssen + */ +class ResolveArrayIterablesPass extends AbstractRecursivePass +{ + /** + * {@inheritdoc} + */ + protected function processValue($value, $isRoot = false) + { + if (!$value instanceof Definition || !$reflectionClass = $this->container->getReflectionClass($value->getClass())) { + return parent::processValue($value, $isRoot); + } + + $calls = $value->getMethodCalls(); + $calls[] = array('__construct', $value->getArguments()); + + foreach ($calls as $i => $call) { + list($method, $arguments) = $call; + + if (!$reflectionClass->hasMethod($method)) { + continue; + } + + $reflectionMethod = $reflectionClass->getMethod($method); + $reflectionParams = $reflectionMethod->getParameters(); + + foreach ($arguments as $key => $argument) { + if (!$argument instanceof IteratorArgument || !isset($reflectionParams[$key])) { + continue; + } + + if ('array' === ProxyHelper::getTypeHint($reflectionMethod, $reflectionParams[$key])) { + $calls[$i][1][$key] = $argument->getValues(); + } + } + } + + $value->setArguments(array_pop($calls)[1]); + $value->setMethodCalls($calls); + + return $value; + } +}