vendor/symfony/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php
changeset 0 7f95f8617b0b
equal deleted inserted replaced
-1:000000000000 0:7f95f8617b0b
       
     1 <?php
       
     2 
       
     3 /*
       
     4  * This file is part of the Symfony package.
       
     5  *
       
     6  * (c) Fabien Potencier <fabien@symfony.com>
       
     7  *
       
     8  * For the full copyright and license information, please view the LICENSE
       
     9  * file that was distributed with this source code.
       
    10  */
       
    11 
       
    12 namespace Symfony\Component\DependencyInjection\Compiler;
       
    13 
       
    14 use Symfony\Component\DependencyInjection\ContainerInterface;
       
    15 use Symfony\Component\DependencyInjection\Definition;
       
    16 use Symfony\Component\DependencyInjection\Reference;
       
    17 use Symfony\Component\DependencyInjection\ContainerBuilder;
       
    18 
       
    19 /**
       
    20  * Inline service definitions where this is possible.
       
    21  *
       
    22  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
       
    23  */
       
    24 class InlineServiceDefinitionsPass implements RepeatablePassInterface
       
    25 {
       
    26     private $repeatedPass;
       
    27     private $graph;
       
    28     private $compiler;
       
    29     private $formatter;
       
    30     private $currentId;
       
    31 
       
    32     /**
       
    33      * {@inheritDoc}
       
    34      */
       
    35     public function setRepeatedPass(RepeatedPass $repeatedPass)
       
    36     {
       
    37         $this->repeatedPass = $repeatedPass;
       
    38     }
       
    39 
       
    40     /**
       
    41      * Processes the ContainerBuilder for inline service definitions.
       
    42      *
       
    43      * @param ContainerBuilder $container
       
    44      */
       
    45     public function process(ContainerBuilder $container)
       
    46     {
       
    47         $this->compiler = $container->getCompiler();
       
    48         $this->formatter = $this->compiler->getLoggingFormatter();
       
    49         $this->graph = $this->compiler->getServiceReferenceGraph();
       
    50 
       
    51         foreach ($container->getDefinitions() as $id => $definition) {
       
    52             $this->currentId = $id;
       
    53 
       
    54             $definition->setArguments(
       
    55                 $this->inlineArguments($container, $definition->getArguments())
       
    56             );
       
    57 
       
    58             $definition->setMethodCalls(
       
    59                 $this->inlineArguments($container, $definition->getMethodCalls())
       
    60             );
       
    61 
       
    62             $definition->setProperties(
       
    63                 $this->inlineArguments($container, $definition->getProperties())
       
    64             );
       
    65         }
       
    66     }
       
    67 
       
    68     /**
       
    69      * Processes inline arguments.
       
    70      *
       
    71      * @param ContainerBuilder $container The ContainerBuilder
       
    72      * @param array            $arguments An array of arguments
       
    73      */
       
    74     private function inlineArguments(ContainerBuilder $container, array $arguments)
       
    75     {
       
    76         foreach ($arguments as $k => $argument) {
       
    77             if (is_array($argument)) {
       
    78                 $arguments[$k] = $this->inlineArguments($container, $argument);
       
    79             } else if ($argument instanceof Reference) {
       
    80                 if (!$container->hasDefinition($id = (string) $argument)) {
       
    81                     continue;
       
    82                 }
       
    83 
       
    84                 if ($this->isInlinableDefinition($container, $id, $definition = $container->getDefinition($id))) {
       
    85                     $this->compiler->addLogMessage($this->formatter->formatInlineService($this, $id, $this->currentId));
       
    86 
       
    87                     if (ContainerInterface::SCOPE_PROTOTYPE !== $definition->getScope()) {
       
    88                         $arguments[$k] = $definition;
       
    89                     } else {
       
    90                         $arguments[$k] = clone $definition;
       
    91                     }
       
    92                 }
       
    93             } else if ($argument instanceof Definition) {
       
    94                 $argument->setArguments($this->inlineArguments($container, $argument->getArguments()));
       
    95                 $argument->setMethodCalls($this->inlineArguments($container, $argument->getMethodCalls()));
       
    96                 $argument->setProperties($this->inlineArguments($container, $argument->getProperties()));
       
    97             }
       
    98         }
       
    99 
       
   100         return $arguments;
       
   101     }
       
   102 
       
   103     /**
       
   104      * Checks if the definition is inlineable.
       
   105      *
       
   106      * @param ContainerBuilder $container
       
   107      * @param string           $id
       
   108      * @param Definition       $definition
       
   109      * @return Boolean If the definition is inlineable
       
   110      */
       
   111     private function isInlinableDefinition(ContainerBuilder $container, $id, Definition $definition)
       
   112     {
       
   113         if (ContainerInterface::SCOPE_PROTOTYPE === $definition->getScope()) {
       
   114             return true;
       
   115         }
       
   116 
       
   117         if ($definition->isPublic()) {
       
   118             return false;
       
   119         }
       
   120 
       
   121         if (!$this->graph->hasNode($id)) {
       
   122             return true;
       
   123         }
       
   124 
       
   125         $ids = array();
       
   126         foreach ($this->graph->getNode($id)->getInEdges() as $edge) {
       
   127             $ids[] = $edge->getSourceNode()->getId();
       
   128         }
       
   129 
       
   130         if (count(array_unique($ids)) > 1) {
       
   131             return false;
       
   132         }
       
   133 
       
   134         return $container->getDefinition(reset($ids))->getScope() === $definition->getScope();
       
   135     }
       
   136 }