Failed Conditions
Pull Request — develop (#3581)
by Jonathan
12:44
created

_getPortableTableIndexesList()   B

Complexity

Conditions 10
Paths 63

Size

Total Lines 60
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 10.0023

Importance

Changes 0
Metric Value
eloc 36
dl 0
loc 60
rs 7.6666
c 0
b 0
f 0
ccs 34
cts 35
cp 0.9714
cc 10
nc 63
nop 2
crap 10.0023

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Doctrine\DBAL\Schema;
6
7
use Doctrine\DBAL\Connection;
8
use Doctrine\DBAL\ConnectionException;
9
use Doctrine\DBAL\DBALException;
10
use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs;
11
use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs;
12
use Doctrine\DBAL\Events;
13
use Doctrine\DBAL\Exception\DatabaseRequired;
14
use Doctrine\DBAL\Platforms\AbstractPlatform;
15
use Doctrine\DBAL\Platforms\Exception\NotSupported;
16
use Throwable;
17
use function array_filter;
18
use function array_intersect;
19
use function array_map;
20
use function array_shift;
21
use function array_values;
22
use function assert;
23
use function call_user_func_array;
24
use function count;
25
use function func_get_args;
26
use function is_array;
27
use function is_callable;
28
use function preg_match;
29
use function strtolower;
30
31
/**
32
 * Base class for schema managers. Schema managers are used to inspect and/or
33
 * modify the database schema/structure.
34
 */
35
abstract class AbstractSchemaManager
36
{
37
    /**
38
     * Holds instance of the Doctrine connection for this schema manager.
39
     *
40
     * @var Connection
41
     */
42
    protected $_conn;
43
44
    /**
45
     * Holds instance of the database platform used for this schema manager.
46
     *
47
     * @var AbstractPlatform
48
     */
49
    protected $_platform;
50
51
    /**
52
     * Constructor. Accepts the Connection instance to manage the schema for.
53
     */
54 5387
    public function __construct(Connection $conn, ?AbstractPlatform $platform = null)
55
    {
56 5387
        $this->_conn     = $conn;
57 5387
        $this->_platform = $platform ?: $this->_conn->getDatabasePlatform();
58 5387
    }
59
60
    /**
61
     * Returns the associated platform.
62
     */
63 3583
    public function getDatabasePlatform() : AbstractPlatform
64
    {
65 3583
        return $this->_platform;
66
    }
67
68
    /**
69
     * Tries any method on the schema manager. Normally a method throws an
70
     * exception when your DBMS doesn't support it or if an error occurs.
71
     * This method allows you to try and method on your SchemaManager
72
     * instance and will return false if it does not work or is not supported.
73
     *
74
     * <code>
75
     * $result = $sm->tryMethod('dropView', 'view_name');
76
     * </code>
77
     *
78
     * @return mixed
79
     */
80 5267
    public function tryMethod()
81
    {
82 5267
        $args   = func_get_args();
83 5267
        $method = $args[0];
84 5267
        unset($args[0]);
85 5267
        $args = array_values($args);
86
87 5267
        $callback = [$this, $method];
88 5267
        assert(is_callable($callback));
89
90
        try {
91 5267
            return call_user_func_array($callback, $args);
92 5253
        } catch (Throwable $e) {
93 5253
            return false;
94
        }
95
    }
96
97
    /**
98
     * Lists the available databases for this connection.
99
     *
100
     * @return array<int, string>
101
     */
102 3197
    public function listDatabases() : array
103
    {
104 3197
        $sql = $this->_platform->getListDatabasesSQL();
105
106 2925
        $databases = $this->_conn->fetchAll($sql);
107
108 2925
        return $this->_getPortableDatabasesList($databases);
109
    }
110
111
    /**
112
     * Returns a list of all namespaces in the current database.
113
     *
114
     * @return array<int, string>
115
     */
116 1061
    public function listNamespaceNames() : array
117
    {
118 1061
        $sql = $this->_platform->getListNamespacesSQL();
119
120 1061
        $namespaces = $this->_conn->fetchAll($sql);
121
122 1061
        return $this->getPortableNamespacesList($namespaces);
123
    }
124
125
    /**
126
     * Lists the available sequences for this connection.
127
     *
128
     * @return array<int, Sequence>
129
     */
130 1090
    public function listSequences(?string $database = null) : array
131
    {
132 1090
        $database = $this->ensureDatabase(
133 1090
            $database ?? $this->_conn->getDatabase(),
134 1090
            __METHOD__
135
        );
136
137 1090
        $sql = $this->_platform->getListSequencesSQL($database);
138
139 1090
        $sequences = $this->_conn->fetchAll($sql);
140
141 1090
        return $this->filterAssetNames($this->_getPortableSequencesList($sequences));
142
    }
143
144
    /**
145
     * Lists the columns for a given table.
146
     *
147
     * In contrast to other libraries and to the old version of Doctrine,
148
     * this column definition does try to contain the 'primary' field for
149
     * the reason that it is not portable across different RDBMS. Use
150
     * {@see listTableIndexes($tableName)} to retrieve the primary key
151
     * of a table. We're a RDBMS specifies more details these are held
152
     * in the platformDetails array.
153
     *
154
     * @return array<string, Column>
155
     */
156 4245
    public function listTableColumns(string $table, ?string $database = null) : array
157
    {
158 4245
        $database = $this->ensureDatabase(
159 4245
            $database ?? $this->_conn->getDatabase(),
160 4245
            __METHOD__
161
        );
162
163 4245
        $sql = $this->_platform->getListTableColumnsSQL($table, $database);
164
165 4245
        $tableColumns = $this->_conn->fetchAll($sql);
166
167 4245
        return $this->_getPortableTableColumnList($table, $database, $tableColumns);
168
    }
169
170
    /**
171
     * Lists the indexes for a given table returning an array of Index instances.
172
     *
173
     * Keys of the portable indexes list are all lower-cased.
174
     *
175
     * @return array<string, Index>
176
     */
177 3948
    public function listTableIndexes(string $table) : array
178
    {
179 3948
        $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
180
181 3948
        $tableIndexes = $this->_conn->fetchAll($sql);
182
183 3948
        return $this->_getPortableTableIndexesList($tableIndexes, $table);
184
    }
185
186
    /**
187
     * Returns true if all the given tables exist.
188
     *
189
     * @param array<int, string> $tableNames
190
     */
191 4667
    public function tablesExist(array $tableNames) : bool
192
    {
193 4667
        $tableNames = array_map('strtolower', $tableNames);
194
195 4667
        return count($tableNames) === count(array_intersect($tableNames, array_map('strtolower', $this->listTableNames())));
196
    }
197
198 4667
    public function tableExists(string $tableName) : bool
199
    {
200 4667
        return $this->tablesExist([$tableName]);
201
    }
202
203
    /**
204
     * Returns a list of all tables in the current database.
205
     *
206
     * @return array<int, string>
207
     */
208 4521
    public function listTableNames() : array
209
    {
210 4521
        $sql = $this->_platform->getListTablesSQL();
211
212 4521
        $tables     = $this->_conn->fetchAll($sql);
213 4521
        $tableNames = $this->_getPortableTablesList($tables);
214
215 4521
        return $this->filterAssetNames($tableNames);
216
    }
217
218
    /**
219
     * Filters asset names if they are configured to return only a subset of all
220
     * the found elements.
221
     *
222
     * @param array<int, mixed> $assetNames
223
     *
224
     * @return array<int, mixed>
225
     */
226 4685
    protected function filterAssetNames(array $assetNames) : array
227
    {
228 4685
        $filter = $this->_conn->getConfiguration()->getSchemaAssetsFilter();
229 4685
        if (! $filter) {
230 4685
            return $assetNames;
231
        }
232
233 1560
        return array_values(array_filter($assetNames, $filter));
234
    }
235
236
    /**
237
     * Lists the tables for this connection.
238
     *
239
     * @return array<int, Table>
240
     */
241 4050
    public function listTables() : array
242
    {
243 4050
        $tableNames = $this->listTableNames();
244
245 4050
        $tables = [];
246 4050
        foreach ($tableNames as $tableName) {
247 4010
            $tables[] = $this->listTableDetails($tableName);
248
        }
249
250 4050
        return $tables;
251
    }
252
253 4233
    public function listTableDetails(string $tableName) : Table
254
    {
255 4233
        $columns     = $this->listTableColumns($tableName);
256 4233
        $foreignKeys = [];
257
258 4233
        if ($this->_platform->supportsForeignKeyConstraints()) {
259 3947
            $foreignKeys = $this->listTableForeignKeys($tableName);
260
        }
261
262 4233
        $indexes = $this->listTableIndexes($tableName);
263
264 4233
        return new Table($tableName, $columns, $indexes, [], $foreignKeys, []);
265
    }
266
267
    /**
268
     * Lists the views this connection has.
269
     *
270
     * @return array<string, View>
271
     */
272 2922
    public function listViews() : array
273
    {
274 2922
        $database = $this->ensureDatabase(
275 2922
            $this->_conn->getDatabase(),
276 2922
            __METHOD__
277
        );
278
279 2922
        $sql   = $this->_platform->getListViewsSQL($database);
280 2922
        $views = $this->_conn->fetchAll($sql);
281
282 2922
        return $this->_getPortableViewsList($views);
283
    }
284
285
    /**
286
     * Lists the foreign keys for the given table.
287
     *
288
     * @return array<int|string, ForeignKeyConstraint>
289
     */
290 4016
    public function listTableForeignKeys(string $table, ?string $database = null) : array
291
    {
292 4016
        if ($database === null) {
293 4016
            $database = $this->_conn->getDatabase();
294
        }
295 4016
        $sql              = $this->_platform->getListTableForeignKeysSQL($table, $database);
296 4016
        $tableForeignKeys = $this->_conn->fetchAll($sql);
297
298 4016
        return $this->_getPortableTableForeignKeysList($tableForeignKeys);
299
    }
300
301
    /* drop*() Methods */
302
303
    /**
304
     * Drops a database.
305
     *
306
     * NOTE: You can not drop the database this SchemaManager is currently connected to.
307
     */
308 4624
    public function dropDatabase(string $database) : void
309
    {
310 4624
        $this->_execSql($this->_platform->getDropDatabaseSQL($database));
311 4090
    }
312
313
    /**
314
     * Drops the given table.
315
     */
316 5247
    public function dropTable(string $tableName) : void
317
    {
318 5247
        $this->_execSql($this->_platform->getDropTableSQL($tableName));
319 5173
    }
320
321
    /**
322
     * Drops the index from the given table.
323
     *
324
     * @param Index|string $index The name of the index.
325
     * @param Table|string $table The name of the table.
326
     */
327 3045
    public function dropIndex($index, $table) : void
328
    {
329 3045
        if ($index instanceof Index) {
330
            $index = $index->getQuotedName($this->_platform);
331
        }
332
333 3045
        $this->_execSql($this->_platform->getDropIndexSQL($index, $table));
334 3045
    }
335
336
    /**
337
     * Drops the constraint from the given table.
338
     *
339
     * @param Table|string $table The name of the table.
340
     */
341
    public function dropConstraint(Constraint $constraint, $table) : void
342
    {
343
        $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table));
344
    }
