Added a way to define the priority of service decoration
This commit is contained in:
parent
2655072bfd
commit
75c98cba03
@ -8,6 +8,7 @@ CHANGELOG
|
|||||||
* deprecated the concept of scopes
|
* deprecated the concept of scopes
|
||||||
* added `Definition::setShared()` and `Definition::isShared()`
|
* added `Definition::setShared()` and `Definition::isShared()`
|
||||||
* added ResettableContainerInterface to be able to reset the container to release memory on shutdown
|
* added ResettableContainerInterface to be able to reset the container to release memory on shutdown
|
||||||
|
* added a way to define the priority of service decoration
|
||||||
|
|
||||||
2.7.0
|
2.7.0
|
||||||
-----
|
-----
|
||||||
|
@ -19,18 +19,28 @@ use Symfony\Component\DependencyInjection\Alias;
|
|||||||
*
|
*
|
||||||
* @author Christophe Coevoet <stof@notk.org>
|
* @author Christophe Coevoet <stof@notk.org>
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
|
* @author Diego Saint Esteben <diego@saintesteben.me>
|
||||||
*/
|
*/
|
||||||
class DecoratorServicePass implements CompilerPassInterface
|
class DecoratorServicePass implements CompilerPassInterface
|
||||||
{
|
{
|
||||||
public function process(ContainerBuilder $container)
|
public function process(ContainerBuilder $container)
|
||||||
{
|
{
|
||||||
|
$definitions = new \SplPriorityQueue();
|
||||||
|
$order = PHP_INT_MAX;
|
||||||
|
|
||||||
foreach ($container->getDefinitions() as $id => $definition) {
|
foreach ($container->getDefinitions() as $id => $definition) {
|
||||||
if (!$decorated = $definition->getDecoratedService()) {
|
if (!$decorated = $definition->getDecoratedService()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
$definitions->insert(array($id, $definition), array($decorated[2], --$order));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($definitions as $arr) {
|
||||||
|
list($id, $definition) = $arr;
|
||||||
|
list($inner, $renamedId) = $definition->getDecoratedService();
|
||||||
|
|
||||||
$definition->setDecoratedService(null);
|
$definition->setDecoratedService(null);
|
||||||
|
|
||||||
list($inner, $renamedId) = $decorated;
|
|
||||||
if (!$renamedId) {
|
if (!$renamedId) {
|
||||||
$renamedId = $id.'.inner';
|
$renamedId = $id.'.inner';
|
||||||
}
|
}
|
||||||
|
@ -150,12 +150,13 @@ class Definition
|
|||||||
*
|
*
|
||||||
* @param null|string $id The decorated service id, use null to remove decoration
|
* @param null|string $id The decorated service id, use null to remove decoration
|
||||||
* @param null|string $renamedId The new decorated service id
|
* @param null|string $renamedId The new decorated service id
|
||||||
|
* @param int $priority The priority of decoration
|
||||||
*
|
*
|
||||||
* @return Definition The current instance
|
* @return Definition The current instance
|
||||||
*
|
*
|
||||||
* @throws InvalidArgumentException In case the decorated service id and the new decorated service id are equals.
|
* @throws InvalidArgumentException In case the decorated service id and the new decorated service id are equals.
|
||||||
*/
|
*/
|
||||||
public function setDecoratedService($id, $renamedId = null)
|
public function setDecoratedService($id, $renamedId = null, $priority = 0)
|
||||||
{
|
{
|
||||||
if ($renamedId && $id == $renamedId) {
|
if ($renamedId && $id == $renamedId) {
|
||||||
throw new \InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id));
|
throw new \InvalidArgumentException(sprintf('The decorated service inner name for "%s" must be different than the service name itself.', $id));
|
||||||
@ -164,7 +165,7 @@ class Definition
|
|||||||
if (null === $id) {
|
if (null === $id) {
|
||||||
$this->decoratedService = null;
|
$this->decoratedService = null;
|
||||||
} else {
|
} else {
|
||||||
$this->decoratedService = array($id, $renamedId);
|
$this->decoratedService = array($id, $renamedId, (int) $priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
@ -173,7 +174,7 @@ class Definition
|
|||||||
/**
|
/**
|
||||||
* Gets the service that decorates this service.
|
* Gets the service that decorates this service.
|
||||||
*
|
*
|
||||||
* @return null|array An array composed of the decorated service id and the new id for it, null if no service is decorated
|
* @return null|array An array composed of the decorated service id, the new id for it and the priority of decoration, null if no service is decorated
|
||||||
*/
|
*/
|
||||||
public function getDecoratedService()
|
public function getDecoratedService()
|
||||||
{
|
{
|
||||||
|
@ -173,11 +173,11 @@ class DefinitionDecorator extends Definition
|
|||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritdoc}
|
||||||
*/
|
*/
|
||||||
public function setDecoratedService($id, $renamedId = null)
|
public function setDecoratedService($id, $renamedId = null, $priority = 0)
|
||||||
{
|
{
|
||||||
$this->changes['decorated_service'] = true;
|
$this->changes['decorated_service'] = true;
|
||||||
|
|
||||||
return parent::setDecoratedService($id, $renamedId);
|
return parent::setDecoratedService($id, $renamedId, $priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -145,11 +145,14 @@ class XmlDumper extends Dumper
|
|||||||
$service->setAttribute('lazy', 'true');
|
$service->setAttribute('lazy', 'true');
|
||||||
}
|
}
|
||||||
if (null !== $decorated = $definition->getDecoratedService()) {
|
if (null !== $decorated = $definition->getDecoratedService()) {
|
||||||
list($decorated, $renamedId) = $decorated;
|
list($decorated, $renamedId, $priority) = $decorated;
|
||||||
$service->setAttribute('decorates', $decorated);
|
$service->setAttribute('decorates', $decorated);
|
||||||
if (null !== $renamedId) {
|
if (null !== $renamedId) {
|
||||||
$service->setAttribute('decoration-inner-name', $renamedId);
|
$service->setAttribute('decoration-inner-name', $renamedId);
|
||||||
}
|
}
|
||||||
|
if (0 !== $priority) {
|
||||||
|
$service->setAttribute('decoration-priority', $priority);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($definition->getTags() as $name => $tags) {
|
foreach ($definition->getTags() as $name => $tags) {
|
||||||
|
@ -137,11 +137,14 @@ class YamlDumper extends Dumper
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (null !== $decorated = $definition->getDecoratedService()) {
|
if (null !== $decorated = $definition->getDecoratedService()) {
|
||||||
list($decorated, $renamedId) = $decorated;
|
list($decorated, $renamedId, $priority) = $decorated;
|
||||||
$code .= sprintf(" decorates: %s\n", $decorated);
|
$code .= sprintf(" decorates: %s\n", $decorated);
|
||||||
if (null !== $renamedId) {
|
if (null !== $renamedId) {
|
||||||
$code .= sprintf(" decoration_inner_name: %s\n", $renamedId);
|
$code .= sprintf(" decoration_inner_name: %s\n", $renamedId);
|
||||||
}
|
}
|
||||||
|
if (0 !== $priority) {
|
||||||
|
$code .= sprintf(" decoration_priority: %s\n", $priority);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($callable = $definition->getFactory()) {
|
if ($callable = $definition->getFactory()) {
|
||||||
|
@ -245,7 +245,8 @@ class XmlFileLoader extends FileLoader
|
|||||||
|
|
||||||
if ($value = $service->getAttribute('decorates')) {
|
if ($value = $service->getAttribute('decorates')) {
|
||||||
$renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null;
|
$renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null;
|
||||||
$definition->setDecoratedService($value, $renameId);
|
$priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0;
|
||||||
|
$definition->setDecoratedService($value, $renameId, $priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $definition;
|
return $definition;
|
||||||
|
@ -290,7 +290,8 @@ class YamlFileLoader extends FileLoader
|
|||||||
|
|
||||||
if (isset($service['decorates'])) {
|
if (isset($service['decorates'])) {
|
||||||
$renameId = isset($service['decoration_inner_name']) ? $service['decoration_inner_name'] : null;
|
$renameId = isset($service['decoration_inner_name']) ? $service['decoration_inner_name'] : null;
|
||||||
$definition->setDecoratedService($service['decorates'], $renameId);
|
$priority = isset($service['decoration_priority']) ? $service['decoration_priority'] : 0;
|
||||||
|
$definition->setDecoratedService($service['decorates'], $renameId, $priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->container->setDefinition($id, $definition);
|
$this->container->setDefinition($id, $definition);
|
||||||
|
@ -101,6 +101,7 @@
|
|||||||
<xsd:attribute name="parent" type="xsd:string" />
|
<xsd:attribute name="parent" type="xsd:string" />
|
||||||
<xsd:attribute name="decorates" type="xsd:string" />
|
<xsd:attribute name="decorates" type="xsd:string" />
|
||||||
<xsd:attribute name="decoration-inner-name" type="xsd:string" />
|
<xsd:attribute name="decoration-inner-name" type="xsd:string" />
|
||||||
|
<xsd:attribute name="decoration-priority" type="xsd:integer" />
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
|
||||||
<xsd:complexType name="tag">
|
<xsd:complexType name="tag">
|
||||||
|
@ -73,6 +73,48 @@ class DecoratorServicePassTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertNull($fooExtendedDefinition->getDecoratedService());
|
$this->assertNull($fooExtendedDefinition->getDecoratedService());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testProcessWithPriority()
|
||||||
|
{
|
||||||
|
$container = new ContainerBuilder();
|
||||||
|
$fooDefinition = $container
|
||||||
|
->register('foo')
|
||||||
|
->setPublic(false)
|
||||||
|
;
|
||||||
|
$barDefinition = $container
|
||||||
|
->register('bar')
|
||||||
|
->setPublic(true)
|
||||||
|
->setDecoratedService('foo')
|
||||||
|
;
|
||||||
|
$bazDefinition = $container
|
||||||
|
->register('baz')
|
||||||
|
->setPublic(true)
|
||||||
|
->setDecoratedService('foo', null, 5)
|
||||||
|
;
|
||||||
|
$quxDefinition = $container
|
||||||
|
->register('qux')
|
||||||
|
->setPublic(true)
|
||||||
|
->setDecoratedService('foo', null, 3)
|
||||||
|
;
|
||||||
|
|
||||||
|
$this->process($container);
|
||||||
|
|
||||||
|
$this->assertEquals('bar', $container->getAlias('foo'));
|
||||||
|
$this->assertFalse($container->getAlias('foo')->isPublic());
|
||||||
|
|
||||||
|
$this->assertSame($fooDefinition, $container->getDefinition('baz.inner'));
|
||||||
|
$this->assertFalse($container->getDefinition('baz.inner')->isPublic());
|
||||||
|
|
||||||
|
$this->assertEquals('qux', $container->getAlias('bar.inner'));
|
||||||
|
$this->assertFalse($container->getAlias('bar.inner')->isPublic());
|
||||||
|
|
||||||
|
$this->assertEquals('baz', $container->getAlias('qux.inner'));
|
||||||
|
$this->assertFalse($container->getAlias('qux.inner')->isPublic());
|
||||||
|
|
||||||
|
$this->assertNull($barDefinition->getDecoratedService());
|
||||||
|
$this->assertNull($bazDefinition->getDecoratedService());
|
||||||
|
$this->assertNull($quxDefinition->getDecoratedService());
|
||||||
|
}
|
||||||
|
|
||||||
protected function process(ContainerBuilder $container)
|
protected function process(ContainerBuilder $container)
|
||||||
{
|
{
|
||||||
$repeatedPass = new DecoratorServicePass();
|
$repeatedPass = new DecoratorServicePass();
|
||||||
|
@ -241,7 +241,7 @@ class ResolveDefinitionTemplatesPassTest extends \PHPUnit_Framework_TestCase
|
|||||||
->setDecoratedService('foo', 'foo_inner')
|
->setDecoratedService('foo', 'foo_inner')
|
||||||
;
|
;
|
||||||
|
|
||||||
$this->assertEquals(array('foo', 'foo_inner'), $container->getDefinition('child1')->getDecoratedService());
|
$this->assertEquals(array('foo', 'foo_inner', 0), $container->getDefinition('child1')->getDecoratedService());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function process(ContainerBuilder $container)
|
protected function process(ContainerBuilder $container)
|
||||||
|
@ -56,16 +56,23 @@ class DefinitionTest extends \PHPUnit_Framework_TestCase
|
|||||||
|
|
||||||
public function testSetGetDecoratedService()
|
public function testSetGetDecoratedService()
|
||||||
{
|
{
|
||||||
|
$def = new Definition('stdClass');
|
||||||
|
$this->assertNull($def->getDecoratedService());
|
||||||
|
$def->setDecoratedService('foo', 'foo.renamed', 5);
|
||||||
|
$this->assertEquals(array('foo', 'foo.renamed', 5), $def->getDecoratedService());
|
||||||
|
$def->setDecoratedService(null);
|
||||||
|
$this->assertNull($def->getDecoratedService());
|
||||||
|
|
||||||
$def = new Definition('stdClass');
|
$def = new Definition('stdClass');
|
||||||
$this->assertNull($def->getDecoratedService());
|
$this->assertNull($def->getDecoratedService());
|
||||||
$def->setDecoratedService('foo', 'foo.renamed');
|
$def->setDecoratedService('foo', 'foo.renamed');
|
||||||
$this->assertEquals(array('foo', 'foo.renamed'), $def->getDecoratedService());
|
$this->assertEquals(array('foo', 'foo.renamed', 0), $def->getDecoratedService());
|
||||||
$def->setDecoratedService(null);
|
$def->setDecoratedService(null);
|
||||||
$this->assertNull($def->getDecoratedService());
|
$this->assertNull($def->getDecoratedService());
|
||||||
|
|
||||||
$def = new Definition('stdClass');
|
$def = new Definition('stdClass');
|
||||||
$def->setDecoratedService('foo');
|
$def->setDecoratedService('foo');
|
||||||
$this->assertEquals(array('foo', null), $def->getDecoratedService());
|
$this->assertEquals(array('foo', null, 0), $def->getDecoratedService());
|
||||||
$def->setDecoratedService(null);
|
$def->setDecoratedService(null);
|
||||||
$this->assertNull($def->getDecoratedService());
|
$this->assertNull($def->getDecoratedService());
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@
|
|||||||
<service id="another_alias_for_foo" alias="foo" public="false" />
|
<service id="another_alias_for_foo" alias="foo" public="false" />
|
||||||
<service id="decorator_service" decorates="decorated" />
|
<service id="decorator_service" decorates="decorated" />
|
||||||
<service id="decorator_service_with_name" decorates="decorated" decoration-inner-name="decorated.pif-pouf"/>
|
<service id="decorator_service_with_name" decorates="decorated" decoration-inner-name="decorated.pif-pouf"/>
|
||||||
|
<service id="decorator_service_with_name_and_priority" decorates="decorated" decoration-inner-name="decorated.pif-pouf" decoration-priority="5"/>
|
||||||
<service id="new_factory1" class="FooBarClass">
|
<service id="new_factory1" class="FooBarClass">
|
||||||
<factory function="factory" />
|
<factory function="factory" />
|
||||||
</service>
|
</service>
|
||||||
|
@ -26,6 +26,10 @@ services:
|
|||||||
decorator_service_with_name:
|
decorator_service_with_name:
|
||||||
decorates: decorated
|
decorates: decorated
|
||||||
decoration_inner_name: decorated.pif-pouf
|
decoration_inner_name: decorated.pif-pouf
|
||||||
|
decorator_service_with_name_and_priority:
|
||||||
|
decorates: decorated
|
||||||
|
decoration_inner_name: decorated.pif-pouf
|
||||||
|
decoration_priority: 5
|
||||||
new_factory1: { class: FooBarClass, factory: factory}
|
new_factory1: { class: FooBarClass, factory: factory}
|
||||||
new_factory2: { class: FooBarClass, factory: [@baz, getClass]}
|
new_factory2: { class: FooBarClass, factory: [@baz, getClass]}
|
||||||
new_factory3: { class: FooBarClass, factory: [BazClass, getInstance]}
|
new_factory3: { class: FooBarClass, factory: [BazClass, getInstance]}
|
||||||
|
@ -242,8 +242,9 @@ class XmlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
|
$this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
|
||||||
$this->assertFalse($aliases['another_alias_for_foo']->isPublic());
|
$this->assertFalse($aliases['another_alias_for_foo']->isPublic());
|
||||||
|
|
||||||
$this->assertEquals(array('decorated', null), $services['decorator_service']->getDecoratedService());
|
$this->assertEquals(array('decorated', null, 0), $services['decorator_service']->getDecoratedService());
|
||||||
$this->assertEquals(array('decorated', 'decorated.pif-pouf'), $services['decorator_service_with_name']->getDecoratedService());
|
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 0), $services['decorator_service_with_name']->getDecoratedService());
|
||||||
|
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 5), $services['decorator_service_with_name_and_priority']->getDecoratedService());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testParsesTags()
|
public function testParsesTags()
|
||||||
|
@ -171,8 +171,9 @@ class YamlFileLoaderTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
|
$this->assertEquals('foo', (string) $aliases['another_alias_for_foo']);
|
||||||
$this->assertFalse($aliases['another_alias_for_foo']->isPublic());
|
$this->assertFalse($aliases['another_alias_for_foo']->isPublic());
|
||||||
|
|
||||||
$this->assertEquals(array('decorated', null), $services['decorator_service']->getDecoratedService());
|
$this->assertEquals(array('decorated', null, 0), $services['decorator_service']->getDecoratedService());
|
||||||
$this->assertEquals(array('decorated', 'decorated.pif-pouf'), $services['decorator_service_with_name']->getDecoratedService());
|
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 0), $services['decorator_service_with_name']->getDecoratedService());
|
||||||
|
$this->assertEquals(array('decorated', 'decorated.pif-pouf', 5), $services['decorator_service_with_name_and_priority']->getDecoratedService());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testLoadFactoryShortSyntax()
|
public function testLoadFactoryShortSyntax()
|
||||||
|
Reference in New Issue
Block a user