Failed Conditions
Pull Request — 2.6 (#7180)
by Ben
11:16
created

AnnotationDriver   F

Complexity

Total Complexity 110

Size/Duplication

Total Lines 633
Duplicated Lines 0 %

Test Coverage

Coverage 96.39%

Importance

Changes 0
Metric Value
dl 0
loc 633
ccs 294
cts 305
cp 0.9639
rs 1.4746
c 0
b 0
f 0
wmc 110

6 Methods

Rating   Name   Duplication   Size   Complexity  
A create() 0 7 2
A joinColumnToArray() 0 9 1
B columnToArray() 0 25 4
F getMethodCallbacks() 0 40 10
F loadMetadataForClass() 0 479 91
A getFetchMode() 0 7 2

How to fix   Complexity   

Complex Class

Complex classes like AnnotationDriver 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 AnnotationDriver, 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\Annotations\AnnotationReader;
23
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
24
use Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver as AbstractAnnotationDriver;
25
use Doctrine\ORM\Events;
26
use Doctrine\ORM\Mapping;
27
use Doctrine\ORM\Mapping\Builder\EntityListenerBuilder;
28
use Doctrine\ORM\Mapping\MappingException;
29
30
/**
31
 * The AnnotationDriver reads the mapping metadata from docblock annotations.
32
 *
33
 * @since 2.0
34
 * @author Benjamin Eberlei <[email protected]>
35
 * @author Guilherme Blanco <[email protected]>
36
 * @author Jonathan H. Wage <[email protected]>
37
 * @author Roman Borschel <[email protected]>
38
 */
39
class AnnotationDriver extends AbstractAnnotationDriver
40
{
41
    /**
42
     * {@inheritDoc}
43
     */
44
    protected $entityAnnotationClasses = [
45
        Mapping\Entity::class => 1,
46
        Mapping\MappedSuperclass::class => 2,
47
    ];
48
49
    /**
50
     * {@inheritDoc}
51
     */
52 415
    public function loadMetadataForClass($className, ClassMetadata $metadata)
53
    {
54
        /* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
55 415
        $class = $metadata->getReflectionClass();
56
57 415
        if ( ! $class) {
0 ignored issues
show
introduced by
$class is of type ReflectionClass, thus it always evaluated to true.
Loading history...
58
            // this happens when running annotation driver in combination with
59
            // static reflection services. This is not the nicest fix
60 1
            $class = new \ReflectionClass($metadata->name);
61
        }
62
63 415
        $classAnnotations = $this->reader->getClassAnnotations($class);
64
65 415
        if ($classAnnotations) {
66 412
            foreach ($classAnnotations as $key => $annot) {
67 412
                if ( ! is_numeric($key)) {
68
                    continue;
69
                }
70
71 412
                $classAnnotations[get_class($annot)] = $annot;
72
            }
73
        }
74
75
        // Evaluate Entity annotation
76 415
        if (isset($classAnnotations[Mapping\Entity::class])) {
77 407
            $entityAnnot = $classAnnotations[Mapping\Entity::class];
78 407
            if ($entityAnnot->repositoryClass !== null) {
79 8
                $metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
80
            }
81
82 407
            if ($entityAnnot->readOnly) {
83 407
                $metadata->markReadOnly();
84
            }
85 45
        } else if (isset($classAnnotations[Mapping\MappedSuperclass::class])) {
86 32
            $mappedSuperclassAnnot = $classAnnotations[Mapping\MappedSuperclass::class];
87
88 32
            $metadata->setCustomRepositoryClass($mappedSuperclassAnnot->repositoryClass);
89 32
            $metadata->isMappedSuperclass = true;
90 15
        } else if (isset($classAnnotations[Mapping\Embeddable::class])) {
91 12
            $metadata->isEmbeddedClass = true;
92
        } else {
93 3
            throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
94
        }
95
96
        // Evaluate Table annotation
97 412
        if (isset($classAnnotations[Mapping\Table::class])) {
98 215
            $tableAnnot   = $classAnnotations[Mapping\Table::class];
99
            $primaryTable = [
100 215
                'name'   => $tableAnnot->name,
101 215
                'schema' => $tableAnnot->schema
102
            ];
103
104 215
            if ($tableAnnot->indexes !== null) {
105 16
                foreach ($tableAnnot->indexes as $indexAnnot) {
106 16
                    $index = ['columns' => $indexAnnot->columns];
107
108 16
                    if ( ! empty($indexAnnot->flags)) {
109 1
                        $index['flags'] = $indexAnnot->flags;
110
                    }
111
112 16
                    if ( ! empty($indexAnnot->options)) {
113 1
                        $index['options'] = $indexAnnot->options;
114
                    }
115
116 16
                    if ( ! empty($indexAnnot->name)) {
117 15
                        $primaryTable['indexes'][$indexAnnot->name] = $index;
118
                    } else {
119 16
                        $primaryTable['indexes'][] = $index;
120
                    }
121
                }
122
            }
123
124 215
            if ($tableAnnot->uniqueConstraints !== null) {
125 9
                foreach ($tableAnnot->uniqueConstraints as $uniqueConstraintAnnot) {
126 9
                    $uniqueConstraint = ['columns' => $uniqueConstraintAnnot->columns];
127
128 9
                    if ( ! empty($uniqueConstraintAnnot->options)) {
129 3
                        $uniqueConstraint['options'] = $uniqueConstraintAnnot->options;
130
                    }
131
132 9
                    if ( ! empty($uniqueConstraintAnnot->name)) {
133 9
                        $primaryTable['uniqueConstraints'][$uniqueConstraintAnnot->name] = $uniqueConstraint;
134
                    } else {
135 9
                        $primaryTable['uniqueConstraints'][] = $uniqueConstraint;
136
                    }
137
                }
138
            }
139
140 215
            if ($tableAnnot->options) {
141 6
                $primaryTable['options'] = $tableAnnot->options;
142
            }
143
144 215
            $metadata->setPrimaryTable($primaryTable);
145
        }
146
147
        // Evaluate @Cache annotation
148 412
        if (isset($classAnnotations[Mapping\Cache::class])) {
149 18
            $cacheAnnot = $classAnnotations[Mapping\Cache::class];
150
            $cacheMap   = [
151 18
                'region' => $cacheAnnot->region,
152 18
                'usage'  => constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $cacheAnnot->usage),
153
            ];
154
155 18
            $metadata->enableCache($cacheMap);
156
        }
157
158
        // Evaluate NamedNativeQueries annotation
159 412
        if (isset($classAnnotations[Mapping\NamedNativeQueries::class])) {
160 17
            $namedNativeQueriesAnnot = $classAnnotations[Mapping\NamedNativeQueries::class];
161
162 17
            foreach ($namedNativeQueriesAnnot->value as $namedNativeQuery) {
163 17
                $metadata->addNamedNativeQuery(
164
                    [
165 17
                        'name'              => $namedNativeQuery->name,
166 17
                        'query'             => $namedNativeQuery->query,
167 17
                        'resultClass'       => $namedNativeQuery->resultClass,
168 17
                        'resultSetMapping'  => $namedNativeQuery->resultSetMapping,
169
                    ]
170
                );
171
            }
172
        }
173
174
        // Evaluate SqlResultSetMappings annotation
175 412
        if (isset($classAnnotations[Mapping\SqlResultSetMappings::class])) {
176 17
            $sqlResultSetMappingsAnnot = $classAnnotations[Mapping\SqlResultSetMappings::class];
177
178 17
            foreach ($sqlResultSetMappingsAnnot->value as $resultSetMapping) {
179 17
                $entities = [];
180 17
                $columns  = [];
181 17
                foreach ($resultSetMapping->entities as $entityResultAnnot) {
182
                    $entityResult = [
183 17
                        'fields'                => [],
184 17
                        'entityClass'           => $entityResultAnnot->entityClass,
185 17
                        'discriminatorColumn'   => $entityResultAnnot->discriminatorColumn,
186
                    ];
187
188 17
                    foreach ($entityResultAnnot->fields as $fieldResultAnnot) {
189 17
                        $entityResult['fields'][] = [
190 17
                            'name'      => $fieldResultAnnot->name,
191 17
                            'column'    => $fieldResultAnnot->column
192
                        ];
193
                    }
194
195 17
                    $entities[] = $entityResult;
196
                }
197
198 17
                foreach ($resultSetMapping->columns as $columnResultAnnot) {
199 10
                    $columns[] = [
200 10
                        'name' => $columnResultAnnot->name,
201
                    ];
202
                }
203
204 17
                $metadata->addSqlResultSetMapping(
205
                    [
206 17
                        'name'          => $resultSetMapping->name,
207 17
                        'entities'      => $entities,
208 17
                        'columns'       => $columns
209
                    ]
210
                );
211
            }
212
        }
213
214
        // Evaluate NamedQueries annotation
215 412
        if (isset($classAnnotations[Mapping\NamedQueries::class])) {
216 11
            $namedQueriesAnnot = $classAnnotations[Mapping\NamedQueries::class];
217
218 11
            if ( ! is_array($namedQueriesAnnot->value)) {
219
                throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
220
            }
221
222 11
            foreach ($namedQueriesAnnot->value as $namedQuery) {
223 11
                if ( ! ($namedQuery instanceof Mapping\NamedQuery)) {
224
                    throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
225
                }
226 11
                $metadata->addNamedQuery(
227
                    [
228 11
                        'name'  => $namedQuery->name,
229 11
                        'query' => $namedQuery->query
230
                    ]
231
                );
232
            }
233
        }
234
235
        // Evaluate InheritanceType annotation
236 412
        if (isset($classAnnotations[Mapping\InheritanceType::class])) {
237 84
            $inheritanceTypeAnnot = $classAnnotations[Mapping\InheritanceType::class];
238
239 84
            $metadata->setInheritanceType(
240 84
                constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceTypeAnnot->value)
241
            );
242
243 84
            if ($metadata->inheritanceType != Mapping\ClassMetadata::INHERITANCE_TYPE_NONE) {
244
                // Evaluate DiscriminatorColumn annotation
245 84
                if (isset($classAnnotations[Mapping\DiscriminatorColumn::class])) {
246 66
                    $discrColumnAnnot = $classAnnotations[Mapping\DiscriminatorColumn::class];
247
248 66
                    $metadata->setDiscriminatorColumn(
249
                        [
250 66
                            'name'             => $discrColumnAnnot->name,
251 66
                            'type'             => $discrColumnAnnot->type ?: 'string',
252 66
                            'length'           => $discrColumnAnnot->length ?: 255,
253 66
                            'columnDefinition' => $discrColumnAnnot->columnDefinition,
254
                        ]
255
                    );
256
                } else {
257 21
                    $metadata->setDiscriminatorColumn(['name' => 'dtype', 'type' => 'string', 'length' => 255]);
258
                }
259
260
                // Evaluate DiscriminatorMap annotation
261 84
                if (isset($classAnnotations[Mapping\DiscriminatorMap::class])) {
262 83
                    $discrMapAnnot = $classAnnotations[Mapping\DiscriminatorMap::class];
263 83
                    $metadata->setDiscriminatorMap($discrMapAnnot->value);
264
                }
265
            }
266
        }
267
268
269
        // Evaluate DoctrineChangeTrackingPolicy annotation
270 412
        if (isset($classAnnotations[Mapping\ChangeTrackingPolicy::class])) {
271 5
            $changeTrackingAnnot = $classAnnotations[Mapping\ChangeTrackingPolicy::class];
272 5
            $metadata->setChangeTrackingPolicy(constant('Doctrine\ORM\Mapping\ClassMetadata::CHANGETRACKING_' . $changeTrackingAnnot->value));
273
        }
274
275
        // Evaluate annotations on properties/fields
276
        /* @var $property \ReflectionProperty */
277 412
        foreach ($class->getProperties() as $property) {
278 410
            if ($metadata->isMappedSuperclass && ! $property->isPrivate()
279
                ||
280 410
                $metadata->isInheritedField($property->name)
281
                ||
282 410
                $metadata->isInheritedAssociation($property->name)
283
                ||
284 410
                $metadata->isInheritedEmbeddedClass($property->name)) {
285 81
                continue;
286
            }
287
288 410
            $mapping = [];
289 410
            $mapping['fieldName'] = $property->getName();
290
291
            // Evaluate @Cache annotation
292 410
            if (($cacheAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Cache::class)) !== null) {
293 14
                $mapping['cache'] = $metadata->getAssociationCacheDefaults(
294 14
                    $mapping['fieldName'],
295
                    [
296 14
                        'usage'  => constant('Doctrine\ORM\Mapping\ClassMetadata::CACHE_USAGE_' . $cacheAnnot->usage),
297 14
                        'region' => $cacheAnnot->region,
298
                    ]
299
                );
300
            }
301
            // Check for JoinColumn/JoinColumns annotations
302 409
            $joinColumns = [];
303
304 409
            if ($joinColumnAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinColumn::class)) {
305 154
                $joinColumns[] = $this->joinColumnToArray($joinColumnAnnot);
306 408
            } else if ($joinColumnsAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinColumns::class)) {
307 19
                foreach ($joinColumnsAnnot->value as $joinColumn) {
308 19
                    $joinColumns[] = $this->joinColumnToArray($joinColumn);
309
                }
310
            }
311
312
            // Field can only be annotated with one of:
313
            // @Column, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany
0 ignored issues
show
Unused Code Comprehensibility introduced by
48% 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...
314 409
            if ($columnAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Column::class)) {
315 401
                if ($columnAnnot->type == null) {
316
                    throw MappingException::propertyTypeIsRequired($className, $property->getName());
317
                }
318
319 401
                $mapping = $this->columnToArray($property->getName(), $columnAnnot);
320
321 401
                if ($idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class)) {
0 ignored issues
show
Unused Code introduced by
The assignment to $idAnnot is dead and can be removed.
Loading history...
322 395
                    $mapping['id'] = true;
323
                }
