[DependencyInjection] Improve ServiceLocatorTagPass service matching

This commit is contained in:
Tim Goudriaan 2018-09-24 19:50:22 +02:00 committed by Nicolas Grekas
parent 3d2124e128
commit 1c1210a3e8
2 changed files with 137 additions and 0 deletions

View File

@ -52,6 +52,12 @@ final class ServiceLocatorTagPass extends AbstractRecursivePass
if (!$v instanceof Reference) {
throw new InvalidArgumentException(sprintf('Invalid definition for service "%s": an array of references is expected as first argument when the "container.service_locator" tag is set, "%s" found for key "%s".', $this->currentId, \is_object($v) ? \get_class($v) : \gettype($v), $k));
}
if (\is_int($k)) {
unset($arguments[0][$k]);
$k = (string) $v;
}
$arguments[0][$k] = new ServiceClosureArgument($v);
}
ksort($arguments[0]);

View File

@ -0,0 +1,131 @@
<?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 PHPUnit\Framework\TestCase;
use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition;
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition1;
use Symfony\Component\DependencyInjection\Tests\Fixtures\TestDefinition2;
require_once __DIR__.'/../Fixtures/includes/classes.php';
class ServiceLocatorTagPassTest extends TestCase
{
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage Invalid definition for service "foo": an array of references is expected as first argument when the "container.service_locator" tag is set.
*/
public function testNoServices()
{
$container = new ContainerBuilder();
$container->register('foo', ServiceLocator::class)
->addTag('container.service_locator')
;
(new ServiceLocatorTagPass())->process($container);
}
/**
* @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException
* @expectedExceptionMessage Invalid definition for service "foo": an array of references is expected as first argument when the "container.service_locator" tag is set, "string" found for key "0".
*/
public function testInvalidServices()
{
$container = new ContainerBuilder();
$container->register('foo', ServiceLocator::class)
->setArguments(array(array(
'dummy',
)))
->addTag('container.service_locator')
;
(new ServiceLocatorTagPass())->process($container);
}
public function testProcessValue()
{
$container = new ContainerBuilder();
$container->register('bar', CustomDefinition::class);
$container->register('baz', CustomDefinition::class);
$container->register('foo', ServiceLocator::class)
->setArguments(array(array(
new Reference('bar'),
new Reference('baz'),
'some.service' => new Reference('bar'),
)))
->addTag('container.service_locator')
;
(new ServiceLocatorTagPass())->process($container);
/** @var ServiceLocator $locator */
$locator = $container->get('foo');
$this->assertSame(CustomDefinition::class, \get_class($locator('bar')));
$this->assertSame(CustomDefinition::class, \get_class($locator('baz')));
$this->assertSame(CustomDefinition::class, \get_class($locator('some.service')));
}
public function testServiceWithKeyOverwritesPreviousInheritedKey()
{
$container = new ContainerBuilder();
$container->register('bar', TestDefinition1::class);
$container->register('baz', TestDefinition2::class);
$container->register('foo', ServiceLocator::class)
->setArguments(array(array(
new Reference('bar'),
'bar' => new Reference('baz'),
)))
->addTag('container.service_locator')
;
(new ServiceLocatorTagPass())->process($container);
/** @var ServiceLocator $locator */
$locator = $container->get('foo');
$this->assertSame(TestDefinition2::class, \get_class($locator('bar')));
}
public function testInheritedKeyOverwritesPreviousServiceWithKey()
{
$container = new ContainerBuilder();
$container->register('bar', TestDefinition1::class);
$container->register('baz', TestDefinition2::class);
$container->register('foo', ServiceLocator::class)
->setArguments(array(array(
'bar' => new Reference('baz'),
new Reference('bar'),
)))
->addTag('container.service_locator')
;
(new ServiceLocatorTagPass())->process($container);
/** @var ServiceLocator $locator */
$locator = $container->get('foo');
$this->assertSame(TestDefinition1::class, \get_class($locator('bar')));
}
}