TaggedIteratorArgument example

$container->register('service1')->addTag('my_custom_tag', ['foo' => 'bar']);

        $definition = $container->register('service2', BarTagClass::class);
        $definition->addTag('my_custom_tag', ['priority' => 100]);
        $definition->addTag('my_custom_tag', ['foo' => 'a']);
        $definition->addTag('my_custom_tag', ['foo' => 'b', 'priority' => 100]);
        $definition->addTag('my_custom_tag', ['foo' => 'b']);
        $definition->addTag('my_custom_tag', []);

        $priorityTaggedServiceTraitImplementation = new PriorityTaggedServiceTraitImplementation();

        $tag = new TaggedIteratorArgument('my_custom_tag', 'foo');
        $expected = [
            'bar_tag_class' => new TypedReference('service2', BarTagClass::class),
            'b' => new TypedReference('service2', BarTagClass::class),
            'bar' => new Reference('service1'),
            'a' => new TypedReference('service2', BarTagClass::class),
        ];
        $services = $priorityTaggedServiceTraitImplementation->test($tag$container);
        $this->assertSame(array_keys($expected)array_keys($services));
        $this->assertEquals($expected$priorityTaggedServiceTraitImplementation->test($tag$container));
    }

    
return new ServiceLocatorArgument($argument);
            }
            if (\in_array($value->getTag()['tagged', 'tagged_iterator', 'tagged_locator'], true)) {
                $forLocator = 'tagged_locator' === $value->getTag();

                if (\is_array($argument) && isset($argument['tag']) && $argument['tag']) {
                    if ($diff = array_diff(array_keys($argument)$supportedKeys = ['tag', 'index_by', 'default_index_method', 'default_priority_method', 'exclude', 'exclude_self'])) {
                        throw new InvalidArgumentException(sprintf('"!%s" tag contains unsupported key "%s"; supported ones are "%s".', $value->getTag()implode('", "', $diff)implode('", "', $supportedKeys)));
                    }

                    $argument = new TaggedIteratorArgument($argument['tag']$argument['index_by'] ?? null, $argument['default_index_method'] ?? null, $forLocator$argument['default_priority_method'] ?? null, (array) ($argument['exclude'] ?? null)$argument['exclude_self'] ?? true);
                } elseif (\is_string($argument) && $argument) {
                    $argument = new TaggedIteratorArgument($argument, null, null, $forLocator);
                } else {
                    throw new InvalidArgumentException(sprintf('"!%s" tags only accept a non empty string or an array with a key "tag" in "%s".', $value->getTag()$file));
                }

                if ($forLocator) {
                    $argument = new ServiceLocatorArgument($argument);
                }

                return $argument;
            }
$this->assertInstanceOf(BoundArgument::class$locator->getBindings()['foo']);
    }

    public function testTaggedServices()
    {
        $container = new ContainerBuilder();

        $container->register('bar', TestDefinition1::class)->addTag('test_tag');
        $container->register('baz', TestDefinition2::class)->addTag('test_tag');

        $container->register('foo', ServiceLocator::class)
            ->setArguments([new TaggedIteratorArgument('test_tag', null, null, true)])
            ->addTag('container.service_locator')
        ;

        (new ServiceLocatorTagPass())->process($container);

        /** @var ServiceLocator $locator */
        $locator = $container->get('foo');

        $this->assertSame(TestDefinition1::class$locator('bar')::class);
        $this->assertSame(TestDefinition2::class$locator('baz')::class);
    }

    
class ResolveBindingsPassTest extends TestCase
{
    use ExpectDeprecationTrait;

    public function testProcess()
    {
        $container = new ContainerBuilder();

        $bindings = [
            CaseSensitiveClass::class => new BoundArgument(new Reference('foo')),
            'Psr\Container\ContainerInterface $container' => new BoundArgument(new ServiceLocatorArgument([]), true, BoundArgument::INSTANCEOF_BINDING),
            'iterable $objects' => new BoundArgument(new TaggedIteratorArgument('tag.name'), true, BoundArgument::INSTANCEOF_BINDING),
        ];

        $definition = $container->register(NamedArgumentsDummy::class, NamedArgumentsDummy::class);
        $definition->setArguments([1 => '123']);
        $definition->addMethodCall('setSensitiveClass');
        $definition->setBindings($bindings);

        $container->register('foo', CaseSensitiveClass::class)
            ->setBindings($bindings);

        $pass = new ResolveBindingsPass();
        
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="%s" has no or empty "tag" attribute in "%s".', $name$type$file));
                    }

