Completed
Push — master ( 22ecc2...971c40 )
by Marco
14:47
created

YamlDriver::loadMetadataForClass()   F

Complexity

Conditions 153
Paths > 20000

Size

Total Lines 618
Code Lines 320

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 278
CRAP Score 170.9327

Importance

Changes 0
Metric Value
dl 0
loc 618
c 0
b 0
f 0
ccs 278
cts 306
cp 0.9085
rs 2
cc 153
eloc 320
nc 153354241
nop 2
crap 170.9327

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/*
3
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the MIT license. For more information, see
17
 * <http://www.doctrine-project.org>.
18
 */
19
20
namespace Doctrine\ORM\Mapping\Driver;
21
22
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
23
use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder;
24
use Doctrine\Common\Persistence\Mapping\Driver\FileDriver;
25
use Doctrine\ORM\Mapping\ClassMetadata as Metadata;
26
use Doctrine\ORM\Mapping\MappingException;
27
use Symfony\Component\Yaml\Yaml;
28
29
/**
30
 * The YamlDriver reads the mapping metadata from yaml schema files.
31
 *
32
 * @since 2.0
33
 * @author Benjamin Eberlei <[email protected]>
34
 * @author Guilherme Blanco <[email protected]>
35
 * @author Jonathan H. Wage <[email protected]>
36
 * @author Roman Borschel <[email protected]>
37
 */
38
class YamlDriver extends FileDriver
39
{
40
    const DEFAULT_FILE_EXTENSION = '.dcm.yml';
41
42
    /**
43
     * {@inheritDoc}
44
     */
45 67
    public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION)
46
    {
47 67
        parent::__construct($locator, $fileExtension);
48 67
    }
49
50
    /**
51
     * {@inheritDoc}
52
     */
53 62
    public function loadMetadataForClass($className, ClassMetadata $metadata)
