vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php line 35

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of the Symfony package.
  4.  *
  5.  * (c) Fabien Potencier <fabien@symfony.com>
  6.  *
  7.  * For the full copyright and license information, please view the LICENSE
  8.  * file that was distributed with this source code.
  9.  */
  10. namespace Symfony\Component\DependencyInjection\Compiler;
  11. use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
  12. use Symfony\Component\DependencyInjection\ContainerBuilder;
  13. use Symfony\Component\DependencyInjection\Definition;
  14. use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
  15. use Symfony\Component\DependencyInjection\Reference;
  16. /**
  17.  * Inline service definitions where this is possible.
  18.  *
  19.  * @author Johannes M. Schmitt <schmittjoh@gmail.com>
  20.  */
  21. class InlineServiceDefinitionsPass extends AbstractRecursivePass
  22. {
  23.     private $analyzingPass;
  24.     private $cloningIds = [];
  25.     private $connectedIds = [];
  26.     private $notInlinedIds = [];
  27.     private $inlinedIds = [];
  28.     private $notInlinableIds = [];
  29.     private $graph;
  30.     public function __construct(AnalyzeServiceReferencesPass $analyzingPass null)
  31.     {
  32.         $this->analyzingPass $analyzingPass;
  33.     }
  34.     public function process(ContainerBuilder $container)
  35.     {
  36.         $this->container $container;
  37.         if ($this->analyzingPass) {
  38.             $analyzedContainer = new ContainerBuilder();
  39.             $analyzedContainer->setAliases($container->getAliases());
  40.             $analyzedContainer->setDefinitions($container->getDefinitions());
  41.             foreach ($container->getExpressionLanguageProviders() as $provider) {
  42.                 $analyzedContainer->addExpressionLanguageProvider($provider);
  43.             }
  44.         } else {
  45.             $analyzedContainer $container;
  46.         }
  47.         try {
  48.             $remainingInlinedIds = [];
  49.             $this->connectedIds $this->notInlinedIds $container->getDefinitions();
  50.             do {
  51.                 if ($this->analyzingPass) {
  52.                     $analyzedContainer->setDefinitions(array_intersect_key($analyzedContainer->getDefinitions(), $this->connectedIds));
  53.                     $this->analyzingPass->process($analyzedContainer);
  54.                 }
  55.                 $this->graph $analyzedContainer->getCompiler()->getServiceReferenceGraph();
  56.                 $notInlinedIds $this->notInlinedIds;
  57.                 $this->connectedIds $this->notInlinedIds $this->inlinedIds = [];
  58.                 foreach ($analyzedContainer->getDefinitions() as $id => $definition) {
  59.                     if (!$this->graph->hasNode($id)) {
  60.                         continue;
  61.                     }
  62.                     foreach ($this->graph->getNode($id)->getOutEdges() as $edge) {
  63.                         if (isset($notInlinedIds[$edge->getSourceNode()->getId()])) {
  64.                             $this->currentId $id;
  65.                             $this->processValue($definitiontrue);
  66.                             break;
  67.                         }
  68.                     }
  69.                 }
  70.                 foreach ($this->inlinedIds as $id => $isPublicOrNotShared) {
  71.                     if ($isPublicOrNotShared) {
  72.                         $remainingInlinedIds[$id] = $id;
  73.                     } else {
  74.                         $container->removeDefinition($id);
  75.                         $analyzedContainer->removeDefinition($id);
  76.                     }
  77.                 }
  78.             } while ($this->inlinedIds && $this->analyzingPass);
  79.             foreach ($remainingInlinedIds as $id) {
  80.                 if (isset($this->notInlinableIds[$id])) {
  81.                     continue;
  82.                 }
  83.                 $definition $container->getDefinition($id);
  84.                 if (!$definition->isShared() && !$definition->isPublic()) {
  85.                     $container->removeDefinition($id);
  86.                 }
  87.             }
  88.         } finally {
  89.             $this->container null;
  90.             $this->connectedIds $this->notInlinedIds $this->inlinedIds = [];
  91.             $this->notInlinableIds = [];
  92.             $this->graph null;
  93.         }
  94.     }
  95.     /**
  96.      * {@inheritdoc}
  97.      */
  98.     protected function processValue($valuebool $isRoot false)
  99.     {
  100.         if ($value instanceof ArgumentInterface) {
  101.             // References found in ArgumentInterface::getValues() are not inlineable
  102.             return $value;
  103.         }
  104.         if ($value instanceof Definition && $this->cloningIds) {
  105.             if ($value->isShared()) {
  106.                 return $value;
  107.             }
  108.             $value = clone $value;
  109.         }
  110.         if (!$value instanceof Reference) {
  111.             return parent::processValue($value$isRoot);
  112.         } elseif (!$this->container->hasDefinition($id = (string) $value)) {
  113.             return $value;
  114.         }
  115.         $definition $this->container->getDefinition($id);
  116.         if (!$this->isInlineableDefinition($id$definition)) {
  117.             $this->notInlinableIds[$id] = true;
  118.             return $value;
  119.         }
  120.         $this->container->log($thissprintf('Inlined service "%s" to "%s".'$id$this->currentId));
  121.         $this->inlinedIds[$id] = $definition->isPublic() || !$definition->isShared();
  122.         $this->notInlinedIds[$this->currentId] = true;
  123.         if ($definition->isShared()) {
  124.             return $definition;
  125.         }
  126.         if (isset($this->cloningIds[$id])) {
  127.             $ids array_keys($this->cloningIds);
  128.             $ids[] = $id;
  129.             throw new ServiceCircularReferenceException($id\array_slice($idsarray_search($id$ids)));
  130.         }
  131.         $this->cloningIds[$id] = true;
  132.         try {
  133.             return $this->processValue($definition);
  134.         } finally {
  135.             unset($this->cloningIds[$id]);
  136.         }
  137.     }
  138.     /**
  139.      * Checks if the definition is inlineable.
  140.      */
  141.     private function isInlineableDefinition(string $idDefinition $definition): bool
  142.     {
  143.         if ($definition->hasErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic() || $definition->hasTag('container.do_not_inline')) {
  144.             return false;
  145.         }
  146.         if (!$definition->isShared()) {
  147.             if (!$this->graph->hasNode($id)) {
  148.                 return true;
  149.             }
  150.             foreach ($this->graph->getNode($id)->getInEdges() as $edge) {
  151.                 $srcId $edge->getSourceNode()->getId();
  152.                 $this->connectedIds[$srcId] = true;
  153.                 if ($edge->isWeak() || $edge->isLazy()) {
  154.                     return !$this->connectedIds[$id] = true;
  155.                 }
  156.             }
  157.             return true;
  158.         }
  159.         if ($definition->isPublic()) {
  160.             return false;
  161.         }
  162.         if (!$this->graph->hasNode($id)) {
  163.             return true;
  164.         }
  165.         if ($this->currentId == $id) {
  166.             return false;
  167.         }
  168.         $this->connectedIds[$id] = true;
  169.         $srcIds = [];
  170.         $srcCount 0;
  171.         foreach ($this->graph->getNode($id)->getInEdges() as $edge) {
  172.             $srcId $edge->getSourceNode()->getId();
  173.             $this->connectedIds[$srcId] = true;
  174.             if ($edge->isWeak() || $edge->isLazy()) {
  175.                 return false;
  176.             }
  177.             $srcIds[$srcId] = true;
  178.             ++$srcCount;
  179.         }
  180.         if (!== \count($srcIds)) {
  181.             $this->notInlinedIds[$id] = true;
  182.             return false;
  183.         }
  184.         if ($srcCount && \is_array($factory $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) {
  185.             return false;
  186.         }
  187.         return $this->container->getDefinition($srcId)->isShared();
  188.     }
  189. }