annotate vendor/symfony/dependency-injection/Compiler/AnalyzeServiceReferencesPass.php @ 14:1fec387a4317

Update Drupal core to 8.5.2 via Composer
author Chris Cannam
date Mon, 23 Apr 2018 09:46:53 +0100
parents 7a779792577d
children 129ea1e6d783
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@14 15 use Symfony\Component\DependencyInjection\ContainerInterface;
Chris@0 16 use Symfony\Component\DependencyInjection\Definition;
Chris@14 17 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
Chris@12 18 use Symfony\Component\DependencyInjection\ExpressionLanguage;
Chris@0 19 use Symfony\Component\DependencyInjection\Reference;
Chris@0 20 use Symfony\Component\DependencyInjection\ContainerBuilder;
Chris@12 21 use Symfony\Component\ExpressionLanguage\Expression;
Chris@0 22
Chris@0 23 /**
Chris@0 24 * Run this pass before passes that need to know more about the relation of
Chris@0 25 * your services.
Chris@0 26 *
Chris@0 27 * This class will populate the ServiceReferenceGraph with information. You can
Chris@0 28 * retrieve the graph in other passes from the compiler.
Chris@0 29 *
Chris@0 30 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
Chris@0 31 */
Chris@14 32 class AnalyzeServiceReferencesPass extends AbstractRecursivePass implements RepeatablePassInterface
Chris@0 33 {
Chris@0 34 private $graph;
Chris@0 35 private $currentDefinition;
Chris@0 36 private $onlyConstructorArguments;
Chris@14 37 private $lazy;
Chris@12 38 private $expressionLanguage;
Chris@0 39
Chris@0 40 /**
Chris@0 41 * @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls
Chris@0 42 */
Chris@0 43 public function __construct($onlyConstructorArguments = false)
Chris@0 44 {
Chris@0 45 $this->onlyConstructorArguments = (bool) $onlyConstructorArguments;
Chris@0 46 }
Chris@0 47
Chris@0 48 /**
Chris@0 49 * {@inheritdoc}
Chris@0 50 */
Chris@0 51 public function setRepeatedPass(RepeatedPass $repeatedPass)
Chris@0 52 {
Chris@14 53 // no-op for BC
Chris@0 54 }
Chris@0 55
Chris@0 56 /**
Chris@0 57 * Processes a ContainerBuilder object to populate the service reference graph.
Chris@0 58 */
Chris@0 59 public function process(ContainerBuilder $container)
Chris@0 60 {
Chris@0 61 $this->container = $container;
Chris@0 62 $this->graph = $container->getCompiler()->getServiceReferenceGraph();
Chris@0 63 $this->graph->clear();
Chris@14 64 $this->lazy = false;
Chris@0 65
Chris@14 66 foreach ($container->getAliases() as $id => $alias) {
Chris@14 67 $targetId = $this->getDefinitionId((string) $alias);
Chris@14 68 $this->graph->connect($id, $alias, $targetId, $this->getDefinition($targetId), null);
Chris@0 69 }
Chris@0 70
Chris@14 71 parent::process($container);
Chris@0 72 }
Chris@0 73
Chris@14 74 protected function processValue($value, $isRoot = false)
Chris@0 75 {
Chris@14 76 $lazy = $this->lazy;
Chris@0 77
Chris@14 78 if ($value instanceof ArgumentInterface) {
Chris@14 79 $this->lazy = true;
Chris@14 80 parent::processValue($value->getValues());
Chris@14 81 $this->lazy = $lazy;
Chris@14 82
Chris@14 83 return $value;
Chris@14 84 }
Chris@14 85 if ($value instanceof Expression) {
Chris@14 86 $this->getExpressionLanguage()->compile((string) $value, array('this' => 'container'));
Chris@14 87
Chris@14 88 return $value;
Chris@14 89 }
Chris@14 90 if ($value instanceof Reference) {
Chris@14 91 $targetId = $this->getDefinitionId((string) $value);
Chris@14 92 $targetDefinition = $this->getDefinition($targetId);
Chris@14 93
Chris@14 94 $this->graph->connect(
Chris@14 95 $this->currentId,
Chris@14 96 $this->currentDefinition,
Chris@14 97 $targetId,
Chris@14 98 $targetDefinition,
Chris@14 99 $value,
Chris@14 100 $this->lazy || ($targetDefinition && $targetDefinition->isLazy()),
Chris@14 101 ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior()
Chris@14 102 );
Chris@14 103
Chris@14 104 return $value;
Chris@14 105 }
Chris@14 106 if (!$value instanceof Definition) {
Chris@14 107 return parent::processValue($value, $isRoot);
Chris@14 108 }
Chris@14 109 if ($isRoot) {
Chris@14 110 if ($value->isSynthetic() || $value->isAbstract()) {
Chris@14 111 return $value;
Chris@0 112 }
Chris@14 113 $this->currentDefinition = $value;
Chris@0 114 }
Chris@14 115 $this->lazy = false;
Chris@14 116
Chris@14 117 $this->processValue($value->getFactory());
Chris@14 118 $this->processValue($value->getArguments());
Chris@14 119
Chris@14 120 if (!$this->onlyConstructorArguments) {
Chris@14 121 $this->processValue($value->getProperties());
Chris@14 122 $this->processValue($value->getMethodCalls());
Chris@14 123 $this->processValue($value->getConfigurator());
Chris@14 124 }
Chris@14 125 $this->lazy = $lazy;
Chris@14 126
Chris@14 127 return $value;
Chris@0 128 }
Chris@0 129
Chris@0 130 /**
Chris@0 131 * Returns a service definition given the full name or an alias.
Chris@0 132 *
Chris@0 133 * @param string $id A full id or alias for a service definition
Chris@0 134 *
Chris@0 135 * @return Definition|null The definition related to the supplied id
Chris@0 136 */
Chris@0 137 private function getDefinition($id)
Chris@0 138 {
Chris@0 139 return null === $id ? null : $this->container->getDefinition($id);
Chris@0 140 }
Chris@0 141
Chris@0 142 private function getDefinitionId($id)
Chris@0 143 {
Chris@0 144 while ($this->container->hasAlias($id)) {
Chris@0 145 $id = (string) $this->container->getAlias($id);
Chris@0 146 }
Chris@0 147
Chris@0 148 if (!$this->container->hasDefinition($id)) {
Chris@0 149 return;
Chris@0 150 }
Chris@0 151
Chris@14 152 return $this->container->normalizeId($id);
Chris@0 153 }
Chris@12 154
Chris@12 155 private function getExpressionLanguage()
Chris@12 156 {
Chris@12 157 if (null === $this->expressionLanguage) {
Chris@14 158 if (!class_exists(ExpressionLanguage::class)) {
Chris@14 159 throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
Chris@14 160 }
Chris@14 161
Chris@12 162 $providers = $this->container->getExpressionLanguageProviders();
Chris@12 163 $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) {
Chris@12 164 if ('""' === substr_replace($arg, '', 1, -1)) {
Chris@12 165 $id = stripcslashes(substr($arg, 1, -1));
Chris@14 166 $id = $this->getDefinitionId($id);
Chris@12 167
Chris@12 168 $this->graph->connect(
Chris@12 169 $this->currentId,
Chris@12 170 $this->currentDefinition,
Chris@14 171 $id,
Chris@12 172 $this->getDefinition($id)
Chris@12 173 );
Chris@12 174 }
Chris@12 175
Chris@12 176 return sprintf('$this->get(%s)', $arg);
Chris@12 177 });
Chris@12 178 }
Chris@12 179
Chris@12 180 return $this->expressionLanguage;
Chris@12 181 }
Chris@0 182 }