Completed
Push — develop ( fa42c1...0ef7d4 )
by Sergei
22:52
created

_getPortableTableIndexesList()   B

Complexity

Conditions 11
Paths 99

Size

Total Lines 60
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 34
CRAP Score 11.0028

Importance

Changes 0
Metric Value
eloc 36
dl 0
loc 60
ccs 34
cts 35
cp 0.9714
rs 7.3166
c 0
b 0
f 0
cc 11
nc 99
nop 2
crap 11.0028

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
namespace Doctrine\DBAL\Schema;
4
5
use Doctrine\DBAL\Connection;
6
use Doctrine\DBAL\ConnectionException;
7
use Doctrine\DBAL\DBALException;
8
use Doctrine\DBAL\Event\SchemaColumnDefinitionEventArgs;
9
use Doctrine\DBAL\Event\SchemaIndexDefinitionEventArgs;
10
use Doctrine\DBAL\Events;
11
use Doctrine\DBAL\Platforms\AbstractPlatform;
12
use Throwable;
13
use function array_filter;
14
use function array_intersect;
15
use function array_map;
16
use function array_values;
17
use function call_user_func_array;
18
use function count;
19
use function func_get_args;
20
use function is_array;
21
use function preg_match;
22
use function str_replace;
23
use function strtolower;
24
25
/**
26
 * Base class for schema managers. Schema managers are used to inspect and/or
27
 * modify the database schema/structure.
28
 */
