Completed
Pull Request — master (#1380)
by
unknown
02:51
created

PdoAdapter::insert()   B

Complexity

Conditions 4
Paths 6

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 15
CRAP Score 4

Importance

Changes 0
Metric Value
dl 0
loc 24
ccs 15
cts 15
cp 1
rs 8.6845
c 0
b 0
f 0
cc 4
eloc 16
nc 6
nop 2
crap 4
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
        foreach ($row as $column => $value) {
232 8
            if (is_bool($value)) {
233
                $row[$column] = $this->castToBool($value);
234 8
            }
235
        }
236 8
237 8
        if ($this->isDryRunEnabled()) {
238 6
            $sql .= ' VALUES (' . implode(', ', array_map([$this, 'quoteValue'], $row)) . ');';
239 6
            $this->output->writeln($sql);
240 2
        } else {
241 1
            $sql .= ' VALUES (' . implode(', ', array_fill(0, count($columns), '?')) . ')';
242 1
            $stmt = $this->getConnection()->prepare($sql);
243 1
            $stmt->execute(array_values($row));
244 1
        }
245 8
    }
246
247 7
    /**
248 7
     * Quotes a database value.
249 7
     *
250 7
     * @param mixed $value  The value to quote
251
     * @return mixed
252 7
     */
253
    private function quoteValue($value)
254
    {
255
        if (is_numeric($value)) {
256
            return $value;
257
        }
258 5
259
        if ($value === null) {
260 5
            return 'null';
261
        }
262 5
263 5
        return $this->getConnection()->quote($value);
264 5
    }
265 5
266 5
    /**
267 5
     * {@inheritdoc}
268 5
     */
269 5
    public function bulkinsert(Table $table, $rows)
270 5
    {
271 5
        $sql = sprintf(
272 5
            'INSERT INTO %s ',
273 5
            $this->quoteTableName($table->getName())
274 5
        );
275 5
        $current = current($rows);
276
        $keys = array_keys($current);
277 5
        $sql .= '(' . implode(', ', array_map([$this, 'quoteColumnName'], $keys)) . ') VALUES ';
278 5
279
        if ($this->isDryRunEnabled()) {
280 3
            $values = array_map(function ($row) {
281 3
                return '(' . implode(', ', array_map([$this, 'quoteValue'], $row)) . ')';
282 3
            }, $rows);
283 3
            $sql .= implode(', ', $values) . ';';
284 3
            $this->output->writeln($sql);
285 3
        } else {
286
            $count_keys = count($keys);
287 3
            $query = '(' . implode(', ', array_fill(0, $count_keys, '?')) . ')';
288
            $count_vars = count($rows);
289
            $queries = array_fill(0, $count_vars, $query);
290 5
            $sql .= implode(',', $queries);
291
            $stmt = $this->getConnection()->prepare($sql);
292
            $vals = [];
293
294
            foreach ($rows as $row) {
295
                foreach ($row as $v) {
296 1
                    if (is_bool($v)) {
297
                        $vals[] = $this->castToBool($v);
298 1
                    } else {
299 1
                        $vals[] = $v;
300 1
                    }
301 1
                }
302 1
            }
303 1
304 1
            $stmt->execute($vals);
305 1
        }
306 1
    }
307 1
308 1
    /**
309 1
     * {@inheritdoc}
310
     */
311 1
    public function getVersions()
312
    {
313
        $rows = $this->getVersionLog();
314
315
        return array_keys($rows);
316
    }
317 1
318
    /**
319 1
     * {@inheritdoc}
320 1
     */
321 1
    public function getVersionLog()
322 1
    {
323 1
        $result = [];
324 1
325 1
        switch ($this->options['version_order']) {
326 1
            case \Phinx\Config\Config::VERSION_ORDER_CREATION_TIME:
327 1
                $orderBy = 'version ASC';
328
                break;
329
            case \Phinx\Config\Config::VERSION_ORDER_EXECUTION_TIME:
330
                $orderBy = 'start_time ASC, version ASC';
331
                break;
332
            default:
333
                throw new \RuntimeException('Invalid version_order configuration option');
334
        }
335
336
        $rows = $this->fetchAll(sprintf('SELECT * FROM %s ORDER BY %s', $this->getSchemaTableName(), $orderBy));
337
        foreach ($rows as $version) {
338
            $result[$version['version']] = $version;
339
        }
340
341
        return $result;
342
    }
