annotate vendor/symfony/dependency-injection/Compiler/ResolveInstanceofConditionalsPass.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
children 129ea1e6d783
rev   line source
Chris@14 1 <?php
Chris@14 2
Chris@14 3 /*
Chris@14 4 * This file is part of the Symfony package.
Chris@14 5 *
Chris@14 6 * (c) Fabien Potencier <fabien@symfony.com>
Chris@14 7 *
Chris@14 8 * For the full copyright and license information, please view the LICENSE
Chris@14 9 * file that was distributed with this source code.
Chris@14 10 */
Chris@14 11
Chris@14 12 namespace Symfony\Component\DependencyInjection\Compiler;
Chris@14 13
Chris@14 14 use Symfony\Component\DependencyInjection\ChildDefinition;
Chris@14 15 use Symfony\Component\DependencyInjection\ContainerBuilder;
Chris@14 16 use Symfony\Component\DependencyInjection\Definition;
Chris@14 17 use Symfony\Component\DependencyInjection\Exception\RuntimeException;
Chris@14 18 use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
Chris@14 19
Chris@14 20 /**
Chris@14 21 * Applies instanceof conditionals to definitions.
Chris@14 22 *
Chris@14 23 * @author Nicolas Grekas <p@tchwork.com>
Chris@14 24 */
Chris@14 25 class ResolveInstanceofConditionalsPass implements CompilerPassInterface
Chris@14 26 {
Chris@14 27 /**
Chris@14 28 * {@inheritdoc}
Chris@14 29 */
Chris@14 30 public function process(ContainerBuilder $container)
Chris@14 31 {
Chris@14 32 foreach ($container->getAutoconfiguredInstanceof() as $interface => $definition) {
Chris@14 33 if ($definition->getArguments()) {
Chris@14 34 throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines arguments but these are not supported and should be removed.', $interface));
Chris@14 35 }
Chris@14 36 if ($definition->getMethodCalls()) {
Chris@14 37 throw new InvalidArgumentException(sprintf('Autoconfigured instanceof for type "%s" defines method calls but these are not supported and should be removed.', $interface));
Chris@14 38 }
Chris@14 39 }
Chris@14 40
Chris@14 41 foreach ($container->getDefinitions() as $id => $definition) {
Chris@14 42 if ($definition instanceof ChildDefinition) {
Chris@14 43 // don't apply "instanceof" to children: it will be applied to their parent
Chris@14 44 continue;
Chris@14 45 }
Chris@14 46 $container->setDefinition($id, $this->processDefinition($container, $id, $definition));
Chris@14 47 }
Chris@14 48 }
Chris@14 49
Chris@14 50 private function processDefinition(ContainerBuilder $container, $id, Definition $definition)
Chris@14 51 {
Chris@14 52 $instanceofConditionals = $definition->getInstanceofConditionals();
Chris@14 53 $autoconfiguredInstanceof = $definition->isAutoconfigured() ? $container->getAutoconfiguredInstanceof() : array();
Chris@14 54 if (!$instanceofConditionals && !$autoconfiguredInstanceof) {
Chris@14 55 return $definition;
Chris@14 56 }
Chris@14 57
Chris@14 58 if (!$class = $container->getParameterBag()->resolveValue($definition->getClass())) {
Chris@14 59 return $definition;
Chris@14 60 }
Chris@14 61
Chris@14 62 $conditionals = $this->mergeConditionals($autoconfiguredInstanceof, $instanceofConditionals, $container);
Chris@14 63
Chris@14 64 $definition->setInstanceofConditionals(array());
Chris@14 65 $parent = $shared = null;
Chris@14 66 $instanceofTags = array();
Chris@14 67
Chris@14 68 foreach ($conditionals as $interface => $instanceofDefs) {
Chris@14 69 if ($interface !== $class && (!$container->getReflectionClass($class, false))) {
Chris@14 70 continue;
Chris@14 71 }
Chris@14 72
Chris@14 73 if ($interface !== $class && !is_subclass_of($class, $interface)) {
Chris@14 74 continue;
Chris@14 75 }
Chris@14 76
Chris@14 77 foreach ($instanceofDefs as $key => $instanceofDef) {
Chris@14 78 /** @var ChildDefinition $instanceofDef */
Chris@14 79 $instanceofDef = clone $instanceofDef;
Chris@14 80 $instanceofDef->setAbstract(true)->setParent($parent ?: 'abstract.instanceof.'.$id);
Chris@14 81 $parent = 'instanceof.'.$interface.'.'.$key.'.'.$id;
Chris@14 82 $container->setDefinition($parent, $instanceofDef);
Chris@14 83 $instanceofTags[] = $instanceofDef->getTags();
Chris@14 84 $instanceofDef->setTags(array());
Chris@14 85
Chris@14 86 if (isset($instanceofDef->getChanges()['shared'])) {
Chris@14 87 $shared = $instanceofDef->isShared();
Chris@14 88 }
Chris@14 89 }
Chris@14 90 }
Chris@14 91
Chris@14 92 if ($parent) {
Chris@14 93 $bindings = $definition->getBindings();
Chris@14 94 $abstract = $container->setDefinition('abstract.instanceof.'.$id, $definition);
Chris@14 95
Chris@14 96 // cast Definition to ChildDefinition
Chris@14 97 $definition->setBindings(array());
Chris@14 98 $definition = serialize($definition);
Chris@14 99 $definition = substr_replace($definition, '53', 2, 2);
Chris@14 100 $definition = substr_replace($definition, 'Child', 44, 0);
Chris@14 101 $definition = unserialize($definition);
Chris@14 102 $definition->setParent($parent);
Chris@14 103
Chris@14 104 if (null !== $shared && !isset($definition->getChanges()['shared'])) {
Chris@14 105 $definition->setShared($shared);
Chris@14 106 }
Chris@14 107
Chris@14 108 $i = count($instanceofTags);
Chris@14 109 while (0 <= --$i) {
Chris@14 110 foreach ($instanceofTags[$i] as $k => $v) {
Chris@14 111 foreach ($v as $v) {
Chris@14 112 if ($definition->hasTag($k) && in_array($v, $definition->getTag($k))) {
Chris@14 113 continue;
Chris@14 114 }
Chris@14 115 $definition->addTag($k, $v);
Chris@14 116 }
Chris@14 117 }
Chris@14 118 }
Chris@14 119
Chris@14 120 // reset fields with "merge" behavior
Chris@14 121 $abstract
Chris@14 122 ->setBindings($bindings)
Chris@14 123 ->setArguments(array())
Chris@14 124 ->setMethodCalls(array())
Chris@14 125 ->setDecoratedService(null)
Chris@14 126 ->setTags(array())
Chris@14 127 ->setAbstract(true);
Chris@14 128 }
Chris@14 129
Chris@14 130 return $definition;
Chris@14 131 }
Chris@14 132
Chris@14 133 private function mergeConditionals(array $autoconfiguredInstanceof, array $instanceofConditionals, ContainerBuilder $container)
Chris@14 134 {
Chris@14 135 // make each value an array of ChildDefinition
Chris@14 136 $conditionals = array_map(function ($childDef) { return array($childDef); }, $autoconfiguredInstanceof);
Chris@14 137
Chris@14 138 foreach ($instanceofConditionals as $interface => $instanceofDef) {
Chris@14 139 // make sure the interface/class exists (but don't validate automaticInstanceofConditionals)
Chris@14 140 if (!$container->getReflectionClass($interface)) {
Chris@14 141 throw new RuntimeException(sprintf('"%s" is set as an "instanceof" conditional, but it does not exist.', $interface));
Chris@14 142 }
Chris@14 143
Chris@14 144 if (!isset($autoconfiguredInstanceof[$interface])) {
Chris@14 145 $conditionals[$interface] = array();
Chris@14 146 }
Chris@14 147
Chris@14 148 $conditionals[$interface][] = $instanceofDef;
Chris@14 149 }
Chris@14 150
Chris@14 151 return $conditionals;
Chris@14 152 }
Chris@14 153 }