Passed
Push — 2.9 ( d389f3...7345cd )
by Sergei
31:44 queued 28:51
created

AbstractSchemaManager   F

Complexity

Total Complexity 117

Size/Duplication

Total Lines 1100
Duplicated Lines 0 %

Test Coverage

Coverage 77.45%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 117
eloc 252
c 1
b 0
f 0
dl 0
loc 1100
ccs 261
cts 337
cp 0.7745
rs 2

65 Methods

Rating   Name   Duplication   Size   Complexity  
A dropTable() 0 3 1
A getPortableNamespaceDefinition() 0 3 1
A __construct() 0 4 2
A getDatabasePlatform() 0 3 1
A listNamespaceNames() 0 7 1
A listSequences() 0 10 2
A listDatabases() 0 7 1
A tryMethod() 0 11 2
A listTableColumns() 0 11 2
A tablesExist() 0 5 1
A listTableIndexes() 0 7 1
A listTableNames() 0 8 1
A filterAssetNames() 0 8 2
A createDatabase() 0 3 1
A dropAndCreateSequence() 0 4 1
A dropAndCreateConstraint() 0 4 1
A createSequence() 0 3 1
A dropIndex() 0 7 2
A dropDatabase() 0 3 1
A dropAndCreateTable() 0 4 1
A alterTable() 0 9 4
A createForeignKey() 0 3 1
A dropConstraint() 0 3 1
A dropAndCreateDatabase() 0 4 1
A createTable() 0 4 1
A createIndex() 0 3 1
A dropAndCreateForeignKey() 0 4 1
A dropAndCreateIndex() 0 4 1
A dropForeignKey() 0 3 1
A dropAndCreateView() 0 4 1
A createView() 0 3 1
A _getPortableSequenceDefinition() 0 3 1
A _getPortableTriggerDefinition() 0 3 1
A _getPortableDatabasesList() 0 14 3
A _getPortableSequencesList() 0 14 3
A _getPortableFunctionDefinition() 0 3 1
A listTableDetails() 0 10 2
A _getPortableTableColumnList() 0 30 6
A _getPortableTriggersList() 0 14 3
A dropView() 0 3 1
A getFilterSchemaAssetsExpression() 0 3 1
A getPortableNamespacesList() 0 9 2
A _getPortableDatabaseDefinition() 0 3 1
A dropSequence() 0 3 1
A listTableForeignKeys() 0 9 2
A listViews() 0 7 1
A listTables() 0 10 2
A _getPortableFunctionsList() 0 14 3
A createSchema() 0 17 3
A _getPortableUserDefinition() 0 3 1
A removeDoctrineTypeFromComment() 0 3 1
A _getPortableTableDefinition() 0 3 1
A _getPortableTableForeignKeyDefinition() 0 3 1
B _getPortableTableIndexesList() 0 60 11
A _getPortableTableForeignKeysList() 0 14 3
A _getPortableTablesList() 0 14 3
A _getPortableViewDefinition() 0 3 1
A _execSql() 0 4 2
A createSchemaConfig() 0 20 5
A getSchemaSearchPaths() 0 3 1
A _getPortableViewsList() 0 15 3
A extractDoctrineTypeFromComment() 0 7 2
A _getPortableUsersList() 0 14 3
A renameTable() 0 5 1
A createConstraint() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like AbstractSchemaManager often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use AbstractSchemaManager, and based on these observations, apply Extract Interface, too.

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 2149
    public function __construct(Connection $conn, ?AbstractPlatform $platform = null)
49
    {
50 2149
        $this->_conn     = $conn;
51 2149
        $this->_platform = $platform ?: $this->_conn->getDatabasePlatform();
52 2149
    }
53
54
    /**
55
     * Returns the associated platform.
56
     *
57
     * @return AbstractPlatform
58
     */
59 619
    public function getDatabasePlatform()
