Completed
Pull Request — master (#6151)
by Andy
09:42
created

YamlDriver::joinColumnToArray()   D

Complexity

Conditions 8
Paths 128

Size

Total Lines 33
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 8.013

Importance

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