Completed
Push — master ( 5dd66e...5b5c2c )
by Marco
114:19 queued 111:15
created

lib/Doctrine/DBAL/Schema/Table.php (1 issue)

1
<?php
2
3
namespace Doctrine\DBAL\Schema;
4
5
use Doctrine\DBAL\DBALException;
6
use Doctrine\DBAL\Schema\Visitor\Visitor;
7
use Doctrine\DBAL\Types\Type;
8
use const ARRAY_FILTER_USE_KEY;
9
use function array_filter;
10
use function array_merge;
11
use function in_array;
12
use function preg_match;
13
use function strlen;
14
use function strtolower;
15
16
/**
17
 * Object Representation of a table.
18
 */
19
class Table extends AbstractAsset
20
{
21
    /** @var Column[] */
22
    protected $_columns = [];
23
24
    /** @var Index[] */
25
    private $implicitIndexes = [];
26
27
    /** @var Index[] */
28
    protected $_indexes = [];
29
30
    /** @var string */
31
    protected $_primaryKeyName = false;
32
33
    /** @var ForeignKeyConstraint[] */
34
    protected $_fkConstraints = [];
35
36
    /** @var mixed[] */
37
    protected $_options = [];
38
39
    /** @var SchemaConfig|null */
40
    protected $_schemaConfig = null;
41
42
    /**
43
     * @param string                 $tableName
44
     * @param Column[]               $columns
45
     * @param Index[]                $indexes
46
     * @param ForeignKeyConstraint[] $fkConstraints
47
     * @param int                    $idGeneratorType
48
     * @param mixed[]                $options
49
     *
50
     * @throws DBALException
51
     */
52 24472
    public function __construct($tableName, array $columns = [], array $indexes = [], array $fkConstraints = [], $idGeneratorType = 0, array $options = [])
0 ignored issues
show
The parameter $idGeneratorType is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

52
    public function __construct($tableName, array $columns = [], array $indexes = [], array $fkConstraints = [], /** @scrutinizer ignore-unused */ $idGeneratorType = 0, array $options = [])

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
53
    {
54 24472
        if (strlen($tableName) === 0) {
55 1627
            throw DBALException::invalidTableName($tableName);
56
        }
57
58 24470
        $this->_setName($tableName);
59
60 24470
        foreach ($columns as $column) {
61 21988
            $this->_addColumn($column);
62
        }
63
64 24468
        foreach ($indexes as $idx) {
65 21857
            $this->_addIndex($idx);
66
        }
67
68 24464
        foreach ($fkConstraints as $constraint) {
69 21064
            $this->_addForeignKeyConstraint($constraint);
70
        }
71
72 24464
        $this->_options = $options;
73 24464
    }
74
75
    /**
76
     * @return void
77
     */
78 22485
    public function setSchemaConfig(SchemaConfig $schemaConfig)
79
    {
80 22485
        $this->_schemaConfig = $schemaConfig;
81 22485
    }
82
83
    /**
84
     * @return int
85
     */
86 22746
    protected function _getMaxIdentifierLength()
87
    {
88 22746
        if ($this->_schemaConfig instanceof SchemaConfig) {
89 22281
            return $this->_schemaConfig->getMaxIdentifierLength();
90
        }
91
92 22685
        return 63;
93
    }
94
95
    /**
96
     * Sets the Primary Key.
97
     *
98
     * @param string[]     $columnNames
99
     * @param string|false $indexName
100
     *
101
     * @return self
102
     */
103 23434
    public function setPrimaryKey(array $columnNames, $indexName = false)
104
    {
105 23434
        $this->_addIndex($this->_createIndex($columnNames, $indexName ?: 'primary', true, true));
106
107 23434
        foreach ($columnNames as $columnName) {
108 23434
            $column = $this->getColumn($columnName);
109 23434
            $column->setNotnull(true);
110
        }
111
112 23434
        return $this;
113
    }
114
115
    /**
116
     * @param string[]    $columnNames
117
     * @param string|null $indexName
118
     * @param string[]    $flags
119
     * @param mixed[]     $options
120
     *
121
     * @return self
122
     */
123 21536
    public function addIndex(array $columnNames, $indexName = null, array $flags = [], array $options = [])
124
    {
125 21536
        if ($indexName === null) {
126 21019
            $indexName = $this->_generateIdentifierName(
127 21019
                array_merge([$this->getName()], $columnNames),
128 21019
                'idx',
129 21019
                $this->_getMaxIdentifierLength()
130
            );
131
        }
132
133 21536
        return $this->_addIndex($this->_createIndex($columnNames, $indexName, false, false, $flags, $options));
134
    }
135
136
    /**
137
     * Drops the primary key from this table.
138
     *
139
     * @return void
140
     */
141 20138
    public function dropPrimaryKey()
142
    {
143 20138
        $this->dropIndex($this->_primaryKeyName);
144 20138
        $this->_primaryKeyName = false;
145 20138
    }
146
147
    /**
148
     * Drops an index from this table.
149
     *
150
     * @param string $indexName The index name.
151
     *
152
     * @return void
153
     *
154
     * @throws SchemaException If the index does not exist.
155
     */
156 20175
    public function dropIndex($indexName)
157
    {
158 20175
        $indexName = $this->normalizeIdentifier($indexName);
159 20175
        if (! $this->hasIndex($indexName)) {
160
            throw SchemaException::indexDoesNotExist($indexName, $this->_name);
161
        }
162 20175
        unset($this->_indexes[$indexName]);
163 20175
    }
164
165
    /**
166
     * @param string[]    $columnNames
167
     * @param string|null $indexName
168
     * @param mixed[]     $options
169
     *
170
     * @return self
171
     */
172 22339
    public function addUniqueIndex(array $columnNames, $indexName = null, array $options = [])
173
    {
174 22339
        if ($indexName === null) {
175 21993
            $indexName = $this->_generateIdentifierName(
176 21993
                array_merge([$this->getName()], $columnNames),
177 21993
                'uniq',
178 21993
                $this->_getMaxIdentifierLength()
179
            );
180
        }
181
182 22339
        return $this->_addIndex($this->_createIndex($columnNames, $indexName, true, false, [], $options));
183
    }
184
185
    /**
186
     * Renames an index.
187
     *
188
     * @param string      $oldIndexName The name of the index to rename from.
189
     * @param string|null $newIndexName The name of the index to rename to.
190
     *                                  If null is given, the index name will be auto-generated.
191
     *
192
     * @return self This table instance.
193
     *
194
     * @throws SchemaException If no index exists for the given current name
195
     *                         or if an index with the given new name already exists on this table.
196
     */
197 19884
    public function renameIndex($oldIndexName, $newIndexName = null)
198
    {
199 19884
        $oldIndexName           = $this->normalizeIdentifier($oldIndexName);
200 19884
        $normalizedNewIndexName = $this->normalizeIdentifier($newIndexName);
201
202 19884
        if ($oldIndexName === $normalizedNewIndexName) {
203 468
            return $this;
204
        }
205
206 19884
        if (! $this->hasIndex($oldIndexName)) {
207 377
            throw SchemaException::indexDoesNotExist($oldIndexName, $this->_name);
208
        }
209
210 19882
        if ($this->hasIndex($normalizedNewIndexName)) {
211 352
            throw SchemaException::indexAlreadyExists($normalizedNewIndexName, $this->_name);
212
        }
213
214 19880
        $oldIndex = $this->_indexes[$oldIndexName];
215
216 19880
        if ($oldIndex->isPrimary()) {
217 452
            $this->dropPrimaryKey();
218
219 452
            return $this->setPrimaryKey($oldIndex->getColumns(), $newIndexName ?? false);
220
        }
221
222 19880
        unset($this->_indexes[$oldIndexName]);
223
224 19880
        if ($oldIndex->isUnique()) {
225 454
            return $this->addUniqueIndex($oldIndex->getColumns(), $newIndexName, $oldIndex->getOptions());
226
        }
227
228 19878
        return $this->addIndex($oldIndex->getColumns(), $newIndexName, $oldIndex->getFlags(), $oldIndex->getOptions());
229
    }
230
231
    /**
232
     * Checks if an index begins in the order of the given columns.
233
     *
234
     * @param string[] $columnNames
235
     *
236
     * @return bool
237
     */
238 20060
    public function columnsAreIndexed(array $columnNames)
239
    {
240 20060
        foreach ($this->getIndexes() as $index) {
241
            /** @var $index Index */
242 20060
            if ($index->spansColumns($columnNames)) {
243 20060
                return true;
244
            }
245
        }
246
247
        return false;
248
    }
249
250
    /**
251
     * @param string[] $columnNames
252
     * @param string   $indexName
253
     * @param bool     $isUnique
254
     * @param bool     $isPrimary
255
     * @param string[] $flags
256
     * @param mixed[]  $options
257
     *
258
     * @return Index
259
     *
260
     * @throws SchemaException
261
     */
262 23732
    private function _createIndex(array $columnNames, $indexName, $isUnique, $isPrimary, array $flags = [], array $options = [])
263
    {
264 23732
        if (preg_match('(([^a-zA-Z0-9_]+))', $this->normalizeIdentifier($indexName))) {
265 1152
            throw SchemaException::indexNameInvalid($indexName);
266
        }
267
268 23730
        foreach ($columnNames as $columnName) {
269 23728
            if (! $this->hasColumn($columnName)) {
270 2121
                throw SchemaException::columnDoesNotExist($columnName, $this->_name);
271
            }
272
        }
273
274 23728
        return new Index($indexName, $columnNames, $isUnique, $isPrimary, $flags, $options);
275
    }
276
277
    /**
278
     * @param string  $columnName
279
     * @param string  $typeName
280
     * @param mixed[] $options
281
     *
282
     * @return Column
283
     */
284 24152
    public function addColumn($columnName, $typeName, array $options = [])
285
    {
286 24152
        $column = new Column($columnName, Type::getType($typeName), $options);
287
288 24152
        $this->_addColumn($column);
289
290 24152
        return $column;
291
    }
292
293
    /**
294
     * Renames a Column.
295
     *
296
     * @deprecated
297
     *
298
     * @param string $oldColumnName
299
     * @param string $newColumnName
300
     *
301
     * @throws DBALException
302
     */
303
    public function renameColumn($oldColumnName, $newColumnName)
304
    {
305
        throw new DBALException('Table#renameColumn() was removed, because it drops and recreates ' .
306
            'the column instead. There is no fix available, because a schema diff cannot reliably detect if a ' .
307
            'column was renamed or one column was created and another one dropped.');
308
    }
309
310
    /**
311
     * Change Column Details.
312
     *
313
     * @param string  $columnName
314
     * @param mixed[] $options
315
     *
316
     * @return self
317
     */
318 20510
    public function changeColumn($columnName, array $options)
319
    {
320 20510
        $column = $this->getColumn($columnName);
321 20510
        $column->setOptions($options);
322
323 20510
        return $this;
324
    }
325
326
    /**
327
     * Drops a Column from the Table.
328
     *
329
     * @param string $columnName
330
     *
331
     * @return self
332
     */
333 1518
    public function dropColumn($columnName)
334
    {
335 1518
        $columnName = $this->normalizeIdentifier($columnName);
336 1518
        unset($this->_columns[$columnName]);
337
338 1518
        return $this;
339
    }
340
341
    /**
342
     * Adds a foreign key constraint.
343
     *
344
     * Name is inferred from the local columns.
345
     *
346
     * @param Table|string $foreignTable       Table schema instance or table name
347
     * @param string[]     $localColumnNames
348
     * @param string[]     $foreignColumnNames
349
     * @param mixed[]      $options
350
     * @param string|null  $constraintName
351
     *
352
     * @return self
353
     */
354 22510
    public function addForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options = [], $constraintName = null)