60
    {
61 619
        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 3128
    public function tryMethod()
77
    {
78 3128
        $args   = func_get_args();
79 3128
        $method = $args[0];
80 3128
        unset($args[0]);
81 3128
        $args = array_values($args);
82
83
        try {
84 3128
            return call_user_func_array([$this, $method], $args);
85 2277
        } catch (Throwable $e) {
86 2277
            return false;
87
        }
88
    }
89
90
    /**
91
     * Lists the available databases for this connection.
92
     *
93
     * @return string[]
94
     */
95 57
    public function listDatabases()
96
    {
97 57
        $sql = $this->_platform->getListDatabasesSQL();
98
99 56
        $databases = $this->_conn->fetchAll($sql);
100
101 56
        return $this->_getPortableDatabasesList($databases);
102
    }
103
104
    /**
105
     * Returns a list of all namespaces in the current database.
106
     *
107
     * @return string[]
108
     */
109 18
    public function listNamespaceNames()
110
    {
111 18
        $sql = $this->_platform->getListNamespacesSQL();
112
113 18
        $namespaces = $this->_conn->fetchAll($sql);
114
115 18
        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 54
    public function listSequences($database = null)
126
    {
127 54
        if ($database === null) {
128 54
            $database = $this->_conn->getDatabase();
129
        }
130 54
        $sql = $this->_platform->getListSequencesSQL($database);
131
132 54
        $sequences = $this->_conn->fetchAll($sql);
133
134 54
        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 1580
    public function listTableColumns($table, $database = null)
153
    {
154 1580
        if (! $database) {
155 1580
            $database = $this->_conn->getDatabase();
156
        }
157
158 1580
        $sql = $this->_platform->getListTableColumnsSQL($table, $database);
159
160 1580
        $tableColumns = $this->_conn->fetchAll($sql);
161
162 1580
        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 1278
    public function listTableIndexes($table)
175
    {
176 1278
        $sql = $this->_platform->getListTableIndexesSQL($table, $this->_conn->getDatabase());
177
178 1278
        $tableIndexes = $this->_conn->fetchAll($sql);
179
180 1278
        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 2337
    public function tablesExist($tableNames)
191
    {
192 2337
        $tableNames = array_map('strtolower', (array) $tableNames);
193
194 2337
        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 2374
    public function listTableNames()
203
    {
204 2374
        $sql = $this->_platform->getListTablesSQL();
205
206 2374
        $tables     = $this->_conn->fetchAll($sql);
207 2374
        $tableNames = $this->_getPortableTablesList($tables);
208
209 2374
        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 2436
    protected function filterAssetNames($assetNames)
221
    {
222 2436
        $filter = $this->_conn->getConfiguration()->getSchemaAssetsFilter();
223 2436
        if (! $filter) {
224 2436
            return $assetNames;
225
        }
226
227 7
        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 157
    public function listTables()
246
    {
247 157
        $tableNames = $this->listTableNames();
248
249 157
        $tables = [];
250 157
        foreach ($tableNames as $tableName) {
251 127
            $tables[] = $this->listTableDetails($tableName);
252
        }
253
254 157
        return $tables;
255
    }
256
257
    /**
258
     * @param string $tableName
259
     *
260
     * @return Table
261
     */
262 1150
    public function listTableDetails($tableName)
263
    {
264 1150
        $columns     = $this->listTableColumns($tableName);
265 1150
        $foreignKeys = [];
266 1150
        if ($this->_platform->supportsForeignKeyConstraints()) {
267 1061
            $foreignKeys = $this->listTableForeignKeys($tableName);
268
        }
269 1150
        $indexes = $this->listTableIndexes($tableName);
270
271 1150
        return new Table($tableName, $columns, $indexes, $foreignKeys, false, []);
272
    }
273
274
    /**
275
     * Lists the views this connection has.
276
     *
277
     * @return View[]
278
     */
279 30
    public function listViews()
280
    {
281 30
        $database = $this->_conn->getDatabase();
282 30
        $sql      = $this->_platform->getListViewsSQL($database);
283 30
        $views    = $this->_conn->fetchAll($sql);
284
285 30
        return $this->_getPortableViewsList($views);
286
    }
287
288
    /**
289
     * Lists the foreign keys for the given table.
290
     *
291
     * @param string      $table    The name of the table.
292
     * @param string|null $database
293
     *
294
     * @return ForeignKeyConstraint[]
295
     */
296 1158
    public function listTableForeignKeys($table, $database = null)
297
    {
298 1158
        if ($database === null) {
299 1158
            $database = $this->_conn->getDatabase();
300
        }
301 1158
        $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

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