| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | declare(strict_types=1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | namespace Cycle\Annotated; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | use Cycle\Annotated\Annotation\Table; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | use Cycle\Annotated\Exception\AnnotationException; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  | use Cycle\Schema\Definition\Entity; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | use Cycle\Schema\GeneratorInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  | use Cycle\Schema\Registry; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  | use Doctrine\Common\Annotations\Reader as DoctrineReader; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  | use Spiral\Attributes\ReaderInterface; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  | use Cycle\Database\Schema\AbstractIndex; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  | use Cycle\Database\Schema\AbstractTable; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |  * Copy index definitions from Mapper/Repository to Entity. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  | final class MergeIndexes implements GeneratorInterface | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |     private ReaderInterface $reader; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 | 790 |  |     public function __construct(DoctrineReader|ReaderInterface $reader = null) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 | 790 |  |         $this->reader = ReaderFactory::create($reader); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 | 790 |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 28 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 29 | 742 |  |     public function run(Registry $registry): Registry | 
            
                                                                        
                            
            
                                    
            
            
                | 30 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 31 | 742 |  |         foreach ($registry as $e) { | 
            
                                                                        
                            
            
                                    
            
            
                | 32 | 742 |  |             if ($e->getClass() === null || !$registry->hasTable($e)) { | 
            
                                                                        
                            
            
                                    
            
            
                | 33 | 72 |  |                 continue; | 
            
                                                                        
                            
            
                                    
            
            
                | 34 |  |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 35 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 36 | 742 |  |             $this->render($registry->getTableSchema($e), $e, $e->getClass()); | 
            
                                                                        
                            
            
                                    
            
            
                | 37 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 38 |  |  |             // copy table declarations from related classes | 
            
                                                                        
                            
            
                                    
            
            
                | 39 | 730 |  |             $this->render($registry->getTableSchema($e), $e, $e->getMapper()); | 
            
                                                                        
                            
            
                                    
            
            
                | 40 | 730 |  |             $this->render($registry->getTableSchema($e), $e, $e->getRepository()); | 
            
                                                                        
                            
            
                                    
            
            
                | 41 | 730 |  |             $this->render($registry->getTableSchema($e), $e, $e->getSource()); | 
            
                                                                        
                            
            
                                    
            
            
                | 42 | 730 |  |             $this->render($registry->getTableSchema($e), $e, $e->getScope()); | 
            
                                                                        
                            
            
                                    
            
            
                | 43 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 44 | 730 |  |             foreach ($registry->getChildren($e) as $child) { | 
            
                                                                        
                            
            
                                    
            
            
                | 45 | 434 |  |                 if (!$child->isChildOfSingleTableInheritance() && $registry->hasEntity($child->getRole())) { | 
            
                                                                        
                            
            
                                    
            
            
                | 46 | 144 |  |                     $tableSchema = $registry->getTableSchema($child); | 
            
                                                                        
                            
            
                                    
            
            
                | 47 |  |  |                 } else { | 
            
                                                                        
                            
            
                                    
            
            
                | 48 | 434 |  |                     $tableSchema = $registry->getTableSchema($e); | 
            
                                                                        
                            
            
                                    
            
            
                | 49 |  |  |                 } | 
            
                                                                        
                            
            
                                    
            
            
                | 50 | 434 |  |                 $this->render($tableSchema, $e, $child->getClass()); | 
            
                                                                        
                            
            
                                    
            
            
                | 51 |  |  |             } | 
            
                                                                        
                            
            
                                    
            
            
                | 52 |  |  |         } | 
            
                                                                        
                            
            
                                    
            
            
                | 53 |  |  |  | 
            
                                                                        
                            
            
                                    
            
            
                | 54 | 730 |  |         return $registry; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |      * @param Table\Index[] $indexes | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 | 502 |  |     public function renderIndexes(AbstractTable $table, Entity $entity, array $indexes): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 | 502 |  |         foreach ($indexes as $index) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 | 502 |  |             if ($index->getColumns() === []) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 | 12 |  |                 throw new AnnotationException( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 | 12 |  |                     "Invalid index definition for `{$entity->getRole()}`. Column list can't be empty." | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |                 ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 | 490 |  |             $columns = $this->mapColumns($entity, $index->getColumns()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 | 490 |  |             if ($index instanceof Table\PrimaryKey) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 | 12 |  |                 $table->setPrimaryKeys($columns); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 | 12 |  |                 $entity->setPrimaryColumns($index->getColumns()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |             } else { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 | 478 |  |                 $indexSchema = $table->index($columns); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 | 478 |  |                 $indexSchema->unique($index->isUnique()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 | 478 |  |                 if ($index->getIndex() !== null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 | 266 |  |                     $indexSchema->setName($index->getIndex()); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 | 490 |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |      * @param class-string|null   $class | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 | 742 |  |     private function render(AbstractTable $table, Entity $entity, ?string $class): void | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 | 742 |  |         if ($class === null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 | 730 |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |         try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 | 742 |  |             $reflection = new \ReflectionClass($class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |         } catch (\ReflectionException $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |         try { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |             /** @var Table|null $tableMeta */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 | 742 |  |             $tableMeta = $this->reader->firstClassMetadata($reflection, Table::class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |             /** @var Table\PrimaryKey|null $primaryKey */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 | 742 |  |             $primaryKey = $tableMeta | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 | 74 |  |                 ? $tableMeta->getPrimary() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 | 716 |  |                 : $this->reader->firstClassMetadata($reflection, Table\PrimaryKey::class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |             /** @var Table\Index[] $indexMeta */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 | 742 |  |             $indexMeta = $this->reader->getClassMetadata($reflection, Table\Index::class); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |         } catch (\Exception $e) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |             throw new AnnotationException($e->getMessage(), $e->getCode(), $e); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 | 742 |  |         $indexes = $tableMeta === null ? [] : $tableMeta->getIndexes(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 | 742 |  |         if ($primaryKey !== null) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 | 24 |  |             $indexes[] = $primaryKey; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 | 742 |  |         foreach ($indexMeta as $index) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 | 436 |  |             $indexes[] = $index; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 | 742 |  |         if ($indexes === []) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 | 698 |  |             return; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 | 502 |  |         $this->renderIndexes($table, $entity, $indexes); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 | 490 |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |      * @return string[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 | 490 |  |     protected function mapColumns(Entity $entity, array $columns): array | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 136 | 490 |  |         $result = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 137 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 138 | 490 |  |         foreach ($columns as $expression) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 139 | 490 |  |             [$column, $order] = AbstractIndex::parseColumn($expression); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 140 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 141 | 490 |  |             $mappedName = $entity->getFields()->has($column) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 142 | 490 |  |                 ? $entity->getFields()->get($column)->getColumn() | 
            
                                                                                                            
                            
            
                                    
            
            
                | 143 | 398 |  |                 : $column; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 144 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 145 |  |  |             // Re-construct `column ORDER` with mapped column name | 
            
                                                                                                            
                            
            
                                    
            
            
                | 146 | 490 |  |             $result[] = $order ? "$mappedName $order" : $mappedName; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 147 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 148 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 149 | 490 |  |         return $result; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 150 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 151 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 152 |  |  |  |