Passed
Pull Request — master (#6869)
by Michael
09:57
created

YamlDriver::joinColumnToArray()   D

Complexity

Conditions 8
Paths 128

Size

Total Lines 32
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 8.013

Importance

Changes 0
Metric Value
cc 8
eloc 16
nc 128
nop 1
dl 0
loc 32
ccs 16
cts 17
cp 0.9412
crap 8.013
rs 4.6666
c 0
b 0
f 0
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 73
    public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION)
46
    {
47 73
        @trigger_error(
48 73
            'YAML mapping driver is deprecated and will be removed in Doctrine 3.0, please migrate to annotation or XML driver.',
49 73
            E_USER_DEPRECATED
50
        );
51
52 73
        parent::__construct($locator, $fileExtension);
53 73
    }
54
55
    /**
56
     * {@inheritDoc}
57
     */
58 68
    public function loadMetadataForClass($className, ClassMetadata $metadata)
59
    {
60
        /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
61 68
        $element = $this->getElement($className);
62
63 66
        if ($element['type'] == 'entity') {
64 64
            if (isset($element['repositoryClass'])) {
65
                $metadata->setCustomRepositoryClass($element['repositoryClass']);
66
            }
67 64
            if (isset($element['readOnly']) && $element['readOnly'] == true) {
68 64
                $metadata->markReadOnly();
69
            }
70 16
        } else if ($element['type'] == 'mappedSuperclass') {
71 14
            $metadata->setCustomRepositoryClass(
72 14
                $element['repositoryClass'] ?? null
73
            );
74 14
            $metadata->isMappedSuperclass = true;
75 2 View Code Duplication
        } else if ($element['type'] == 'embeddable') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
76
            $metadata->isEmbeddedClass = true;
77
        } else {
78 2
            throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
79
        }
80
81
        // Evaluate root level properties
82 64
        $primaryTable = [];
83
84 64
        if (isset($element['table'])) {
85 26
            $primaryTable['name'] = $element['table'];
86
        }
87
88 64
        if (isset($element['schema'])) {
89 2
            $primaryTable['schema'] = $element['schema'];
90
        }
91
92
        // Evaluate second level cache
93 64
        if (isset($element['cache'])) {
94 2
            $metadata->enableCache($this->cacheToArray($element['cache']));
95
        }
96
97 64
        $metadata->setPrimaryTable($primaryTable);
98
99
        // Evaluate named queries
100 64
        if (isset($element['namedQueries'])) {
101 8
            foreach ($element['namedQueries'] as $name => $queryMapping) {
102 8
                if (is_string($queryMapping)) {
103 8
                    $queryMapping = ['query' => $queryMapping];
104
                }
105
106 8
                if ( ! isset($queryMapping['name'])) {
107 8
                    $queryMapping['name'] = $name;
108
                }
109
110 8
                $metadata->addNamedQuery($queryMapping);
111
            }
112
        }
113
114
        // Evaluate named native queries
115 64
        if (isset($element['namedNativeQueries'])) {
116 6
            foreach ($element['namedNativeQueries'] as $name => $mappingElement) {
117 6
                if (!isset($mappingElement['name'])) {
118 6
                    $mappingElement['name'] = $name;
119
                }
120 6
                $metadata->addNamedNativeQuery(
121
                    [
122 6
                        'name'              => $mappingElement['name'],
123 6
                        'query'             => $mappingElement['query'] ?? null,
124 6
                        'resultClass'       => $mappingElement['resultClass'] ?? null,
125 6
                        'resultSetMapping'  => $mappingElement['resultSetMapping'] ?? null,
126
                    ]
127
                );
128
            }
129
        }
130
131
        // Evaluate sql result set mappings
