Completed
Pull Request — master (#1393)
by
unknown
01:51
created

Table   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 653
Duplicated Lines 4.75 %

Coupling/Cohesion

Components 1
Dependencies 18

Test Coverage

Coverage 96.24%

Importance

Changes 0
Metric Value
wmc 58
lcom 1
cbo 18
dl 31
loc 653
rs 4.507
c 0
b 0
f 0
ccs 205
cts 213
cp 0.9624

39 Methods

Rating   Name   Duplication   Size   Complexity  
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 exists() 0 4 1
A drop() 0 6 1
A rename() 0 6 1
A changePrimaryKey() 0 5 1
A changeComment() 0 5 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 addColumn() 5 21 3
A removeColumn() 0 7 1
A renameColumn() 0 7 1
A changeColumn() 5 11 2
A hasColumn() 0 4 1
A addIndex() 0 7 1
A removeIndex() 0 7 1
A removeIndexByName() 0 7 1
A hasIndex() 0 4 1
A hasIndexByName() 0 4 1
A addForeignKey() 7 7 1
A addForeignKeyWithName() 14 14 1
A dropForeignKey() 0 7 1
A hasForeignKey() 0 4 1
A addTimestamps() 0 18 3
A addTimestampsWithTimezone() 0 6 1
A insert() 0 14 4
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

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
 * 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
28
 */
29
namespace Phinx\Db;
30
31
use Phinx\Db\Action\AddColumn;
32
use Phinx\Db\Action\AddForeignKey;
33
use Phinx\Db\Action\AddIndex;
34
use Phinx\Db\Action\ChangeColumn;
35
use Phinx\Db\Action\ChangeComment;
36
use Phinx\Db\Action\ChangePrimaryKey;
37
use Phinx\Db\Action\CreateTable;
38
use Phinx\Db\Action\DropColumn;
39
use Phinx\Db\Action\DropForeignKey;
40
use Phinx\Db\Action\DropIndex;
41
use Phinx\Db\Action\DropTable;
42
use Phinx\Db\Action\RemoveColumn;
43
use Phinx\Db\Action\RenameColumn;
44
use Phinx\Db\Action\RenameTable;
45
use Phinx\Db\Adapter\AdapterInterface;
46
use Phinx\Db\Plan\Intent;
47
use Phinx\Db\Plan\Plan;
48
use Phinx\Db\Table\Column;
49
use Phinx\Db\Table\Table as TableValue;
50
51
/**
52
 *
53
 * This object is based loosely on: http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html.
54
 */
55
class Table
56
{
57
    /**
58
     * @var \Phinx\Db\Table\Table
59
     */
60
    protected $table;
61
62
    /**
63
     * @var \Phinx\Db\Adapter\AdapterInterface
64
     */
65
    protected $adapter;
66
67
    /**
68
     * @var \Phinx\Db\Plan\Intent
69
     */
70
    protected $actions;
71
72
    /**
73
     * @var array
74
     */
75
    protected $data = [];
76
77
    /**
78
     * Class Constructor.
79
     *
80
     * @param string $name Table Name
81
     * @param array $options Options
82
     * @param \Phinx\Db\Adapter\AdapterInterface $adapter Database Adapter
83
     */
84 239
    public function __construct($name, $options = [], AdapterInterface $adapter = null)
85
    {
86 239
        $this->table = new TableValue($name, $options);
87 239
        $this->actions = new Intent();
88
89 239
        if ($adapter !== null) {
90 231
            $this->setAdapter($adapter);
91 231
        }
92 239
    }
93
94
    /**
95
     * Gets the table name.
96
     *
97
     * @return string|null
98
     */
99
    public function getName()
100 239
    {
101
        return $this->table->getName();
102 239
    }
103 239
104
    /**
105
     * Gets the table options.
106
     *
107
     * @return array
108
     */
109
    public function getOptions()
110
    {
111 215
        return $this->table->getOptions();
112
    }
113 215
114
    /**
115
     * Gets the table name and options as an object
116
     *
117
     * @return \Phinx\Db\Table\Table
118
     */
119
    public function getTable()
120
    {
121
        return $this->table;
122 239
    }
123
124 239
    /**
125 239
     * Sets the database adapter.
126
     *
127
     * @param \Phinx\Db\Adapter\AdapterInterface $adapter Database Adapter
128
     * @return \Phinx\Db\Table
129
     */
130
    public function setAdapter(AdapterInterface $adapter)
131
    {
132
        $this->adapter = $adapter;
133 189
134
        return $this;
135 189
    }
136
137
    /**
138
     * Gets the database adapter.
139
     *
140
     * @return \Phinx\Db\Adapter\AdapterInterface|null
141
     */
142
    public function getAdapter()
143
    {
144 231
        if (!$this->adapter) {
145
            throw new \RuntimeException('There is no database adapter set yet, cannot proceed');
146 231
        }
147 231
148
        return $this->adapter;
149
    }
150
151
    /**
152
     * Does the table exist?
153
     *
154
     * @return bool
155 225
     */
156
    public function exists()
157 225
    {
158
        return $this->getAdapter()->hasTable($this->getName());
159
    }
160
161
    /**
162
     * Drops the database table.
163
     *
164
     * @return \Phinx\Db\Table
165 195
     */
166
    public function drop()
167 195
    {
168
        $this->actions->addAction(new DropTable($this->table));
169
170
        return $this;
171
    }
172
173
    /**
174
     * Renames the database table.
175 1
     *
176
     * @param string $newTableName New Table Name
177 1
     * @return \Phinx\Db\Table
178 1
     */
179
    public function rename($newTableName)
180
    {
181
        $this->actions->addAction(new RenameTable($this->table, $newTableName));
182
183
        return $this;
184
    }
185
186 3
    /**
187
     * Changes the primary key of the database table.
188 3
     *
189 3
     * @param string|array|null $columns Column name(s) to belong to the primary key, or null to drop the key
190 3
     * @return $this
191
     */
192
    public function changePrimaryKey($columns) {
193
        $this->actions->addAction(new ChangePrimaryKey($this->table, $columns));
194
195
        return $this;
196
    }
197
198
    /**
199
     * Changes the comment of the database table.
200
     *
201
     * @param string|null $comment New comment string, or null to drop the comment
202
     * @return $this
203
     */
204
    public function changeComment(string $comment = null) {
205
        $this->actions->addAction(new ChangeComment($this->table, $comment));
206
207
        return $this;
208
    }
209
210
    /**
211 10
     * Gets an array of the table columns.
212
     *
213 10
     * @return \Phinx\Db\Table\Column[]
214
     */
215
    public function getColumns()
216
    {
217
        return $this->getAdapter()->getColumns($this->getName());
218
    }
219
220
    /**
221
     * Gets a table column if it exists.
222 196
     *
223
     * @param string $name Column name
224 196
     * @return \Phinx\Db\Table\Column|null
225 196
     */
226
    public function getColumn($name)
227
    {
228
        $columns = array_filter(
229
            $this->getColumns(),
230
            function ($column) use ($name) {
231
                return $column->getName() === $name;
232
            }
233 204
        );
234
235 204
        return array_pop($columns);
236
    }
237
238
    /**
239
     * Sets an array of data to be inserted.
240
     *
241
     * @param array $data Data
242
     * @return \Phinx\Db\Table
243
     */
244 196
    public function setData($data)
245
    {
246 196
        $this->data = $data;
247 196
248
        return $this;
249
    }
250
251
    /**
252
     * Gets the data waiting to be inserted.
253
     *
254
     * @return array
255 191
     */
256
    public function getData()
257 191
    {
258
        return $this->data;
259
    }
260
261
    /**
262
     * Resets all of the pending data to be inserted
263
     *
264
     * @return void
265
     */
266 196
    public function resetData()
267
    {
268 196
        $this->setData([]);
269 196
    }
270
271
    /**
272
     * Resets all of the pending table changes.
273
     *
274
     * @return void
275
     */
276
    public function reset()
277 192
    {
278
        $this->actions = new Intent();
279 192
        $this->resetData();
280
    }
281
282
    /**
283
     * Add a table column.
284
     *
285
     * Type can be: string, text, integer, float, decimal, datetime, timestamp,
286
     * time, date, binary, boolean.
287
     *
288 196
     * Valid options can be: limit, default, null, precision or scale.
289
     *
290 196
     * @param string|\Phinx\Db\Table\Column $columnName Column Name
291 196
     * @param string|\Phinx\Util\Literal $type Column Type
292
     * @param array $options Column Options
293
     * @throws \RuntimeException
294
     * @throws \InvalidArgumentException
295
     * @return \Phinx\Db\Table
296
     */
297
    public function addColumn($columnName, $type = null, $options = [])
298
    {
299 197 View Code Duplication
        if ($columnName instanceof Column) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
300
            $action = new AddColumn($this->table, $columnName);
301 197
        } else {
302
            $action = AddColumn::build($this->table, $columnName, $type, $options);
303
        }
304
305
        // Delegate to Adapters to check column type
306
        if (!$this->getAdapter()->isValidColumnType($action->getColumn())) {
307
            throw new \InvalidArgumentException(sprintf(
308
                'An invalid column type "%s" was specified for column "%s".',
309 196
                $type,
310
                $action->getColumn()->getName()
311 196
            ));
312 196
        }
313 196
314 196
        $this->actions->addAction($action);
315 196
316
        return $this;
317
    }
318
319
    /**
320
     * Remove a table column.
321
     *
322
     * @param string $columnName Column Name
323
     * @return \Phinx\Db\Table
324
     */
325
    public function removeColumn($columnName)
326
    {
327
        $action = RemoveColumn::build($this->table, $columnName);
328
        $this->actions->addAction($action);
329
330
        return $this;
331
    }
332 210
333
    /**
334
     * Rename a table column.
335 210
     *
336 1
     * @param string $oldName Old Column Name
337
     * @param string $newName New Column Name
338
     * @return \Phinx\Db\Table
339
     */
340 209
    public function renameColumn($oldName, $newName)
341 207
    {
342 207
        $action = RenameColumn::build($this->table, $oldName, $newName);
343 207
        $this->actions->addAction($action);
344 207
345 207
        return $this;
346 2
    }
347
348
    /**
349
     * Change a table column type.
350 209
     *
351 1
     * @param string        $columnName    Column Name
352 1
     * @param string|\Phinx\Db\Table\Column|\Phinx\Util\Literal $newColumnType New Column Type
353 1
     * @param array         $options       Options
354 1
     * @return \Phinx\Db\Table
355 1
     */
356
    public function changeColumn($columnName, $newColumnType, array $options = [])
357
    {
358 208 View Code Duplication
        if ($newColumnType instanceof Column) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
359 208
            $action = new ChangeColumn($this->table, $columnName, $newColumnType);
360
        } else {
361
            $action = ChangeColumn::build($this->table, $columnName, $newColumnType, $options);
362
        }
363
        $this->actions->addAction($action);
364
365
        return $this;
366
    }