355
    {
356 22510
        $constraintName = $constraintName ?: $this->_generateIdentifierName(array_merge((array) $this->getName(), $localColumnNames), 'fk', $this->_getMaxIdentifierLength());
357
358 22510
        return $this->addNamedForeignKeyConstraint($constraintName, $foreignTable, $localColumnNames, $foreignColumnNames, $options);
359
    }
360
361
    /**
362
     * Adds a foreign key constraint.
363
     *
364
     * Name is to be generated by the database itself.
365
     *
366
     * @deprecated Use {@link addForeignKeyConstraint}
367
     *
368
     * @param Table|string $foreignTable       Table schema instance or table name
369
     * @param string[]     $localColumnNames
370
     * @param string[]     $foreignColumnNames
371
     * @param mixed[]      $options
372
     *
373
     * @return self
374
     */
375 16018
    public function addUnnamedForeignKeyConstraint($foreignTable, array $localColumnNames, array $foreignColumnNames, array $options = [])
376
    {
377 16018
        return $this->addForeignKeyConstraint($foreignTable, $localColumnNames, $foreignColumnNames, $options);
378
    }
379
380
    /**
381
     * Adds a foreign key constraint with a given name.
382
     *
383
     * @deprecated Use {@link addForeignKeyConstraint}
384
     *
385
     * @param string       $name
386
     * @param Table|string $foreignTable       Table schema instance or table name
387
     * @param string[]     $localColumnNames
388
     * @param string[]     $foreignColumnNames
389
     * @param mixed[]      $options
390
     *
391
     * @return self
392
     *
393
     * @throws SchemaException
394
     */
