Navigation Menu

Skip to content

Commit

Permalink
[DependencyInjection] added a simple way to replace a service by keep…
Browse files Browse the repository at this point in the history
…ing a reference to the old one
  • Loading branch information
fabpot authored and romainneutron committed Mar 31, 2014
1 parent 58bed5d commit 1eb1f4d
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 0 deletions.
5 changes: 5 additions & 0 deletions src/Symfony/Component/DependencyInjection/CHANGELOG.md
@@ -1,6 +1,11 @@
CHANGELOG
=========

2.5.0
-----

* added DecoratorServicePass and a way to override a service definition (Definition::setDecoratedService())

2.4.0
-----

Expand Down
@@ -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));
}
}
}
Expand Up @@ -46,6 +46,7 @@ public function __construct()

$this->optimizationPasses = array(
new ResolveDefinitionTemplatesPass(),
new DecoratorServicePass(),
new ResolveParameterPlaceHoldersPass(),
new CheckDefinitionValidityPass(),
new ResolveReferencesToAliasesPass(),
Expand Down
26 changes: 26 additions & 0 deletions src/Symfony/Component/DependencyInjection/Definition.php
Expand Up @@ -38,6 +38,7 @@ class Definition
private $abstract = false;
private $synchronized = false;
private $lazy = false;
private $decoratedService;

protected $arguments;

Expand Down Expand Up @@ -100,6 +101,31 @@ public function setFactoryMethod($factoryMethod)
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.
*
Expand Down

0 comments on commit 1eb1f4d

Please sign in to comment.