[DependencyInjection] Add a new pass to check arguments validity
This commit is contained in:
parent
6e501296f9
commit
2ce36a6074
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* 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\Definition;
|
||||
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Checks if arguments of methods are properly configured.
|
||||
*
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
* @author Nicolas Grekas <p@tchwork.com>
|
||||
*/
|
||||
class CheckArgumentsValidityPass extends AbstractRecursivePass
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function processValue($value, $isRoot = false)
|
||||
{
|
||||
if (!$value instanceof Definition) {
|
||||
return parent::processValue($value, $isRoot);
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
foreach ($value->getArguments() as $k => $v) {
|
||||
if ($k !== $i++) {
|
||||
if (!is_int($k)) {
|
||||
throw new RuntimeException(sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k));
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('Invalid constructor argument %d for service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $this->currentId, $i));
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($value->getMethodCalls() as $methodCall) {
|
||||
$i = 0;
|
||||
foreach ($methodCall[1] as $k => $v) {
|
||||
if ($k !== $i++) {
|
||||
if (!is_int($k)) {
|
||||
throw new RuntimeException(sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k));
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('Invalid argument %d for method call "%s" of service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $methodCall[0], $this->currentId, $i));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -60,6 +60,7 @@ class PassConfig
|
||||
new AnalyzeServiceReferencesPass(true),
|
||||
new CheckCircularReferencesPass(),
|
||||
new CheckReferenceValidityPass(),
|
||||
new CheckArgumentsValidityPass(),
|
||||
));
|
||||
|
||||
$this->removingPasses = array(array(
|
||||
|
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Symfony package.
|
||||
*
|
||||
* (c) Fabien Potencier <fabien@symfony.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Symfony\Component\DependencyInjection\Tests\Compiler;
|
||||
|
||||
use Symfony\Component\DependencyInjection\Compiler\CheckArgumentsValidityPass;
|
||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||
|
||||
/**
|
||||
* @author Kévin Dunglas <dunglas@gmail.com>
|
||||
*/
|
||||
class CheckArgumentsValidityPassTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testProcess()
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$definition = $container->register('foo');
|
||||
$definition->setArguments(array(null, 1, 'a'));
|
||||
$definition->setMethodCalls(array(
|
||||
array('bar', array('a', 'b')),
|
||||
array('baz', array('c', 'd')),
|
||||
));
|
||||
|
||||
$pass = new CheckArgumentsValidityPass();
|
||||
$pass->process($container);
|
||||
|
||||
$this->assertEquals(array(null, 1, 'a'), $container->getDefinition('foo')->getArguments());
|
||||
$this->assertEquals(array(
|
||||
array('bar', array('a', 'b')),
|
||||
array('baz', array('c', 'd')),
|
||||
), $container->getDefinition('foo')->getMethodCalls());
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
|
||||
* @dataProvider definitionProvider
|
||||
*/
|
||||
public function testException(array $arguments, array $methodCalls)
|
||||
{
|
||||
$container = new ContainerBuilder();
|
||||
$definition = $container->register('foo');
|
||||
$definition->setArguments($arguments);
|
||||
$definition->setMethodCalls($methodCalls);
|
||||
|
||||
$pass = new CheckArgumentsValidityPass();
|
||||
$pass->process($container);
|
||||
}
|
||||
|
||||
public function definitionProvider()
|
||||
{
|
||||
return array(
|
||||
array(array(null, 'a' => 'a'), array()),
|
||||
array(array(1 => 1), array()),
|
||||
array(array(), array(array('baz', array(null, 'a' => 'a')))),
|
||||
array(array(), array(array('baz', array(1 => 1)))),
|
||||
);
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
|
||||
<services>
|
||||
<service id="Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy">
|
||||
<argument />
|
||||
<argument key="$apiKey">ABCD</argument>
|
||||
<call method="setApiKey">
|
||||
<argument key="$apiKey">123</argument>
|
||||
|
@ -1,9 +1,10 @@
|
||||
services:
|
||||
Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy: { $apiKey: ABCD }
|
||||
Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy: { 0: ~, $apiKey: ABCD }
|
||||
|
||||
another_one:
|
||||
class: Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy
|
||||
arguments:
|
||||
0: ~
|
||||
$apiKey: ABCD
|
||||
calls:
|
||||
- ['setApiKey', { $apiKey: '123' }]
|
||||
|
@ -701,11 +701,11 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml'));
|
||||
$loader->load('services_named_args.xml');
|
||||
|
||||
$this->assertEquals(array('$apiKey' => 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
|
||||
$this->assertEquals(array(null, '$apiKey' => 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
|
||||
|
||||
$container->compile();
|
||||
|
||||
$this->assertEquals(array(1 => 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
|
||||
$this->assertEquals(array(null, 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
|
||||
$this->assertEquals(array(array('setApiKey', array('123'))), $container->getDefinition(NamedArgumentsDummy::class)->getMethodCalls());
|
||||
}
|
||||
}
|
||||
|
@ -447,13 +447,13 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
||||
$loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml'));
|
||||
$loader->load('services_named_args.yml');
|
||||
|
||||
$this->assertEquals(array('$apiKey' => 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
|
||||
$this->assertEquals(array('$apiKey' => 'ABCD'), $container->getDefinition('another_one')->getArguments());
|
||||
$this->assertEquals(array(null, '$apiKey' => 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
|
||||
$this->assertEquals(array(null, '$apiKey' => 'ABCD'), $container->getDefinition('another_one')->getArguments());
|
||||
|
||||
$container->compile();
|
||||
|
||||
$this->assertEquals(array(1 => 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
|
||||
$this->assertEquals(array(1 => 'ABCD'), $container->getDefinition('another_one')->getArguments());
|
||||
$this->assertEquals(array(null, 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments());
|
||||
$this->assertEquals(array(null, 'ABCD'), $container->getDefinition('another_one')->getArguments());
|
||||
$this->assertEquals(array(array('setApiKey', array('123'))), $container->getDefinition('another_one')->getMethodCalls());
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user