54
    {
55
        /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
56 62
        $element = $this->getElement($className);
57
58 60
        if ($element['type'] == 'entity') {
59 58
            if (isset($element['repositoryClass'])) {
60
                $metadata->setCustomRepositoryClass($element['repositoryClass']);
61
            }
62 58
            if (isset($element['readOnly']) && $element['readOnly'] == true) {
63 58
                $metadata->markReadOnly();
64
            }
65 16
        } else if ($element['type'] == 'mappedSuperclass') {
66 14
            $metadata->setCustomRepositoryClass(
67 14
                isset($element['repositoryClass']) ? $element['repositoryClass'] : null
68
            );
69 14
            $metadata->isMappedSuperclass = true;
70 2
        } else if ($element['type'] == 'embeddable') {
71
            $metadata->isEmbeddedClass = true;
72
        } else {
73 2
            throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
74
        }
75
76
        // Evaluate root level properties
77 58
        $primaryTable = [];
78
79 58
        if (isset($element['table'])) {
80 22
            $primaryTable['name'] = $element['table'];
81
        }
82
83 58
        if (isset($element['schema'])) {
84 2
            $primaryTable['schema'] = $element['schema'];
85
        }
86
87
        // Evaluate second level cache
88 58
        if (isset($element['cache'])) {
89 2
            $metadata->enableCache($this->cacheToArray($element['cache']));
90
        }
91
92 58
        $metadata->setPrimaryTable($primaryTable);
93
94
        // Evaluate named queries
95 58
        if (isset($element['namedQueries'])) {
96 4
            foreach ($element['namedQueries'] as $name => $queryMapping) {
97 4
                if (is_string($queryMapping)) {
98 4
                    $queryMapping = ['query' => $queryMapping];
99
                }
100
101 4
                if ( ! isset($queryMapping['name'])) {
102 4
                    $queryMapping['name'] = $name;
103
                }
104
105 4
                $metadata->addNamedQuery($queryMapping);
106
            }
107
        }
108
109
        // Evaluate named native queries
110 58
        if (isset($element['namedNativeQueries'])) {
111 6
            foreach ($element['namedNativeQueries'] as $name => $mappingElement) {
112 6
                if (!isset($mappingElement['name'])) {
113 6
                    $mappingElement['name'] = $name;
114
                }
115 6
                $metadata->addNamedNativeQuery(
116
                    [
117 6
                        'name'              => $mappingElement['name'],
118 6
                        'query'             => isset($mappingElement['query']) ? $mappingElement['query'] : null,
119 6
                        'resultClass'       => isset($mappingElement['resultClass']) ? $mappingElement['resultClass'] : null,
120 6
                        'resultSetMapping'  => isset($mappingElement['resultSetMapping']) ? $mappingElement['resultSetMapping'] : null,
121
                    ]
122
                );
123
            }
124
        }
125
126
        // Evaluate sql result set mappings
127 58
        if (isset($element['sqlResultSetMappings'])) {
128 6
            foreach ($element['sqlResultSetMappings'] as $name => $resultSetMapping) {
129 6
                if (!isset($resultSetMapping['name'])) {
130 6
                    $resultSetMapping['name'] = $name;
131
                }
132
133 6
                $entities = [];
134 6
                $columns  = [];
135 6
                if (isset($resultSetMapping['entityResult'])) {
136 6
                    foreach ($resultSetMapping['entityResult'] as $entityResultElement) {
137
                        $entityResult = [
138 6
                            'fields'                => [],
139 6
                            'entityClass'           => isset($entityResultElement['entityClass']) ? $entityResultElement['entityClass'] : null,
140 6
                            'discriminatorColumn'   => isset($entityResultElement['discriminatorColumn']) ? $entityResultElement['discriminatorColumn'] : null,
141
                        ];
142
143 6
                        if (isset($entityResultElement['fieldResult'])) {
144 6
                            foreach ($entityResultElement['fieldResult'] as $fieldResultElement) {
145 6
                                $entityResult['fields'][] = [
146 6
                                    'name'      => isset($fieldResultElement['name']) ? $fieldResultElement['name'] : null,
147 6
                                    'column'    => isset($fieldResultElement['column']) ? $fieldResultElement['column'] : null,
148
                                ];
149
                            }
150
                        }
151
152 6
                        $entities[] = $entityResult;
153
                    }
154
                }
155
156
157 6
                if (isset($resultSetMapping['columnResult'])) {
158 6
                    foreach ($resultSetMapping['columnResult'] as $columnResultAnnot) {
159 6
                        $columns[] = [
160 6
                            'name' => isset($columnResultAnnot['name']) ? $columnResultAnnot['name'] : null,
161
                        ];
162
                    }
163
                }
164
165 6
                $metadata->addSqlResultSetMapping(
166
                    [
167 6
                        'name'          => $resultSetMapping['name'],
168 6
                        'entities'      => $entities,
169 6
                        'columns'       => $columns
170
                    ]
171
                );
172
            }
173
        }
174
175 58
        if (isset($element['inheritanceType'])) {
176 18
            $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . strtoupper($element['inheritanceType'])));
177
178 18
            if ($metadata->inheritanceType != \Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) {
179
                // Evaluate discriminatorColumn
180 18
                if (isset($element['discriminatorColumn'])) {
181 12
                    $discrColumn = $element['discriminatorColumn'];
182 12
                    $metadata->setDiscriminatorColumn(
183
                        [
184 12
                            'name' => isset($discrColumn['name']) ? (string) $discrColumn['name'] : null,
185 12
                            'type' => isset($discrColumn['type']) ? (string) $discrColumn['type'] : 'string',
186 12
                            'length' => isset($discrColumn['length']) ? (string) $discrColumn['length'] : 255,
187 12
                            'columnDefinition' => isset($discrColumn['columnDefinition']) ? (string) $discrColumn['columnDefinition'] : null
188
                        ]
189
                    );
190
                } else {
191 12
                    $metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]);
192
                }
193
194
                // Evaluate discriminatorMap
195 18
                if (isset($element['discriminatorMap'])) {
196 18
                    $metadata->setDiscriminatorMap($element['discriminatorMap']);
197
                }