395 22512
    public function addNamedForeignKeyConstraint($name, $foreignTable, array $localColumnNames, array $foreignColumnNames, array $options = [])
396
    {
397 22512
        if ($foreignTable instanceof Table) {
398 22033
            foreach ($foreignColumnNames as $columnName) {
399 22033
                if (! $foreignTable->hasColumn($columnName)) {
400 1166
                    throw SchemaException::columnDoesNotExist($columnName, $foreignTable->getName());
401
                }
402
            }
403
        }
404
405 22510
        foreach ($localColumnNames as $columnName) {
406 22510
            if (! $this->hasColumn($columnName)) {
407 1301
                throw SchemaException::columnDoesNotExist($columnName, $this->_name);
408
            }
409
        }
410
411 22508
        $constraint = new ForeignKeyConstraint(
412 21677
            $localColumnNames,
413 224
            $foreignTable,
414 224
            $foreignColumnNames,
415 224
            $name,
416 1055
            $options
417
        );
418 22508
        $this->_addForeignKeyConstraint($constraint);
419
420 22508
        return $this;
421
    }
422
423
    /**
424
     * @param string $name
425
     * @param mixed  $value
426
     *
427
     * @return self
428
     */
429 20307
    public function addOption($name, $value)
430
    {
431 20307
        $this->_options[$name] = $value;
432
433 20307
        return $this;
434
    }
