Completed
Pull Request — master (#6374)
by Antoine
11:18
created

YamlDriver::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
c 0
b 0
f 0
ccs 3
cts 3
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 2
crap 1
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\MappingException;
26
use Symfony\Component\Yaml\Yaml;
27
28
/**
29
 * The YamlDriver reads the mapping metadata from yaml schema files.
30
 *
31
 * @since 2.0
32
 * @author Benjamin Eberlei <[email protected]>
33
 * @author Guilherme Blanco <[email protected]>
34
 * @author Jonathan H. Wage <[email protected]>
35
 * @author Roman Borschel <[email protected]>
36
 */
37
class YamlDriver extends FileDriver
38
{
39
    const DEFAULT_FILE_EXTENSION = '.dcm.yml';
40
41
    /**
42
     * {@inheritDoc}
43
     */
44 67
    public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION)
45
    {
46 67
        parent::__construct($locator, $fileExtension);
47 67
    }
48
49
    /**
50
     * {@inheritDoc}
51
     */
52 62
    public function loadMetadataForClass($className, ClassMetadata $metadata)
53
    {
54
        /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
55 62
        $element = $this->getElement($className);
56
57 60
        if ($element['type'] == 'entity') {
58 50
            if (isset($element['repositoryClass'])) {
59
                $metadata->setCustomRepositoryClass($element['repositoryClass']);
60
            }
61 50
            if (isset($element['readOnly']) && $element['readOnly'] == true) {
62 50
                $metadata->markReadOnly();
63
            }
64 14
        } else if ($element['type'] == 'mappedSuperclass') {
65 12
            $metadata->setCustomRepositoryClass(
66 12
                isset($element['repositoryClass']) ? $element['repositoryClass'] : null
67
            );
68 12
            $metadata->isMappedSuperclass = true;
69 2
        } else if ($element['type'] == 'embeddable') {
70
            $metadata->isEmbeddedClass = true;
71
        } else {
72 2
            throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
73
        }
74
75
        // Evaluate root level properties
76 58
        $primaryTable = [];
77
78 58
        if (isset($element['table'])) {
79 24
            $primaryTable['name'] = $element['table'];
80
        }
81
82 58
        if (isset($element['schema'])) {
83 2
            $primaryTable['schema'] = $element['schema'];
84
        }
85
86
        // Evaluate second level cache
87 58
        if (isset($element['cache'])) {
88 2
            $metadata->enableCache($this->cacheToArray($element['cache']));
89
        }
90
91 58
        $metadata->setPrimaryTable($primaryTable);
92
93
        // Evaluate named queries
94 58
        if (isset($element['namedQueries'])) {
95 6
            foreach ($element['namedQueries'] as $name => $queryMapping) {
96 6
                if (is_string($queryMapping)) {
97 6
                    $queryMapping = ['query' => $queryMapping];
98
                }
99
100 6
                if ( ! isset($queryMapping['name'])) {
101 6
                    $queryMapping['name'] = $name;
102
                }
103
104 6
                $metadata->addNamedQuery($queryMapping);
105
            }
106
        }
107
108
        // Evaluate named native queries
109 58
        if (isset($element['namedNativeQueries'])) {
110 6
            foreach ($element['namedNativeQueries'] as $name => $mappingElement) {
111 6
                if (!isset($mappingElement['name'])) {
112 6
                    $mappingElement['name'] = $name;
113
                }
114 6
                $metadata->addNamedNativeQuery(
115
                    [
116 6
                        'name'              => $mappingElement['name'],
117 6
                        'query'             => isset($mappingElement['query']) ? $mappingElement['query'] : null,
118 6
                        'resultClass'       => isset($mappingElement['resultClass']) ? $mappingElement['resultClass'] : null,
119 6
                        'resultSetMapping'  => isset($mappingElement['resultSetMapping']) ? $mappingElement['resultSetMapping'] : null,
120
                    ]
121
                );
122
            }
123
        }
124
125
        // Evaluate sql result set mappings
126 58
        if (isset($element['sqlResultSetMappings'])) {
127 6
            foreach ($element['sqlResultSetMappings'] as $name => $resultSetMapping) {
128 6
                if (!isset($resultSetMapping['name'])) {
129 6
                    $resultSetMapping['name'] = $name;
130
                }
131
132 6
                $entities = [];
133 6
                $columns  = [];
134 6
                if (isset($resultSetMapping['entityResult'])) {
135 6
                    foreach ($resultSetMapping['entityResult'] as $entityResultElement) {
136
                        $entityResult = [
137 6
                            'fields'                => [],
138 6
                            'entityClass'           => isset($entityResultElement['entityClass']) ? $entityResultElement['entityClass'] : null,
139 6
                            'discriminatorColumn'   => isset($entityResultElement['discriminatorColumn']) ? $entityResultElement['discriminatorColumn'] : null,
140
                        ];
141
142 6
                        if (isset($entityResultElement['fieldResult'])) {
143 6
                            foreach ($entityResultElement['fieldResult'] as $fieldResultElement) {
144 6
                                $entityResult['fields'][] = [
145 6
                                    'name'      => isset($fieldResultElement['name']) ? $fieldResultElement['name'] : null,
146 6
                                    'column'    => isset($fieldResultElement['column']) ? $fieldResultElement['column'] : null,
147
                                ];
148
                            }
149
                        }
150
151 6
                        $entities[] = $entityResult;
152
                    }
153
                }
154
155
156 6
                if (isset($resultSetMapping['columnResult'])) {
157 6
                    foreach ($resultSetMapping['columnResult'] as $columnResultAnnot) {
158 6
                        $columns[] = [
159 6
                            'name' => isset($columnResultAnnot['name']) ? $columnResultAnnot['name'] : null,
160
                        ];
161
                    }
162
                }
163
164 6
                $metadata->addSqlResultSetMapping(
165
                    [
166 6
                        'name'          => $resultSetMapping['name'],
167 6
                        'entities'      => $entities,
168 6
                        'columns'       => $columns
169
                    ]
170
                );
171
            }
172
        }
173
174 58
        if (isset($element['inheritanceType'])) {
175 18
            $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . strtoupper($element['inheritanceType'])));
176
177 18
            if ($metadata->inheritanceType != \Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) {
178
                // Evaluate discriminatorColumn
179 18
                if (isset($element['discriminatorColumn'])) {
180 6
                    $discrColumn = $element['discriminatorColumn'];
181 6
                    $metadata->setDiscriminatorColumn(
182
                        [
183 6
                            'name' => isset($discrColumn['name']) ? (string) $discrColumn['name'] : null,
184 6
                            'type' => isset($discrColumn['type']) ? (string) $discrColumn['type'] : 'string',
185 6
                            'length' => isset($discrColumn['length']) ? (string) $discrColumn['length'] : 255,
186 6
                            'columnDefinition' => isset($discrColumn['columnDefinition']) ? (string) $discrColumn['columnDefinition'] : null
187
                        ]
188
                    );
189
                } else {
190 12
                    $metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]);
191
                }