324
325 401
                if ($generatedValueAnnot = $this->reader->getPropertyAnnotation($property, Mapping\GeneratedValue::class)) {
326 339
                    $metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $generatedValueAnnot->strategy));
327
                }
328
329 401
                if ($this->reader->getPropertyAnnotation($property, Mapping\Version::class)) {
330 17
                    $metadata->setVersionMapping($mapping);
331
                }
332
333 401
                $metadata->mapField($mapping);
334
335
                // Check for SequenceGenerator/TableGenerator definition
336 401
                if ($seqGeneratorAnnot = $this->reader->getPropertyAnnotation($property, Mapping\SequenceGenerator::class)) {
337 9
                    $metadata->setSequenceGeneratorDefinition(
338
                        [
339 9
                            'sequenceName' => $seqGeneratorAnnot->sequenceName,
340 9
                            'allocationSize' => $seqGeneratorAnnot->allocationSize,
341 9
                            'initialValue' => $seqGeneratorAnnot->initialValue
342
                        ]
343
                    );
344 398
                } else if ($this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\TableGenerator')) {
345
                    throw MappingException::tableIdGeneratorNotImplemented($className);
346 398
                } else if ($customGeneratorAnnot = $this->reader->getPropertyAnnotation($property, Mapping\CustomIdGenerator::class)) {
347 3
                    $metadata->setCustomGeneratorDefinition(
348
                        [
349 401
                            'class' => $customGeneratorAnnot->class
350
                        ]
351
                    );
352
                }