435
436
    /**
437
     * @return void
438
     *
439
     * @throws SchemaException
440
     */
441 24224
    protected function _addColumn(Column $column)
442
    {
443 24224
        $columnName = $column->getName();
444 24224
        $columnName = $this->normalizeIdentifier($columnName);
445
446 24224
        if (isset($this->_columns[$columnName])) {
447 1452
            throw SchemaException::columnAlreadyExists($this->getName(), $columnName);
448
        }
449
450 24224
        $this->_columns[$columnName] = $column;
451 24224
    }
452
453
    /**
454
     * Adds an index to the table.
455
     *
456
     * @return self
457
     *
458
     * @throws SchemaException
459
     */
460 23742
    protected function _addIndex(Index $indexCandidate)
461
    {
462 23742
        $indexName               = $indexCandidate->getName();
463 23742
        $indexName               = $this->normalizeIdentifier($indexName);
464 23742
        $replacedImplicitIndexes = [];
465
466 23742
        foreach ($this->implicitIndexes as $name => $implicitIndex) {
467 19038
            if (! $implicitIndex->isFullfilledBy($indexCandidate) || ! isset($this->_indexes[$name])) {
468 19030
                continue;
469
            }
470
471 758
            $replacedImplicitIndexes[] = $name;
472
        }
473
474 23742
        if ((isset($this->_indexes[$indexName]) && ! in_array($indexName, $replacedImplicitIndexes, true)) ||
475 23742
            ($this->_primaryKeyName !== false && $indexCandidate->isPrimary())
476
        ) {
477 1329
            throw SchemaException::indexAlreadyExists($indexName, $this->_name);
478
        }
479
480 23742
        foreach ($replacedImplicitIndexes as $name) {
481 758
            unset($this->_indexes[$name], $this->implicitIndexes[$name]);
482
        }
483
484 23742
        if ($indexCandidate->isPrimary()) {
485 23438
            $this->_primaryKeyName = $indexName;
486
        }
487
488 23742
        $this->_indexes[$indexName] = $indexCandidate;
489
490 23742
        return $this;
491
    }
