Completed
Pull Request — master (#1618)
by
unknown
02:35 queued 44s
created

Plan::inverseUpdatesSequence()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10

Duplication

Lines 10
Ratio 100 %

Importance

Changes 0
Metric Value
dl 10
loc 10
rs 9.9332
c 0
b 0
f 0
cc 1
nc 1
nop 0
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
     * @return AlterTable[][]
143
     */
144 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...
145
    {
146
        return [
147
            $this->tableMoves,
148
            $this->constraints,
149
            $this->indexes,
150
            $this->columnRemoves,
151
            $this->tableUpdates
152
        ];
153
    }
154
155
    /**
156
     * Executes this plan using the given AdapterInterface
157
     *
158
     * @param AdapterInterface $executor The executor object for the plan
159
     * @return void
160
     */
161 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...
162
    {
163
        foreach ($this->tableCreates as $newTable) {
164
            $executor->createTable($newTable->getTable(), $newTable->getColumns(), $newTable->getIndexes());
165
        }
166
167
        collection($this->updatesSequence())
168
            ->unfold()
169
            ->each(function ($updates) use ($executor) {
170
                $executor->executeActions($updates->getTable(), $updates->getActions());
171
            });
172
    }
173
174
    /**
175
     * Executes the inverse plan (rollback the actions) with the given AdapterInterface:w
176
     *
177
     * @param AdapterInterface $executor The executor object for the plan
178
     * @return void
179
     */
180 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...
181
    {
182
        collection($this->inverseUpdatesSequence())
183
            ->unfold()
184
            ->each(function ($updates) use ($executor) {
185
                $executor->executeActions($updates->getTable(), $updates->getActions());
186
            });
187
188
        foreach ($this->tableCreates as $newTable) {
189
            $executor->createTable($newTable->getTable(), $newTable->getColumns(), $newTable->getIndexes());
190
        }
191
    }
192
193
    /**
194
     * Deletes certain actions from the plan if they are found to be conflicting or redundant.
195
     *
196
     * @return void
197
     */
198
    protected function resolveConflicts()
199
    {
200
        $moveActions = collection($this->tableMoves)
201
            ->unfold(function ($move) {
202
                return $move->getActions();
203
            });
204
205
        foreach ($moveActions as $action) {
206
            if ($action instanceof DropTable) {
207
                $this->tableUpdates = $this->forgetTable($action->getTable(), $this->tableUpdates);
208
                $this->constraints = $this->forgetTable($action->getTable(), $this->constraints);
209
                $this->indexes = $this->forgetTable($action->getTable(), $this->indexes);
210
                $this->columnRemoves = $this->forgetTable($action->getTable(), $this->columnRemoves);
211
            }
212
        }
213
214
        // Columns that are dropped will automatically cause the indexes to be dropped as well
215
        foreach ($this->columnRemoves as $columnRemove) {
216
            foreach ($columnRemove->getActions() as $action) {
217
                if ($action instanceof RemoveColumn) {
218
                    list($this->indexes) = $this->forgetDropIndex(
219
                        $action->getTable(),
220
                        [$action->getColumn()->getName()],
221
                        $this->indexes
222
                    );
223
                }
224
            }
225
        }
226
227
        $this->tableUpdates = collection($this->tableUpdates)
228
            // Renaming a column and then changing the renamed column is something people do,
229
            // but it is a conflicting action. Luckily solving the conflict can be done by moving
230
            // the ChangeColumn action to another AlterTable
231
            ->unfold(new ActionSplitter(RenameColumn::class, ChangeColumn::class, function (RenameColumn $a, ChangeColumn $b) {
232
                return $a->getNewName() == $b->getColumnName();
233
            }))
234
            ->toList();
235
236
        $this->constraints = collection($this->constraints)
237
            ->map(function (AlterTable $alter) {
238
                // Dropping indexes used by foreign keys is a conflict, but one we can resolve
239
                // if the foreign key is also scheduled to be dropped. If we can find such a a case,
240
                // we force the execution of the index drop after the foreign key is dropped.
241
                return $this->remapContraintAndIndexConflicts($alter);
242
            })
243
            // Changing constraint properties sometimes require dropping it and then
244
            // creating it again with the new stuff. Unfortunately, we have already bundled
245
            // everything together in as few AlterTable statements as we could, so we need to
246
            // resolve this conflict manually
247
            ->unfold(new ActionSplitter(DropForeignKey::class, AddForeignKey::class, function (DropForeignKey $a, AddForeignKey $b) {
248
                return $a->getForeignKey()->getColumns() === $b->getForeignKey()->getColumns();
249
            }))
250
            ->toList();
251
    }
252
253
    /**
254
     * Deletes all actions related to the given table and keeps the
255
     * rest
256
     *
257
     * @param Table $table The table to find in the list of actions
258
     * @param AlterTable[] $actions The actions to transform
259
     * @return AlterTable[] The list of actions without actions for the given table
260
     */
261
    protected function forgetTable(Table $table, $actions)
262
    {
263
        $result = [];
264
        foreach ($actions as $action) {
265
            if ($action->getTable()->getName() === $table->getName()) {
266
                continue;
267
            }
268
            $result[] = $action;
269
        }
270
271
        return $result;
272
    }
273
274
    /**
275
     * Finds all DropForeignKey actions in an AlterTable and moves
276
     * all conflicting DropIndex action in `$this->indexes` into the
277
     * given AlterTable.
278
     *
279
     * @param AlterTable $alter The collection of actions to inspect
280
     * @return AlterTable The updated AlterTable object. This function
281
     * has the side effect of changing the `$this->indexes` property.
282
     */
283
    protected function remapContraintAndIndexConflicts(AlterTable $alter)
284
    {
285
        $newAlter = new AlterTable($alter->getTable());
286
        collection($alter->getActions())
287
            ->unfold(function ($action) {
288
                if (!$action instanceof DropForeignKey) {
289
                    return [$action];
290
                }
291
292
                list($this->indexes, $dropIndexActions) = $this->forgetDropIndex(
293
                    $action->getTable(),
294
                    $action->getForeignKey()->getColumns(),
295
                    $this->indexes
296
                );
297
298
                list($this->columnRemoves, $removeColumnActions) = $this->forgetRemoveColumn(
299
                    $action->getTable(),
300
                    $action->getForeignKey()->getColumns(),
301
                    $this->columnRemoves
302
                );
303
304
                $return = [$action];
305
                if (!empty($dropIndexActions)) {
306
                    $return = array_merge($return, $dropIndexActions);
307
                }
308
309
                if (!empty($removeColumnActions)) {
310
                    $return = array_merge($return, $removeColumnActions);
311
                }
312
313
                return $return;
314
            })
315
            ->each(function ($action) use ($newAlter) {
316
                $newAlter->addAction($action);
317
            });
318
319
        return $newAlter;
320
    }
321
322
    /**
323
     * Deletes any DropIndex actions for the given table and exact columns
324
     *
325
     * @param Table $table The table to find in the list of actions
326
     * @param string[] $columns The column names to match
327
     * @param AlterTable[] $actions The actions to transform
328
     * @return array A tuple containing the list of actions without actions for dropping the index
329
     * and a list of drop index actions that were removed.
330
     */
331 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...
332
    {
333
        $dropIndexActions = new ArrayObject();
334
        $indexes = collection($actions)
335
            ->map(function ($alter) use ($table, $columns, $dropIndexActions) {
336
                if ($alter->getTable()->getName() !== $table->getName()) {
337
                    return $alter;
338
                }
339
340
                $newAlter = new AlterTable($table);
341
                collection($alter->getActions())
342
                    ->map(function ($action) use ($columns) {
343
                        if (!$action instanceof DropIndex) {
344
                            return [$action, null];
345
                        }
346
                        if ($action->getIndex()->getColumns() === $columns) {
347
                            return [null, $action];
348
                        }
349
350
                        return [$action, null];
351
                    })
352
                    ->each(function ($tuple) use ($newAlter, $dropIndexActions) {
353
                        list($action, $dropIndex) = $tuple;
354
                        if ($action) {
355
                            $newAlter->addAction($action);
356
                        }
357
                        if ($dropIndex) {
358
                            $dropIndexActions->append($dropIndex);
359
                        }
360
                    });
361
362
                return $newAlter;
363
            })
364
            ->toArray();
365
366
        return [$indexes, $dropIndexActions->getArrayCopy()];
367
    }
368
369
    /**
370
     * Deletes any RemoveColumn actions for the given table and exact columns
371
     *
372
     * @param Table $table The table to find in the list of actions
373
     * @param string[] $columns The column names to match
374
     * @param AlterTable[] $actions The actions to transform
375
     * @return array A tuple containing the list of actions without actions for removing the column
376
     * and a list of remove column actions that were removed.
377
     */
378 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...
379
    {
380
        $removeColumnActions = new ArrayObject();
381
        $indexes = collection($actions)
382
            ->map(function ($alter) use ($table, $columns, $removeColumnActions) {
383
                if ($alter->getTable()->getName() !== $table->getName()) {
384
                    return $alter;
385
                }
386
387
                $newAlter = new AlterTable($table);
388
                collection($alter->getActions())
389
                    ->map(function ($action) use ($columns) {
390
                        if (!$action instanceof RemoveColumn) {
391
                            return [$action, null];
392
                        }
393
                        if (in_array($action->getColumn(), $columns)) {
394
                            return [null, $action];
395
                        }
396
397
                        return [$action, null];
398
                    })
399
                    ->each(function ($tuple) use ($newAlter, $removeColumnActions) {
400
                        list($action, $removeColumn) = $tuple;
401
                        if ($action) {
402
                            $newAlter->addAction($action);
403
                        }
404
                        if ($removeColumn) {
405
                            $removeColumnActions->append($removeColumn);
406
                        }
407
                    });
408
409
                return $newAlter;
410
            })
411
            ->toArray();
412
413
        return [$indexes, $removeColumnActions->getArrayCopy()];
414
    }
415
416
    /**
417
     * Collects all table creation actions from the given intent
418
     *
419
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
420
     * @return void
421
     */
422
    protected function gatherCreates($actions)
423
    {
424
        collection($actions)
425
            ->filter(function ($action) {
426
                return $action instanceof CreateTable;
427
            })
428
            ->map(function ($action) {
429
                return [$action->getTable()->getName(), new NewTable($action->getTable())];
430
            })
431
            ->each(function ($step) {
432
                $this->tableCreates[$step[0]] = $step[1];
433
            });
434
435
        collection($actions)
436
            ->filter(function ($action) {
437
                return $action instanceof AddColumn
438
                    || $action instanceof AddIndex;
439
            })
440
            ->filter(function ($action) {
441
                return isset($this->tableCreates[$action->getTable()->getName()]);
442
            })
443
            ->each(function ($action) {
444
                $table = $action->getTable();
445
446
                if ($action instanceof AddColumn) {
447
                    $this->tableCreates[$table->getName()]->addColumn($action->getColumn());
448
                }
449
450
                if ($action instanceof AddIndex) {
451
                    $this->tableCreates[$table->getName()]->addIndex($action->getIndex());
452
                }
453
            });
454
    }
455
456
    /**
457
     * Collects all alter table actions from the given intent
458
     *
459
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
460
     * @return void
461
     */
462
    protected function gatherUpdates($actions)
463
    {
464
        collection($actions)
465
            ->filter(function ($action) {
466
                return $action instanceof AddColumn
467
                    || $action instanceof ChangeColumn
468
                    || $action instanceof RemoveColumn
469
                    || $action instanceof RenameColumn;
470
            })
471
            // We are only concerned with table changes
472
            ->reject(function ($action) {
473
                return isset($this->tableCreates[$action->getTable()->getName()]);
474
            })
475
            ->each(function ($action) {
476
                $table = $action->getTable();
477
                $name = $table->getName();
478
479
                if ($action instanceof RemoveColumn) {
480
                    if (!isset($this->columnRemoves[$name])) {
481
                        $this->columnRemoves[$name] = new AlterTable($table);
482
                    }
483
                    $this->columnRemoves[$name]->addAction($action);
484
                } else {
485
                    if (!isset($this->tableUpdates[$name])) {
486
                        $this->tableUpdates[$name] = new AlterTable($table);
487
                    }
488
                    $this->tableUpdates[$name]->addAction($action);
489
                }
490
            });
491
    }
492
493
    /**
494
     * Collects all alter table drop and renames from the given intent
495
     *
496
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
497
     * @return void
498
     */
499
    protected function gatherTableMoves($actions)
500
    {
501
        collection($actions)
502
            ->filter(function ($action) {
503
                return $action instanceof DropTable
504
                    || $action instanceof RenameTable
505
                    || $action instanceof ChangePrimaryKey
506
                    || $action instanceof ChangeComment;
507
            })
508 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...
509
                $table = $action->getTable();
510
                $name = $table->getName();
511
512
                if (!isset($this->tableMoves[$name])) {
513
                    $this->tableMoves[$name] = new AlterTable($table);
514
                }
515
516
                $this->tableMoves[$name]->addAction($action);
517
            });