198
            }
199
        }
200
201
202
        // Evaluate changeTrackingPolicy
203 58
        if (isset($element['changeTrackingPolicy'])) {
204
            $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_'
205
                . strtoupper($element['changeTrackingPolicy'])));
206
        }
207
208
        // Evaluate indexes
209 58
        if (isset($element['indexes'])) {
210 6
            foreach ($element['indexes'] as $name => $indexYml) {
211 6
                if ( ! isset($indexYml['name'])) {
212 6
                    $indexYml['name'] = $name;
213
                }
214
215 6
                if (is_string($indexYml['columns'])) {
216 6
                    $index = ['columns' => array_map('trim', explode(',', $indexYml['columns']))];
217
                } else {
218
                    $index = ['columns' => $indexYml['columns']];
219
                }
220
221 6
                if (isset($indexYml['flags'])) {
222 2
                    if (is_string($indexYml['flags'])) {
223 2
                        $index['flags'] = array_map('trim', explode(',', $indexYml['flags']));
224
                    } else {
225
                        $index['flags'] = $indexYml['flags'];
226
                    }
227
                }
228
229 6
                if (isset($indexYml['options'])) {
230 2
                    $index['options'] = $indexYml['options'];
231
                }
232
233 6
                $metadata->table['indexes'][$indexYml['name']] = $index;
234
            }
235
        }
236
237
        // Evaluate uniqueConstraints
238 58
        if (isset($element['uniqueConstraints'])) {
239 5
            foreach ($element['uniqueConstraints'] as $name => $uniqueYml) {
240 5
                if ( ! isset($uniqueYml['name'])) {
241 5
                    $uniqueYml['name'] = $name;
242
                }
243
244 5
                if (is_string($uniqueYml['columns'])) {
245 4
                    $unique = ['columns' => array_map('trim', explode(',', $uniqueYml['columns']))];
246
                } else {
247 1
                    $unique = ['columns' => $uniqueYml['columns']];
248
                }
249
250 5
                if (isset($uniqueYml['options'])) {
251 2
                    $unique['options'] = $uniqueYml['options'];
252
                }
253
254 5
                $metadata->table['uniqueConstraints'][$uniqueYml['name']] = $unique;
255
            }
256
        }
257
258 58
        if (isset($element['options'])) {
259 4
            $metadata->table['options'] = $element['options'];
260
        }
261
262 58
        $associationIds = [];
263 58
        if (isset($element['id'])) {
264
            // Evaluate identifier settings
265 54
            foreach ($element['id'] as $name => $idElement) {
266 54
                if (isset($idElement['associationKey']) && $idElement['associationKey'] == true) {
267
                    $associationIds[$name] = true;
268
                    continue;
269
                }
270
271
                $mapping = [
272 54
                    'id' => true,
273 54
                    'fieldName' => $name
274
                ];
275
276 54
                if (isset($idElement['type'])) {
277 34
                    $mapping['type'] = $idElement['type'];
278
                }
279
280 54
                if (isset($idElement['column'])) {
281 8
                    $mapping['columnName'] = $idElement['column'];
282
                }
283
284 54
                if (isset($idElement['length'])) {
285 6
                    $mapping['length'] = $idElement['length'];
286
                }
287
288 54
                if (isset($idElement['columnDefinition'])) {
289 2
                    $mapping['columnDefinition'] = $idElement['columnDefinition'];
290
                }
291
292 54
                if (isset($idElement['options'])) {
293 2
                    $mapping['options'] = $idElement['options'];
294
                }
295
296 54
                $metadata->mapField($mapping);
297
298 54
                if (isset($idElement['generator'])) {
299 51
                    $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
300 51
                        . strtoupper($idElement['generator']['strategy'])));
301
                }
302
                // Check for SequenceGenerator/TableGenerator definition