345
346
    /**
347
     * Drops a foreign key from a table.
348
     *
349
     * @param ForeignKeyConstraint|string $foreignKey The name of the foreign key.
350
     * @param Table|string                $table      The name of the table with the foreign key.
351
     */
352
    public function dropForeignKey($foreignKey, $table) : void
353
    {
354
        $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table));
355
    }
356
357
    /**
358
     * Drops a sequence with a given name.
359
     */
360 1087
    public function dropSequence(string $name) : void
361
    {
362 1087
        $this->_execSql($this->_platform->getDropSequenceSQL($name));
363
    }
364
365
    /**
366
     * Drops a view.
367
     */
368 3083
    public function dropView(string $name) : void
369
    {
370 3083
        $this->_execSql($this->_platform->getDropViewSQL($name));
371
    }
372
373
    /* create*() Methods */
374
375
    /**
376
     * Creates a new database.
377
     */
378 4622
    public function createDatabase(string $database) : void
379
    {
380 4622
        $this->_execSql($this->_platform->getCreateDatabaseSQL($database));
381 4622
    }
382
383
    /**
384
     * Creates a new table.
385
     */
386 5265
    public function createTable(Table $table) : void
387
    {
388 5265
        $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS;
389 5265
        $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags));
390 5244
    }
391
392
    /**
393
     * Creates a new sequence.
394
     *
395
     * @throws ConnectionException If something fails at database level.
396
     */