192
193
                // Evaluate discriminatorMap
194 18
                if (isset($element['discriminatorMap'])) {
195 18
                    $metadata->setDiscriminatorMap($element['discriminatorMap']);
196
                }
197
            }
198
        }
199
200
201
        // Evaluate changeTrackingPolicy
202 58
        if (isset($element['changeTrackingPolicy'])) {
203
            $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_'
204
                . strtoupper($element['changeTrackingPolicy'])));
205
        }
206
207
        // Evaluate indexes
208 58
        if (isset($element['indexes'])) {
209 8
            foreach ($element['indexes'] as $name => $indexYml) {
210 8
                if ( ! isset($indexYml['name'])) {
211 8
                    $indexYml['name'] = $name;
212
                }
213
214 8
                if (is_string($indexYml['columns'])) {
215 8
                    $index = ['columns' => array_map('trim', explode(',', $indexYml['columns']))];
216
                } else {
217
                    $index = ['columns' => $indexYml['columns']];
218
                }
219
220 8
                if (isset($indexYml['flags'])) {
221 2
                    if (is_string($indexYml['flags'])) {
222 2
                        $index['flags'] = array_map('trim', explode(',', $indexYml['flags']));
223
                    } else {
224
                        $index['flags'] = $indexYml['flags'];
225
                    }
226
                }
227
228 8
                if (isset($indexYml['options'])) {
229 2
                    $index['options'] = $indexYml['options'];
230
                }
231
232 8
                $metadata->table['indexes'][$indexYml['name']] = $index;
233
            }
234
        }