303 54
                if (isset($idElement['sequenceGenerator'])) {
304 2
                    $metadata->setSequenceGeneratorDefinition($idElement['sequenceGenerator']);
305 52
                } else if (isset($idElement['customIdGenerator'])) {
306 4
                    $customGenerator = $idElement['customIdGenerator'];
307 4
                    $metadata->setCustomGeneratorDefinition(
308
                        [
309 4
                            'class' => (string) $customGenerator['class']
310
                        ]
311
                    );
312 48
                } else if (isset($idElement['tableGenerator'])) {
313 54
                    throw MappingException::tableIdGeneratorNotImplemented($className);
314
                }
315
            }
316
        }
317
318
        // Evaluate fields
319 58
        if (isset($element['fields'])) {
320 39
            foreach ($element['fields'] as $name => $fieldMapping) {
321
322 39
                $mapping = $this->columnToArray($name, $fieldMapping);
323
324 39
                if (isset($fieldMapping['id'])) {
325
                    $mapping['id'] = true;
326
                    if (isset($fieldMapping['generator']['strategy'])) {
327
                        $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
328
                            . strtoupper($fieldMapping['generator']['strategy'])));
329
                    }
330
                }
331
332 39
                if (isset($mapping['version'])) {
333 2
                    $metadata->setVersionMapping($mapping);
334 2
                    unset($mapping['version']);
335
                }
336
337 39
                $metadata->mapField($mapping);
338
            }
339
        }
340
341 58
        if (isset($element['embedded'])) {
342
            foreach ($element['embedded'] as $name => $embeddedMapping) {
343
                $mapping = [
344
                    'fieldName' => $name,
345
                    'class' => $embeddedMapping['class'],
346
                    'columnPrefix' => isset($embeddedMapping['columnPrefix']) ? $embeddedMapping['columnPrefix'] : null,
347
                ];
348
                $metadata->mapEmbedded($mapping);
349
            }
350
        }
351
352
        // Evaluate oneToOne relationships
353 58
        if (isset($element['oneToOne'])) {
354 11
            foreach ($element['oneToOne'] as $name => $oneToOneElement) {
355
                $mapping = [
356 11
                    'fieldName' => $name,
357 11
                    'targetEntity' => $oneToOneElement['targetEntity']
358
                ];
359
360 11
                if (isset($associationIds[$mapping['fieldName']])) {
361
                    $mapping['id'] = true;
362
                }
363
364 11
                if (isset($oneToOneElement['fetch'])) {
365 3
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToOneElement['fetch']);
366
                }
367
368 11
                if (isset($oneToOneElement['mappedBy'])) {
369 3
                    $mapping['mappedBy'] = $oneToOneElement['mappedBy'];
370
                } else {
371 10
                    if (isset($oneToOneElement['inversedBy'])) {
372 10
                        $mapping['inversedBy'] = $oneToOneElement['inversedBy'];
373
                    }
374
375 10
                    $joinColumns = [];
376
377 10
                    if (isset($oneToOneElement['joinColumn'])) {
378 9
                        $joinColumns[] = $this->joinColumnToArray($oneToOneElement['joinColumn']);
379 1
                    } else if (isset($oneToOneElement['joinColumns'])) {
380 1
                        foreach ($oneToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
381 1
                            if ( ! isset($joinColumnElement['name'])) {
382 1
                                $joinColumnElement['name'] = $joinColumnName;
383
                            }
384
385 1
                            $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
386
                        }
387
                    }
388
389 10
                    $mapping['joinColumns'] = $joinColumns;
390
                }
391
392 11
                if (isset($oneToOneElement['cascade'])) {
393 7
                    $mapping['cascade'] = $oneToOneElement['cascade'];
394
                }
395
396 11
                if (isset($oneToOneElement['orphanRemoval'])) {
397 5
                    $mapping['orphanRemoval'] = (bool) $oneToOneElement['orphanRemoval'];
398
                }
399
400
                // Evaluate second level cache
401 11
                if (isset($oneToOneElement['cache'])) {
402
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToOneElement['cache']));
403
                }
404
405 11
                $metadata->mapOneToOne($mapping);