29
abstract class AbstractSchemaManager
30
{
31
    /**
32
     * Holds instance of the Doctrine connection for this schema manager.
33
     *
34
     * @var Connection
35
     */
36
    protected $_conn;
37
38
    /**
39
     * Holds instance of the database platform used for this schema manager.
40
     *
41
     * @var AbstractPlatform
42
     */
43
    protected $_platform;
44
45
    /**
46
     * Constructor. Accepts the Connection instance to manage the schema for.
47
     */
48 1601
    public function __construct(Connection $conn, ?AbstractPlatform $platform = null)
49
    {
50 1601
        $this->_conn     = $conn;
51 1601
        $this->_platform = $platform ?: $this->_conn->getDatabasePlatform();
52 1601
    }
53
54
    /**
55
     * Returns the associated platform.
56
     *
57
     * @return AbstractPlatform
58
     */
59 465
    public function getDatabasePlatform()
60
    {
61 465
        return $this->_platform;
62
    }
63
64
    /**
65
     * Tries any method on the schema manager. Normally a method throws an
66
     * exception when your DBMS doesn't support it or if an error occurs.
67
     * This method allows you to try and method on your SchemaManager
68
     * instance and will return false if it does not work or is not supported.
69
     *
70
     * <code>
71
     * $result = $sm->tryMethod('dropView', 'view_name');
72
     * </code>
73
     *
74
     * @return mixed
75
     */
76 2276
    public function tryMethod()
77
    {
78 2276
        $args   = func_get_args();
79 2276
        $method = $args[0];
80 2276
        unset($args[0]);
81 2276
        $args = array_values($args);
82
83
        try {
84 2276
            return call_user_func_array([$this, $method], $args);
85 1690
        } catch (Throwable $e) {
86 1690
            return false;
87
        }
88
    }
89
90
    /**
91
     * Lists the available databases for this connection.
92
     *
93
     * @return string[]
94
     */
95 43
    public function listDatabases()
96
    {
97 43
        $sql = $this->_platform->getListDatabasesSQL();
98
99 42
        $databases = $this->_conn->fetchAll($sql);
100
101 42
        return $this->_getPortableDatabasesList($databases);
102
    }
103
104
    /**
105
     * Returns a list of all namespaces in the current database.
106
     *
107
     * @return string[]
108
     */
109 16
    public function listNamespaceNames()
110
    {
111 16
        $sql = $this->_platform->getListNamespacesSQL();
112
113 16
        $namespaces = $this->_conn->fetchAll($sql);
114
115 16
        return $this->getPortableNamespacesList($namespaces);
116
    }
117
118
    /**
119
     * Lists the available sequences for this connection.
120
     *
121
     * @param string|null $database
122
     *
123
     * @return Sequence[]
124
     */
125 53
    public function listSequences($database = null)
126
    {
127 53
        if ($database === null) {
128 53
            $database = $this->_conn->getDatabase();
129
        }
130 53
        $sql = $this->_platform->getListSequencesSQL($database);
131
132 53
        $sequences = $this->_conn->fetchAll($sql);
133
134 53
        return $this->filterAssetNames($this->_getPortableSequencesList($sequences));
135
    }
136
137
    /**
138
     * Lists the columns for a given table.
139
     *
140
     * In contrast to other libraries and to the old version of Doctrine,
141
     * this column definition does try to contain the 'primary' field for
142
     * the reason that it is not portable across different RDBMS. Use
143
     * {@see listTableIndexes($tableName)} to retrieve the primary key
144
     * of a table. We're a RDBMS specifies more details these are held
145
     * in the platformDetails array.
146
     *
147
     * @param string      $table    The name of the table.
148
     * @param string|null $database
149
     *
150
     * @return Column[]
151
     */
152 1153
    public function listTableColumns($table, $database = null)
153
    {
154 1153
        if (! $database) {
155 1152
            $database = $this->_conn->getDatabase();
156
        }
157
158 1153
        $sql = $this->_platform->getListTableColumnsSQL($table, $database);
159
160 1153
        $tableColumns = $this->_conn->fetchAll($sql);
161
162 1153
        return $this->_getPortableTableColumnList($table, $database, $tableColumns);
163
    }
164
165
    /**
166
     * Lists the indexes for a given table returning an array of Index instances.
167
     *
168
     * Keys of the portable indexes list are all lower-cased.
169
     *
170
     * @param string $table The name of the table.
171
     *
172
     * @return Index[]
173
     */
174 893
    public function listTableIndexes($table)
175
    {
176 893
        $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
177
178 893
        $tableIndexes = $this->_conn->fetchAll($sql);
179
180 893
        return $this->_getPortableTableIndexesList($tableIndexes, $table);
181
    }
182
183
    /**
184
     * Returns true if all the given tables exist.
185
     *
186
     * @param string[] $tableNames
187
     *
188
     * @return bool
189
     */
190 1745
    public function tablesExist($tableNames)
191
    {
192 1745
        $tableNames = array_map('strtolower', (array) $tableNames);
193
194 1745
        return count($tableNames) === count(array_intersect($tableNames, array_map('strtolower', $this->listTableNames())));
195
    }
196
197
    /**
198
     * Returns a list of all tables in the current database.
199
     *
200
     * @return string[]
201
     */
202 1761
    public function listTableNames()
203
    {
204 1761
        $sql = $this->_platform->getListTablesSQL();
205
206 1761
        $tables     = $this->_conn->fetchAll($sql);
207 1761
        $tableNames = $this->_getPortableTablesList($tables);
208
209 1761
        return $this->filterAssetNames($tableNames);
210
    }
211
212
    /**
213
     * Filters asset names if they are configured to return only a subset of all
214
     * the found elements.
215
     *
216
     * @param mixed[] $assetNames
217
     *
218
     * @return mixed[]
219
     */
220 1823
    protected function filterAssetNames($assetNames)
221
    {
222 1823
        $filter = $this->_conn->getConfiguration()->getSchemaAssetsFilter();
223 1823
        if (! $filter) {
224 1823
            return $assetNames;
225
        }
226
227 6
        return array_values(array_filter($assetNames, $filter));
228
    }
229
230
    /**
231
     * @deprecated Use Configuration::getSchemaAssetsFilter() instead
232
     *
233
     * @return string|null
234
     */
235
    protected function getFilterSchemaAssetsExpression()
236
    {
237
        return $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression();
1 ignored issue
show
Deprecated Code introduced by
The function Doctrine\DBAL\Configurat...chemaAssetsExpression() has been deprecated: Use Configuration::getSchemaAssetsFilter() instead ( Ignorable by Annotation )

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

237
        return /** @scrutinizer ignore-deprecated */ $this->_conn->getConfiguration()->getFilterSchemaAssetsExpression();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
238
    }
239
240
    /**
241
     * Lists the tables for this connection.
242
     *
243
     * @return Table[]
244
     */
245 122
    public function listTables()
246
    {
247 122
        $tableNames = $this->listTableNames();
248
249 122
        $tables = [];
250 122
        foreach ($tableNames as $tableName) {
251 99
            $tables[] = $this->listTableDetails($tableName);
252
        }
253
254 122
        return $tables;
255
    }
256
257
    /**
258
     * @param string $tableName
259
     *
260
     * @return Table
261
     */
262 824
    public function listTableDetails($tableName)
263
    {
264 824
        $columns     = $this->listTableColumns($tableName);
265 824
        $foreignKeys = [];
266
267 824
        if ($this->_platform->supportsForeignKeyConstraints()) {
268 750
            $foreignKeys = $this->listTableForeignKeys($tableName);
269
        }
270
271 824
        $indexes = $this->listTableIndexes($tableName);
272
273 824
        return new Table($tableName, $columns, $indexes, [], $foreignKeys, []);
274
    }
275
276
    /**
277
     * Lists the views this connection has.
278
     *
279
     * @return View[]
280
     */
281 23
    public function listViews()
282
    {
283 23
        $database = $this->_conn->getDatabase();
284 23
        $sql      = $this->_platform->getListViewsSQL($database);
285 23
        $views    = $this->_conn->fetchAll($sql);
286
287 23
        return $this->_getPortableViewsList($views);
288
    }
289
290
    /**
291
     * Lists the foreign keys for the given table.
292
     *
293
     * @param string      $table    The name of the table.
294
     * @param string|null $database
295
     *
296
     * @return ForeignKeyConstraint[]
297
     */
298 825
    public function listTableForeignKeys($table, $database = null)
299
    {
300 825
        if ($database === null) {
301 825
            $database = $this->_conn->getDatabase();
302
        }
303 825
        $sql              = $this->_platform->getListTableForeignKeysSQL($table, $database);
0 ignored issues
show
Unused Code introduced by
The call to Doctrine\DBAL\Platforms\...stTableForeignKeysSQL() has too many arguments starting with $database. ( Ignorable by Annotation )

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

303
        /** @scrutinizer ignore-call */ 
304
        $sql              = $this->_platform->getListTableForeignKeysSQL($table, $database);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
304 825
        $tableForeignKeys = $this->_conn->fetchAll($sql);
305
306 825
        return $this->_getPortableTableForeignKeysList($tableForeignKeys);
307
    }
308
309
    /* drop*() Methods */
310
311
    /**
312
     * Drops a database.
313
     *
314
     * NOTE: You can not drop the database this SchemaManager is currently connected to.
315
     *
316
     * @param string $database The name of the database to drop.
317
     *
318
     * @return void
319
     */
320 42
    public function dropDatabase($database)
321
    {
322 42
        $this->_execSql($this->_platform->getDropDatabaseSQL($database));
323 31
    }
324
325
    /**
326
     * Drops the given table.
327
     *
328
     * @param string $tableName The name of the table to drop.
329
     *
330
     * @return void
331
     */
332 2590
    public function dropTable($tableName)
333
    {
334 2590
        $this->_execSql($this->_platform->getDropTableSQL($tableName));
335 1257
    }
336
337
    /**
338
     * Drops the index from the given table.
339
     *
340
     * @param Index|string $index The name of the index.
341
     * @param Table|string $table The name of the table.
342
     *
343
     * @return void
344
     */
345 23
    public function dropIndex($index, $table)
346
    {
347 23
        if ($index instanceof Index) {
348
            $index = $index->getQuotedName($this->_platform);
349
        }
350
351 23
        $this->_execSql($this->_platform->getDropIndexSQL($index, $table));
352 23
    }
353
354
    /**
355
     * Drops the constraint from the given table.
356
     *
357
     * @param Table|string $table The name of the table.
358
     *
359
     * @return void
360
     */
361
    public function dropConstraint(Constraint $constraint, $table)
362
    {
363
        $this->_execSql($this->_platform->getDropConstraintSQL($constraint, $table));
364
    }
365
366
    /**
367
     * Drops a foreign key from a table.
368
     *
369
     * @param ForeignKeyConstraint|string $foreignKey The name of the foreign key.
370
     * @param Table|string                $table      The name of the table with the foreign key.
371
     *
372
     * @return void
373
     */
374
    public function dropForeignKey($foreignKey, $table)
375
    {
376
        $this->_execSql($this->_platform->getDropForeignKeySQL($foreignKey, $table));
377
    }
378
379
    /**
380
     * Drops a sequence with a given name.
381
     *
382
     * @param string $name The name of the sequence to drop.
383
     *
384
     * @return void
385
     */
386 18
    public function dropSequence($name)
387
    {
388 18
        $this->_execSql($this->_platform->getDropSequenceSQL($name));
389
    }
390
391
    /**
392
     * Drops a view.
393
     *
394
     * @param string $name The name of the view.
395
     *
396
     * @return void
397
     */
398 29
    public function dropView($name)
399
    {
400 29
        $this->_execSql($this->_platform->getDropViewSQL($name));
401
    }
402
403
    /* create*() Methods */
404
405
    /**
406
     * Creates a new database.
407
     *
408
     * @param string $database The name of the database to create.
409
     *
410
     * @return void
411
     */
412 40
    public function createDatabase($database)
413
    {
414 40
        $this->_execSql($this->_platform->getCreateDatabaseSQL($database));
415 40
    }
416
417
    /**
418
     * Creates a new table.
419
     *
420
     * @return void
421
     */
422 3381
    public function createTable(Table $table)
423
    {
424 3381
        $createFlags = AbstractPlatform::CREATE_INDEXES|AbstractPlatform::CREATE_FOREIGNKEYS;
425 3381
        $this->_execSql($this->_platform->getCreateTableSQL($table, $createFlags));
426 2528
    }
427
428
    /**
429
     * Creates a new sequence.
430
     *
431
     * @param Sequence $sequence
432
     *
433
     * @return void
434
     *
435
     * @throws ConnectionException If something fails at database level.
436
     */
437 44
    public function createSequence($sequence)
438
    {
439 44
        $this->_execSql($this->_platform->getCreateSequenceSQL($sequence));
440 38
    }
441
442
    /**
443
     * Creates a constraint on a table.
444
     *
445
     * @param Table|string $table
446
     *
447
     * @return void
448
     */
449 1
    public function createConstraint(Constraint $constraint, $table)
450
    {
451 1
        $this->_execSql($this->_platform->getCreateConstraintSQL($constraint, $table));
452 1
    }
453
454
    /**
455
     * Creates a new index on a table.
456
     *
457
     * @param Table|string $table The name of the table on which the index is to be created.
458
     *
459
     * @return void
460
     */
461 23
    public function createIndex(Index $index, $table)
462
    {
463 23
        $this->_execSql($this->_platform->getCreateIndexSQL($index, $table));
464 23
    }
465
466
    /**
467
     * Creates a new foreign key.
468
     *
469
     * @param ForeignKeyConstraint $foreignKey The ForeignKey instance.
470
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
471
     *
472
     * @return void
473
     */
474 44
    public function createForeignKey(ForeignKeyConstraint $foreignKey, $table)
475
    {
476 44
        $this->_execSql($this->_platform->getCreateForeignKeySQL($foreignKey, $table));
477 44
    }
478
479
    /**
480
     * Creates a new view.
481
     *
482
     * @return void
483
     */
484 29
    public function createView(View $view)
485
    {
486 29
        $this->_execSql($this->_platform->getCreateViewSQL($view->getQuotedName($this->_platform), $view->getSql()));
487 29
    }
488
489
    /* dropAndCreate*() Methods */
490
491
    /**
492
     * Drops and creates a constraint.
493
     *
494
     * @see dropConstraint()
495
     * @see createConstraint()
496
     *
497
     * @param Table|string $table
498
     *
499
     * @return void
500
     */
501
    public function dropAndCreateConstraint(Constraint $constraint, $table)
502
    {
503
        $this->tryMethod('dropConstraint', $constraint, $table);
504
        $this->createConstraint($constraint, $table);
505
    }
506
507
    /**
508
     * Drops and creates a new index on a table.
509
     *
510
     * @param Table|string $table The name of the table on which the index is to be created.
511
     *
512
     * @return void
513
     */
514 23
    public function dropAndCreateIndex(Index $index, $table)
515
    {
516 23
        $this->tryMethod('dropIndex', $index->getQuotedName($this->_platform), $table);
517 23
        $this->createIndex($index, $table);
518 23
    }
519
520
    /**
521
     * Drops and creates a new foreign key.
522
     *
523
     * @param ForeignKeyConstraint $foreignKey An associative array that defines properties of the foreign key to be created.
524
     * @param Table|string         $table      The name of the table on which the foreign key is to be created.
525
     *
526
     * @return void
527
     */
528
    public function dropAndCreateForeignKey(ForeignKeyConstraint $foreignKey, $table)
529
    {
530
        $this->tryMethod('dropForeignKey', $foreignKey, $table);
531
        $this->createForeignKey($foreignKey, $table);
532
    }
533
534
    /**
535
     * Drops and create a new sequence.
536
     *
537
     * @return void
538
     *
539
     * @throws ConnectionException If something fails at database level.
540
     */
541 18
    public function dropAndCreateSequence(Sequence $sequence)
542
    {
543 18
        $this->tryMethod('dropSequence', $sequence->getQuotedName($this->_platform));
544 18
        $this->createSequence($sequence);
545 18
    }
546
547
    /**
548
     * Drops and creates a new table.
549
     *
550
     * @return void
551
     */
552 1553
    public function dropAndCreateTable(Table $table)
553
    {
554 1553
        $this->tryMethod('dropTable', $table->getQuotedName($this->_platform));
555 1553
        $this->createTable($table);
556 1553
    }
557
558
    /**
559
     * Drops and creates a new database.
560
     *
561
     * @param string $database The name of the database to create.
562
     *
563
     * @return void
564
     */
565 43
    public function dropAndCreateDatabase($database)
566
    {
567 43
        $this->tryMethod('dropDatabase', $database);
568 43
        $this->createDatabase($database);
569 43
    }
570
571
    /**
572
     * Drops and creates a new view.
573
     *
574
     * @return void
575
     */
576 29
    public function dropAndCreateView(View $view)
577
    {
578 29
        $this->tryMethod('dropView', $view->getQuotedName($this->_platform));
579 29
        $this->createView($view);
580 29
    }
581
582
    /* alterTable() Methods */
583
584
    /**
585
     * Alters an existing tables schema.
586
     *
587
     * @return void
588
     */
589 420
    public function alterTable(TableDiff $tableDiff)
590
    {
591 420
        $queries = $this->_platform->getAlterTableSQL($tableDiff);
592
593 420
        if (! is_array($queries) || ! count($queries)) {
594 8
            return;
595
        }
596
597 412
        foreach ($queries as $ddlQuery) {
598 412
            $this->_execSql($ddlQuery);
599
        }
600 412
    }
601
602
    /**
603
     * Renames a given table to another name.
604
     *
605
     * @param string $name    The current name of the table.
606
     * @param string $newName The new name of the table.
607
     *
608
     * @return void
609
     */
610 1
    public function renameTable($name, $newName)
611
    {
612 1
        $tableDiff          = new TableDiff($name);
613 1
        $tableDiff->newName = $newName;
614 1
        $this->alterTable($tableDiff);
615 1
    }
616
617
    /**
618
     * Methods for filtering return values of list*() methods to convert
619
     * the native DBMS data definition to a portable Doctrine definition
620
     */
621
622
    /**
623
     * @param mixed[] $databases
624
     *
625
     * @return string[]
626
     */
627 42
    protected function _getPortableDatabasesList($databases)
628
    {
629 42
        $list = [];
630 42
        foreach ($databases as $value) {
631 42
            $value = $this->_getPortableDatabaseDefinition($value);
632
633 42
            if (! $value) {
634
                continue;
635
            }
636
637 42
            $list[] = $value;
638
        }
639
640 42
        return $list;
641
    }
642
643
    /**
644
     * Converts a list of namespace names from the native DBMS data definition to a portable Doctrine definition.
645
     *
646
     * @param mixed[][] $namespaces The list of namespace names in the native DBMS data definition.
647
     *
648
     * @return string[]
649
     */
650 16
    protected function getPortableNamespacesList(array $namespaces)
651
    {
652 16
        $namespacesList = [];
653
654 16
        foreach ($namespaces as $namespace) {
655 16
            $namespacesList[] = $this->getPortableNamespaceDefinition($namespace);
656
        }
657
658 16
        return $namespacesList;
659
    }
660
661
    /**
662
     * @param mixed $database
663
     *
664
     * @return mixed
665
     */
666
    protected function _getPortableDatabaseDefinition($database)
667
    {
668
        return $database;
669
    }
670
671
    /**
672
     * Converts a namespace definition from the native DBMS data definition to a portable Doctrine definition.
673
     *
674
     * @param mixed[] $namespace The native DBMS namespace definition.
675
     *
676
     * @return mixed
677
     */
678
    protected function getPortableNamespaceDefinition(array $namespace)
679
    {
680
        return $namespace;
681
    }
682
683
    /**
684
     * @param mixed[][] $functions
685
     *
686
     * @return mixed[][]
687
     */
688
    protected function _getPortableFunctionsList($functions)
689
    {
690
        $list = [];
691
        foreach ($functions as $value) {
692
            $value = $this->_getPortableFunctionDefinition($value);
693
694
            if (! $value) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $value of type array<mixed,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...
695
                continue;
696
            }
697
698
            $list[] = $value;
699
        }
700
701
        return $list;
702
    }