397 1089
    public function createSequence(Sequence $sequence) : void
398
    {
399 1089
        $this->_execSql($this->_platform->getCreateSequenceSQL($sequence));
400 1089
    }
401
402
    /**
403
     * Creates a constraint on a table.
404
     *
405
     * @param Table|string $table
406
     */
407 1
    public function createConstraint(Constraint $constraint, $table) : void
408
    {
409 1
        $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table));
410 1
    }
411
412
    /**
413
     * Creates a new index on a table.
414
     *
415
     * @param Table|string $table The name of the table on which the index is to be created.
416
     */
417 3045
    public function createIndex(Index $index, $table) : void
418
    {
419 3045
        $this->_execSql($this->_platform->getCreateIndexSQL($index, $table));
420 3045
    }
421
422
    /**
423
     * Creates a new foreign key.
424
     *
425
     * @param ForeignKeyConstraint $foreignKey The ForeignKey instance.
426
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
427
     */
428 2947
    public function createForeignKey(ForeignKeyConstraint $foreignKey, $table) : void
429
    {
430 2947
        $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table));
431 2947
    }
432
433
    /**
434
     * Creates a new view.
435
     */
436 3083
    public function createView(View $view) : void
437
    {
438 3083
        $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql()));
439 3083
    }
440
441
    /* dropAndCreate*() Methods */