                    $excludes = array_column($this->getChildren($arg, 'exclude'), 'nodeValue');
                    if ($arg->hasAttribute('exclude')) {
                        if (\count($excludes) > 0) {
                            throw new InvalidArgumentException('You cannot use both the attribute "exclude" and <exclude> tags at the same time.');
                        }
                        $excludes = [$arg->getAttribute('exclude')];
                    }

                    $arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag')$arg->getAttribute('index-by') ?: null, $arg->getAttribute('default-index-method') ?: null, $forLocator$arg->getAttribute('default-priority-method') ?: null, $excludes, !$arg->hasAttribute('exclude-self') || XmlUtils::phpize($arg->getAttribute('exclude-self')));

                    if ($forLocator) {
                        $arguments[$key] = new ServiceLocatorArgument($arguments[$key]);
                    }
                    break;
                case 'binary':
                    if (false === $value = base64_decode($arg->nodeValue)) {
                        throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="binary" is not a valid base64 encoded string.', $name));
                    }
                    $arguments[$key] = $value;
                    break;
                
#[\Attribute(\Attribute::TARGET_PARAMETER)] class TaggedIterator extends Autowire
{
    public function __construct(
        public string $tag,
        public ?string $indexAttribute = null,
        public ?string $defaultIndexMethod = null,
        public ?string $defaultPriorityMethod = null,
        public string|array $exclude = [],
        public bool $excludeSelf = true,
    ) {
        parent::__construct(new TaggedIteratorArgument($tag$indexAttribute$defaultIndexMethod, false, $defaultPriorityMethod(array) $exclude$excludeSelf));
    }
}
$loader = new XmlFileLoader($containernew FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('services_dump_load.xml');

        $this->assertEquals([new Reference('bar', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)]$container->getDefinition('foo')->getArguments());

        $dumper = new XmlDumper($container);
        $this->assertStringEqualsFile(self::$fixturesPath.'/xml/services_dump_load.xml', $dumper->dump());
    }

    public function testTaggedArguments()
    {
        $taggedIterator = new TaggedIteratorArgument('foo_tag', 'barfoo', 'foobar', false, 'getPriority');
        $taggedIterator2 = new TaggedIteratorArgument('foo_tag', null, null, false, null, ['baz']);
        $taggedIterator3 = new TaggedIteratorArgument('foo_tag', null, null, false, null, ['baz', 'qux'], false);

        $container = new ContainerBuilder();

        $container->register('foo', 'Foo')->addTag('foo_tag');
        $container->register('baz', 'Baz')->addTag('foo_tag');
        $container->register('qux', 'Qux')->addTag('foo_tag');

        $container->register('foo_tagged_iterator', 'Bar')
            ->setPublic(true)
            
'autowired' => new ServiceClosureArgument(new TypedReference('stdClass', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'autowired', [new Autowire(service: 'service.id')])),
            'autowired.nullable' => new ServiceClosureArgument(new TypedReference('stdClass', 'stdClass', ContainerInterface::IGNORE_ON_INVALID_REFERENCE, 'autowired.nullable', [new Autowire(service: 'service.id')])),
            'autowired.parameter' => new ServiceClosureArgument(new TypedReference('string', 'string', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'autowired.parameter', [new Autowire(service: '%parameter.1%')])),
            'autowire.decorated' => new ServiceClosureArgument(new TypedReference('stdClass', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'autowire.decorated', [new AutowireDecorated()])),
            'target' => new ServiceClosureArgument(new TypedReference('stdClass', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'target', [new Target('someTarget')])),
        ];
        $this->assertEquals($expected$container->getDefinition((string) $locator->getFactory()[0])->getArgument(0));

