[DI] Reference tagged services in config
This commit is contained in:
parent
d7885ec3b2
commit
979e58f370
@ -0,0 +1,37 @@
|
|||||||
|
<?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\Argument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a collection of services found by tag name to lazily iterate over.
|
||||||
|
*
|
||||||
|
* @author Roland Franssen <franssen.roland@gmail.com>
|
||||||
|
*/
|
||||||
|
class TaggedIteratorArgument extends IteratorArgument
|
||||||
|
{
|
||||||
|
private $tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $tag
|
||||||
|
*/
|
||||||
|
public function __construct($tag)
|
||||||
|
{
|
||||||
|
parent::__construct(array());
|
||||||
|
|
||||||
|
$this->tag = (string) $tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getTag()
|
||||||
|
{
|
||||||
|
return $this->tag;
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ CHANGELOG
|
|||||||
* deprecated support for top-level anonymous services in XML
|
* deprecated support for top-level anonymous services in XML
|
||||||
* deprecated case insensitivity of parameter names
|
* deprecated case insensitivity of parameter names
|
||||||
* deprecated the `ResolveDefinitionTemplatesPass` class in favor of `ResolveChildDefinitionsPass`
|
* deprecated the `ResolveDefinitionTemplatesPass` class in favor of `ResolveChildDefinitionsPass`
|
||||||
|
* added `TaggedIteratorArgument` with YAML (`!tagged foo`) and XML (`<service type="tagged"/>`) support
|
||||||
|
|
||||||
3.3.0
|
3.3.0
|
||||||
-----
|
-----
|
||||||
|
@ -61,6 +61,7 @@ class PassConfig
|
|||||||
new AutowireRequiredMethodsPass(),
|
new AutowireRequiredMethodsPass(),
|
||||||
new ResolveBindingsPass(),
|
new ResolveBindingsPass(),
|
||||||
new AutowirePass(false),
|
new AutowirePass(false),
|
||||||
|
new ResolveTaggedIteratorArgumentPass(),
|
||||||
new ResolveServiceSubscribersPass(),
|
new ResolveServiceSubscribersPass(),
|
||||||
new ResolveReferencesToAliasesPass(),
|
new ResolveReferencesToAliasesPass(),
|
||||||
new ResolveInvalidReferencesPass(),
|
new ResolveInvalidReferencesPass(),
|
||||||
|
@ -0,0 +1,38 @@
|
|||||||
|
<?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\Argument\TaggedIteratorArgument;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves all TaggedIteratorArgument arguments.
|
||||||
|
*
|
||||||
|
* @author Roland Franssen <franssen.roland@gmail.com>
|
||||||
|
*/
|
||||||
|
class ResolveTaggedIteratorArgumentPass extends AbstractRecursivePass
|
||||||
|
{
|
||||||
|
use PriorityTaggedServiceTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
protected function processValue($value, $isRoot = false)
|
||||||
|
{
|
||||||
|
if (!$value instanceof TaggedIteratorArgument) {
|
||||||
|
return parent::processValue($value, $isRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
$value->setValues($this->findAndSortTaggedServices($value->getTag(), $this->container));
|
||||||
|
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ namespace Symfony\Component\DependencyInjection\Dumper;
|
|||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
use Symfony\Component\DependencyInjection\Parameter;
|
use Symfony\Component\DependencyInjection\Parameter;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
@ -298,6 +299,9 @@ class XmlDumper extends Dumper
|
|||||||
if (is_array($value)) {
|
if (is_array($value)) {
|
||||||
$element->setAttribute('type', 'collection');
|
$element->setAttribute('type', 'collection');
|
||||||
$this->convertParameters($value, $type, $element, 'key');
|
$this->convertParameters($value, $type, $element, 'key');
|
||||||
|
} elseif ($value instanceof TaggedIteratorArgument) {
|
||||||
|
$element->setAttribute('type', 'tagged');
|
||||||
|
$element->setAttribute('tag', $value->getTag());
|
||||||
} elseif ($value instanceof IteratorArgument) {
|
} elseif ($value instanceof IteratorArgument) {
|
||||||
$element->setAttribute('type', 'iterator');
|
$element->setAttribute('type', 'iterator');
|
||||||
$this->convertParameters($value->getValues(), $type, $element, 'key');
|
$this->convertParameters($value->getValues(), $type, $element, 'key');
|
||||||
|
@ -19,6 +19,7 @@ use Symfony\Component\DependencyInjection\Alias;
|
|||||||
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
|
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
use Symfony\Component\DependencyInjection\Parameter;
|
use Symfony\Component\DependencyInjection\Parameter;
|
||||||
@ -263,6 +264,9 @@ class YamlDumper extends Dumper
|
|||||||
$value = $value->getValues()[0];
|
$value = $value->getValues()[0];
|
||||||
}
|
}
|
||||||
if ($value instanceof ArgumentInterface) {
|
if ($value instanceof ArgumentInterface) {
|
||||||
|
if ($value instanceof TaggedIteratorArgument) {
|
||||||
|
return new TaggedValue('tagged', $value->getTag());
|
||||||
|
}
|
||||||
if ($value instanceof IteratorArgument) {
|
if ($value instanceof IteratorArgument) {
|
||||||
$tag = 'iterator';
|
$tag = 'iterator';
|
||||||
} else {
|
} else {
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Definition;
|
use Symfony\Component\DependencyInjection\Definition;
|
||||||
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
|
||||||
@ -115,6 +116,18 @@ function iterator(array $values)
|
|||||||
return new IteratorArgument(AbstractConfigurator::processValue($values, true));
|
return new IteratorArgument(AbstractConfigurator::processValue($values, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a lazy iterator by tag name.
|
||||||
|
*
|
||||||
|
* @param string $tag
|
||||||
|
*
|
||||||
|
* @return TaggedIteratorArgument
|
||||||
|
*/
|
||||||
|
function tagged($tag)
|
||||||
|
{
|
||||||
|
return new TaggedIteratorArgument($tag);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an expression.
|
* Creates an expression.
|
||||||
*
|
*
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
namespace Symfony\Component\DependencyInjection\Loader;
|
namespace Symfony\Component\DependencyInjection\Loader;
|
||||||
|
|
||||||
use Symfony\Component\Config\Util\XmlUtils;
|
use Symfony\Component\Config\Util\XmlUtils;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
use Symfony\Component\DependencyInjection\Alias;
|
use Symfony\Component\DependencyInjection\Alias;
|
||||||
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
|
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
|
||||||
@ -518,6 +519,12 @@ class XmlFileLoader extends FileLoader
|
|||||||
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="iterator" only accepts collections of type="service" references in "%s".', $name, $file));
|
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="iterator" only accepts collections of type="service" references in "%s".', $name, $file));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 'tagged':
|
||||||
|
if (!$arg->getAttribute('tag')) {
|
||||||
|
throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="tagged" has no or empty "tag" attribute in "%s".', $name, $file));
|
||||||
|
}
|
||||||
|
$arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag'));
|
||||||
|
break;
|
||||||
case 'string':
|
case 'string':
|
||||||
$arguments[$key] = $arg->nodeValue;
|
$arguments[$key] = $arg->nodeValue;
|
||||||
break;
|
break;
|
||||||
|
@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\Alias;
|
|||||||
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
|
use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
|
||||||
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
|
use Symfony\Component\DependencyInjection\Argument\BoundArgument;
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
|
||||||
use Symfony\Component\DependencyInjection\ChildDefinition;
|
use Symfony\Component\DependencyInjection\ChildDefinition;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
@ -726,6 +727,13 @@ class YamlFileLoader extends FileLoader
|
|||||||
throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts arrays of "@service" references in "%s".', $file));
|
throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts arrays of "@service" references in "%s".', $file));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ('tagged' === $value->getTag()) {
|
||||||
|
if (!is_string($argument) || !$argument) {
|
||||||
|
throw new InvalidArgumentException(sprintf('"!tagged" tag only accepts non empty string in "%s".', $file));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TaggedIteratorArgument($argument);
|
||||||
|
}
|
||||||
if ('service' === $value->getTag()) {
|
if ('service' === $value->getTag()) {
|
||||||
if ($isParameter) {
|
if ($isParameter) {
|
||||||
throw new InvalidArgumentException(sprintf('Using an anonymous service in a parameter is not allowed in "%s".', $file));
|
throw new InvalidArgumentException(sprintf('Using an anonymous service in a parameter is not allowed in "%s".', $file));
|
||||||
|
@ -208,6 +208,7 @@
|
|||||||
<xsd:attribute name="name" type="xsd:string" />
|
<xsd:attribute name="name" type="xsd:string" />
|
||||||
<xsd:attribute name="on-invalid" type="invalid_sequence" />
|
<xsd:attribute name="on-invalid" type="invalid_sequence" />
|
||||||
<xsd:attribute name="strict" type="boolean" />
|
<xsd:attribute name="strict" type="boolean" />
|
||||||
|
<xsd:attribute name="tag" type="xsd:string" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
<xsd:complexType name="bind" mixed="true">
|
<xsd:complexType name="bind" mixed="true">
|
||||||
@ -233,6 +234,7 @@
|
|||||||
<xsd:attribute name="index" type="xsd:integer" />
|
<xsd:attribute name="index" type="xsd:integer" />
|
||||||
<xsd:attribute name="on-invalid" type="invalid_sequence" />
|
<xsd:attribute name="on-invalid" type="invalid_sequence" />
|
||||||
<xsd:attribute name="strict" type="boolean" />
|
<xsd:attribute name="strict" type="boolean" />
|
||||||
|
<xsd:attribute name="tag" type="xsd:string" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
<xsd:complexType name="call">
|
<xsd:complexType name="call">
|
||||||
@ -258,6 +260,7 @@
|
|||||||
<xsd:enumeration value="string" />
|
<xsd:enumeration value="string" />
|
||||||
<xsd:enumeration value="constant" />
|
<xsd:enumeration value="constant" />
|
||||||
<xsd:enumeration value="iterator" />
|
<xsd:enumeration value="iterator" />
|
||||||
|
<xsd:enumeration value="tagged" />
|
||||||
</xsd:restriction>
|
</xsd:restriction>
|
||||||
</xsd:simpleType>
|
</xsd:simpleType>
|
||||||
|
|
||||||
|
@ -0,0 +1,40 @@
|
|||||||
|
<?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\Argument\TaggedIteratorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Compiler\ResolveTaggedIteratorArgumentPass;
|
||||||
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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', array('priority' => 20));
|
||||||
|
$container->register('c', 'stdClass')->addTag('foo', array('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(array(new Reference('b'), new Reference('c'), new Reference('a')));
|
||||||
|
$this->assertEquals($expected, $properties['foos']);
|
||||||
|
}
|
||||||
|
}
|
@ -5,9 +5,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
|||||||
use App\BarService;
|
use App\BarService;
|
||||||
|
|
||||||
return function (ContainerConfigurator $c) {
|
return function (ContainerConfigurator $c) {
|
||||||
|
|
||||||
$s = $c->services();
|
$s = $c->services();
|
||||||
$s->set(BarService::class)
|
$s->set(BarService::class)
|
||||||
->args(array(inline('FooClass')));
|
->args(array(inline('FooClass')));
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,6 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
|||||||
use App\BarService;
|
use App\BarService;
|
||||||
|
|
||||||
return function (ContainerConfigurator $c) {
|
return function (ContainerConfigurator $c) {
|
||||||
|
|
||||||
$c->services()
|
$c->services()
|
||||||
->set('bar', 'Class1')
|
->set('bar', 'Class1')
|
||||||
->set(BarService::class)
|
->set(BarService::class)
|
||||||
@ -20,5 +19,4 @@ return function (ContainerConfigurator $c) {
|
|||||||
->parent('bar')
|
->parent('bar')
|
||||||
->parent(BarService::class)
|
->parent(BarService::class)
|
||||||
;
|
;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,6 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
|||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo;
|
||||||
|
|
||||||
return function (ContainerConfigurator $c) {
|
return function (ContainerConfigurator $c) {
|
||||||
|
|
||||||
$c->import('basic.php');
|
$c->import('basic.php');
|
||||||
|
|
||||||
$s = $c->services()->defaults()
|
$s = $c->services()->defaults()
|
||||||
@ -19,5 +18,4 @@ return function (ContainerConfigurator $c) {
|
|||||||
|
|
||||||
$s->set(Foo::class)->args(array(ref('bar')))->public();
|
$s->set(Foo::class)->args(array(ref('bar')))->public();
|
||||||
$s->set('bar', Foo::class)->call('setFoo')->autoconfigure(false);
|
$s->set('bar', Foo::class)->call('setFoo')->autoconfigure(false);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -6,7 +6,6 @@ use App\FooService;
|
|||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
|
||||||
|
|
||||||
return function (ContainerConfigurator $c) {
|
return function (ContainerConfigurator $c) {
|
||||||
|
|
||||||
$s = $c->services();
|
$s = $c->services();
|
||||||
$s->instanceof(Prototype\Foo::class)
|
$s->instanceof(Prototype\Foo::class)
|
||||||
->property('p', 0)
|
->property('p', 0)
|
||||||
@ -20,5 +19,4 @@ return function (ContainerConfigurator $c) {
|
|||||||
$s->load(Prototype::class.'\\', '../Prototype')->exclude('../Prototype/*/*');
|
$s->load(Prototype::class.'\\', '../Prototype')->exclude('../Prototype/*/*');
|
||||||
|
|
||||||
$s->set('foo', FooService::class);
|
$s->set('foo', FooService::class);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,6 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
|||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo;
|
||||||
|
|
||||||
return function (ContainerConfigurator $c) {
|
return function (ContainerConfigurator $c) {
|
||||||
|
|
||||||
$c->parameters()
|
$c->parameters()
|
||||||
('foo', 'Foo')
|
('foo', 'Foo')
|
||||||
('bar', 'Bar')
|
('bar', 'Bar')
|
||||||
@ -17,5 +16,4 @@ return function (ContainerConfigurator $c) {
|
|||||||
('bar', Foo::class)
|
('bar', Foo::class)
|
||||||
->call('setFoo')
|
->call('setFoo')
|
||||||
;
|
;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,6 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator;
|
|||||||
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
|
use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype;
|
||||||
|
|
||||||
return function (ContainerConfigurator $c) {
|
return function (ContainerConfigurator $c) {
|
||||||
|
|
||||||
$di = $c->services()->defaults()
|
$di = $c->services()->defaults()
|
||||||
->tag('baz');
|
->tag('baz');
|
||||||
$di->load(Prototype::class.'\\', '../Prototype')
|
$di->load(Prototype::class.'\\', '../Prototype')
|
||||||
@ -20,5 +19,4 @@ return function (ContainerConfigurator $c) {
|
|||||||
->parent('foo');
|
->parent('foo');
|
||||||
$di->set('foo')->lazy()->abstract();
|
$di->set('foo')->lazy()->abstract();
|
||||||
$di->get(Prototype\Foo::class)->lazy(false);
|
$di->get(Prototype\Foo::class)->lazy(false);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,6 @@ require_once __DIR__.'/../includes/classes.php';
|
|||||||
require_once __DIR__.'/../includes/foo.php';
|
require_once __DIR__.'/../includes/foo.php';
|
||||||
|
|
||||||
return function (ContainerConfigurator $c) {
|
return function (ContainerConfigurator $c) {
|
||||||
|
|
||||||
$p = $c->parameters();
|
$p = $c->parameters();
|
||||||
$p->set('baz_class', 'BazClass');
|
$p->set('baz_class', 'BazClass');
|
||||||
$p->set('foo_class', FooClass::class)
|
$p->set('foo_class', FooClass::class)
|
||||||
@ -119,4 +118,11 @@ return function (ContainerConfigurator $c) {
|
|||||||
$s->set('lazy_context_ignore_invalid_ref', 'LazyContext')
|
$s->set('lazy_context_ignore_invalid_ref', 'LazyContext')
|
||||||
->args(array(iterator(array(ref('foo.baz'), ref('invalid')->ignoreOnInvalid())), iterator(array())));
|
->args(array(iterator(array(ref('foo.baz'), ref('invalid')->ignoreOnInvalid())), iterator(array())));
|
||||||
|
|
||||||
|
$s->set('tagged_iterator_foo', 'Bar')
|
||||||
|
->private()
|
||||||
|
->tag('foo');
|
||||||
|
|
||||||
|
$s->set('tagged_iterator', 'Bar')
|
||||||
|
->public()
|
||||||
|
->args(array(tagged('foo')));
|
||||||
};
|
};
|
||||||
|
@ -4,6 +4,7 @@ require_once __DIR__.'/../includes/classes.php';
|
|||||||
require_once __DIR__.'/../includes/foo.php';
|
require_once __DIR__.'/../includes/foo.php';
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument;
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||||
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
use Symfony\Component\DependencyInjection\ContainerBuilder;
|
||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
@ -161,5 +162,15 @@ $container
|
|||||||
->setArguments(array(new IteratorArgument(array(new Reference('foo.baz'), new Reference('invalid', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))), new IteratorArgument(array())))
|
->setArguments(array(new IteratorArgument(array(new Reference('foo.baz'), new Reference('invalid', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))), new IteratorArgument(array())))
|
||||||
->setPublic(true)
|
->setPublic(true)
|
||||||
;
|
;
|
||||||
|
$container
|
||||||
|
->register('tagged_iterator_foo', 'Bar')
|
||||||
|
->addTag('foo')
|
||||||
|
->setPublic(false)
|
||||||
|
;
|
||||||
|
$container
|
||||||
|
->register('tagged_iterator', 'Bar')
|
||||||
|
->addArgument(new TaggedIteratorArgument('foo'))
|
||||||
|
->setPublic(true)
|
||||||
|
;
|
||||||
|
|
||||||
return $container;
|
return $container;
|
||||||
|
@ -29,6 +29,8 @@ digraph sc {
|
|||||||
node_factory_service_simple [label="factory_service_simple\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
|
node_factory_service_simple [label="factory_service_simple\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
|
||||||
node_lazy_context [label="lazy_context\nLazyContext\n", shape=record, fillcolor="#eeeeee", style="filled"];
|
node_lazy_context [label="lazy_context\nLazyContext\n", shape=record, fillcolor="#eeeeee", style="filled"];
|
||||||
node_lazy_context_ignore_invalid_ref [label="lazy_context_ignore_invalid_ref\nLazyContext\n", shape=record, fillcolor="#eeeeee", style="filled"];
|
node_lazy_context_ignore_invalid_ref [label="lazy_context_ignore_invalid_ref\nLazyContext\n", shape=record, fillcolor="#eeeeee", style="filled"];
|
||||||
|
node_tagged_iterator_foo [label="tagged_iterator_foo\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
|
||||||
|
node_tagged_iterator [label="tagged_iterator\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
|
||||||
node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"];
|
node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"];
|
||||||
node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"];
|
node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"];
|
||||||
node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"];
|
node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"];
|
||||||
|
@ -56,6 +56,8 @@ class ProjectServiceContainer extends Container
|
|||||||
'new_factory' => 'getNewFactoryService',
|
'new_factory' => 'getNewFactoryService',
|
||||||
'new_factory_service' => 'getNewFactoryServiceService',
|
'new_factory_service' => 'getNewFactoryServiceService',
|
||||||
'service_from_static_method' => 'getServiceFromStaticMethodService',
|
'service_from_static_method' => 'getServiceFromStaticMethodService',
|
||||||
|
'tagged_iterator' => 'getTaggedIteratorService',
|
||||||
|
'tagged_iterator_foo' => 'getTaggedIteratorFooService',
|
||||||
);
|
);
|
||||||
$this->privates = array(
|
$this->privates = array(
|
||||||
'configurator_service' => true,
|
'configurator_service' => true,
|
||||||
@ -63,6 +65,7 @@ class ProjectServiceContainer extends Container
|
|||||||
'factory_simple' => true,
|
'factory_simple' => true,
|
||||||
'inlined' => true,
|
'inlined' => true,
|
||||||
'new_factory' => true,
|
'new_factory' => true,
|
||||||
|
'tagged_iterator_foo' => true,
|
||||||
);
|
);
|
||||||
$this->aliases = array(
|
$this->aliases = array(
|
||||||
'Psr\\Container\\ContainerInterface' => 'service_container',
|
'Psr\\Container\\ContainerInterface' => 'service_container',
|
||||||
@ -337,6 +340,18 @@ class ProjectServiceContainer extends Container
|
|||||||
return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance();
|
return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the public 'tagged_iterator' shared service.
|
||||||
|
*
|
||||||
|
* @return \Bar
|
||||||
|
*/
|
||||||
|
protected function getTaggedIteratorService()
|
||||||
|
{
|
||||||
|
return $this->services['tagged_iterator'] = new \Bar(new RewindableGenerator(function () {
|
||||||
|
return new \EmptyIterator();
|
||||||
|
}, 0));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the private 'configurator_service' shared service.
|
* Gets the private 'configurator_service' shared service.
|
||||||
*
|
*
|
||||||
@ -404,6 +419,16 @@ class ProjectServiceContainer extends Container
|
|||||||
return $instance;
|
return $instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the private 'tagged_iterator_foo' shared service.
|
||||||
|
*
|
||||||
|
* @return \Bar
|
||||||
|
*/
|
||||||
|
protected function getTaggedIteratorFooService()
|
||||||
|
{
|
||||||
|
return $this->services['tagged_iterator_foo'] = new \Bar();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the default parameters.
|
* Gets the default parameters.
|
||||||
*
|
*
|
||||||
|
@ -235,6 +235,27 @@ use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
|||||||
|
|
||||||
return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance();
|
return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance();
|
||||||
|
|
||||||
|
[Container%s/getTaggedIteratorService.php] => <?php
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||||
|
|
||||||
|
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
|
||||||
|
// Returns the public 'tagged_iterator' shared service.
|
||||||
|
|
||||||
|
return $this->services['tagged_iterator'] = new \Bar(new RewindableGenerator(function () {
|
||||||
|
yield 0 => ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->load(__DIR__.'/getFooService.php')) && false ?: '_'};
|
||||||
|
yield 1 => ${($_ = isset($this->services['tagged_iterator_foo']) ? $this->services['tagged_iterator_foo'] : $this->services['tagged_iterator_foo'] = new \Bar()) && false ?: '_'};
|
||||||
|
}, 2));
|
||||||
|
|
||||||
|
[Container%s/getTaggedIteratorFooService.php] => <?php
|
||||||
|
|
||||||
|
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||||
|
|
||||||
|
// This file has been auto-generated by the Symfony Dependency Injection Component for internal use.
|
||||||
|
// Returns the private 'tagged_iterator_foo' shared service.
|
||||||
|
|
||||||
|
return $this->services['tagged_iterator_foo'] = new \Bar();
|
||||||
|
|
||||||
[Container%s/Container.php] => <?php
|
[Container%s/Container.php] => <?php
|
||||||
|
|
||||||
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
use Symfony\Component\DependencyInjection\Argument\RewindableGenerator;
|
||||||
@ -292,9 +313,12 @@ class Container%s extends Container
|
|||||||
'method_call1' => __DIR__.'/getMethodCall1Service.php',
|
'method_call1' => __DIR__.'/getMethodCall1Service.php',
|
||||||
'new_factory_service' => __DIR__.'/getNewFactoryServiceService.php',
|
'new_factory_service' => __DIR__.'/getNewFactoryServiceService.php',
|
||||||
'service_from_static_method' => __DIR__.'/getServiceFromStaticMethodService.php',
|
'service_from_static_method' => __DIR__.'/getServiceFromStaticMethodService.php',
|
||||||
|
'tagged_iterator' => __DIR__.'/getTaggedIteratorService.php',
|
||||||
|
'tagged_iterator_foo' => __DIR__.'/getTaggedIteratorFooService.php',
|
||||||
);
|
);
|
||||||
$this->privates = array(
|
$this->privates = array(
|
||||||
'factory_simple' => true,
|
'factory_simple' => true,
|
||||||
|
'tagged_iterator_foo' => true,
|
||||||
);
|
);
|
||||||
$this->aliases = array(
|
$this->aliases = array(
|
||||||
'alias_for_alias' => 'foo',
|
'alias_for_alias' => 'foo',
|
||||||
|
@ -49,9 +49,12 @@ class ProjectServiceContainer extends Container
|
|||||||
'method_call1' => 'getMethodCall1Service',
|
'method_call1' => 'getMethodCall1Service',
|
||||||
'new_factory_service' => 'getNewFactoryServiceService',
|
'new_factory_service' => 'getNewFactoryServiceService',
|
||||||
'service_from_static_method' => 'getServiceFromStaticMethodService',
|
'service_from_static_method' => 'getServiceFromStaticMethodService',
|
||||||
|
'tagged_iterator' => 'getTaggedIteratorService',
|
||||||
|
'tagged_iterator_foo' => 'getTaggedIteratorFooService',
|
||||||
);
|
);
|
||||||
$this->privates = array(
|
$this->privates = array(
|
||||||
'factory_simple' => true,
|
'factory_simple' => true,
|
||||||
|
'tagged_iterator_foo' => true,
|
||||||
);
|
);
|
||||||
$this->aliases = array(
|
$this->aliases = array(
|
||||||
'alias_for_alias' => 'foo',
|
'alias_for_alias' => 'foo',
|
||||||
@ -339,6 +342,19 @@ class ProjectServiceContainer extends Container
|
|||||||
return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance();
|
return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the public 'tagged_iterator' shared service.
|
||||||
|
*
|
||||||
|
* @return \Bar
|
||||||
|
*/
|
||||||
|
protected function getTaggedIteratorService()
|
||||||
|
{
|
||||||
|
return $this->services['tagged_iterator'] = new \Bar(new RewindableGenerator(function () {
|
||||||
|
yield 0 => ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->getFooService()) && false ?: '_'};
|
||||||
|
yield 1 => ${($_ = isset($this->services['tagged_iterator_foo']) ? $this->services['tagged_iterator_foo'] : $this->services['tagged_iterator_foo'] = new \Bar()) && false ?: '_'};
|
||||||
|
}, 2));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the private 'factory_simple' shared service.
|
* Gets the private 'factory_simple' shared service.
|
||||||
*
|
*
|
||||||
@ -353,6 +369,16 @@ class ProjectServiceContainer extends Container
|
|||||||
return $this->services['factory_simple'] = new \SimpleFactoryClass('foo');
|
return $this->services['factory_simple'] = new \SimpleFactoryClass('foo');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the private 'tagged_iterator_foo' shared service.
|
||||||
|
*
|
||||||
|
* @return \Bar
|
||||||
|
*/
|
||||||
|
protected function getTaggedIteratorFooService()
|
||||||
|
{
|
||||||
|
return $this->services['tagged_iterator_foo'] = new \Bar();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
|
@ -133,6 +133,12 @@
|
|||||||
</argument>
|
</argument>
|
||||||
<argument type="iterator"/>
|
<argument type="iterator"/>
|
||||||
</service>
|
</service>
|
||||||
|
<service id="tagged_iterator_foo" class="Bar" public="false">
|
||||||
|
<tag name="foo"/>
|
||||||
|
</service>
|
||||||
|
<service id="tagged_iterator" class="Bar" public="true">
|
||||||
|
<argument type="tagged" tag="foo"/>
|
||||||
|
</service>
|
||||||
<service id="Psr\Container\ContainerInterface" alias="service_container" public="false"/>
|
<service id="Psr\Container\ContainerInterface" alias="service_container" public="false"/>
|
||||||
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container" public="false"/>
|
<service id="Symfony\Component\DependencyInjection\ContainerInterface" alias="service_container" public="false"/>
|
||||||
<service id="alias_for_foo" alias="foo" public="true"/>
|
<service id="alias_for_foo" alias="foo" public="true"/>
|
||||||
|
@ -145,6 +145,16 @@ services:
|
|||||||
alias_for_alias:
|
alias_for_alias:
|
||||||
alias: 'foo'
|
alias: 'foo'
|
||||||
public: true
|
public: true
|
||||||
|
tagged_iterator_foo:
|
||||||
|
class: Bar
|
||||||
|
tags:
|
||||||
|
- { name: foo }
|
||||||
|
public: false
|
||||||
|
tagged_iterator:
|
||||||
|
class: Bar
|
||||||
|
arguments:
|
||||||
|
- !tagged foo
|
||||||
|
public: true
|
||||||
Psr\Container\ContainerInterface:
|
Psr\Container\ContainerInterface:
|
||||||
alias: service_container
|
alias: service_container
|
||||||
public: false
|
public: false
|
||||||
|
@ -774,8 +774,8 @@ class Inline
|
|||||||
$nextOffset += strspn($value, ' ', $nextOffset);
|
$nextOffset += strspn($value, ' ', $nextOffset);
|
||||||
|
|
||||||
// Is followed by a scalar
|
// Is followed by a scalar
|
||||||
if (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) {
|
if ((!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) && 'tagged' !== $tag) {
|
||||||
// Manage scalars in {@link self::evaluateScalar()}
|
// Manage non-whitelisted scalars in {@link self::evaluateScalar()}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,6 +698,8 @@ class Parser
|
|||||||
if ('' !== $matches['tag']) {
|
if ('' !== $matches['tag']) {
|
||||||
if ('!!binary' === $matches['tag']) {
|
if ('!!binary' === $matches['tag']) {
|
||||||
return Inline::evaluateBinaryScalar($data);
|
return Inline::evaluateBinaryScalar($data);
|
||||||
|
} elseif ('tagged' === $matches['tag']) {
|
||||||
|
return new TaggedValue(substr($matches['tag'], 1), $data);
|
||||||
} elseif ('!' !== $matches['tag']) {
|
} elseif ('!' !== $matches['tag']) {
|
||||||
@trigger_error(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since version 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class), E_USER_DEPRECATED);
|
@trigger_error(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since version 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class), E_USER_DEPRECATED);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user