<?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\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Inline service definitions where this is possible. * * @author Johannes M. Schmitt <schmittjoh@gmail.com> */ class InlineServiceDefinitionsPass implements RepeatablePassInterface { private $repeatedPass; private $graph; private $compiler; private $formatter; private $currentId; /** * {@inheritDoc} */ public function setRepeatedPass(RepeatedPass $repeatedPass) { $this->repeatedPass = $repeatedPass; } /** * Processes the ContainerBuilder for inline service definitions. * * @param ContainerBuilder $container */ public function process(ContainerBuilder $container) { $this->compiler = $container ->getCompiler(); $this->formatter = $this->compiler ->getLoggingFormatter(); $this->graph = $this->compiler ->getServiceReferenceGraph(); foreach ($container ->getDefinitions() as $id => $definition) { $this->currentId = $id; $definition ->setArguments($this ->inlineArguments($container, $definition ->getArguments())); $definition ->setMethodCalls($this ->inlineArguments($container, $definition ->getMethodCalls())); $definition ->setProperties($this ->inlineArguments($container, $definition ->getProperties())); } } /** * Processes inline arguments. * * @param ContainerBuilder $container The ContainerBuilder * @param array $arguments An array of arguments */ private function inlineArguments(ContainerBuilder $container, array $arguments) { foreach ($arguments as $k => $argument) { if (is_array($argument)) { $arguments[$k] = $this ->inlineArguments($container, $argument); } elseif ($argument instanceof Reference) { if (!$container ->hasDefinition($id = (string) $argument)) { continue; } if ($this ->isInlineableDefinition($container, $id, $definition = $container ->getDefinition($id))) { $this->compiler ->addLogMessage($this->formatter ->formatInlineService($this, $id, $this->currentId)); if (ContainerInterface::SCOPE_PROTOTYPE !== $definition ->getScope()) { $arguments[$k] = $definition; } else { $arguments[$k] = clone $definition; } } } elseif ($argument instanceof Definition) { $argument ->setArguments($this ->inlineArguments($container, $argument ->getArguments())); $argument ->setMethodCalls($this ->inlineArguments($container, $argument ->getMethodCalls())); $argument ->setProperties($this ->inlineArguments($container, $argument ->getProperties())); } } return $arguments; } /** * Checks if the definition is inlineable. * * @param ContainerBuilder $container * @param string $id * @param Definition $definition * * @return Boolean If the definition is inlineable */ private function isInlineableDefinition(ContainerBuilder $container, $id, Definition $definition) { if (ContainerInterface::SCOPE_PROTOTYPE === $definition ->getScope()) { return true; } if ($definition ->isPublic()) { return false; } if (!$this->graph ->hasNode($id)) { return true; } $ids = array(); foreach ($this->graph ->getNode($id) ->getInEdges() as $edge) { $ids[] = $edge ->getSourceNode() ->getId(); } if (count(array_unique($ids)) > 1) { return false; } return $container ->getDefinition(reset($ids)) ->getScope() === $definition ->getScope(); } }