132 64
        if (isset($element['sqlResultSetMappings'])) {
133 6
            foreach ($element['sqlResultSetMappings'] as $name => $resultSetMapping) {
134 6
                if (!isset($resultSetMapping['name'])) {
135 6
                    $resultSetMapping['name'] = $name;
136
                }
137
138 6
                $entities = [];
139 6
                $columns  = [];
140 6
                if (isset($resultSetMapping['entityResult'])) {
141 6
                    foreach ($resultSetMapping['entityResult'] as $entityResultElement) {
142
                        $entityResult = [
143 6
                            'fields'                => [],
144 6
                            'entityClass'           => $entityResultElement['entityClass'] ?? null,
145 6
                            'discriminatorColumn'   => $entityResultElement['discriminatorColumn'] ?? null,
146
                        ];
147
148 6
                        if (isset($entityResultElement['fieldResult'])) {
149 6
                            foreach ($entityResultElement['fieldResult'] as $fieldResultElement) {
150 6
                                $entityResult['fields'][] = [
151 6
                                    'name'      => $fieldResultElement['name'] ?? null,
152 6
                                    'column'    => $fieldResultElement['column'] ?? null,
153
                                ];
154
                            }
155
                        }
156
157 6
                        $entities[] = $entityResult;
158
                    }
159
                }
160
161
162 6
                if (isset($resultSetMapping['columnResult'])) {
163 6
                    foreach ($resultSetMapping['columnResult'] as $columnResultAnnot) {
164 6
                        $columns[] = [
165 6
                            'name' => $columnResultAnnot['name'] ?? null,
166
                        ];
167
                    }
168
                }
169
170 6
                $metadata->addSqlResultSetMapping(
171
                    [
172 6
                        'name'          => $resultSetMapping['name'],
173 6
                        'entities'      => $entities,
174 6
                        'columns'       => $columns
175
                    ]
176
                );
177
            }
178
        }
179
180 64
        if (isset($element['inheritanceType'])) {
181 18
            $metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . strtoupper($element['inheritanceType'])));
182
183 18
            if ($metadata->inheritanceType != Metadata::INHERITANCE_TYPE_NONE) {
184
                // Evaluate discriminatorColumn
185 18 View Code Duplication
                if (isset($element['discriminatorColumn'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
186 12
                    $discrColumn = $element['discriminatorColumn'];
187 12
                    $metadata->setDiscriminatorColumn(
188
                        [
189 12
                            'name' => isset($discrColumn['name']) ? (string) $discrColumn['name'] : null,
190 12
                            'type' => isset($discrColumn['type']) ? (string) $discrColumn['type'] : 'string',
191 12
                            'length' => isset($discrColumn['length']) ? (string) $discrColumn['length'] : 255,
192 12
                            'columnDefinition' => isset($discrColumn['columnDefinition']) ? (string) $discrColumn['columnDefinition'] : null
193
                        ]
194
                    );
195
                } else {
196 12
                    $metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]);
197
                }
198
199
                // Evaluate discriminatorMap
200 18
                if (isset($element['discriminatorMap'])) {
201 18
                    $metadata->setDiscriminatorMap($element['discriminatorMap']);
202
                }
203
            }
204
        }
205
206
207
        // Evaluate changeTrackingPolicy
208 64 View Code Duplication
        if (isset($element['changeTrackingPolicy'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
209
            $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_'
210
                . strtoupper($element['changeTrackingPolicy'])));
211
        }
212
213
        // Evaluate indexes
