| Total Complexity | 51 |
| Total Lines | 479 |
| Duplicated Lines | 0 % |
| Changes | 0 | ||
Complex classes like Renderer often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use Renderer, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 23 | final class Renderer implements RendererInterface |
||
| 24 | { |
||
| 25 | use SerializerTrait; |
||
| 26 | |||
| 27 | /** |
||
| 28 | * Comparator alteration states. |
||
| 29 | */ |
||
| 30 | public const NEW_STATE = 0; |
||
| 31 | public const ORIGINAL_STATE = 1; |
||
| 32 | |||
| 33 | /** |
||
| 34 | * {@inheritdoc} |
||
| 35 | */ |
||
| 36 | public function createTable(Source $source, AbstractTable $table): void |
||
| 37 | { |
||
| 38 | $this->render( |
||
| 39 | $source, |
||
| 40 | '$this->table(%s)', |
||
| 41 | $table |
||
| 42 | ); |
||
| 43 | $comparator = $table->getComparator(); |
||
| 44 | |||
| 45 | $this->declareColumns($source, $comparator); |
||
| 46 | $this->declareIndexes($source, $comparator); |
||
| 47 | $this->declareForeignKeys($source, $comparator, $table->getPrefix()); |
||
| 48 | |||
| 49 | if (count($table->getPrimaryKeys())) { |
||
| 50 | $this->render( |
||
| 51 | $source, |
||
| 52 | ' ->setPrimaryKeys(%s)', |
||
| 53 | $table->getPrimaryKeys() |
||
| 54 | ); |
||
| 55 | } |
||
| 56 | |||
| 57 | //Finalization |
||
| 58 | $source->addLine(' ->create();'); |
||
| 59 | } |
||
| 60 | |||
| 61 | /** |
||
| 62 | * {@inheritdoc} |
||
| 63 | */ |
||
| 64 | public function updateTable(Source $source, AbstractTable $table): void |
||
| 65 | { |
||
| 66 | $this->render( |
||
| 67 | $source, |
||
| 68 | '$this->table(%s)', |
||
| 69 | $table |
||
| 70 | ); |
||
| 71 | $comparator = $table->getComparator(); |
||
| 72 | |||
| 73 | if ($comparator->isPrimaryChanged()) { |
||
| 74 | $this->render( |
||
| 75 | $source, |
||
| 76 | ' ->setPrimaryKeys(%s)', |
||
| 77 | $table->getPrimaryKeys() |
||
| 78 | ); |
||
| 79 | } |
||
| 80 | |||
| 81 | $this->declareColumns($source, $comparator); |
||
| 82 | $this->declareIndexes($source, $comparator); |
||
| 83 | $this->declareForeignKeys($source, $comparator, $table->getPrefix()); |
||
| 84 | |||
| 85 | //Finalization |
||
| 86 | $source->addLine(' ->update();'); |
||
| 87 | } |
||
| 88 | |||
| 89 | /** |
||
| 90 | * {@inheritdoc} |
||
| 91 | */ |
||
| 92 | public function revertTable(Source $source, AbstractTable $table): void |
||
| 93 | { |
||
| 94 | //Get table blueprint |
||
| 95 | $this->render( |
||
| 96 | $source, |
||
| 97 | '$this->table(%s)', |
||
| 98 | $table |
||
| 99 | ); |
||
| 100 | $comparator = $table->getComparator(); |
||
| 101 | |||
| 102 | $this->revertForeignKeys($source, $comparator, $table->getPrefix()); |
||
| 103 | $this->revertIndexes($source, $comparator); |
||
| 104 | $this->revertColumns($source, $comparator); |
||
| 105 | |||
| 106 | //Finalization |
||
| 107 | $source->addLine(' ->update();'); |
||
| 108 | } |
||
| 109 | |||
| 110 | /** |
||
| 111 | * {@inheritdoc} |
||
| 112 | */ |
||
| 113 | public function dropTable(Source $source, AbstractTable $table): void |
||
| 114 | { |
||
| 115 | $this->render( |
||
| 116 | $source, |
||
| 117 | '$this->table(%s)->drop();', |
||
| 118 | $table |
||
| 119 | ); |
||
| 120 | } |
||
| 121 | |||
| 122 | /** |
||
| 123 | * @param Source $source |
||
| 124 | * @param Comparator $comparator |
||
| 125 | */ |
||
| 126 | private function declareColumns(Source $source, Comparator $comparator): void |
||
| 127 | { |
||
| 128 | foreach ($comparator->addedColumns() as $column) { |
||
| 129 | $this->render( |
||
| 130 | $source, |
||
| 131 | ' ->addColumn(%s, %s, %s)', |
||
| 132 | $column->getName(), |
||
| 133 | $column->getDeclaredType() ?? $column->getAbstractType(), |
||
| 134 | $column |
||
| 135 | ); |
||
| 136 | } |
||
| 137 | |||
| 138 | foreach ($comparator->alteredColumns() as $pair) { |
||
| 139 | $this->alterColumn( |
||
| 140 | $source, |
||
| 141 | $pair[self::NEW_STATE], |
||
| 142 | $pair[self::ORIGINAL_STATE] |
||
| 143 | ); |
||
| 144 | } |
||
| 145 | |||
| 146 | foreach ($comparator->droppedColumns() as $column) { |
||
| 147 | $this->render( |
||
| 148 | $source, |
||
| 149 | ' ->dropColumn(%s)', |
||
| 150 | $column->getName() |
||
| 151 | ); |
||
| 152 | } |
||
| 153 | } |
||
| 154 | |||
| 155 | /** |
||
| 156 | * @param Source $source |
||
| 157 | * @param Comparator $comparator |
||
| 158 | */ |
||
| 159 | private function declareIndexes(Source $source, Comparator $comparator): void |
||
| 160 | { |
||
| 161 | foreach ($comparator->addedIndexes() as $index) { |
||
| 162 | $this->render( |
||
| 163 | $source, |
||
| 164 | ' ->addIndex(%s, %s)', |
||
| 165 | $index->getColumns(), |
||
| 166 | $index |
||
| 167 | ); |
||
| 168 | } |
||
| 169 | |||
| 170 | foreach ($comparator->alteredIndexes() as $pair) { |
||
| 171 | /** @var AbstractIndex $index */ |
||
| 172 | $index = $pair[self::NEW_STATE]; |
||
| 173 | $this->render( |
||
| 174 | $source, |
||
| 175 | ' ->alterIndex(%s, %s)', |
||
| 176 | $index->getColumns(), |
||
| 177 | $index |
||
| 178 | ); |
||
| 179 | } |
||
| 180 | |||
| 181 | foreach ($comparator->droppedIndexes() as $index) { |
||
| 182 | $this->render( |
||
| 183 | $source, |
||
| 184 | ' ->dropIndex(%s)', |
||
| 185 | $index->getColumns() |
||
| 186 | ); |
||
| 187 | } |
||
| 188 | } |
||
| 189 | |||
| 190 | /** |
||
| 191 | * @param Source $source |
||
| 192 | * @param Comparator $comparator |
||
| 193 | * @param string $prefix Database isolation prefix |
||
| 194 | */ |
||
| 195 | private function declareForeignKeys(Source $source, Comparator $comparator, string $prefix = ''): void |
||
| 196 | { |
||
| 197 | foreach ($comparator->addedForeignKeys() as $key) { |
||
| 198 | $this->render( |
||
| 199 | $source, |
||
| 200 | ' ->addForeignKey(%s, %s, %s, %s)', |
||
| 201 | $key->getColumns(), |
||
| 202 | substr($key->getForeignTable(), strlen($prefix)), |
||
| 203 | $key->getForeignKeys(), |
||
| 204 | $key |
||
| 205 | ); |
||
| 206 | } |
||
| 207 | |||
| 208 | foreach ($comparator->alteredForeignKeys() as $pair) { |
||
| 209 | /** @var AbstractForeignKey $key */ |
||
| 210 | $key = $pair[self::NEW_STATE]; |
||
| 211 | $this->render( |
||
| 212 | $source, |
||
| 213 | ' ->alterForeignKey(%s, %s, %s, %s)', |
||
| 214 | $key->getColumns(), |
||
| 215 | substr($key->getForeignTable(), strlen($prefix)), |
||
| 216 | $key->getForeignKeys(), |
||
| 217 | $key |
||
| 218 | ); |
||
| 219 | } |
||
| 220 | |||
| 221 | foreach ($comparator->droppedForeignKeys() as $key) { |
||
| 222 | $this->render( |
||
| 223 | $source, |
||
| 224 | ' ->dropForeignKey(%s)', |
||
| 225 | $key->getColumns() |
||
| 226 | ); |
||
| 227 | } |
||
| 228 | } |
||
| 229 | |||
| 230 | /** |
||
| 231 | * @param Source $source |
||
| 232 | * @param Comparator $comparator |
||
| 233 | */ |
||
| 234 | private function revertColumns(Source $source, Comparator $comparator): void |
||
| 235 | { |
||
| 236 | foreach ($comparator->droppedColumns() as $column) { |
||
| 237 | $this->render( |
||
| 238 | $source, |
||
| 239 | ' ->addColumn(%s, %s, %s)', |
||
| 240 | $column->getName(), |
||
| 241 | $column->getDeclaredType() ?? $column->getAbstractType(), |
||
| 242 | $column |
||
| 243 | ); |
||
| 244 | } |
||
| 245 | |||
| 246 | foreach ($comparator->alteredColumns() as $pair) { |
||
| 247 | $this->alterColumn( |
||
| 248 | $source, |
||
| 249 | $pair[self::ORIGINAL_STATE], |
||
| 250 | $pair[self::NEW_STATE] |
||
| 251 | ); |
||
| 252 | } |
||
| 253 | |||
| 254 | foreach ($comparator->addedColumns() as $column) { |
||
| 255 | $this->render( |
||
| 256 | $source, |
||
| 257 | ' ->dropColumn(%s)', |
||
| 258 | $column->getName() |
||
| 259 | ); |
||
| 260 | } |
||
| 261 | } |
||
| 262 | |||
| 263 | /** |
||
| 264 | * @param Source $source |
||
| 265 | * @param Comparator $comparator |
||
| 266 | */ |
||
| 267 | private function revertIndexes(Source $source, Comparator $comparator): void |
||
| 294 | ); |
||
| 295 | } |
||
| 296 | } |
||
| 297 | |||
| 298 | /** |
||
| 299 | * @param Source $source |
||
| 300 | * @param Comparator $comparator |
||
| 301 | * @param string $prefix Database isolation prefix. |
||
| 302 | */ |
||
| 303 | private function revertForeignKeys(Source $source, Comparator $comparator, string $prefix = ''): void |
||
| 331 | } |
||
| 332 | } |
||
| 333 | |||
| 334 | /** |
||
| 335 | * @param Source $source |
||
| 336 | * @param AbstractColumn $column |
||
| 337 | * @param AbstractColumn $original |
||
| 338 | */ |
||
| 339 | protected function alterColumn( |
||
| 340 | Source $source, |
||
| 341 | AbstractColumn $column, |
||
| 342 | AbstractColumn $original |
||
| 343 | ): void { |
||
| 344 | if ($column->getName() !== $original->getName()) { |
||
| 345 | $name = $original->getName(); |
||
| 346 | } else { |
||
| 347 | $name = $column->getName(); |
||
| 348 | } |
||
| 349 | |||
| 350 | $this->render( |
||
| 351 | $source, |
||
| 352 | ' ->alterColumn(%s, %s, %s)', |
||
| 353 | $name, |
||
| 354 | $column->getDeclaredType() ?? $column->getAbstractType(), |
||
| 355 | $column |
||
| 356 | ); |
||
| 357 | |||
| 358 | if ($column->getName() !== $original->getName()) { |
||
| 359 | $this->render( |
||
| 360 | $source, |
||
| 361 | ' ->renameColumn(%s, %s)', |
||
| 362 | $name, |
||
| 363 | $column->getName() |
||
| 364 | ); |
||
| 365 | } |
||
| 366 | } |
||
| 367 | |||
| 368 | /** |
||
| 369 | * Render values and options into source. |
||
| 370 | * |
||
| 371 | * @param Source $source |
||
| 372 | * @param string $format |
||
| 373 | * @param array ...$values |
||
| 374 | */ |
||
| 375 | protected function render(Source $source, string $format, ...$values): void |
||
| 415 | } |
||
| 416 | } |
||
| 417 | |||
| 418 | /** |
||
| 419 | * @param Serializer $serializer |
||
| 420 | * @param AbstractColumn $column |
||
| 421 | * |
||
| 422 | * @return string |
||
| 423 | */ |
||
| 424 | private function columnOptions(Serializer $serializer, AbstractColumn $column): string |
||
| 425 | { |
||
| 426 | $options = [ |
||
| 427 | 'nullable' => $column->isNullable(), |
||
| 428 | 'default' => $column->getDefaultValue(), |
||
| 429 | ]; |
||
| 430 | |||
| 431 | if ($column->getAbstractType() === 'enum') { |
||
| 432 | $options['values'] = $column->getEnumValues(); |
||
| 433 | } |
||
| 434 | |||
| 435 | if ($column->getAbstractType() === 'string') { |
||
| 436 | $options['size'] = $column->getSize(); |
||
| 437 | } |
||
| 438 | |||
| 439 | if ($column->getAbstractType() === 'decimal') { |
||
| 440 | $options['scale'] = $column->getScale(); |
||
| 441 | $options['precision'] = $column->getPrecision(); |
||
| 442 | } |
||
| 443 | |||
| 444 | return $this->mountIndents($serializer->serialize($options)); |
||
| 445 | } |
||
| 446 | |||
| 447 | /** |
||
| 448 | * @param Serializer $serializer |
||
| 449 | * @param AbstractIndex $index |
||
| 450 | * |
||
| 451 | * @return string |
||
| 452 | */ |
||
| 453 | private function indexOptions(Serializer $serializer, AbstractIndex $index): string |
||
| 460 | ] |
||
| 461 | ) |
||
| 462 | ); |
||
| 463 | } |
||
| 464 | |||
| 465 | /** |
||
| 466 | * @param Serializer $serializer |
||
| 467 | * @param AbstractForeignKey $reference |
||
| 468 | * |
||
| 469 | * @return string |
||
| 470 | */ |
||
| 471 | private function foreignKeyOptions( |
||
| 472 | Serializer $serializer, |
||
| 473 | AbstractForeignKey $reference |
||
| 474 | ): string { |
||
| 475 | return $this->mountIndents( |
||
| 476 | $serializer->serialize( |
||
| 477 | [ |
||
| 478 | 'name' => $reference->getName(), |
||
| 479 | 'delete' => $reference->getDeleteRule(), |
||
| 480 | 'update' => $reference->getUpdateRule(), |
||
| 481 | ] |
||
| 482 | ) |
||
| 483 | ); |
||
| 484 | } |
||
| 485 | |||
| 486 | /** |
||
| 487 | * Mount indents for column and index options. |
||
| 488 | * |
||
| 489 | * @param $serialized |
||
| 490 | * |
||
| 491 | * @return string |
||
| 492 | */ |
||
| 493 | private function mountIndents(string $serialized): string |
||
| 502 | } |
||
| 503 | } |
||
| 504 |