These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /* |
||
4 | * This file is part of the CrossContainerExtension package. |
||
5 | * |
||
6 | * (c) Kamil Kokot <[email protected]> |
||
7 | * |
||
8 | * For the full copyright and license information, please view the LICENSE |
||
9 | * file that was distributed with this source code. |
||
10 | */ |
||
11 | |||
12 | namespace FriendsOfBehat\CrossContainerExtension; |
||
13 | |||
14 | use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; |
||
15 | use Symfony\Component\DependencyInjection\ContainerBuilder; |
||
16 | use Symfony\Component\DependencyInjection\Definition; |
||
17 | use Symfony\Component\DependencyInjection\Reference; |
||
18 | |||
19 | final class CrossContainerProcessor implements CompilerPassInterface |
||
20 | { |
||
21 | /** |
||
22 | * @var ContainerAccessor[] |
||
23 | */ |
||
24 | private $containerAccessors; |
||
25 | |||
26 | /** |
||
27 | * @param ContainerAccessor[] $containerAccessors |
||
28 | */ |
||
29 | public function __construct(array $containerAccessors = []) |
||
30 | { |
||
31 | foreach ($containerAccessors as $containerIdentifier => $containerAccessor) { |
||
32 | $this->addContainerAccessor($containerIdentifier, $containerAccessor); |
||
33 | } |
||
34 | } |
||
35 | |||
36 | /** |
||
37 | * @param string $containerIdentifier |
||
38 | * @param ContainerAccessor $containerAccessor |
||
39 | */ |
||
40 | public function addContainerAccessor($containerIdentifier, ContainerAccessor $containerAccessor) |
||
41 | { |
||
42 | $this->containerAccessors[$containerIdentifier] = $containerAccessor; |
||
43 | } |
||
44 | |||
45 | /** |
||
46 | * {@inheritdoc} |
||
47 | */ |
||
48 | public function process(ContainerBuilder $container) |
||
49 | { |
||
50 | foreach ($container->getDefinitions() as $identifier => $definition) { |
||
51 | $container->setDefinition($identifier, $this->resolveDefinition($definition)); |
||
52 | } |
||
53 | |||
54 | $this->copyParameters($container); |
||
55 | } |
||
56 | |||
57 | /** |
||
58 | * @param Definition $definition |
||
59 | * |
||
60 | * @return Definition |
||
61 | */ |
||
62 | private function resolveDefinition(Definition $definition) |
||
63 | { |
||
64 | $definition->setArguments($this->resolveArguments($definition->getArguments())); |
||
65 | $definition->setFactory($this->resolveFactory($definition->getFactory())); |
||
0 ignored issues
–
show
It seems like
$this->resolveFactory($definition->getFactory()) targeting FriendsOfBehat\CrossCont...essor::resolveFactory() can also be of type null ; however, Symfony\Component\Depend...efinition::setFactory() does only seem to accept string|array , maybe add an additional type check?
This check looks at variables that are passed out again to other methods. If the outgoing method call has stricter type requirements than the method itself, an issue is raised. An additional type check may prevent trouble.
Loading history...
|
|||
66 | |||
67 | return $definition; |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * @param array|null $factory |
||
72 | * |
||
73 | * @return array|null |
||
74 | */ |
||
75 | private function resolveFactory($factory) |
||
76 | { |
||
77 | if ([] === $factory) { |
||
78 | return []; |
||
79 | } |
||
80 | |||
81 | if (isset($factory[0]) && $factory[0] instanceof Reference) { |
||
82 | $factory[0] = $this->resolveReference($factory[0]); |
||
83 | } |
||
84 | |||
85 | return $factory; |
||
86 | } |
||
87 | |||
88 | /** |
||
89 | * @param array $arguments |
||
90 | * |
||
91 | * @return array |
||
92 | */ |
||
93 | private function resolveArguments(array $arguments) |
||
94 | { |
||
95 | return array_map(function ($argument){ |
||
96 | return $this->resolveArgument($argument); |
||
97 | }, $arguments); |
||
98 | } |
||
99 | |||
100 | /** |
||
101 | * @param mixed $argument |
||
102 | * |
||
103 | * @return mixed |
||
104 | */ |
||
105 | private function resolveArgument($argument) |
||
106 | { |
||
107 | if ($argument instanceof Definition) { |
||
108 | return $this->resolveDefinition($argument); |
||
109 | } |
||
110 | |||
111 | if ($argument instanceof Reference) { |
||
112 | return $this->resolveReference($argument); |
||
113 | } |
||
114 | |||
115 | if (is_array($argument)) { |
||
116 | return $this->resolveArguments($argument); |
||
117 | } |
||
118 | |||
119 | return $argument; |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * @param Reference $reference |
||
124 | * |
||
125 | * @return Definition|Reference |
||
126 | */ |
||
127 | private function resolveReference(Reference $reference) |
||
128 | { |
||
129 | if (!ExternalReference::isValid($reference)) { |
||
130 | return $reference; |
||
131 | } |
||
132 | |||
133 | return $this->transformReferenceToDefinition(new ExternalReference($reference)); |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * @param ExternalReference $externalReference |
||
138 | * |
||
139 | * @return Definition |
||
140 | */ |
||
141 | private function transformReferenceToDefinition(ExternalReference $externalReference) |
||
142 | { |
||
143 | $this->assertExternalReferenceHasKnownContainer($externalReference); |
||
144 | |||
145 | $definition = new Definition(null, [$externalReference->serviceIdentifier()]); |
||
146 | $definition->setFactory([$this->containerAccessors[$externalReference->containerIdentifier()], 'getService']); |
||
147 | |||
148 | return $definition; |
||
149 | } |
||
150 | |||
151 | /** |
||
152 | * @param ExternalReference $externalReference |
||
153 | * |
||
154 | * @throws \DomainException |
||
155 | */ |
||
156 | private function assertExternalReferenceHasKnownContainer(ExternalReference $externalReference) |
||
157 | { |
||
158 | if (!isset($this->containerAccessors[$externalReference->containerIdentifier()])) { |
||
159 | throw new \DomainException(sprintf( |
||
160 | 'External container with identifier "%s" does not exist.', |
||
161 | $externalReference->containerIdentifier() |
||
162 | )); |
||
163 | } |
||
164 | } |
||
165 | |||
166 | /** |
||
167 | * @param ContainerBuilder $container |
||
168 | */ |
||
169 | private function copyParameters(ContainerBuilder $container) |
||
170 | { |
||
171 | foreach ($this->containerAccessors as $containerIdentifier => $containerAccessor) { |
||
172 | foreach ($containerAccessor->getParameters() as $name => $value) { |
||
173 | $container->setParameter(sprintf('__%s__.%s', $containerIdentifier, $name), $value); |
||
174 | } |
||
175 | } |
||
176 | } |
||
177 | } |
||
178 |
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.