235
236
        // Evaluate uniqueConstraints
237 58
        if (isset($element['uniqueConstraints'])) {
238 7
            foreach ($element['uniqueConstraints'] as $name => $uniqueYml) {
239 7
                if ( ! isset($uniqueYml['name'])) {
240 7
                    $uniqueYml['name'] = $name;
241
                }
242
243 7
                if (is_string($uniqueYml['columns'])) {
244 6
                    $unique = ['columns' => array_map('trim', explode(',', $uniqueYml['columns']))];
245
                } else {
246 1
                    $unique = ['columns' => $uniqueYml['columns']];
247
                }
248
249 7
                if (isset($uniqueYml['options'])) {
250 4
                    $unique['options'] = $uniqueYml['options'];
251
                }
252
253 7
                $metadata->table['uniqueConstraints'][$uniqueYml['name']] = $unique;
254
            }
255
        }
256
257 58
        if (isset($element['options'])) {
258 6
            $metadata->table['options'] = $element['options'];
259
        }
260
261 58
        $associationIds = [];
262 58
        if (isset($element['id'])) {
263
            // Evaluate identifier settings
264 54
            foreach ($element['id'] as $name => $idElement) {
265 32
                if (isset($idElement['associationKey']) && $idElement['associationKey'] == true) {
266
                    $associationIds[$name] = true;
267
                    continue;
268
                }
269
270
                $mapping = [
271 32
                    'id' => true,
272 32
                    'fieldName' => $name
273
                ];
274
275 32
                if (isset($idElement['type'])) {
276 26
                    $mapping['type'] = $idElement['type'];
277
                }
278
279 32
                if (isset($idElement['column'])) {
280 2
                    $mapping['columnName'] = $idElement['column'];
281
                }
282
283 32
                if (isset($idElement['length'])) {
284 2
                    $mapping['length'] = $idElement['length'];
285
                }
286
287 32
                if (isset($idElement['columnDefinition'])) {
288
                    $mapping['columnDefinition'] = $idElement['columnDefinition'];
289
                }
290
291 32
                if (isset($idElement['options'])) {
292 4
                    $mapping['options'] = $idElement['options'];
293
                }
294
295 32
                $metadata->mapField($mapping);
296
297 32
                if (isset($idElement['generator'])) {
298 29
                    $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
299 29
                        . strtoupper($idElement['generator']['strategy'])));
300
                }
301
                // Check for SequenceGenerator/TableGenerator definition
302 32
                if (isset($idElement['sequenceGenerator'])) {
303 4
                    $metadata->setSequenceGeneratorDefinition($idElement['sequenceGenerator']);
304 28
                } else if (isset($idElement['customIdGenerator'])) {
305 4
                    $customGenerator = $idElement['customIdGenerator'];
306 4
                    $metadata->setCustomGeneratorDefinition(
307
                        [
308 4
                            'class' => (string) $customGenerator['class']
309
                        ]
310
                    );
311 24
                } else if (isset($idElement['tableGenerator'])) {
312 32
                    throw MappingException::tableIdGeneratorNotImplemented($className);
313
                }
314
            }
315
        }
316
317
        // Evaluate fields
318 36
        if (isset($element['fields'])) {
319 27
            foreach ($element['fields'] as $name => $fieldMapping) {
320
321 27
                $mapping = $this->columnToArray($name, $fieldMapping);
322
323 27
                if (isset($fieldMapping['id'])) {
324
                    $mapping['id'] = true;
325
                    if (isset($fieldMapping['generator']['strategy'])) {
326
                        $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
327
                            . strtoupper($fieldMapping['generator']['strategy'])));
328
                    }
329
                }
330
331 27
                if (isset($mapping['version'])) {
332 4
                    $metadata->setVersionMapping($mapping);
333 4
                    unset($mapping['version']);
334
                }
335
336 27
                $metadata->mapField($mapping);
337
            }
338
        }