492
493
    /**
494
     * @return void
495
     */
496 22597
    protected function _addForeignKeyConstraint(ForeignKeyConstraint $constraint)
497
    {
498 22597
        $constraint->setLocalTable($this);
499
500 22597
        if (strlen($constraint->getName())) {
501 22516
            $name = $constraint->getName();
502
        } else {
503 2049
            $name = $this->_generateIdentifierName(
504 2049
                array_merge((array) $this->getName(), $constraint->getLocalColumns()),
505 2049
                'fk',
506 2049
                $this->_getMaxIdentifierLength()
507
            );
508
        }
509 22597
        $name = $this->normalizeIdentifier($name);
510
511 22597
        $this->_fkConstraints[$name] = $constraint;
512
513
        // add an explicit index on the foreign key columns. If there is already an index that fulfils this requirements drop the request.
514
        // In the case of __construct calling this method during hydration from schema-details all the explicitly added indexes
515
        // lead to duplicates. This creates computation overhead in this case, however no duplicate indexes are ever added (based on columns).
516 22597
        $indexName      = $this->_generateIdentifierName(
517 22597
            array_merge([$this->getName()], $constraint->getColumns()),
518 22597
            'idx',
519 22597
            $this->_getMaxIdentifierLength()
520
        );
521 22597
        $indexCandidate = $this->_createIndex($constraint->getColumns(), $indexName, false, false);
522
523 22597
        foreach ($this->_indexes as $existingIndex) {
524 22545
            if ($indexCandidate->isFullfilledBy($existingIndex)) {
525 21143
                return;
526
            }
527
        }
528
529 22537
        $this->_addIndex($indexCandidate);
530 22537
        $this->implicitIndexes[$this->normalizeIdentifier($indexName)] = $indexCandidate;
531 22537
    }
532
533
    /**
534
     * Returns whether this table has a foreign key constraint with the given name.
535
     *
536
     * @param string $constraintName
537
     *
538
     * @return bool
539
     */
540 19875
    public function hasForeignKey($constraintName)
541
    {
542 19875
        $constraintName = $this->normalizeIdentifier($constraintName);
543
544 19875
        return isset($this->_fkConstraints[$constraintName]);
545
    }
546
547
    /**
548
     * Returns the foreign key constraint with the given name.
549
     *
550
     * @param string $constraintName The constraint name.
551
     *
552
     * @return ForeignKeyConstraint
553
     *
554
     * @throws SchemaException If the foreign key does not exist.
555
     */
556 343
    public function getForeignKey($constraintName)
557
    {
558 343
        $constraintName = $this->normalizeIdentifier($constraintName);
559 343
        if (! $this->hasForeignKey($constraintName)) {
560
            throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name);
561
        }
562
563 343
        return $this->_fkConstraints[$constraintName];
564
    }
565
566
    /**
567
     * Removes the foreign key constraint with the given name.
568
     *
569
     * @param string $constraintName The constraint name.
570
     *
571
     * @return void
572
     *
573
     * @throws SchemaException
574
     */
