Completed
Push — master ( 3ee855...788745 )
by José
13s queued 11s
created

PdoAdapter::quoteString()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
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\ChangeComment;
37
use Phinx\Db\Action\ChangePrimaryKey;
38
use Phinx\Db\Action\DropForeignKey;
39
use Phinx\Db\Action\DropIndex;
40
use Phinx\Db\Action\DropTable;
41
use Phinx\Db\Action\RemoveColumn;
42
use Phinx\Db\Action\RenameColumn;
43
use Phinx\Db\Action\RenameTable;
44
use Phinx\Db\Table\Column;
45
use Phinx\Db\Table\ForeignKey;
46
use Phinx\Db\Table\Index;
47
use Phinx\Db\Table\Table;
48
use Phinx\Db\Util\AlterInstructions;
49
use Phinx\Migration\MigrationInterface;
50
use Symfony\Component\Console\Output\OutputInterface;
51 287
52
/**
53 287
 * Phinx PDO Adapter.
54
 *
55 287
 * @author Rob Morgan <[email protected]>
56 3
 */
57 3
abstract class PdoAdapter extends AbstractAdapter implements DirectActionInterface
58
{
59 287
    /**
60
     * @var \PDO|null
61
     */
62
    protected $connection;
63
64
    /**
65
     * Writes a message to stdout if verbose output is on
66
     *
67
     * @param string $message The message to show
68 193
     * @return void
69
     */
70 193
    protected function verboseLog($message)
71
    {
72
        if (!$this->isDryRunEnabled() &&
73 193
             $this->getOutput()->getVerbosity() < OutputInterface::VERBOSITY_VERY_VERBOSE) {
74 191
            return;
75 191
        }
76 74
77 74
        $this->getOutput()->writeln($message);
78
    }
79
80
    /**
81
     * {@inheritdoc}
82
     */
83
    public function setOptions(array $options)
84
    {
85
        parent::setOptions($options);
86 74
87
        if (isset($options['connection'])) {
88
            $this->setConnection($options['connection']);
89
        }
90
91
        return $this;
92
    }
93 193
94
    /**
95
     * Sets the database connection.
96
     *
97
     * @param \PDO $connection Connection
98
     * @return \Phinx\Db\Adapter\AdapterInterface
99
     */
100
    public function setConnection(\PDO $connection)
101 191
    {
102
        $this->connection = $connection;
103 191
104 189
        // Create the schema table if it doesn't already exist
105 189
        if (!$this->hasSchemaTable()) {
106 191
            $this->createSchemaTable();
107
        } else {
108
            $table = new \Phinx\Db\Table($this->getSchemaTableName(), [], $this);
109
            if (!$table->hasColumn('migration_name')) {
110
                $table
111
                    ->addColumn(
112 1
                        'migration_name',
113
                        'string',
114 1
                        ['limit' => 100, 'after' => 'version', 'default' => null, 'null' => true]
115
                    )
116
                    ->save();
117
            }
118
            if (!$table->hasColumn('breakpoint')) {
119
                $table
120
                    ->addColumn('breakpoint', 'boolean', ['default' => false])
121
                    ->save();
122
            }
123
        }
124
125
        return $this;
126 218
    }
127
128 218
    /**
129 3
     * Gets the database connection
130 3
     *
131
     * @return \PDO
132
     */
133 217
    public function getConnection()
134
    {
135
        if ($this->connection === null) {
136
            $this->connect();
137
        }
138
139
        return $this->connection;
140
    }
141
142 220
    /**
143
     * {@inheritdoc}
144 220
     */
145
    public function connect()
146
    {
147
    }
148
149
    /**
150 151
     * {@inheritdoc}
151
     */
152 151
    public function disconnect()
153 151
    {
154
    }
155
156
    /**
157
     * {@inheritdoc}
158
     */
159 213
    public function execute($sql)
160
    {
161 213
        $this->verboseLog($sql);
162 213
163 213
        if ($this->isDryRunEnabled()) {
164 208
            return 0;
165 208
        }
166 213
167
        return $this->getConnection()->exec($sql);
168
    }
169
170
    /**
171
     * Returns the Cake\Database connection object using the same underlying
172 1
     * PDO object as this connection.
173
     *
174 1
     * @return \Cake\Database\Connection
175 1
     */
176 1
    abstract public function getDecoratedConnection();
177 1
178
    /**
179 1
     * {@inheritdoc}
180 1
     */
181 1
    public function getQueryBuilder()
182
    {
183 1
        return $this->getDecoratedConnection()->newQuery();
184 1
    }
185 1
186
    /**
187
     * Executes a query and returns PDOStatement.
188
     *
189
     * @param string $sql SQL
190 11
     * @return \PDOStatement
191
     */
192 11
    public function query($sql)
193 11
    {
194 11
        return $this->getConnection()->query($sql);
195 11
    }
196
197 11
    /**
198 11
     * {@inheritdoc}
199 11
     */
200
    public function fetchRow($sql)
201 11
    {
202 11
        $result = $this->query($sql);
203 11
204 11
        return $result->fetch();
205 11
    }
206 11
207
    /**
208 11
     * {@inheritdoc}
209 11
     */
210
    public function fetchAll($sql)
211 11
    {
212 11
        $rows = [];
213 11
        $result = $this->query($sql);
214
        while ($row = $result->fetch()) {
215 11
            $rows[] = $row;
216 11
        }
217 11
218
        return $rows;
219
    }
220
221
    /**
222 5
     * {@inheritdoc}
223
     */
224 5
    public function insert(Table $table, $row)
225
    {
226 5
        $sql = sprintf(
227
            'INSERT INTO %s ',
228
            $this->quoteTableName($table->getName())
229
        );
230
        $columns = array_keys($row);
231
        $sql .= '(' . implode(', ', array_map([$this, 'quoteColumnName'], $columns)) . ')';
232 8
233
        foreach ($row as $column => $value) {
234 8
            if (is_bool($value)) {
235
                $row[$column] = $this->castToBool($value);
236 8
            }
237 8
        }
238 6
239 6
        if ($this->isDryRunEnabled()) {
240 2
            $sql .= ' VALUES (' . implode(', ', array_map([$this, 'quoteValue'], $row)) . ');';
241 1
            $this->output->writeln($sql);
242 1
        } else {
243 1
            $sql .= ' VALUES (' . implode(', ', array_fill(0, count($columns), '?')) . ')';
244 1
            $stmt = $this->getConnection()->prepare($sql);
245 8
            $stmt->execute(array_values($row));
246
        }
247 7
    }
248 7
249 7
    /**
250 7
     * Quotes a database value.
251
     *
252 7
     * @param mixed $value  The value to quote
253
     * @return mixed
254
     */
255
    protected function quoteValue($value)
256
    {
257
        if (is_numeric($value)) {
258 5
            return $value;
259
        }
260 5
261
        if ($value === null) {
262 5
            return 'null';
263 5
        }
264 5
265 5
        return $this->getConnection()->quote($value);
266 5
    }
267 5
268 5
    /**
269 5
     * Quotes a database string.
270 5
     *
271 5
     * @param string $value  The string to quote
272 5
     * @return mixed
273 5
     */
274 5
    protected function quoteString($value)
275 5
    {
276
        return $this->getConnection()->quote($value);
277 5
    }
278 5
279
    /**
280 3
     * {@inheritdoc}
281 3
     */
282 3
    public function bulkinsert(Table $table, $rows)
283 3
    {
284 3
        $sql = sprintf(
285 3
            'INSERT INTO %s ',
286
            $this->quoteTableName($table->getName())
287 3
        );
288
        $current = current($rows);
289
        $keys = array_keys($current);
290 5
        $sql .= '(' . implode(', ', array_map([$this, 'quoteColumnName'], $keys)) . ') VALUES ';
291
292
        if ($this->isDryRunEnabled()) {
293
            $values = array_map(function ($row) {
294
                return '(' . implode(', ', array_map([$this, 'quoteValue'], $row)) . ')';
295
            }, $rows);
296 1
            $sql .= implode(', ', $values) . ';';
297
            $this->output->writeln($sql);
298 1
        } else {
299 1
            $count_keys = count($keys);
300 1
            $query = '(' . implode(', ', array_fill(0, $count_keys, '?')) . ')';
301 1
            $count_vars = count($rows);
302 1
            $queries = array_fill(0, $count_vars, $query);
303 1
            $sql .= implode(',', $queries);
304 1
            $stmt = $this->getConnection()->prepare($sql);
305 1
            $vals = [];
306 1
307 1
            foreach ($rows as $row) {
308 1
                foreach ($row as $v) {
309 1
                    if (is_bool($v)) {
310
                        $vals[] = $this->castToBool($v);
311 1
                    } else {
312
                        $vals[] = $v;
313
                    }
314
                }
315
            }
316
317 1
            $stmt->execute($vals);
318
        }
319 1
    }
320 1
321 1
    /**
322 1
     * {@inheritdoc}
323 1
     */
324 1
    public function getVersions()
325 1
    {
326 1
        $rows = $this->getVersionLog();
327 1
328
        return array_keys($rows);
329
    }
330
331
    /**
332
     * {@inheritdoc}
333
     */
334
    public function getVersionLog()
335
    {
336
        $result = [];
337
338
        switch ($this->options['version_order']) {
339
            case \Phinx\Config\Config::VERSION_ORDER_CREATION_TIME:
340
                $orderBy = 'version ASC';
341
                break;
342
            case \Phinx\Config\Config::VERSION_ORDER_EXECUTION_TIME:
343
                $orderBy = 'start_time ASC, version ASC';
344
                break;
345
            default:
346
                throw new \RuntimeException('Invalid version_order configuration option');
347
        }
348
349 208
        $rows = $this->fetchAll(sprintf('SELECT * FROM %s ORDER BY %s', $this->getSchemaTableName(), $orderBy));
350
        foreach ($rows as $version) {
351
            $result[$version['version']] = $version;
352 208
        }
353 208
354 208
        return $result;
355 208
    }
356 208
357 208
    /**
358 208
     * {@inheritdoc}
359 208
     */
360 208
    public function migrated(MigrationInterface $migration, $direction, $startTime, $endTime)
361 208
    {
362 208
        if (strcasecmp($direction, MigrationInterface::UP) === 0) {
363 208
            // up
364 208
            $sql = sprintf(
365 208
                "INSERT INTO %s (%s, %s, %s, %s, %s) VALUES ('%s', '%s', '%s', '%s', %s);",
366 208
                $this->quoteTableName($this->getSchemaTableName()),
367 208
                $this->quoteColumnName('version'),
368
                $this->quoteColumnName('migration_name'),
369 208
                $this->quoteColumnName('start_time'),
370 208
                $this->quoteColumnName('end_time'),
371 208
                $this->quoteColumnName('breakpoint'),
372 208
                $migration->getVersion(),
373 208
                substr($migration->getName(), 0, 100),
374
                $startTime,
375
                $endTime,
376
                $this->castToBool(false)
377
            );
378
379 121
            $this->execute($sql);
380
        } else {
381 121
            // down
382
            $sql = sprintf(
383
                "DELETE FROM %s WHERE %s = '%s'",
384
                $this->quoteTableName($this->getSchemaTableName()),
385
                $this->quoteColumnName('version'),
386
                $migration->getVersion()
387
            );
388
389
            $this->execute($sql);
390
        }
391
392
        return $this;
393
    }
394
395
    /**
396
     * {@inheritdoc}
397
     */
398
    public function toggleBreakpoint(MigrationInterface $migration)
399
    {
400
        $this->query(
401
            sprintf(
402
                '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\';',
403
                $this->getSchemaTableName(),
404
                $this->quoteColumnName('breakpoint'),
405
                $this->castToBool(true),
406
                $this->castToBool(false),
407
                $this->quoteColumnName('version'),
408
                $migration->getVersion(),
409
                $this->quoteColumnName('start_time')
410
            )
411
        );
412
413
        return $this;
414
    }
415
416
    /**
417
     * {@inheritdoc}
418
     */
419
    public function resetAllBreakpoints()
420
    {
421
        return $this->execute(
422
            sprintf(
423
                'UPDATE %1$s SET %2$s = %3$s, %4$s = %4$s WHERE %2$s <> %3$s;',
424
                $this->getSchemaTableName(),
425
                $this->quoteColumnName('breakpoint'),
426
                $this->castToBool(false),
427
                $this->quoteColumnName('start_time')
428
            )
429
        );
430
    }
431
432
    /**
433
     * {@inheritdoc}
434
     */
435
    public function createSchema($schemaName = 'public')
436
    {
437
        throw new BadMethodCallException('Creating a schema is not supported');
438
    }
439
440
    /**
441
     * {@inheritdoc}
442
     */
443
    public function dropSchema($name)
444
    {
445
        throw new BadMethodCallException('Dropping a schema is not supported');
446
    }
447
448
    /**
449
     * {@inheritdoc}
450
     */
451
    public function getColumnTypes()
452
    {
453
        return [
454
            'string',
455
            'char',
456
            'text',
457
            'smallinteger',
458
            'integer',
459
            'biginteger',
460
            'bit',
461
            'float',
462
            'decimal',
463
            'double',
464
            'datetime',
465
            'timestamp',
466
            'time',
467
            'date',
468
            'blob',
469
            'binary',
470
            'varbinary',
471
            'boolean',
472
            'uuid',
473
            // Geospatial data types
474
            'geometry',
475
            'point',
476
            'linestring',
477
            'polygon',
478
        ];
479
    }
480
481
    /**
482
     * {@inheritdoc}
483
     */
484
    public function castToBool($value)
485
    {
486
        return (bool)$value ? 1 : 0;
487
    }
488
489
    /**
490
     * Retrieve a database connection attribute
491
     * @see http://php.net/manual/en/pdo.getattribute.php
492
     *
493
     * @param int $attribute One of the PDO::ATTR_* constants
494
     * @return mixed
495
     */
496
    public function getAttribute($attribute)
497
    {
498
        return $this->connection->getAttribute($attribute);
499
    }
500
501
    /**
502
     * Get the definition for a `DEFAULT` statement.
503
     *
504
     * @param  mixed $default Default value
505
     * @param string $columnType column type added
506
     * @return string
507
     */
508 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...
509
    {
510
        if (is_string($default) && 'CURRENT_TIMESTAMP' !== $default) {
511
            $default = $this->getConnection()->quote($default);
512
        } elseif (is_bool($default)) {
513
            $default = $this->castToBool($default);
514
        } elseif ($default !== null && $columnType === static::PHINX_TYPE_BOOLEAN) {
515
            $default = $this->castToBool((bool)$default);
516
        }
517
518
        return isset($default) ? " DEFAULT $default" : '';
519
    }
520
521
    /**
522
     * Executes all the ALTER TABLE instructions passed for the given table
523
     *
524
     * @param string $tableName The table name to use in the ALTER statement
525
     * @param AlterInstructions $instructions The object containing the alter sequence
526
     * @return void
527
     */
528
    protected function executeAlterSteps($tableName, AlterInstructions $instructions)
529
    {
530
        $alter = sprintf('ALTER TABLE %s %%s', $this->quoteTableName($tableName));
531
        $instructions->execute($alter, [$this, 'execute']);
532
    }
533
534
    /**
535
     * {@inheritdoc}
536
     */
537
    public function addColumn(Table $table, Column $column)
538
    {
539
        $instructions = $this->getAddColumnInstructions($table, $column);
540
        $this->executeAlterSteps($table->getName(), $instructions);
541
    }
542
543
    /**
544
     * Returns the instructions to add the specified column to a database table.
545
     *
546
     * @param \Phinx\Db\Table\Table $table Table
547
     * @param \Phinx\Db\Table\Column $column Column
548
     * @return AlterInstructions
549
     */
550
    abstract protected function getAddColumnInstructions(Table $table, Column $column);
551
552
    /**
553
     * {@inheritdoc}
554
     */
555
    public function renameColumn($tableName, $columnName, $newColumnName)
556
    {
557
        $instructions = $this->getRenameColumnInstructions($tableName, $columnName, $newColumnName);
558
        $this->executeAlterSteps($tableName, $instructions);
559
    }
560
561
    /**
562
     * Returns the instructions to rename the specified column.
563
     *
564
     * @param string $tableName Table Name
565
     * @param string $columnName Column Name
566
     * @param string $newColumnName New Column Name
567
     * @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...
568
     *
569
     */
570
    abstract protected function getRenameColumnInstructions($tableName, $columnName, $newColumnName);
571
572
    /**
573
     * {@inheritdoc}
574
     */
575
    public function changeColumn($tableName, $columnName, Column $newColumn)
576
    {
577
        $instructions = $this->getChangeColumnInstructions($tableName, $columnName, $newColumn);
578
        $this->executeAlterSteps($tableName, $instructions);
579
    }
580
581
    /**
582
     * Returns the instructions to change a table column type.
583
     *
584
     * @param string $tableName  Table Name
585
     * @param string $columnName Column Name
586
     * @param \Phinx\Db\Table\Column $newColumn  New Column
587
     * @return AlterInstructions
588
     */
589
    abstract protected function getChangeColumnInstructions($tableName, $columnName, Column $newColumn);
590
591
    /**
592
     * {@inheritdoc}
593
     */
594
    public function dropColumn($tableName, $columnName)
595
    {
596
        $instructions = $this->getDropColumnInstructions($tableName, $columnName);
597
        $this->executeAlterSteps($tableName, $instructions);
598
    }
599
600
    /**
601
     * Returns the instructions to drop the specified column.
602
     *
603
     * @param string $tableName Table Name
604
     * @param string $columnName Column Name
605
     * @return AlterInstructions
606
     */
607
    abstract protected function getDropColumnInstructions($tableName, $columnName);
608
609
    /**
610
     * {@inheritdoc}
611
     */
612
    public function addIndex(Table $table, Index $index)
613
    {
614
        $instructions = $this->getAddIndexInstructions($table, $index);
615
        $this->executeAlterSteps($table->getName(), $instructions);
616
    }
617
618
    /**
619
     * Returns the instructions to add the specified index to a database table.
620
     *
621
     * @param \Phinx\Db\Table\Table $table Table
622
     * @param \Phinx\Db\Table\Index $index Index
623
     * @return AlterInstructions
624
     */
625
    abstract protected function getAddIndexInstructions(Table $table, Index $index);
626
627
    /**
628
     * {@inheritdoc}
629
     */
630
    public function dropIndex($tableName, $columns)
631
    {
632
        $instructions = $this->getDropIndexByColumnsInstructions($tableName, $columns);
633
        $this->executeAlterSteps($tableName, $instructions);
634
    }
635
636
    /**
637
     * Returns the instructions to drop the specified index from a database table.
638
     *
639
     * @param string $tableName The name of of the table where the index is
640
     * @param mixed $columns Column(s)
641
     * @return AlterInstructions
642
     */
643
    abstract protected function getDropIndexByColumnsInstructions($tableName, $columns);
644
645
    /**
646
     * {@inheritdoc}
647
     */
648
    public function dropIndexByName($tableName, $indexName)
649
    {
650
        $instructions = $this->getDropIndexByNameInstructions($tableName, $indexName);
651
        $this->executeAlterSteps($tableName, $instructions);
652
    }
653
654
    /**
655
     * Returns the instructions to drop the index specified by name from a database table.
656
     *
657
     * @param string $tableName The table name whe the index is
658
     * @param string $indexName The name of the index
659
     * @return AlterInstructions
660
     */
661
    abstract protected function getDropIndexByNameInstructions($tableName, $indexName);
662
663
    /**
664
     * {@inheritdoc}
665
     */
666
    public function addForeignKey(Table $table, ForeignKey $foreignKey)
667
    {
668
        $instructions = $this->getAddForeignKeyInstructions($table, $foreignKey);
669
        $this->executeAlterSteps($table->getName(), $instructions);
670
    }
671
672
    /**
673
     * Returns the instructions to adds the specified foreign key to a database table.
674
     *
675
     * @param \Phinx\Db\Table\Table $table The table to add the constraint to
676
     * @param \Phinx\Db\Table\ForeignKey $foreignKey The foreign key to add
677
     * @return AlterInstructions
678
     */
679
    abstract protected function getAddForeignKeyInstructions(Table $table, ForeignKey $foreignKey);
680
681
    /**
682
     * {@inheritdoc}
683
     */
684
    public function dropForeignKey($tableName, $columns, $constraint = null)
685
    {
686
        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...
687
            $instructions = $this->getDropForeignKeyInstructions($tableName, $constraint);
688
        } else {
689
            $instructions = $this->getDropForeignKeyByColumnsInstructions($tableName, $columns);
690
        }
691
692
        $this->executeAlterSteps($tableName, $instructions);
693
    }