353 287
            } else if ($oneToOneAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OneToOne::class)) {
354 123
                if ($idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class)) {
355 12
                    $mapping['id'] = true;
356
                }
357
358 123
                $mapping['targetEntity'] = $oneToOneAnnot->targetEntity;
359 123
                $mapping['joinColumns'] = $joinColumns;
360 123
                $mapping['mappedBy'] = $oneToOneAnnot->mappedBy;
361 123
                $mapping['inversedBy'] = $oneToOneAnnot->inversedBy;
362 123
                $mapping['cascade'] = $oneToOneAnnot->cascade;
363 123
                $mapping['orphanRemoval'] = $oneToOneAnnot->orphanRemoval;
364 123
                $mapping['fetch'] = $this->getFetchMode($className, $oneToOneAnnot->fetch);
365 123
                $metadata->mapOneToOne($mapping);
366 234
            } else if ($oneToManyAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OneToMany::class)) {
367 117
                $mapping['mappedBy'] = $oneToManyAnnot->mappedBy;
368 117
                $mapping['targetEntity'] = $oneToManyAnnot->targetEntity;
369 117
                $mapping['cascade'] = $oneToManyAnnot->cascade;
370 117
                $mapping['indexBy'] = $oneToManyAnnot->indexBy;
371 117
                $mapping['orphanRemoval'] = $oneToManyAnnot->orphanRemoval;
372 117
                $mapping['fetch'] = $this->getFetchMode($className, $oneToManyAnnot->fetch);
373
374 117
                if ($orderByAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OrderBy::class)) {
375 16
                    $mapping['orderBy'] = $orderByAnnot->value;
376
                }