703
704
    /**
705
     * @param mixed[] $function
706
     *
707
     * @return mixed
708
     */
709
    protected function _getPortableFunctionDefinition($function)
710
    {
711
        return $function;
712
    }
713
714
    /**
715
     * @param mixed[][] $triggers
716
     *
717
     * @return mixed[][]
718
     */
719
    protected function _getPortableTriggersList($triggers)
720
    {
721
        $list = [];
722
        foreach ($triggers as $value) {
723
            $value = $this->_getPortableTriggerDefinition($value);
724
725
            if (! $value) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $value of type array<mixed,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...
726
                continue;
727
            }
728
729
            $list[] = $value;
730
        }
731
732
        return $list;
733
    }
734
735
    /**
736
     * @param mixed[] $trigger
737
     *
738
     * @return mixed
739
     */
740
    protected function _getPortableTriggerDefinition($trigger)
741
    {
742
        return $trigger;
743
    }
744
745
    /**
746
     * @param mixed[][] $sequences
747
     *
748
     * @return Sequence[]
749
     */
750 17
    protected function _getPortableSequencesList($sequences)
751
    {
752 17
        $list = [];
753 17
        foreach ($sequences as $value) {
754 17
            $value = $this->_getPortableSequenceDefinition($value);
755
756 17
            if (! $value) {
757
                continue;
758
            }
759
760 17
            $list[] = $value;
761
        }
762
763 17
        return $list;
764
    }