694
695
    /**
696
     * Returns the instructions to drop the specified foreign key from a database table.
697
     *
698
     * @param string   $tableName The table where the foreign key constraint is
699
     * @param string   $constraint Constraint name
700
     * @return AlterInstructions
701
     */
702
    abstract protected function getDropForeignKeyInstructions($tableName, $constraint);
703
704
    /**
705
     * Returns the instructions to drop the specified foreign key from a database table.
706
     *
707
     * @param string $tableName The table where the foreign key constraint is
708
     * @param array $columns The list of column names
709
     * @return AlterInstructions
710
     */
711
    abstract protected function getDropForeignKeyByColumnsInstructions($tableName, $columns);
712
713
    /**
714
     * {@inheritdoc}
715
     */
716
    public function dropTable($tableName)
717
    {
718
        $instructions = $this->getDropTableInstructions($tableName);
719
        $this->executeAlterSteps($tableName, $instructions);
720
    }
721
722
    /**
723
     * Returns the instructions to drop the specified database table.
724
     *
725
     * @param string $tableName Table Name
726
     * @return AlterInstructions
727
     */
728
    abstract protected function getDropTableInstructions($tableName);
729
730
    /**
731
     * {@inheritdoc}
732
     */
733
    public function renameTable($tableName, $newTableName)
