1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
/** |
4
|
|
|
* MIT License |
5
|
|
|
* For full license information, please view the LICENSE file that was distributed with this source code. |
6
|
|
|
*/ |
7
|
|
|
|
8
|
|
|
namespace Phinx\Db\Plan; |
9
|
|
|
|
10
|
|
|
use ArrayObject; |
11
|
|
|
use Phinx\Db\Action\AddColumn; |
12
|
|
|
use Phinx\Db\Action\AddForeignKey; |
13
|
|
|
use Phinx\Db\Action\AddIndex; |
14
|
|
|
use Phinx\Db\Action\ChangeColumn; |
15
|
|
|
use Phinx\Db\Action\ChangeComment; |
16
|
|
|
use Phinx\Db\Action\ChangePrimaryKey; |
17
|
|
|
use Phinx\Db\Action\CreateTable; |
18
|
|
|
use Phinx\Db\Action\DropForeignKey; |
19
|
|
|
use Phinx\Db\Action\DropIndex; |
20
|
|
|
use Phinx\Db\Action\DropTable; |
21
|
|
|
use Phinx\Db\Action\RemoveColumn; |
22
|
|
|
use Phinx\Db\Action\RenameColumn; |
23
|
|
|
use Phinx\Db\Action\RenameTable; |
24
|
|
|
use Phinx\Db\Adapter\AdapterInterface; |
25
|
|
|
use Phinx\Db\Plan\Solver\ActionSplitter; |
26
|
|
|
use Phinx\Db\Table\Table; |
27
|
|
|
|
28
|
|
|
/** |
29
|
|
|
* A Plan takes an Intent and transforms int into a sequence of |
30
|
|
|
* instructions that can be correctly executed by an AdapterInterface. |
31
|
|
|
* |
32
|
|
|
* The main focus of Plan is to arrange the actions in the most efficient |
33
|
|
|
* way possible for the database. |
34
|
|
|
*/ |
35
|
|
|
class Plan |
36
|
|
|
{ |
37
|
|
|
/** |
38
|
|
|
* List of tables to be created |
39
|
|
|
* |
40
|
|
|
* @var \Phinx\Db\Plan\NewTable[] |
41
|
|
|
*/ |
42
|
|
|
protected $tableCreates = []; |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* List of table updates |
46
|
|
|
* |
47
|
|
|
* @var \Phinx\Db\Plan\AlterTable[] |
48
|
|
|
*/ |
49
|
|
|
protected $tableUpdates = []; |
50
|
|
|
|
51
|
|
|
/** |
52
|
|
|
* List of table removals or renames |
53
|
|
|
* |
54
|
|
|
* @var \Phinx\Db\Plan\AlterTable[] |
55
|
|
|
*/ |
56
|
|
|
protected $tableMoves = []; |
57
|
|
|
|
58
|
|
|
/** |
59
|
|
|
* List of index additions or removals |
60
|
|
|
* |
61
|
|
|
* @var \Phinx\Db\Plan\AlterTable[] |
62
|
|
|
*/ |
63
|
|
|
protected $indexes = []; |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* List of constraint additions or removals |
67
|
|
|
* |
68
|
|
|
* @var \Phinx\Db\Plan\AlterTable[] |
69
|
|
|
*/ |
70
|
|
|
protected $constraints = []; |
71
|
|
|
|
72
|
|
|
/** |
73
|
|
|
* List of dropped columns |
74
|
|
|
* |
75
|
|
|
* @var \Phinx\Db\Plan\AlterTable[] |
76
|
|
|
*/ |
77
|
|
|
protected $columnRemoves = []; |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* Constructor |
81
|
|
|
* |
82
|
|
|
* @param \Phinx\Db\Plan\Intent $intent All the actions that should be executed |
83
|
|
|
*/ |
84
|
|
|
public function __construct(Intent $intent) |
85
|
|
|
{ |
86
|
|
|
$this->createPlan($intent->getActions()); |
87
|
|
|
} |
88
|
|
|
|
89
|
|
|
/** |
90
|
|
|
* Parses the given Intent and creates the separate steps to execute |
91
|
|
|
* |
92
|
|
|
* @param \Phinx\Db\Action\Action[] $actions The actions to use for the plan |
93
|
|
|
* |
94
|
|
|
* @return void |
95
|
|
|
*/ |
96
|
|
|
protected function createPlan($actions) |
97
|
|
|
{ |
98
|
|
|
$this->gatherCreates($actions); |
99
|
|
|
$this->gatherUpdates($actions); |
100
|
|
|
$this->gatherTableMoves($actions); |
101
|
|
|
$this->gatherIndexes($actions); |
102
|
|
|
$this->gatherConstraints($actions); |
103
|
|
|
$this->resolveConflicts(); |
104
|
|
|
} |
105
|
|
|
|
106
|
|
|
/** |
107
|
|
|
* Returns a nested list of all the steps to execute |
108
|
|
|
* |
109
|
|
|
* @return \Phinx\Db\Plan\AlterTable[][] |
110
|
|
|
*/ |
111
|
|
View Code Duplication |
protected function updatesSequence() |
|
|
|
|
112
|
|
|
{ |
113
|
|
|
return [ |
114
|
|
|
$this->tableUpdates, |
115
|
|
|
$this->constraints, |
116
|
|
|
$this->indexes, |
117
|
|
|
$this->columnRemoves, |
118
|
|
|
$this->tableMoves, |
119
|
|
|
]; |
120
|
|
|
} |
121
|
|
|
|
122
|
|
|
/** |
123
|
|
|
* Returns a nested list of all the steps to execute in inverse order |
124
|
|
|
* |
125
|
|
|
* @return \Phinx\Db\Plan\AlterTable[][] |
126
|
|
|
*/ |
127
|
|
View Code Duplication |
protected function inverseUpdatesSequence() |
|
|
|
|
128
|
|
|
{ |
129
|
|
|
return [ |
130
|
|
|
$this->constraints, |
131
|
|
|
$this->tableMoves, |
132
|
|
|
$this->indexes, |
133
|
|
|
$this->columnRemoves, |
134
|
|
|
$this->tableUpdates, |
135
|
|
|
]; |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
/** |
139
|
|
|
* Executes this plan using the given AdapterInterface |
140
|
|
|
* |
141
|
|
|
* @param \Phinx\Db\Adapter\AdapterInterface $executor The executor object for the plan |
142
|
|
|
* |
143
|
|
|
* @return void |
144
|
|
|
*/ |
145
|
|
View Code Duplication |
public function execute(AdapterInterface $executor) |
|
|
|
|
146
|
|
|
{ |
147
|
|
|
foreach ($this->tableCreates as $newTable) { |
148
|
|
|
$executor->createTable($newTable->getTable(), $newTable->getColumns(), $newTable->getIndexes()); |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
foreach ($this->updatesSequence() as $updates) { |
152
|
|
|
foreach ($updates as $update) { |
153
|
|
|
$executor->executeActions($update->getTable(), $update->getActions()); |
154
|
|
|
} |
155
|
|
|
} |
156
|
|
|
} |
157
|
|
|
|
158
|
|
|
/** |
159
|
|
|
* Executes the inverse plan (rollback the actions) with the given AdapterInterface:w |
160
|
|
|
* |
161
|
|
|
* @param \Phinx\Db\Adapter\AdapterInterface $executor The executor object for the plan |
162
|
|
|
* |
163
|
|
|
* @return void |
164
|
|
|
*/ |
165
|
|
View Code Duplication |
public function executeInverse(AdapterInterface $executor) |
|
|
|
|
166
|
|
|
{ |
167
|
|
|
foreach ($this->inverseUpdatesSequence() as $updates) { |
168
|
|
|
foreach ($updates as $update) { |
169
|
|
|
$executor->executeActions($update->getTable(), $update->getActions()); |
170
|
|
|
} |
171
|
|
|
} |
172
|
|
|
|
173
|
|
|
foreach ($this->tableCreates as $newTable) { |
174
|
|
|
$executor->createTable($newTable->getTable(), $newTable->getColumns(), $newTable->getIndexes()); |
175
|
|
|
} |
176
|
|
|
} |
177
|
|
|
|
178
|
|
|
/** |
179
|
|
|
* Deletes certain actions from the plan if they are found to be conflicting or redundant. |
180
|
|
|
* |
181
|
|
|
* @return void |
182
|
|
|
*/ |
183
|
|
|
protected function resolveConflicts() |
184
|
|
|
{ |
185
|
|
|
foreach ($this->tableMoves as $alterTable) { |
186
|
|
|
foreach ($alterTable->getActions() as $action) { |
187
|
|
|
if ($action instanceof DropTable) { |
188
|
|
|
$this->tableUpdates = $this->forgetTable($action->getTable(), $this->tableUpdates); |
189
|
|
|
$this->constraints = $this->forgetTable($action->getTable(), $this->constraints); |
190
|
|
|
$this->indexes = $this->forgetTable($action->getTable(), $this->indexes); |
191
|
|
|
$this->columnRemoves = $this->forgetTable($action->getTable(), $this->columnRemoves); |
192
|
|
|
} |
193
|
|
|
} |
194
|
|
|
} |
195
|
|
|
|
196
|
|
|
// Columns that are dropped will automatically cause the indexes to be dropped as well |
197
|
|
|
foreach ($this->columnRemoves as $columnRemove) { |
198
|
|
|
foreach ($columnRemove->getActions() as $action) { |
199
|
|
|
if ($action instanceof RemoveColumn) { |
200
|
|
|
list($this->indexes) = $this->forgetDropIndex( |
201
|
|
|
$action->getTable(), |
202
|
|
|
[$action->getColumn()->getName()], |
203
|
|
|
$this->indexes |
204
|
|
|
); |
205
|
|
|
} |
206
|
|
|
} |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
// Renaming a column and then changing the renamed column is something people do, |
210
|
|
|
// but it is a conflicting action. Luckily solving the conflict can be done by moving |
211
|
|
|
// the ChangeColumn action to another AlterTable. |
212
|
|
|
$splitter = new ActionSplitter( |
213
|
|
|
RenameColumn::class, |
214
|
|
|
ChangeColumn::class, |
215
|
|
|
function (RenameColumn $a, ChangeColumn $b) { |
216
|
|
|
return $a->getNewName() === $b->getColumnName(); |
217
|
|
|
} |
218
|
|
|
); |
219
|
|
|
$tableUpdates = []; |
220
|
|
|
foreach ($this->tableUpdates as $update) { |
221
|
|
|
$tableUpdates = array_merge($tableUpdates, $splitter($update)); |
222
|
|
|
} |
223
|
|
|
$this->tableUpdates = $tableUpdates; |
224
|
|
|
|
225
|
|
|
// Dropping indexes used by foreign keys is a conflict, but one we can resolve |
226
|
|
|
// if the foreign key is also scheduled to be dropped. If we can find such a a case, |
227
|
|
|
// we force the execution of the index drop after the foreign key is dropped. |
228
|
|
|
// Changing constraint properties sometimes require dropping it and then |
229
|
|
|
// creating it again with the new stuff. Unfortunately, we have already bundled |
230
|
|
|
// everything together in as few AlterTable statements as we could, so we need to |
231
|
|
|
// resolve this conflict manually. |
232
|
|
|
$splitter = new ActionSplitter( |
233
|
|
|
DropForeignKey::class, |
234
|
|
|
AddForeignKey::class, |
235
|
|
|
function (DropForeignKey $a, AddForeignKey $b) { |
236
|
|
|
return $a->getForeignKey()->getColumns() === $b->getForeignKey()->getColumns(); |
237
|
|
|
} |
238
|
|
|
); |
239
|
|
|
$constraints = []; |
240
|
|
|
foreach ($this->constraints as $constraint) { |
241
|
|
|
$constraints = array_merge( |
242
|
|
|
$constraints, |
243
|
|
|
$splitter($this->remapContraintAndIndexConflicts($constraint)) |
244
|
|
|
); |
245
|
|
|
} |
246
|
|
|
$this->constraints = $constraints; |
247
|
|
|
} |
248
|
|
|
|
249
|
|
|
/** |
250
|
|
|
* Deletes all actions related to the given table and keeps the |
251
|
|
|
* rest |
252
|
|
|
* |
253
|
|
|
* @param \Phinx\Db\Table\Table $table The table to find in the list of actions |
254
|
|
|
* @param \Phinx\Db\Plan\AlterTable[] $actions The actions to transform |
255
|
|
|
* |
256
|
|
|
* @return \Phinx\Db\Plan\AlterTable[] The list of actions without actions for the given table |
257
|
|
|
*/ |
258
|
|
|
protected function forgetTable(Table $table, $actions) |
259
|
|
|
{ |
260
|
|
|
$result = []; |
261
|
|
|
foreach ($actions as $action) { |
262
|
|
|
if ($action->getTable()->getName() === $table->getName()) { |
263
|
|
|
continue; |
264
|
|
|
} |
265
|
|
|
$result[] = $action; |
266
|
|
|
} |
267
|
|
|
|
268
|
|
|
return $result; |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
/** |
272
|
|
|
* Finds all DropForeignKey actions in an AlterTable and moves |
273
|
|
|
* all conflicting DropIndex action in `$this->indexes` into the |
274
|
|
|
* given AlterTable. |
275
|
|
|
* |
276
|
|
|
* @param \Phinx\Db\Plan\AlterTable $alter The collection of actions to inspect |
277
|
|
|
* |
278
|
|
|
* @return \Phinx\Db\Plan\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
|
|
|
|
285
|
|
|
foreach ($alter->getActions() as $action) { |
286
|
|
|
$newAlter->addAction($action); |
287
|
|
|
if ($action instanceof DropForeignKey) { |
288
|
|
|
list($this->indexes, $dropIndexActions) = $this->forgetDropIndex( |
289
|
|
|
$action->getTable(), |
290
|
|
|
$action->getForeignKey()->getColumns(), |
291
|
|
|
$this->indexes |
292
|
|
|
); |
293
|
|
|
foreach ($dropIndexActions as $dropIndexAction) { |
294
|
|
|
$newAlter->addAction($dropIndexAction); |
295
|
|
|
} |
296
|
|
|
} |
297
|
|
|
} |
298
|
|
|
|
299
|
|
|
return $newAlter; |
300
|
|
|
} |
301
|
|
|
|
302
|
|
|
/** |
303
|
|
|
* Deletes any DropIndex actions for the given table and exact columns |
304
|
|
|
* |
305
|
|
|
* @param \Phinx\Db\Table\Table $table The table to find in the list of actions |
306
|
|
|
* @param string[] $columns The column names to match |
307
|
|
|
* @param \Phinx\Db\Plan\AlterTable[] $actions The actions to transform |
308
|
|
|
* |
309
|
|
|
* @return array A tuple containing the list of actions without actions for dropping the index |
310
|
|
|
* and a list of drop index actions that were removed. |
311
|
|
|
*/ |
312
|
|
View Code Duplication |
protected function forgetDropIndex(Table $table, array $columns, array $actions) |
|
|
|
|
313
|
|
|
{ |
314
|
|
|
$dropIndexActions = new ArrayObject(); |
315
|
|
|
$indexes = array_map(function ($alter) use ($table, $columns, $dropIndexActions) { |
316
|
|
|
if ($alter->getTable()->getName() !== $table->getName()) { |
317
|
|
|
return $alter; |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
$newAlter = new AlterTable($table); |
321
|
|
|
foreach ($alter->getActions() as $action) { |
322
|
|
|
if ($action instanceof DropIndex && $action->getIndex()->getColumns() === $columns) { |
323
|
|
|
$dropIndexActions->append($action); |
324
|
|
|
} else { |
325
|
|
|
$newAlter->addAction($action); |
326
|
|
|
} |
327
|
|
|
} |
328
|
|
|
|
329
|
|
|
return $newAlter; |
330
|
|
|
}, $actions); |
331
|
|
|
|
332
|
|
|
return [$indexes, $dropIndexActions->getArrayCopy()]; |
333
|
|
|
} |
334
|
|
|
|
335
|
|
|
/** |
336
|
|
|
* Deletes any RemoveColumn actions for the given table and exact columns |
337
|
|
|
* |
338
|
|
|
* @param \Phinx\Db\Table\Table $table The table to find in the list of actions |
339
|
|
|
* @param string[] $columns The column names to match |
340
|
|
|
* @param \Phinx\Db\Plan\AlterTable[] $actions The actions to transform |
341
|
|
|
* |
342
|
|
|
* @return array A tuple containing the list of actions without actions for removing the column |
343
|
|
|
* and a list of remove column actions that were removed. |
344
|
|
|
*/ |
345
|
|
View Code Duplication |
protected function forgetRemoveColumn(Table $table, array $columns, array $actions) |
|
|
|
|
346
|
|
|
{ |
347
|
|
|
$removeColumnActions = new ArrayObject(); |
348
|
|
|
$indexes = array_map(function ($alter) use ($table, $columns, $removeColumnActions) { |
349
|
|
|
if ($alter->getTable()->getName() !== $table->getName()) { |
350
|
|
|
return $alter; |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
$newAlter = new AlterTable($table); |
354
|
|
|
foreach ($alter->getActions() as $action) { |
355
|
|
|
if ($action instanceof RemoveColumn && in_array($action->getColumn()->getName(), $columns, true)) { |
356
|
|
|
$removeColumnActions->append($action); |
357
|
|
|
} else { |
358
|
|
|
$newAlter->addAction($action); |
359
|
|
|
} |
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
return $newAlter; |
363
|
|
|
}, $actions); |
364
|
|
|
|
365
|
|
|
return [$indexes, $removeColumnActions->getArrayCopy()]; |
366
|
|
|
} |
367
|
|
|
|
368
|
|
|
/** |
369
|
|
|
* Collects all table creation actions from the given intent |
370
|
|
|
* |
371
|
|
|
* @param \Phinx\Db\Action\Action[] $actions The actions to parse |
372
|
|
|
* |
373
|
|
|
* @return void |
374
|
|
|
*/ |
375
|
|
|
protected function gatherCreates($actions) |
376
|
|
|
{ |
377
|
|
|
foreach ($actions as $action) { |
378
|
|
|
if ($action instanceof CreateTable) { |
379
|
|
|
$this->tableCreates[$action->getTable()->getName()] = new NewTable($action->getTable()); |
380
|
|
|
} |
381
|
|
|
} |
382
|
|
|
|
383
|
|
|
foreach ($actions as $action) { |
384
|
|
|
if ( |
385
|
|
|
($action instanceof AddColumn || $action instanceof AddIndex) |
386
|
|
|
&& isset($this->tableCreates[$action->getTable()->getName()]) |
387
|
|
|
) { |
388
|
|
|
$table = $action->getTable(); |
389
|
|
|
|
390
|
|
|
if ($action instanceof AddColumn) { |
391
|
|
|
$this->tableCreates[$table->getName()]->addColumn($action->getColumn()); |
392
|
|
|
} |
393
|
|
|
|
394
|
|
|
if ($action instanceof AddIndex) { |
395
|
|
|
$this->tableCreates[$table->getName()]->addIndex($action->getIndex()); |
396
|
|
|
} |
397
|
|
|
} |
398
|
|
|
} |
399
|
|
|
} |
400
|
|
|
|
401
|
|
|
/** |
402
|
|
|
* Collects all alter table actions from the given intent |
403
|
|
|
* |
404
|
|
|
* @param \Phinx\Db\Action\Action[] $actions The actions to parse |
405
|
|
|
* |
406
|
|
|
* @return void |
407
|
|
|
*/ |
408
|
|
|
protected function gatherUpdates($actions) |
409
|
|
|
{ |
410
|
|
|
foreach ($actions as $action) { |
411
|
|
|
if ( |
412
|
|
|
!($action instanceof AddColumn) |
413
|
|
|
&& !($action instanceof ChangeColumn) |
414
|
|
|
&& !($action instanceof RemoveColumn) |
415
|
|
|
&& !($action instanceof RenameColumn) |
416
|
|
|
) { |
417
|
|
|
continue; |
418
|
|
|
} elseif (isset($this->tableCreates[$action->getTable()->getName()])) { |
419
|
|
|
continue; |
420
|
|
|
} |
421
|
|
|
$table = $action->getTable(); |
422
|
|
|
$name = $table->getName(); |
423
|
|
|
|
424
|
|
|
if ($action instanceof RemoveColumn) { |
425
|
|
|
if (!isset($this->columnRemoves[$name])) { |
426
|
|
|
$this->columnRemoves[$name] = new AlterTable($table); |
427
|
|
|
} |
428
|
|
|
$this->columnRemoves[$name]->addAction($action); |
429
|
|
|
} else { |
430
|
|
|
if (!isset($this->tableUpdates[$name])) { |
431
|
|
|
$this->tableUpdates[$name] = new AlterTable($table); |
432
|
|
|
} |
433
|
|
|
$this->tableUpdates[$name]->addAction($action); |
434
|
|
|
} |
435
|
|
|
} |
436
|
|
|
} |
437
|
|
|
|
438
|
|
|
/** |
439
|
|
|
* Collects all alter table drop and renames from the given intent |
440
|
|
|
* |
441
|
|
|
* @param \Phinx\Db\Action\Action[] $actions The actions to parse |
442
|
|
|
* @return void |
443
|
|
|
*/ |
444
|
|
|
protected function gatherTableMoves($actions) |
445
|
|
|
{ |
446
|
|
|
foreach ($actions as $action) { |
447
|
|
|
if ( |
448
|
|
|
!($action instanceof DropTable) |
449
|
|
|
&& !($action instanceof RenameTable) |
450
|
|
|
&& !($action instanceof ChangePrimaryKey) |
451
|
|
|
&& !($action instanceof ChangeComment) |
452
|
|
|
) { |
453
|
|
|
continue; |
454
|
|
|
} |
455
|
|
|
$table = $action->getTable(); |
456
|
|
|
$name = $table->getName(); |
457
|
|
|
|
458
|
|
|
if (!isset($this->tableMoves[$name])) { |
459
|
|
|
$this->tableMoves[$name] = new AlterTable($table); |
460
|
|
|
} |
461
|
|
|
|
462
|
|
|
$this->tableMoves[$name]->addAction($action); |
463
|
|
|
} |
464
|
|
|
} |
465
|
|
|
|
466
|
|
|
/** |
467
|
|
|
* Collects all index creation and drops from the given intent |
468
|
|
|
* |
469
|
|
|
* @param \Phinx\Db\Action\Action[] $actions The actions to parse |
470
|
|
|
* |
471
|
|
|
* @return void |
472
|
|
|
*/ |
473
|
|
|
protected function gatherIndexes($actions) |
474
|
|
|
{ |
475
|
|
|
foreach ($actions as $action) { |
476
|
|
|
if (!($action instanceof AddIndex) && !($action instanceof DropIndex)) { |
477
|
|
|
continue; |
478
|
|
|
} elseif (isset($this->tableCreates[$action->getTable()->getName()])) { |
479
|
|
|
continue; |
480
|
|
|
} |
481
|
|
|
|
482
|
|
|
$table = $action->getTable(); |
483
|
|
|
$name = $table->getName(); |
484
|
|
|
|
485
|
|
|
if (!isset($this->indexes[$name])) { |
486
|
|
|
$this->indexes[$name] = new AlterTable($table); |
487
|
|
|
} |
488
|
|
|
|
489
|
|
|
$this->indexes[$name]->addAction($action); |
490
|
|
|
} |
491
|
|
|
} |
492
|
|
|
|
493
|
|
|
/** |
494
|
|
|
* Collects all foreign key creation and drops from the given intent |
495
|
|
|
* |
496
|
|
|
* @param \Phinx\Db\Action\Action[] $actions The actions to parse |
497
|
|
|
* |
498
|
|
|
* @return void |
499
|
|
|
*/ |
500
|
|
|
protected function gatherConstraints($actions) |
501
|
|
|
{ |
502
|
|
|
foreach ($actions as $action) { |
503
|
|
|
if (!($action instanceof AddForeignKey || $action instanceof DropForeignKey)) { |
504
|
|
|
continue; |
505
|
|
|
} |
506
|
|
|
$table = $action->getTable(); |
507
|
|
|
$name = $table->getName(); |
508
|
|
|
|
509
|
|
|
if (!isset($this->constraints[$name])) { |
510
|
|
|
$this->constraints[$name] = new AlterTable($table); |
511
|
|
|
} |
512
|
|
|
|
513
|
|
|
$this->constraints[$name]->addAction($action); |
514
|
|
|
} |
515
|
|
|
} |
516
|
|
|
} |
517
|
|
|
|
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.