Completed
Pull Request — master (#1517)
by
unknown
01:36
created

Table::addTimestampsWithAutoUpdate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 1

Importance

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