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