765
766
    /**
767
     * @param mixed[] $sequence
768
     *
769
     * @return Sequence
770
     *
771
     * @throws DBALException
772
     */
773
    protected function _getPortableSequenceDefinition($sequence)
774
    {
775
        throw DBALException::notSupported('Sequences');
776
    }
777
778
    /**
779
     * Independent of the database the keys of the column list result are lowercased.
780
     *
781
     * The name of the created column instance however is kept in its case.
782
     *
783
     * @param string    $table        The name of the table.
784
     * @param string    $database
785
     * @param mixed[][] $tableColumns
786
     *
787
     * @return Column[]
788
     */
789 1153
    protected function _getPortableTableColumnList($table, $database, $tableColumns)
790
    {
791 1153
        $eventManager = $this->_platform->getEventManager();
792
793 1153
        $list = [];
794 1153
        foreach ($tableColumns as $tableColumn) {
795 1153
            $column           = null;
796 1153
            $defaultPrevented = false;
797
798 1153
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaColumnDefinition)) {
799 23
                $eventArgs = new SchemaColumnDefinitionEventArgs($tableColumn, $table, $database, $this->_conn);
800 23
                $eventManager->dispatchEvent(Events::onSchemaColumnDefinition, $eventArgs);
801
802 23
                $defaultPrevented = $eventArgs->isDefaultPrevented();
803 23
                $column           = $eventArgs->getColumn();
804
            }