367
368 1
    /**
369
     * Checks to see if a column exists.
370 1
     *
371 1
     * @param string $columnName Column Name
372
     * @return bool
373
     */
374
    public function hasColumn($columnName)
375
    {
376
        return $this->getAdapter()->hasColumn($this->getName(), $columnName);
377
    }
378
379
    /**
380
     * Add an index to a database table.
381 4
     *
382
     * In $options you can specific unique = true/false or name (index name).
383 4
     *
384 4
     * @param string|array|\Phinx\Db\Table\Index $columns Table Column(s)
385
     * @param array $options Index Options
386
     * @return \Phinx\Db\Table
387
     */
388
    public function addIndex($columns, array $options = [])
389
    {
390
        $action = AddIndex::build($this->table, $columns, $options);
391
        $this->actions->addAction($action);
392
393
        return $this;
394
    }
395 17
396
    /**
397
     * Removes the given index from a table.
398 17
     *
399 4
     * @param array $columns Columns
400 4
     * @return \Phinx\Db\Table
401 4
     */
402 4
    public function removeIndex(array $columns)
403 13
    {
404
        $action = DropIndex::build($this->table, $columns);
405
        $this->actions->addAction($action);
406
407 17
        return $this;
408 15
    }
409 15
410
    /**
411 17
     * Removes the given index identified by its name from a table.
412 17
     *
413
     * @param string $name Index name
414
     * @return \Phinx\Db\Table
415
     */
