Completed
Pull Request — master (#1618)
by
unknown
03:46 queued 01:16
created

Plan::forgetTable()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
cc 3
nc 3
nop 2
1
<?php
2
/**
3
 * Phinx
4
 *
5
 * (The MIT license)
6
 *
7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
8
 * of this software and associated * documentation files (the "Software"), to
9
 * deal in the Software without restriction, including without limitation the
10
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
11
 * sell copies of the Software, and to permit persons to whom the Software is
12
 * furnished to do so, subject to the following conditions:
13
 *
14
 * The above copyright notice and this permission notice shall be included in
15
 * all copies or substantial portions of the Software.
16
 *
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23
 * IN THE SOFTWARE.
24
 */
25
namespace Phinx\Db\Plan;
26
27
use ArrayObject;
28
use Phinx\Db\Action\AddColumn;
29
use Phinx\Db\Action\AddForeignKey;
30
use Phinx\Db\Action\AddIndex;
31
use Phinx\Db\Action\ChangeColumn;
32
use Phinx\Db\Action\ChangeComment;
33
use Phinx\Db\Action\ChangePrimaryKey;
34
use Phinx\Db\Action\CreateTable;
35
use Phinx\Db\Action\DropForeignKey;
36
use Phinx\Db\Action\DropIndex;
37
use Phinx\Db\Action\DropTable;
38
use Phinx\Db\Action\RemoveColumn;
39
use Phinx\Db\Action\RenameColumn;
40
use Phinx\Db\Action\RenameTable;
41
use Phinx\Db\Adapter\AdapterInterface;
42
use Phinx\Db\Plan\Solver\ActionSplitter;
43
use Phinx\Db\Table\Table;
44
45
/**
46
 * A Plan takes an Intent and transforms int into a sequence of
47
 * instructions that can be correctly executed by an AdapterInterface.
48
 *
49
 * The main focus of Plan is to arrange the actions in the most efficient
50
 * way possible for the database.
51
 */
52
class Plan
53
{
54
55
    /**
56
     * List of tables to be created
57
     *
58
     * @var \Phinx\Db\Plan\NewTable[]
59
     */
60
    protected $tableCreates = [];
61
62
    /**
63
     * List of table updates
64
     *
65
     * @var \Phinx\Db\Plan\AlterTable[]
66
     */
67
    protected $tableUpdates = [];
68
69
    /**
70
     * List of table removals or renames
71
     *
72
     * @var \Phinx\Db\Plan\AlterTable[]
73
     */
74
    protected $tableMoves = [];
75
76
    /**
77
     * List of index additions or removals
78
     *
79
     * @var \Phinx\Db\Plan\AlterTable[]
80
     */
81
    protected $indexes = [];
82
83
    /**
84
     * List of constraint additions or removals
85
     *
86
     * @var \Phinx\Db\Plan\AlterTable[]
87
     */
88
    protected $constraints = [];
89
90
    /**
91
     * List of dropped columns
92
     *
93
     * @var \Phinx\Db\Plan\AlterTable[]
94
     */
95
    protected $columnRemoves = [];
96
97
    /**
98
     * Constructor
99
     *
100
     * @param Intent $intent All the actions that should be executed
101
     */
102
    public function __construct(Intent $intent)
103
    {
104
        $this->createPlan($intent->getActions());
0 ignored issues
show
Documentation introduced by
$intent->getActions() is of type array<integer,object<Phinx\Db\Action\Action>>, but the function expects a object<Phinx\Db\Plan\Intent>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
105
    }
106
107
    /**
108
     * Parses the given Intent and creates the separate steps to execute
109
     *
110
     * @param Intent $actions The actions to use for the plan
111
     * @return void
112
     */
113
    protected function createPlan($actions)
114
    {
115
        $this->gatherCreates($actions);
0 ignored issues
show
Documentation introduced by
$actions is of type object<Phinx\Db\Plan\Intent>, but the function expects a array<integer,object<Phinx\Db\Action\Action>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
116
        $this->gatherUpdates($actions);
0 ignored issues
show
Documentation introduced by
$actions is of type object<Phinx\Db\Plan\Intent>, but the function expects a array<integer,object<Phinx\Db\Action\Action>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
117
        $this->gatherTableMoves($actions);
0 ignored issues
show
Documentation introduced by
$actions is of type object<Phinx\Db\Plan\Intent>, but the function expects a array<integer,object<Phinx\Db\Action\Action>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
118
        $this->gatherIndexes($actions);
0 ignored issues
show
Documentation introduced by
$actions is of type object<Phinx\Db\Plan\Intent>, but the function expects a array<integer,object<Phinx\Db\Action\Action>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
119
        $this->gatherConstraints($actions);
0 ignored issues
show
Documentation introduced by
$actions is of type object<Phinx\Db\Plan\Intent>, but the function expects a array<integer,object<Phinx\Db\Action\Action>>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
120
        $this->resolveConflicts();
121
    }
122
123
    /**
124
     * Returns a nested list of all the steps to execute for a migrate plan
125
     *
126
     * @return AlterTable[][]
127
     */
128 View Code Duplication
    protected function updatesSequence()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
129
    {
130
        return [
131
            $this->tableUpdates,
132
            $this->constraints,
133
            $this->indexes,
134
            $this->columnRemoves,
135
            $this->tableMoves,
136
        ];
137
    }
138
139
    /**
140
     * Returns a nested list of all the steps to execute for a rollback plan
141
     */
142 View Code Duplication
    protected function inverseUpdatesSequence()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
143
    {
144
        return [
145
            $this->tableMoves,
146
            $this->constraints,
147
            $this->indexes,
148
            $this->columnRemoves,
149
            $this->tableUpdates
150
        ];
151
    }
152
153
    /**
154
     * Executes this plan using the given AdapterInterface
155
     *
156
     * @param AdapterInterface $executor The executor object for the plan
157
     * @return void
158
     */
159 View Code Duplication
    public function execute(AdapterInterface $executor)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
160
    {
161
        foreach ($this->tableCreates as $newTable) {
162
            $executor->createTable($newTable->getTable(), $newTable->getColumns(), $newTable->getIndexes());
163
        }
164
165
        collection($this->updatesSequence())
166
            ->unfold()
167
            ->each(function ($updates) use ($executor) {
168
                $executor->executeActions($updates->getTable(), $updates->getActions());
169
            });
170
    }
171
172
    /**
173
     * Executes the inverse plan (rollback the actions) with the given AdapterInterface:w
174
     *
175
     * @param AdapterInterface $executor The executor object for the plan
176
     * @return void
177
     */
178 View Code Duplication
    public function executeInverse(AdapterInterface $executor)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
179
    {
180
        collection($this->inverseUpdatesSequence())
181
            ->unfold()
182
            ->each(function ($updates) use ($executor) {
183
                $executor->executeActions($updates->getTable(), $updates->getActions());
184
            });
185
186
        foreach ($this->tableCreates as $newTable) {
187
            $executor->createTable($newTable->getTable(), $newTable->getColumns(), $newTable->getIndexes());
188
        }
189
    }
190
191
    /**
192
     * Deletes certain actions from the plan if they are found to be conflicting or redundant.
193
     *
194
     * @return void
195
     */
196
    protected function resolveConflicts()
197
    {
198
        $moveActions = collection($this->tableMoves)
199
            ->unfold(function ($move) {
200
                return $move->getActions();
201
            });
202
203
        foreach ($moveActions as $action) {
204
            if ($action instanceof DropTable) {
205
                $this->tableUpdates = $this->forgetTable($action->getTable(), $this->tableUpdates);
206
                $this->constraints = $this->forgetTable($action->getTable(), $this->constraints);
207
                $this->indexes = $this->forgetTable($action->getTable(), $this->indexes);
208
                $this->columnRemoves = $this->forgetTable($action->getTable(), $this->columnRemoves);
209
            }
210
        }
211
212
        // Columns that are dropped will automatically cause the indexes to be dropped as well
213
        foreach ($this->columnRemoves as $columnRemove) {
214
            foreach ($columnRemove->getActions() as $action) {
215
                if ($action instanceof RemoveColumn) {
216
                    list($this->indexes) = $this->forgetDropIndex(
217
                        $action->getTable(),
218
                        [$action->getColumn()->getName()],
219
                        $this->indexes
220
                    );
221
                }
222
            }
223
        }
224
225
        $this->tableUpdates = collection($this->tableUpdates)
226
            // Renaming a column and then changing the renamed column is something people do,
227
            // but it is a conflicting action. Luckily solving the conflict can be done by moving
228
            // the ChangeColumn action to another AlterTable
229
            ->unfold(new ActionSplitter(RenameColumn::class, ChangeColumn::class, function (RenameColumn $a, ChangeColumn $b) {
230
                return $a->getNewName() == $b->getColumnName();
231
            }))
232
            ->toList();
233
234
        $this->constraints = collection($this->constraints)
235
            ->map(function (AlterTable $alter) {
236
                // Dropping indexes used by foreign keys is a conflict, but one we can resolve
237
                // if the foreign key is also scheduled to be dropped. If we can find such a a case,
238
                // we force the execution of the index drop after the foreign key is dropped.
239
                return $this->remapContraintAndIndexConflicts($alter);
240
            })
241
            // Changing constraint properties sometimes require dropping it and then
242
            // creating it again with the new stuff. Unfortunately, we have already bundled
243
            // everything together in as few AlterTable statements as we could, so we need to
244
            // resolve this conflict manually
245
            ->unfold(new ActionSplitter(DropForeignKey::class, AddForeignKey::class, function (DropForeignKey $a, AddForeignKey $b) {
246
                return $a->getForeignKey()->getColumns() === $b->getForeignKey()->getColumns();
247
            }))
248
            ->toList();
249
    }
250
251
    /**
252
     * Deletes all actions related to the given table and keeps the
253
     * rest
254
     *
255
     * @param Table $table The table to find in the list of actions
256
     * @param AlterTable[] $actions The actions to transform
257
     * @return AlterTable[] The list of actions without actions for the given table
258
     */
259
    protected function forgetTable(Table $table, $actions)
260
    {
261
        $result = [];
262
        foreach ($actions as $action) {
263
            if ($action->getTable()->getName() === $table->getName()) {
264
                continue;
265
            }
266
            $result[] = $action;
267
        }
268
269
        return $result;
270
    }
271
272
    /**
273
     * Finds all DropForeignKey actions in an AlterTable and moves
274
     * all conflicting DropIndex action in `$this->indexes` into the
275
     * given AlterTable.
276
     *
277
     * @param AlterTable $alter The collection of actions to inspect
278
     * @return AlterTable The updated AlterTable object. This function
279
     * has the side effect of changing the `$this->indexes` property.
280
     */
281
    protected function remapContraintAndIndexConflicts(AlterTable $alter)
282
    {
283
        $newAlter = new AlterTable($alter->getTable());
284
        collection($alter->getActions())
285
            ->unfold(function ($action) {
286
                if (!$action instanceof DropForeignKey) {
287
                    return [$action];
288
                }
289
290
                list($this->indexes, $dropIndexActions) = $this->forgetDropIndex(
291
                    $action->getTable(),
292
                    $action->getForeignKey()->getColumns(),
293
                    $this->indexes
294
                );
295
296
                list($this->columnRemoves, $removeColumnActions) = $this->forgetRemoveColumn(
297
                    $action->getTable(),
298
                    $action->getForeignKey()->getColumns(),
299
                    $this->columnRemoves
300
                );
301
302
                $return = [$action];
303
                if (!empty($dropIndexActions)) {
304
                    $return = array_merge($return, $dropIndexActions);
305
                }
306
307
                if (!empty($removeColumnActions)) {
308
                    $return = array_merge($return, $removeColumnActions);
309
                }
310
311
                return $return;
312
            })
313
            ->each(function ($action) use ($newAlter) {
314
                $newAlter->addAction($action);
315
            });
316
317
        return $newAlter;
318
    }
319
320
    /**
321
     * Deletes any DropIndex actions for the given table and exact columns
322
     *
323
     * @param Table $table The table to find in the list of actions
324
     * @param string[] $columns The column names to match
325
     * @param AlterTable[] $actions The actions to transform
326
     * @return array A tuple containing the list of actions without actions for dropping the index
327
     * and a list of drop index actions that were removed.
328
     */
329 View Code Duplication
    protected function forgetDropIndex(Table $table, array $columns, array $actions)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
330
    {
331
        $dropIndexActions = new ArrayObject();
332
        $indexes = collection($actions)
333
            ->map(function ($alter) use ($table, $columns, $dropIndexActions) {
334
                if ($alter->getTable()->getName() !== $table->getName()) {
335
                    return $alter;
336
                }
337
338
                $newAlter = new AlterTable($table);
339
                collection($alter->getActions())
340
                    ->map(function ($action) use ($columns) {
341
                        if (!$action instanceof DropIndex) {
342
                            return [$action, null];
343
                        }
344
                        if ($action->getIndex()->getColumns() === $columns) {
345
                            return [null, $action];
346
                        }
347
348
                        return [$action, null];
349
                    })
350
                    ->each(function ($tuple) use ($newAlter, $dropIndexActions) {
351
                        list($action, $dropIndex) = $tuple;
352
                        if ($action) {
353
                            $newAlter->addAction($action);
354
                        }
355
                        if ($dropIndex) {
356
                            $dropIndexActions->append($dropIndex);
357
                        }
358
                    });
359
360
                return $newAlter;
361
            })
362
            ->toArray();
363
364
        return [$indexes, $dropIndexActions->getArrayCopy()];
365
    }
366
367
    /**
368
     * Deletes any RemoveColumn actions for the given table and exact columns
369
     *
370
     * @param Table $table The table to find in the list of actions
371
     * @param string[] $columns The column names to match
372
     * @param AlterTable[] $actions The actions to transform
373
     * @return array A tuple containing the list of actions without actions for removing the column
374
     * and a list of remove column actions that were removed.
375
     */
376 View Code Duplication
    protected function forgetRemoveColumn(Table $table, array $columns, array $actions)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
377
    {
378
        $removeColumnActions = new ArrayObject();
379
        $indexes = collection($actions)
380
            ->map(function ($alter) use ($table, $columns, $removeColumnActions) {
381
                if ($alter->getTable()->getName() !== $table->getName()) {
382
                    return $alter;
383
                }
384
385
                $newAlter = new AlterTable($table);
386
                collection($alter->getActions())
387
                    ->map(function ($action) use ($columns) {
388
                        if (!$action instanceof RemoveColumn) {
389
                            return [$action, null];
390
                        }
391
                        if (in_array($action->getColumn(), $columns)) {
392
                            return [null, $action];
393
                        }
394
395
                        return [$action, null];
396
                    })
397
                    ->each(function ($tuple) use ($newAlter, $removeColumnActions) {
398
                        list($action, $removeColumn) = $tuple;
399
                        if ($action) {
400
                            $newAlter->addAction($action);
401
                        }
402
                        if ($removeColumn) {
403
                            $removeColumnActions->append($removeColumn);
404
                        }
405
                    });
406
407
                return $newAlter;
408
            })
409
            ->toArray();
410
411
        return [$indexes, $removeColumnActions->getArrayCopy()];
412
    }
413
414
    /**
415
     * Collects all table creation actions from the given intent
416
     *
417
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
418
     * @return void
419
     */
420
    protected function gatherCreates($actions)
421
    {
422
        collection($actions)
423
            ->filter(function ($action) {
424
                return $action instanceof CreateTable;
425
            })
426
            ->map(function ($action) {
427
                return [$action->getTable()->getName(), new NewTable($action->getTable())];
428
            })
429
            ->each(function ($step) {
430
                $this->tableCreates[$step[0]] = $step[1];
431
            });
432
433
        collection($actions)
434
            ->filter(function ($action) {
435
                return $action instanceof AddColumn
436
                    || $action instanceof AddIndex;
437
            })
438
            ->filter(function ($action) {
439
                return isset($this->tableCreates[$action->getTable()->getName()]);
440
            })
441
            ->each(function ($action) {
442
                $table = $action->getTable();
443
444
                if ($action instanceof AddColumn) {
445
                    $this->tableCreates[$table->getName()]->addColumn($action->getColumn());
446
                }
447
448
                if ($action instanceof AddIndex) {
449
                    $this->tableCreates[$table->getName()]->addIndex($action->getIndex());
450
                }
451
            });
452
    }
453
454
    /**
455
     * Collects all alter table actions from the given intent
456
     *
457
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
458
     * @return void
459
     */
460
    protected function gatherUpdates($actions)
461
    {
462
        collection($actions)
463
            ->filter(function ($action) {
464
                return $action instanceof AddColumn
465
                    || $action instanceof ChangeColumn
466
                    || $action instanceof RemoveColumn
467
                    || $action instanceof RenameColumn;
468
            })
469
            // We are only concerned with table changes
470
            ->reject(function ($action) {
471
                return isset($this->tableCreates[$action->getTable()->getName()]);
472
            })
473
            ->each(function ($action) {
474
                $table = $action->getTable();
475
                $name = $table->getName();
476
477
                if ($action instanceof RemoveColumn) {
478
                    if (!isset($this->columnRemoves[$name])) {
479
                        $this->columnRemoves[$name] = new AlterTable($table);
480
                    }
481
                    $this->columnRemoves[$name]->addAction($action);
482
                } else {
483
                    if (!isset($this->tableUpdates[$name])) {
484
                        $this->tableUpdates[$name] = new AlterTable($table);
485
                    }
486
                    $this->tableUpdates[$name]->addAction($action);
487
                }
488
            });
489
    }
490
491
    /**
492
     * Collects all alter table drop and renames from the given intent
493
     *
494
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
495
     * @return void
496
     */
497
    protected function gatherTableMoves($actions)
498
    {
499
        collection($actions)
500
            ->filter(function ($action) {
501
                return $action instanceof DropTable
502
                    || $action instanceof RenameTable
503
                    || $action instanceof ChangePrimaryKey
504
                    || $action instanceof ChangeComment;
505
            })
506 View Code Duplication
            ->each(function ($action) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
507
                $table = $action->getTable();
508
                $name = $table->getName();
509
510
                if (!isset($this->tableMoves[$name])) {
511
                    $this->tableMoves[$name] = new AlterTable($table);
512
                }
513
514
                $this->tableMoves[$name]->addAction($action);
515
            });
516
    }
517
518
    /**
519
     * Collects all index creation and drops from the given intent
520
     *
521
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
522
     * @return void
523
     */
524
    protected function gatherIndexes($actions)
525
    {
526
        collection($actions)
527
            ->filter(function ($action) {
528
                return $action instanceof AddIndex
529
                    || $action instanceof DropIndex;
530
            })
531
            ->reject(function ($action) {
532
                // Indexes for new tables are created inline
533
                // so we don't wan't them here too
534
                return isset($this->tableCreates[$action->getTable()->getName()]);
535
            })
536 View Code Duplication
            ->each(function ($action) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
537
                $table = $action->getTable();
538
                $name = $table->getName();
539
540
                if (!isset($this->indexes[$name])) {
541
                    $this->indexes[$name] = new AlterTable($table);
542
                }
543
544
                $this->indexes[$name]->addAction($action);
545
            });
546
    }
547
548
    /**
549
     * Collects all foreign key creation and drops from the given intent
550
     *
551
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
552
     * @return void
553
     */
554
    protected function gatherConstraints($actions)
555
    {
556
        collection($actions)
557
            ->filter(function ($action) {
558
                return $action instanceof AddForeignKey
559
                    || $action instanceof DropForeignKey;
560
            })
561 View Code Duplication
            ->each(function ($action) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
562
                $table = $action->getTable();
563
                $name = $table->getName();
564
565
                if (!isset($this->constraints[$name])) {
566
                    $this->constraints[$name] = new AlterTable($table);
567
                }
568
569
                $this->constraints[$name]->addAction($action);
570
            });
571
    }
572
}
573