805
806 1153
            if (! $defaultPrevented) {
807 1153
                $column = $this->_getPortableTableColumnDefinition($tableColumn);
808
            }
809
810 1153
            if (! $column) {
811
                continue;
812
            }
813
814 1153
            $name        = strtolower($column->getQuotedName($this->_platform));
815 1153
            $list[$name] = $column;
816
        }
817
818 1153
        return $list;
819
    }
820
821
    /**
822
     * Gets Table Column Definition.
823
     *
824
     * @param mixed[] $tableColumn
825
     *
826
     * @return Column
827
     */
828
    abstract protected function _getPortableTableColumnDefinition($tableColumn);
829
830
    /**
831
     * Aggregates and groups the index results according to the required data result.
832
     *
833
     * @param mixed[][]   $tableIndexRows
834
     * @param string|null $tableName
835
     *
836
     * @return Index[]
837
     */
838 951
    protected function _getPortableTableIndexesList($tableIndexRows, $tableName = null)
839
    {
840 951
        $result = [];
841 951
        foreach ($tableIndexRows as $tableIndex) {
842 542
            $indexName = $keyName = $tableIndex['key_name'];
843 542
            if ($tableIndex['primary']) {
844 456
                $keyName = 'primary';
845
            }
846 542
            $keyName = strtolower($keyName);
847
848 542
            if (! isset($result[$keyName])) {
849
                $options = [
850 542
                    'lengths' => [],
851
                ];
852
853 542
                if (isset($tableIndex['where'])) {
854 18
                    $options['where'] = $tableIndex['where'];
855
                }
856
857 542
                $result[$keyName] = [
858 542
                    'name' => $indexName,
859
                    'columns' => [],
860 542
                    'unique' => $tableIndex['non_unique'] ? false : true,
861 542
                    'primary' => $tableIndex['primary'],
862 542
                    'flags' => $tableIndex['flags'] ?? [],
863 542
                    'options' => $options,
864
                ];
865
            }
866
867 542
            $result[$keyName]['columns'][]            = $tableIndex['column_name'];
868 542
            $result[$keyName]['options']['lengths'][] = $tableIndex['length'] ?? null;
869
        }
870
871 951
        $eventManager = $this->_platform->getEventManager();
872
873 951
        $indexes = [];
874 951
        foreach ($result as $indexKey => $data) {
875 542
            $index            = null;
876 542
            $defaultPrevented = false;
877
878 542
            if ($eventManager !== null && $eventManager->hasListeners(Events::onSchemaIndexDefinition)) {
879 23
                $eventArgs = new SchemaIndexDefinitionEventArgs($data, $tableName, $this->_conn);
880 23
                $eventManager->dispatchEvent(Events::onSchemaIndexDefinition, $eventArgs);
881
882 23
                $defaultPrevented = $eventArgs->isDefaultPrevented();
883 23
                $index            = $eventArgs->getIndex();
884
            }
885
886 542
            if (! $defaultPrevented) {
887 542
                $index = new Index($data['name'], $data['columns'], $data['unique'], $data['primary'], $data['flags'], $data['options']);
888
            }
889
890 542
            if (! $index) {
891
                continue;
892
            }
893
894 542
            $indexes[$indexKey] = $index;
895
        }
896
897 951
        return $indexes;
898
    }
