Completed
Pull Request — master (#1175)
by David Joseph
01:40
created

Table   C

Complexity

Total Complexity 70

Size/Duplication

Total Lines 712
Duplicated Lines 2.25 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 96.24%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 70
lcom 1
cbo 5
dl 16
loc 712
ccs 205
cts 213
cp 0.9624
rs 5
c 3
b 0
f 0

40 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
A setName() 0 6 1
A getName() 0 4 1
A setOptions() 0 6 1
A getOptions() 0 4 1
A setAdapter() 0 6 1
A getAdapter() 0 4 1
A exists() 0 4 1
A drop() 0 4 1
A rename() 0 7 1
A setColumns() 0 6 1
A getColumns() 0 4 1
A setPendingColumns() 0 6 1
A getPendingColumns() 0 4 1
A setIndexes() 0 6 1
A getIndexes() 0 4 1
A setForeignKeys() 0 6 1
A getForeignKeys() 0 4 1
A setData() 0 6 1
A getData() 0 4 1
A reset() 0 7 1
B addColumn() 8 30 4
A addCustomColumn() 8 15 2
A removeColumn() 0 6 1
A renameColumn() 0 6 1
A changeColumn() 0 20 4
A hasColumn() 0 4 1
A addIndex() 0 18 3
A removeIndex() 0 6 1
A removeIndexByName() 0 6 1
A hasIndex() 0 4 1
A addForeignKey() 0 18 3
A dropForeignKey() 0 13 3
A hasForeignKey() 0 4 1
A addTimestamps() 0 15 3
A insert() 0 14 4
A create() 0 6 1
B update() 0 22 5
B saveData() 0 26 6
A save() 0 10 2

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\Adapter\AdapterInterface;
32
use Phinx\Db\Table\Column;
33
use Phinx\Db\Table\CustomColumn;
34
use Phinx\Db\Table\ForeignKey;
35
use Phinx\Db\Table\Index;
36
37
/**
38
 *
39
 * This object is based loosely on: http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/Table.html.
40
 */
41
class Table
42
{
43
    /**
44
     * @var string
45
     */
46
    protected $name;
47
48
    /**
49
     * @var array
50
     */
51
    protected $options = [];
52
53
    /**
54
     * @var \Phinx\Db\Adapter\AdapterInterface
55
     */
56
    protected $adapter;
57
58
    /**
59
     * @var array
60
     */
61
    protected $columns = [];
62
63
    /**
64
     * @var array
65
     */
66
    protected $indexes = [];
67
68
    /**
69
     * @var \Phinx\Db\Table\ForeignKey[]
70
     */
71
    protected $foreignKeys = [];
72
73
    /**
74
     * @var array
75
     */
76
    protected $data = [];
77
78
    /**
79
     * Class Constuctor.
80
     *
81
     * @param string $name Table Name
82
     * @param array $options Options
83
     * @param \Phinx\Db\Adapter\AdapterInterface $adapter Database Adapter
84 239
     */
85
    public function __construct($name, $options = [], AdapterInterface $adapter = null)
86 239
    {
87 239
        $this->setName($name);
88
        $this->setOptions($options);
89 239
90 231
        if ($adapter !== null) {
91 231
            $this->setAdapter($adapter);
92 239
        }
93
    }
94
95
    /**
96
     * Sets the table name.
97
     *
98
     * @param string $name Table Name
99
     * @return \Phinx\Db\Table
100 239
     */
101
    public function setName($name)
102 239
    {
103 239
        $this->name = $name;
104
105
        return $this;
106
    }
107
108
    /**
109
     * Gets the table name.
110
     *
111 215
     * @return string
112
     */
113 215
    public function getName()
114
    {
115
        return $this->name;
116
    }
117
118
    /**
119
     * Sets the table options.
120
     *
121
     * @param array $options
122 239
     * @return \Phinx\Db\Table
123
     */
124 239
    public function setOptions($options)
125 239
    {
126
        $this->options = $options;
127
128
        return $this;
129
    }
130
131
    /**
132
     * Gets the table options.
133 189
     *
134
     * @return array
135 189
     */
136
    public function getOptions()
137
    {
138
        return $this->options;
139
    }
140
141
    /**
142
     * Sets the database adapter.
143
     *
144 231
     * @param \Phinx\Db\Adapter\AdapterInterface $adapter Database Adapter
145
     * @return \Phinx\Db\Table
146 231
     */
147 231
    public function setAdapter(AdapterInterface $adapter)
148
    {
149
        $this->adapter = $adapter;
150
151
        return $this;
152
    }
153
154
    /**
155 225
     * Gets the database adapter.
156
     *
157 225
     * @return \Phinx\Db\Adapter\AdapterInterface
158
     */
159
    public function getAdapter()
160
    {
161
        return $this->adapter;
162
    }
163
164
    /**
165 195
     * Does the table exist?
166
     *
167 195
     * @return bool
168
     */
169
    public function exists()
170
    {
171
        return $this->getAdapter()->hasTable($this->getName());
172
    }
173
174
    /**
175 1
     * Drops the database table.
176
     *
177 1
     * @return void
178 1
     */
179
    public function drop()
180
    {
181
        $this->getAdapter()->dropTable($this->getName());
182
    }
183
184
    /**
185
     * Renames the database table.
186 3
     *
187
     * @param string $newTableName New Table Name
188 3
     * @return \Phinx\Db\Table
189 3
     */
190 3
    public function rename($newTableName)
191
    {
192
        $this->getAdapter()->renameTable($this->getName(), $newTableName);
193
        $this->setName($newTableName);
194
195
        return $this;
196
    }
197
198
    /**
199
     * Sets an array of columns waiting to be committed.
200
     * Use setPendingColumns
201
     *
202
     * @deprecated
203
     * @param array $columns Columns
204
     * @return \Phinx\Db\Table
205
     */
206
    public function setColumns($columns)
207
    {
208
        $this->setPendingColumns($columns);
209
210
        return $this;
211 10
    }
212
213 10
    /**
214
     * Gets an array of the table columns.
215
     *
216
     * @return \Phinx\Db\Table\Column[]
217
     */
218
    public function getColumns()
219
    {
220
        return $this->getAdapter()->getColumns($this->getName());
221
    }
222 196
223
    /**
224 196
     * Sets an array of columns waiting to be committed.
225 196
     *
226
     * @param array $columns Columns
227
     * @return \Phinx\Db\Table
228
     */
229
    public function setPendingColumns($columns)
230
    {
231
        $this->columns = $columns;
232
233 204
        return $this;
234
    }
235 204
236
    /**
237
     * Gets an array of columns waiting to be committed.
238
     *
239
     * @return \Phinx\Db\Table\Column[]
240
     */
241
    public function getPendingColumns()
242
    {
243
        return $this->columns;
244 196
    }
245
246 196
    /**
247 196
     * Sets an array of columns waiting to be indexed.
248
     *
249
     * @param array $indexes Indexes
250
     * @return \Phinx\Db\Table
251
     */
252
    public function setIndexes($indexes)
253
    {
254
        $this->indexes = $indexes;
255 191
256
        return $this;
257 191
    }
258
259
    /**
260
     * Gets an array of indexes waiting to be committed.
261
     *
262
     * @return array
263
     */
264
    public function getIndexes()
265
    {
266 196
        return $this->indexes;
267
    }
268 196
269 196
    /**
270
     * Sets an array of foreign keys waiting to be commited.
271
     *
272
     * @param \Phinx\Db\Table\ForeignKey[] $foreignKeys foreign keys
273
     * @return \Phinx\Db\Table
274
     */
275
    public function setForeignKeys($foreignKeys)
276
    {
277 192
        $this->foreignKeys = $foreignKeys;
278
279 192
        return $this;
280
    }
281
282
    /**
283
     * Gets an array of foreign keys waiting to be commited.
284
     *
285
     * @return array|\Phinx\Db\Table\ForeignKey[]
286
     */
287
    public function getForeignKeys()
288 196
    {
289
        return $this->foreignKeys;
290 196
    }
291 196
292
    /**
293
     * Sets an array of data to be inserted.
294
     *
295
     * @param array $data Data
296
     * @return \Phinx\Db\Table
297
     */
298
    public function setData($data)
299 197
    {
300
        $this->data = $data;
301 197
302
        return $this;
303
    }
304
305
    /**
306
     * Gets the data waiting to be inserted.
307
     *
308
     * @return array
309 196
     */
310
    public function getData()
311 196
    {
312 196
        return $this->data;
313 196
    }
314 196
315 196
    /**
316
     * Resets all of the pending table changes.
317
     *
318
     * @return void
319
     */
320
    public function reset()
321
    {
322
        $this->setPendingColumns([]);
323
        $this->setIndexes([]);
324
        $this->setForeignKeys([]);
325
        $this->setData([]);
326
    }
327
328
    /**
329
     * Add a table column.
330
     *
331
     * Type can be: string, text, integer, float, decimal, datetime, timestamp,
332 210
     * time, date, binary, boolean.
333
     *
334
     * Valid options can be: limit, default, null, precision or scale.
335 210
     *
336 1
     * @param string|\Phinx\Db\Table\Column $columnName Column Name
337
     * @param string $type Column Type
338
     * @param array $options Column Options
339
     * @throws \RuntimeException
340 209
     * @throws \InvalidArgumentException
341 207
     * @return \Phinx\Db\Table
342 207
     */
343 207
    public function addColumn($columnName, $type = null, $options = [])
344 207
    {
345 207
        // we need an adapter set to add a column
346 2
        if ($this->getAdapter() === null) {
347
            throw new \RuntimeException('An adapter must be specified to add a column.');
348
        }
349
350 209
        // create a new column object if only strings were supplied
351 1 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...
352 1
            $column = new Column();
353 1
            $column->setName($columnName);
354 1
            $column->setType($type);
355 1
            $column->setOptions($options); // map options to column methods
356
        } else {
357
            $column = $columnName;
358 208
        }
359 208
360
        // Delegate to Adapters to check column type
361
        if (!$this->getAdapter()->isValidColumnType($column)) {
362
            throw new \InvalidArgumentException(sprintf(
363
                'An invalid column type "%s" was specified for column "%s".',
364
                $column->getType(),
365
                $column->getName()
366
            ));
367
        }
368 1
369
        $this->columns[] = $column;
370 1
371 1
        return $this;
372
    }
373
374
    /**
375
     * Add a table column with a custom type definition.
376
     *
377
     * Type can be any string that you expect your DBMS to understand
378
     *
379
     * Valid options can be:  default or null.
380
     *
381 4
     * For widely supported types @see addColumn
382
     *
383 4
     * @param string|CustomColumn $columnName Column Name
384 4
     * @param string $type Column Type
385
     * @param array $options Column Options
386
     * @return Table
387
     */
388
    public function addCustomColumn($columnName, $type = null, $options = array())
389
    {
390
        // create a new CustomColumn object if only strings were supplied
391 View Code Duplication
        if (!$columnName instanceof CustomColumn) {
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...
392
            $column = new CustomColumn();
393
            $column->setName($columnName);
394
            $column->setType($type);
395 17
            $column->setOptions($options); // map options to column methods
396
        } else {
397
            $column = $columnName;
398 17
        }
399 4
400 4
        $this->columns[] = $column;
401 4
        return $this;
402 4
    }
403 13
404
    /**
405
     * Remove a table column.
406
     *
407 17
     * @param string $columnName Column Name
408 15
     * @return \Phinx\Db\Table
409 15
     */
410
    public function removeColumn($columnName)
411 17
    {
412 17
        $this->getAdapter()->dropColumn($this->getName(), $columnName);
413
414
        return $this;
415
    }
416
417
    /**
418
     * Rename a table column.
419
     *
420
     * @param string $oldName Old Column Name
421 89
     * @param string $newName New Column Name
422
     * @return \Phinx\Db\Table
423 89
     */
424
    public function renameColumn($oldName, $newName)
425
    {
426
        $this->getAdapter()->renameColumn($this->getName(), $oldName, $newName);
427
428
        return $this;
429
    }
430
431
    /**
432
     * Change a table column type.
433
     *
434
     * @param string        $columnName    Column Name
435 29
     * @param string|\Phinx\Db\Table\Column $newColumnType New Column Type
436
     * @param array         $options       Options
437
     * @return \Phinx\Db\Table
438 29
     */
439 28
    public function changeColumn($columnName, $newColumnType, $options = [])
440 28
    {
441 22
        // create a column object if one wasn't supplied
442 22
        if (!$newColumnType instanceof Column) {
443 28
            $newColumn = new Column();
444 28
            $newColumn->setType($newColumnType);
445 28
            $newColumn->setOptions($options);
446 1
        } else {
447
            $newColumn = $newColumnType;
448
        }
449 29
450 29
        // if the name was omitted use the existing column name
451
        if ($newColumn->getName() === null || strlen($newColumn->getName()) === 0) {
452
            $newColumn->setName($columnName);
453
        }
454
455
        $this->getAdapter()->changeColumn($this->getName(), $columnName, $newColumn);
456
457
        return $this;
458
    }
459 1
460
    /**
461 1
     * Checks to see if a column exists.
462 1
     *
463
     * @param string $columnName Column Name
464
     * @return bool
465
     */
466
    public function hasColumn($columnName)
467
    {
468
        return $this->getAdapter()->hasColumn($this->getName(), $columnName);
469
    }
470
471 1
    /**
472
     * Add an index to a database table.
473 1
     *
474 1
     * In $options you can specific unique = true/false or name (index name).
475
     *
476
     * @param string|array|\Phinx\Db\Table\Index $columns Table Column(s)
477
     * @param array $options Index Options
478
     * @return \Phinx\Db\Table
479
     */
480
    public function addIndex($columns, $options = [])
481
    {
482
        // create a new index object if strings or an array of strings were supplied
483
        if (!$columns instanceof Index) {
484 12
            $index = new Index();
485
            if (is_string($columns)) {
486 12
                $columns = [$columns]; // str to array
487
            }
488
            $index->setColumns($columns);
489
            $index->setOptions($options);
490
        } else {
491
            $index = $columns;
492
        }
493
494
        $this->indexes[] = $index;
495
496
        return $this;
497
    }
498
499
    /**
500
     * Removes the given index from a table.
501 8
     *
502
     * @param array $columns Columns
503 8
     * @return \Phinx\Db\Table
504 4
     */
505 4
    public function removeIndex($columns)
506 8
    {
507 8
        $this->getAdapter()->dropIndex($this->getName(), $columns);
508
509
        return $this;
510 8
    }
511
512 8
    /**
513 8
     * Removes the given index identified by its name from a table.
514 8
     *
515 8
     * @param string $name Index name
516
     * @return \Phinx\Db\Table
517 8
     */
518
    public function removeIndexByName($name)
519
    {
520
        $this->getAdapter()->dropIndexByName($this->getName(), $name);
521
522
        return $this;
523
    }
524
525
    /**
526
     * Checks to see if an index exists.
527 1
     *
528
     * @param string|array $columns Columns
529 1
     * @param array        $options Options
0 ignored issues
show
Bug introduced by
There is no parameter named $options. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
530 1
     * @return bool
531 1
     */
532 1
    public function hasIndex($columns)
533
    {
534
        return $this->getAdapter()->hasIndex($this->getName(), $columns);
535 1
    }
536
537
    /**
538 1
     * Add a foreign key to a database table.
539
     *
540
     * In $options you can specify on_delete|on_delete = cascade|no_action ..,
541
     * on_update, constraint = constraint name.
542
     *
543
     * @param string|array $columns Columns
544
     * @param string|\Phinx\Db\Table $referencedTable   Referenced Table
545
     * @param string|array $referencedColumns Referenced Columns
546
     * @param array $options Options
547
     * @return \Phinx\Db\Table
548 1
     */
549
    public function addForeignKey($columns, $referencedTable, $referencedColumns = ['id'], $options = [])
550 1
    {
551
        if (is_string($referencedColumns)) {
552
            $referencedColumns = [$referencedColumns]; // str to array
553
        }
554
        $fk = new ForeignKey();
555
        if ($referencedTable instanceof Table) {
556
            $fk->setReferencedTable($referencedTable);
557
        } else {
558
            $fk->setReferencedTable(new Table($referencedTable, [], $this->adapter));
559
        }
560
        $fk->setColumns($columns)
561 15
           ->setReferencedColumns($referencedColumns)
562
           ->setOptions($options);
563 15
        $this->foreignKeys[] = $fk;
564 15
565 15
        return $this;
566 15
    }
567
568 15
    /**
569 15
     * Removes the given foreign key from the table.
570 15
     *
571
     * @param string|array $columns    Column(s)
572 15
     * @param null|string  $constraint Constraint names
573
     * @return \Phinx\Db\Table
574 15
     */
575
    public function dropForeignKey($columns, $constraint = null)
576
    {
577
        if (is_string($columns)) {
578
            $columns = [$columns];
579
        }
580
        if ($constraint) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $constraint of type null|string is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
581
            $this->getAdapter()->dropForeignKey($this->getName(), [], $constraint);
582
        } else {
583
            $this->getAdapter()->dropForeignKey($this->getName(), $columns);
584
        }
585
586
        return $this;
587
    }
