Completed
Pull Request — master (#1357)
by José
11:07
created

PdoAdapter::addForeignKey()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 9.4285
c 0
b 0
f 0
ccs 0
cts 0
cp 0
cc 1
eloc 3
nc 1
nop 2
crap 2
1
<?php
2
/**
3
 * Phinx
4
 *
5
 * (The MIT license)
6
 * Copyright (c) 2015 Rob Morgan
7
 *
8
 * Permission is hereby granted, free of charge, to any person obtaining a copy
9
 * of this software and associated * documentation files (the "Software"), to
10
 * deal in the Software without restriction, including without limitation the
11
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12
 * sell copies of the Software, and to permit persons to whom the Software is
13
 * furnished to do so, subject to the following conditions:
14
 *
15
 * The above copyright notice and this permission notice shall be included in
16
 * all copies or substantial portions of the Software.
17
 *
18
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24
 * IN THE SOFTWARE.
25
 *
26
 * @package    Phinx
27
 * @subpackage Phinx\Db\Adapter
28
 */
29
namespace Phinx\Db\Adapter;
30
31
use BadMethodCallException;
32
use Phinx\Db\Action\AddColumn;
33
use Phinx\Db\Action\AddForeignKey;
34
use Phinx\Db\Action\AddIndex;
35
use Phinx\Db\Action\ChangeColumn;
36
use Phinx\Db\Action\DropForeignKey;
37
use Phinx\Db\Action\DropIndex;
38
use Phinx\Db\Action\DropTable;
39
use Phinx\Db\Action\RemoveColumn;
40
use Phinx\Db\Action\RenameColumn;
41
use Phinx\Db\Action\RenameTable;
42
use Phinx\Db\Table\Column;
43
use Phinx\Db\Table\ForeignKey;
44
use Phinx\Db\Table\Index;
45
use Phinx\Db\Table\Table;
46
use Phinx\Db\Util\AlterInstructions;
47
use Phinx\Migration\MigrationInterface;
48
use Symfony\Component\Console\Output\OutputInterface;
49
50
/**
51 287
 * Phinx PDO Adapter.
52
 *
53 287
 * @author Rob Morgan <[email protected]>
54
 */
55 287
abstract class PdoAdapter extends AbstractAdapter implements DirectActionInterface
56 3
{
57 3
    /**
58
     * @var \PDO|null
59 287
     */
60
    protected $connection;
61
62
    /**
63
     * Writes a message to stdout if vebose output is on
64
     *
65
     * @param string $message The message to show
66
     * @return void
67
     */
68 193
    protected function verboseLog($message)
69
    {
70 193
        if (!$this->isDryRunEnabled() &&
71
             $this->getOutput()->getVerbosity() < OutputInterface::VERBOSITY_VERY_VERBOSE) {
72
            return;
73 193
        }
74 191
75 191
        $this->getOutput()->writeln($message);
76 74
    }
77 74
78
    /**
79
     * {@inheritdoc}
80
     */
81
    public function setOptions(array $options)
82
    {
83
        parent::setOptions($options);
84
85
        if (isset($options['connection'])) {
86 74
            $this->setConnection($options['connection']);
87
        }
88
89
        return $this;
90
    }
91
92
    /**
93 193
     * Sets the database connection.
94
     *
95
     * @param \PDO $connection Connection
96
     * @return \Phinx\Db\Adapter\AdapterInterface
97
     */
98
    public function setConnection(\PDO $connection)
99
    {
100
        $this->connection = $connection;
101 191
102
        // Create the schema table if it doesn't already exist
103 191
        if (!$this->hasSchemaTable()) {
104 189
            $this->createSchemaTable();
105 189
        } else {
106 191
            $table = new \Phinx\Db\Table($this->getSchemaTableName(), [], $this);
107
            if (!$table->hasColumn('migration_name')) {
108
                $table
109
                    ->addColumn(
110
                        'migration_name',
111
                        'string',
112 1
                        ['limit' => 100, 'after' => 'version', 'default' => null, 'null' => true]
113
                    )
114 1
                    ->save();
115
            }
116
            if (!$table->hasColumn('breakpoint')) {
117
                $table
118
                    ->addColumn('breakpoint', 'boolean', ['default' => false])
119
                    ->save();
120
            }
121
        }
122
123
        return $this;
124
    }
125
126 218
    /**
127
     * Gets the database connection
128 218
     *
129 3
     * @return \PDO
130 3
     */
131
    public function getConnection()
132
    {
133 217
        if ($this->connection === null) {
134
            $this->connect();
135
        }
136
137
        return $this->connection;
138
    }
139
140
    /**
141
     * {@inheritdoc}
142 220
     */
143
    public function connect()
144 220
    {
145
    }
146
147
    /**
148
     * {@inheritdoc}
149
     */
150 151
    public function disconnect()
151
    {
152 151
    }
153 151
154
    /**
155
     * {@inheritdoc}
156
     */
157
    public function execute($sql)
158
    {
159 213
        $this->verboseLog($sql);
160
161 213
        if ($this->isDryRunEnabled()) {
162 213
            return 0;
163 213
        }
164 208
165 208
        return $this->getConnection()->exec($sql);
166 213
    }
167
168
    /**
169
     * Returns the Cake\Database connection object using the same underlying
170
     * PDO object as this connection.
171
     *
172 1
     * @return \Cake\Database\Connection
173
     */
174 1
    abstract public function getDecoratedConnection();
175 1
176 1
    /**
177 1
     * {@inheritdoc}
178
     */
179 1
    public function getQueryBuilder()
180 1
    {
181 1
        return $this->getDecoratedConnection()->newQuery();
182
    }
183 1
184 1
    /**
185 1
     * Executes a query and returns PDOStatement.
186
     *
187
     * @param string $sql SQL
188
     * @return \PDOStatement
189
     */
190 11
    public function query($sql)
191
    {
192 11
        return $this->getConnection()->query($sql);
193 11
    }
194 11
195 11
    /**
196
     * {@inheritdoc}
197 11
     */
198 11
    public function fetchRow($sql)
199 11
    {
200
        $result = $this->query($sql);
201 11
202 11
        return $result->fetch();
203 11
    }
204 11
205 11
    /**
206 11
     * {@inheritdoc}
207
     */
208 11
    public function fetchAll($sql)
209 11
    {
210
        $rows = [];
211 11
        $result = $this->query($sql);
212 11
        while ($row = $result->fetch()) {
213 11
            $rows[] = $row;
214
        }
215 11
216 11
        return $rows;
217 11
    }
218
219
    /**
220
     * {@inheritdoc}
221
     */
222 5
    public function insert(Table $table, $row)
223
    {
224 5
        $sql = sprintf(
225
            'INSERT INTO %s ',
226 5
            $this->quoteTableName($table->getName())
227
        );
228
        $columns = array_keys($row);
229
        $sql .= '(' . implode(', ', array_map([$this, 'quoteColumnName'], $columns)) . ')';
230
231
        if ($this->isDryRunEnabled()) {
232 8
            $sql .= ' VALUES (' . implode(', ', array_map([$this, 'quoteValue'], $row)) . ');';
233
            $this->output->writeln($sql);
234 8
        } else {
235
            $sql .= ' VALUES (' . implode(', ', array_fill(0, count($columns), '?')) . ')';
236 8
            $stmt = $this->getConnection()->prepare($sql);
237 8
            $stmt->execute(array_values($row));
238 6
        }
239 6
    }
240 2
241 1
    /**
242 1
     * Quotes a database value.
243 1
     *
244 1
     * @param mixed $value  The value to quote
245 8
     * @return mixed
246
     */
247 7
    private function quoteValue($value)
248 7
    {
249 7
        if (is_numeric($value)) {
250 7
            return $value;
251
        }
252 7
253
        if ($value === null) {
254
            return 'null';
255
        }
256
257
        return $this->getConnection()->quote($value);
258 5
    }
259
260 5
    /**
261
     * {@inheritdoc}
262 5
     */
263 5
    public function bulkinsert(Table $table, $rows)
264 5
    {
265 5
        $sql = sprintf(
266 5
            'INSERT INTO %s ',
267 5
            $this->quoteTableName($table->getName())
268 5
        );
269 5
        $current = current($rows);
270 5
        $keys = array_keys($current);
271 5
        $sql .= '(' . implode(', ', array_map([$this, 'quoteColumnName'], $keys)) . ') VALUES ';
272 5
273 5
        if ($this->isDryRunEnabled()) {
274 5
            $values = array_map(function ($row) {
275 5
                return '(' . implode(', ', array_map([$this, 'quoteValue'], $row)) . ')';
276
            }, $rows);
277 5
            $sql .= implode(', ', $values) . ';';
278 5
            $this->output->writeln($sql);
279
        } else {
280 3
            $count_keys = count($keys);
281 3
            $query = '(' . implode(', ', array_fill(0, $count_keys, '?')) . ')';
282 3
            $count_vars = count($rows);
283 3
            $queries = array_fill(0, $count_vars, $query);
284 3
            $sql .= implode(',', $queries);
285 3
            $stmt = $this->getConnection()->prepare($sql);
286
            $vals = [];
287 3
288
            foreach ($rows as $row) {
289
                foreach ($row as $v) {
290 5
                    $vals[] = $v;
291
                }
292
            }
293
294
            $stmt->execute($vals);
295
        }
296 1
    }
297
298 1
    /**
299 1
     * {@inheritdoc}
300 1
     */
301 1
    public function getVersions()
302 1
    {
303 1
        $rows = $this->getVersionLog();
304 1
305 1
        return array_keys($rows);
306 1
    }
307 1
308 1
    /**
309 1
     * {@inheritdoc}
310
     */
311 1
    public function getVersionLog()
312
    {
313
        $result = [];
314
315
        switch ($this->options['version_order']) {
316
            case \Phinx\Config\Config::VERSION_ORDER_CREATION_TIME:
317 1
                $orderBy = 'version ASC';
318
                break;
319 1
            case \Phinx\Config\Config::VERSION_ORDER_EXECUTION_TIME:
320 1
                $orderBy = 'start_time ASC, version ASC';
321 1
                break;
322 1
            default:
323 1
                throw new \RuntimeException('Invalid version_order configuration option');
324 1
        }
325 1
326 1
        $rows = $this->fetchAll(sprintf('SELECT * FROM %s ORDER BY %s', $this->getSchemaTableName(), $orderBy));
327 1
        foreach ($rows as $version) {
328
            $result[$version['version']] = $version;
329
        }
330
331
        return $result;
332
    }
333
334
    /**
335
     * {@inheritdoc}
336
     */
337
    public function migrated(MigrationInterface $migration, $direction, $startTime, $endTime)
338
    {
339
        if (strcasecmp($direction, MigrationInterface::UP) === 0) {
340
            // up
341
            $sql = sprintf(
342
                "INSERT INTO %s (%s, %s, %s, %s, %s) VALUES ('%s', '%s', '%s', '%s', %s);",
343
                $this->quoteTableName($this->getSchemaTableName()),
344
                $this->quoteColumnName('version'),
345
                $this->quoteColumnName('migration_name'),
346
                $this->quoteColumnName('start_time'),
347
                $this->quoteColumnName('end_time'),
348
                $this->quoteColumnName('breakpoint'),
349 208
                $migration->getVersion(),
350
                substr($migration->getName(), 0, 100),
351
                $startTime,
352 208
                $endTime,
353 208
                $this->castToBool(false)
354 208
            );
355 208
356 208
            $this->execute($sql);
357 208
        } else {
358 208
            // down
359 208
            $sql = sprintf(
360 208
                "DELETE FROM %s WHERE %s = '%s'",
361 208
                $this->quoteTableName($this->getSchemaTableName()),
362 208
                $this->quoteColumnName('version'),
363 208
                $migration->getVersion()
364 208
            );
365 208
366 208
            $this->execute($sql);
367 208
        }
368
369 208
        return $this;
370 208
    }
371 208
372 208
    /**
373 208
     * @inheritDoc
374
     */
375
    public function toggleBreakpoint(MigrationInterface $migration)
376
    {
377
        $this->query(
378
            sprintf(
379 121
                'UPDATE %1$s SET %2$s = CASE %2$s WHEN %3$s THEN %4$s ELSE %3$s END, %7$s = %7$s WHERE %5$s = \'%6$s\';',
380
                $this->getSchemaTableName(),
381 121
                $this->quoteColumnName('breakpoint'),
382
                $this->castToBool(true),
383
                $this->castToBool(false),
384
                $this->quoteColumnName('version'),
385
                $migration->getVersion(),
386
                $this->quoteColumnName('start_time')
387
            )
388
        );
389
390
        return $this;
391
    }
392
393
    /**
394
     * @inheritDoc
395
     */
396
    public function resetAllBreakpoints()
397
    {
398
        return $this->execute(
399
            sprintf(
400
                'UPDATE %1$s SET %2$s = %3$s, %4$s = %4$s WHERE %2$s <> %3$s;',
401
                $this->getSchemaTableName(),
402
                $this->quoteColumnName('breakpoint'),
403
                $this->castToBool(false),
404
                $this->quoteColumnName('start_time')
405
            )
406
        );
407
    }
408
409
    /**
410
     * {@inheritdoc}
411
     */
412
    public function createSchema($schemaName = 'public')
413
    {
414
        throw new BadMethodCallException('Creating a schema is not supported');
415
    }
416
417
    /**
418
     * {@inheritdoc}
419
     */
420
    public function dropSchema($name)
421
    {
422
        throw new BadMethodCallException('Dropping a schema is not supported');
423
    }
424
425
    /**
426
     * {@inheritdoc}
427
     */
428
    public function getColumnTypes()
429
    {
430
        return [
431
            'string',
432
            'char',
433
            'text',
434
            'integer',
435
            'biginteger',
436
            'bit',
437
            'float',
438
            'decimal',
439
            'datetime',
440
            'timestamp',
441
            'time',
442
            'date',
443
            'blob',
444
            'binary',
445
            'varbinary',
446
            'boolean',
447
            'uuid',
448
            // Geospatial data types
449
            'geometry',
450
            'point',
451
            'linestring',
452
            'polygon',
453
        ];
454
    }
455
456
    /**
457
     * {@inheritdoc}
458
     */
459
    public function castToBool($value)
460
    {
461
        return (bool)$value ? 1 : 0;
462
    }
463
464
    /**
465
     * Retrieve a database connection attribute
466
     * @see http://php.net/manual/en/pdo.getattribute.php
467
     *
468
     * @param int $attribute One of the PDO::ATTR_* constants
469
     * @return mixed
470
     */
471
    public function getAttribute($attribute)
472
    {
473
        return $this->connection->getAttribute($attribute);
474
    }
475
476
    /**
477
     * Get the defintion for a `DEFAULT` statement.
478
     *
479
     * @param  mixed $default Default value
480
     * @param string $columnType column type added
481
     * @return string
482
     */
483 View Code Duplication
    protected function getDefaultValueDefinition($default, $columnType = null)
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...
484
    {
485
        if (is_string($default) && 'CURRENT_TIMESTAMP' !== $default) {
486
            $default = $this->getConnection()->quote($default);
487
        } elseif (is_bool($default)) {
488
            $default = $this->castToBool($default);
489
        } elseif ($columnType === static::PHINX_TYPE_BOOLEAN) {
490
            $default = $this->castToBool((bool)$default);
491
        }
492
493
        return isset($default) ? " DEFAULT $default" : '';
494
    }
495
496
    /**
497
     * Executes all the ALTER TABLE instructions passed for the given table
498
     *
499
     * @param string $tableName The table name to use in the ALTER statement
500
     * @param AlterInstructions $instructions The object containing the alter sequence
501
     * @return void
502
     */
503
    protected function executeAlterSteps($tableName, AlterInstructions $instructions)
504
    {
505
        $alter = sprintf('ALTER TABLE %s %%s', $this->quoteTableName($tableName));
506
        $instructions->execute($alter, [$this, 'execute']);
507
    }
508
509
    /**
510
     * {@inheritdoc}
511
     */
512
    public function addColumn(Table $table, Column $column)
513
    {
514
        $instructions = $this->getAddColumnInstructions($table, $column);
515
        $this->executeAlterSteps($table, $instructions);
0 ignored issues
show
Documentation introduced by
$table is of type object<Phinx\Db\Table\Table>, but the function expects a string.

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...
516
    }
517
518
    /**
519
     * Returns the instrutions to add the specified column to a database table.
520
     *
521
     * @param \Phinx\Db\Table\Table $table Table
522
     * @param \Phinx\Db\Table\Column $column Column
523
     * @return AlterInstructions
524
     */
525
    abstract protected function getAddColumnInstructions(Table $table, Column $column);
526
527
    /**
528
     * {@inheritdoc}
529
     */
530
    public function renameColumn($tableName, $columnName, $newColumnName)
531
    {
532
        $instructions = $this->getRenameColumnInstructions($tableName, $columnName, $newColumnName);
533
        $this->executeAlterSteps($tableName, $instructions);
534
    }
535
536
    /**
537
     * Returns the instructions to rename the specified column.
538
     *
539
     * @param string $tableName Table Name
540
     * @param string $columnName Column Name
541
     * @param string $newColumnName New Column Name
542
     * @return AlterInstructions:w
0 ignored issues
show
Documentation introduced by
The doc-type AlterInstructions:w could not be parsed: Unknown type name "AlterInstructions:w" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
543
     *
544
     */
545
    abstract protected function getRenameColumnInstructions($tableName, $columnName, $newColumnName);
546
547
    /**
548
     * {@inheritdoc}
549
     */
550
    public function changeColumn($tableName, $columnName, Column $newColumn)
551
    {
552
        $instructions = $this->getChangeColumnInstructions($tableName, $columnName, $newColumn);
553
        $this->executeAlterSteps($tableName, $instructions);
554
    }
555
556
    /**
557
     * Returns the instructions to change a table column type.
558
     *
559
     * @param string $tableName  Table Name
560
     * @param string $columnName Column Name
561
     * @param \Phinx\Db\Table\Column $newColumn  New Column
562
     * @return AlterInstructions
563
     */
564
    abstract protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn);
565
566
    /**
567
     * {@inheritdoc}
568
     */
569
    public function dropColumn($tableName, $columnName)
570
    {
571
        $instructions = $this->getDropColumnInstructions($tableName, $columnName);
572
        $this->executeAlterSteps($tableName, $instructions);
573
    }
574
575
    /**
576
     * Returns the instructions to drop the specified column.
577
     *
578
     * @param string $tableName Table Name
579
     * @param string $columnName Column Name
580
     * @return AlterInstructions
581
     */
582
    abstract protected function getDropColumnInstructions($tableName, $columnName);
583
584
    /**
585
     * {@inheritdoc}
586
     */
587
    public function addIndex(Table $table, Index $index)
588
    {
589
        $instructions = $this->getAddIndexInstructions($table, $index);
590
        $this->executeAlterSteps($table->getName(), $instructions);
591
    }
592
593
    /**
594
     * Returns the instructions to add the specified index to a database table.
595
     *
596
     * @param \Phinx\Db\Table\Table $table Table
597
     * @param \Phinx\Db\Table\Index $index Index
598
     * @return AlterInstructions
599
     */
600
    abstract protected function getAddIndexInstructions(Table $table, Index $index);
601
602
    /**
603
     * {@inheritdoc}
604
     */
605
    public function dropIndex($tableName, $columns)
606
    {
607
        $instructions = $this->getDropIndexByColumnsInstructions($tableName, $columns);
608
        $this->executeAlterSteps($tableName, $instructions);
609
    }
610
611
    /**
612
     * Returns the instructions to drop the specified index from a database table.
613
     *
614
     * @param string $tableName The name of of the table where the index is
615
     * @param mixed $columns Column(s)
616
     * @return AlterInstructions
617
     */
618
    abstract protected function getDropIndexByColumnsInstructions($tableName, $columns);
619
620
    /**
621
     * {@inheritdoc}
622
     */
623
    public function dropIndexByName($tableName, $indexName)
624
    {
625
        $instructions = $this->getDropIndexByNameInstructions($tableName, $indexName);
626
        $this->executeAlterSteps($tableName, $instructions);
627
    }
628
629
    /**
630
     * Returns the instructions to drop the index specified by name from a database table.
631
     *
632
     * @param string $tableName The table name whe the index is
633
     * @param string $indexName The name of the index
634
     * @return AlterInstructions
635
     */
636
    abstract protected function getDropIndexByNameInstructions($tableName, $indexName);
637
638
    /**
639
     * {@inheritdoc}
640
     */
641
    public function addForeignKey(Table $table, ForeignKey $foreignKey)
642
    {
643
        $instructions = $this->getAddForeignKeyInstructions($table, $foreignKey);
644
        $this->executeAlterSteps($table->getName(), $instructions);
645
    }
646
647
    /**
648
     * Returns the instructions to adds the specified foreign key to a database table.
649
     *
650
     * @param \Phinx\Db\Table\Table $table The table to add the constraint to
651
     * @param \Phinx\Db\Table\ForeignKey $foreignKey The foreign key to add
652
     * @return AlterInstructions
653
     */
654
    abstract protected function getAddForeignKeyInstructions(Table $table, ForeignKey $foreignKey);
655
656
    /**
657
     * {@inheritdoc}
658
     */
659
    public function dropForeignKey($tableName, $columns, $constraint = null)
660
    {
661
        if ($constraint) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $constraint of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
662
            $instructions = $this->getDropForeignKeyInstructions($tableName, $constraint);
663
        } else {
664
            $instructions = $this->getDropForeignKeyByColumnsInstructions($tableName, $columns);
665
        }
666
667
        $this->executeAlterSteps($tableName, $instructions);
668
    }
