[DependencyInjection] added a simple way to replace a service by keeping a reference to the old one

This commit is contained in:
Fabien Potencier 2013-09-12 12:15:48 +02:00 committed by Romain Neutron
parent 58bed5d200
commit 1eb1f4dd73
4 changed files with 86 additions and 0 deletions

View File

@ -1,6 +1,11 @@
CHANGELOG
=========
2.5.0
-----
* added DecoratorServicePass and a way to override a service definition (Definition::setDecoratedService())
2.4.0
-----

View File

@ -0,0 +1,54 @@
<?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\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Alias;
/**
* Overwrites a service but keeps the overridden one.
*
* @author Christophe Coevoet <stof@notk.org>
* @author Fabien Potencier <fabien@symfony.com>
*/
class DecoratorServicePass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
foreach ($container->getDefinitions() as $id => $definition) {
if (!$decorated = $definition->getDecoratedService()) {
continue;
}
list ($decorated, $renamedId) = $decorated;
if (!$renamedId) {
$renamedId = $id.'.inner';
}
// we create a new alias/service for the service we are replacing
// to be able to reference it in the new one
if ($container->hasAlias($decorated)) {
$alias = $container->getAlias($decorated);
$public = $alias->isPublic();
$container->setAlias($renamedId, new Alias((string) $alias, false));
} else {
$definition = $container->getDefinition($decorated);
$public = $definition->isPublic();
$definition->setPublic(false);
$container->setDefinition($renamedId, $definition);
}
$container->setAlias($decorated, new Alias($id, $public));
}
}
}

View File

@ -46,6 +46,7 @@ class PassConfig
$this->optimizationPasses = array(
new ResolveDefinitionTemplatesPass(),
new DecoratorServicePass(),
new ResolveParameterPlaceHoldersPass(),
new CheckDefinitionValidityPass(),
new ResolveReferencesToAliasesPass(),

View File

@ -38,6 +38,7 @@ class Definition
private $abstract = false;
private $synchronized = false;
private $lazy = false;
private $decoratedService;
protected $arguments;
@ -100,6 +101,31 @@ class Definition
return $this;
}
/**
* Sets the service that this service is decorating.
*
* @param string $id The decorated service id
* @param string $renamedId The new decorated service id
*/
public function setDecoratedService($id, $renamedId = null)
{
if ($renamedId && $id == $renamedId) {
throw new \LogicException(sprintf('The decorated service parent name for "%s" must be different than the service name itself.', $id));
}
$this->decoratedService = array($id, $renamedId);
}
/**
* Gets the service that decorates this service.
*
* @return array An array composed of the decorated service id and the new id for it
*/
public function getDecoratedService()
{
return $this->decoratedService;
}
/**
* Gets the factory method.
*