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 }
|