339
340 36
        if (isset($element['embedded'])) {
341
            foreach ($element['embedded'] as $name => $embeddedMapping) {
342
                $mapping = [
343
                    'fieldName' => $name,
344
                    'class' => $embeddedMapping['class'],
345
                    'columnPrefix' => isset($embeddedMapping['columnPrefix']) ? $embeddedMapping['columnPrefix'] : null,
346
                ];
347
                $metadata->mapEmbedded($mapping);
348
            }
349
        }
350
351
        // Evaluate oneToOne relationships
352 36
        if (isset($element['oneToOne'])) {
353 13
            foreach ($element['oneToOne'] as $name => $oneToOneElement) {
354
                $mapping = [
355 13
                    'fieldName' => $name,
356 13
                    'targetEntity' => $oneToOneElement['targetEntity']
357
                ];
358
359 13
                if (isset($associationIds[$mapping['fieldName']])) {
360
                    $mapping['id'] = true;
361
                }
362
363 13
                if (isset($oneToOneElement['fetch'])) {
364 3
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToOneElement['fetch']);
365
                }
366
367 13
                if (isset($oneToOneElement['mappedBy'])) {
368 3
                    $mapping['mappedBy'] = $oneToOneElement['mappedBy'];
369
                } else {
370 12
                    if (isset($oneToOneElement['inversedBy'])) {
371 12
                        $mapping['inversedBy'] = $oneToOneElement['inversedBy'];
372
                    }
373
374 12
                    $joinColumns = [];
375
376 12
                    if (isset($oneToOneElement['joinColumn'])) {
377 11
                        $joinColumns[] = $this->joinColumnToArray($oneToOneElement['joinColumn']);
378 1
                    } else if (isset($oneToOneElement['joinColumns'])) {
379 1
                        foreach ($oneToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
380 1
                            if ( ! isset($joinColumnElement['name'])) {
381 1
                                $joinColumnElement['name'] = $joinColumnName;
382
                            }
383
384 1
                            $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
385
                        }
386
                    }
387
388 12
                    $mapping['joinColumns'] = $joinColumns;
389
                }
390
391 13
                if (isset($oneToOneElement['cascade'])) {
392 9
                    $mapping['cascade'] = $oneToOneElement['cascade'];
393
                }
394
395 13
                if (isset($oneToOneElement['orphanRemoval'])) {
396 5
                    $mapping['orphanRemoval'] = (bool) $oneToOneElement['orphanRemoval'];
397
                }
398
399
                // Evaluate second level cache
400 13
                if (isset($oneToOneElement['cache'])) {
401
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToOneElement['cache']));
402
                }
403
404 13
                $metadata->mapOneToOne($mapping);
405
            }
406
        }
407
408
        // Evaluate oneToMany relationships
409 36
        if (isset($element['oneToMany'])) {
410 8
            foreach ($element['oneToMany'] as $name => $oneToManyElement) {
411
                $mapping = [
412 8
                    'fieldName' => $name,
413 8
                    'targetEntity' => $oneToManyElement['targetEntity'],
414 8
                    'mappedBy' => $oneToManyElement['mappedBy']
415
                ];
416
417 8
                if (isset($oneToManyElement['fetch'])) {
418 2
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToManyElement['fetch']);
419
                }
420
421 8
                if (isset($oneToManyElement['cascade'])) {
422 6
                    $mapping['cascade'] = $oneToManyElement['cascade'];
423
                }
424
425 8
                if (isset($oneToManyElement['orphanRemoval'])) {
426 6
                    $mapping['orphanRemoval'] = (bool) $oneToManyElement['orphanRemoval'];
427
                }
428
429 8
                if (isset($oneToManyElement['orderBy'])) {
430 8
                    $mapping['orderBy'] = $oneToManyElement['orderBy'];
431
                }
432
433 8
                if (isset($oneToManyElement['indexBy'])) {
434
                    $mapping['indexBy'] = $oneToManyElement['indexBy'];
435
                }
436
437
438
                // Evaluate second level cache
439 8
                if (isset($oneToManyElement['cache'])) {
440 2
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToManyElement['cache']));
441
                }
442
443 8
                $metadata->mapOneToMany($mapping);
444
            }
445
        }
446
447
        // Evaluate manyToOne relationships