575 345
    public function removeForeignKey($constraintName)
576
    {
577 345
        $constraintName = $this->normalizeIdentifier($constraintName);
578 345
        if (! $this->hasForeignKey($constraintName)) {
579
            throw SchemaException::foreignKeyDoesNotExist($constraintName, $this->_name);
580
        }
581
582 345
        unset($this->_fkConstraints[$constraintName]);
583 345
    }
584
585
    /**
586
     * Returns ordered list of columns (primary keys are first, then foreign keys, then the rest)
587
     *
588
     * @return Column[]
589
     */
590 23806
    public function getColumns()
591
    {
592 23806
        $primaryKey        = $this->getPrimaryKey();
593 23806
        $primaryKeyColumns = [];
594
595 23806
        if ($primaryKey !== null) {
596 23198
            $primaryKeyColumns = $this->filterColumns($primaryKey->getColumns());
597
        }
598
599 23806
        return array_merge($primaryKeyColumns, $this->getForeignKeyColumns(), $this->_columns);
600
    }
601
602
    /**
603
     * Returns foreign key columns
604
     *
605
     * @return Column[]
606
     */
607 23806
    private function getForeignKeyColumns()
608
    {
609 23806
        $foreignKeyColumns = [];
610 23806
        foreach ($this->getForeignKeys() as $foreignKey) {
611 22473
            $foreignKeyColumns = array_merge($foreignKeyColumns, $foreignKey->getColumns());
612
        }
613 23806
        return $this->filterColumns($foreignKeyColumns);
614
    }
615
616
    /**
617
     * Returns only columns that have specified names
618
     *
619
     * @param string[] $columnNames
620
     *
621
     * @return Column[]
622
     */
623 23806
    private function filterColumns(array $columnNames)
624
    {
625
        return array_filter($this->_columns, static function ($columnName) use ($columnNames) {
626 23754
            return in_array($columnName, $columnNames, true);
627 23806
        }, ARRAY_FILTER_USE_KEY);
628
    }
629
630
    /**
631
     * Returns whether this table has a Column with the given name.
632
     *
633
     * @param string $columnName The column name.
634
     *
635
     * @return bool
636
     */
637 23896
    public function hasColumn($columnName)
638
    {
639 23896
        $columnName = $this->normalizeIdentifier($columnName);
640
641 23896
        return isset($this->_columns[$columnName]);
642
    }
643
644
    /**
645
     * Returns the Column with the given name.
646
     *
647
     * @param string $columnName The column name.
648
     *
649
     * @return Column
650
     *
651
     * @throws SchemaException If the column does not exist.
652
     */
653 23628
    public function getColumn($columnName)
654
    {
655 23628
        $columnName = $this->normalizeIdentifier($columnName);
656 23628
        if (! $this->hasColumn($columnName)) {
657 1477
            throw SchemaException::columnDoesNotExist($columnName, $this->_name);
658
        }
659
660 23626
        return $this->_columns[$columnName];
661
    }
662
663
    /**
664
     * Returns the primary key.
665
     *
666
     * @return Index|null The primary key, or null if this Table has no primary key.
667
     */
668 23816
    public function getPrimaryKey()
669
    {
670 23816
        if (! $this->hasPrimaryKey()) {
671 23041
            return null;
672
        }
673
674 23208
        return $this->getIndex($this->_primaryKeyName);
675
    }
676
677
    /**
678
     * Returns the primary key columns.
679
     *
680
     * @return string[]
681
     *
682
     * @throws DBALException
683
     */
684 20128
    public function getPrimaryKeyColumns()
685
    {
686 20128
        $primaryKey = $this->getPrimaryKey();
687
688 20128
        if ($primaryKey === null) {
689
            throw new DBALException('Table ' . $this->getName() . ' has no primary key.');
690
        }
691
692 20128
        return $primaryKey->getColumns();
693
    }
694
695
    /**
696
     * Returns whether this table has a primary key.
697
     *
698
     * @return bool
699
     */