899
900
    /**
901
     * @param mixed[][] $tables
902
     *
903
     * @return string[]
904
     */
905 1761
    protected function _getPortableTablesList($tables)
906
    {
907 1761
        $list = [];
908 1761
        foreach ($tables as $value) {
909 1738
            $value = $this->_getPortableTableDefinition($value);
910
911 1738
            if (! $value) {
912
                continue;
913
            }
914
915 1738
            $list[] = $value;
916
        }
917
918 1761
        return $list;
919
    }
920
921
    /**
922
     * @param mixed $table
923
     *
924
     * @return string
925
     */
926
    protected function _getPortableTableDefinition($table)
927
    {
928
        return $table;
929
    }
930
931
    /**
932
     * @param mixed[][] $users
933
     *
934
     * @return string[][]
935
     */
936
    protected function _getPortableUsersList($users)
937
    {
938
        $list = [];
939
        foreach ($users as $value) {
940
            $value = $this->_getPortableUserDefinition($value);
941
942
            if (! $value) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $value of type array<mixed,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...
943
                continue;
944
            }
945
946
            $list[] = $value;
947
        }
948
949
        return $list;
950
    }
951
952
    /**
953
     * @param mixed[] $user
954
     *
955
     * @return mixed[]
956
     */
957
    protected function _getPortableUserDefinition($user)