343
344
    /**
345
     * {@inheritdoc}
346
     */
347
    public function migrated(MigrationInterface $migration, $direction, $startTime, $endTime)
348
    {
349 208
        if (strcasecmp($direction, MigrationInterface::UP) === 0) {
350
            // up
351
            $sql = sprintf(
352 208
                "INSERT INTO %s (%s, %s, %s, %s, %s) VALUES ('%s', '%s', '%s', '%s', %s);",
353 208
                $this->quoteTableName($this->getSchemaTableName()),
354 208
                $this->quoteColumnName('version'),
355 208
                $this->quoteColumnName('migration_name'),
356 208
                $this->quoteColumnName('start_time'),
357 208
                $this->quoteColumnName('end_time'),
358 208
                $this->quoteColumnName('breakpoint'),
359 208
                $migration->getVersion(),
360 208
                substr($migration->getName(), 0, 100),
361 208
                $startTime,
362 208
                $endTime,
363 208
                $this->castToBool(false)
364 208
            );
365 208
366 208
            $this->execute($sql);
367 208
        } else {
368
            // down
369 208
            $sql = sprintf(
370 208
                "DELETE FROM %s WHERE %s = '%s'",
371 208
                $this->quoteTableName($this->getSchemaTableName()),
372 208
                $this->quoteColumnName('version'),
373 208
                $migration->getVersion()
374
            );
375
376
            $this->execute($sql);
377
        }
378
379 121
        return $this;
380
    }
381 121
382
    /**
383
     * @inheritDoc
384
     */
385
    public function toggleBreakpoint(MigrationInterface $migration)
386
    {
387
        $this->query(
388
            sprintf(
389
                '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\';',
390
                $this->getSchemaTableName(),
391
                $this->quoteColumnName('breakpoint'),
392
                $this->castToBool(true),
393
                $this->castToBool(false),
394
                $this->quoteColumnName('version'),
395
                $migration->getVersion(),
396
                $this->quoteColumnName('start_time')
397
            )
398
        );
399
400
        return $this;
401
    }
402
403
    /**
404
     * @inheritDoc
405
     */
406
    public function resetAllBreakpoints()
407
    {
408
        return $this->execute(
409
            sprintf(
410
                'UPDATE %1$s SET %2$s = %3$s, %4$s = %4$s WHERE %2$s <> %3$s;',
411
                $this->getSchemaTableName(),
412
                $this->quoteColumnName('breakpoint'),
413
                $this->castToBool(false),
414
                $this->quoteColumnName('start_time')
415
            )
416
        );
417
    }
418
419
    /**
420
     * {@inheritdoc}
421
     */
422
    public function createSchema($schemaName = 'public')
423
    {
424
        throw new BadMethodCallException('Creating a schema is not supported');
425
    }
426
427
    /**
428
     * {@inheritdoc}
429
     */
430
    public function dropSchema($name)
431
    {
432
        throw new BadMethodCallException('Dropping a schema is not supported');
433
    }
434
435
    /**
436
     * {@inheritdoc}
437
     */
438
    public function getColumnTypes()
439
    {
440
        return [
441
            'string',
442
            'char',
443
            'text',
444
            'integer',
445
            'biginteger',
446
            'bit',
447
            'float',
448
            'decimal',
449
            'datetime',
450
            'timestamp',
451
            'time',
452
            'date',
453
            'blob',
454
            'binary',
455
            'varbinary',
456
            'boolean',
457
            'uuid',
458
            // Geospatial data types
459
            'geometry',
460
            'point',
461
            'linestring',
462
            'polygon',
463
        ];
464
    }
465
466
    /**
467
     * {@inheritdoc}
468
     */
469
    public function castToBool($value)
470
    {
471
        return (bool)$value ? 1 : 0;
472
    }