406
            }
407
        }
408
409
        // Evaluate oneToMany relationships
410 58
        if (isset($element['oneToMany'])) {
411 6
            foreach ($element['oneToMany'] as $name => $oneToManyElement) {
412
                $mapping = [
413 6
                    'fieldName' => $name,
414 6
                    'targetEntity' => $oneToManyElement['targetEntity'],
415 6
                    'mappedBy' => $oneToManyElement['mappedBy']
416
                ];
417
418 6
                if (isset($oneToManyElement['fetch'])) {
419 2
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToManyElement['fetch']);
420
                }
421
422 6
                if (isset($oneToManyElement['cascade'])) {
423 4
                    $mapping['cascade'] = $oneToManyElement['cascade'];
424
                }
425
426 6
                if (isset($oneToManyElement['orphanRemoval'])) {
427 4
                    $mapping['orphanRemoval'] = (bool) $oneToManyElement['orphanRemoval'];
428
                }
429
430 6
                if (isset($oneToManyElement['orderBy'])) {
431 6
                    $mapping['orderBy'] = $oneToManyElement['orderBy'];
432
                }
433
434 6
                if (isset($oneToManyElement['indexBy'])) {
435
                    $mapping['indexBy'] = $oneToManyElement['indexBy'];
436
                }
437
438
439
                // Evaluate second level cache
440 6
                if (isset($oneToManyElement['cache'])) {
441 2
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToManyElement['cache']));
442
                }
443
444 6
                $metadata->mapOneToMany($mapping);
445
            }
446
        }
447
448
        // Evaluate manyToOne relationships
449 58
        if (isset($element['manyToOne'])) {
450 10
            foreach ($element['manyToOne'] as $name => $manyToOneElement) {
451
                $mapping = [
452 10
                    'fieldName' => $name,
453 10
                    'targetEntity' => $manyToOneElement['targetEntity']
454
                ];
455
456 10
                if (isset($associationIds[$mapping['fieldName']])) {
457
                    $mapping['id'] = true;
458
                }
459
460 10
                if (isset($manyToOneElement['fetch'])) {
461 1
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToOneElement['fetch']);
462
                }
463
464 10
                if (isset($manyToOneElement['inversedBy'])) {
465 2
                    $mapping['inversedBy'] = $manyToOneElement['inversedBy'];
466
                }
467
468 10
                $joinColumns = [];
469
470 10
                if (isset($manyToOneElement['joinColumn'])) {
471 4
                    $joinColumns[] = $this->joinColumnToArray($manyToOneElement['joinColumn']);
472 6
                } else if (isset($manyToOneElement['joinColumns'])) {
473 3
                    foreach ($manyToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
474 3
                        if ( ! isset($joinColumnElement['name'])) {
475 3
                            $joinColumnElement['name'] = $joinColumnName;
476
                        }
477
478 3
                        $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
479
                    }
480
                }
481
482 10
                $mapping['joinColumns'] = $joinColumns;
483
484 10
                if (isset($manyToOneElement['cascade'])) {
485 5
                    $mapping['cascade'] = $manyToOneElement['cascade'];
486
                }
487
488
                // Evaluate second level cache
489 10
                if (isset($manyToOneElement['cache'])) {
490 2
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToOneElement['cache']));
491
                }
492
493 10
                $metadata->mapManyToOne($mapping);
494
            }
495
        }
496
497
        // Evaluate manyToMany relationships