958
    {
959
        return $user;
960
    }
961
962
    /**
963
     * @param mixed[][] $views
964
     *
965
     * @return View[]
966
     */
967 23
    protected function _getPortableViewsList($views)
968
    {
969 23
        $list = [];
970 23
        foreach ($views as $value) {
971 23
            $view = $this->_getPortableViewDefinition($value);
972
973 23
            if (! $view) {
974
                continue;
975
            }
976
977 23
            $viewName        = strtolower($view->getQuotedName($this->_platform));
978 23
            $list[$viewName] = $view;
979
        }
980
981 23
        return $list;
982
    }
983
984
    /**
985
     * @param mixed[] $view
986
     *
987
     * @return View|false
988
     */
989
    protected function _getPortableViewDefinition($view)
990
    {
991
        return false;
992
    }
993
994
    /**
995
     * @param mixed[][] $tableForeignKeys
996
     *
997
     * @return ForeignKeyConstraint[]
998
     */
999 340
    protected function _getPortableTableForeignKeysList($tableForeignKeys)
1000
    {
1001 340
        $list = [];
1002 340
        foreach ($tableForeignKeys as $value) {
1003 107
            $value = $this->_getPortableTableForeignKeyDefinition($value);
1004
1005 107
            if (! $value) {
1006
                continue;
1007
            }
1008
1009 107
            $list[] = $value;
1010
        }
1011
1012 340
        return $list;
1013
    }