734
    {
735
        $instructions = $this->getRenameTableInstructions($tableName, $newTableName);
736
        $this->executeAlterSteps($tableName, $instructions);
737
    }
738
739
    /**
740
     * Returns the instructions to rename the specified database table.
741
     *
742
     * @param string $tableName Table Name
743
     * @param string $newTableName New Name
744
     * @return AlterInstructions
745
     */
746
    abstract protected function getRenameTableInstructions($tableName, $newTableName);
747
748
    /**
749
     * {@inheritdoc}
750
     */
751
    public function changePrimaryKey(Table $table, $newColumns)
752
    {
753
        $instructions = $this->getChangePrimaryKeyInstructions($table, $newColumns);
754
        $this->executeAlterSteps($table->getName(), $instructions);
755
    }
756
757
    /**
758
     * Returns the instructions to change the primary key for the specified database table.
759
     *
760
     * @param Table $table Table
761
     * @param string|array|null $newColumns Column name(s) to belong to the primary key, or null to drop the key
762
     * @return AlterInstructions
763
     */
764
    abstract protected function getChangePrimaryKeyInstructions(Table $table, $newColumns);
765
766
    /**
767
     * {@inheritdoc}
768
     */
769
    public function changeComment(Table $table, $newComment)
770
    {
771
        $instructions = $this->getChangeCommentInstructions($table, $newComment);
772
        $this->executeAlterSteps($table->getName(), $instructions);
773
    }