442
443
    /**
444
     * Drops and creates a constraint.
445
     *
446
     * @see dropConstraint()
447
     * @see createConstraint()
448
     *
449
     * @param Table|string $table
450
     */
451
    public function dropAndCreateConstraint(Constraint $constraint, $table) : void
452
    {
453
        $this->tryMethod('dropConstraint', $constraint, $table);
454
        $this->createConstraint($constraint, $table);
455
    }
456
457
    /**
458
     * Drops and creates a new index on a table.
459
     *
460
     * @param Table|string $table The name of the table on which the index is to be created.
461
     */
462 3045
    public function dropAndCreateIndex(Index $index, $table) : void
463
    {
464 3045
        $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table);
465 3045
        $this->createIndex($index, $table);
466 3045
    }
467
468
    /**
469
     * Drops and creates a new foreign key.
470
     *
471
     * @param ForeignKeyConstraint $foreignKey An associative array that defines properties of the foreign key to be created.
472
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
473
     */
474
    public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table) : void
475
    {
476
        $this->tryMethod('dropForeignKey', $foreignKey, $table);
477
        $this->createForeignKey($foreignKey, $table);
478
    }
479
480
    /**
481
     * Drops and create a new sequence.
482
     *
483
     * @throws ConnectionException If something fails at database level.
484
     */
485 1087
    public function dropAndCreateSequence(Sequence $sequence) : void
486
    {
487 1087
        $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform));
488 1087
        $this->createSequence($sequence);
489 1087
    }
490
491
    /**
492
     * Drops and creates a new table.
493
     */
494 5210
    public function dropAndCreateTable(Table $table) : void
495
    {
496 5210
        $this->tryMethod('dropTable', $table->getQuotedName($this->_platform));
497 5210
        $this->createTable($table);
498 5210
    }
499
500
    /**
501
     * Drops and creates a new database.
502
     */
503 4892
    public function dropAndCreateDatabase(string $database) : void
504
    {
505 4892
        $this->tryMethod('dropDatabase', $database);
506 4892
        $this->createDatabase($database);
507 4892
    }
508
509
    /**
510
     * Drops and creates a new view.
511
     */
512 3083
    public function dropAndCreateView(View $view) : void
513
    {
514 3083
        $this->tryMethod('dropView', $view->getQuotedName($this->_platform));
515 3083
        $this->createView($view);
516 3083
    }
517
518
    /* alterTable() Methods */
519
520
    /**
521
     * Alters an existing tables schema.
522
     */
523 3770
    public function alterTable(TableDiff $tableDiff) : void
524
    {
525 3770
        $queries = $this->_platform->getAlterTableSQL($tableDiff);
526
527 3770
        if (! is_array($queries) || ! count($queries)) {
528 1465
            return;
529
        }
530
531 3770
        foreach ($queries as $ddlQuery) {
532 3770
            $this->_execSql($ddlQuery);
533
        }
534 3770
    }
535
536
    /**
537
     * Renames a given table to another name.
538
     */
539 1
    public function renameTable(string $name, string $newName) : void
540
    {
541 1
        $tableDiff          = new TableDiff($name);
542 1
        $tableDiff->newName = $newName;
543 1
        $this->alterTable($tableDiff);
544 1
    }
545
546
    /**
547
     * Methods for filtering return values of list*() methods to convert
548
     * the native DBMS data definition to a portable Doctrine definition
549
     */