214 64
        if (isset($element['indexes'])) {
215 12
            foreach ($element['indexes'] as $name => $indexYml) {
216 12
                if ( ! isset($indexYml['name'])) {
217 12
                    $indexYml['name'] = $name;
218
                }
219
220 12 View Code Duplication
                if (is_string($indexYml['columns'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
221 12
                    $index = ['columns' => array_map('trim', explode(',', $indexYml['columns']))];
222
                } else {
223
                    $index = ['columns' => $indexYml['columns']];
224
                }
225
226 12
                if (isset($indexYml['flags'])) {
227 2
                    if (is_string($indexYml['flags'])) {
228 2
                        $index['flags'] = array_map('trim', explode(',', $indexYml['flags']));
229
                    } else {
230
                        $index['flags'] = $indexYml['flags'];
231
                    }
232
                }
233
234 12
                if (isset($indexYml['options'])) {
235 2
                    $index['options'] = $indexYml['options'];
236
                }
237
238 12
                $metadata->table['indexes'][$indexYml['name']] = $index;
239
            }
240
        }
241
242
        // Evaluate uniqueConstraints
243 64
        if (isset($element['uniqueConstraints'])) {
244 11
            foreach ($element['uniqueConstraints'] as $name => $uniqueYml) {
245 11
                if ( ! isset($uniqueYml['name'])) {
246 11
                    $uniqueYml['name'] = $name;
247
                }
248
249 11 View Code Duplication
                if (is_string($uniqueYml['columns'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
250 10
                    $unique = ['columns' => array_map('trim', explode(',', $uniqueYml['columns']))];
251
                } else {
252 1
                    $unique = ['columns' => $uniqueYml['columns']];
253
                }
254
255 11
                if (isset($uniqueYml['options'])) {
256 6
                    $unique['options'] = $uniqueYml['options'];
257
                }
258
259 11
                $metadata->table['uniqueConstraints'][$uniqueYml['name']] = $unique;
260
            }
261
        }
262
263 64
        if (isset($element['options'])) {
264 8
            $metadata->table['options'] = $element['options'];
265
        }
266
267 64
        $associationIds = [];
268 64
        if (isset($element['id'])) {
269
            // Evaluate identifier settings
270 60
            foreach ($element['id'] as $name => $idElement) {
271 60
                if (isset($idElement['associationKey']) && $idElement['associationKey'] == true) {
272
                    $associationIds[$name] = true;
273
                    continue;
274
                }
275
276
                $mapping = [
277 60
                    'id' => true,
278 60
                    'fieldName' => $name
279
                ];
280
281 60
                if (isset($idElement['type'])) {
282 38
                    $mapping['type'] = $idElement['type'];
283
                }
284
285 60
                if (isset($idElement['column'])) {
286 8
                    $mapping['columnName'] = $idElement['column'];
287
                }
288
289 60
                if (isset($idElement['length'])) {
290 6
                    $mapping['length'] = $idElement['length'];
291
                }
292
293 60
                if (isset($idElement['columnDefinition'])) {
294 2
                    $mapping['columnDefinition'] = $idElement['columnDefinition'];
295
                }
296
297 60
                if (isset($idElement['options'])) {
298 6
                    $mapping['options'] = $idElement['options'];
299
                }
300
301 60
                $metadata->mapField($mapping);
302
303 60 View Code Duplication
                if (isset($idElement['generator'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
304 55
                    $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
305 55
                        . strtoupper($idElement['generator']['strategy'])));
306
                }
307
                // Check for SequenceGenerator/TableGenerator definition
308 60
                if (isset($idElement['sequenceGenerator'])) {
309 6
                    $metadata->setSequenceGeneratorDefinition($idElement['sequenceGenerator']);
310 54
                } else if (isset($idElement['customIdGenerator'])) {
311 4
                    $customGenerator = $idElement['customIdGenerator'];
312 4
                    $metadata->setCustomGeneratorDefinition(
313
                        [
314 4
                            'class' => (string) $customGenerator['class']
315
                        ]
316
                    );
317 50
                } else if (isset($idElement['tableGenerator'])) {
318 60
                    throw MappingException::tableIdGeneratorNotImplemented($className);
319
                }
320
            }
321
        }
322
323
        // Evaluate fields
324 64
        if (isset($element['fields'])) {
325 45
            foreach ($element['fields'] as $name => $fieldMapping) {
326
327 45
                $mapping = $this->columnToArray($name, $fieldMapping);
328
329 45
                if (isset($fieldMapping['id'])) {
330
                    $mapping['id'] = true;
331 View Code Duplication
                    if (isset($fieldMapping['generator']['strategy'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
332
                        $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_'
333
                            . strtoupper($fieldMapping['generator']['strategy'])));
334
                    }
335
                }
336
337 45
                if (isset($mapping['version'])) {
338 6
                    $metadata->setVersionMapping($mapping);
339 6
                    unset($mapping['version']);
340
                }
341
342 45
                $metadata->mapField($mapping);
343
            }
344
        }
345
346 64
        if (isset($element['embedded'])) {
347
            foreach ($element['embedded'] as $name => $embeddedMapping) {
348
                $mapping = [
349
                    'fieldName' => $name,
350
                    'class' => $embeddedMapping['class'],
351
                    'columnPrefix' => $embeddedMapping['columnPrefix'] ?? null,
352
                ];
353
                $metadata->mapEmbedded($mapping);
354
            }
355
        }
356
357
        // Evaluate oneToOne relationships
358 64
        if (isset($element['oneToOne'])) {
359 15
            foreach ($element['oneToOne'] as $name => $oneToOneElement) {
360
                $mapping = [
361 15
                    'fieldName' => $name,
362 15
                    'targetEntity' => $oneToOneElement['targetEntity']
363
                ];
364
365 15
                if (isset($associationIds[$mapping['fieldName']])) {
366
                    $mapping['id'] = true;
367
                }
368
369 15 View Code Duplication
                if (isset($oneToOneElement['fetch'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
370 3
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToOneElement['fetch']);
371
                }
372
373 15
                if (isset($oneToOneElement['mappedBy'])) {
374 3
                    $mapping['mappedBy'] = $oneToOneElement['mappedBy'];
375
                } else {
376 14
                    if (isset($oneToOneElement['inversedBy'])) {
377 14
                        $mapping['inversedBy'] = $oneToOneElement['inversedBy'];
378
                    }
379
380 14
                    $joinColumns = [];
381
382 14 View Code Duplication
                    if (isset($oneToOneElement['joinColumn'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
383 13
                        $joinColumns[] = $this->joinColumnToArray($oneToOneElement['joinColumn']);
384 1
                    } else if (isset($oneToOneElement['joinColumns'])) {
385 1
                        foreach ($oneToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
386 1
                            if ( ! isset($joinColumnElement['name'])) {
387 1
                                $joinColumnElement['name'] = $joinColumnName;
388
                            }
389
390 1
                            $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
391
                        }
392
                    }
393
394 14
                    $mapping['joinColumns'] = $joinColumns;
395
                }
396
397 15
                if (isset($oneToOneElement['cascade'])) {
398 11
                    $mapping['cascade'] = $oneToOneElement['cascade'];
399
                }
400
401 15
                if (isset($oneToOneElement['orphanRemoval'])) {
402 5
                    $mapping['orphanRemoval'] = (bool) $oneToOneElement['orphanRemoval'];
403
                }
404
405
                // Evaluate second level cache
406 15 View Code Duplication
                if (isset($oneToOneElement['cache'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
407
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToOneElement['cache']));
408
                }
409
410 15
                $metadata->mapOneToOne($mapping);
411
            }
412
        }
413
414
        // Evaluate oneToMany relationships
415 64
        if (isset($element['oneToMany'])) {
416 10
            foreach ($element['oneToMany'] as $name => $oneToManyElement) {
417
                $mapping = [
418 10
                    'fieldName' => $name,
419 10
                    'targetEntity' => $oneToManyElement['targetEntity'],
420 10
                    'mappedBy' => $oneToManyElement['mappedBy']
421
                ];
422
423 10 View Code Duplication
                if (isset($oneToManyElement['fetch'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
424 2
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToManyElement['fetch']);
425
                }
426
427 10
                if (isset($oneToManyElement['cascade'])) {
428 8
                    $mapping['cascade'] = $oneToManyElement['cascade'];
429
                }
430
431 10
                if (isset($oneToManyElement['orphanRemoval'])) {
432 8
                    $mapping['orphanRemoval'] = (bool) $oneToManyElement['orphanRemoval'];
433
                }
434
435 10
                if (isset($oneToManyElement['orderBy'])) {
436 10
                    $mapping['orderBy'] = $oneToManyElement['orderBy'];
437
                }
438
439 10
                if (isset($oneToManyElement['indexBy'])) {
440
                    $mapping['indexBy'] = $oneToManyElement['indexBy'];
441
                }
442
443
444
                // Evaluate second level cache
445 10 View Code Duplication
                if (isset($oneToManyElement['cache'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
446 2
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($oneToManyElement['cache']));
447
                }
448
449 10
                $metadata->mapOneToMany($mapping);
450
            }
451
        }
452
453
        // Evaluate manyToOne relationships
454 64
        if (isset($element['manyToOne'])) {
455 10
            foreach ($element['manyToOne'] as $name => $manyToOneElement) {
456
                $mapping = [
457 10
                    'fieldName' => $name,
458 10
                    'targetEntity' => $manyToOneElement['targetEntity']
459
                ];
460
461 10
                if (isset($associationIds[$mapping['fieldName']])) {
462
                    $mapping['id'] = true;
463
                }
464
465 10 View Code Duplication
                if (isset($manyToOneElement['fetch'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
466 1
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToOneElement['fetch']);
467
                }
468
469 10
                if (isset($manyToOneElement['inversedBy'])) {
470 2
                    $mapping['inversedBy'] = $manyToOneElement['inversedBy'];
471
                }
472
473 10
                $joinColumns = [];
474
475 10 View Code Duplication
                if (isset($manyToOneElement['joinColumn'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
476 4
                    $joinColumns[] = $this->joinColumnToArray($manyToOneElement['joinColumn']);
477 6
                } else if (isset($manyToOneElement['joinColumns'])) {
478 3
                    foreach ($manyToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
479 3
                        if ( ! isset($joinColumnElement['name'])) {
480 3
                            $joinColumnElement['name'] = $joinColumnName;
481
                        }
482
483 3
                        $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
484
                    }
485
                }
486
487 10
                $mapping['joinColumns'] = $joinColumns;
488
489 10
                if (isset($manyToOneElement['cascade'])) {
490 5
                    $mapping['cascade'] = $manyToOneElement['cascade'];
491
                }
492
493
                // Evaluate second level cache
494 10 View Code Duplication
                if (isset($manyToOneElement['cache'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
495 2
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToOneElement['cache']));
496
                }
497
498 10
                $metadata->mapManyToOne($mapping);
499
            }
500
        }
501
502
        // Evaluate manyToMany relationships
503 64
        if (isset($element['manyToMany'])) {
504 21
            foreach ($element['manyToMany'] as $name => $manyToManyElement) {
505
                $mapping = [
506 21
                    'fieldName' => $name,
507 21
                    'targetEntity' => $manyToManyElement['targetEntity']
508
                ];
509
510 21 View Code Duplication
                if (isset($manyToManyElement['fetch'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
511 2
                    $mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToManyElement['fetch']);
512
                }
513
514 21
                if (isset($manyToManyElement['mappedBy'])) {
515 2
                    $mapping['mappedBy'] = $manyToManyElement['mappedBy'];
516 19
                } else if (isset($manyToManyElement['joinTable'])) {
517
518 15
                    $joinTableElement = $manyToManyElement['joinTable'];
519
                    $joinTable = [
520 15
                        'name' => $joinTableElement['name']
521
                    ];
522
523 15
                    if (isset($joinTableElement['schema'])) {
524
                        $joinTable['schema'] = $joinTableElement['schema'];
525
                    }
526
527 15 View Code Duplication
                    if (isset($joinTableElement['joinColumns'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
528 15
                        foreach ($joinTableElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
529 15
                            if ( ! isset($joinColumnElement['name'])) {
530 14
                                $joinColumnElement['name'] = $joinColumnName;
531
                            }
532 15
                            $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
533
                        }
534
                    }
535
536 15 View Code Duplication
                    if (isset($joinTableElement['inverseJoinColumns'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
537 15
                        foreach ($joinTableElement['inverseJoinColumns'] as $joinColumnName => $joinColumnElement) {
538 15
                            if ( ! isset($joinColumnElement['name'])) {
539 14
                                $joinColumnElement['name'] = $joinColumnName;
540
                            }
541 15
                            $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
542
                        }
543
                    }
544
545 15
                    $mapping['joinTable'] = $joinTable;
546
                }
547
548 21
                if (isset($manyToManyElement['inversedBy'])) {
549 2
                    $mapping['inversedBy'] = $manyToManyElement['inversedBy'];
550
                }
551
552 21
                if (isset($manyToManyElement['cascade'])) {
553 14
                    $mapping['cascade'] = $manyToManyElement['cascade'];
554
                }
555
556 21
                if (isset($manyToManyElement['orderBy'])) {
557
                    $mapping['orderBy'] = $manyToManyElement['orderBy'];
558
                }
559
560 21
                if (isset($manyToManyElement['indexBy'])) {
561
                    $mapping['indexBy'] = $manyToManyElement['indexBy'];
562
                }
563
564 21
                if (isset($manyToManyElement['orphanRemoval'])) {
565
                    $mapping['orphanRemoval'] = (bool) $manyToManyElement['orphanRemoval'];
566
                }
567
568
                // Evaluate second level cache
569 21 View Code Duplication
                if (isset($manyToManyElement['cache'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
570
                    $mapping['cache'] = $metadata->getAssociationCacheDefaults($mapping['fieldName'], $this->cacheToArray($manyToManyElement['cache']));
571
                }
572
573 21
                $metadata->mapManyToMany($mapping);
574
            }
575
        }
576
577
        // Evaluate associationOverride
578 64
        if (isset($element['associationOverride']) && is_array($element['associationOverride'])) {
579
580 8
            foreach ($element['associationOverride'] as $fieldName => $associationOverrideElement) {
581 8
                $override   = [];
582
583
                // Check for joinColumn
584 8
                if (isset($associationOverrideElement['joinColumn'])) {
585 4
                    $joinColumns = [];
586 4
                    foreach ($associationOverrideElement['joinColumn'] as $name => $joinColumnElement) {
587 4
                        if ( ! isset($joinColumnElement['name'])) {
588
                            $joinColumnElement['name'] = $name;
589
                        }
590 4
                        $joinColumns[] = $this->joinColumnToArray($joinColumnElement);
591
                    }
592 4
                    $override['joinColumns'] = $joinColumns;
593
                }
594
595
                // Check for joinTable
596 8
                if (isset($associationOverrideElement['joinTable'])) {
597
598 4
                    $joinTableElement   = $associationOverrideElement['joinTable'];
599
                    $joinTable          =  [
600 4
                        'name' => $joinTableElement['name']
601
                    ];
602
603 4
                    if (isset($joinTableElement['schema'])) {
604
                        $joinTable['schema'] = $joinTableElement['schema'];
605
                    }
606
607 4
                    foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) {
608 4
                        if ( ! isset($joinColumnElement['name'])) {
609 4
                            $joinColumnElement['name'] = $name;
610
                        }
611
612 4
                        $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
613
                    }
614
615 4
                    foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) {
616 4
                        if ( ! isset($joinColumnElement['name'])) {
617 4
                            $joinColumnElement['name'] = $name;
618
                        }
619
620 4
                        $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
621
                    }
622
623 4
                    $override['joinTable'] = $joinTable;
624
                }
625
626
                // Check for inversedBy
627 8
                if (isset($associationOverrideElement['inversedBy'])) {
628 2
                    $override['inversedBy'] = (string) $associationOverrideElement['inversedBy'];
629
                }
630
631
                // Check for `fetch`
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
632 8 View Code Duplication
                if (isset($associationOverrideElement['fetch'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
633 2
                    $override['fetch'] = constant(Metadata::class . '::FETCH_' . $associationOverrideElement['fetch']);
634
                }
635
636 8
                $metadata->setAssociationOverride($fieldName, $override);
637
            }
638
        }
639
640
        // Evaluate associationOverride
641 64
        if (isset($element['attributeOverride']) && is_array($element['attributeOverride'])) {
642
643 4
            foreach ($element['attributeOverride'] as $fieldName => $attributeOverrideElement) {
644 4
                $mapping = $this->columnToArray($fieldName, $attributeOverrideElement);
645 4
                $metadata->setAttributeOverride($fieldName, $mapping);
646
            }
647
        }
648
649
        // Evaluate lifeCycleCallbacks
650 64
        if (isset($element['lifecycleCallbacks'])) {
651 9
            foreach ($element['lifecycleCallbacks'] as $type => $methods) {
652 8
                foreach ($methods as $method) {
653 8
                    $metadata->addLifecycleCallback($method, constant('Doctrine\ORM\Events::' . $type));
654
                }
655
            }
656
        }
657
658
        // Evaluate entityListeners
659 64
        if (isset($element['entityListeners'])) {
660 10
            foreach ($element['entityListeners'] as $className => $entityListener) {
661
                // Evaluate the listener using naming convention.
662 10
                if (empty($entityListener)) {
663 4
                    EntityListenerBuilder::bindEntityListener($metadata, $className);
664
665 4
                    continue;
666
                }
667
668 6
                foreach ($entityListener as $eventName => $callbackElement) {
669 6
                    foreach ($callbackElement as $methodName) {
670 6
                        $metadata->addEntityListener($eventName, $className, $methodName);
671
                    }
672
                }
673
            }
674
        }
675 64
    }
676
677
    /**
678
     * Constructs a joinColumn mapping array based on the information
679
     * found in the given join column element.
680
     *
681
     * @param array $joinColumnElement The array join column element.
682
     *
683
     * @return array The mapping array.
684
     */
685 21
    private function joinColumnToArray($joinColumnElement)
686
    {
687 21
        $joinColumn = [];
688 21
        if (isset($joinColumnElement['referencedColumnName'])) {
689 21
            $joinColumn['referencedColumnName'] = (string) $joinColumnElement['referencedColumnName'];
690
        }
691
692 21
        if (isset($joinColumnElement['name'])) {
693 17
            $joinColumn['name'] = (string) $joinColumnElement['name'];
694
        }
695
696 21
        if (isset($joinColumnElement['fieldName'])) {
697
            $joinColumn['fieldName'] = (string) $joinColumnElement['fieldName'];
698
        }
699
700 21
        if (isset($joinColumnElement['unique'])) {
701 8
            $joinColumn['unique'] = (bool) $joinColumnElement['unique'];
702
        }
703
704 21
        if (isset($joinColumnElement['nullable'])) {
705 10
            $joinColumn['nullable'] = (bool) $joinColumnElement['nullable'];
706
        }
707
708 21
        if (isset($joinColumnElement['onDelete'])) {
709 8
            $joinColumn['onDelete'] = $joinColumnElement['onDelete'];
710
        }
711
712 21
        if (isset($joinColumnElement['columnDefinition'])) {
713 8
            $joinColumn['columnDefinition'] = $joinColumnElement['columnDefinition'];
714
        }
715
716 21
        return $joinColumn;
717
    }
718
719
    /**
720
     * Parses the given column as array.
721
     *
722
     * @param string $fieldName
723
     * @param array  $column
724
     *
725
     * @return  array
726
     */
727 45
    private function columnToArray($fieldName, $column)
728
    {
729
        $mapping = [
730 45
            'fieldName' => $fieldName
731
        ];
732
733 45
        if (isset($column['type'])) {
734 39
            $params = explode('(', $column['type']);
735
736 39
            $column['type']  = $params[0];
737 39
            $mapping['type'] = $column['type'];
738
739 39
            if (isset($params[1])) {
740 4
                $column['length'] = (integer) substr($params[1], 0, strlen($params[1]) - 1);
741
            }
742
        }
743
744 45
        if (isset($column['column'])) {
745 15
            $mapping['columnName'] = $column['column'];
746
        }
747
748 45
        if (isset($column['length'])) {
749 27
            $mapping['length'] = $column['length'];
750
        }
751
752 45
        if (isset($column['precision'])) {
753
            $mapping['precision'] = $column['precision'];
754
        }
755
756 45
        if (isset($column['scale'])) {
757
            $mapping['scale'] = $column['scale'];
758
        }
759
760 45
        if (isset($column['unique'])) {
761 17
            $mapping['unique'] = (bool) $column['unique'];
762
        }
763
764 45
        if (isset($column['options'])) {
765 8
            $mapping['options'] = $column['options'];
766
        }
767
768 45
        if (isset($column['nullable'])) {
769 14
            $mapping['nullable'] = $column['nullable'];
770
        }
771
772 45
        if (isset($column['version']) && $column['version']) {
773 6
            $mapping['version'] = $column['version'];
774
        }
775
776 45
        if (isset($column['columnDefinition'])) {
777 10
            $mapping['columnDefinition'] = $column['columnDefinition'];
778
        }
779
780 45
        return $mapping;
781
    }
782
783
    /**
784
     * Parse / Normalize the cache configuration
785
     *
786
     * @param array $cacheMapping
787
     *
788
     * @return array
789
     */
790 2 View Code Duplication
    private function cacheToArray($cacheMapping)
791
    {
792 2
        $region = isset($cacheMapping['region']) ? (string) $cacheMapping['region'] : null;
793 2
        $usage  = isset($cacheMapping['usage']) ? strtoupper($cacheMapping['usage']) : null;
794
795 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 null|string 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...
796
            throw new \InvalidArgumentException(sprintf('Invalid cache usage "%s"', $usage));
797
        }
798
799 2
        if ($usage) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $usage of type null|string 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...
800 2
            $usage = constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $usage);
801
        }
802
803
        return [
804 2
            'usage'  => $usage,
805 2
            'region' => $region,
806
        ];
807
    }
808
809
    /**
810
     * {@inheritDoc}
811
     */
812 68
    protected function loadMappingFile($file)
813
    {
814 68
        return Yaml::parse(file_get_contents($file));
0 ignored issues
show
Bug introduced by
It seems like file_get_contents($file) can also be of type false; however, parameter $input of Symfony\Component\Yaml\Yaml::parse() does only seem to accept string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

814
        return Yaml::parse(/** @scrutinizer ignore-type */ file_get_contents($file));
Loading history...
815
    }
816
}
817