588
589 17
    /**
590
     * Checks to see if a foreign key exists.
591
     *
592 17
     * @param  string|array $columns    Column(s)
593 11
     * @param  null|string  $constraint Constraint names
594 11
     * @return bool
595 11
     */
596 11
    public function hasForeignKey($columns, $constraint = null)
597
    {
598 8
        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...
599 8
    }
600
601
    /**
602
     * Add timestamp columns created_at and updated_at to the table.
603
     *
604
     * @param string $createdAtColumnName
605
     * @param string $updatedAtColumnName
606
     *
607 196
     * @return \Phinx\Db\Table
608
     */
609 196
    public function addTimestamps($createdAtColumnName = 'created_at', $updatedAtColumnName = 'updated_at')
610 196
    {
611 196
        $createdAtColumnName = is_null($createdAtColumnName) ? 'created_at' : $createdAtColumnName;
612 196
        $updatedAtColumnName = is_null($updatedAtColumnName) ? 'updated_at' : $updatedAtColumnName;
613
        $this->addColumn($createdAtColumnName, 'timestamp', [
614
                'default' => 'CURRENT_TIMESTAMP',
615
                'update' => ''
616
            ])
617
             ->addColumn($updatedAtColumnName, 'timestamp', [
618
                 'null' => true,
619
                 'default' => null
620 46
             ]);
621
622 46
        return $this;
623
    }
