|
3 | 3 | namespace Toramanlis\ImplicitMigrations\Blueprint;
|
4 | 4 |
|
5 | 5 | use Exception;
|
| 6 | +use Illuminate\Database\Schema\Blueprint; |
6 | 7 | use Illuminate\Database\Schema\ColumnDefinition;
|
7 | 8 | use Illuminate\Support\Facades\App;
|
8 | 9 | use Illuminate\Support\Fluent;
|
|
11 | 12 | class BlueprintDiff implements Migratable
|
12 | 13 | {
|
13 | 14 | /**
|
14 |
| - * @param SimplifyingBlueprint $from |
15 |
| - * @param SimplifyingBlueprint $to |
16 |
| - * @param array<string> $modifiedColumns |
| 15 | + * @param array<string> |
| 16 | + */ |
| 17 | + public array $modifiedColumns; |
| 18 | + |
| 19 | + /** |
17 | 20 | * @param array<ColumnDefinition> $droppedColumns
|
| 21 | + */ |
| 22 | + public array $droppedColumns; |
| 23 | + |
| 24 | + /** |
18 | 25 | * @param array<ColumnDefinition> $addedColumns
|
| 26 | + */ |
| 27 | + public array $addedColumns; |
| 28 | + |
| 29 | + /** |
19 | 30 | * @param array<Fluent> $droppedIndexes
|
| 31 | + */ |
| 32 | + public array $droppedIndexes; |
| 33 | + |
| 34 | + /** |
20 | 35 | * @param array<string, string> $renamedIndexes
|
| 36 | + */ |
| 37 | + public array $renamedIndexes; |
| 38 | + |
| 39 | + /** |
21 | 40 | * @param array<Fluent> $addedIndexes
|
22 | 41 | */
|
| 42 | + public array $addedIndexes; |
| 43 | + |
| 44 | + /** |
| 45 | + * @param SimplifyingBlueprint $from |
| 46 | + * @param SimplifyingBlueprint $to |
| 47 | + */ |
23 | 48 | public function __construct(
|
24 | 49 | readonly public SimplifyingBlueprint $from,
|
25 |
| - readonly public SimplifyingBlueprint $to, |
26 |
| - public array $modifiedColumns, |
27 |
| - public array $droppedColumns, |
28 |
| - public array $addedColumns, |
29 |
| - public array $droppedIndexes, |
30 |
| - public array $renamedIndexes, |
31 |
| - public array $addedIndexes |
| 50 | + readonly public SimplifyingBlueprint $to |
32 | 51 | ) {
|
| 52 | + [$this->modifiedColumns, $this->droppedColumns, $this->addedColumns] = static::getColumnDiffs($from, $to); |
| 53 | + [$this->droppedIndexes, $this->renamedIndexes, $this->addedIndexes] = static::getIndexDiffs($from, $to); |
33 | 54 | }
|
34 | 55 |
|
35 | 56 | public function applyColumnIndexes(bool $reverse = false)
|
@@ -246,4 +267,126 @@ public function defaultIndexName(Fluent $index, bool $reverse = false)
|
246 | 267 | {
|
247 | 268 | return ($reverse ? $this->from : $this->to)->defaultIndexName($index);
|
248 | 269 | }
|
| 270 | + |
| 271 | + protected static function attributesEqual(Fluent $left, Fluent $right, array $exceptions = []) |
| 272 | + { |
| 273 | + $leftClone = clone $left; |
| 274 | + $rightClone = clone $right; |
| 275 | + |
| 276 | + $leftAttributes = array_filter($leftClone->getAttributes(), fn ($i) => null !== $i); |
| 277 | + $rightAttributes = array_filter($rightClone->getAttributes(), fn ($i) => null !== $i); |
| 278 | + |
| 279 | + ksort($leftAttributes); |
| 280 | + ksort($rightAttributes); |
| 281 | + |
| 282 | + foreach ($exceptions as $exception) { |
| 283 | + unset($leftAttributes[$exception], $rightAttributes[$exception]); |
| 284 | + } |
| 285 | + |
| 286 | + return $leftAttributes === $rightAttributes; |
| 287 | + } |
| 288 | + |
| 289 | + /** |
| 290 | + * @param Blueprint $from |
| 291 | + * @param Blueprint $to |
| 292 | + * @return array |
| 293 | + */ |
| 294 | + protected static function getColumnDiffs(Blueprint $from, Blueprint $to): array |
| 295 | + { |
| 296 | + $unchangedColumns = []; |
| 297 | + $modifiedColumns = []; |
| 298 | + $droppedColumns = []; |
| 299 | + $addedColumns = []; |
| 300 | + |
| 301 | + foreach ($from->getColumns() as $fromColumn) { |
| 302 | + foreach ($to->getColumns() as $toColumn) { |
| 303 | + if (in_array($toColumn->name, $unchangedColumns)) { |
| 304 | + continue; |
| 305 | + } |
| 306 | + |
| 307 | + if ($fromColumn->name === $toColumn->name) { |
| 308 | + if (static::attributesEqual($fromColumn, $toColumn)) { |
| 309 | + $unchangedColumns[] = $fromColumn->name; |
| 310 | + continue 2; |
| 311 | + } |
| 312 | + |
| 313 | + $modifiedColumns[] = $fromColumn->name; |
| 314 | + continue 2; |
| 315 | + } |
| 316 | + } |
| 317 | + |
| 318 | + $droppedColumns[] = $fromColumn; |
| 319 | + } |
| 320 | + |
| 321 | + foreach ($to->getColumns() as $toColumn) { |
| 322 | + if ( |
| 323 | + in_array($toColumn->name, $unchangedColumns) || |
| 324 | + in_array($toColumn->name, $modifiedColumns) |
| 325 | + ) { |
| 326 | + continue; |
| 327 | + } |
| 328 | + |
| 329 | + $addedColumns[] = $toColumn; |
| 330 | + } |
| 331 | + |
| 332 | + return [$modifiedColumns, $droppedColumns, $addedColumns]; |
| 333 | + } |
| 334 | + |
| 335 | + /** |
| 336 | + * @param Blueprint $from |
| 337 | + * @param Blueprint $to |
| 338 | + * @return array |
| 339 | + */ |
| 340 | + protected static function getIndexDiffs(Blueprint $from, Blueprint $to): array |
| 341 | + { |
| 342 | + $unchangedIndexes = []; |
| 343 | + $droppedIndexes = []; |
| 344 | + $renamedIndexes = []; |
| 345 | + $addedIndexes = []; |
| 346 | + |
| 347 | + foreach ($from->getCommands() as $fromCommand) { |
| 348 | + if (null === IndexType::tryFrom($fromCommand->name)) { |
| 349 | + continue; |
| 350 | + } |
| 351 | + |
| 352 | + foreach ($to->getCommands() as $toCommand) { |
| 353 | + if ( |
| 354 | + null === IndexType::tryFrom($toCommand->name) || |
| 355 | + in_array($toCommand->index, $unchangedIndexes) |
| 356 | + ) { |
| 357 | + continue; |
| 358 | + } |
| 359 | + |
| 360 | + if (static::attributesEqual($fromCommand, $toCommand, ['index'])) { |
| 361 | + if ($fromCommand->index === $toCommand->index) { |
| 362 | + unset($renamedIndexes[$fromCommand->index]); |
| 363 | + $unchangedIndexes[] = $fromCommand->index; |
| 364 | + continue 2; |
| 365 | + } |
| 366 | + |
| 367 | + $renamedIndexes[$fromCommand->index] = $toCommand->index; |
| 368 | + continue 2; |
| 369 | + } |
| 370 | + } |
| 371 | + |
| 372 | + $droppedIndexes[] = $fromCommand; |
| 373 | + } |
| 374 | + |
| 375 | + foreach ($to->getCommands() as $toCommand) { |
| 376 | + if (null === IndexType::tryFrom($toCommand->name)) { |
| 377 | + continue; |
| 378 | + } |
| 379 | + |
| 380 | + if ( |
| 381 | + in_array($toCommand->index, $unchangedIndexes) || |
| 382 | + in_array($toCommand->index, $renamedIndexes) |
| 383 | + ) { |
| 384 | + continue; |
| 385 | + } |
| 386 | + |
| 387 | + $addedIndexes[] = $toCommand; |
| 388 | + } |
| 389 | + |
| 390 | + return [$droppedIndexes, $renamedIndexes, $addedIndexes]; |
| 391 | + } |
249 | 392 | }
|
0 commit comments