498 58
        if (isset($element['manyToMany'])) {
499 17
            foreach ($element['manyToMany'] as $name => $manyToManyElement) {
500
                $mapping = [
501 17
                    'fieldName' => $name,
502 17
                    'targetEntity' => $manyToManyElement['targetEntity']
503
                ];
504
505 17
                if (isset($manyToManyElement['fetch'])) {
506 2
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToManyElement['fetch']);
507
                }
508
509 17
                if (isset($manyToManyElement['mappedBy'])) {
510 2
                    $mapping['mappedBy'] = $manyToManyElement['mappedBy'];
511 15
                } else if (isset($manyToManyElement['joinTable'])) {
512
513 11
                    $joinTableElement = $manyToManyElement['joinTable'];
514
                    $joinTable = [
515 11
                        'name' => $joinTableElement['name']
516
                    ];
517
518 11
                    if (isset($joinTableElement['schema'])) {
519
                        $joinTable['schema'] = $joinTableElement['schema'];
520
                    }
521
522 11
                    if (isset($joinTableElement['joinColumns'])) {
523 11
                        foreach ($joinTableElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
524 11
                            if ( ! isset($joinColumnElement['name'])) {
525 10
                                $joinColumnElement['name'] = $joinColumnName;
526
                            }
527 11
                            $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
528
                        }
529
                    }
530
531 11
                    if (isset($joinTableElement['inverseJoinColumns'])) {
532 11
                        foreach ($joinTableElement['inverseJoinColumns'] as $joinColumnName => $joinColumnElement) {
533 11
                            if ( ! isset($joinColumnElement['name'])) {
534 10
                                $joinColumnElement['name'] = $joinColumnName;
535
                            }
536 11
                            $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
537
                        }
538
                    }
539
540 11
                    $mapping['joinTable'] = $joinTable;
541
                }
542
543 17
                if (isset($manyToManyElement['inversedBy'])) {
544 2
                    $mapping['inversedBy'] = $manyToManyElement['inversedBy'];
545
                }
546
547 17
                if (isset($manyToManyElement['cascade'])) {
548 10
                    $mapping['cascade'] = $manyToManyElement['cascade'];
549
                }
550
551 17
                if (isset($manyToManyElement['orderBy'])) {
552
                    $mapping['orderBy'] = $manyToManyElement['orderBy'];
553
                }
554
555 17
                if (isset($manyToManyElement['indexBy'])) {
556
                    $mapping['indexBy'] = $manyToManyElement['indexBy'];
557
                }
558
559 17
                if (isset($manyToManyElement['orphanRemoval'])) {
560
                    $mapping['orphanRemoval'] = (bool) $manyToManyElement['orphanRemoval'];
561
                }
562
563
                // Evaluate second level cache
564 17
                if (isset($manyToManyElement['cache'])) {
565
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToManyElement['cache']));
566
                }
567
568 17
                $metadata->mapManyToMany($mapping);
569
            }
570
        }
571
572
        // Evaluate associationOverride
573 58
        if (isset($element['associationOverride']) && is_array($element['associationOverride'])) {
574
575 8
            foreach ($element['associationOverride'] as $fieldName => $associationOverrideElement) {
576 8
                $override   = [];
577
578
                // Check for joinColumn
579 8
                if (isset($associationOverrideElement['joinColumn'])) {
580 4
                    $joinColumns = [];
581 4
                    foreach ($associationOverrideElement['joinColumn'] as $name => $joinColumnElement) {
582 4
                        if ( ! isset($joinColumnElement['name'])) {
583
                            $joinColumnElement['name'] = $name;
584
                        }
585 4
                        $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
586
                    }
587 4
                    $override['joinColumns'] = $joinColumns;
588
                }
589
590
                // Check for joinTable
591 8
                if (isset($associationOverrideElement['joinTable'])) {
592
593 4
                    $joinTableElement   = $associationOverrideElement['joinTable'];
594
                    $joinTable          =  [
595 4
                        'name' => $joinTableElement['name']
596
                    ];
597
598 4
                    if (isset($joinTableElement['schema'])) {
599
                        $joinTable['schema'] = $joinTableElement['schema'];
600
                    }
601
602 4
                    foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) {
603 4
                        if ( ! isset($joinColumnElement['name'])) {
604 4
                            $joinColumnElement['name'] = $name;
605
                        }
606
607 4
                        $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
608
                    }
609
610 4
                    foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) {
611 4
                        if ( ! isset($joinColumnElement['name'])) {
612 4
                            $joinColumnElement['name'] = $name;
613
                        }
614
615 4
                        $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
616
                    }
617
618 4
                    $override['joinTable'] = $joinTable;
619
                }