448 36
        if (isset($element['manyToOne'])) {
449 4
            foreach ($element['manyToOne'] as $name => $manyToOneElement) {
450
                $mapping = [
451 4
                    'fieldName' => $name,
452 4
                    'targetEntity' => $manyToOneElement['targetEntity']
453
                ];
454
455 4
                if (isset($associationIds[$mapping['fieldName']])) {
456
                    $mapping['id'] = true;
457
                }
458
459 4
                if (isset($manyToOneElement['fetch'])) {
460 1
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToOneElement['fetch']);
461
                }
462
463 4
                if (isset($manyToOneElement['inversedBy'])) {
464 2
                    $mapping['inversedBy'] = $manyToOneElement['inversedBy'];
465
                }
466
467 4
                $joinColumns = [];
468
469 4
                if (isset($manyToOneElement['joinColumn'])) {
470
                    $joinColumns[] = $this->joinColumnToArray($manyToOneElement['joinColumn']);
471 4
                } else if (isset($manyToOneElement['joinColumns'])) {
472 3
                    foreach ($manyToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
473 3
                        if ( ! isset($joinColumnElement['name'])) {
474 3
                            $joinColumnElement['name'] = $joinColumnName;
475
                        }
476
477 3
                        $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
478
                    }
479
                }
480
481 4
                $mapping['joinColumns'] = $joinColumns;
482
483 4
                if (isset($manyToOneElement['cascade'])) {
484 1
                    $mapping['cascade'] = $manyToOneElement['cascade'];
485
                }
486
487
                // Evaluate second level cache
488 4
                if (isset($manyToOneElement['cache'])) {
489 2
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToOneElement['cache']));
490
                }
491
492 4
                $metadata->mapManyToOne($mapping);
493
            }
494
        }
495
496
        // Evaluate manyToMany relationships
497 36
        if (isset($element['manyToMany'])) {
498 13
            foreach ($element['manyToMany'] as $name => $manyToManyElement) {
499
                $mapping = [
500 13
                    'fieldName' => $name,
501 13
                    'targetEntity' => $manyToManyElement['targetEntity']
502
                ];
503
504 13
                if (isset($manyToManyElement['fetch'])) {
505 2
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToManyElement['fetch']);
506
                }
507
508 13
                if (isset($manyToManyElement['mappedBy'])) {
509 2
                    $mapping['mappedBy'] = $manyToManyElement['mappedBy'];
510 11
                } else if (isset($manyToManyElement['joinTable'])) {
511
512 9
                    $joinTableElement = $manyToManyElement['joinTable'];
513
                    $joinTable = [
514 9
                        'name' => $joinTableElement['name']
515
                    ];
516
517 9
                    if (isset($joinTableElement['schema'])) {
518
                        $joinTable['schema'] = $joinTableElement['schema'];
519
                    }
520
521 9
                    if (isset($joinTableElement['joinColumns'])) {
522 9
                        foreach ($joinTableElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
523 9
                            if ( ! isset($joinColumnElement['name'])) {
524 8
                                $joinColumnElement['name'] = $joinColumnName;
525
                            }
526 9
                            $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
527
                        }
528
                    }
529
530 9
                    if (isset($joinTableElement['inverseJoinColumns'])) {
531 9
                        foreach ($joinTableElement['inverseJoinColumns'] as $joinColumnName => $joinColumnElement) {
532 9
                            if ( ! isset($joinColumnElement['name'])) {
533 8
                                $joinColumnElement['name'] = $joinColumnName;
534
                            }
535 9
                            $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
536
                        }
537
                    }
538
539 9
                    $mapping['joinTable'] = $joinTable;
540
                }
541
542 13
                if (isset($manyToManyElement['inversedBy'])) {
543
                    $mapping['inversedBy'] = $manyToManyElement['inversedBy'];
544
                }
545
546 13
                if (isset($manyToManyElement['cascade'])) {
547 8
                    $mapping['cascade'] = $manyToManyElement['cascade'];
548
                }
549
550 13
                if (isset($manyToManyElement['orderBy'])) {
551
                    $mapping['orderBy'] = $manyToManyElement['orderBy'];
552
                }
553
554 13
                if (isset($manyToManyElement['indexBy'])) {
555
                    $mapping['indexBy'] = $manyToManyElement['indexBy'];
556
                }
557
558 13
                if (isset($manyToManyElement['orphanRemoval'])) {
559
                    $mapping['orphanRemoval'] = (bool) $manyToManyElement['orphanRemoval'];
560
                }
561
562
                // Evaluate second level cache
563 13
                if (isset($manyToManyElement['cache'])) {
564
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToManyElement['cache']));
565
                }