774
775
    /**
776
     * Returns the instruction to change the comment for the specified database table.
777
     *
778
     * @param Table $table Table
779
     * @param string|null $newComment New comment string, or null to drop the comment
780
     * @return AlterInstructions
781
     */
782
    abstract protected function getChangeCommentInstructions(Table $table, $newComment);
783
784
    /**
785
     * {@inheritdoc}
786
     */
787
    public function executeActions(Table $table, array $actions)
788
    {
789
        $instructions = new AlterInstructions();
790
791
        foreach ($actions as $action) {
792
            switch (true) {
793
                case ($action instanceof AddColumn):
794
                    $instructions->merge($this->getAddColumnInstructions($table, $action->getColumn()));
795
                    break;
796
797
                case ($action instanceof AddIndex):
798
                    $instructions->merge($this->getAddIndexInstructions($table, $action->getIndex()));
799
                    break;
800
801
                case ($action instanceof AddForeignKey):
802
                    $instructions->merge($this->getAddForeignKeyInstructions($table, $action->getForeignKey()));
803
                    break;
804
805
                case ($action instanceof ChangeColumn):
806
                    $instructions->merge($this->getChangeColumnInstructions(
807
                        $table->getName(),
808
                        $action->getColumnName(),
809
                        $action->getColumn()
810
                    ));
811
                    break;
812
813
                case ($action instanceof DropForeignKey && !$action->getForeignKey()->getConstraint()):
814
                    $instructions->merge($this->getDropForeignKeyByColumnsInstructions(
815
                        $table->getName(),
816
                        $action->getForeignKey()->getColumns()
817
                    ));
818
                    break;
819
820
                case ($action instanceof DropForeignKey && $action->getForeignKey()->getConstraint()):
821
                    $instructions->merge($this->getDropForeignKeyInstructions(
822
                        $table->getName(),
823
                        $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...
824
                    ));
825
                    break;
826
827
                case ($action instanceof DropIndex && $action->getIndex()->getName() !== null):
828
                    $instructions->merge($this->getDropIndexByNameInstructions(
829
                        $table->getName(),
830
                        $action->getIndex()->getName()
831
                    ));
832
                    break;
833
834
                case ($action instanceof DropIndex && $action->getIndex()->getName() == null):
835
                    $instructions->merge($this->getDropIndexByColumnsInstructions(
836
                        $table->getName(),
837
                        $action->getIndex()->getColumns()
838
                    ));
839
                    break;
840
841
                case ($action instanceof DropTable):
842
                    $instructions->merge($this->getDropTableInstructions(
843
                        $table->getName()
844
                    ));
845
                    break;
846
847
                case ($action instanceof RemoveColumn):
848
                    $instructions->merge($this->getDropColumnInstructions(
849
                        $table->getName(),
850
                        $action->getColumn()->getName()
851
                    ));
852
                    break;
853
854
                case ($action instanceof RenameColumn):
855
                    $instructions->merge($this->getRenameColumnInstructions(
856
                        $table->getName(),
857
                        $action->getColumn()->getName(),
858
                        $action->getNewName()
859
                    ));
860
                    break;
861
862
                case ($action instanceof RenameTable):
863
                    $instructions->merge($this->getRenameTableInstructions(
864
                        $table->getName(),
865
                        $action->getNewName()
866
                    ));
867
                    break;
868
869
                case ($action instanceof ChangePrimaryKey):
870
                    $instructions->merge($this->getChangePrimaryKeyInstructions(
871
                        $table,
872
                        $action->getNewColumns()
873
                    ));
874
                    break;
875
876
                case ($action instanceof ChangeComment):
877
                    $instructions->merge($this->getChangeCommentInstructions(
878
                        $table,
879
                        $action->getNewComment()
880
                    ));
881
                    break;
882
883
                default:
884
                    throw new \InvalidArgumentException(
885
                        sprintf("Don't know how to execute action: '%s'", get_class($action))
886
                    );
887
            }
888
        }
889
890
        $this->executeAlterSteps($table->getName(), $instructions);
891
    }
892
}
893