377
378 117
                $metadata->mapOneToMany($mapping);
379 230
            } else if ($manyToOneAnnot = $this->reader->getPropertyAnnotation($property, Mapping\ManyToOne::class)) {
380 151
                if ($idAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Id::class)) {
381 35
                    $mapping['id'] = true;
382
                }
383
384 151
                $mapping['joinColumns'] = $joinColumns;
385 151
                $mapping['cascade'] = $manyToOneAnnot->cascade;
386 151
                $mapping['inversedBy'] = $manyToOneAnnot->inversedBy;
387 151
                $mapping['targetEntity'] = $manyToOneAnnot->targetEntity;
388 151
                $mapping['fetch'] = $this->getFetchMode($className, $manyToOneAnnot->fetch);
389 151
                $metadata->mapManyToOne($mapping);
390 130
            } else if ($manyToManyAnnot = $this->reader->getPropertyAnnotation($property, Mapping\ManyToMany::class)) {
391 96
                $joinTable = [];
392
393 96
                if ($joinTableAnnot = $this->reader->getPropertyAnnotation($property, Mapping\JoinTable::class)) {
394
                    $joinTable = [
395 76
                        'name' => $joinTableAnnot->name,
396 76
                        'schema' => $joinTableAnnot->schema
397
                    ];
398
399 76
                    foreach ($joinTableAnnot->joinColumns as $joinColumn) {
400 75
                        $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn);
401
                    }
402
403 76
                    foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) {
404 75
                        $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn);