        (new AutowirePass())->process($container);

        $expected = [
            'tagged.iterator' => new ServiceClosureArgument(new TaggedIteratorArgument('tag')),
            'tagged.locator' => new ServiceClosureArgument(new ServiceLocatorArgument(new TaggedIteratorArgument('tag', 'tag', needsIndexes: true))),
            'autowired' => new ServiceClosureArgument(new TypedReference('service.id', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'autowired', [new Autowire(service: 'service.id')])),
            'autowired.nullable' => new ServiceClosureArgument(new TypedReference('service.id', 'stdClass', ContainerInterface::IGNORE_ON_INVALID_REFERENCE, 'autowired.nullable', [new Autowire(service: 'service.id')])),
            'autowired.parameter' => new ServiceClosureArgument('foobar'),
            'autowire.decorated' => new ServiceClosureArgument(new Reference('.service_locator.0tSxobl.inner', ContainerInterface::NULL_ON_INVALID_REFERENCE)),
            'target' => new ServiceClosureArgument(new TypedReference('stdClass', 'stdClass', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, 'target', [new Target('someTarget')])),
        ];
        $this->assertEquals($expected$container->getDefinition((string) $locator->getFactory()[0])->getArgument(0));
    }

    public function testBinding()
    {
/** * @return void */
    public function process(ContainerBuilder $container)
    {
        if (!$container->hasDefinition('argument_resolver')) {
            return;
        }

        $definitions = $container->getDefinitions();
        $namedResolvers = $this->findAndSortTaggedServices(new TaggedIteratorArgument('controller.targeted_value_resolver', 'name', needsIndexes: true)$container);
        $resolvers = $this->findAndSortTaggedServices(new TaggedIteratorArgument('controller.argument_value_resolver', 'name', needsIndexes: true)$container);

        foreach ($resolvers as $name => $resolver) {
            if ($definitions[(string) $resolver]->hasTag('controller.targeted_value_resolver')) {
                unset($resolvers[$name]);
            } else {
                $namedResolvers[$name] ??= clone $resolver;
            }
        }

        if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class) && $container->has('debug.stopwatch')) {
            
/** * @author Roland Franssen <franssen.roland@gmail.com> */
class ResolveTaggedIteratorArgumentPassTest extends TestCase
{
    public function testProcess()
    {
        $container = new ContainerBuilder();
        $container->register('a', 'stdClass')->addTag('foo');
        $container->register('b', 'stdClass')->addTag('foo', ['priority' => 20]);
        $container->register('c', 'stdClass')->addTag('foo', ['priority' => 10]);
        $container->register('d', 'stdClass')->setProperty('foos', new TaggedIteratorArgument('foo'));

        (new ResolveTaggedIteratorArgumentPass())->process($container);

        $properties = $container->getDefinition('d')->getProperties();
        $expected = new TaggedIteratorArgument('foo');
        $expected->setValues([new Reference('b')new Reference('c')new Reference('a')]);
        $this->assertEquals($expected$properties['foos']);
    }

    public function testProcessWithIndexes()
    {
        

        $container = new ContainerBuilder();
        $container->register(BarTagClass::class)
            ->setPublic(true)
            ->addTag('foo_bar', ['foo' => 'bar'])
        ;
        $container->register(FooTagClass::class)
            ->setPublic(true)
            ->addTag('foo_bar')
        ;
        $container->register(FooBarTaggedClass::class)
            ->addArgument(new TaggedIteratorArgument('foo_bar', 'foo'))
            ->setPublic(true)
        ;

        $container->compile();

        $s = $container->get(FooBarTaggedClass::class);

        $param = iterator_to_array($s->getParam()->getIterator());
        $this->assertSame(['bar' => $container->get(BarTagClass::class), 'foo_tag_class' => $container->get(FooTagClass::class)]$param);
    }

    

function iterator(array $values): IteratorArgument
{
    return new IteratorArgument(AbstractConfigurator::processValue($values, true));
}

/** * Creates a lazy iterator by tag name. */
function tagged_iterator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = true): TaggedIteratorArgument
{
    return new TaggedIteratorArgument($tag$indexAttribute$defaultIndexMethod, false, $defaultPriorityMethod(array) $exclude$excludeSelf);
}

/** * Creates a service locator by tag name. */
function tagged_locator(string $tag, string $indexAttribute = null, string $defaultIndexMethod = null, string $defaultPriorityMethod = null, string|array $exclude = [], bool $excludeSelf = true): ServiceLocatorArgument
{
    return new ServiceLocatorArgument(new TaggedIteratorArgument($tag$indexAttribute$defaultIndexMethod, true, $defaultPriorityMethod(array) $exclude$excludeSelf));
}

/** * Creates an expression. */
$container->register(AsDecoratorFoo::class);
        $container->register(AutowireNestedAttributes::class)->setAutowired(true);

        (new ResolveClassPass())->process($container);
        (new AutowireAsDecoratorPass())->process($container);
        (new DecoratorServicePass())->process($container);
        (new AutowirePass())->process($container);

        $expected = [
            'decorated' => new Reference(AutowireNestedAttributes::class.'.inner'),
            'iterator' => new TaggedIteratorArgument('foo'),
            'locator' => new ServiceLocatorArgument(new TaggedIteratorArgument('foo', needsIndexes: true)),
            'service' => new Reference('bar'),
        ];
        $this->assertEquals($expected$container->getDefinition(AutowireNestedAttributes::class)->getArgument(0));
    }
}
#[\Attribute(\Attribute::TARGET_PARAMETER)] class TaggedLocator extends Autowire
{
    public function __construct(
        public string $tag,
        public ?string $indexAttribute = null,
        public ?string $defaultIndexMethod = null,
        public ?string $defaultPriorityMethod = null,
        public string|array $exclude = [],
        public bool $excludeSelf = true,
    ) {
        parent::__construct(new ServiceLocatorArgument(new TaggedIteratorArgument($tag$indexAttribute$defaultIndexMethod, true, $defaultPriorityMethod(array) $exclude$excludeSelf)));
    }
}
public function testParseTaggedArgumentsWithIndexBy()
    {
        $container = new ContainerBuilder();
        $loader = new XmlFileLoader($containernew FileLocator(self::$fixturesPath.'/xml'));
        $loader->load('services_with_tagged_arguments.xml');

        $this->assertCount(1, $container->getDefinition('foo')->getTag('foo_tag'));
        $this->assertCount(1, $container->getDefinition('foo_tagged_iterator')->getArguments());
        $this->assertCount(1, $container->getDefinition('foo_tagged_locator')->getArguments());

        $taggedIterator = new TaggedIteratorArgument('foo_tag', 'barfoo', 'foobar', false, 'getPriority');
        $this->assertEquals($taggedIterator$container->getDefinition('foo_tagged_iterator')->getArgument(0));
        $taggedIterator2 = new TaggedIteratorArgument('foo_tag', null, null, false, null, ['baz']);
        $this->assertEquals($taggedIterator2$container->getDefinition('foo2_tagged_iterator')->getArgument(0));
        $taggedIterator3 = new TaggedIteratorArgument('foo_tag', null, null, false, null, ['baz', 'qux'], false);
        $this->assertEquals($taggedIterator3$container->getDefinition('foo3_tagged_iterator')->getArgument(0));

        $taggedIterator = new TaggedIteratorArgument('foo_tag', 'barfoo', 'foobar', true, 'getPriority');
        $this->assertEquals(new ServiceLocatorArgument($taggedIterator)$container->getDefinition('foo_tagged_locator')->getArgument(0));
        $taggedIterator2 = new TaggedIteratorArgument('foo_tag', 'foo_tag', 'getDefaultFooTagName', true, 'getDefaultFooTagPriority', ['baz']);
        $this->assertEquals(new ServiceLocatorArgument($taggedIterator2)$container->getDefinition('foo2_tagged_locator')->getArgument(0));
        $taggedIterator3 = new TaggedIteratorArgument('foo_tag', 'foo_tag', 'getDefaultFooTagName', true, 'getDefaultFooTagPriority', ['baz', 'qux'], false);
        
Home | Imprint | This part of the site doesn't use cookies.