620
621
                // Check for inversedBy
622 8
                if (isset($associationOverrideElement['inversedBy'])) {
623 2
                    $override['inversedBy'] = (string) $associationOverrideElement['inversedBy'];
624
                }
625
626
                // Check for `fetch`
627 8
                if (isset($associationOverrideElement['fetch'])) {
628 2
                    $override['fetch'] = constant(Metadata::class . '::FETCH_' . $associationOverrideElement['fetch']);
629
                }
630
631 8
                $metadata->setAssociationOverride($fieldName, $override);
632
            }
633
        }
634
635
        // Evaluate associationOverride
636 58
        if (isset($element['attributeOverride']) && is_array($element['attributeOverride'])) {
637
638 4
            foreach ($element['attributeOverride'] as $fieldName => $attributeOverrideElement) {
639 4
                $mapping = $this->columnToArray($fieldName, $attributeOverrideElement);
640 4
                $metadata->setAttributeOverride($fieldName, $mapping);
641
            }
642
        }
643
644
        // Evaluate lifeCycleCallbacks
645 58
        if (isset($element['lifecycleCallbacks'])) {
646 5
            foreach ($element['lifecycleCallbacks'] as $type => $methods) {
647 4
                foreach ($methods as $method) {
648 4
                    $metadata->addLifecycleCallback($method, constant('Doctrine\ORM\Events::' . $type));
649
                }
650
            }
651
        }
652
653
        // Evaluate entityListeners
654 58
        if (isset($element['entityListeners'])) {
655 8
            foreach ($element['entityListeners'] as $className => $entityListener) {
656
                // Evaluate the listener using naming convention.
657 8
                if (empty($entityListener)) {
658 4
                    EntityListenerBuilder::bindEntityListener($metadata, $className);
0 ignored issues
show
Compatibility introduced by
$metadata of type object<Doctrine\ORM\Mapping\ClassMetadataInfo> is not a sub-type of object<Doctrine\ORM\Mapping\ClassMetadata>. It seems like you assume a child class of the class Doctrine\ORM\Mapping\ClassMetadataInfo 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.

Loading history...
659
660 4
                    continue;
661
                }
662
663 4
                foreach ($entityListener as $eventName => $callbackElement) {
664 4
                    foreach ($callbackElement as $methodName) {
665 4
                        $metadata->addEntityListener($eventName, $className, $methodName);
666
                    }
667
                }
668
            }
669
        }
670 58
    }
671
672
    /**
673
     * Constructs a joinColumn mapping array based on the information
674
     * found in the given join column element.
675
     *
676
     * @param array $joinColumnElement The array join column element.
677
     *
678
     * @return array The mapping array.
679
     */
680 17
    private function joinColumnToArray($joinColumnElement)
681
    {
682 17
        $joinColumn = [];
683 17
        if (isset($joinColumnElement['referencedColumnName'])) {
684 17
            $joinColumn['referencedColumnName'] = (string) $joinColumnElement['referencedColumnName'];
685
        }
686
687 17
        if (isset($joinColumnElement['name'])) {
688 13
            $joinColumn['name'] = (string) $joinColumnElement['name'];
689
        }
690
691 17
        if (isset($joinColumnElement['fieldName'])) {
692
            $joinColumn['fieldName'] = (string) $joinColumnElement['fieldName'];
693
        }
694
695 17
        if (isset($joinColumnElement['unique'])) {
696 4
            $joinColumn['unique'] = (bool) $joinColumnElement['unique'];
697
        }
698
699 17
        if (isset($joinColumnElement['nullable'])) {
700 6
            $joinColumn['nullable'] = (bool) $joinColumnElement['nullable'];
701
        }
702
703 17
        if (isset($joinColumnElement['onDelete'])) {
704 4
            $joinColumn['onDelete'] = $joinColumnElement['onDelete'];
705
        }
706
707 17
        if (isset($joinColumnElement['columnDefinition'])) {
708 4
            $joinColumn['columnDefinition'] = $joinColumnElement['columnDefinition'];
709
        }
710
711 17
        return $joinColumn;
712
    }
