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\Definition; Chris@0: use Symfony\Component\DependencyInjection\Reference; Chris@0: use Symfony\Component\DependencyInjection\ContainerBuilder; Chris@0: Chris@0: /** Chris@0: * Inline service definitions where this is possible. Chris@0: * Chris@0: * @author Johannes M. Schmitt Chris@0: */ Chris@0: class InlineServiceDefinitionsPass implements RepeatablePassInterface Chris@0: { Chris@0: private $repeatedPass; Chris@0: private $graph; Chris@0: private $compiler; Chris@0: private $formatter; Chris@0: private $currentId; Chris@0: Chris@0: /** Chris@0: * {@inheritdoc} Chris@0: */ Chris@0: public function setRepeatedPass(RepeatedPass $repeatedPass) Chris@0: { Chris@0: $this->repeatedPass = $repeatedPass; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Processes the ContainerBuilder for inline service definitions. Chris@0: * Chris@0: * @param ContainerBuilder $container Chris@0: */ Chris@0: public function process(ContainerBuilder $container) Chris@0: { Chris@0: $this->compiler = $container->getCompiler(); Chris@0: $this->formatter = $this->compiler->getLoggingFormatter(); Chris@0: $this->graph = $this->compiler->getServiceReferenceGraph(); Chris@0: Chris@0: $container->setDefinitions($this->inlineArguments($container, $container->getDefinitions(), true)); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Processes inline arguments. Chris@0: * Chris@0: * @param ContainerBuilder $container The ContainerBuilder Chris@0: * @param array $arguments An array of arguments Chris@0: * @param bool $isRoot If we are processing the root definitions or not Chris@0: * Chris@0: * @return array Chris@0: */ Chris@0: private function inlineArguments(ContainerBuilder $container, array $arguments, $isRoot = false) Chris@0: { Chris@0: foreach ($arguments as $k => $argument) { Chris@0: if ($isRoot) { Chris@0: $this->currentId = $k; Chris@0: } Chris@0: if (is_array($argument)) { Chris@0: $arguments[$k] = $this->inlineArguments($container, $argument); Chris@0: } elseif ($argument instanceof Reference) { Chris@0: if (!$container->hasDefinition($id = (string) $argument)) { Chris@0: continue; Chris@0: } Chris@0: Chris@0: if ($this->isInlineableDefinition($id, $definition = $container->getDefinition($id))) { Chris@0: $this->compiler->addLogMessage($this->formatter->formatInlineService($this, $id, $this->currentId)); Chris@0: Chris@0: if ($definition->isShared()) { Chris@0: $arguments[$k] = $definition; Chris@0: } else { Chris@0: $arguments[$k] = clone $definition; Chris@0: } Chris@0: } Chris@0: } elseif ($argument instanceof Definition) { Chris@0: $argument->setArguments($this->inlineArguments($container, $argument->getArguments())); Chris@0: $argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls())); Chris@0: $argument->setProperties($this->inlineArguments($container, $argument->getProperties())); Chris@0: Chris@0: $configurator = $this->inlineArguments($container, array($argument->getConfigurator())); Chris@0: $argument->setConfigurator($configurator[0]); Chris@0: Chris@0: $factory = $this->inlineArguments($container, array($argument->getFactory())); Chris@0: $argument->setFactory($factory[0]); Chris@0: } Chris@0: } Chris@0: Chris@0: return $arguments; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Checks if the definition is inlineable. Chris@0: * Chris@0: * @param string $id Chris@0: * @param Definition $definition Chris@0: * Chris@0: * @return bool If the definition is inlineable Chris@0: */ Chris@0: private function isInlineableDefinition($id, Definition $definition) Chris@0: { Chris@0: if (!$definition->isShared()) { Chris@0: return true; Chris@0: } Chris@0: Chris@0: if ($definition->isPublic() || $definition->isLazy()) { Chris@0: return false; Chris@0: } Chris@0: Chris@0: if (!$this->graph->hasNode($id)) { Chris@0: return true; Chris@0: } Chris@0: Chris@0: if ($this->currentId == $id) { Chris@0: return false; Chris@0: } Chris@0: Chris@0: $ids = array(); Chris@0: foreach ($this->graph->getNode($id)->getInEdges() as $edge) { Chris@0: $ids[] = $edge->getSourceNode()->getId(); Chris@0: } Chris@0: Chris@0: if (count(array_unique($ids)) > 1) { Chris@0: return false; Chris@0: } Chris@0: Chris@0: if (count($ids) > 1 && is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) { Chris@0: return false; Chris@0: } Chris@0: Chris@0: return true; Chris@0: } Chris@0: }