550
551
    /**
552
     * @param array<int, mixed> $databases
553
     *
554
     * @return array<int, string>
555
     */
556 2925
    protected function _getPortableDatabasesList(array $databases) : array
557
    {
558 2925
        $list = [];
559 2925
        foreach ($databases as $value) {
560 2925
            $value = $this->_getPortableDatabaseDefinition($value);
561
562 2925
            if (! $value) {
563
                continue;
564
            }
565
566 2925
            $list[] = $value;
567
        }
568
569 2925
        return $list;
570
    }
571
572
    /**
573
     * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition.
574
     *
575
     * @param array<int, array<int, mixed>> $namespaces The list of namespace names in the native DBMS data definition.
576
     *
577
     * @return array<int, string>
578
     */
579 1061
    protected function getPortableNamespacesList(array $namespaces) : array
580
    {
581 1061
        $namespacesList = [];
582
583 1061
        foreach ($namespaces as $namespace) {
584 1061
            $namespacesList[] = $this->getPortableNamespaceDefinition($namespace);
585
        }
586
587 1061
        return $namespacesList;
588
    }
589
590
    /**
591
     * @param array<string, string> $database
592
     */
593
    protected function _getPortableDatabaseDefinition(array $database) : string
594
    {
595
        return array_shift($database);
596
    }
597
598
    /**
599
     * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition.
600
     *
601
     * @param array<string|int, mixed> $namespace The native DBMS namespace definition.
602
     */
603
    protected function getPortableNamespaceDefinition(array $namespace) : string
604
    {
605
        return array_shift($namespace);
606
    }
607
608
    /**
609
     * @param array<int, array<string, mixed>> $sequences
610
     *
611
     * @return array<int, Sequence>
612
     */
613 277
    protected function _getPortableSequencesList(array $sequences) : array
614
    {
615 277
        $list = [];
616
617 277
        foreach ($sequences as $value) {
618 277
            $list[] = $this->_getPortableSequenceDefinition($value);
619
        }
620
621 277
        return $list;
622
    }
623
624
    /**
625
     * @param array<string, mixed> $sequence
626
     *
627
     * @throws DBALException
628
     */
629
    protected function _getPortableSequenceDefinition(array $sequence) : Sequence
630
    {
631
        throw NotSupported::new('Sequences');
632
    }
633
634
    /**
635
     * Independent of the database the keys of the column list result are lowercased.
636
     *
637
     * The name of the created column instance however is kept in its case.
638
     *
639
     * @param array<int, array<string, mixed>> $tableColumns
640
     *
641
     * @return array<string, Column>
642
     */
643 4245
    protected function _getPortableTableColumnList(string $table, string $database, array $tableColumns) : array
644
    {
645 4245
        $eventManager = $this->_platform->getEventManager();
646
647 4245
        $list = [];
648 4245
        foreach ($tableColumns as $tableColumn) {
649 4245
            $column           = null;
650 4245
            $defaultPrevented = false;
651
652 4245
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) {
653 3145
                $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn);
654 3145
                $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs);
655
656 3145
                $defaultPrevented = $eventArgs->isDefaultPrevented();
657 3145
                $column           = $eventArgs->getColumn();
658
            }
659
660 4245
            if (! $defaultPrevented) {
661 4245
                $column = $this->_getPortableTableColumnDefinition($tableColumn);
662
            }
663
664 4245
            if (! $column) {
665
                continue;
666
            }
667
668 4245
            $name        = strtolower($column->getQuotedName($this->_platform));
669 4245
            $list[$name] = $column;
670
        }
671
672 4245
        return $list;
673
    }
674
675
    /**
676
     * Gets Table Column Definition.
677
     *
678
     * @param array<string, mixed> $tableColumn
679
     */
680
    abstract protected function _getPortableTableColumnDefinition(array $tableColumn) : Column;
681
682
    /**
683
     * Aggregates and groups the index results according to the required data result.
684
     *
685
     * @param array<int, array<string, mixed>> $tableIndexRows
686
     *
687
     * @return array<string, Index>
688
     */
689 4238
    protected function _getPortableTableIndexesList(array $tableIndexRows, string $tableName) : array