405
                    }
406
                }
407
408 96
                $mapping['joinTable'] = $joinTable;
409 96
                $mapping['targetEntity'] = $manyToManyAnnot->targetEntity;
410 96
                $mapping['mappedBy'] = $manyToManyAnnot->mappedBy;
411 96
                $mapping['inversedBy'] = $manyToManyAnnot->inversedBy;
412 96
                $mapping['cascade'] = $manyToManyAnnot->cascade;
413 96
                $mapping['indexBy'] = $manyToManyAnnot->indexBy;
414 96
                $mapping['orphanRemoval'] = $manyToManyAnnot->orphanRemoval;
415 96
                $mapping['fetch'] = $this->getFetchMode($className, $manyToManyAnnot->fetch);
416
417 96
                if ($orderByAnnot = $this->reader->getPropertyAnnotation($property, Mapping\OrderBy::class)) {
418 3
                    $mapping['orderBy'] = $orderByAnnot->value;
419
                }
420
421 96
                $metadata->mapManyToMany($mapping);
422 54
            } else if ($embeddedAnnot = $this->reader->getPropertyAnnotation($property, Mapping\Embedded::class)) {
423 13
                $mapping['class'] = $embeddedAnnot->class;
424 13
                $mapping['columnPrefix'] = $embeddedAnnot->columnPrefix;
425
426 408
                $metadata->mapEmbedded($mapping);
427
            }
428
        }
429
430
        // Evaluate AssociationOverrides annotation