566
567 13
                $metadata->mapManyToMany($mapping);
568
            }
569
        }
570
571
        // Evaluate associationOverride
572 36
        if (isset($element['associationOverride']) && is_array($element['associationOverride'])) {
573
574 2
            foreach ($element['associationOverride'] as $fieldName => $associationOverrideElement) {
575 2
                $override   = [];
576
577
                // Check for joinColumn
578 2
                if (isset($associationOverrideElement['joinColumn'])) {
579
                    $joinColumns = [];
580
                    foreach ($associationOverrideElement['joinColumn'] as $name => $joinColumnElement) {
581
                        if ( ! isset($joinColumnElement['name'])) {
582
                            $joinColumnElement['name'] = $name;
583
                        }
584
                        $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
585
                    }
586
                    $override['joinColumns'] = $joinColumns;
587
                }
588
589
                // Check for joinTable
590 2
                if (isset($associationOverrideElement['joinTable'])) {
591
592
                    $joinTableElement   = $associationOverrideElement['joinTable'];
593
                    $joinTable          =  [
594
                        'name' => $joinTableElement['name']
595
                    ];
596
597
                    if (isset($joinTableElement['schema'])) {
598
                        $joinTable['schema'] = $joinTableElement['schema'];
599
                    }
600
601
                    foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) {
602
                        if ( ! isset($joinColumnElement['name'])) {
603
                            $joinColumnElement['name'] = $name;
604
                        }
605
606
                        $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
607
                    }
608
609
                    foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) {
610
                        if ( ! isset($joinColumnElement['name'])) {
611
                            $joinColumnElement['name'] = $name;
612
                        }
613
614
                        $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
615
                    }
616
617
                    $override['joinTable'] = $joinTable;
618
                }
619
620
                // Check for inversedBy
621 2
                if (isset($associationOverrideElement['inversedBy'])) {
622 2
                    $override['inversedBy'] = (string) $associationOverrideElement['inversedBy'];
623
                }
624
625 2
                $metadata->setAssociationOverride($fieldName, $override);
626
            }
627
        }
628
629
        // Evaluate associationOverride
630 36
        if (isset($element['attributeOverride']) && is_array($element['attributeOverride'])) {
631
632
            foreach ($element['attributeOverride'] as $fieldName => $attributeOverrideElement) {
633
                $mapping = $this->columnToArray($fieldName, $attributeOverrideElement);
634
                $metadata->setAttributeOverride($fieldName, $mapping);
635
            }
636
        }
637
638
        // Evaluate lifeCycleCallbacks
639 36
        if (isset($element['lifecycleCallbacks'])) {
640 7
            foreach ($element['lifecycleCallbacks'] as $type => $methods) {
641 6
                foreach ($methods as $method) {
642 6
                    $metadata->addLifecycleCallback($method, constant('Doctrine\ORM\Events::' . $type));
643
                }
644
            }
645
        }
646
647
        // Evaluate entityListeners
648 36
        if (isset($element['entityListeners'])) {
649 8
            foreach ($element['entityListeners'] as $className => $entityListener) {
650
                // Evaluate the listener using naming convention.
651 8
                if (empty($entityListener)) {
652 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...
653
654 4
                    continue;
655
                }
656
657 4
                foreach ($entityListener as $eventName => $callbackElement) {
658 4
                    foreach ($callbackElement as $methodName) {
659 4
                        $metadata->addEntityListener($eventName, $className, $methodName);
660
                    }
661
                }
662
            }
663
        }
664 36
    }
665
666
    /**
667
     * Constructs a joinColumn mapping array based on the information
668
     * found in the given join column element.
669
     *
670
     * @param array $joinColumnElement The array join column element.
671
     *
672
     * @return array The mapping array.
673
     */
674 15
    private function joinColumnToArray($joinColumnElement)