416
    public function removeIndexByName($name)
417
    {
418
        $action = DropIndex::buildFromName($this->table, $name);
419
        $this->actions->addAction($action);
420
421 89
        return $this;
422
    }
423 89
424
    /**
425
     * Checks to see if an index exists.
426
     *
427
     * @param string|array $columns Columns
428
     * @return bool
429
     */
430
    public function hasIndex($columns)
431
    {
432
        return $this->getAdapter()->hasIndex($this->getName(), $columns);
433
    }
434
435 29
    /**
436
     * Checks to see if an index specified by name exists.
437
     *
438 29
     * @param string $indexName
439 28
     * @return bool
440 28
     */
441 22
    public function hasIndexByName($indexName)
442 22
    {
443 28
        return $this->getAdapter()->hasIndexByName($this->getName(), $indexName);
444 28
    }
445 28
446 1
    /**
447
     * Add a foreign key to a database table.
448
     *
449 29
     * In $options you can specify on_delete|on_delete = cascade|no_action ..,
450 29
     * on_update, constraint = constraint name.
451
     *
452
     * @param string|array $columns Columns
453
     * @param string|\Phinx\Db\Table $referencedTable   Referenced Table
454
     * @param string|array $referencedColumns Referenced Columns
455
     * @param array $options Options
456
     * @return \Phinx\Db\Table
457
     */
