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\Alias; Chris@0: use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; Chris@0: use Symfony\Component\DependencyInjection\Reference; Chris@0: use Symfony\Component\DependencyInjection\ContainerBuilder; Chris@0: Chris@0: /** Chris@0: * Replaces all references to aliases with references to the actual service. Chris@0: * Chris@0: * @author Johannes M. Schmitt Chris@0: */ Chris@0: class ResolveReferencesToAliasesPass implements CompilerPassInterface Chris@0: { Chris@0: private $container; Chris@0: Chris@0: /** Chris@0: * Processes the ContainerBuilder to replace references to aliases with actual service references. Chris@0: * Chris@0: * @param ContainerBuilder $container Chris@0: */ Chris@0: public function process(ContainerBuilder $container) Chris@0: { Chris@0: $this->container = $container; Chris@0: Chris@0: foreach ($container->getDefinitions() as $definition) { Chris@0: if ($definition->isSynthetic() || $definition->isAbstract()) { Chris@0: continue; Chris@0: } Chris@0: Chris@0: $definition->setArguments($this->processArguments($definition->getArguments())); Chris@0: $definition->setMethodCalls($this->processArguments($definition->getMethodCalls())); Chris@0: $definition->setProperties($this->processArguments($definition->getProperties())); Chris@0: $definition->setFactory($this->processFactory($definition->getFactory())); Chris@0: } Chris@0: Chris@0: foreach ($container->getAliases() as $id => $alias) { Chris@0: $aliasId = (string) $alias; Chris@0: if ($aliasId !== $defId = $this->getDefinitionId($aliasId)) { Chris@0: $container->setAlias($id, new Alias($defId, $alias->isPublic())); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: /** Chris@0: * Processes the arguments to replace aliases. Chris@0: * Chris@0: * @param array $arguments An array of References Chris@0: * Chris@0: * @return array An array of References Chris@0: */ Chris@0: private function processArguments(array $arguments) Chris@0: { Chris@0: foreach ($arguments as $k => $argument) { Chris@0: if (is_array($argument)) { Chris@0: $arguments[$k] = $this->processArguments($argument); Chris@0: } elseif ($argument instanceof Reference) { Chris@0: $defId = $this->getDefinitionId($id = (string) $argument); Chris@0: Chris@0: if ($defId !== $id) { Chris@0: $arguments[$k] = new Reference($defId, $argument->getInvalidBehavior()); Chris@0: } Chris@0: } Chris@0: } Chris@0: Chris@0: return $arguments; Chris@0: } Chris@0: Chris@0: private function processFactory($factory) Chris@0: { Chris@0: if (null === $factory || !is_array($factory) || !$factory[0] instanceof Reference) { Chris@0: return $factory; Chris@0: } Chris@0: Chris@0: $defId = $this->getDefinitionId($id = (string) $factory[0]); Chris@0: Chris@0: if ($defId !== $id) { Chris@0: $factory[0] = new Reference($defId, $factory[0]->getInvalidBehavior()); Chris@0: } Chris@0: Chris@0: return $factory; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Resolves an alias into a definition id. Chris@0: * Chris@0: * @param string $id The definition or alias id to resolve Chris@0: * Chris@0: * @return string The definition id with aliases resolved Chris@0: */ Chris@0: private function getDefinitionId($id) Chris@0: { Chris@0: $seen = array(); Chris@0: while ($this->container->hasAlias($id)) { Chris@0: if (isset($seen[$id])) { Chris@0: throw new ServiceCircularReferenceException($id, array_keys($seen)); Chris@0: } Chris@0: $seen[$id] = true; Chris@0: $id = (string) $this->container->getAlias($id); Chris@0: } Chris@0: Chris@0: return $id; Chris@0: } Chris@0: }