624
625
    /**
626
     * Insert data into the table.
627 46
     *
628 38
     * @param array $data array of data in the form:
629 46
     *              array(
630
     *                  array("col1" => "value1", "col2" => "anotherValue1"),
631 46
     *                  array("col2" => "value2", "col2" => "anotherValue2"),
632 6
     *              )
633 46
     *              or array("col1" => "value1", "col2" => "anotherValue1")
634
     *
635 46
     * @return \Phinx\Db\Table
636 3
     */
637 46
    public function insert($data)
638
    {
639 46
        // handle array of array situations
640 46
        if (isset($data[0]) && is_array($data[0])) {
641 46
            foreach ($data as $row) {
642
                $this->data[] = $row;
643
            }
644
645
            return $this;
646
        }
647
        $this->data[] = $data;
648 196
649
        return $this;
650 196
    }
651 196
652 192
    /**
653
     * Creates a table from the object instance.
654
     *
655 12
     * @return void
656 12
     */
657 12
    public function create()
658 12
    {
659 12
        $this->getAdapter()->createTable($this);
660 12
        $this->saveData();
661 1
        $this->reset(); // reset pending changes
662 1
    }
663
664 12
    /**
665
     * Updates a table from the object instance.
666 12
     *
667 11
     * @throws \RuntimeException
668 11
     * @return void
669 1
     */