473
474
    /**
475
     * Retrieve a database connection attribute
476
     * @see http://php.net/manual/en/pdo.getattribute.php
477
     *
478
     * @param int $attribute One of the PDO::ATTR_* constants
479
     * @return mixed
480
     */
481
    public function getAttribute($attribute)
482
    {
483
        return $this->connection->getAttribute($attribute);
484
    }
485
486
    /**
487
     * Get the defintion for a `DEFAULT` statement.
488
     *
489
     * @param  mixed $default Default value
490
     * @param string $columnType column type added
491
     * @return string
492
     */
493 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...
494
    {
495
        if (is_string($default) && 'CURRENT_TIMESTAMP' !== $default) {
496
            $default = $this->getConnection()->quote($default);
497
        } elseif (is_bool($default)) {
498
            $default = $this->castToBool($default);
499
        } elseif ($columnType === static::PHINX_TYPE_BOOLEAN) {
500
            $default = $this->castToBool((bool)$default);
501
        }
502
503
        return isset($default) ? " DEFAULT $default" : '';
504
    }
505
506
    /**
507
     * Executes all the ALTER TABLE instructions passed for the given table
508
     *
509
     * @param string $tableName The table name to use in the ALTER statement
510
     * @param AlterInstructions $instructions The object containing the alter sequence
511
     * @return void
512
     */
513
    protected function executeAlterSteps($tableName, AlterInstructions $instructions)
514
    {
515
        $alter = sprintf('ALTER TABLE %s %%s', $this->quoteTableName($tableName));
516
        $instructions->execute($alter, [$this, 'execute']);
517
    }
518
519
    /**
520
     * {@inheritdoc}
521
     */
522
    public function addColumn(Table $table, Column $column)
523
    {
524
        $instructions = $this->getAddColumnInstructions($table, $column);
525
        $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...
526
    }
527
528
    /**
529
     * Returns the instrutions to add the specified column to a database table.
530
     *
531
     * @param \Phinx\Db\Table\Table $table Table
532
     * @param \Phinx\Db\Table\Column $column Column
533
     * @return AlterInstructions
534
     */
535
    abstract protected function getAddColumnInstructions(Table $table, Column $column);
536
537
    /**
538
     * {@inheritdoc}
539
     */
540
    public function renameColumn($tableName, $columnName, $newColumnName)
541
    {
542
        $instructions = $this->getRenameColumnInstructions($tableName, $columnName, $newColumnName);
543
        $this->executeAlterSteps($tableName, $instructions);
544
    }
545
546
    /**
547
     * Returns the instructions to rename the specified column.
548
     *
549
     * @param string $tableName Table Name
550
     * @param string $columnName Column Name
551
     * @param string $newColumnName New Column Name
552
     * @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...
553
     *
554
     */
555
    abstract protected function getRenameColumnInstructions($tableName, $columnName, $newColumnName);
556
557
    /**
558
     * {@inheritdoc}
559
     */
560
    public function changeColumn($tableName, $columnName, Column $newColumn)
561
    {
562
        $instructions = $this->getChangeColumnInstructions($tableName, $columnName, $newColumn);
563
        $this->executeAlterSteps($tableName, $instructions);
564
    }
565
566
    /**
567
     * Returns the instructions to change a table column type.
568
     *
569
     * @param string $tableName  Table Name
570
     * @param string $columnName Column Name
571
     * @param \Phinx\Db\Table\Column $newColumn  New Column
572
     * @return AlterInstructions
573
     */
574
    abstract protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn);
575
576
    /**
577
     * {@inheritdoc}
578
     */
579
    public function dropColumn($tableName, $columnName)
580
    {
581
        $instructions = $this->getDropColumnInstructions($tableName, $columnName);
582
        $this->executeAlterSteps($tableName, $instructions);
583
    }
584
585
    /**
586
     * Returns the instructions to drop the specified column.
587
     *
588
     * @param string $tableName Table Name
589
     * @param string $columnName Column Name
590
     * @return AlterInstructions
591
     */
592
    abstract protected function getDropColumnInstructions($tableName, $columnName);