669
670
    /**
671
     * Returns the instructions to drop the specified foreign key from a database table.
672
     *
673
     * @param string   $tableName The table where the foreign key constraint is
674
     * @param string   $constraint Constraint name
675
     * @return AlterInstructions
676
     */
677
    abstract protected function getDropForeignKeyInstructions($tableName, $constraint);
678
679
    /**
680
     * Returns the instructions to drop the specified foreign key from a database table.
681
     *
682
     * @param string $tableName The table where the foreign key constraint is
683
     * @param array $columns The list of column names
684
     * @return AlterInstructions
685
     */
686
    abstract protected function getDropForeignKeyByColumnsInstructions($tableName, $columns);
687
688
    /**
689
     * {@inheritdoc}
690
     */
691
    public function dropTable($tableName)
692
    {
693
        $instructions = $this->getDropTableInstructions($tableName);
694
        $this->executeAlterSteps($tableName, $instructions);
695
    }
696
697
    /**
698
     * Returns the instructions to drop the specified database table.
699
     *
700
     * @param string $tableName Table Name
701
     * @return AlterInstructions
702
     */
703
    abstract protected function getDropTableInstructions($tableName);
704
705
    /**
706
     * {@inheritdoc}
707
     */
708
    public function renameTable($tableName, $newTableName)
