annotate vendor/symfony/dependency-injection/Compiler/ResolveDefinitionTemplatesPass.php @ 0:4c8ae668cc8c

Initial import (non-working)
author Chris Cannam
date Wed, 29 Nov 2017 16:09:58 +0000
parents
children 1fec387a4317
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@0 14 use Symfony\Component\DependencyInjection\Definition;
Chris@0 15 use Symfony\Component\DependencyInjection\DefinitionDecorator;
Chris@0 16 use Symfony\Component\DependencyInjection\ContainerBuilder;
Chris@0 17 use Symfony\Component\DependencyInjection\Exception\ExceptionInterface;
Chris@0 18 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
Chris@0 19
Chris@0 20 /**
Chris@0 21 * This replaces all DefinitionDecorator instances with their equivalent fully
Chris@0 22 * merged Definition instance.
Chris@0 23 *
Chris@0 24 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
Chris@0 25 * @author Nicolas Grekas <p@tchwork.com>
Chris@0 26 */
Chris@0 27 class ResolveDefinitionTemplatesPass implements CompilerPassInterface
Chris@0 28 {
Chris@0 29 private $compiler;
Chris@0 30 private $formatter;
Chris@0 31 private $currentId;
Chris@0 32
Chris@0 33 /**
Chris@0 34 * Process the ContainerBuilder to replace DefinitionDecorator instances with their real Definition instances.
Chris@0 35 *
Chris@0 36 * @param ContainerBuilder $container
Chris@0 37 */
Chris@0 38 public function process(ContainerBuilder $container)
Chris@0 39 {
Chris@0 40 $this->compiler = $container->getCompiler();
Chris@0 41 $this->formatter = $this->compiler->getLoggingFormatter();
Chris@0 42
Chris@0 43 $container->setDefinitions($this->resolveArguments($container, $container->getDefinitions(), true));
Chris@0 44 }
Chris@0 45
Chris@0 46 /**
Chris@0 47 * Resolves definition decorator arguments.
Chris@0 48 *
Chris@0 49 * @param ContainerBuilder $container The ContainerBuilder
Chris@0 50 * @param array $arguments An array of arguments
Chris@0 51 * @param bool $isRoot If we are processing the root definitions or not
Chris@0 52 *
Chris@0 53 * @return array
Chris@0 54 */
Chris@0 55 private function resolveArguments(ContainerBuilder $container, array $arguments, $isRoot = false)
Chris@0 56 {
Chris@0 57 foreach ($arguments as $k => $argument) {
Chris@0 58 if ($isRoot) {
Chris@0 59 // yes, we are specifically fetching the definition from the
Chris@0 60 // container to ensure we are not operating on stale data
Chris@0 61 $arguments[$k] = $argument = $container->getDefinition($k);
Chris@0 62 $this->currentId = $k;
Chris@0 63 }
Chris@0 64 if (is_array($argument)) {
Chris@0 65 $arguments[$k] = $this->resolveArguments($container, $argument);
Chris@0 66 } elseif ($argument instanceof Definition) {
Chris@0 67 if ($argument instanceof DefinitionDecorator) {
Chris@0 68 $arguments[$k] = $argument = $this->resolveDefinition($container, $argument);
Chris@0 69 if ($isRoot) {
Chris@0 70 $container->setDefinition($k, $argument);
Chris@0 71 }
Chris@0 72 }
Chris@0 73 $argument->setArguments($this->resolveArguments($container, $argument->getArguments()));
Chris@0 74 $argument->setMethodCalls($this->resolveArguments($container, $argument->getMethodCalls()));
Chris@0 75 $argument->setProperties($this->resolveArguments($container, $argument->getProperties()));
Chris@0 76
Chris@0 77 $configurator = $this->resolveArguments($container, array($argument->getConfigurator()));
Chris@0 78 $argument->setConfigurator($configurator[0]);
Chris@0 79
Chris@0 80 $factory = $this->resolveArguments($container, array($argument->getFactory()));
Chris@0 81 $argument->setFactory($factory[0]);
Chris@0 82 }
Chris@0 83 }
Chris@0 84
Chris@0 85 return $arguments;
Chris@0 86 }
Chris@0 87
Chris@0 88 /**
Chris@0 89 * Resolves the definition.
Chris@0 90 *
Chris@0 91 * @param ContainerBuilder $container The ContainerBuilder
Chris@0 92 * @param DefinitionDecorator $definition
Chris@0 93 *
Chris@0 94 * @return Definition
Chris@0 95 *
Chris@0 96 * @throws \RuntimeException When the definition is invalid
Chris@0 97 */
Chris@0 98 private function resolveDefinition(ContainerBuilder $container, DefinitionDecorator $definition)
Chris@0 99 {
Chris@0 100 try {
Chris@0 101 return $this->doResolveDefinition($container, $definition);
Chris@0 102 } catch (ExceptionInterface $e) {
Chris@0 103 $r = new \ReflectionProperty($e, 'message');
Chris@0 104 $r->setAccessible(true);
Chris@0 105 $r->setValue($e, sprintf('Service "%s": %s', $this->currentId, $e->getMessage()));
Chris@0 106
Chris@0 107 throw $e;
Chris@0 108 }
Chris@0 109 }
Chris@0 110
Chris@0 111 private function doResolveDefinition(ContainerBuilder $container, DefinitionDecorator $definition)
Chris@0 112 {
Chris@0 113 if (!$container->has($parent = $definition->getParent())) {
Chris@0 114 throw new RuntimeException(sprintf('Parent definition "%s" does not exist.', $parent));
Chris@0 115 }
Chris@0 116
Chris@0 117 $parentDef = $container->findDefinition($parent);
Chris@0 118 if ($parentDef instanceof DefinitionDecorator) {
Chris@0 119 $id = $this->currentId;
Chris@0 120 $this->currentId = $parent;
Chris@0 121 $parentDef = $this->resolveDefinition($container, $parentDef);
Chris@0 122 $container->setDefinition($parent, $parentDef);
Chris@0 123 $this->currentId = $id;
Chris@0 124 }
Chris@0 125
Chris@0 126 $this->compiler->addLogMessage($this->formatter->formatResolveInheritance($this, $this->currentId, $parent));
Chris@0 127 $def = new Definition();
Chris@0 128
Chris@0 129 // merge in parent definition
Chris@0 130 // purposely ignored attributes: abstract, tags
Chris@0 131 $def->setClass($parentDef->getClass());
Chris@0 132 $def->setArguments($parentDef->getArguments());
Chris@0 133 $def->setMethodCalls($parentDef->getMethodCalls());
Chris@0 134 $def->setProperties($parentDef->getProperties());
Chris@0 135 $def->setAutowiringTypes($parentDef->getAutowiringTypes());
Chris@0 136 if ($parentDef->isDeprecated()) {
Chris@0 137 $def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%'));
Chris@0 138 }
Chris@0 139 $def->setFactory($parentDef->getFactory());
Chris@0 140 $def->setConfigurator($parentDef->getConfigurator());
Chris@0 141 $def->setFile($parentDef->getFile());
Chris@0 142 $def->setPublic($parentDef->isPublic());
Chris@0 143 $def->setLazy($parentDef->isLazy());
Chris@0 144 $def->setAutowired($parentDef->isAutowired());
Chris@0 145
Chris@0 146 // overwrite with values specified in the decorator
Chris@0 147 $changes = $definition->getChanges();
Chris@0 148 if (isset($changes['class'])) {
Chris@0 149 $def->setClass($definition->getClass());
Chris@0 150 }
Chris@0 151 if (isset($changes['factory'])) {
Chris@0 152 $def->setFactory($definition->getFactory());
Chris@0 153 }
Chris@0 154 if (isset($changes['configurator'])) {
Chris@0 155 $def->setConfigurator($definition->getConfigurator());
Chris@0 156 }
Chris@0 157 if (isset($changes['file'])) {
Chris@0 158 $def->setFile($definition->getFile());
Chris@0 159 }
Chris@0 160 if (isset($changes['public'])) {
Chris@0 161 $def->setPublic($definition->isPublic());
Chris@0 162 }
Chris@0 163 if (isset($changes['lazy'])) {
Chris@0 164 $def->setLazy($definition->isLazy());
Chris@0 165 }
Chris@0 166 if (isset($changes['deprecated'])) {
Chris@0 167 $def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%'));
Chris@0 168 }
Chris@0 169 if (isset($changes['autowire'])) {
Chris@0 170 $def->setAutowired($definition->isAutowired());
Chris@0 171 }
Chris@0 172 if (isset($changes['decorated_service'])) {
Chris@0 173 $decoratedService = $definition->getDecoratedService();
Chris@0 174 if (null === $decoratedService) {
Chris@0 175 $def->setDecoratedService($decoratedService);
Chris@0 176 } else {
Chris@0 177 $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2]);
Chris@0 178 }
Chris@0 179 }
Chris@0 180
Chris@0 181 // merge arguments
Chris@0 182 foreach ($definition->getArguments() as $k => $v) {
Chris@0 183 if (is_numeric($k)) {
Chris@0 184 $def->addArgument($v);
Chris@0 185 continue;
Chris@0 186 }
Chris@0 187
Chris@0 188 if (0 !== strpos($k, 'index_')) {
Chris@0 189 throw new RuntimeException(sprintf('Invalid argument key "%s" found.', $k));
Chris@0 190 }
Chris@0 191
Chris@0 192 $index = (int) substr($k, strlen('index_'));
Chris@0 193 $def->replaceArgument($index, $v);
Chris@0 194 }
Chris@0 195
Chris@0 196 // merge properties
Chris@0 197 foreach ($definition->getProperties() as $k => $v) {
Chris@0 198 $def->setProperty($k, $v);
Chris@0 199 }
Chris@0 200
Chris@0 201 // append method calls
Chris@0 202 if (count($calls = $definition->getMethodCalls()) > 0) {
Chris@0 203 $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls));
Chris@0 204 }
Chris@0 205
Chris@0 206 // merge autowiring types
Chris@0 207 foreach ($definition->getAutowiringTypes() as $autowiringType) {
Chris@0 208 $def->addAutowiringType($autowiringType);
Chris@0 209 }
Chris@0 210
Chris@0 211 // these attributes are always taken from the child
Chris@0 212 $def->setAbstract($definition->isAbstract());
Chris@0 213 $def->setShared($definition->isShared());
Chris@0 214 $def->setTags($definition->getTags());
Chris@0 215
Chris@0 216 return $def;
Chris@0 217 }
Chris@0 218 }