675
    {
676 15
        $joinColumn = [];
677 15
        if (isset($joinColumnElement['referencedColumnName'])) {
678 15
            $joinColumn['referencedColumnName'] = (string) $joinColumnElement['referencedColumnName'];
679
        }
680
681 15
        if (isset($joinColumnElement['name'])) {
682 11
            $joinColumn['name'] = (string) $joinColumnElement['name'];
683
        }
684
685 15
        if (isset($joinColumnElement['fieldName'])) {
686
            $joinColumn['fieldName'] = (string) $joinColumnElement['fieldName'];
687
        }
688
689 15
        if (isset($joinColumnElement['unique'])) {
690 6
            $joinColumn['unique'] = (bool) $joinColumnElement['unique'];
691
        }
692
693 15
        if (isset($joinColumnElement['nullable'])) {
694 6
            $joinColumn['nullable'] = (bool) $joinColumnElement['nullable'];
695
        }
696
697 15
        if (isset($joinColumnElement['onDelete'])) {
698 6
            $joinColumn['onDelete'] = $joinColumnElement['onDelete'];
699
        }
700
701 15
        if (isset($joinColumnElement['columnDefinition'])) {
702 6
            $joinColumn['columnDefinition'] = $joinColumnElement['columnDefinition'];
703
        }
704
705 15
        return $joinColumn;
706
    }
707
708
    /**
709
     * Parses the given column as array.
710
     *
711
     * @param string $fieldName
712
     * @param array  $column
713
     *
714
     * @return  array
715
     */
716 27
    private function columnToArray($fieldName, $column)
717
    {
718
        $mapping = [
719 27
            'fieldName' => $fieldName
720
        ];
721
722 27
        if (isset($column['type'])) {
723 27
            $params = explode('(', $column['type']);
724
725 27
            $column['type']  = $params[0];
726 27
            $mapping['type'] = $column['type'];
727
728 27
            if (isset($params[1])) {
729 2
                $column['length'] = (integer) substr($params[1], 0, strlen($params[1]) - 1);
730
            }
731
        }
732
733 27
        if (isset($column['column'])) {
734 9
            $mapping['columnName'] = $column['column'];
735
        }
736
737 27
        if (isset($column['length'])) {
738 17
            $mapping['length'] = $column['length'];
739
        }
740
741 27
        if (isset($column['precision'])) {
742
            $mapping['precision'] = $column['precision'];
743
        }
744
745 27
        if (isset($column['scale'])) {
746
            $mapping['scale'] = $column['scale'];
747
        }
748
749 27
        if (isset($column['unique'])) {
750 11
            $mapping['unique'] = (bool) $column['unique'];
751
        }
752
753 27
        if (isset($column['options'])) {
754 6
            $mapping['options'] = $column['options'];
755
        }
756
757 27
        if (isset($column['nullable'])) {
758 8
            $mapping['nullable'] = $column['nullable'];
759
        }
760
761 27
        if (isset($column['version']) && $column['version']) {
762 4
            $mapping['version'] = $column['version'];
763
        }
764
765 27
        if (isset($column['columnDefinition'])) {
766 6
            $mapping['columnDefinition'] = $column['columnDefinition'];
767
        }
768
769 27
        return $mapping;
770
    }
771
772
    /**
773
     * Parse / Normalize the cache configuration
774
     *
775
     * @param array $cacheMapping
776
     *
777
     * @return array
778
     */
779 2
    private function cacheToArray($cacheMapping)
780
    {
781 2
        $region = isset($cacheMapping['region']) ? (string) $cacheMapping['region'] : null;
782 2
        $usage  = isset($cacheMapping['usage']) ? strtoupper($cacheMapping['usage']) : null;
783
784 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...
785
            throw new \InvalidArgumentException(sprintf('Invalid cache usage "%s"', $usage));
786
        }
787
788 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...
789 2
            $usage = constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage);
790
        }
791
792
        return [
793 2
            'usage'  => $usage,
794 2
            'region' => $region,
795
        ];
796
    }
797
798
    /**
799
     * {@inheritDoc}
800
     */
801 62
    protected function loadMappingFile($file)
802
    {
803 62
        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...
804
    }
805
}
806