709
    {
710
        $instructions = $this->getRenameTableInstructions($tableName, $newTableName);
711
        $this->executeAlterSteps($tableName, $instructions);
712
    }
713
714
    /**
715
     * Returns the instructions to rename the specified database table.
716
     *
717
     * @param string $tableName Table Name
718
     * @param string $newTableName New Name
719
     * @return AlterInstructions
720
     */
721
    abstract protected function getRenameTableInstructions($tableName, $newTableName);
722
723
    /**
724
     * {@inheritdoc}
725
     */
726
    public function executeActions(Table $table, array $actions)
727
    {
728
        $instructions = new AlterInstructions();
729
730
        foreach ($actions as $action) {
731
            switch (true) {
732
                case ($action instanceof AddColumn):
733
                    $instructions->merge($this->getAddColumnInstructions($table, $action->getColumn()));
734
                    break;
735
736
                case ($action instanceof AddIndex):
737
                    $instructions->merge($this->getAddIndexInstructions($table, $action->getIndex()));
738
                    break;
739
740
                case ($action instanceof AddForeignKey):
741
                    $instructions->merge($this->getAddForeignKeyInstructions($table, $action->getForeignKey()));
742
                    break;
743
744
                case ($action instanceof ChangeColumn):
745
                    $instructions->merge($this->getChangeColumnInstructions(
746
                        $table->getName(),
747
                        $action->getColumnName(),
748
                        $action->getColumn()
749
                    ));
750
                    break;
751
752
                case ($action instanceof DropForeignKey && !$action->getForeignKey()->getConstraint()):
753
                    $instructions->merge($this->getDropForeignKeyByColumnsInstructions(
754
                        $table->getName(),
755
                        $action->getForeignKey()->getColumns()
756
                    ));
757
                    break;
758
759
                case ($action instanceof DropForeignKey && $action->getForeignKey()->getConstraint()):
760
                    $instructions->merge($this->getDropForeignKeyInstructions(
761
                        $table->getName(),
762
                        $action->getForeignKey()->getConstraint()
0 ignored issues
show
Bug introduced by
It seems like $action->getForeignKey()->getConstraint() targeting Phinx\Db\Table\ForeignKey::getConstraint() can also be of type boolean; however, Phinx\Db\Adapter\PdoAdap...oreignKeyInstructions() does only seem to accept string, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
763
                    ));
764
                    break;
765
766
                case ($action instanceof DropIndex && $action->getIndex()->getName() !== null):
767
                    $instructions->merge($this->getDropIndexByNameInstructions(
768
                        $table->getName(),
769
                        $action->getIndex()->getName()
770
                    ));
771
                    break;
772
773
                case ($action instanceof DropIndex && $action->getIndex()->getName() == null):
774
                    $instructions->merge($this->getDropIndexByColumnsInstructions(
775
                        $table->getName(),
776
                        $action->getIndex()->getColumns()
777
                    ));
778
                    break;
779
780
                case ($action instanceof DropTable):
781
                    $instructions->merge($this->getDropTableInstructions(
782
                        $table->getName()
783
                    ));
784
                    break;
785
786
                case ($action instanceof RemoveColumn):
787
                    $instructions->merge($this->getDropColumnInstructions(
788
                        $table->getName(),
789
                        $action->getColumn()->getName()
790
                    ));
791
                    break;
792
793
                case ($action instanceof RenameColumn):
794
                    $instructions->merge($this->getRenameColumnInstructions(
795
                        $table->getName(),
796
                        $action->getColumn()->getName(),
797
                        $action->getNewName()
798
                    ));
799
                    break;
800
801
                case ($action instanceof RenameTable):
802
                    $instructions->merge($this->getRenameTableInstructions(
803
                        $table->getName(),
804
                        $action->getNewName()
805
                    ));
806
                    break;
807
808
                default:
809
                    throw new \InvalidArgumentException(
810
                        sprintf("Don't know how to execute action: '%s'", get_class($action))
811
                    );
812
            }
813
        }
814
815
        $this->executeAlterSteps($table->getName(), $instructions);
816
    }
817
}
818