Completed
Pull Request — master (#1687)
by
unknown
01:29
created

Table   F

Complexity

Total Complexity 65

Size/Duplication

Total Lines 694
Duplicated Lines 3.03 %

Coupling/Cohesion

Components 1
Dependencies 18

Test Coverage

Coverage 96.24%

Importance

Changes 0
Metric Value
wmc 65
lcom 1
cbo 18
dl 21
loc 694
ccs 205
cts 213
cp 0.9624
rs 3.106
c 0
b 0
f 0

40 Methods

Rating   Name   Duplication   Size   Complexity  
A removeColumn() 0 7 1
A addForeignKeyWithName() 14 14 1
A addForeignKey() 7 7 1
A __construct() 0 9 2
A getName() 0 4 1
A getOptions() 0 4 1
A getTable() 0 4 1
A setAdapter() 0 6 1
A getAdapter() 0 8 2
A hasPendingActions() 0 4 2
A exists() 0 4 1
A drop() 0 6 1
A rename() 0 6 1
A changePrimaryKey() 0 6 1
A changeComment() 0 6 1
A getColumns() 0 4 1
A getColumn() 0 11 1
A setData() 0 6 1
A getData() 0 4 1
A resetData() 0 4 1
A reset() 0 5 1
A renameColumn() 0 7 1
A changeColumn() 0 11 2
A hasColumn() 0 4 1
A addIndex() 0 7 1
A removeIndex() 0 7 2
A removeIndexByName() 0 7 1
A hasIndex() 0 4 1
A hasIndexByName() 0 4 1
A dropForeignKey() 0 7 1
A hasForeignKey() 0 4 1
A addTimestamps() 0 18 3
A addTimestampsWithTimezone() 0 6 1
A insert() 0 19 5
A create() 0 6 1
A update() 0 6 1
B saveData() 0 28 6
A save() 0 8 2
A executeActions() 0 24 3
B addColumn() 0 24 6

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Table often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Table, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/**
4
 * MIT License
5
 * For full license information, please view the LICENSE file that was distributed with this source code.
6
 */
7
8
namespace Phinx\Db;
9
10
use InvalidArgumentException;
11
use Phinx\Db\Action\AddColumn;
12
use Phinx\Db\Action\AddForeignKey;
13
use Phinx\Db\Action\AddIndex;
14
use Phinx\Db\Action\ChangeColumn;
15
use Phinx\Db\Action\ChangeComment;
16
use Phinx\Db\Action\ChangePrimaryKey;
17
use Phinx\Db\Action\CreateTable;
18
use Phinx\Db\Action\DropForeignKey;
19
use Phinx\Db\Action\DropIndex;
20
use Phinx\Db\Action\DropTable;
21
use Phinx\Db\Action\RemoveColumn;
22
use Phinx\Db\Action\RenameColumn;
23
use Phinx\Db\Action\RenameTable;
24
use Phinx\Db\Adapter\AdapterInterface;
25
use Phinx\Db\Plan\Intent;
26
use Phinx\Db\Plan\Plan;
27
use Phinx\Db\Table\Column;
28
use Phinx\Db\Table\Table as TableValue;
29
use RuntimeException;
30
31
/**
32
 * This object is based loosely on: http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html.
33
 */
34
class Table
35
{
36
    /**
37
     * @var \Phinx\Db\Table\Table
38
     */
39
    protected $table;
40
41
    /**
42
     * @var \Phinx\Db\Adapter\AdapterInterface
43
     */
44
    protected $adapter;
45
46
    /**
47
     * @var \Phinx\Db\Plan\Intent
48
     */
49
    protected $actions;
50
51
    /**
52
     * @var array
53
     */
54
    protected $data = [];
55
56
    /**
57
     * @param string $name Table Name
58
     * @param array $options Options
59
     * @param \Phinx\Db\Adapter\AdapterInterface|null $adapter Database Adapter
60
     */
61
    public function __construct($name, $options = [], AdapterInterface $adapter = null)
62
    {
63
        $this->table = new TableValue($name, $options);
64
        $this->actions = new Intent();
65
66
        if ($adapter !== null) {
67
            $this->setAdapter($adapter);
68
        }
69
    }
70
71
    /**
72
     * Gets the table name.
73
     *
74
     * @return string|null
75
     */
76
    public function getName()
77
    {
78
        return $this->table->getName();
79
    }
80
81
    /**
82
     * Gets the table options.
83
     *
84 239
     * @return array
85
     */
86 239
    public function getOptions()
87 239
    {
88
        return $this->table->getOptions();
89 239
    }
90 231
91 231
    /**
92 239
     * Gets the table name and options as an object
93
     *
94
     * @return \Phinx\Db\Table\Table
95
     */
96
    public function getTable()
97
    {
98
        return $this->table;
99
    }
100 239
101
    /**
102 239
     * Sets the database adapter.
103 239
     *
104
     * @param \Phinx\Db\Adapter\AdapterInterface $adapter Database Adapter
105
     *
106
     * @return $this
107
     */
108
    public function setAdapter(AdapterInterface $adapter)
109
    {
110
        $this->adapter = $adapter;
111 215
112
        return $this;
113 215
    }
114
115
    /**
116
     * Gets the database adapter.
117
     *
118
     * @throws \RuntimeException
119
     *
120
     * @return \Phinx\Db\Adapter\AdapterInterface|null
121
     */
122 239
    public function getAdapter()
123
    {
124 239
        if (!$this->adapter) {
125 239
            throw new RuntimeException('There is no database adapter set yet, cannot proceed');
126
        }
127
128
        return $this->adapter;
129
    }
130
131
    /**
132
     * Does the table have pending actions?
133 189
     *
134
     * @return bool
135 189
     */
136
    public function hasPendingActions()
137
    {
138
        return count($this->actions->getActions()) > 0 || count($this->data) > 0;
139
    }
140
141
    /**
142
     * Does the table exist?
143
     *
144 231
     * @return bool
145
     */
146 231
    public function exists()
147 231
    {
148
        return $this->getAdapter()->hasTable($this->getName());
149
    }
150
151
    /**
152
     * Drops the database table.
153
     *
154
     * @return $this
155 225
     */
156
    public function drop()
157 225
    {
158
        $this->actions->addAction(new DropTable($this->table));
159
160
        return $this;
161
    }
162
163
    /**
164
     * Renames the database table.
165 195
     *
166
     * @param string $newTableName New Table Name
167 195
     *
168
     * @return $this
169
     */
170
    public function rename($newTableName)
171
    {
172
        $this->actions->addAction(new RenameTable($this->table, $newTableName));
173
174
        return $this;
175 1
    }
176
177 1
    /**
178 1
     * Changes the primary key of the database table.
179
     *
180
     * @param string|array|null $columns Column name(s) to belong to the primary key, or null to drop the key
181
     *
182
     * @return $this
183
     */
184
    public function changePrimaryKey($columns)
185
    {
186 3
        $this->actions->addAction(new ChangePrimaryKey($this->table, $columns));
187
188 3
        return $this;
189 3
    }
190 3
191
    /**
192
     * Changes the comment of the database table.
193
     *
194
     * @param string|null $comment New comment string, or null to drop the comment
195
     *
196
     * @return $this
197
     */
198
    public function changeComment($comment)
199
    {
200
        $this->actions->addAction(new ChangeComment($this->table, $comment));
201
202
        return $this;
203
    }
204
205
    /**
206
     * Gets an array of the table columns.
207
     *
208
     * @return \Phinx\Db\Table\Column[]
209
     */
210
    public function getColumns()
211 10
    {
212
        return $this->getAdapter()->getColumns($this->getName());
213 10
    }
214
215
    /**
216
     * Gets a table column if it exists.
217
     *
218
     * @param string $name Column name
219
     *
220
     * @return \Phinx\Db\Table\Column|null
221
     */
222 196
    public function getColumn($name)
223
    {
224 196
        $columns = array_filter(
225 196
            $this->getColumns(),
226
            function ($column) use ($name) {
227
                return $column->getName() === $name;
228
            }
229
        );
230
231
        return array_pop($columns);
232
    }
233 204
234
    /**
235 204
     * Sets an array of data to be inserted.
236
     *
237
     * @param array $data Data
238
     *
239
     * @return $this
240
     */
241
    public function setData($data)
242
    {
243
        $this->data = $data;
244 196
245
        return $this;
246 196
    }
247 196
248
    /**
249
     * Gets the data waiting to be inserted.
250
     *
251
     * @return array
252
     */
253
    public function getData()
254
    {
255 191
        return $this->data;
256
    }
257 191
258
    /**
259
     * Resets all of the pending data to be inserted
260
     *
261
     * @return void
262
     */
263
    public function resetData()
264
    {
265
        $this->setData([]);
266 196
    }
267
268 196
    /**
269 196
     * Resets all of the pending table changes.
270
     *
271
     * @return void
272
     */
273
    public function reset()
274
    {
275
        $this->actions = new Intent();
276
        $this->resetData();
277 192
    }
278
279 192
    /**
280
     * Add a table column.
281
     *
282
     * Type can be: string, text, integer, float, decimal, datetime, timestamp,
283
     * time, date, binary, boolean.
284
     *
285
     * Valid options can be: limit, default, null, precision or scale.
286
     *
287
     * @param string|\Phinx\Db\Table\Column $columnName Column Name
288 196
     * @param string|\Phinx\Util\Literal|null $type Column Type
289
     * @param array $options Column Options
290 196
     *
291 196
     * @throws \InvalidArgumentException
292
     *
293
     * @return $this
294
     */
295
    public function addColumn($columnName, $type = null, $options = [])
296
    {
297
        if ($columnName instanceof Column) {
298
            $action = new AddColumn($this->table, $columnName);
299 197
        } else {
300
            if ('sqlite' == $this->getAdapter()->getAdapterType() || 'sqlite' == (getenv('PHINX_TESTING_ADAPTER'))) {
301 197
                array_key_exists('null', $options) ?: $options['null'] = true;
302
            }
303
            $action = AddColumn::build($this->table, $columnName, $type, $options);
304
        }
305
306
        // Delegate to Adapters to check column type
307
        if (!$this->getAdapter()->isValidColumnType($action->getColumn())) {
308
            throw new InvalidArgumentException(sprintf(
309 196
                'An invalid column type "%s" was specified for column "%s".',
310
                $type,
311 196
                $action->getColumn()->getName()
312 196
            ));
313 196
        }
314 196
315 196
        $this->actions->addAction($action);
316
317
        return $this;
318
    }
319
320
    /**
321
     * Remove a table column.
322
     *
323
     * @param string $columnName Column Name
324
     *
325
     * @return $this
326
     */
327
    public function removeColumn($columnName)
328
    {
329
        $action = RemoveColumn::build($this->table, $columnName);
330
        $this->actions->addAction($action);
331
332 210
        return $this;
333
    }
334
335 210
    /**
336 1
     * Rename a table column.
337
     *
338
     * @param string $oldName Old Column Name
339
     * @param string $newName New Column Name
340 209
     *
341 207
     * @return $this
342 207
     */
343 207
    public function renameColumn($oldName, $newName)
344 207
    {
345 207
        $action = RenameColumn::build($this->table, $oldName, $newName);
346 2
        $this->actions->addAction($action);
347
348
        return $this;
349
    }
350 209
351 1
    /**
352 1
     * Change a table column type.
353 1
     *
354 1
     * @param string $columnName Column Name
355 1
     * @param string|\Phinx\Db\Table\Column|\Phinx\Util\Literal $newColumnType New Column Type
356
     * @param array $options Options
357
     *
358 208
     * @return $this
359 208
     */
360
    public function changeColumn($columnName, $newColumnType, array $options = [])
361
    {
362
        if ($newColumnType instanceof Column) {
363
            $action = new ChangeColumn($this->table, $columnName, $newColumnType);
364
        } else {
365
            $action = ChangeColumn::build($this->table, $columnName, $newColumnType, $options);
366
        }
367
        $this->actions->addAction($action);
368 1
369
        return $this;
370 1
    }
371 1
372
    /**
373
     * Checks to see if a column exists.
374
     *
375
     * @param string $columnName Column Name
376
     *
377
     * @return bool
378
     */
379
    public function hasColumn($columnName)
380
    {
381 4
        return $this->getAdapter()->hasColumn($this->getName(), $columnName);
382
    }
383 4
384 4
    /**
385
     * Add an index to a database table.
386
     *
387
     * In $options you can specific unique = true/false or name (index name).
388
     *
389
     * @param string|array|\Phinx\Db\Table\Index $columns Table Column(s)
390
     * @param array $options Index Options
391
     *
392
     * @return $this
393
     */
394
    public function addIndex($columns, array $options = [])
395 17
    {
396
        $action = AddIndex::build($this->table, $columns, $options);
397
        $this->actions->addAction($action);
398 17
399 4
        return $this;
400 4
    }
401 4
402 4
    /**
403 13
     * Removes the given index from a table.
404
     *
405
     * @param string|array $columns Columns
406
     *
407 17
     * @return $this
408 15
     */
409 15
    public function removeIndex($columns)
410
    {
411 17
        $action = DropIndex::build($this->table, is_string($columns) ? [$columns] : $columns);
412 17
        $this->actions->addAction($action);
413
414
        return $this;
415
    }
416
417
    /**
418
     * Removes the given index identified by its name from a table.
419
     *
420
     * @param string $name Index name
421 89
     *
422
     * @return $this
423 89
     */
424
    public function removeIndexByName($name)
425
    {
426
        $action = DropIndex::buildFromName($this->table, $name);
427
        $this->actions->addAction($action);
428
429
        return $this;
430
    }
431
432
    /**
433
     * Checks to see if an index exists.
434
     *
435 29
     * @param string|array $columns Columns
436
     *
437
     * @return bool
438 29
     */
439 28
    public function hasIndex($columns)
440 28
    {
441 22
        return $this->getAdapter()->hasIndex($this->getName(), $columns);
0 ignored issues
show
Bug introduced by
It seems like $columns defined by parameter $columns on line 439 can also be of type array; however, Phinx\Db\Adapter\AdapterInterface::hasIndex() does only seem to accept string|array<integer,string>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
442 22
    }
443 28
444 28
    /**
445 28
     * Checks to see if an index specified by name exists.
446 1
     *
447
     * @param string $indexName
448
     *
449 29
     * @return bool
450 29
     */
451
    public function hasIndexByName($indexName)
452
    {
453
        return $this->getAdapter()->hasIndexByName($this->getName(), $indexName);
454
    }
455
456
    /**
457
     * Add a foreign key to a database table.
458
     *
459 1
     * In $options you can specify on_delete|on_delete = cascade|no_action ..,
460
     * on_update, constraint = constraint name.
461 1
     *
462 1
     * @param string|array $columns Columns
463
     * @param string|\Phinx\Db\Table $referencedTable Referenced Table
464
     * @param string|array $referencedColumns Referenced Columns
465
     * @param array $options Options
466
     *
467
     * @return $this
468
     */
469 View Code Duplication
    public function addForeignKey($columns, $referencedTable, $referencedColumns = ['id'], $options = [])
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...
470
    {
471 1
        $action = AddForeignKey::build($this->table, $columns, $referencedTable, $referencedColumns, $options);
0 ignored issues
show
Bug introduced by
It seems like $columns defined by parameter $columns on line 469 can also be of type array; however, Phinx\Db\Action\AddForeignKey::build() does only seem to accept string|array<integer,string>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
Bug introduced by
It seems like $referencedTable defined by parameter $referencedTable on line 469 can also be of type object<Phinx\Db\Table>; however, Phinx\Db\Action\AddForeignKey::build() does only seem to accept object<Phinx\Db\Table\Table>|string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
472
        $this->actions->addAction($action);
473 1
474 1
        return $this;
475
    }
476
477
    /**
478
     * Add a foreign key to a database table with a given name.
479
     *
480
     * In $options you can specify on_delete|on_delete = cascade|no_action ..,
481
     * on_update, constraint = constraint name.
482
     *
483
     * @param string $name The constraint name
484 12
     * @param string|array $columns Columns
485
     * @param string|\Phinx\Db\Table $referencedTable Referenced Table
486 12
     * @param string|array $referencedColumns Referenced Columns
487
     * @param array $options Options
488
     *
489
     * @return $this
490
     */
491 View Code Duplication
    public function addForeignKeyWithName($name, $columns, $referencedTable, $referencedColumns = ['id'], $options = [])
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...
492
    {
493
        $action = AddForeignKey::build(
494
            $this->table,
495
            $columns,
0 ignored issues
show
Bug introduced by
It seems like $columns defined by parameter $columns on line 491 can also be of type array; however, Phinx\Db\Action\AddForeignKey::build() does only seem to accept string|array<integer,string>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
496
            $referencedTable,
0 ignored issues
show
Bug introduced by
It seems like $referencedTable defined by parameter $referencedTable on line 491 can also be of type object<Phinx\Db\Table>; however, Phinx\Db\Action\AddForeignKey::build() does only seem to accept object<Phinx\Db\Table\Table>|string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
497
            $referencedColumns,
498
            $options,
499
            $name
500
        );
501 8
        $this->actions->addAction($action);
502
503 8
        return $this;
504 4
    }
505 4
506 8
    /**
507 8
     * Removes the given foreign key from the table.
508
     *
509
     * @param string|array $columns Column(s)
510 8
     * @param string|null $constraint Constraint names
511
     *
512 8
     * @return $this
513 8
     */
514 8
    public function dropForeignKey($columns, $constraint = null)
515 8
    {
516
        $action = DropForeignKey::build($this->table, $columns, $constraint);
0 ignored issues
show
Bug introduced by
It seems like $columns defined by parameter $columns on line 514 can also be of type array; however, Phinx\Db\Action\DropForeignKey::build() does only seem to accept string|array<integer,string>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
517 8
        $this->actions->addAction($action);
518
519
        return $this;
520
    }
521
522
    /**
523
     * Checks to see if a foreign key exists.
524
     *
525
     * @param string|array $columns Column(s)
526
     * @param string|null $constraint Constraint names
527 1
     *
528
     * @return bool
529 1
     */
530 1
    public function hasForeignKey($columns, $constraint = null)
531 1
    {
532 1
        return $this->getAdapter()->hasForeignKey($this->getName(), $columns, $constraint);
0 ignored issues
show
Bug introduced by
It seems like $columns defined by parameter $columns on line 530 can also be of type array; however, Phinx\Db\Adapter\AdapterInterface::hasForeignKey() does only seem to accept string|array<integer,string>, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and 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...
533
    }
534
535 1
    /**
536
     * Add timestamp columns created_at and updated_at to the table.
537
     *
538 1
     * @param string|null $createdAt Alternate name for the created_at column
539
     * @param string|null $updatedAt Alternate name for the updated_at column
540
     * @param bool $withTimezone Whether to set the timezone option on the added columns
541
     *
542
     * @return $this
543
     */
544
    public function addTimestamps($createdAt = 'created_at', $updatedAt = 'updated_at', $withTimezone = false)
545
    {
546
        $createdAt = $createdAt === null ? 'created_at' : $createdAt;
547
        $updatedAt = $updatedAt === null ? 'updated_at' : $updatedAt;
548 1
549
        $this->addColumn($createdAt, 'timestamp', [
550 1
                   'default' => 'CURRENT_TIMESTAMP',
551
                   'update' => '',
552
                   'timezone' => $withTimezone,
553
             ])
554
             ->addColumn($updatedAt, 'timestamp', [
555
                 'null' => true,
556
                 'default' => null,
557
                 'timezone' => $withTimezone,
558
             ]);
559
560
        return $this;
561 15
    }
562
563 15
    /**
564 15
     * Alias that always sets $withTimezone to true
565 15
     *
566 15
     * @see addTimestamps
567
     *
568 15
     * @param string|null $createdAt Alternate name for the created_at column
569 15
     * @param string|null $updatedAt Alternate name for the updated_at column
570 15
     *
571
     * @return $this
572 15
     */
573
    public function addTimestampsWithTimezone($createdAt = null, $updatedAt = null)
574 15
    {
575
        $this->addTimestamps($createdAt, $updatedAt, true);
576
577
        return $this;
578
    }
579
580
    /**
581
     * Insert data into the table.
582
     *
583
     * @param array $data array of data in the form:
584
     *              array(
585
     *                  array("col1" => "value1", "col2" => "anotherValue1"),
586
     *                  array("col2" => "value2", "col2" => "anotherValue2"),
587
     *              )
588
     *              or array("col1" => "value1", "col2" => "anotherValue1")
589 17
     *
590
     * @return $this
591
     */
592 17
    public function insert($data)
593 11
    {
594 11
        // handle array of array situations
595 11
        $keys = array_keys($data);
596 11
        $firstKey = array_shift($keys);
597
        if ($firstKey !== null && is_array($data[$firstKey])) {
598 8
            foreach ($data as $row) {
599 8
                $this->data[] = $row;
600
            }
601
602
            return $this;
603
        }
604
605
        if (count($data) > 0) {
606
            $this->data[] = $data;
607 196
        }
608
609 196
        return $this;
610 196
    }
611 196
612 196
    /**
613
     * Creates a table from the object instance.
614
     *
615
     * @return void
616
     */
617
    public function create()
618
    {
619
        $this->executeActions(false);
620 46
        $this->saveData();
621
        $this->reset(); // reset pending changes
622 46
    }
623
624
    /**
625
     * Updates a table from the object instance.
626
     *
627 46
     * @return void
628 38
     */
629 46
    public function update()
630
    {
631 46
        $this->executeActions(true);
632 6
        $this->saveData();
633 46
        $this->reset(); // reset pending changes
634
    }
635 46
636 3
    /**
637 46
     * Commit the pending data waiting for insertion.
638
     *
639 46
     * @return void
640 46
     */
641 46
    public function saveData()
642
    {
643
        $rows = $this->getData();
644
        if (empty($rows)) {
645
            return;
646
        }
647
648 196
        $bulk = true;
649
        $row = current($rows);
650 196
        $c = array_keys($row);
651 196
        foreach ($this->getData() as $row) {
652 192
            $k = array_keys($row);
653
            if ($k != $c) {
654
                $bulk = false;
655 12
                break;
656 12
            }
657 12
        }
658 12
659 12
        if ($bulk) {
660 12
            $this->getAdapter()->bulkinsert($this->table, $this->getData());
661 1
        } else {
662 1
            foreach ($this->getData() as $row) {
663
                $this->getAdapter()->insert($this->table, $row);
664 12
            }
665
        }
666 12
667 11
        $this->resetData();
668 11
    }
669 1
670 1
    /**
671 1
     * Immediately truncates the table. This operation cannot be undone
672
     *
673 12
     * @return void
674
     */
675
    public function truncate()
676
    {
677
        $this->getAdapter()->truncateTable($this->getName());
678
    }
679
680 2
    /**
681
     * Commits the table changes.
682 2
     *
683 2
     * If the table doesn't exist it is created otherwise it is updated.
684
     *
685
     * @return void
686
     */
687
    public function save()
688
    {
689
        if ($this->exists()) {
690
            $this->update(); // update the table
691
        } else {
692 195
            $this->create(); // create the table
693
        }
694 195
    }
695 45
696 45
    /**
697 195
     * Executes all the pending actions for this table
698
     *
699
     * @param bool $exists Whether or not the table existed prior to executing this method
700 195
     *
701 195
     * @return void
702
     */
703
    protected function executeActions($exists)
704
    {
705
        // Renaming a table is tricky, specially when running a reversible migration
706
        // down. We will just assume the table already exists if the user commands a
707
        // table rename.
708
        $renamed = collection($this->actions->getActions())
709
            ->filter(function ($action) {
710
                return $action instanceof RenameTable;
711
            })
712
            ->first();
713
714
        if ($renamed) {
715
            $exists = true;
716
        }
717
718
        // If the table does not exist, the last command in the chain needs to be
719
        // a CreateTable action.
720
        if (!$exists) {
721
            $this->actions->addAction(new CreateTable($this->table));
722
        }
723
724
        $plan = new Plan($this->actions);
725
        $plan->execute($this->getAdapter());
0 ignored issues
show
Bug introduced by
It seems like $this->getAdapter() can be null; however, execute() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
726
    }
727
}
728