431 410
        if (isset($classAnnotations[Mapping\AssociationOverrides::class])) {
432 5
            $associationOverridesAnnot = $classAnnotations[Mapping\AssociationOverrides::class];
433
434 5
            foreach ($associationOverridesAnnot->value as $associationOverride) {
435 5
                $override   = [];
436 5
                $fieldName  = $associationOverride->name;
437
438
                // Check for JoinColumn/JoinColumns annotations
439 5
                if ($associationOverride->joinColumns) {
440 3
                    $joinColumns = [];
441
442 3
                    foreach ($associationOverride->joinColumns as $joinColumn) {
443 3
                        $joinColumns[] = $this->joinColumnToArray($joinColumn);
444
                    }
445
446 3
                    $override['joinColumns'] = $joinColumns;
447
                }
448
449
                // Check for JoinTable annotations
450 5
                if ($associationOverride->joinTable) {
451 2
                    $joinTableAnnot = $associationOverride->joinTable;
452
                    $joinTable      = [
453 2
                        'name'      => $joinTableAnnot->name,
454 2
                        'schema'    => $joinTableAnnot->schema
455
                    ];
456
457 2
                    foreach ($joinTableAnnot->joinColumns as $joinColumn) {
458 2
                        $joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn);
459
                    }
460
461 2
                    foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) {
462 2
                        $joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn);
463
                    }
464
465 2
                    $override['joinTable'] = $joinTable;
466
                }
467
468
                // Check for inversedBy
469 5
                if ($associationOverride->inversedBy) {
470 1
                    $override['inversedBy'] = $associationOverride->inversedBy;
471
                }
472
473
                // 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...
474 5
                if ($associationOverride->fetch) {
475 1
                    $override['fetch'] = constant(Mapping\ClassMetadata::class . '::FETCH_' . $associationOverride->fetch);
476
                }
477
478 5
                $metadata->setAssociationOverride($fieldName, $override);
479
            }
480
        }
481
482
        // Evaluate AttributeOverrides annotation
483 410
        if (isset($classAnnotations[Mapping\AttributeOverrides::class])) {
484 3
            $attributeOverridesAnnot = $classAnnotations[Mapping\AttributeOverrides::class];
485
486 3
            foreach ($attributeOverridesAnnot->value as $attributeOverrideAnnot) {
487 3
                $attributeOverride = $this->columnToArray($attributeOverrideAnnot->name, $attributeOverrideAnnot->column);
488
489 3
                $metadata->setAttributeOverride($attributeOverrideAnnot->name, $attributeOverride);
490
            }
491
        }
492
493
        // Evaluate EntityListeners annotation
494 410
        if (isset($classAnnotations[Mapping\EntityListeners::class])) {
495 12
            $entityListenersAnnot = $classAnnotations[Mapping\EntityListeners::class];
496
497 12
            foreach ($entityListenersAnnot->value as $item) {
498 12
                $listenerClassName = $metadata->fullyQualifiedClassName($item);
499
500 12
                if ( ! class_exists($listenerClassName)) {
501
                    throw MappingException::entityListenerClassNotFound($listenerClassName, $className);
502
                }
503
504 12
                $hasMapping     = false;
505 12
                $listenerClass  = new \ReflectionClass($listenerClassName);
506
507
                /* @var $method \ReflectionMethod */
508 12
                foreach ($listenerClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
509
                    // find method callbacks.
510 12
                    $callbacks  = $this->getMethodCallbacks($method);
511 12
                    $hasMapping = $hasMapping ?: ( ! empty($callbacks));
512
513 12
                    foreach ($callbacks as $value) {
514 12
                        $metadata->addEntityListener($value[1], $listenerClassName, $value[0]);
515
                    }
516
                }
517
518
                // Evaluate the listener using naming convention.
519 12
                if ( ! $hasMapping ) {
520 12
                    EntityListenerBuilder::bindEntityListener($metadata, $listenerClassName);
521
                }
522
            }
523
        }
524
525
        // Evaluate @HasLifecycleCallbacks annotation
526 410
        if (isset($classAnnotations[Mapping\HasLifecycleCallbacks::class])) {
527
            /* @var $method \ReflectionMethod */
528 19
            foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) {
529 18
                foreach ($this->getMethodCallbacks($method) as $value) {
530 18
                    $metadata->addLifecycleCallback($value[0], $value[1]);
531
                }
532
            }
533
        }
534 410
    }
535
536
    /**
537
     * Attempts to resolve the fetch mode.
538
     *
539
     * @param string $className The class name.
540
     * @param string $fetchMode The fetch mode.
541
     *
542
     * @return integer The fetch mode as defined in ClassMetadata.
543
     *
544
     * @throws MappingException If the fetch mode is not valid.
545
     */
546 273
    private function getFetchMode($className, $fetchMode)