593
594
    /**
595
     * {@inheritdoc}
596
     */
597
    public function addIndex(Table $table, Index $index)
598
    {
599
        $instructions = $this->getAddIndexInstructions($table, $index);
600
        $this->executeAlterSteps($table->getName(), $instructions);
601
    }
602
603
    /**
604
     * Returns the instructions to add the specified index to a database table.
605
     *
606
     * @param \Phinx\Db\Table\Table $table Table
607
     * @param \Phinx\Db\Table\Index $index Index
608
     * @return AlterInstructions
609
     */
610
    abstract protected function getAddIndexInstructions(Table $table, Index $index);
611
612
    /**
613
     * {@inheritdoc}
614
     */
615
    public function dropIndex($tableName, $columns)
616
    {
617
        $instructions = $this->getDropIndexByColumnsInstructions($tableName, $columns);
618
        $this->executeAlterSteps($tableName, $instructions);
619
    }
620
621
    /**
622
     * Returns the instructions to drop the specified index from a database table.
623
     *
624
     * @param string $tableName The name of of the table where the index is
625
     * @param mixed $columns Column(s)
626
     * @return AlterInstructions
627
     */
628
    abstract protected function getDropIndexByColumnsInstructions($tableName, $columns);
629
630
    /**
631
     * {@inheritdoc}
632
     */
633
    public function dropIndexByName($tableName, $indexName)
634
    {
635
        $instructions = $this->getDropIndexByNameInstructions($tableName, $indexName);
636
        $this->executeAlterSteps($tableName, $instructions);
637
    }
638
639
    /**
640
     * Returns the instructions to drop the index specified by name from a database table.
641
     *
642
     * @param string $tableName The table name whe the index is
643
     * @param string $indexName The name of the index
644
     * @return AlterInstructions
645
     */
646
    abstract protected function getDropIndexByNameInstructions($tableName, $indexName);
647
648
    /**
649
     * {@inheritdoc}
650
     */
651
    public function addForeignKey(Table $table, ForeignKey $foreignKey)
652
    {
653
        $instructions = $this->getAddForeignKeyInstructions($table, $foreignKey);
654
        $this->executeAlterSteps($table->getName(), $instructions);
655
    }
656
657
    /**
658
     * Returns the instructions to adds the specified foreign key to a database table.
659
     *
660
     * @param \Phinx\Db\Table\Table $table The table to add the constraint to
661
     * @param \Phinx\Db\Table\ForeignKey $foreignKey The foreign key to add
662
     * @return AlterInstructions
663
     */
664
    abstract protected function getAddForeignKeyInstructions(Table $table, ForeignKey $foreignKey);
665
666
    /**
667
     * {@inheritdoc}
668
     */
669
    public function dropForeignKey($tableName, $columns, $constraint = null)
670
    {
671
        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...
672
            $instructions = $this->getDropForeignKeyInstructions($tableName, $constraint);
673
        } else {
674
            $instructions = $this->getDropForeignKeyByColumnsInstructions($tableName, $columns);
675
        }
676
677
        $this->executeAlterSteps($tableName, $instructions);
678
    }
679
680
    /**
681
     * Returns the instructions to drop the specified foreign key from a database table.
682
     *
683
     * @param string   $tableName The table where the foreign key constraint is
684
     * @param string   $constraint Constraint name
685
     * @return AlterInstructions
686
     */
687
    abstract protected function getDropForeignKeyInstructions($tableName, $constraint);
688
689
    /**
690
     * Returns the instructions to drop the specified foreign key from a database table.
691
     *
692
     * @param string $tableName The table where the foreign key constraint is
693
     * @param array $columns The list of column names
694
     * @return AlterInstructions
695
     */
696
    abstract protected function getDropForeignKeyByColumnsInstructions($tableName, $columns);
697
698
    /**
699
     * {@inheritdoc}
700
     */
701
    public function dropTable($tableName)
702
    {
703
        $instructions = $this->getDropTableInstructions($tableName);
704
        $this->executeAlterSteps($tableName, $instructions);
705
    }
