annotate vendor/symfony/dependency-injection/Compiler/InlineServiceDefinitionsPass.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents 129ea1e6d783
children
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of the Symfony package.
Chris@0 5 *
Chris@0 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Symfony\Component\DependencyInjection\Compiler;
Chris@0 13
Chris@14 14 use Symfony\Component\DependencyInjection\Argument\ArgumentInterface;
Chris@0 15 use Symfony\Component\DependencyInjection\Definition;
Chris@14 16 use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
Chris@0 17 use Symfony\Component\DependencyInjection\Reference;
Chris@0 18
Chris@0 19 /**
Chris@0 20 * Inline service definitions where this is possible.
Chris@0 21 *
Chris@0 22 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
Chris@0 23 */
Chris@14 24 class InlineServiceDefinitionsPass extends AbstractRecursivePass implements RepeatablePassInterface
Chris@0 25 {
Chris@17 26 private $cloningIds = [];
Chris@17 27 private $inlinedServiceIds = [];
Chris@0 28
Chris@0 29 /**
Chris@0 30 * {@inheritdoc}
Chris@0 31 */
Chris@0 32 public function setRepeatedPass(RepeatedPass $repeatedPass)
Chris@0 33 {
Chris@14 34 // no-op for BC
Chris@0 35 }
Chris@0 36
Chris@0 37 /**
Chris@14 38 * Returns an array of all services inlined by this pass.
Chris@0 39 *
Chris@14 40 * The key is the inlined service id and its value is the list of services it was inlined into.
Chris@14 41 *
Chris@14 42 * @deprecated since version 3.4, to be removed in 4.0.
Chris@14 43 *
Chris@14 44 * @return array
Chris@0 45 */
Chris@14 46 public function getInlinedServiceIds()
Chris@0 47 {
Chris@14 48 @trigger_error('Calling InlineServiceDefinitionsPass::getInlinedServiceIds() is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
Chris@0 49
Chris@14 50 return $this->inlinedServiceIds;
Chris@0 51 }
Chris@0 52
Chris@0 53 /**
Chris@14 54 * {@inheritdoc}
Chris@0 55 */
Chris@14 56 protected function processValue($value, $isRoot = false)
Chris@0 57 {
Chris@14 58 if ($value instanceof ArgumentInterface) {
Chris@14 59 // Reference found in ArgumentInterface::getValues() are not inlineable
Chris@14 60 return $value;
Chris@0 61 }
Chris@0 62
Chris@14 63 if ($value instanceof Definition && $this->cloningIds) {
Chris@14 64 if ($value->isShared()) {
Chris@14 65 return $value;
Chris@14 66 }
Chris@14 67 $value = clone $value;
Chris@14 68 }
Chris@14 69
Chris@14 70 if (!$value instanceof Reference || !$this->container->hasDefinition($id = $this->container->normalizeId($value))) {
Chris@14 71 return parent::processValue($value, $isRoot);
Chris@14 72 }
Chris@14 73
Chris@14 74 $definition = $this->container->getDefinition($id);
Chris@14 75
Chris@14 76 if (!$this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) {
Chris@14 77 return $value;
Chris@14 78 }
Chris@14 79
Chris@14 80 $this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId));
Chris@14 81 $this->inlinedServiceIds[$id][] = $this->currentId;
Chris@14 82
Chris@14 83 if ($definition->isShared()) {
Chris@14 84 return $definition;
Chris@14 85 }
Chris@14 86
Chris@14 87 if (isset($this->cloningIds[$id])) {
Chris@14 88 $ids = array_keys($this->cloningIds);
Chris@14 89 $ids[] = $id;
Chris@14 90
Chris@17 91 throw new ServiceCircularReferenceException($id, \array_slice($ids, array_search($id, $ids)));
Chris@14 92 }
Chris@14 93
Chris@14 94 $this->cloningIds[$id] = true;
Chris@14 95 try {
Chris@14 96 return $this->processValue($definition);
Chris@14 97 } finally {
Chris@14 98 unset($this->cloningIds[$id]);
Chris@14 99 }
Chris@0 100 }
Chris@0 101
Chris@0 102 /**
Chris@0 103 * Checks if the definition is inlineable.
Chris@0 104 *
Chris@0 105 * @return bool If the definition is inlineable
Chris@0 106 */
Chris@14 107 private function isInlineableDefinition($id, Definition $definition, ServiceReferenceGraph $graph)
Chris@0 108 {
Chris@16 109 if ($definition->getErrors() || $definition->isDeprecated() || $definition->isLazy() || $definition->isSynthetic()) {
Chris@16 110 return false;
Chris@16 111 }
Chris@16 112
Chris@0 113 if (!$definition->isShared()) {
Chris@0 114 return true;
Chris@0 115 }
Chris@0 116
Chris@16 117 if ($definition->isPublic() || $definition->isPrivate()) {
Chris@0 118 return false;
Chris@0 119 }
Chris@0 120
Chris@14 121 if (!$graph->hasNode($id)) {
Chris@0 122 return true;
Chris@0 123 }
Chris@0 124
Chris@0 125 if ($this->currentId == $id) {
Chris@0 126 return false;
Chris@0 127 }
Chris@0 128
Chris@17 129 $ids = [];
Chris@17 130 $isReferencedByConstructor = false;
Chris@14 131 foreach ($graph->getNode($id)->getInEdges() as $edge) {
Chris@17 132 $isReferencedByConstructor = $isReferencedByConstructor || $edge->isReferencedByConstructor();
Chris@17 133 if ($edge->isWeak() || $edge->isLazy()) {
Chris@14 134 return false;
Chris@14 135 }
Chris@0 136 $ids[] = $edge->getSourceNode()->getId();
Chris@0 137 }
Chris@0 138
Chris@17 139 if (!$ids) {
Chris@17 140 return true;
Chris@17 141 }
Chris@17 142
Chris@17 143 if (\count(array_unique($ids)) > 1) {
Chris@0 144 return false;
Chris@0 145 }
Chris@0 146
Chris@17 147 if (\count($ids) > 1 && \is_array($factory = $definition->getFactory()) && ($factory[0] instanceof Reference || $factory[0] instanceof Definition)) {
Chris@0 148 return false;
Chris@0 149 }
Chris@0 150
Chris@17 151 return $this->container->getDefinition($ids[0])->isShared();
Chris@0 152 }
Chris@0 153 }