Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\DependencyInjection\Compiler; Chris@0: Chris@0: use Symfony\Component\DependencyInjection\ContainerBuilder; Chris@0: use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; Chris@0: use Symfony\Component\DependencyInjection\Reference; Chris@0: Chris@0: /** Chris@0: * Replaces aliases with actual service definitions, effectively removing these Chris@0: * aliases. Chris@0: * Chris@0: * @author Johannes M. Schmitt Chris@0: */ Chris@14: class ReplaceAliasByActualDefinitionPass extends AbstractRecursivePass Chris@0: { Chris@14: private $replacements; Chris@0: Chris@0: /** Chris@0: * Process the Container to replace aliases with service definitions. Chris@0: * Chris@0: * @throws InvalidArgumentException if the service definition does not exist Chris@0: */ Chris@0: public function process(ContainerBuilder $container) Chris@0: { Chris@0: // First collect all alias targets that need to be replaced Chris@17: $seenAliasTargets = []; Chris@17: $replacements = []; Chris@0: foreach ($container->getAliases() as $definitionId => $target) { Chris@14: $targetId = $container->normalizeId($target); Chris@0: // Special case: leave this target alone Chris@0: if ('service_container' === $targetId) { Chris@0: continue; Chris@0: } Chris@0: // Check if target needs to be replaces Chris@0: if (isset($replacements[$targetId])) { Chris@14: $container->setAlias($definitionId, $replacements[$targetId])->setPublic($target->isPublic())->setPrivate($target->isPrivate()); Chris@0: } Chris@0: // No need to process the same target twice Chris@0: if (isset($seenAliasTargets[$targetId])) { Chris@0: continue; Chris@0: } Chris@0: // Process new target Chris@0: $seenAliasTargets[$targetId] = true; Chris@0: try { Chris@0: $definition = $container->getDefinition($targetId); Chris@0: } catch (InvalidArgumentException $e) { Chris@0: throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $definitionId, $targetId), null, $e); Chris@0: } Chris@14: if ($definition->isPublic() || $definition->isPrivate()) { Chris@0: continue; Chris@0: } Chris@0: // Remove private definition and schedule for replacement Chris@14: $definition->setPublic(!$target->isPrivate()); Chris@14: $definition->setPrivate($target->isPrivate()); Chris@0: $container->setDefinition($definitionId, $definition); Chris@0: $container->removeDefinition($targetId); Chris@0: $replacements[$targetId] = $definitionId; Chris@0: } Chris@14: $this->replacements = $replacements; Chris@0: Chris@14: parent::process($container); Chris@17: $this->replacements = []; Chris@0: } Chris@0: Chris@0: /** Chris@14: * {@inheritdoc} Chris@0: */ Chris@14: protected function processValue($value, $isRoot = false) Chris@0: { Chris@14: if ($value instanceof Reference && isset($this->replacements[$referenceId = $this->container->normalizeId($value)])) { Chris@0: // Perform the replacement Chris@14: $newId = $this->replacements[$referenceId]; Chris@14: $value = new Reference($newId, $value->getInvalidBehavior()); Chris@14: $this->container->log($this, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $this->currentId, $referenceId, $newId)); Chris@0: } Chris@0: Chris@14: return parent::processValue($value, $isRoot); Chris@0: } Chris@0: }