Total Complexity | 143 |
Total Lines | 1189 |
Duplicated Lines | 11.52 % |
Changes | 0 |
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 classes like NewAnnotationDriver 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 NewAnnotationDriver, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
15 | class NewAnnotationDriver implements MappingDriver |
||
16 | { |
||
17 | static protected $entityAnnotationClasses = [ |
||
18 | Annotation\Entity::class => 1, |
||
19 | Annotation\MappedSuperclass::class => 2, |
||
20 | ]; |
||
21 | |||
22 | /** |
||
23 | * The Annotation reader. |
||
24 | * |
||
25 | * @var AnnotationReader |
||
26 | */ |
||
27 | protected $reader; |
||
28 | |||
29 | /** |
||
30 | * The file locator. |
||
31 | * |
||
32 | * @var FileLocator |
||
33 | */ |
||
34 | protected $locator; |
||
35 | |||
36 | /** |
||
37 | * @var Factory\NamingStrategy |
||
38 | */ |
||
39 | protected $namingStrategy; |
||
40 | |||
41 | /** |
||
42 | * Cache for AnnotationDriver#getAllClassNames(). |
||
43 | * |
||
44 | * @var array|null |
||
45 | */ |
||
46 | private $classNames; |
||
47 | |||
48 | /** |
||
49 | * Initializes a new AnnotationDriver that uses the given AnnotationReader for reading docblock annotations. |
||
50 | * |
||
51 | * @param AnnotationReader $reader The AnnotationReader to use, duck-typed. |
||
52 | * @param FileLocator $locator A FileLocator or one/multiple paths where mapping documents can be found. |
||
53 | * @param Factory\NamingStrategy $namingStrategy The NamingStrategy to use. |
||
54 | */ |
||
55 | public function __construct(AnnotationReader $reader, FileLocator $locator, Factory\NamingStrategy $namingStrategy) |
||
56 | { |
||
57 | $this->reader = $reader; |
||
58 | $this->locator = $locator; |
||
59 | $this->namingStrategy = $namingStrategy; |
||
60 | } |
||
61 | |||
62 | /** |
||
63 | * {@inheritdoc} |
||
64 | * |
||
65 | * @return Mapping\ClassMetadata |
||
66 | * |
||
67 | * @throws Mapping\MappingException |
||
68 | */ |
||
69 | public function loadMetadataForClass( |
||
70 | string $className, |
||
71 | Mapping\ClassMetadata $metadata, |
||
72 | Mapping\ClassMetadataBuildingContext $metadataBuildingContext |
||
73 | ) |
||
74 | { |
||
75 | // IMPORTANT: We're handling $metadata as "parent" metadata here, while building the $className ClassMetadata. |
||
76 | $reflectionClass = new \ReflectionClass($className); |
||
77 | |||
78 | // Evaluate annotations on class metadata |
||
79 | $classAnnotations = $this->getClassAnnotations($reflectionClass); |
||
80 | $classMetadata = $this->convertClassAnnotationsToClassMetadata( |
||
81 | $classAnnotations, |
||
82 | $reflectionClass, |
||
83 | $metadata |
||
84 | ); |
||
85 | |||
86 | // Evaluate @Cache annotation |
||
87 | View Code Duplication | if (isset($classAnnotations[Annotation\Cache::class])) { |
|
|
|||
88 | $cacheAnnot = $classAnnotations[Annotation\Cache::class]; |
||
89 | $cache = $this->convertCacheAnnotationToCacheMetadata($cacheAnnot, $classMetadata); |
||
90 | |||
91 | $classMetadata->setCache($cache); |
||
92 | } |
||
93 | |||
94 | // Evaluate annotations on properties/fields |
||
95 | /* @var \ReflectionProperty $reflectionProperty */ |
||
96 | foreach ($reflectionClass->getProperties() as $reflectionProperty) { |
||
97 | if ($reflectionProperty->getDeclaringClass()->getClassName() !== $reflectionClass->getName()) { |
||
98 | continue; |
||
99 | } |
||
100 | |||
101 | $propertyAnnotations = $this->getPropertyAnnotations($reflectionProperty); |
||
102 | $property = $this->convertReflectionPropertyAnnotationsToProperty( |
||
103 | $reflectionProperty, |
||
104 | $propertyAnnotations, |
||
105 | $classMetadata |
||
106 | ); |
||
107 | |||
108 | $classMetadata->addDeclaredProperty($property); |
||
109 | } |
||
110 | |||
111 | return $classMetadata; |
||
112 | } |
||
113 | |||
114 | /** |
||
115 | * {@inheritdoc} |
||
116 | */ |
||
117 | public function getAllClassNames() |
||
118 | { |
||
119 | if ($this->classNames !== null) { |
||
120 | return $this->classNames; |
||
121 | } |
||
122 | |||
123 | $classNames = array_filter( |
||
124 | $this->locator->getAllClassNames(null), |
||
125 | function ($className) { |
||
126 | return ! $this->isTransient($className); |
||
127 | } |
||
128 | ); |
||
129 | |||
130 | $this->classNames = $classNames; |
||
131 | |||
132 | return $classNames; |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * {@inheritdoc} |
||
137 | */ |
||
138 | public function isTransient($className) |
||
139 | { |
||
140 | $reflectionClass = new \ReflectionClass($className); |
||
141 | $classAnnotations = $this->reader->getClassAnnotations($reflectionClass); |
||
142 | |||
143 | foreach ($classAnnotations as $annotation) { |
||
144 | if (isset(self::$entityAnnotationClasses[get_class($annotation)])) { |
||
145 | return false; |
||
146 | } |
||
147 | } |
||
148 | |||
149 | return true; |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * @param array $classAnnotations |
||
154 | * @param \ReflectionClass $reflectionClass |
||
155 | * @param Mapping\ClassMetadata $parent |
||
156 | * |
||
157 | * @return Mapping\ClassMetadata|Mapping\ComponentMetadata |
||
158 | * |
||
159 | * @throws Mapping\MappingException |
||
160 | */ |
||
161 | private function convertClassAnnotationsToClassMetadata( |
||
162 | array $classAnnotations, |
||
163 | \ReflectionClass $reflectionClass, |
||
164 | Mapping\ClassMetadata $parent |
||
165 | ) |
||
166 | { |
||
167 | switch (true) { |
||
168 | case isset($classAnnotations[Annotation\Entity::class]): |
||
169 | return $this->convertClassAnnotationsToEntityClassMetadata( |
||
170 | $classAnnotations, |
||
171 | $reflectionClass, |
||
172 | $parent |
||
173 | ); |
||
174 | |||
175 | break; |
||
176 | |||
177 | case isset($classAnnotations[Annotation\MappedSuperclass::class]): |
||
178 | return $this->convertClassAnnotationsToMappedSuperClassMetadata( |
||
179 | $classAnnotations, |
||
180 | $reflectionClass, |
||
181 | $parent |
||
182 | ); |
||
183 | |||
184 | case isset($classAnnotations[Annotation\Embeddable::class]): |
||
185 | return $this->convertClassAnnotationsToEntityClassMetadata( |
||
186 | $classAnnotations, |
||
187 | $reflectionClass, |
||
188 | $parent |
||
189 | ); |
||
190 | |||
191 | default: |
||
192 | throw Mapping\MappingException::classIsNotAValidEntityOrMappedSuperClass($reflectionClass->getName()); |
||
193 | } |
||
194 | } |
||
195 | |||
196 | /** |
||
197 | * @param array $classAnnotations |
||
198 | * @param \ReflectionClass $reflectionClass |
||
199 | * @param Mapping\ClassMetadata $parent |
||
200 | * |
||
201 | * @return Mapping\ClassMetadata |
||
202 | * |
||
203 | * @throws Mapping\MappingException |
||
204 | * @throws \UnexpectedValueException |
||
205 | */ |
||
206 | private function convertClassAnnotationsToEntityClassMetadata( |
||
207 | array $classAnnotations, |
||
208 | \ReflectionClass $reflectionClass, |
||
209 | Mapping\ClassMetadata $parent |
||
210 | ) |
||
211 | { |
||
212 | /** @var Annotation\Entity $entityAnnot */ |
||
213 | $entityAnnot = $classAnnotations[Annotation\Entity::class]; |
||
214 | $classMetadata = new Mapping\ClassMetadata($reflectionClass->getName(), $parent); |
||
215 | |||
216 | if ($entityAnnot->repositoryClass !== null) { |
||
217 | $classMetadata->setCustomRepositoryClassName( |
||
218 | $classMetadata->fullyQualifiedClassName($entityAnnot->repositoryClass) |
||
219 | ); |
||
220 | } |
||
221 | |||
222 | if ($entityAnnot->readOnly) { |
||
223 | $classMetadata->asReadOnly(); |
||
224 | } |
||
225 | |||
226 | // Evaluate @Table annotation |
||
227 | if (isset($classAnnotations[Annotation\Table::class])) { |
||
228 | /** @var Annotation\Table $tableAnnot */ |
||
229 | $tableAnnot = $classAnnotations[Annotation\Table::class]; |
||
230 | $table = $this->convertTableAnnotationToTableMetadata($tableAnnot); |
||
231 | |||
232 | $classMetadata->setTable($table); |
||
233 | } |
||
234 | |||
235 | // Evaluate @ChangeTrackingPolicy annotation |
||
236 | if (isset($classAnnotations[Annotation\ChangeTrackingPolicy::class])) { |
||
237 | /** @var Annotation\ChangeTrackingPolicy $changeTrackingAnnot */ |
||
238 | $changeTrackingAnnot = $classAnnotations[Annotation\ChangeTrackingPolicy::class]; |
||
239 | |||
240 | $classMetadata->setChangeTrackingPolicy( |
||
241 | constant(sprintf('%s::%s', Mapping\ChangeTrackingPolicy::class, $changeTrackingAnnot->value)) |
||
242 | ); |
||
243 | } |
||
244 | |||
245 | // Evaluate @NamedNativeQueries annotation |
||
246 | if (isset($classAnnotations[Annotation\NamedNativeQueries::class])) { |
||
247 | /** @var Annotation\NamedNativeQueries $namedNativeQueriesAnnot */ |
||
248 | $namedNativeQueriesAnnot = $classAnnotations[Annotation\NamedNativeQueries::class]; |
||
249 | |||
250 | foreach ($namedNativeQueriesAnnot->value as $namedNativeQuery) { |
||
251 | $classMetadata->addNamedNativeQuery( |
||
252 | $namedNativeQuery->name, |
||
253 | $namedNativeQuery->query, |
||
254 | [ |
||
255 | 'resultClass' => $namedNativeQuery->resultClass, |
||
256 | 'resultSetMapping' => $namedNativeQuery->resultSetMapping, |
||
257 | ] |
||
258 | ); |
||
259 | } |
||
260 | } |
||
261 | |||
262 | // Evaluate @SqlResultSetMappings annotation |
||
263 | if (isset($classAnnotations[Annotation\SqlResultSetMappings::class])) { |
||
264 | /** @var Annotation\SqlResultSetMappings $sqlResultSetMappingsAnnot */ |
||
265 | $sqlResultSetMappingsAnnot = $classAnnotations[Annotation\SqlResultSetMappings::class]; |
||
266 | |||
267 | foreach ($sqlResultSetMappingsAnnot->value as $resultSetMapping) { |
||
268 | $sqlResultSetMapping = $this->convertSqlResultSetMapping($resultSetMapping); |
||
269 | |||
270 | $classMetadata->addSqlResultSetMapping($sqlResultSetMapping); |
||
271 | } |
||
272 | } |
||
273 | |||
274 | // Evaluate @NamedQueries annotation |
||
275 | if (isset($classAnnotations[Annotation\NamedQueries::class])) { |
||
276 | /** @var Annotation\NamedQueries $namedQueriesAnnot */ |
||
277 | $namedQueriesAnnot = $classAnnotations[Annotation\NamedQueries::class]; |
||
278 | |||
279 | if (! is_array($namedQueriesAnnot->value)) { |
||
280 | throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations."); |
||
281 | } |
||
282 | |||
283 | foreach ($namedQueriesAnnot->value as $namedQuery) { |
||
284 | if (! ($namedQuery instanceof Annotation\NamedQuery)) { |
||
285 | throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations."); |
||
286 | } |
||
287 | |||
288 | $classMetadata->addNamedQuery($namedQuery->name, $namedQuery->query); |
||
289 | } |
||
290 | } |
||
291 | |||
292 | // Evaluate @EntityListeners annotation |
||
293 | if (isset($classAnnotations[Annotation\EntityListeners::class])) { |
||
294 | /** @var Annotation\EntityListeners $entityListenersAnnot */ |
||
295 | $entityListenersAnnot = $classAnnotations[Annotation\EntityListeners::class]; |
||
296 | |||
297 | foreach ($entityListenersAnnot->value as $item) { |
||
298 | $listenerClassName = $classMetadata->fullyQualifiedClassName($item); |
||
299 | |||
300 | if (! class_exists($listenerClassName)) { |
||
301 | throw Mapping\MappingException::entityListenerClassNotFound( |
||
302 | $listenerClassName, |
||
303 | $reflectionClass->getName() |
||
304 | ); |
||
305 | } |
||
306 | |||
307 | $listenerClass = new \ReflectionClass($listenerClassName); |
||
308 | |||
309 | /* @var $method \ReflectionMethod */ |
||
310 | foreach ($listenerClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { |
||
311 | foreach ($this->getMethodCallbacks($method) as $callback) { |
||
312 | $classMetadata->addEntityListener($callback, $listenerClassName, $method->getName()); |
||
313 | } |
||
314 | } |
||
315 | } |
||
316 | } |
||
317 | |||
318 | // Evaluate @HasLifecycleCallbacks annotation |
||
319 | if (isset($classAnnotations[Annotation\HasLifecycleCallbacks::class])) { |
||
320 | /* @var $method \ReflectionMethod */ |
||
321 | foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $method) { |
||
322 | foreach ($this->getMethodCallbacks($method) as $callback) { |
||
323 | $classMetadata->addLifecycleCallback($method->getName(), $callback); |
||
324 | } |
||
325 | } |
||
326 | } |
||
327 | |||
328 | // Evaluate @InheritanceType annotation |
||
329 | if (isset($classAnnotations[Annotation\InheritanceType::class])) { |
||
330 | /** @var Annotation\InheritanceType $inheritanceTypeAnnot */ |
||
331 | $inheritanceTypeAnnot = $classAnnotations[Annotation\InheritanceType::class]; |
||
332 | |||
333 | $classMetadata->setInheritanceType( |
||
334 | constant(sprintf('%s::%s', Mapping\InheritanceType::class, $inheritanceTypeAnnot->value)) |
||
335 | ); |
||
336 | |||
337 | if ($classMetadata->inheritanceType !== Mapping\InheritanceType::NONE) { |
||
338 | $discriminatorColumn = new Mapping\DiscriminatorColumnMetadata(); |
||
339 | |||
340 | // Evaluate @DiscriminatorColumn annotation |
||
341 | if (isset($classAnnotations[Annotation\DiscriminatorColumn::class])) { |
||
342 | /** @var Annotation\DiscriminatorColumn $discriminatorColumnAnnot */ |
||
343 | $discriminatorColumnAnnot = $classAnnotations[Annotation\DiscriminatorColumn::class]; |
||
344 | |||
345 | $discriminatorColumn->setColumnName($discriminatorColumnAnnot->name); |
||
346 | |||
347 | if (! empty($discriminatorColumnAnnot->columnDefinition)) { |
||
348 | $discriminatorColumn->setColumnDefinition($discriminatorColumnAnnot->columnDefinition); |
||
349 | } |
||
350 | |||
351 | if (! empty($discriminatorColumnAnnot->type)) { |
||
352 | $discriminatorColumn->setType(Type::getType($discriminatorColumnAnnot->type)); |
||
353 | } |
||
354 | |||
355 | if (! empty($discriminatorColumnAnnot->length)) { |
||
356 | $discriminatorColumn->setLength($discriminatorColumnAnnot->length); |
||
357 | } |
||
358 | } |
||
359 | |||
360 | if (empty($discriminatorColumn->getColumnName())) { |
||
361 | throw Mapping\MappingException::nameIsMandatoryForDiscriminatorColumns($reflectionClass->getName()); |
||
362 | } |
||
363 | |||
364 | $classMetadata->setDiscriminatorColumn($discriminatorColumn); |
||
365 | |||
366 | // Evaluate @DiscriminatorMap annotation |
||
367 | if (isset($classAnnotations[Annotation\DiscriminatorMap::class])) { |
||
368 | /** @var Annotation\DiscriminatorMap $discriminatorMapAnnotation */ |
||
369 | $discriminatorMapAnnotation = $classAnnotations[Annotation\DiscriminatorMap::class]; |
||
370 | $discriminatorMap = array_map( |
||
371 | function ($className) use ($classMetadata) { |
||
372 | return $classMetadata->fullyQualifiedClassName($className); |
||
373 | }, |
||
374 | $discriminatorMapAnnotation->value |
||
375 | ); |
||
376 | |||
377 | $classMetadata->setDiscriminatorMap($discriminatorMap); |
||
378 | } |
||
379 | } |
||
380 | } |
||
381 | |||
382 | return $classMetadata; |
||
383 | } |
||
384 | |||
385 | /** |
||
386 | * @param array $classAnnotations |
||
387 | * @param \ReflectionClass $reflectionClass |
||
388 | * @param Mapping\ClassMetadata $parent |
||
389 | * |
||
390 | * @return Mapping\MappedSuperClassMetadata |
||
391 | */ |
||
392 | private function convertClassAnnotationsToMappedSuperClassMetadata( |
||
393 | array $classAnnotations, |
||
394 | \ReflectionClass $reflectionClass, |
||
395 | Mapping\ClassMetadata $parent |
||
396 | ) |
||
397 | { |
||
398 | /** @var Annotation\MappedSuperclass $mappedSuperclassAnnot */ |
||
399 | $mappedSuperclassAnnot = $classAnnotations[Annotation\MappedSuperclass::class]; |
||
400 | $classMetadata = new Mapping\MappedSuperClassMetadata($reflectionClass->getName(), $parent); |
||
401 | |||
402 | if ($mappedSuperclassAnnot->repositoryClass !== null) { |
||
403 | $classMetadata->setCustomRepositoryClassName( |
||
404 | $classMetadata->fullyQualifiedClassName($mappedSuperclassAnnot->repositoryClass) |
||
405 | ); |
||
406 | } |
||
407 | |||
408 | return $classMetadata; |
||
409 | } |
||
410 | |||
411 | /** |
||
412 | * Parse the given Table as TableMetadata |
||
413 | * |
||
414 | * @param Annotation\Table $tableAnnot |
||
415 | * |
||
416 | * @return Mapping\TableMetadata |
||
417 | */ |
||
418 | private function convertTableAnnotationToTableMetadata(Annotation\Table $tableAnnot) |
||
419 | { |
||
420 | $table = new Mapping\TableMetadata(); |
||
421 | |||
422 | if (! empty($tableAnnot->name)) { |
||
423 | $table->setName($tableAnnot->name); |
||
424 | } |
||
425 | |||
426 | if (! empty($tableAnnot->schema)) { |
||
427 | $table->setSchema($tableAnnot->schema); |
||
428 | } |
||
429 | |||
430 | foreach ($tableAnnot->options as $optionName => $optionValue) { |
||
431 | $table->addOption($optionName, $optionValue); |
||
432 | } |
||
433 | |||
434 | foreach ($tableAnnot->indexes as $indexAnnot) { |
||
435 | $table->addIndex([ |
||
436 | 'name' => $indexAnnot->name, |
||
437 | 'columns' => $indexAnnot->columns, |
||
438 | 'unique' => $indexAnnot->unique, |
||
439 | 'options' => $indexAnnot->options, |
||
440 | 'flags' => $indexAnnot->flags, |
||
441 | ]); |
||
442 | } |
||
443 | |||
444 | foreach ($tableAnnot->uniqueConstraints as $uniqueConstraintAnnot) { |
||
445 | $table->addUniqueConstraint([ |
||
446 | 'name' => $uniqueConstraintAnnot->name, |
||
447 | 'columns' => $uniqueConstraintAnnot->columns, |
||
448 | 'options' => $uniqueConstraintAnnot->options, |
||
449 | 'flags' => $uniqueConstraintAnnot->flags, |
||
450 | ]); |
||
451 | } |
||
452 | |||
453 | return $table; |
||
454 | } |
||
455 | |||
456 | /** |
||
457 | * @param Annotation\SqlResultSetMapping $resultSetMapping |
||
458 | * |
||
459 | * @return array |
||
460 | */ |
||
461 | private function convertSqlResultSetMapping(Annotation\SqlResultSetMapping $resultSetMapping) |
||
462 | { |
||
463 | $entities = []; |
||
464 | |||
465 | foreach ($resultSetMapping->entities as $entityResultAnnot) { |
||
466 | $entityResult = [ |
||
467 | 'fields' => [], |
||
468 | 'entityClass' => $entityResultAnnot->entityClass, |
||
469 | 'discriminatorColumn' => $entityResultAnnot->discriminatorColumn, |
||
470 | ]; |
||
471 | |||
472 | foreach ($entityResultAnnot->fields as $fieldResultAnnot) { |
||
473 | $entityResult['fields'][] = [ |
||
474 | 'name' => $fieldResultAnnot->name, |
||
475 | 'column' => $fieldResultAnnot->column |
||
476 | ]; |
||
477 | } |
||
478 | |||
479 | $entities[] = $entityResult; |
||
480 | } |
||
481 | |||
482 | $columns = []; |
||
483 | |||
484 | foreach ($resultSetMapping->columns as $columnResultAnnot) { |
||
485 | $columns[] = [ |
||
486 | 'name' => $columnResultAnnot->name, |
||
487 | ]; |
||
488 | } |
||
489 | |||
490 | return [ |
||
491 | 'name' => $resultSetMapping->name, |
||
492 | 'entities' => $entities, |
||
493 | 'columns' => $columns |
||
494 | ]; |
||
495 | } |
||
496 | |||
497 | /** |
||
498 | * Parse the given Cache as CacheMetadata |
||
499 | * |
||
500 | * @param Annotation\Cache $cacheAnnot |
||
501 | * @param Mapping\ClassMetadata $metadata |
||
502 | * @param null|string $fieldName |
||
503 | * |
||
504 | * @return Mapping\CacheMetadata |
||
505 | */ |
||
506 | private function convertCacheAnnotationToCacheMetadata( |
||
507 | Annotation\Cache $cacheAnnot, |
||
508 | Mapping\ClassMetadata $metadata, |
||
509 | $fieldName = null |
||
510 | ) |
||
511 | { |
||
512 | $usage = constant(sprintf('%s::%s', Mapping\CacheUsage::class, $cacheAnnot->usage)); |
||
513 | $baseRegion = strtolower(str_replace('\\', '_', $metadata->getRootClassName())); |
||
514 | $defaultRegion = $baseRegion . ($fieldName ? '__' . $fieldName : ''); |
||
515 | |||
516 | return new Mapping\CacheMetadata($usage, $cacheAnnot->region ?: $defaultRegion); |
||
517 | } |
||
518 | |||
519 | /** |
||
520 | * @param \ReflectionProperty $reflectionProperty |
||
521 | * @param array $propertyAnnotations |
||
522 | * @param Mapping\ClassMetadata $classMetadata |
||
523 | * |
||
524 | * @return Mapping\Property |
||
525 | * |
||
526 | * @throws Mapping\MappingException |
||
527 | */ |
||
528 | private function convertReflectionPropertyAnnotationsToProperty( |
||
529 | \ReflectionProperty $reflectionProperty, |
||
530 | array $propertyAnnotations, |
||
531 | Mapping\ClassMetadata $classMetadata |
||
532 | ) |
||
533 | { |
||
534 | // Field can only be annotated with one of: |
||
535 | // @Column, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany, @Embedded |
||
536 | switch (true) { |
||
537 | case isset($propertyAnnotations[Annotation\Column::class]): |
||
538 | return $this->convertReflectionPropertyToFieldMetadata( |
||
539 | $reflectionProperty, |
||
540 | $propertyAnnotations, |
||
541 | $classMetadata |
||
542 | ); |
||
543 | |||
544 | case isset($propertyAnnotations[Annotation\OneToOne::class]): |
||
545 | return $this->convertReflectionPropertyToOneToOneAssociationMetadata( |
||
546 | $reflectionProperty, |
||
547 | $propertyAnnotations, |
||
548 | $classMetadata |
||
549 | ); |
||
550 | |||
551 | case isset($propertyAnnotations[Annotation\ManyToOne::class]): |
||
552 | return $this->convertReflectionPropertyToManyToOneAssociationMetadata( |
||
553 | $reflectionProperty, |
||
554 | $propertyAnnotations, |
||
555 | $classMetadata |
||
556 | ); |
||
557 | |||
558 | case isset($propertyAnnotations[Annotation\OneToMany::class]): |
||
559 | return $this->convertReflectionPropertyToOneToManyAssociationMetadata( |
||
560 | $reflectionProperty, |
||
561 | $propertyAnnotations, |
||
562 | $classMetadata |
||
563 | ); |
||
564 | |||
565 | case isset($propertyAnnotations[Annotation\ManyToMany::class]): |
||
566 | return $this->convertReflectionPropertyToManyToManyAssociationMetadata( |
||
567 | $reflectionProperty, |
||
568 | $propertyAnnotations, |
||
569 | $classMetadata |
||
570 | ); |
||
571 | |||
572 | case isset($propertyAnnotations[Annotation\Embedded::class]): |
||
573 | // @todo guilhermeblanco Implement later... =) |
||
574 | break; |
||
575 | |||
576 | default: |
||
577 | return new Mapping\TransientMetadata($reflectionProperty->getName()); |
||
578 | } |
||
579 | } |
||
580 | |||
581 | /** |
||
582 | * @param \ReflectionProperty $reflectionProperty |
||
583 | * @param array $propertyAnnotations |
||
584 | * @param Mapping\ClassMetadata $classMetadata |
||
585 | * |
||
586 | * @return Mapping\FieldMetadata |
||
587 | * |
||
588 | * @throws Mapping\MappingException |
||
589 | */ |
||
590 | private function convertReflectionPropertyToFieldMetadata( |
||
591 | \ReflectionProperty $reflectionProperty, |
||
592 | array $propertyAnnotations, |
||
593 | Mapping\ClassMetadata $classMetadata |
||
594 | ) |
||
595 | { |
||
596 | $className = $classMetadata->getClassName(); |
||
597 | $fieldName = $reflectionProperty->getName(); |
||
598 | $columnAnnot = $propertyAnnotations[Annotation\Column::class]; |
||
599 | $isVersioned = isset($propertyAnnotations[Annotation\Version::class]); |
||
600 | $isPrimaryKey = isset($propertyAnnotations[Annotation\Id::class]); |
||
601 | |||
602 | if ($columnAnnot->type === null) { |
||
603 | throw Mapping\MappingException::propertyTypeIsRequired($className, $fieldName); |
||
604 | } |
||
605 | |||
606 | if ($isVersioned && $isPrimaryKey) { |
||
607 | throw Mapping\MappingException::cannotVersionIdField($className, $fieldName); |
||
608 | } |
||
609 | |||
610 | $columnName = empty($columnAnnot->name) |
||
611 | ? $this->namingStrategy->propertyToColumnName($fieldName, $className) |
||
612 | : $columnAnnot->name |
||
613 | ; |
||
614 | |||
615 | $fieldMetadata = $isVersioned |
||
616 | ? new Mapping\VersionFieldMetadata($fieldName) |
||
617 | : new Mapping\FieldMetadata($fieldName) |
||
618 | ; |
||
619 | |||
620 | $fieldMetadata->setType(Type::getType($columnAnnot->type)); |
||
621 | $fieldMetadata->setColumnName($columnName); |
||
622 | $fieldMetadata->setScale($columnAnnot->scale); |
||
623 | $fieldMetadata->setPrecision($columnAnnot->precision); |
||
624 | $fieldMetadata->setNullable($columnAnnot->nullable); |
||
625 | $fieldMetadata->setUnique($columnAnnot->unique); |
||
626 | |||
627 | // Check for Id |
||
628 | if ($isPrimaryKey) { |
||
629 | if ($fieldMetadata->getType()->canRequireSQLConversion()) { |
||
630 | throw Mapping\MappingException::sqlConversionNotAllowedForPrimaryKeyProperties($className, $fieldMetadata); |
||
631 | }; |
||
632 | |||
633 | $fieldMetadata->setPrimaryKey(true); |
||
634 | } |
||
635 | |||
636 | if (! empty($columnAnnot->columnDefinition)) { |
||
637 | $fieldMetadata->setColumnDefinition($columnAnnot->columnDefinition); |
||
638 | } |
||
639 | |||
640 | if (! empty($columnAnnot->length)) { |
||
641 | $fieldMetadata->setLength($columnAnnot->length); |
||
642 | } |
||
643 | |||
644 | // Assign default options |
||
645 | $customOptions = $columnAnnot->options ?? []; |
||
646 | $defaultOptions = []; |
||
647 | |||
648 | if ($isVersioned) { |
||
649 | switch ($fieldMetadata->getTypeName()) { |
||
650 | case 'integer': |
||
651 | case 'bigint': |
||
652 | case 'smallint': |
||
653 | $defaultOptions['default'] = 1; |
||
654 | break; |
||
655 | |||
656 | case 'datetime': |
||
657 | $defaultOptions['default'] = 'CURRENT_TIMESTAMP'; |
||
658 | break; |
||
659 | |||
660 | default: |
||
661 | if (! isset($customOptions['default'])) { |
||
662 | throw Mapping\MappingException::unsupportedOptimisticLockingType($fieldMetadata->getType()); |
||
663 | } |
||
664 | } |
||
665 | } |
||
666 | |||
667 | $fieldMetadata->setOptions(array_merge($defaultOptions, $customOptions)); |
||
668 | |||
669 | return $fieldMetadata; |
||
670 | } |
||
671 | |||
672 | /** |
||
673 | * @param \ReflectionProperty $reflectionProperty |
||
674 | * @param array $propertyAnnotations |
||
675 | * @param Mapping\ClassMetadata $classMetadata |
||
676 | * |
||
677 | * @return Mapping\OneToOneAssociationMetadata |
||
678 | */ |
||
679 | private function convertReflectionPropertyToOneToOneAssociationMetadata( |
||
754 | } |
||
755 | |||
756 | /** |
||
757 | * @param \ReflectionProperty $reflectionProperty |
||
758 | * @param array $propertyAnnotations |
||
759 | * @param Mapping\ClassMetadata $classMetadata |
||
760 | * |
||
761 | * @return Mapping\ManyToOneAssociationMetadata |
||
762 | */ |
||
763 | private function convertReflectionPropertyToManyToOneAssociationMetadata( |
||
764 | \ReflectionProperty $reflectionProperty, |
||
765 | array $propertyAnnotations, |
||
766 | Mapping\ClassMetadata $classMetadata |
||
767 | ) |
||
768 | { |
||
769 | $className = $classMetadata->getClassName(); |
||
770 | $fieldName = $reflectionProperty->getName(); |
||
771 | $manyToOneAnnot = $propertyAnnotations[Annotation\ManyToOne::class]; |
||
772 | |||
773 | if ($manyToOneAnnot->targetEntity === null) { |
||
774 | throw Mapping\MappingException::missingTargetEntity($fieldName); |
||
775 | } |
||
776 | |||
777 | $assocMetadata = new Mapping\ManyToOneAssociationMetadata($fieldName); |
||
778 | $targetEntity = $classMetadata->fullyQualifiedClassName($manyToOneAnnot->targetEntity); |
||
779 | |||
780 | $assocMetadata->setSourceEntity($className); |
||
781 | $assocMetadata->setTargetEntity($targetEntity); |
||
782 | $assocMetadata->setCascade($this->getCascade($className, $fieldName, $manyToOneAnnot->cascade)); |
||
783 | $assocMetadata->setFetchMode($this->getFetchMode($className, $manyToOneAnnot->fetch)); |
||
784 | |||
785 | if (! empty($manyToOneAnnot->inversedBy)) { |
||
786 | $assocMetadata->setInversedBy($manyToOneAnnot->inversedBy); |
||
787 | } |
||
788 | |||
789 | // Check for Id |
||
790 | if (isset($propertyAnnotations[Annotation\Id::class])) { |
||
791 | $assocMetadata->setPrimaryKey(true); |
||
792 | } |
||
793 | |||
794 | // Check for Cache |
||
795 | View Code Duplication | if (isset($propertyAnnotations[Annotation\Cache::class])) { |
|
796 | $cacheAnnot = $propertyAnnotations[Annotation\Cache::class]; |
||
797 | $cacheMetadata = $this->convertCacheAnnotationToCacheMetadata($cacheAnnot, $classMetadata, $fieldName); |
||
798 | |||
799 | $assocMetadata->setCache($cacheMetadata); |
||
800 | } |
||
801 | |||
802 | // Check for JoinColumn/JoinColumns annotations |
||
803 | View Code Duplication | switch (true) { |
|
804 | case isset($propertyAnnotations[Annotation\JoinColumn::class]): |
||
805 | $joinColumnAnnot = $propertyAnnotations[Annotation\JoinColumn::class]; |
||
806 | $joinColumn = $this->convertJoinColumnAnnotationToJoinColumnMetadata( |
||
807 | $reflectionProperty, |
||
808 | $joinColumnAnnot, |
||
809 | $classMetadata |
||
810 | ); |
||
811 | |||
812 | $assocMetadata->addJoinColumn($joinColumn); |
||
813 | |||
814 | break; |
||
815 | |||
816 | case isset($propertyAnnotations[Annotation\JoinColumns::class]): |
||
817 | $joinColumnsAnnot = $propertyAnnotations[Annotation\JoinColumns::class]; |
||
818 | |||
819 | foreach ($joinColumnsAnnot->value as $joinColumnAnnot) { |
||
820 | $joinColumn = $this->convertJoinColumnAnnotationToJoinColumnMetadata( |
||
821 | $reflectionProperty, |
||
822 | $joinColumnAnnot, |
||
823 | $classMetadata |
||
824 | ); |
||
825 | |||
826 | $assocMetadata->addJoinColumn($joinColumn); |
||
827 | } |
||
828 | |||
829 | break; |
||
830 | } |
||
831 | |||
832 | return $assocMetadata; |
||
833 | } |
||
834 | |||
835 | /** |
||
836 | * @param \ReflectionProperty $reflectionProperty |
||
837 | * @param array $propertyAnnotations |
||
838 | * @param Mapping\ClassMetadata $classMetadata |
||
839 | * |
||
840 | * @return Mapping\OneToManyAssociationMetadata |
||
841 | */ |
||
842 | private function convertReflectionPropertyToOneToManyAssociationMetadata( |
||
843 | \ReflectionProperty $reflectionProperty, |
||
844 | array $propertyAnnotations, |
||
845 | Mapping\ClassMetadata $classMetadata |
||
846 | ) |
||
847 | { |
||
848 | $className = $classMetadata->getClassName(); |
||
849 | $fieldName = $reflectionProperty->getName(); |
||
850 | $oneToManyAnnot = $propertyAnnotations[Annotation\OneToMany::class]; |
||
851 | |||
852 | if ($oneToManyAnnot->targetEntity === null) { |
||
853 | throw Mapping\MappingException::missingTargetEntity($fieldName); |
||
854 | } |
||
855 | |||
856 | $assocMetadata = new Mapping\OneToManyAssociationMetadata($fieldName); |
||
857 | $targetEntity = $classMetadata->fullyQualifiedClassName($oneToManyAnnot->targetEntity); |
||
858 | |||
859 | $assocMetadata->setSourceEntity($className); |
||
860 | $assocMetadata->setTargetEntity($targetEntity); |
||
861 | $assocMetadata->setCascade($this->getCascade($className, $fieldName, $oneToManyAnnot->cascade)); |
||
862 | $assocMetadata->setOrphanRemoval($oneToManyAnnot->orphanRemoval); |
||
863 | $assocMetadata->setFetchMode($this->getFetchMode($className, $oneToManyAnnot->fetch)); |
||
864 | |||
865 | if (! empty($oneToManyAnnot->mappedBy)) { |
||
866 | $assocMetadata->setMappedBy($oneToManyAnnot->mappedBy); |
||
867 | } |
||
868 | |||
869 | if (! empty($oneToManyAnnot->indexBy)) { |
||
870 | $assocMetadata->setIndexedBy($oneToManyAnnot->indexBy); |
||
871 | } |
||
872 | |||
873 | // Check for OrderBy |
||
874 | View Code Duplication | if (isset($propertyAnnotations[Annotation\OrderBy::class])) { |
|
875 | $orderByAnnot = $propertyAnnotations[Annotation\OrderBy::class]; |
||
876 | |||
877 | $assocMetadata->setOrderBy($orderByAnnot->value); |
||
878 | } |
||
879 | |||
880 | // Check for Id |
||
881 | if (isset($propertyAnnotations[Annotation\Id::class])) { |
||
882 | $assocMetadata->setPrimaryKey(true); |
||
883 | } |
||
884 | |||
885 | // Check for Cache |
||
886 | View Code Duplication | if (isset($propertyAnnotations[Annotation\Cache::class])) { |
|
887 | $cacheAnnot = $propertyAnnotations[Annotation\Cache::class]; |
||
888 | $cacheMetadata = $this->convertCacheAnnotationToCacheMetadata($cacheAnnot, $classMetadata, $fieldName); |
||
889 | |||
890 | $assocMetadata->setCache($cacheMetadata); |
||
891 | } |
||
892 | |||
893 | return $assocMetadata; |
||
894 | } |
||
895 | |||
896 | /** |
||
897 | * @param \ReflectionProperty $reflectionProperty |
||
898 | * @param array $propertyAnnotations |
||
899 | * @param Mapping\ClassMetadata $classMetadata |
||
900 | * |
||
901 | * @return Mapping\ManyToManyAssociationMetadata |
||
902 | */ |
||
903 | private function convertReflectionPropertyToManyToManyAssociationMetadata( |
||
904 | \ReflectionProperty $reflectionProperty, |
||
905 | array $propertyAnnotations, |
||
906 | Mapping\ClassMetadata $classMetadata |
||
907 | ) |
||
908 | { |
||
909 | $className = $classMetadata->getClassName(); |
||
910 | $fieldName = $reflectionProperty->getName(); |
||
911 | $manyToManyAnnot = $propertyAnnotations[Annotation\ManyToMany::class]; |
||
912 | |||
913 | if ($manyToManyAnnot->targetEntity === null) { |
||
914 | throw Mapping\MappingException::missingTargetEntity($fieldName); |
||
915 | } |
||
916 | |||
917 | $assocMetadata = new Mapping\ManyToManyAssociationMetadata($fieldName); |
||
918 | $targetEntity = $classMetadata->fullyQualifiedClassName($manyToManyAnnot->targetEntity); |
||
919 | |||
920 | $assocMetadata->setSourceEntity($className); |
||
921 | $assocMetadata->setTargetEntity($targetEntity); |
||
922 | $assocMetadata->setCascade($this->getCascade($className, $fieldName, $manyToManyAnnot->cascade)); |
||
923 | $assocMetadata->setOrphanRemoval($manyToManyAnnot->orphanRemoval); |
||
924 | $assocMetadata->setFetchMode($this->getFetchMode($className, $manyToManyAnnot->fetch)); |
||
925 | |||
926 | if (! empty($manyToManyAnnot->mappedBy)) { |
||
927 | $assocMetadata->setMappedBy($manyToManyAnnot->mappedBy); |
||
928 | } |
||
929 | |||
930 | if (! empty($manyToManyAnnot->inversedBy)) { |
||
931 | $assocMetadata->setInversedBy($manyToManyAnnot->inversedBy); |
||
932 | } |
||
933 | |||
934 | if (! empty($manyToManyAnnot->indexBy)) { |
||
935 | $assocMetadata->setIndexedBy($manyToManyAnnot->indexBy); |
||
936 | } |
||
937 | |||
938 | // Check for JoinTable |
||
939 | if (isset($propertyAnnotations[Annotation\JoinTable::class])) { |
||
940 | $joinTableAnnot = $propertyAnnotations[Annotation\JoinTable::class]; |
||
941 | $joinTableMetadata = $this->convertJoinTableAnnotationToJoinTableMetadata( |
||
942 | $reflectionProperty, |
||
943 | $joinTableAnnot, |
||
944 | $classMetadata |
||
945 | ); |
||
946 | |||
947 | $assocMetadata->setJoinTable($joinTableMetadata); |
||
948 | } |
||
949 | |||
950 | // Check for OrderBy |
||
951 | View Code Duplication | if (isset($propertyAnnotations[Annotation\OrderBy::class])) { |
|
952 | $orderByAnnot = $propertyAnnotations[Annotation\OrderBy::class]; |
||
953 | |||
954 | $assocMetadata->setOrderBy($orderByAnnot->value); |
||
955 | } |
||
956 | |||
957 | // Check for Id |
||
958 | if (isset($propertyAnnotations[Annotation\Id::class])) { |
||
959 | $assocMetadata->setPrimaryKey(true); |
||
960 | } |
||
961 | |||
962 | // Check for Cache |
||
963 | View Code Duplication | if (isset($propertyAnnotations[Annotation\Cache::class])) { |
|
964 | $cacheAnnot = $propertyAnnotations[Annotation\Cache::class]; |
||
965 | $cacheMetadata = $this->convertCacheAnnotationToCacheMetadata($cacheAnnot, $classMetadata, $fieldName); |
||
966 | |||
967 | $assocMetadata->setCache($cacheMetadata); |
||
968 | } |
||
969 | |||
970 | return $assocMetadata; |
||
971 | } |
||
972 | |||
973 | /** |
||
974 | * Parse the given JoinTable as JoinTableMetadata |
||
975 | * |
||
976 | * @param \ReflectionProperty $reflectionProperty |
||
977 | * @param Annotation\JoinTable $joinTableAnnot |
||
978 | * @param Mapping\ClassMetadata $classMetadata |
||
979 | * |
||
980 | * @return Mapping\JoinTableMetadata |
||
981 | */ |
||
982 | private function convertJoinTableAnnotationToJoinTableMetadata( |
||
983 | \ReflectionProperty $reflectionProperty, |
||
984 | Annotation\JoinTable $joinTableAnnot, |
||
985 | Mapping\ClassMetadata $classMetadata |
||
986 | ) |
||
987 | { |
||
988 | $joinTable = new Mapping\JoinTableMetadata(); |
||
989 | |||
990 | if (! empty($joinTableAnnot->name)) { |
||
991 | $joinTable->setName($joinTableAnnot->name); |
||
992 | } |
||
993 | |||
994 | if (! empty($joinTableAnnot->schema)) { |
||
995 | $joinTable->setSchema($joinTableAnnot->schema); |
||
996 | } |
||
997 | |||
998 | foreach ($joinTableAnnot->joinColumns as $joinColumnAnnot) { |
||
999 | $joinColumn = $this->convertJoinColumnAnnotationToJoinColumnMetadata( |
||
1000 | $reflectionProperty, |
||
1001 | $joinColumnAnnot, |
||
1002 | $classMetadata |
||
1003 | ); |
||
1004 | |||
1005 | $joinTable->addJoinColumn($joinColumn); |
||
1006 | } |
||
1007 | |||
1008 | foreach ($joinTableAnnot->inverseJoinColumns as $joinColumnAnnot) { |
||
1009 | $joinColumn = $this->convertJoinColumnAnnotationToJoinColumnMetadata( |
||
1010 | $reflectionProperty, |
||
1011 | $joinColumnAnnot, |
||
1012 | $classMetadata |
||
1013 | ); |
||
1014 | |||
1015 | $joinTable->addInverseJoinColumn($joinColumn); |
||
1016 | } |
||
1017 | |||
1018 | return $joinTable; |
||
1019 | } |
||
1020 | |||
1021 | /** |
||
1022 | * Parse the given JoinColumn as JoinColumnMetadata |
||
1023 | * |
||
1024 | * @param Annotation\JoinColumn $joinColumnAnnot |
||
1025 | * |
||
1026 | * @return Mapping\JoinColumnMetadata |
||
1027 | */ |
||
1028 | private function convertJoinColumnAnnotationToJoinColumnMetadata( |
||
1029 | \ReflectionProperty $reflectionProperty, |
||
1030 | Annotation\JoinColumn $joinColumnAnnot, |
||
1031 | Mapping\ClassMetadata $classMetadata |
||
1032 | ) |
||
1033 | { |
||
1034 | $fieldName = $reflectionProperty->getName(); |
||
1035 | $joinColumn = new Mapping\JoinColumnMetadata(); |
||
1036 | $columnName = empty($joinColumnAnnot->name) |
||
1037 | ? $this->namingStrategy->propertyToColumnName($fieldName, $classMetadata->getClassName()) |
||
1038 | : $joinColumnAnnot->name |
||
1039 | ; |
||
1040 | $referencedColumnName = empty($joinColumnAnnot->referencedColumnName) |
||
1041 | ? $this->namingStrategy->referenceColumnName() |
||
1042 | : $joinColumnAnnot->referencedColumnName |
||
1043 | ; |
||
1044 | |||
1045 | $joinColumn->setColumnName($columnName); |
||
1046 | $joinColumn->setReferencedColumnName($referencedColumnName); |
||
1047 | $joinColumn->setNullable($joinColumnAnnot->nullable); |
||
1048 | $joinColumn->setUnique($joinColumnAnnot->unique); |
||
1049 | |||
1050 | if (! empty($joinColumnAnnot->fieldName)) { |
||
1051 | $joinColumn->setAliasedName($joinColumnAnnot->fieldName); |
||
1052 | } |
||
1053 | |||
1054 | if (! empty($joinColumnAnnot->columnDefinition)) { |
||
1055 | $joinColumn->setColumnDefinition($joinColumnAnnot->columnDefinition); |
||
1056 | } |
||
1057 | |||
1058 | if ($joinColumnAnnot->onDelete) { |
||
1059 | $joinColumn->setOnDelete(strtoupper($joinColumnAnnot->onDelete)); |
||
1060 | } |
||
1061 | |||
1062 | return $joinColumn; |
||
1063 | } |
||
1064 | |||
1065 | /** |
||
1066 | * Parses the given method. |
||
1067 | * |
||
1068 | * @param \ReflectionMethod $method |
||
1069 | * |
||
1070 | * @return array |
||
1071 | */ |
||
1072 | private function getMethodCallbacks(\ReflectionMethod $method) |
||
1073 | { |
||
1074 | $annotations = $this->getMethodAnnotations($method); |
||
1075 | $events = [ |
||
1076 | Events::prePersist => Annotation\PrePersist::class, |
||
1077 | Events::postPersist => Annotation\PostPersist::class, |
||
1078 | Events::preUpdate => Annotation\PreUpdate::class, |
||
1079 | Events::postUpdate => Annotation\PostUpdate::class, |
||
1080 | Events::preRemove => Annotation\PreRemove::class, |
||
1081 | Events::postRemove => Annotation\PostRemove::class, |
||
1082 | Events::postLoad => Annotation\PostLoad::class, |
||
1083 | Events::preFlush => Annotation\PreFlush::class, |
||
1084 | ]; |
||
1085 | |||
1086 | // Check for callbacks |
||
1087 | $callbacks = []; |
||
1088 | |||
1089 | foreach ($events as $eventName => $annotationClassName) { |
||
1090 | if (isset($annotations[$annotationClassName]) || $method->getName() === $eventName) { |
||
1091 | $callbacks[] = $eventName; |
||
1092 | } |
||
1093 | } |
||
1094 | |||
1095 | return $callbacks; |
||
1096 | } |
||
1097 | |||
1098 | /** |
||
1099 | * Attempts to resolve the fetch mode. |
||
1100 | * |
||
1101 | * @param string $className The class name. |
||
1102 | * @param string $fetchMode The fetch mode. |
||
1103 | * |
||
1104 | * @return integer The fetch mode as defined in ClassMetadata. |
||
1105 | * |
||
1106 | * @throws Mapping\MappingException If the fetch mode is not valid. |
||
1107 | */ |
||
1108 | private function getFetchMode($className, $fetchMode) |
||
1109 | { |
||
1110 | $fetchModeConstant = sprintf('%s::%s', Mapping\FetchMode::class, $fetchMode); |
||
1111 | |||
1112 | if (! defined($fetchModeConstant)) { |
||
1113 | throw Mapping\MappingException::invalidFetchMode($className, $fetchMode); |
||
1114 | } |
||
1115 | |||
1116 | return constant($fetchModeConstant); |
||
1117 | } |
||
1118 | |||
1119 | /** |
||
1120 | * @param string $className The class name. |
||
1121 | * @param string $fieldName The field name. |
||
1122 | * @param array $originalCascades The original unprocessed field cascades. |
||
1123 | * |
||
1124 | * @return array The processed field cascades. |
||
1125 | * |
||
1126 | * @throws Mapping\MappingException If a cascade option is not valid. |
||
1127 | */ |
||
1128 | private function getCascade(string $className, string $fieldName, array $originalCascades) |
||
1129 | { |
||
1130 | $cascadeTypes = ['remove', 'persist', 'refresh']; |
||
1131 | $cascades = array_map('strtolower', $originalCascades); |
||
1132 | |||
1133 | if (in_array('all', $cascades)) { |
||
1134 | $cascades = $cascadeTypes; |
||
1135 | } |
||
1136 | |||
1137 | if (count($cascades) !== count(array_intersect($cascades, $cascadeTypes))) { |
||
1138 | $diffCascades = array_diff($cascades, array_intersect($cascades, $cascadeTypes)); |
||
1139 | |||
1140 | throw Mapping\MappingException::invalidCascadeOption($diffCascades, $className, $fieldName); |
||
1141 | } |
||
1142 | |||
1143 | return $cascades; |
||
1144 | } |
||
1145 | |||
1146 | /** |
||
1147 | * @param \ReflectionClass $reflectionClass |
||
1148 | * |
||
1149 | * @return array |
||
1150 | */ |
||
1151 | View Code Duplication | private function getClassAnnotations(\ReflectionClass $reflectionClass) |
|
1152 | { |
||
1153 | $classAnnotations = $this->reader->getClassAnnotations($reflectionClass); |
||
1154 | |||
1155 | foreach ($classAnnotations as $key => $annot) { |
||
1156 | if (! is_numeric($key)) { |
||
1157 | continue; |
||
1158 | } |
||
1159 | |||
1160 | $classAnnotations[get_class($annot)] = $annot; |
||
1161 | } |
||
1162 | |||
1163 | return $classAnnotations; |
||
1164 | } |
||
1165 | |||
1166 | /** |
||
1167 | * @param \ReflectionProperty $reflectionProperty |
||
1168 | * |
||
1169 | * @return array |
||
1170 | */ |
||
1171 | View Code Duplication | private function getPropertyAnnotations(\ReflectionProperty $reflectionProperty) |
|
1184 | } |
||
1185 | |||
1186 | /** |
||
1187 | * @param \ReflectionMethod $reflectionMethod |
||
1188 | * |
||
1189 | * @return array |
||
1190 | */ |
||
1191 | View Code Duplication | private function getMethodAnnotations(\ReflectionMethod $reflectionMethod) |
|
1192 | { |
||
1193 | $methodAnnotations = $this->reader->getMethodAnnotations($reflectionMethod); |
||
1194 | |||
1195 | foreach ($methodAnnotations as $key => $annot) { |
||
1196 | if (! is_numeric($key)) { |
||
1197 | continue; |
||
1198 | } |
||
1199 | |||
1200 | $methodAnnotations[get_class($annot)] = $annot; |
||
1201 | } |
||
1202 | |||
1203 | return $methodAnnotations; |
||
1204 | } |
||
1205 | } |
||
1206 |
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.