458 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...
459 1
    {
460
        $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 458 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 458 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...
461 1
        $this->actions->addAction($action);
462 1
463
        return $this;
464
    }
465
466
    /**
467
     * Add a foreign key to a database table with a given name.
468
     *
469
     * In $options you can specify on_delete|on_delete = cascade|no_action ..,
470
     * on_update, constraint = constraint name.
471 1
     *
472
     * @param string $name The constraint name
473 1
     * @param string|array $columns Columns
474 1
     * @param string|\Phinx\Db\Table $referencedTable   Referenced Table
475
     * @param string|array $referencedColumns Referenced Columns
476
     * @param array $options Options
477
     * @return \Phinx\Db\Table
478
     */
479 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...
480
    {
481
        $action = AddForeignKey::build(
482
            $this->table,
483
            $columns,
0 ignored issues
show
Bug introduced by
It seems like $columns defined by parameter $columns on line 479 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...
484 12
            $referencedTable,
0 ignored issues
show
Bug introduced by
It seems like $referencedTable defined by parameter $referencedTable on line 479 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...
485
            $referencedColumns,
486 12
            $options,
487
            $name
488
        );
489
        $this->actions->addAction($action);
490
491
        return $this;
492
    }
493
494
    /**
495
     * Removes the given foreign key from the table.
496
     *
497
     * @param string|array $columns    Column(s)
498
     * @param null|string  $constraint Constraint names
499
     * @return \Phinx\Db\Table
500
     */
501 8
    public function dropForeignKey($columns, $constraint = null)
502
    {
503 8
        $action = DropForeignKey::build($this->table, $columns, $constraint);
0 ignored issues
show
Bug introduced by
It seems like $columns defined by parameter $columns on line 501 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...
504 4
        $this->actions->addAction($action);
505 4
506 8
        return $this;
507 8
    }
508
509
    /**
510 8
     * Checks to see if a foreign key exists.
511
     *
512 8
     * @param  string|array $columns    Column(s)
513 8
     * @param  null|string  $constraint Constraint names
514 8
     * @return bool
515 8
     */
516
    public function hasForeignKey($columns, $constraint = null)
517 8
    {
518
        return $this->getAdapter()->hasForeignKey($this->getName(), $columns, $constraint);
0 ignored issues
show
Documentation introduced by
$columns is of type string|array, but the function expects a array<integer,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...
519
    }
520
521
    /**
522
     * Add timestamp columns created_at and updated_at to the table.
523
     *
524
     * @param string|null $createdAt    Alternate name for the created_at column
525
     * @param string|null $updatedAt    Alternate name for the updated_at column
526
     * @param bool        $withTimezone Whether to set the timezone option on the added columns
527 1
     *
528
     * @return \Phinx\Db\Table
529 1
     */
530 1
    public function addTimestamps($createdAt = 'created_at', $updatedAt = 'updated_at', $withTimezone = false)
531 1
    {
532 1
        $createdAt = is_null($createdAt) ? 'created_at' : $createdAt;
533
        $updatedAt = is_null($updatedAt) ? 'updated_at' : $updatedAt;
534
535 1
        $this->addColumn($createdAt, 'timestamp', [
536
                   'default' => 'CURRENT_TIMESTAMP',
537
                   'update' => '',
538 1
                   'timezone' => $withTimezone,
539
             ])
540
             ->addColumn($updatedAt, 'timestamp', [
541
                 'null' => true,
542
                 'default' => null,
543
                 'timezone' => $withTimezone,
544
             ]);
545
546
        return $this;
547
    }
