[#17878] Fixing a bug where scalar values caused invalid ordering

This commit is contained in:
Ryan Weaver 2016-02-21 20:17:09 -05:00
parent cf692a6bd8
commit 865f2029fd
2 changed files with 113 additions and 1 deletions

View File

@ -78,6 +78,14 @@ class AutowirePass implements CompilerPassInterface
try {
if (!$typeHint = $parameter->getClass()) {
// no default value? Then fail
if (!$parameter->isOptional()) {
throw new RuntimeException(sprintf('Unable to autowire argument index %s ($%s) for the service "%s". If this is an object, give it a type-hint. Otherwise, specify this argument\'s value explicitly.', $index, $parameter->name, $id));
}
// specifically pass the default value
$arguments[$index] = $parameter->getDefaultValue();
continue;
}

View File

@ -302,7 +302,6 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
$pass->process($container);
$definition = $container->getDefinition('multiple');
// takes advantage of Reference's __toString
$this->assertEquals(
array(
new Reference('a'),
@ -312,6 +311,92 @@ class AutowirePassTest extends \PHPUnit_Framework_TestCase
$definition->getArguments()
);
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Unable to autowire argument index 1 ($foo) for the service "arg_no_type_hint". If this is an object, give it a type-hint. Otherwise, specify this argument's value explicitly.
*/
public function testScalarArgsCannotBeAutowired()
{
$container = new ContainerBuilder();
$container->register('a', __NAMESPACE__.'\A');
$container->register('dunglas', __NAMESPACE__.'\Dunglas');
$container->register('arg_no_type_hint', __NAMESPACE__.'\MultipleArguments')
->setAutowired(true);
$pass = new AutowirePass();
$pass->process($container);
$container->getDefinition('arg_no_type_hint');
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException
* @expectedExceptionMessage Unable to autowire argument index 1 ($foo) for the service "not_really_optional_scalar". If this is an object, give it a type-hint. Otherwise, specify this argument's value explicitly.
*/
public function testOptionalScalarNotReallyOptionalThrowException()
{
$container = new ContainerBuilder();
$container->register('a', __NAMESPACE__.'\A');
$container->register('lille', __NAMESPACE__.'\Lille');
$container->register('not_really_optional_scalar', __NAMESPACE__.'\MultipleArgumentsOptionalScalarNotReallyOptional')
->setAutowired(true);
$pass = new AutowirePass();
$pass->process($container);
}
public function testOptionalScalarArgsDontMessUpOrder()
{
$container = new ContainerBuilder();
$container->register('a', __NAMESPACE__.'\A');
$container->register('lille', __NAMESPACE__.'\Lille');
$container->register('with_optional_scalar', __NAMESPACE__.'\MultipleArgumentsOptionalScalar')
->setAutowired(true);
$pass = new AutowirePass();
$pass->process($container);
$definition = $container->getDefinition('with_optional_scalar');
$this->assertEquals(
array(
new Reference('a'),
// use the default value
'default_val',
new Reference('lille'),
),
$definition->getArguments()
);
}
public function testOptionalScalarArgsNotPassedIfLast()
{
$container = new ContainerBuilder();
$container->register('a', __NAMESPACE__.'\A');
$container->register('lille', __NAMESPACE__.'\Lille');
$container->register('with_optional_scalar_last', __NAMESPACE__.'\MultipleArgumentsOptionalScalarLast')
->setAutowired(true);
$pass = new AutowirePass();
$pass->process($container);
$definition = $container->getDefinition('with_optional_scalar_last');
$this->assertEquals(
array(
new Reference('a'),
new Reference('lille'),
// third arg shouldn't *need* to be passed
// but that's hard to "pull of" with autowiring, so
// this assumes passing the default val is ok
'some_val',
),
$definition->getArguments()
);
}
}
class Foo
@ -441,4 +526,23 @@ class MultipleArguments
public function __construct(A $k, $foo, Dunglas $dunglas)
{
}
}
class MultipleArgumentsOptionalScalar
{
public function __construct(A $a, $foo = 'default_val', Lille $lille = null)
{
}
}
class MultipleArgumentsOptionalScalarLast
{
public function __construct(A $a, Lille $lille, $foo = 'some_val')
{
}
}
class MultipleArgumentsOptionalScalarNotReallyOptional
{
public function __construct(A $a, $foo = 'default_val', Lille $lille)
{
}
}