518
    }
519
520
    /**
521
     * Collects all index creation and drops from the given intent
522
     *
523
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
524
     * @return void
525
     */
526
    protected function gatherIndexes($actions)
527
    {
528
        collection($actions)
529
            ->filter(function ($action) {
530
                return $action instanceof AddIndex
531
                    || $action instanceof DropIndex;
532
            })
533
            ->reject(function ($action) {
534
                // Indexes for new tables are created inline
535
                // so we don't wan't them here too
536
                return isset($this->tableCreates[$action->getTable()->getName()]);
537
            })
538 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...
539
                $table = $action->getTable();
540
                $name = $table->getName();
541
542
                if (!isset($this->indexes[$name])) {
543
                    $this->indexes[$name] = new AlterTable($table);
544
                }
545
546
                $this->indexes[$name]->addAction($action);
547
            });
548
    }
549
550
    /**
551
     * Collects all foreign key creation and drops from the given intent
552
     *
553
     * @param \Phinx\Db\Action\Action[] $actions The actions to parse
554
     * @return void
555
     */
556
    protected function gatherConstraints($actions)
557
    {
558
        collection($actions)
559
            ->filter(function ($action) {
560
                return $action instanceof AddForeignKey
561
                    || $action instanceof DropForeignKey;
562
            })
563 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...
564
                $table = $action->getTable();
565
                $name = $table->getName();
566
567
                if (!isset($this->constraints[$name])) {
568
                    $this->constraints[$name] = new AlterTable($table);
569
                }
570
571
                $this->constraints[$name]->addAction($action);
572
            });
573
    }
574
}
575