548 1
549
    /**
550 1
     * Alias that always sets $withTimezone to true
551
     * @see addTimestamps
552
     *
553
     * @param string|null $createdAt Alternate name for the created_at column
554
     * @param string|null $updatedAt Alternate name for the updated_at column
555
     *
556
     * @return \Phinx\Db\Table
557
     */
558
    public function addTimestampsWithTimezone($createdAt = null, $updatedAt = null)
559
    {
560
        $this->addTimestamps($createdAt, $updatedAt, true);
561 15
562
        return $this;
563 15
    }
564 15
565 15
    /**
566 15
     * Insert data into the table.
567
     *
568 15
     * @param array $data array of data in the form:
569 15
     *              array(
570 15
     *                  array("col1" => "value1", "col2" => "anotherValue1"),
571
     *                  array("col2" => "value2", "col2" => "anotherValue2"),
572 15
     *              )
573
     *              or array("col1" => "value1", "col2" => "anotherValue1")
574 15
     *
575
     * @return \Phinx\Db\Table
576
     */
577
    public function insert($data)
578
    {
579
        // handle array of array situations
580
        if (isset($data[0]) && is_array($data[0])) {
581
            foreach ($data as $row) {
582
                $this->data[] = $row;
583
            }
584
585
            return $this;
586
        }
587
        $this->data[] = $data;
588
589 17
        return $this;
590
    }
591
592 17
    /**
593 11
     * Creates a table from the object instance.
594 11
     *
595 11
     * @return void
596 11
     */
597
    public function create()
598 8
    {
599 8
        $this->executeActions(false);
600
        $this->saveData();
601
        $this->reset(); // reset pending changes
602
    }
603
604
    /**
605
     * Updates a table from the object instance.
606
     *
607 196
     * @throws \RuntimeException
608
     * @return void
609 196
     */
610 196
    public function update()
611 196
    {
612 196
        $this->executeActions(true);
613
        $this->saveData();
614
        $this->reset(); // reset pending changes
615
    }
616
617
    /**
618
     * Commit the pending data waiting for insertion.
619
     *
620 46
     * @return void
621
     */
622 46
    public function saveData()
623
    {
624
        $rows = $this->getData();
625
        if (empty($rows)) {
626
            return;
627 46
        }
628 38
629 46
        $bulk = true;
630
        $row = current($rows);
631 46
        $c = array_keys($row);
632 6
        foreach ($this->getData() as $row) {
633 46
            $k = array_keys($row);
634
            if ($k != $c) {
635 46
                $bulk = false;
636 3
                break;
637 46
            }
638
        }
639 46
640 46
        if ($bulk) {
641 46
            $this->getAdapter()->bulkinsert($this->table, $this->getData());
642
        } else {
643
            foreach ($this->getData() as $row) {
644
                $this->getAdapter()->insert($this->table, $row);
645
            }
646
        }
647
648 196
        $this->resetData();
649
    }
650 196
651 196
    /**
652 192
     * Immediately truncates the table. This operation cannot be undone
653
     *
654
     * @return void
655 12
     */
656 12
    public function truncate()
657 12
    {
658 12
        $this->getAdapter()->truncateTable($this->getName());
659 12
    }
660 12
661 1
    /**
662 1
     * Commits the table changes.
663
     *
664 12
     * If the table doesn't exist it is created otherwise it is updated.
665
     *
666 12
     * @return void
667 11
     */
668 11
    public function save()
669 1
    {
670 1
        if ($this->exists()) {
671 1
            $this->update(); // update the table
672
        } else {
673 12
            $this->create(); // create the table
674
        }
675
    }
676
677
    /**
678
     * Executes all the pending actions for this table
679
     *
680 2
     * @param bool $exists Whether or not the table existed prior to executing this method
681
     * @return void
682 2
     */
683 2
    protected function executeActions($exists)
684
    {
685
        // Renaming a table is tricky, specially when running a reversible migration
686
        // down. We will just assume the table already exists if the user commands a
687
        // table rename.
688
        $renamed = collection($this->actions->getActions())
689
            ->filter(function ($action) {
690
                return $action instanceof RenameTable;
691
            })
692 195
            ->first();
693
694 195
        if ($renamed) {
695 45
            $exists = true;
696 45
        }
697 195
698
        // If the table does not exist, the last command in the chain needs to be
699
        // a CreateTable action.
700 195
        if (!$exists) {
701 195
            $this->actions->addAction(new CreateTable($this->table));
702
        }
703
704
        $plan = new Plan($this->actions);
705
        $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...
706
    }
707
}
708