700 23822
    public function hasPrimaryKey()
701
    {
702 23822
        return $this->_primaryKeyName && $this->hasIndex($this->_primaryKeyName);
703
    }
704
705
    /**
706
     * Returns whether this table has an Index with the given name.
707
     *
708
     * @param string $indexName The index name.
709
     *
710
     * @return bool
711
     */
712 23312
    public function hasIndex($indexName)
713
    {
714 23312
        $indexName = $this->normalizeIdentifier($indexName);
715
716 23312
        return isset($this->_indexes[$indexName]);
717
    }
718
719
    /**
720
     * Returns the Index with the given name.
721
     *
722
     * @param string $indexName The index name.
723
     *
724
     * @return Index
725
     *
726
     * @throws SchemaException If the index does not exist.
727
     */
728 23268
    public function getIndex($indexName)
729
    {
730 23268
        $indexName = $this->normalizeIdentifier($indexName);
731 23268
        if (! $this->hasIndex($indexName)) {
732 1352
            throw SchemaException::indexDoesNotExist($indexName, $this->_name);
733
        }
734
735 23266
        return $this->_indexes[$indexName];
736
    }
737
738
    /**
739
     * @return Index[]
740
     */
741 23750
    public function getIndexes()
742
    {
743 23750
        return $this->_indexes;
744
    }
745
746
    /**
747
     * Returns the foreign key constraints.
748
     *
749
     * @return ForeignKeyConstraint[]
750
     */
751 23842
    public function getForeignKeys()
752
    {
753 23842
        return $this->_fkConstraints;
754
    }
755
756
    /**
757
     * @param string $name
758
     *
759
     * @return bool
760
     */
761 20292
    public function hasOption($name)
762
    {
763 20292
        return isset($this->_options[$name]);
764
    }
765
766
    /**
767
     * @param string $name
768
     *
769
     * @return mixed
770
     */
771 19771
    public function getOption($name)
772
    {
773 19771
        return $this->_options[$name];
774
    }
775
776
    /**
777
     * @return mixed[]
778
     */
779 23536
    public function getOptions()
780
    {
781 23536
        return $this->_options;
782
    }
783
784
    /**
785
     * @return void
786
     */
787 22214
    public function visit(Visitor $visitor)
788
    {
789 22214
        $visitor->acceptTable($this);
790
791 22214
        foreach ($this->getColumns() as $column) {
792 22208
            $visitor->acceptColumn($this, $column);
793
        }
794
795 22214
        foreach ($this->getIndexes() as $index) {
796 20053
            $visitor->acceptIndex($this, $index);
797
        }
798
799 22214
        foreach ($this->getForeignKeys() as $constraint) {
800 158
            $visitor->acceptForeignKey($this, $constraint);
801
        }
802 22214
    }
803
804
    /**
805
     * Clone of a Table triggers a deep clone of all affected assets.
806
     *
807
     * @return void
808
     */
809 21569
    public function __clone()
810
    {
811 21569
        foreach ($this->_columns as $k => $column) {
812 21567
            $this->_columns[$k] = clone $column;
813
        }
814 21569
        foreach ($this->_indexes as $k => $index) {
815 21545
            $this->_indexes[$k] = clone $index;
816
        }
817 21569
        foreach ($this->_fkConstraints as $k => $fk) {
818 20550
            $this->_fkConstraints[$k] = clone $fk;
819 20550
            $this->_fkConstraints[$k]->setLocalTable($this);
820
        }
821 21569
    }
822
823
    /**
824
     * Normalizes a given identifier.
825
     *
826
     * Trims quotes and lowercases the given identifier.
827
     *
828
     * @param string|null $identifier The identifier to normalize.
829
     *
830
     * @return string The normalized identifier.
831
     */
832 24232
    private function normalizeIdentifier($identifier)
833
    {
834 24232
        if ($identifier === null) {
835 452
            return '';
836
        }
837
838 24232
        return $this->trimQuotes(strtolower($identifier));
839
    }
840
}
841