670 1
    public function update()
671 1
    {
672
        if (!$this->exists()) {
673 12
            throw new \RuntimeException('Cannot update a table that doesn\'t exist!');
674
        }
675
676
        // update table
677
        foreach ($this->getPendingColumns() as $column) {
678
            $this->getAdapter()->addColumn($this, $column);
679
        }
680 2
681
        foreach ($this->getIndexes() as $index) {
682 2
            $this->getAdapter()->addIndex($this, $index);
683 2
        }
684
685
        foreach ($this->getForeignKeys() as $foreignKey) {
686
            $this->getAdapter()->addForeignKey($this, $foreignKey);
687
        }
688
689
        $this->saveData();
690
        $this->reset(); // reset pending changes
691
    }
692 195
693
    /**
694 195
     * Commit the pending data waiting for insertion.
695 45
     *
696 45
     * @return void
697 195
     */
698
    public function saveData()
699
    {
700 195
        $rows = $this->getData();
701 195
        if (empty($rows)) {
702
            return;
703
        }
704
705
        $bulk = true;
706
        $row = current($rows);
707
        $c = array_keys($row);
708
        foreach ($this->getData() as $row) {
709
            $k = array_keys($row);
710
            if ($k != $c) {
711
                $bulk = false;
712
                break;
713
            }
714
        }
715
716
        if ($bulk) {
717
            $this->getAdapter()->bulkinsert($this, $this->getData());
718
        } else {
719
            foreach ($this->getData() as $row) {
720
                $this->getAdapter()->insert($this, $row);
721
            }
722
        }
723
    }
724
725
    /**
726
     * Truncates the table.
727
     *
728
     * @return void
729
     */
730
    public function truncate()
731
    {
732
        $this->getAdapter()->truncateTable($this->getName());
733
    }
734
735
    /**
736
     * Commits the table changes.
737
     *
738
     * If the table doesn't exist it is created otherwise it is updated.
739
     *
740
     * @return void
741
     */
742
    public function save()
743
    {
744
        if ($this->exists()) {
745
            $this->update(); // update the table
746
        } else {
747
            $this->create(); // create the table
748
        }
749
750
        $this->reset(); // reset pending changes
751
    }
752
}
753