690
    {
691 4238
        $result = [];
692 4238
        foreach ($tableIndexRows as $tableIndex) {
693 4132
            $indexName = $keyName = $tableIndex['key_name'];
694 4132
            if ($tableIndex['primary']) {
695 4130
                $keyName = 'primary';
696
            }
697 4132
            $keyName = strtolower($keyName);
698
699 4132
            if (! isset($result[$keyName])) {
700
                $options = [
701 4132
                    'lengths' => [],
702
                ];
703
704 4132
                if (isset($tableIndex['where'])) {
705 872
                    $options['where'] = $tableIndex['where'];
706
                }
707
708 4132
                $result[$keyName] = [
709 4132
                    'name' => $indexName,
710
                    'columns' => [],
711 4132
                    'unique' => ! $tableIndex['non_unique'],
712 4132
                    'primary' => $tableIndex['primary'],
713 4132
                    'flags' => $tableIndex['flags'] ?? [],
714 4132
                    'options' => $options,
715
                ];
716
            }
717
718 4132
            $result[$keyName]['columns'][]            = $tableIndex['column_name'];
719 4132
            $result[$keyName]['options']['lengths'][] = $tableIndex['length'] ?? null;
720
        }
721
722 4238
        $eventManager = $this->_platform->getEventManager();
723
724 4238
        $indexes = [];
725 4238
        foreach ($result as $indexKey => $data) {
726 4132
            $index            = null;
727 4132
            $defaultPrevented = false;
728
729 4132
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
730 3120
                $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn);
731 3120
                $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs);
732
733 3120
                $defaultPrevented = $eventArgs->isDefaultPrevented();
734 3120
                $index            = $eventArgs->getIndex();
735
            }
736
737 4132
            if (! $defaultPrevented) {
738 4132
                $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags'], $data['options']);
739
            }
740
741 4132
            if (! $index) {
742
                continue;
743
            }
744
745 4132
            $indexes[$indexKey] = $index;
746
        }
747
748 4238
        return $indexes;
749
    }
750
751
    /**
752
     * @param array<int, array<string, mixed>> $tables
753
     *
754
     * @return array<int, string>
755
     */
756 4521
    protected function _getPortableTablesList(array $tables) : array
757
    {
758 4521
        $list = [];
759 4521
        foreach ($tables as $value) {
760 4519
            $value = $this->_getPortableTableDefinition($value);
761
762 4519
            if (! $value) {
763
                continue;
764
            }
765
766 4519
            $list[] = $value;
767
        }
768
769 4521
        return $list;
770
    }
771
772
    /**
773
     * @param array<string, string> $table
774
     */
775
    protected function _getPortableTableDefinition(array $table) : string
776
    {
777
        return array_shift($table);
778
    }
779
780
    /**
781
     * @param array<int, array<string, mixed>> $users
782
     *
783
     * @return array<int, array<string, mixed>>
784
     */
785
    protected function _getPortableUsersList(array $users) : array
786
    {
787
        $list = [];
788
        foreach ($users as $value) {
789
            $value = $this->_getPortableUserDefinition($value);
790
791
            if (! $value) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $value of type array<string,mixed> is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
792
                continue;
793
            }
794
795
            $list[] = $value;
796
        }
797
798
        return $list;
799
    }
800
801
    /**
802
     * @param array<string, mixed> $user
803
     *
804
     * @return array<string, mixed>
805
     */
806
    protected function _getPortableUserDefinition(array $user) : array
807
    {
808
        return $user;
809
    }
810
811
    /**
812
     * @param array<int, array<string, mixed>> $views
813
     *
814
     * @return array<string, View>
815
     */
816 2922
    protected function _getPortableViewsList(array $views) : array
817
    {
818 2922
        $list = [];
819 2922
        foreach ($views as $value) {
820 2922
            $view        = $this->_getPortableViewDefinition($value);
821 2922
            $name        = strtolower($view->getQuotedName($this->_platform));
822 2922
            $list[$name] = $view;
823
        }
824
825 2922
        return $list;
826
    }
827
828
    /**
829
     * @param array<string, mixed> $view
830
     */
831
    protected function _getPortableViewDefinition(array $view) : View
832
    {
833
        throw NotSupported::new('Views');
834
    }
835
836
    /**
837
     * @param array<int|string, array<string, mixed>> $tableForeignKeys
838
     *
839
     * @return array<int, ForeignKeyConstraint>
840
     */
841 1410
    protected function _getPortableTableForeignKeysList(array $tableForeignKeys) : array
