Completed
Pull Request — master (#1618)
by
unknown
01:26
created

Plan::createPlan()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 9
rs 9.9666
c 0
b 0
f 0
cc 1
nc 1
nop 1
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
        return [$indexes, $removeColumnActions->getArrayCopy()];
411
    }
412
413
    /**
414
     * Collects all table creation actions from the given intent
415
     *
416
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
417
     * @return void
418
     */
419
    protected function gatherCreates($actions)
420
    {
421
        collection($actions)
422
            ->filter(function ($action) {
423
                return $action instanceof CreateTable;
424
            })
425
            ->map(function ($action) {
426
                return [$action->getTable()->getName(), new NewTable($action->getTable())];
427
            })
428
            ->each(function ($step) {
429
                $this->tableCreates[$step[0]] = $step[1];
430
            });
431
432
        collection($actions)
433
            ->filter(function ($action) {
434
                return $action instanceof AddColumn
435
                    || $action instanceof AddIndex;
436
            })
437
            ->filter(function ($action) {
438
                return isset($this->tableCreates[$action->getTable()->getName()]);
439
            })
440
            ->each(function ($action) {
441
                $table = $action->getTable();
442
443
                if ($action instanceof AddColumn) {
444
                    $this->tableCreates[$table->getName()]->addColumn($action->getColumn());
445
                }
446
447
                if ($action instanceof AddIndex) {
448
                    $this->tableCreates[$table->getName()]->addIndex($action->getIndex());
449
                }
450
            });
451
    }
452
453
    /**
454
     * Collects all alter table actions from the given intent
455
     *
456
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
457
     * @return void
458
     */
459
    protected function gatherUpdates($actions)
460
    {
461
        collection($actions)
462
            ->filter(function ($action) {
463
                return $action instanceof AddColumn
464
                    || $action instanceof ChangeColumn
465
                    || $action instanceof RemoveColumn
466
                    || $action instanceof RenameColumn;
467
            })
468
            // We are only concerned with table changes
469
            ->reject(function ($action) {
470
                return isset($this->tableCreates[$action->getTable()->getName()]);
471
            })
472
            ->each(function ($action) {
473
                $table = $action->getTable();
474
                $name = $table->getName();
475
476
                if ($action instanceof RemoveColumn) {
477
                    if (!isset($this->columnRemoves[$name])) {
478
                        $this->columnRemoves[$name] = new AlterTable($table);
479
                    }
480
                    $this->columnRemoves[$name]->addAction($action);
481
                } else {
482
                    if (!isset($this->tableUpdates[$name])) {
483
                        $this->tableUpdates[$name] = new AlterTable($table);
484
                    }
485
                    $this->tableUpdates[$name]->addAction($action);
486
                }
487
            });
488
    }
489
490
    /**
491
     * Collects all alter table drop and renames from the given intent
492
     *
493
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
494
     * @return void
495
     */
496
    protected function gatherTableMoves($actions)
497
    {
498
        collection($actions)
499
            ->filter(function ($action) {
500
                return $action instanceof DropTable
501
                    || $action instanceof RenameTable
502
                    || $action instanceof ChangePrimaryKey
503
                    || $action instanceof ChangeComment;
504
            })
505 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...
506
                $table = $action->getTable();
507
                $name = $table->getName();
508
509
                if (!isset($this->tableMoves[$name])) {
510
                    $this->tableMoves[$name] = new AlterTable($table);
511
                }
512
513
                $this->tableMoves[$name]->addAction($action);
514
            });
515
    }
516
517
    /**
518
     * Collects all index creation and drops from the given intent
519
     *
520
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
521
     * @return void
522
     */
523
    protected function gatherIndexes($actions)
524
    {
525
        collection($actions)
526
            ->filter(function ($action) {
527
                return $action instanceof AddIndex
528
                    || $action instanceof DropIndex;
529
            })
530
            ->reject(function ($action) {
531
                // Indexes for new tables are created inline
532
                // so we don't wan't them here too
533
                return isset($this->tableCreates[$action->getTable()->getName()]);
534
            })
535 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...
536
                $table = $action->getTable();
537
                $name = $table->getName();
538
539
                if (!isset($this->indexes[$name])) {
540
                    $this->indexes[$name] = new AlterTable($table);
541
                }
542
543
                $this->indexes[$name]->addAction($action);
544
            });
545
    }
546
547
    /**
548
     * Collects all foreign key creation and drops from the given intent
549
     *
550
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
551
     * @return void
552
     */
553
    protected function gatherConstraints($actions)
554
    {
555
        collection($actions)
556
            ->filter(function ($action) {
557
                return $action instanceof AddForeignKey
558
                    || $action instanceof DropForeignKey;
559
            })
560 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...
561
                $table = $action->getTable();
562
                $name = $table->getName();
563
564
                if (!isset($this->constraints[$name])) {
565
                    $this->constraints[$name] = new AlterTable($table);
566
                }
567
568
                $this->constraints[$name]->addAction($action);
569
            });
570
    }
571
}
572