706
707
    /**
708
     * Returns the instructions to drop the specified database table.
709
     *
710
     * @param string $tableName Table Name
711
     * @return AlterInstructions
712
     */
713
    abstract protected function getDropTableInstructions($tableName);
714
715
    /**
716
     * {@inheritdoc}
717
     */
718
    public function renameTable($tableName, $newTableName)
719
    {
720
        $instructions = $this->getRenameTableInstructions($tableName, $newTableName);
721
        $this->executeAlterSteps($tableName, $instructions);
722
    }
723
724
    /**
725
     * Returns the instructions to rename the specified database table.
726
     *
727
     * @param string $tableName Table Name
728
     * @param string $newTableName New Name
729
     * @return AlterInstructions
730
     */
731
    abstract protected function getRenameTableInstructions($tableName, $newTableName);
732
733
    /**
734
     * {@inheritdoc}
735
     */
736
    public function executeActions(Table $table, array $actions)
737
    {
738
        $instructions = new AlterInstructions();
739
740
        foreach ($actions as $action) {
741
            switch (true) {
742
                case ($action instanceof AddColumn):
743
                    $instructions->merge($this->getAddColumnInstructions($table, $action->getColumn()));
744
                    break;
745
746
                case ($action instanceof AddIndex):
747
                    $instructions->merge($this->getAddIndexInstructions($table, $action->getIndex()));
748
                    break;
749
750
                case ($action instanceof AddForeignKey):
751
                    $instructions->merge($this->getAddForeignKeyInstructions($table, $action->getForeignKey()));
752
                    break;
753
754
                case ($action instanceof ChangeColumn):
755
                    $instructions->merge($this->getChangeColumnInstructions(
756
                        $table->getName(),
757
                        $action->getColumnName(),
758
                        $action->getColumn()
759
                    ));
760
                    break;
761
762
                case ($action instanceof DropForeignKey && !$action->getForeignKey()->getConstraint()):
763
                    $instructions->merge($this->getDropForeignKeyByColumnsInstructions(
764
                        $table->getName(),
765
                        $action->getForeignKey()->getColumns()
766
                    ));
767
                    break;
768
769
                case ($action instanceof DropForeignKey && $action->getForeignKey()->getConstraint()):
770
                    $instructions->merge($this->getDropForeignKeyInstructions(
771
                        $table->getName(),
772
                        $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...
773
                    ));
774
                    break;
775
776
                case ($action instanceof DropIndex && $action->getIndex()->getName() !== null):
777
                    $instructions->merge($this->getDropIndexByNameInstructions(
778
                        $table->getName(),
779
                        $action->getIndex()->getName()
780
                    ));
781
                    break;
782
783
                case ($action instanceof DropIndex && $action->getIndex()->getName() == null):
784
                    $instructions->merge($this->getDropIndexByColumnsInstructions(
785
                        $table->getName(),
786
                        $action->getIndex()->getColumns()
787
                    ));
788
                    break;
789
790
                case ($action instanceof DropTable):
791
                    $instructions->merge($this->getDropTableInstructions(
792
                        $table->getName()
793
                    ));
794
                    break;
795
796
                case ($action instanceof RemoveColumn):
797
                    $instructions->merge($this->getDropColumnInstructions(
798
                        $table->getName(),
799
                        $action->getColumn()->getName()
800
                    ));
801
                    break;
802
803
                case ($action instanceof RenameColumn):
804
                    $instructions->merge($this->getRenameColumnInstructions(
805
                        $table->getName(),
806
                        $action->getColumn()->getName(),
807
                        $action->getNewName()
808
                    ));
809
                    break;
810
811
                case ($action instanceof RenameTable):
812
                    $instructions->merge($this->getRenameTableInstructions(
813
                        $table->getName(),
814
                        $action->getNewName()
815
                    ));
816
                    break;
817
818
                default:
819
                    throw new \InvalidArgumentException(
820
                        sprintf("Don't know how to execute action: '%s'", get_class($action))
821
                    );
822
            }
823
        }
824
825
        $this->executeAlterSteps($table->getName(), $instructions);
826
    }
827
}
828