1014
1015
    /**
1016
     * @param mixed $tableForeignKey
1017
     *
1018
     * @return ForeignKeyConstraint
1019
     */
1020
    protected function _getPortableTableForeignKeyDefinition($tableForeignKey)
1021
    {
1022
        return $tableForeignKey;
1023
    }
1024
1025
    /**
1026
     * @param string[]|string $sql
1027
     *
1028
     * @return void
1029
     */
1030 3715
    protected function _execSql($sql)
1031
    {
1032 3715
        foreach ((array) $sql as $query) {
1033 3715
            $this->_conn->executeUpdate($query);
1034
        }
1035 2631
    }
1036
1037
    /**
1038
     * Creates a schema instance for the current database.
1039
     *
1040
     * @return Schema
1041
     */
1042 92
    public function createSchema()
1043
    {
1044 92
        $namespaces = [];
1045
1046 92
        if ($this->_platform->supportsSchemas()) {
1047 8
            $namespaces = $this->listNamespaceNames();
1048
        }
1049
1050 92
        $sequences = [];
1051
1052 92
        if ($this->_platform->supportsSequences()) {
1053 9
            $sequences = $this->listSequences();
1054
        }
1055
1056 92
        $tables = $this->listTables();
1057
1058 92
        return new Schema($tables, $sequences, $this->createSchemaConfig(), $namespaces);
1059
    }
1060
1061
    /**
1062
     * Creates the configuration for this schema.
1063
     *
1064
     * @return SchemaConfig
1065
     */
1066 402
    public function createSchemaConfig()
1067
    {
1068 402
        $schemaConfig = new SchemaConfig();
1069 402
        $schemaConfig->setMaxIdentifierLength($this->_platform->getMaxIdentifierLength());
1070
1071 402
        $searchPaths = $this->getSchemaSearchPaths();
1072 402
        if (isset($searchPaths[0])) {
1073 300
            $schemaConfig->setName($searchPaths[0]);
1074
        }
1075
1076 402
        $params = $this->_conn->getParams();
1077 402
        if (! isset($params['defaultTableOptions'])) {
1078 402
            $params['defaultTableOptions'] = [];
1079
        }
1080 402
        if (! isset($params['defaultTableOptions']['charset']) && isset($params['charset'])) {
1081 23
            $params['defaultTableOptions']['charset'] = $params['charset'];
1082
        }
1083 402
        $schemaConfig->setDefaultTableOptions($params['defaultTableOptions']);
1084
1085 402
        return $schemaConfig;
1086
    }
1087
1088
    /**
1089
     * The search path for namespaces in the currently connected database.
1090
     *
1091
     * The first entry is usually the default namespace in the Schema. All
1092
     * further namespaces contain tables/sequences which can also be addressed
1093
     * with a short, not full-qualified name.
1094
     *
1095
     * For databases that don't support subschema/namespaces this method
1096
     * returns the name of the currently connected database.
1097
     *
1098
     * @return string[]
1099
     */
1100 312
    public function getSchemaSearchPaths()
1101
    {
1102 312
        return [$this->_conn->getDatabase()];
1103
    }
1104
1105
    /**
1106
     * Given a table comment this method tries to extract a typehint for Doctrine Type, or returns
1107
     * the type given as default.
1108
     *
1109
     * @param string $comment
1110
     * @param string $currentType
1111
     *
1112
     * @return string
1113
     */
1114 1232
    public function extractDoctrineTypeFromComment($comment, $currentType)
1115
    {
1116 1232
        if (preg_match('(\(DC2Type:(((?!\)).)+)\))', $comment, $match)) {
1117 269
            $currentType = $match[1];
1118
        }
1119
1120 1232
        return $currentType;
1121
    }
1122
1123
    /**
1124
     * @param string $comment
1125
     * @param string $type
1126
     *
1127
     * @return string
1128
     */
1129 1082
    public function removeDoctrineTypeFromComment($comment, $type)
1130
    {
1131 1082
        return str_replace('(DC2Type:' . $type . ')', '', $comment);
1132
    }
1133
}
1134