| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | declare(strict_types=1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | namespace Cycle\Annotated; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | use Cycle\Annotated\Annotation\Column; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | use Cycle\Annotated\Annotation\Embeddable; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | use Cycle\Annotated\Annotation\Entity; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | use Cycle\Annotated\Annotation\ForeignKey; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | use Cycle\Annotated\Annotation\GeneratedValue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | use Cycle\Annotated\Annotation\Relation as RelationAnnotation; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | use Cycle\Annotated\Exception\AnnotationException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | use Cycle\Annotated\Exception\AnnotationRequiredArgumentsException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | use Cycle\Annotated\Exception\AnnotationWrongTypeArgumentException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | use Cycle\Annotated\Utils\EntityUtils; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | use Cycle\ORM\Schema\GeneratedField; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  | use Cycle\Schema\Definition\Entity as EntitySchema; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  | use Cycle\Schema\Definition\ForeignKey as ForeignKeySchema; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | use Cycle\Schema\Definition\Field; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | use Cycle\Schema\Definition\Relation; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  | use Cycle\Schema\Generator\SyncTables; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  | use Cycle\Schema\SchemaModifierInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  | use Doctrine\Common\Annotations\Reader as DoctrineReader; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  | use Doctrine\Inflector\Inflector; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  | use Doctrine\Inflector\Rules\English\InflectorFactory; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  | use Spiral\Attributes\ReaderInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  | final class Configurator | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |     private ReaderInterface $reader; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 | 1056 |  |     private Inflector $inflector; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |     private EntityUtils $utils; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |     public function __construct( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 | 1056 |  |         DoctrineReader|ReaderInterface $reader, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 | 1056 |  |         private int $tableNamingStrategy = Entities::TABLE_NAMING_PLURAL, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 | 1056 |  |     ) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 | 1056 |  |         $this->reader = ReaderFactory::create($reader); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 40 |  |  |         $this->inflector = (new InflectorFactory())->build(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 41 | 1056 |  |         $this->utils = new EntityUtils($this->reader); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 42 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 43 | 1056 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 | 1056 |  |     public function initEntity(Entity $ann, \ReflectionClass $class): EntitySchema | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 | 1056 |  |         $e = new EntitySchema(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |         $e->setClass($class->getName()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 | 1056 |  |         $e->setRole($ann->getRole() ?? $this->inflector->camelize($class->getShortName())); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 | 1056 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 | 1056 |  |         // representing classes | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 | 1056 |  |         $e->setMapper($this->resolveName($ann->getMapper(), $class)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 | 1056 |  |         $e->setRepository($this->resolveName($ann->getRepository(), $class)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 | 1056 |  |         $e->setSource($this->resolveName($ann->getSource(), $class)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 | 1056 |  |         $e->setScope($this->resolveName($ann->getScope(), $class)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |         $e->setDatabase($ann->getDatabase()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |         $e->setTableName( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 | 1056 |  |             $ann->getTable() ?? $this->utils->tableName($e->getRole(), $this->tableNamingStrategy) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 | 1056 |  |         ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 | 496 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |         $typecast = $ann->getTypecast(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 | 1056 |  |         if (is_array($typecast)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |             $typecast = array_map(fn (string $value): string => $this->resolveName($value, $class), $typecast); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |         } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 | 1056 |  |             $typecast = $this->resolveName($typecast, $class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 | 1056 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |         $e->setTypecast($typecast); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |         if ($ann->isReadonlySchema()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 | 1056 |  |             $e->getOptions()->set(SyncTables::READONLY_SCHEMA, true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 | 72 |  |         return $e; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 | 72 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 | 72 |  |     public function initEmbedding(Embeddable $emb, \ReflectionClass $class): EntitySchema | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 | 72 |  |         $e = new EntitySchema(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |         $e->setClass($class->getName()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 | 72 |  |         $e->setRole($emb->getRole() ?? $this->inflector->camelize($class->getShortName())); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 | 72 |  |         // representing classes | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |         $e->setMapper($this->resolveName($emb->getMapper(), $class)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 | 1056 |  |         return $e; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 | 1056 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |     public function initFields(EntitySchema $entity, \ReflectionClass $class, string $columnPrefix = ''): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 | 1056 |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 | 24 |  |         foreach ($class->getProperties() as $property) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |             try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 | 24 |  |                 $column = $this->reader->firstPropertyMetadata($property, Column::class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 | 24 |  |             } catch (\Exception $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |                 throw new AnnotationException($e->getMessage(), $e->getCode(), $e); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |             } catch (\ArgumentCountError $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |                 throw AnnotationRequiredArgumentsException::createFor($property, Column::class, $e); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |             } catch (\TypeError $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 | 1032 |  |                 throw AnnotationWrongTypeArgumentException::createFor($property, $e); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 | 976 |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |             if ($column === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 | 1008 |  |                 continue; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 | 1008 |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 | 1008 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |             $field = $this->initField($property->getName(), $column, $class, $columnPrefix); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 | 1032 |  |             $field->setEntityClass($property->getDeclaringClass()->getName()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |             $entity->getFields()->set($property->getName(), $field); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 | 1032 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 | 1032 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |     public function initRelations(EntitySchema $entity, \ReflectionClass $class): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 | 1032 |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |         foreach ($class->getProperties() as $property) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |             $metadata = $this->getPropertyMetadata($property, RelationAnnotation\RelationInterface::class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |             foreach ($metadata as $meta) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 | 1032 |  |                 assert($meta instanceof RelationAnnotation\RelationInterface); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |                 if ($meta->getTarget() === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 | 808 |  |                     throw new AnnotationException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |                         "Relation target definition is required on `{$entity->getClass()}`.`{$property->getName()}`" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |                     ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |                 $relation = new Relation(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 | 808 |  |                 $relation->setTarget($this->resolveName($meta->getTarget(), $class)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 | 808 |  |                 $relation->setType($meta->getType()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 | 808 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |                 $inverse = $meta->getInverse() ?? $this->reader->firstPropertyMetadata( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 | 808 |  |                     $property, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |                     RelationAnnotation\Inverse::class | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 | 768 |  |                 ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |                 if ($inverse !== null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 | 808 |  |                     $relation->setInverse( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 | 144 |  |                         $inverse->getName(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 | 144 |  |                         $inverse->getType(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 | 144 |  |                         $inverse->getLoadMethod() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 | 144 |  |                     ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 |  |  |                 if ($meta instanceof RelationAnnotation\Embedded && $meta->getPrefix() === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 | 808 |  |                     /** @var Embeddable|null $embeddable */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |                     $embeddable = $this->reader->firstClassMetadata( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 | 72 |  |                         new \ReflectionClass($relation->getTarget()), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 | 72 |  |                         Embeddable::class | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 | 72 |  |                     ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 |  |  |                     $meta->setPrefix($embeddable->getColumnPrefix()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 | 72 |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 151 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 152 |  |  |                 foreach ($meta->getOptions() as $option => $value) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 153 | 808 |  |                     $value = match ($option) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 154 | 808 |  |                         'collection' => $this->resolveName($value, $class), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 155 | 568 |  |                         'though', 'through' => $this->resolveName($value, $class), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 156 | 284 |  |                         default => $value | 
            
                                                                                                            
                            
            
                                    
            
            
                | 157 | 404 |  |                     }; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 158 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 159 |  |  |                     $relation->getOptions()->set($option, $value); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 160 | 808 |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 161 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 162 |  |  |                 // need relation definition | 
            
                                                                                                            
                            
            
                                    
            
            
                | 163 |  |  |                 $entity->getRelations()->set($property->getName(), $relation); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 164 | 808 |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 165 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 166 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 167 | 1032 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 168 |  |  |     public function initModifiers(EntitySchema $entity, \ReflectionClass $class): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 169 | 1032 |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 170 |  |  |         $metadata = $this->getClassMetadata($class, SchemaModifierInterface::class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 171 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 172 | 1032 |  |         foreach ($metadata as $meta) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 173 |  |  |             assert($meta instanceof SchemaModifierInterface); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 174 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 175 |  |  |             // need relation definition | 
            
                                                                                                            
                            
            
                                    
            
            
                | 176 |  |  |             $entity->addSchemaModifier($meta); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 177 | 1032 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 178 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 179 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 180 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 181 | 24 |  |      * @param Column[] $columns | 
            
                                                                                                            
                            
            
                                    
            
            
                | 182 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 183 | 1032 |  |     public function initColumns(EntitySchema $entity, array $columns, \ReflectionClass $class): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 184 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 185 |  |  |         foreach ($columns as $key => $column) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 186 |  |  |             $isNumericKey = is_numeric($key); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 187 |  |  |             $propertyName = $column->getProperty(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 188 | 1032 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 189 |  |  |             if (!$isNumericKey && $propertyName !== null && $key !== $propertyName) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 190 | 1032 |  |                 throw new AnnotationException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 191 | 472 |  |                     "Can not use name \"{$key}\" for Column of the `{$entity->getRole()}` role, because the " | 
            
                                                                                                            
                            
            
                                    
            
            
                | 192 | 472 |  |                     . "\"property\" field of the metadata class has already been set to \"{$propertyName}\"." | 
            
                                                                                                            
                            
            
                                    
            
            
                | 193 |  |  |                 ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 194 | 472 |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 195 | 6 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 196 | 6 |  |             $propertyName = $propertyName ?? ($isNumericKey ? null : $key); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 197 | 6 |  |             $columnName = $column->getColumn() ?? $propertyName; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 198 |  |  |             $propertyName = $propertyName ?? $columnName; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 199 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 200 |  |  |             if ($columnName === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 201 | 466 |  |                 throw new AnnotationException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 202 | 466 |  |                     "Column name definition is required on `{$entity->getClass()}`" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 203 | 466 |  |                 ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 204 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 205 | 466 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 206 |  |  |             if ($column->getType() === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 207 |  |  |                 throw new AnnotationException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 208 |  |  |                     "Column type definition is required on `{$entity->getClass()}`.`{$columnName}`" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 209 |  |  |                 ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 210 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 211 | 466 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 212 |  |  |             $field = $this->initField($columnName, $column, $class, ''); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 213 |  |  |             $field->setEntityClass($entity->getClass()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 214 |  |  |             $entity->getFields()->set($propertyName, $field); | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 215 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 216 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 217 | 466 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 218 | 466 |  |     public function initField(string $name, Column $column, \ReflectionClass $class, string $columnPrefix): Field | 
            
                                                                                                            
                            
            
                                    
            
            
                | 219 | 466 |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 220 |  |  |         $field = new Field(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 221 | 1032 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 222 |  |  |         $field->setType($column->getType()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 223 | 1032 |  |         $field->setColumn($columnPrefix . ($column->getColumn() ?? $this->inflector->tableize($name))); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 224 |  |  |         $field->setPrimary($column->isPrimary()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 225 | 1032 |  |         if ($this->isOnInsertGeneratedField($field)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 226 |  |  |             $field->setGenerated(GeneratedField::ON_INSERT); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 227 | 1032 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 228 | 1032 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 229 | 1032 |  |         $field->setTypecast($this->resolveTypecast($column->getTypecast(), $class)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 230 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 231 | 1032 |  |         if ($column->isNullable()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 232 |  |  |             $field->getOptions()->set(\Cycle\Schema\Table\Column::OPT_NULLABLE, true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 233 | 1032 |  |             $field->getOptions()->set(\Cycle\Schema\Table\Column::OPT_DEFAULT, null); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 234 | 48 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 235 | 48 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 236 |  |  |         if ($column->hasDefault()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 237 |  |  |             $field->getOptions()->set(\Cycle\Schema\Table\Column::OPT_DEFAULT, $column->getDefault()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 238 | 1032 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 239 | 496 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 240 |  |  |         if ($column->castDefault()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 241 |  |  |             $field->getOptions()->set(\Cycle\Schema\Table\Column::OPT_CAST_DEFAULT, true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 242 | 1032 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 243 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 244 |  |  |         if ($column->isReadonlySchema()) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 245 |  |  |             $field->getAttributes()->set('readonlySchema', true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 246 | 1032 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 247 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 248 |  |  |         foreach ($column->getAttributes() as $k => $v) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 249 |  |  |             $field->getAttributes()->set($k, $v); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 250 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 251 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 252 | 1056 |  |         return $field; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 253 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 254 | 1056 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 255 | 1056 |  |     public function initForeignKeys(Entity $ann, EntitySchema $entity, \ReflectionClass $class): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 256 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 257 |  |  |         $foreignKeys = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 258 | 680 |  |         foreach ($ann->getForeignKeys() as $foreignKey) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 259 | 680 |  |             $foreignKeys[] = $foreignKey; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 260 | 680 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 261 | 680 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 262 |  |  |         foreach ($this->getClassMetadata($class, ForeignKey::class) as $foreignKey) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 263 |  |  |             $foreignKeys[] = $foreignKey; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 264 | 680 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 265 | 656 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 266 |  |  |         foreach ($class->getProperties() as $property) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 267 |  |  |             foreach ($this->getPropertyMetadata($property, ForeignKey::class) as $foreignKey) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 268 | 520 |  |                 if ($foreignKey->innerKey === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 269 |  |  |                     $foreignKey->innerKey = [$property->getName()]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 270 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 271 | 1032 |  |                 $foreignKeys[] = $foreignKey; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 272 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 273 | 1032 |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 274 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 275 |  |  |         foreach ($foreignKeys as $foreignKey) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 276 |  |  |             if ($foreignKey->innerKey === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 277 |  |  |                 throw new AnnotationException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 278 |  |  |                     "Inner column definition for the foreign key is required on `{$entity->getClass()}`" | 
            
                                                                                                            
                            
            
                                    
            
            
                | 279 |  |  |                 ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 280 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 281 | 1032 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 282 |  |  |             $fk = new ForeignKeySchema(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 283 |  |  |             $fk->setTarget($foreignKey->target); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 284 |  |  |             $fk->setInnerColumns((array) $foreignKey->innerKey); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 285 |  |  |             $fk->setOuterColumns((array) $foreignKey->outerKey); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 286 |  |  |             $fk->createIndex($foreignKey->indexCreate); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 287 |  |  |             $fk->setAction($foreignKey->action); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 288 | 1032 |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 289 |  |  |             $entity->getForeignKeys()->set($fk); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 290 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 291 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 292 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 293 |  |  |     public function initGeneratedFields(EntitySchema $entity, \ReflectionClass $class): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 294 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 295 |  |  |         foreach ($class->getProperties() as $property) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 296 |  |  |             try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 297 |  |  |                 $generated = $this->reader->firstPropertyMetadata($property, GeneratedValue::class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 298 |  |  |                 if ($generated !== null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 299 |  |  |                     $entity->getFields()->get($property->getName())->setGenerated($generated->getFlags()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 300 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 301 |  |  |             } catch (\Throwable $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 302 |  |  |                 throw new AnnotationException($e->getMessage(), (int) $e->getCode(), $e); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 303 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 304 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 305 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 306 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 307 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 308 |  |  |      * Resolve class or role name relative to the current class. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 309 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 310 |  |  |     public function resolveName(?string $name, \ReflectionClass $class): ?string | 
            
                                                                                                            
                            
            
                                    
            
            
                | 311 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 312 |  |  |         if ($name === null || $this->exists($name)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 313 |  |  |             return $name; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 314 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 315 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 316 |  |  |         $resolved = \sprintf( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 317 |  |  |             '%s\\%s', | 
            
                                                                                                            
                            
            
                                    
            
            
                | 318 |  |  |             $class->getNamespaceName(), | 
            
                                                                                                            
                            
            
                                    
            
            
                | 319 |  |  |             \ltrim(\str_replace('/', '\\', $name), '\\') | 
            
                                                                                                            
                            
            
                                    
            
            
                | 320 |  |  |         ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 321 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 322 |  |  |         if ($this->exists($resolved)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 323 |  |  |             return \ltrim($resolved, '\\'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 324 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 325 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 326 |  |  |         return $name; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 327 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 328 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 329 |  |  |     private function exists(string $name): bool | 
            
                                                                                                            
                            
            
                                    
            
            
                | 330 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 331 |  |  |         return \class_exists($name, true) || \interface_exists($name, true); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 332 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 333 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 334 |  |  |     private function resolveTypecast(mixed $typecast, \ReflectionClass $class): mixed | 
            
                                                                                                            
                            
            
                                    
            
            
                | 335 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 336 |  |  |         if (\is_string($typecast) && \str_contains($typecast, '::')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 337 |  |  |             // short definition | 
            
                                                                                                            
                            
            
                                    
            
            
                | 338 |  |  |             $typecast = \explode('::', $typecast); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 339 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 340 |  |  |             // resolve class name | 
            
                                                                                                            
                            
            
                                    
            
            
                | 341 |  |  |             $typecast[0] = $this->resolveName($typecast[0], $class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 342 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 343 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 344 |  |  |         if (\is_string($typecast)) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 345 |  |  |             $typecast = $this->resolveName($typecast, $class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 346 |  |  |             if (\class_exists($typecast) && \method_exists($typecast, 'typecast')) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 347 |  |  |                 $typecast = [$typecast, 'typecast']; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 348 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 349 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 350 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 351 |  |  |         return $typecast; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 352 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 353 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 354 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 355 |  |  |      * @template T | 
            
                                                                                                            
                            
            
                                    
            
            
                | 356 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 357 |  |  |      * @param class-string<T>|null | 
            
                                                                                                            
                            
            
                                    
            
            
                | 358 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 359 |  |  |      * @throws AnnotationException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 360 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 361 |  |  |      * @return iterable<T> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 362 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 363 |  |  |     private function getClassMetadata(\ReflectionClass $class, string $name): iterable | 
            
                                                                                                            
                            
            
                                    
            
            
                | 364 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 365 |  |  |         try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 366 |  |  |             return $this->reader->getClassMetadata($class, $name); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 367 |  |  |         } catch (\Exception $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 368 |  |  |             throw new AnnotationException($e->getMessage(), $e->getCode(), $e); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 369 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 370 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 371 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 372 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 373 |  |  |      * @template T | 
            
                                                                                                            
                            
            
                                    
            
            
                | 374 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 375 |  |  |      * @param class-string<T>|null $name | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 376 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 377 |  |  |      * @throws AnnotationException | 
            
                                                                                                            
                            
            
                                    
            
            
                | 378 |  |  |      * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 379 |  |  |      * @return iterable<T> | 
            
                                                                                                            
                            
            
                                    
            
            
                | 380 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 381 |  |  |     private function getPropertyMetadata(\ReflectionProperty $property, string $name): iterable | 
            
                                                                                                            
                            
            
                                    
            
            
                | 382 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 383 |  |  |         try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 384 |  |  |             return $this->reader->getPropertyMetadata($property, $name); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 385 |  |  |         } catch (\Exception $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 386 |  |  |             throw new AnnotationException($e->getMessage(), $e->getCode(), $e); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 387 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 388 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 389 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 390 |  |  |     private function isOnInsertGeneratedField(Field $field): bool | 
            
                                                                        
                            
            
                                    
            
            
                | 391 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 392 |  |  |         return match ($field->getType()) { | 
            
                                                                        
                            
            
                                    
            
            
                | 393 |  |  |             'serial', 'bigserial', 'smallserial' => true, | 
            
                                                                        
                            
            
                                    
            
            
                | 394 |  |  |             default => $field->isPrimary() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 395 |  |  |         }; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 396 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 397 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 398 |  |  |  |