This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection; |
||
4 | |||
5 | use Doctrine\ORM\EntityManager; |
||
6 | use ReflectionClass; |
||
7 | use Symfony\Component\Config\Definition\BaseNode; |
||
8 | use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition; |
||
9 | use Symfony\Component\Config\Definition\Builder\NodeDefinition; |
||
10 | use Symfony\Component\Config\Definition\Builder\TreeBuilder; |
||
11 | use Symfony\Component\Config\Definition\ConfigurationInterface; |
||
12 | use Symfony\Component\DependencyInjection\Exception\LogicException; |
||
13 | use function array_key_exists; |
||
14 | use function in_array; |
||
15 | use function is_array; |
||
16 | |||
17 | /** |
||
18 | * This class contains the configuration information for the bundle |
||
19 | * |
||
20 | * This information is solely responsible for how the different configuration |
||
21 | * sections are normalized, and merged. |
||
22 | */ |
||
23 | class Configuration implements ConfigurationInterface |
||
24 | { |
||
25 | /** @var bool */ |
||
26 | private $debug; |
||
27 | |||
28 | /** |
||
29 | * @param bool $debug Whether to use the debug mode |
||
30 | */ |
||
31 | public function __construct($debug) |
||
32 | { |
||
33 | $this->debug = (bool) $debug; |
||
34 | } |
||
35 | |||
36 | /** |
||
37 | * {@inheritDoc} |
||
38 | */ |
||
39 | public function getConfigTreeBuilder() : TreeBuilder |
||
40 | { |
||
41 | $treeBuilder = new TreeBuilder('doctrine'); |
||
42 | $rootNode = $treeBuilder->getRootNode(); |
||
43 | |||
44 | $this->addDbalSection($rootNode); |
||
0 ignored issues
–
show
|
|||
45 | $this->addOrmSection($rootNode); |
||
0 ignored issues
–
show
$rootNode of type object<Symfony\Component...Builder\NodeDefinition> is not a sub-type of object<Symfony\Component...er\ArrayNodeDefinition> . It seems like you assume a child class of the class Symfony\Component\Config...\Builder\NodeDefinition to be always present.
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass. Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type. ![]() |
|||
46 | |||
47 | return $treeBuilder; |
||
48 | } |
||
49 | |||
50 | /** |
||
51 | * Add DBAL section to configuration tree |
||
52 | */ |
||
53 | private function addDbalSection(ArrayNodeDefinition $node) : void |
||
54 | { |
||
55 | $node |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
Symfony\Component\Config...\Builder\NodeDefinition as the method children() does only exist in the following sub-classes of Symfony\Component\Config...\Builder\NodeDefinition : Symfony\Component\Config...der\ArrayNodeDefinition . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
56 | ->children() |
||
57 | ->arrayNode('dbal') |
||
58 | ->beforeNormalization() |
||
59 | ->ifTrue(static function ($v) { |
||
60 | return is_array($v) && ! array_key_exists('connections', $v) && ! array_key_exists('connection', $v); |
||
61 | }) |
||
62 | ->then(static function ($v) { |
||
63 | // Key that should not be rewritten to the connection config |
||
64 | $excludedKeys = ['default_connection' => true, 'types' => true, 'type' => true]; |
||
65 | $connection = []; |
||
66 | View Code Duplication | foreach ($v as $key => $value) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
67 | if (isset($excludedKeys[$key])) { |
||
68 | continue; |
||
69 | } |
||
70 | $connection[$key] = $v[$key]; |
||
71 | unset($v[$key]); |
||
72 | } |
||
73 | $v['default_connection'] = isset($v['default_connection']) ? (string) $v['default_connection'] : 'default'; |
||
74 | $v['connections'] = [$v['default_connection'] => $connection]; |
||
75 | |||
76 | return $v; |
||
77 | }) |
||
78 | ->end() |
||
79 | ->children() |
||
80 | ->scalarNode('default_connection')->end() |
||
81 | ->end() |
||
82 | ->fixXmlConfig('type') |
||
83 | ->children() |
||
84 | ->arrayNode('types') |
||
85 | ->useAttributeAsKey('name') |
||
86 | ->prototype('array') |
||
87 | ->beforeNormalization() |
||
88 | ->ifString() |
||
89 | ->then(static function ($v) { |
||
90 | return ['class' => $v]; |
||
91 | }) |
||
92 | ->end() |
||
93 | ->children() |
||
94 | ->scalarNode('class')->isRequired()->end() |
||
95 | ->booleanNode('commented')->setDeprecated(...$this->getCommentedParamDeprecationMsg())->end() |
||
96 | ->end() |
||
97 | ->end() |
||
98 | ->end() |
||
99 | ->end() |
||
100 | ->fixXmlConfig('connection') |
||
101 | ->append($this->getDbalConnectionsNode()) |
||
102 | ->end(); |
||
103 | } |
||
104 | |||
105 | /** |
||
106 | * Return the dbal connections node |
||
107 | */ |
||
108 | private function getDbalConnectionsNode() : ArrayNodeDefinition |
||
109 | { |
||
110 | $treeBuilder = new TreeBuilder('connections'); |
||
111 | $node = $treeBuilder->getRootNode(); |
||
112 | |||
113 | /** @var ArrayNodeDefinition $connectionNode */ |
||
114 | $connectionNode = $node |
||
115 | ->requiresAtLeastOneElement() |
||
116 | ->useAttributeAsKey('name') |
||
117 | ->prototype('array'); |
||
118 | |||
119 | $this->configureDbalDriverNode($connectionNode); |
||
120 | |||
121 | $connectionNode |
||
122 | ->fixXmlConfig('option') |
||
123 | ->fixXmlConfig('mapping_type') |
||
124 | ->fixXmlConfig('slave') |
||
125 | ->fixXmlConfig('shard') |
||
126 | ->fixXmlConfig('default_table_option') |
||
127 | ->children() |
||
128 | ->scalarNode('driver')->defaultValue('pdo_mysql')->end() |
||
129 | ->scalarNode('platform_service')->end() |
||
130 | ->booleanNode('auto_commit')->end() |
||
131 | ->scalarNode('schema_filter')->end() |
||
132 | ->booleanNode('logging')->defaultValue($this->debug)->end() |
||
133 | ->booleanNode('profiling')->defaultValue($this->debug)->end() |
||
134 | ->booleanNode('profiling_collect_backtrace') |
||
135 | ->defaultValue(false) |
||
136 | ->info('Enables collecting backtraces when profiling is enabled') |
||
137 | ->end() |
||
138 | ->booleanNode('profiling_collect_schema_errors') |
||
139 | ->defaultValue(true) |
||
140 | ->info('Enables collecting schema errors when profiling is enabled') |
||
141 | ->end() |
||
142 | ->scalarNode('server_version')->end() |
||
143 | ->scalarNode('driver_class')->end() |
||
144 | ->scalarNode('wrapper_class')->end() |
||
145 | ->scalarNode('shard_manager_class')->end() |
||
146 | ->scalarNode('shard_choser')->end() |
||
147 | ->scalarNode('shard_choser_service')->end() |
||
148 | ->booleanNode('keep_slave')->end() |
||
149 | ->arrayNode('options') |
||
150 | ->useAttributeAsKey('key') |
||
151 | ->prototype('variable')->end() |
||
152 | ->end() |
||
153 | ->arrayNode('mapping_types') |
||
154 | ->useAttributeAsKey('name') |
||
155 | ->prototype('scalar')->end() |
||
156 | ->end() |
||
157 | ->arrayNode('default_table_options') |
||
158 | ->info("This option is used by the schema-tool and affects generated SQL. Possible keys include 'charset','collate', and 'engine'.") |
||
159 | ->useAttributeAsKey('name') |
||
160 | ->prototype('scalar')->end() |
||
161 | ->end() |
||
162 | ->end(); |
||
163 | |||
164 | $slaveNode = $connectionNode |
||
165 | ->children() |
||
166 | ->arrayNode('slaves') |
||
167 | ->useAttributeAsKey('name') |
||
168 | ->prototype('array'); |
||
169 | $this->configureDbalDriverNode($slaveNode); |
||
0 ignored issues
–
show
$slaveNode of type object<Symfony\Component...Builder\NodeDefinition> is not a sub-type of object<Symfony\Component...er\ArrayNodeDefinition> . It seems like you assume a child class of the class Symfony\Component\Config...\Builder\NodeDefinition to be always present.
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass. Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type. ![]() |
|||
170 | |||
171 | $shardNode = $connectionNode |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
Symfony\Component\Config...\Builder\NodeDefinition as the method children() does only exist in the following sub-classes of Symfony\Component\Config...\Builder\NodeDefinition : Symfony\Component\Config...der\ArrayNodeDefinition . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
172 | ->children() |
||
173 | ->arrayNode('shards') |
||
174 | ->prototype('array') |
||
175 | ->children() |
||
176 | ->integerNode('id') |
||
177 | ->min(1) |
||
178 | ->isRequired() |
||
179 | ->end() |
||
180 | ->end(); |
||
181 | $this->configureDbalDriverNode($shardNode); |
||
182 | |||
183 | return $node; |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Adds config keys related to params processed by the DBAL drivers |
||
188 | * |
||
189 | * These keys are available for slave configurations too. |
||
190 | */ |
||
191 | private function configureDbalDriverNode(ArrayNodeDefinition $node) : void |
||
192 | { |
||
193 | $node |
||
194 | ->children() |
||
195 | ->scalarNode('url')->info('A URL with connection information; any parameter value parsed from this string will override explicitly set parameters')->end() |
||
196 | ->scalarNode('dbname')->end() |
||
197 | ->scalarNode('host')->defaultValue('localhost')->end() |
||
198 | ->scalarNode('port')->defaultNull()->end() |
||
199 | ->scalarNode('user')->defaultValue('root')->end() |
||
200 | ->scalarNode('password')->defaultNull()->end() |
||
201 | ->scalarNode('application_name')->end() |
||
202 | ->scalarNode('charset')->end() |
||
203 | ->scalarNode('path')->end() |
||
204 | ->booleanNode('memory')->end() |
||
205 | ->scalarNode('unix_socket')->info('The unix socket to use for MySQL')->end() |
||
206 | ->booleanNode('persistent')->info('True to use as persistent connection for the ibm_db2 driver')->end() |
||
207 | ->scalarNode('protocol')->info('The protocol to use for the ibm_db2 driver (default to TCPIP if omitted)')->end() |
||
208 | ->booleanNode('service') |
||
209 | ->info('True to use SERVICE_NAME as connection parameter instead of SID for Oracle') |
||
210 | ->end() |
||
211 | ->scalarNode('servicename') |
||
212 | ->info( |
||
213 | 'Overrules dbname parameter if given and used as SERVICE_NAME or SID connection parameter ' . |
||
214 | 'for Oracle depending on the service parameter.' |
||
215 | ) |
||
216 | ->end() |
||
217 | ->scalarNode('sessionMode') |
||
218 | ->info('The session mode to use for the oci8 driver') |
||
219 | ->end() |
||
220 | ->scalarNode('server') |
||
221 | ->info('The name of a running database server to connect to for SQL Anywhere.') |
||
222 | ->end() |
||
223 | ->scalarNode('default_dbname') |
||
224 | ->info( |
||
225 | 'Override the default database (postgres) to connect to for PostgreSQL connexion.' |
||
226 | ) |
||
227 | ->end() |
||
228 | ->scalarNode('sslmode') |
||
229 | ->info( |
||
230 | 'Determines whether or with what priority a SSL TCP/IP connection will be negotiated with ' . |
||
231 | 'the server for PostgreSQL.' |
||
232 | ) |
||
233 | ->end() |
||
234 | ->scalarNode('sslrootcert') |
||
235 | ->info( |
||
236 | 'The name of a file containing SSL certificate authority (CA) certificate(s). ' . |
||
237 | 'If the file exists, the server\'s certificate will be verified to be signed by one of these authorities.' |
||
238 | ) |
||
239 | ->end() |
||
240 | ->scalarNode('sslcert') |
||
241 | ->info( |
||
242 | 'The path to the SSL client certificate file for PostgreSQL.' |
||
243 | ) |
||
244 | ->end() |
||
245 | ->scalarNode('sslkey') |
||
246 | ->info( |
||
247 | 'The path to the SSL client key file for PostgreSQL.' |
||
248 | ) |
||
249 | ->end() |
||
250 | ->scalarNode('sslcrl') |
||
251 | ->info( |
||
252 | 'The file name of the SSL certificate revocation list for PostgreSQL.' |
||
253 | ) |
||
254 | ->end() |
||
255 | ->booleanNode('pooled')->info('True to use a pooled server with the oci8/pdo_oracle driver')->end() |
||
256 | ->booleanNode('MultipleActiveResultSets')->info('Configuring MultipleActiveResultSets for the pdo_sqlsrv driver')->end() |
||
257 | ->booleanNode('use_savepoints')->info('Use savepoints for nested transactions')->end() |
||
258 | ->scalarNode('instancename') |
||
259 | ->info( |
||
260 | 'Optional parameter, complete whether to add the INSTANCE_NAME parameter in the connection.' . |
||
261 | ' It is generally used to connect to an Oracle RAC server to select the name' . |
||
262 | ' of a particular instance.' |
||
263 | ) |
||
264 | ->end() |
||
265 | ->scalarNode('connectstring') |
||
266 | ->info( |
||
267 | 'Complete Easy Connect connection descriptor, see https://docs.oracle.com/database/121/NETAG/naming.htm.' . |
||
268 | 'When using this option, you will still need to provide the user and password parameters, but the other ' . |
||
269 | 'parameters will no longer be used. Note that when using this parameter, the getHost and getPort methods' . |
||
270 | ' from Doctrine\DBAL\Connection will no longer function as expected.' |
||
271 | ) |
||
272 | ->end() |
||
273 | ->end() |
||
274 | ->beforeNormalization() |
||
275 | ->ifTrue(static function ($v) { |
||
276 | return ! isset($v['sessionMode']) && isset($v['session_mode']); |
||
277 | }) |
||
278 | ->then(static function ($v) { |
||
279 | $v['sessionMode'] = $v['session_mode']; |
||
280 | unset($v['session_mode']); |
||
281 | |||
282 | return $v; |
||
283 | }) |
||
284 | ->end() |
||
285 | ->beforeNormalization() |
||
286 | ->ifTrue(static function ($v) { |
||
287 | return ! isset($v['MultipleActiveResultSets']) && isset($v['multiple_active_result_sets']); |
||
288 | }) |
||
289 | ->then(static function ($v) { |
||
290 | $v['MultipleActiveResultSets'] = $v['multiple_active_result_sets']; |
||
291 | unset($v['multiple_active_result_sets']); |
||
292 | |||
293 | return $v; |
||
294 | }) |
||
295 | ->end(); |
||
296 | } |
||
297 | |||
298 | /** |
||
299 | * Add the ORM section to configuration tree |
||
300 | */ |
||
301 | private function addOrmSection(ArrayNodeDefinition $node) : void |
||
302 | { |
||
303 | $node |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
Symfony\Component\Config...\Builder\NodeDefinition as the method children() does only exist in the following sub-classes of Symfony\Component\Config...\Builder\NodeDefinition : Symfony\Component\Config...der\ArrayNodeDefinition . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
304 | ->children() |
||
305 | ->arrayNode('orm') |
||
306 | ->beforeNormalization() |
||
307 | ->ifTrue(static function ($v) { |
||
308 | if (! empty($v) && ! class_exists(EntityManager::class)) { |
||
309 | throw new LogicException('The doctrine/orm package is required when the doctrine.orm config is set.'); |
||
310 | } |
||
311 | |||
312 | return $v === null || (is_array($v) && ! array_key_exists('entity_managers', $v) && ! array_key_exists('entity_manager', $v)); |
||
313 | }) |
||
314 | ->then(static function ($v) { |
||
315 | $v = (array) $v; |
||
316 | // Key that should not be rewritten to the connection config |
||
317 | $excludedKeys = [ |
||
318 | 'default_entity_manager' => true, |
||
319 | 'auto_generate_proxy_classes' => true, |
||
320 | 'proxy_dir' => true, |
||
321 | 'proxy_namespace' => true, |
||
322 | 'resolve_target_entities' => true, |
||
323 | 'resolve_target_entity' => true, |
||
324 | ]; |
||
325 | $entityManager = []; |
||
326 | View Code Duplication | foreach ($v as $key => $value) { |
|
0 ignored issues
–
show
This code seems to be duplicated across your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
327 | if (isset($excludedKeys[$key])) { |
||
328 | continue; |
||
329 | } |
||
330 | $entityManager[$key] = $v[$key]; |
||
331 | unset($v[$key]); |
||
332 | } |
||
333 | $v['default_entity_manager'] = isset($v['default_entity_manager']) ? (string) $v['default_entity_manager'] : 'default'; |
||
334 | $v['entity_managers'] = [$v['default_entity_manager'] => $entityManager]; |
||
335 | |||
336 | return $v; |
||
337 | }) |
||
338 | ->end() |
||
339 | ->children() |
||
340 | ->scalarNode('default_entity_manager')->end() |
||
341 | ->scalarNode('auto_generate_proxy_classes')->defaultValue(false) |
||
342 | ->info('Auto generate mode possible values are: "NEVER", "ALWAYS", "FILE_NOT_EXISTS", "EVAL"') |
||
343 | ->validate() |
||
344 | ->ifTrue(function ($v) { |
||
345 | $generationModes = $this->getAutoGenerateModes(); |
||
346 | |||
347 | if (is_int($v) && in_array($v, $generationModes['values']/*array(0, 1, 2, 3)*/)) { |
||
348 | return false; |
||
349 | } |
||
350 | if (is_bool($v)) { |
||
351 | return false; |
||
352 | } |
||
353 | if (is_string($v)) { |
||
354 | if (in_array(strtoupper($v), $generationModes['names']/*array('NEVER', 'ALWAYS', 'FILE_NOT_EXISTS', 'EVAL')*/)) { |
||
355 | return false; |
||
356 | } |
||
357 | } |
||
358 | |||
359 | return true; |
||
360 | }) |
||
361 | ->thenInvalid('Invalid auto generate mode value %s') |
||
362 | ->end() |
||
363 | ->validate() |
||
364 | ->ifString() |
||
365 | ->then(static function ($v) { |
||
366 | return constant('Doctrine\Common\Proxy\AbstractProxyFactory::AUTOGENERATE_' . strtoupper($v)); |
||
367 | }) |
||
368 | ->end() |
||
369 | ->end() |
||
370 | ->scalarNode('proxy_dir')->defaultValue('%kernel.cache_dir%/doctrine/orm/Proxies')->end() |
||
371 | ->scalarNode('proxy_namespace')->defaultValue('Proxies')->end() |
||
372 | ->end() |
||
373 | ->fixXmlConfig('entity_manager') |
||
374 | ->append($this->getOrmEntityManagersNode()) |
||
375 | ->fixXmlConfig('resolve_target_entity', 'resolve_target_entities') |
||
376 | ->append($this->getOrmTargetEntityResolverNode()) |
||
377 | ->end() |
||
378 | ->end(); |
||
379 | } |
||
380 | |||
381 | /** |
||
382 | * Return ORM target entity resolver node |
||
383 | */ |
||
384 | private function getOrmTargetEntityResolverNode() : NodeDefinition |
||
385 | { |
||
386 | $treeBuilder = new TreeBuilder('resolve_target_entities'); |
||
387 | $node = $treeBuilder->getRootNode(); |
||
388 | |||
389 | $node |
||
0 ignored issues
–
show
The method
useAttributeAsKey() does not exist on Symfony\Component\Config...\Builder\NodeDefinition . Did you maybe mean attribute() ?
This check marks calls to methods that do not seem to exist on an object. This is most likely the result of a method being renamed without all references to it being renamed likewise. ![]() |
|||
390 | ->useAttributeAsKey('interface') |
||
391 | ->prototype('scalar') |
||
392 | ->cannotBeEmpty() |
||
393 | ->end(); |
||
394 | |||
395 | return $node; |
||
396 | } |
||
397 | |||
398 | /** |
||
399 | * Return ORM entity listener node |
||
400 | */ |
||
401 | private function getOrmEntityListenersNode() : NodeDefinition |
||
402 | { |
||
403 | $treeBuilder = new TreeBuilder('entity_listeners'); |
||
404 | $node = $treeBuilder->getRootNode(); |
||
405 | |||
406 | $normalizer = static function ($mappings) { |
||
407 | $entities = []; |
||
408 | |||
409 | foreach ($mappings as $entityClass => $mapping) { |
||
410 | $listeners = []; |
||
411 | |||
412 | foreach ($mapping as $listenerClass => $listenerEvent) { |
||
413 | $events = []; |
||
414 | |||
415 | foreach ($listenerEvent as $eventType => $eventMapping) { |
||
416 | if ($eventMapping === null) { |
||
417 | $eventMapping = [null]; |
||
418 | } |
||
419 | |||
420 | foreach ($eventMapping as $method) { |
||
421 | $events[] = [ |
||
422 | 'type' => $eventType, |
||
423 | 'method' => $method, |
||
424 | ]; |
||
425 | } |
||
426 | } |
||
427 | |||
428 | $listeners[] = [ |
||
429 | 'class' => $listenerClass, |
||
430 | 'event' => $events, |
||
431 | ]; |
||
432 | } |
||
433 | |||
434 | $entities[] = [ |
||
435 | 'class' => $entityClass, |
||
436 | 'listener' => $listeners, |
||
437 | ]; |
||
438 | } |
||
439 | |||
440 | return ['entities' => $entities]; |
||
441 | }; |
||
442 | |||
443 | $node |
||
444 | ->beforeNormalization() |
||
445 | // Yaml normalization |
||
446 | ->ifTrue(static function ($v) { |
||
447 | return is_array(reset($v)) && is_string(key(reset($v))); |
||
448 | }) |
||
449 | ->then($normalizer) |
||
450 | ->end() |
||
451 | ->fixXmlConfig('entity', 'entities') |
||
452 | ->children() |
||
453 | ->arrayNode('entities') |
||
454 | ->useAttributeAsKey('class') |
||
455 | ->prototype('array') |
||
456 | ->fixXmlConfig('listener') |
||
457 | ->children() |
||
458 | ->arrayNode('listeners') |
||
459 | ->useAttributeAsKey('class') |
||
460 | ->prototype('array') |
||
461 | ->fixXmlConfig('event') |
||
462 | ->children() |
||
463 | ->arrayNode('events') |
||
464 | ->prototype('array') |
||
465 | ->children() |
||
466 | ->scalarNode('type')->end() |
||
467 | ->scalarNode('method')->defaultNull()->end() |
||
468 | ->end() |
||
469 | ->end() |
||
470 | ->end() |
||
471 | ->end() |
||
472 | ->end() |
||
473 | ->end() |
||
474 | ->end() |
||
475 | ->end() |
||
476 | ->end() |
||
477 | ->end(); |
||
478 | |||
479 | return $node; |
||
480 | } |
||
481 | |||
482 | /** |
||
483 | * Return ORM entity manager node |
||
484 | */ |
||
485 | private function getOrmEntityManagersNode() : ArrayNodeDefinition |
||
486 | { |
||
487 | $treeBuilder = new TreeBuilder('entity_managers'); |
||
488 | $node = $treeBuilder->getRootNode(); |
||
489 | |||
490 | $node |
||
491 | ->requiresAtLeastOneElement() |
||
492 | ->useAttributeAsKey('name') |
||
493 | ->prototype('array') |
||
494 | ->addDefaultsIfNotSet() |
||
495 | ->append($this->getOrmCacheDriverNode('query_cache_driver')) |
||
496 | ->append($this->getOrmCacheDriverNode('metadata_cache_driver')) |
||
497 | ->append($this->getOrmCacheDriverNode('result_cache_driver')) |
||
498 | ->append($this->getOrmEntityListenersNode()) |
||
499 | ->children() |
||
500 | ->scalarNode('connection')->end() |
||
501 | ->scalarNode('class_metadata_factory_name')->defaultValue('Doctrine\ORM\Mapping\ClassMetadataFactory')->end() |
||
502 | ->scalarNode('default_repository_class')->defaultValue('Doctrine\ORM\EntityRepository')->end() |
||
503 | ->scalarNode('auto_mapping')->defaultFalse()->end() |
||
504 | ->scalarNode('naming_strategy')->defaultValue('doctrine.orm.naming_strategy.default')->end() |
||
505 | ->scalarNode('quote_strategy')->defaultValue('doctrine.orm.quote_strategy.default')->end() |
||
506 | ->scalarNode('entity_listener_resolver')->defaultNull()->end() |
||
507 | ->scalarNode('repository_factory')->defaultValue('doctrine.orm.container_repository_factory')->end() |
||
508 | ->end() |
||
509 | ->children() |
||
510 | ->arrayNode('second_level_cache') |
||
511 | ->children() |
||
512 | ->append($this->getOrmCacheDriverNode('region_cache_driver')) |
||
513 | ->scalarNode('region_lock_lifetime')->defaultValue(60)->end() |
||
514 | ->booleanNode('log_enabled')->defaultValue($this->debug)->end() |
||
515 | ->scalarNode('region_lifetime')->defaultValue(0)->end() |
||
516 | ->booleanNode('enabled')->defaultValue(true)->end() |
||
517 | ->scalarNode('factory')->end() |
||
518 | ->end() |
||
519 | ->fixXmlConfig('region') |
||
520 | ->children() |
||
521 | ->arrayNode('regions') |
||
522 | ->useAttributeAsKey('name') |
||
523 | ->prototype('array') |
||
524 | ->children() |
||
525 | ->append($this->getOrmCacheDriverNode('cache_driver')) |
||
526 | ->scalarNode('lock_path')->defaultValue('%kernel.cache_dir%/doctrine/orm/slc/filelock')->end() |
||
527 | ->scalarNode('lock_lifetime')->defaultValue(60)->end() |
||
528 | ->scalarNode('type')->defaultValue('default')->end() |
||
529 | ->scalarNode('lifetime')->defaultValue(0)->end() |
||
530 | ->scalarNode('service')->end() |
||
531 | ->scalarNode('name')->end() |
||
532 | ->end() |
||
533 | ->end() |
||
534 | ->end() |
||
535 | ->end() |
||
536 | ->fixXmlConfig('logger') |
||
537 | ->children() |
||
538 | ->arrayNode('loggers') |
||
539 | ->useAttributeAsKey('name') |
||
540 | ->prototype('array') |
||
541 | ->children() |
||
542 | ->scalarNode('name')->end() |
||
543 | ->scalarNode('service')->end() |
||
544 | ->end() |
||
545 | ->end() |
||
546 | ->end() |
||
547 | ->end() |
||
548 | ->end() |
||
549 | ->end() |
||
550 | ->fixXmlConfig('hydrator') |
||
551 | ->children() |
||
552 | ->arrayNode('hydrators') |
||
553 | ->useAttributeAsKey('name') |
||
554 | ->prototype('scalar')->end() |
||
555 | ->end() |
||
556 | ->end() |
||
557 | ->fixXmlConfig('mapping') |
||
558 | ->children() |
||
559 | ->arrayNode('mappings') |
||
560 | ->useAttributeAsKey('name') |
||
561 | ->prototype('array') |
||
562 | ->beforeNormalization() |
||
563 | ->ifString() |
||
564 | ->then(static function ($v) { |
||
565 | return ['type' => $v]; |
||
566 | }) |
||
567 | ->end() |
||
568 | ->treatNullLike([]) |
||
569 | ->treatFalseLike(['mapping' => false]) |
||
570 | ->performNoDeepMerging() |
||
571 | ->children() |
||
572 | ->scalarNode('mapping')->defaultValue(true)->end() |
||
573 | ->scalarNode('type')->end() |
||
574 | ->scalarNode('dir')->end() |
||
575 | ->scalarNode('alias')->end() |
||
576 | ->scalarNode('prefix')->end() |
||
577 | ->booleanNode('is_bundle')->end() |
||
578 | ->end() |
||
579 | ->end() |
||
580 | ->end() |
||
581 | ->arrayNode('dql') |
||
582 | ->fixXmlConfig('string_function') |
||
583 | ->fixXmlConfig('numeric_function') |
||
584 | ->fixXmlConfig('datetime_function') |
||
585 | ->children() |
||
586 | ->arrayNode('string_functions') |
||
587 | ->useAttributeAsKey('name') |
||
588 | ->prototype('scalar')->end() |
||
589 | ->end() |
||
590 | ->arrayNode('numeric_functions') |
||
591 | ->useAttributeAsKey('name') |
||
592 | ->prototype('scalar')->end() |
||
593 | ->end() |
||
594 | ->arrayNode('datetime_functions') |
||
595 | ->useAttributeAsKey('name') |
||
596 | ->prototype('scalar')->end() |
||
597 | ->end() |
||
598 | ->end() |
||
599 | ->end() |
||
600 | ->end() |
||
601 | ->fixXmlConfig('filter') |
||
602 | ->children() |
||
603 | ->arrayNode('filters') |
||
604 | ->info('Register SQL Filters in the entity manager') |
||
605 | ->useAttributeAsKey('name') |
||
606 | ->prototype('array') |
||
607 | ->beforeNormalization() |
||
608 | ->ifString() |
||
609 | ->then(static function ($v) { |
||
610 | return ['class' => $v]; |
||
611 | }) |
||
612 | ->end() |
||
613 | ->beforeNormalization() |
||
614 | // The content of the XML node is returned as the "value" key so we need to rename it |
||
615 | ->ifTrue(static function ($v) { |
||
616 | return is_array($v) && isset($v['value']); |
||
617 | }) |
||
618 | ->then(static function ($v) { |
||
619 | $v['class'] = $v['value']; |
||
620 | unset($v['value']); |
||
621 | |||
622 | return $v; |
||
623 | }) |
||
624 | ->end() |
||
625 | ->fixXmlConfig('parameter') |
||
626 | ->children() |
||
627 | ->scalarNode('class')->isRequired()->end() |
||
628 | ->booleanNode('enabled')->defaultFalse()->end() |
||
629 | ->arrayNode('parameters') |
||
630 | ->useAttributeAsKey('name') |
||
631 | ->prototype('variable')->end() |
||
632 | ->end() |
||
633 | ->end() |
||
634 | ->end() |
||
635 | ->end() |
||
636 | ->end() |
||
637 | ->end(); |
||
638 | |||
639 | return $node; |
||
640 | } |
||
641 | |||
642 | /** |
||
643 | * Return a ORM cache driver node for an given entity manager |
||
644 | */ |
||
645 | private function getOrmCacheDriverNode(string $name) : ArrayNodeDefinition |
||
646 | { |
||
647 | $treeBuilder = new TreeBuilder($name); |
||
648 | $node = $treeBuilder->getRootNode(); |
||
649 | |||
650 | $node |
||
651 | ->addDefaultsIfNotSet() |
||
652 | ->beforeNormalization() |
||
653 | ->ifString() |
||
654 | ->then(static function ($v) : array { |
||
655 | return ['type' => $v]; |
||
656 | }) |
||
657 | ->end() |
||
658 | ->children() |
||
659 | ->scalarNode('type')->defaultNull()->end() |
||
660 | ->scalarNode('id')->end() |
||
661 | ->scalarNode('pool')->end() |
||
662 | ->end(); |
||
663 | |||
664 | return $node; |
||
665 | } |
||
666 | |||
667 | /** |
||
668 | * Find proxy auto generate modes for their names and int values |
||
669 | */ |
||
670 | private function getAutoGenerateModes() : array |
||
671 | { |
||
672 | $constPrefix = 'AUTOGENERATE_'; |
||
673 | $prefixLen = strlen($constPrefix); |
||
674 | $refClass = new ReflectionClass('Doctrine\Common\Proxy\AbstractProxyFactory'); |
||
675 | $constsArray = $refClass->getConstants(); |
||
676 | $namesArray = []; |
||
677 | $valuesArray = []; |
||
678 | |||
679 | foreach ($constsArray as $key => $value) { |
||
680 | if (strpos($key, $constPrefix) !== 0) { |
||
681 | continue; |
||
682 | } |
||
683 | |||
684 | $namesArray[] = substr($key, $prefixLen); |
||
685 | $valuesArray[] = (int) $value; |
||
686 | } |
||
687 | |||
688 | return [ |
||
689 | 'names' => $namesArray, |
||
690 | 'values' => $valuesArray, |
||
691 | ]; |
||
692 | } |
||
693 | |||
694 | /** |
||
695 | * Returns the correct deprecation param's as an array for setDeprecated. |
||
696 | * |
||
697 | * Symfony/Config v5.1 introduces a deprecation notice when calling |
||
698 | * setDeprecation() with less than 3 args and the getDeprecation method was |
||
699 | * introduced at the same time. By checking if getDeprecation() exists, |
||
700 | * we can determine the correct param count to use when calling setDeprecated. |
||
701 | */ |
||
702 | private function getCommentedParamDeprecationMsg() : array |
||
703 | { |
||
704 | $message = 'The doctrine-bundle type commenting features were removed; the corresponding config parameter was deprecated in 2.0 and will be dropped in 3.0.'; |
||
705 | |||
706 | if (method_exists(BaseNode::class, 'getDeprecation')) { |
||
707 | return [ |
||
708 | 'doctrine/doctrine-bundle', |
||
709 | '2.0', |
||
710 | $message, |
||
711 | ]; |
||
712 | } |
||
713 | |||
714 | return [$message]; |
||
715 | } |
||
716 | } |
||
717 |
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.
Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.