713
714
    /**
715
     * Parses the given column as array.
716
     *
717
     * @param string $fieldName
718
     * @param array  $column
719
     *
720
     * @return  array
721
     */
722 39
    private function columnToArray($fieldName, $column)
723
    {
724
        $mapping = [
725 39
            'fieldName' => $fieldName
726
        ];
727
728 39
        if (isset($column['type'])) {
729 33
            $params = explode('(', $column['type']);
730
731 33
            $column['type']  = $params[0];
732 33
            $mapping['type'] = $column['type'];
733
734 33
            if (isset($params[1])) {
735 2
                $column['length'] = (integer) substr($params[1], 0, strlen($params[1]) - 1);
736
            }
737
        }
738
739 39
        if (isset($column['column'])) {
740 11
            $mapping['columnName'] = $column['column'];
741
        }
742
743 39
        if (isset($column['length'])) {
744 21
            $mapping['length'] = $column['length'];
745
        }
746
747 39
        if (isset($column['precision'])) {
748
            $mapping['precision'] = $column['precision'];
749
        }
750
751 39
        if (isset($column['scale'])) {
752
            $mapping['scale'] = $column['scale'];
753
        }
754
755 39
        if (isset($column['unique'])) {
756 13
            $mapping['unique'] = (bool) $column['unique'];
757
        }
758
759 39
        if (isset($column['options'])) {
760 4
            $mapping['options'] = $column['options'];
761
        }
762
763 39
        if (isset($column['nullable'])) {
764 10
            $mapping['nullable'] = $column['nullable'];
765
        }
766
767 39
        if (isset($column['version']) && $column['version']) {
768 2
            $mapping['version'] = $column['version'];
769
        }
770
771 39
        if (isset($column['columnDefinition'])) {
772 6
            $mapping['columnDefinition'] = $column['columnDefinition'];
773
        }
774
775 39
        return $mapping;
776
    }
777
778
    /**
779
     * Parse / Normalize the cache configuration
780
     *
781
     * @param array $cacheMapping
782
     *
783
     * @return array
784
     */
785 2
    private function cacheToArray($cacheMapping)
786
    {
787 2
        $region = isset($cacheMapping['region']) ? (string) $cacheMapping['region'] : null;
788 2
        $usage  = isset($cacheMapping['usage']) ? strtoupper($cacheMapping['usage']) : null;
789
790 2
        if ($usage && ! defined('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage)) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $usage of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
791
            throw new \InvalidArgumentException(sprintf('Invalid cache usage "%s"', $usage));
792
        }
793
794 2
        if ($usage) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $usage of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
795 2
            $usage = constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage);
796
        }
797
798
        return [
799 2
            'usage'  => $usage,
800 2
            'region' => $region,
801
        ];
802
    }
803
804
    /**
805
     * {@inheritDoc}
806
     */
807 62
    protected function loadMappingFile($file)
808
    {
809 62
        if (defined(Yaml::class . '::PARSE_KEYS_AS_STRINGS')) {
810 62
            return Yaml::parse(file_get_contents($file), Yaml::PARSE_KEYS_AS_STRINGS);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Symfony\Componen...PARSE_KEYS_AS_STRINGS); (null|Symfony\Component\Y...e|string|array|stdClass) is incompatible with the return type declared by the abstract method Doctrine\Common\Persiste...Driver::loadMappingFile of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
811
        }
812
813
        return Yaml::parse(file_get_contents($file));
0 ignored issues
show
Bug Best Practice introduced by
The return type of return \Symfony\Componen...e_get_contents($file)); (null|Symfony\Component\Y...e|string|array|stdClass) is incompatible with the return type declared by the abstract method Doctrine\Common\Persiste...Driver::loadMappingFile of type array.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
814
    }
815
}
816