Failed Conditions
Pull Request — master (#6886)
by Grégoire
09:16
created

YamlDriver   F

Complexity

Total Complexity 172

Size/Duplication

Total Lines 772
Duplicated Lines 15.93 %

Test Coverage

Coverage 90.93%

Importance

Changes 0
Metric Value
dl 123
loc 772
ccs 331
cts 364
cp 0.9093
rs 1.263
c 0
b 0
f 0
wmc 172

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 3 1
D joinColumnToArray() 0 32 8
F columnToArray() 0 54 13
B cacheToArray() 16 16 6
A loadMappingFile() 0 3 1
F loadMetadataForClass() 105 613 143

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like YamlDriver often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use YamlDriver, and based on these observations, apply Extract Interface, too.

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

809
        return Yaml::parse(/** @scrutinizer ignore-type */ file_get_contents($file));
Loading history...
810
    }
811
}
812