547
    {
548 273
        if ( ! defined('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode)) {
549
            throw MappingException::invalidFetchMode($className, $fetchMode);
550
        }
551
552 273
        return constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode);
553
    }
554
555
    /**
556
     * Parses the given method.
557
     *
558
     * @param \ReflectionMethod $method
559
     *
560
     * @return array
561
     */
562 28
    private function getMethodCallbacks(\ReflectionMethod $method)
563
    {
564 28
        $callbacks   = [];
565 28
        $annotations = $this->reader->getMethodAnnotations($method);
566
567 28
        foreach ($annotations as $annot) {
568 22
            if ($annot instanceof Mapping\PrePersist) {
569 15
                $callbacks[] = [$method->name, Events::prePersist];
570
            }
571
572 22
            if ($annot instanceof Mapping\PostPersist) {
573 11
                $callbacks[] = [$method->name, Events::postPersist];
574
            }
575
576 22
            if ($annot instanceof Mapping\PreUpdate) {
577 11
                $callbacks[] = [$method->name, Events::preUpdate];
578
            }
579
580 22
            if ($annot instanceof Mapping\PostUpdate) {
581 7
                $callbacks[] = [$method->name, Events::postUpdate];
582
            }
583
584 22
            if ($annot instanceof Mapping\PreRemove) {
585 8
                $callbacks[] = [$method->name, Events::preRemove];
586
            }
587
588 22
            if ($annot instanceof Mapping\PostRemove) {
589 6
                $callbacks[] = [$method->name, Events::postRemove];
590
            }
591
592 22
            if ($annot instanceof Mapping\PostLoad) {
593 11
                $callbacks[] = [$method->name, Events::postLoad];
594
            }
595
596 22
            if ($annot instanceof Mapping\PreFlush) {
597 22
                $callbacks[] = [$method->name, Events::preFlush];
598
            }
599
        }
600
601 28
        return $callbacks;
602
    }
603
604
    /**
605
     * Parse the given JoinColumn as array
606
     *
607
     * @param Mapping\JoinColumn $joinColumn
608
     * @return array
609
     */
610 191
    private function joinColumnToArray(Mapping\JoinColumn $joinColumn)
611
    {
612
        return [
613 191
            'name' => $joinColumn->name,
614 191
            'unique' => $joinColumn->unique,
615 191
            'nullable' => $joinColumn->nullable,
616 191
            'onDelete' => $joinColumn->onDelete,
617 191
            'columnDefinition' => $joinColumn->columnDefinition,
618 191
            'referencedColumnName' => $joinColumn->referencedColumnName,
619
        ];
620
    }
621
622
    /**
623
     * Parse the given Column as array
624
     *
625
     * @param string $fieldName
626
     * @param Mapping\Column $column
627
     *
628
     * @return array
629
     */
630 401
    private function columnToArray($fieldName, Mapping\Column $column)
631
    {
632
        $mapping = [
633 401
            'fieldName' => $fieldName,
634 401
            'type'      => $column->type,
635 401
            'scale'     => $column->scale,
636 401
            'length'    => $column->length,
637 401
            'unique'    => $column->unique,
638 401
            'nullable'  => $column->nullable,
639 401
            'precision' => $column->precision
640
        ];
641
642 401
        if ($column->options) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $column->options of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
643 10
            $mapping['options'] = $column->options;
644
        }
645
646 401
        if (isset($column->name)) {
647 85
            $mapping['columnName'] = $column->name;
648
        }
649
650 401
        if (isset($column->columnDefinition)) {
651 6
            $mapping['columnDefinition'] = $column->columnDefinition;
652
        }
653
654 401
        return $mapping;
655
    }
656
657
    /**
658
     * Factory method for the Annotation Driver.
659
     *
660
     * @param array|string          $paths
661
     * @param AnnotationReader|null $reader
662
     *
663
     * @return AnnotationDriver
664
     */
665
    static public function create($paths = [], AnnotationReader $reader = null)
0 ignored issues
show
Coding Style introduced by
As per PSR2, the static declaration should come after the visibility declaration.
Loading history...
666
    {
667
        if ($reader == null) {
668
            $reader = new AnnotationReader();
669
        }
670
671
        return new self($reader, $paths);
672
    }
673
}
674