842
    {
843 1410
        $list = [];
844
845 1410
        foreach ($tableForeignKeys as $value) {
846 1290
            $list[] = $this->_getPortableTableForeignKeyDefinition($value);
847
        }
848
849 1410
        return $list;
850
    }
851
852
    /**
853
     * @param array<string, mixed> $tableForeignKey
854
     */
855
    protected function _getPortableTableForeignKeyDefinition(array $tableForeignKey) : ForeignKeyConstraint
0 ignored issues
show
Unused Code introduced by
The parameter $tableForeignKey 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

855
    protected function _getPortableTableForeignKeyDefinition(/** @scrutinizer ignore-unused */ array $tableForeignKey) : ForeignKeyConstraint

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...
856
    {
857
        throw NotSupported::new('ForeignKey');
858
    }
859
860
    /**
861
     * @param array<int, string>|string $sql
862
     */
863 5296
    protected function _execSql($sql) : void
864
    {
865 5296
        foreach ((array) $sql as $query) {
866 5296
            $this->_conn->executeUpdate($query);
867
        }
868 5269
    }
869
870
    /**
871
     * Creates a schema instance for the current database.
872
     */
873 3869
    public function createSchema() : Schema
874
    {
875 3869
        $namespaces = [];
876
877 3869
        if ($this->_platform->supportsSchemas()) {
878 979
            $namespaces = $this->listNamespaceNames();
879
        }
880
881 3869
        $sequences = [];
882
883 3869
        if ($this->_platform->supportsSequences()) {
884 980
            $sequences = $this->listSequences();
885
        }
886
887 3869
        $tables = $this->listTables();
888
889 3869
        return new Schema($tables, $sequences, $this->createSchemaConfig(), $namespaces);
890
    }
891
892
    /**
893
     * Creates the configuration for this schema.
894
     */
895 4117
    public function createSchemaConfig() : SchemaConfig
896
    {
897 4117
        $schemaConfig = new SchemaConfig();
898 4117
        $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength());
899
900 4117
        $searchPaths = $this->getSchemaSearchPaths();
901 4117
        if (isset($searchPaths[0])) {
902 4116
            $schemaConfig->setName($searchPaths[0]);
903
        }
904
905 4117
        $params = $this->_conn->getParams();
906 4117
        if (! isset($params['defaultTableOptions'])) {
907 4117
            $params['defaultTableOptions'] = [];
908
        }
909 4117
        if (! isset($params['defaultTableOptions']['charset']) && isset($params['charset'])) {
910 851
            $params['defaultTableOptions']['charset'] = $params['charset'];
911
        }
912 4117
        $schemaConfig->setDefaultTableOptions($params['defaultTableOptions']);
913
914 4117
        return $schemaConfig;
915
    }
916
917
    /**
918
     * The search path for namespaces in the currently connected database.
919
     *
920
     * The first entry is usually the default namespace in the Schema. All
921
     * further namespaces contain tables/sequences which can also be addressed
922
     * with a short, not full-qualified name.
923
     *
924
     * For databases that don't support subschema/namespaces this method
925
     * returns the name of the currently connected database.
926
     *
927
     * @return array<int, string>
928
     */
929 3413
    public function getSchemaSearchPaths() : array
930
    {
931 3413
        $database = $this->_conn->getDatabase();
932
933 3413
        if ($database !== null) {
934 3226
            return [$database];
935
        }
936
937 851
        return [];
938
    }
939
940
    /**
941
     * Given a table comment this method tries to extract a type hint for Doctrine Type. If the type hint is found,
942
     * it's removed from the comment.
943
     *
944
     * @return string|null The extracted Doctrine type or NULL of the type hint was not found.
945
     */
946 4252
    final protected function extractDoctrineTypeFromComment(?string &$comment) : ?string
947
    {
948 4252
        if ($comment === null || ! preg_match('/(.*)\(DC2Type:(((?!\)).)+)\)(.*)/', $comment, $match)) {
949 4247
            return null;
950
        }
951
952 3278
        $comment = $match[1] . $match[4];
953
954 3278
        return $match[2];
955
    }
956
957
    /**
958
     * @throws DatabaseRequired
959
     */
960 4250
    private function ensureDatabase(?string $database, string $methodName) : string
961
    {
962 4250
        if ($database === null) {
963 1844
            throw DatabaseRequired::new($methodName);
964
        }
965
966 4250
        return $database;
967
    }
968
}
969