Total Complexity | 100 |
Total Lines | 590 |
Duplicated Lines | 29.83 % |
Coverage | 0% |
Changes | 0 |
Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
Complex classes like DrizzlePlatform 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 DrizzlePlatform, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
33 | class DrizzlePlatform extends AbstractPlatform |
||
34 | { |
||
35 | /** |
||
36 | * {@inheritDoc} |
||
37 | */ |
||
38 | public function getName() |
||
39 | { |
||
40 | return 'drizzle'; |
||
41 | } |
||
42 | |||
43 | /** |
||
44 | * {@inheritDoc} |
||
45 | */ |
||
46 | public function getIdentifierQuoteCharacter() |
||
47 | { |
||
48 | return '`'; |
||
49 | } |
||
50 | |||
51 | /** |
||
52 | * {@inheritDoc} |
||
53 | */ |
||
54 | public function getConcatExpression() |
||
55 | { |
||
56 | $args = func_get_args(); |
||
57 | |||
58 | return 'CONCAT(' . join(', ', (array) $args) . ')'; |
||
59 | } |
||
60 | |||
61 | /** |
||
62 | * {@inheritdoc} |
||
63 | */ |
||
64 | protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) |
||
65 | { |
||
66 | $function = '+' === $operator ? 'DATE_ADD' : 'DATE_SUB'; |
||
67 | |||
68 | return $function . '(' . $date . ', INTERVAL ' . $interval . ' ' . $unit . ')'; |
||
69 | } |
||
70 | |||
71 | /** |
||
72 | * {@inheritDoc} |
||
73 | */ |
||
74 | public function getDateDiffExpression($date1, $date2) |
||
75 | { |
||
76 | return 'DATEDIFF(' . $date1 . ', ' . $date2 . ')'; |
||
77 | } |
||
78 | |||
79 | /** |
||
80 | * {@inheritDoc} |
||
81 | */ |
||
82 | public function getBooleanTypeDeclarationSQL(array $field) |
||
83 | { |
||
84 | return 'BOOLEAN'; |
||
85 | } |
||
86 | |||
87 | /** |
||
88 | * {@inheritDoc} |
||
89 | */ |
||
90 | public function getIntegerTypeDeclarationSQL(array $field) |
||
91 | { |
||
92 | return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); |
||
93 | } |
||
94 | |||
95 | /** |
||
96 | * {@inheritDoc} |
||
97 | */ |
||
98 | protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) |
||
99 | { |
||
100 | $autoinc = ''; |
||
101 | if ( ! empty($columnDef['autoincrement'])) { |
||
102 | $autoinc = ' AUTO_INCREMENT'; |
||
103 | } |
||
104 | |||
105 | return $autoinc; |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * {@inheritDoc} |
||
110 | */ |
||
111 | public function getBigIntTypeDeclarationSQL(array $field) |
||
112 | { |
||
113 | return 'BIGINT' . $this->_getCommonIntegerTypeDeclarationSQL($field); |
||
114 | } |
||
115 | |||
116 | /** |
||
117 | * {@inheritDoc} |
||
118 | */ |
||
119 | public function getSmallIntTypeDeclarationSQL(array $field) |
||
120 | { |
||
121 | return 'INT' . $this->_getCommonIntegerTypeDeclarationSQL($field); |
||
122 | } |
||
123 | |||
124 | /** |
||
125 | * {@inheritDoc} |
||
126 | */ |
||
127 | protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) |
||
128 | { |
||
129 | return $length ? 'VARCHAR(' . $length . ')' : 'VARCHAR(255)'; |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * {@inheritdoc} |
||
134 | */ |
||
135 | protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) |
||
136 | { |
||
137 | return 'VARBINARY(' . ($length ?: 255) . ')'; |
||
138 | } |
||
139 | |||
140 | /** |
||
141 | * {@inheritDoc} |
||
142 | */ |
||
143 | protected function initializeDoctrineTypeMappings() |
||
144 | { |
||
145 | $this->doctrineTypeMapping = [ |
||
146 | 'boolean' => 'boolean', |
||
147 | 'varchar' => 'string', |
||
148 | 'varbinary' => 'binary', |
||
149 | 'integer' => 'integer', |
||
150 | 'blob' => 'blob', |
||
151 | 'decimal' => 'decimal', |
||
152 | 'datetime' => 'datetime', |
||
153 | 'date' => 'date', |
||
154 | 'time' => 'time', |
||
155 | 'text' => 'text', |
||
156 | 'timestamp' => 'datetime', |
||
157 | 'double' => 'float', |
||
158 | 'bigint' => 'bigint', |
||
159 | ]; |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * {@inheritDoc} |
||
164 | */ |
||
165 | public function getClobTypeDeclarationSQL(array $field) |
||
166 | { |
||
167 | return 'TEXT'; |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * {@inheritDoc} |
||
172 | */ |
||
173 | public function getBlobTypeDeclarationSQL(array $field) |
||
174 | { |
||
175 | return 'BLOB'; |
||
176 | } |
||
177 | |||
178 | /** |
||
179 | * {@inheritDoc} |
||
180 | */ |
||
181 | public function getCreateDatabaseSQL($name) |
||
182 | { |
||
183 | return 'CREATE DATABASE ' . $name; |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * {@inheritDoc} |
||
188 | */ |
||
189 | public function getDropDatabaseSQL($name) |
||
190 | { |
||
191 | return 'DROP DATABASE ' . $name; |
||
192 | } |
||
193 | |||
194 | /** |
||
195 | * {@inheritDoc} |
||
196 | */ |
||
197 | protected function _getCreateTableSQL($tableName, array $columns, array $options = []) |
||
198 | { |
||
199 | $queryFields = $this->getColumnDeclarationListSQL($columns); |
||
200 | |||
201 | if (isset($options['uniqueConstraints']) && ! empty($options['uniqueConstraints'])) { |
||
202 | foreach ($options['uniqueConstraints'] as $index => $definition) { |
||
203 | $queryFields .= ', ' . $this->getUniqueConstraintDeclarationSQL($index, $definition); |
||
204 | } |
||
205 | } |
||
206 | |||
207 | // add all indexes |
||
208 | if (isset($options['indexes']) && ! empty($options['indexes'])) { |
||
209 | foreach ($options['indexes'] as $index => $definition) { |
||
210 | $queryFields .= ', ' . $this->getIndexDeclarationSQL($index, $definition); |
||
211 | } |
||
212 | } |
||
213 | |||
214 | // attach all primary keys |
||
215 | View Code Duplication | if (isset($options['primary']) && ! empty($options['primary'])) { |
|
|
|||
216 | $keyColumns = array_unique(array_values($options['primary'])); |
||
217 | $queryFields .= ', PRIMARY KEY(' . implode(', ', $keyColumns) . ')'; |
||
218 | } |
||
219 | |||
220 | $query = 'CREATE '; |
||
221 | |||
222 | if (!empty($options['temporary'])) { |
||
223 | $query .= 'TEMPORARY '; |
||
224 | } |
||
225 | |||
226 | $query .= 'TABLE ' . $tableName . ' (' . $queryFields . ') '; |
||
227 | $query .= $this->buildTableOptions($options); |
||
228 | $query .= $this->buildPartitionOptions($options); |
||
229 | |||
230 | $sql[] = $query; |
||
231 | |||
232 | View Code Duplication | if (isset($options['foreignKeys'])) { |
|
233 | foreach ((array) $options['foreignKeys'] as $definition) { |
||
234 | $sql[] = $this->getCreateForeignKeySQL($definition, $tableName); |
||
235 | } |
||
236 | } |
||
237 | |||
238 | return $sql; |
||
239 | } |
||
240 | |||
241 | /** |
||
242 | * Build SQL for table options |
||
243 | * |
||
244 | * @param array $options |
||
245 | * |
||
246 | * @return string |
||
247 | */ |
||
248 | private function buildTableOptions(array $options) |
||
249 | { |
||
250 | if (isset($options['table_options'])) { |
||
251 | return $options['table_options']; |
||
252 | } |
||
253 | |||
254 | $tableOptions = []; |
||
255 | |||
256 | // Collate |
||
257 | if ( ! isset($options['collate'])) { |
||
258 | $options['collate'] = 'utf8_unicode_ci'; |
||
259 | } |
||
260 | |||
261 | $tableOptions[] = sprintf('COLLATE %s', $options['collate']); |
||
262 | |||
263 | // Engine |
||
264 | if ( ! isset($options['engine'])) { |
||
265 | $options['engine'] = 'InnoDB'; |
||
266 | } |
||
267 | |||
268 | $tableOptions[] = sprintf('ENGINE = %s', $options['engine']); |
||
269 | |||
270 | // Auto increment |
||
271 | if (isset($options['auto_increment'])) { |
||
272 | $tableOptions[] = sprintf('AUTO_INCREMENT = %s', $options['auto_increment']); |
||
273 | } |
||
274 | |||
275 | // Comment |
||
276 | View Code Duplication | if (isset($options['comment'])) { |
|
277 | $comment = trim($options['comment'], " '"); |
||
278 | |||
279 | $tableOptions[] = sprintf("COMMENT = %s ", $this->quoteStringLiteral($comment)); |
||
280 | } |
||
281 | |||
282 | // Row format |
||
283 | if (isset($options['row_format'])) { |
||
284 | $tableOptions[] = sprintf('ROW_FORMAT = %s', $options['row_format']); |
||
285 | } |
||
286 | |||
287 | return implode(' ', $tableOptions); |
||
288 | } |
||
289 | |||
290 | /** |
||
291 | * Build SQL for partition options. |
||
292 | * |
||
293 | * @param array $options |
||
294 | * |
||
295 | * @return string |
||
296 | */ |
||
297 | private function buildPartitionOptions(array $options) |
||
298 | { |
||
299 | return (isset($options['partition_options'])) |
||
300 | ? ' ' . $options['partition_options'] |
||
301 | : ''; |
||
302 | } |
||
303 | |||
304 | /** |
||
305 | * {@inheritDoc} |
||
306 | */ |
||
307 | public function getListDatabasesSQL() |
||
308 | { |
||
309 | return "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.SCHEMATA WHERE CATALOG_NAME='LOCAL'"; |
||
310 | } |
||
311 | |||
312 | /** |
||
313 | * {@inheritDoc} |
||
314 | */ |
||
315 | protected function getReservedKeywordsClass() |
||
316 | { |
||
317 | return Keywords\DrizzleKeywords::class; |
||
318 | } |
||
319 | |||
320 | /** |
||
321 | * {@inheritDoc} |
||
322 | */ |
||
323 | public function getListTablesSQL() |
||
324 | { |
||
325 | return "SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE='BASE' AND TABLE_SCHEMA=DATABASE()"; |
||
326 | } |
||
327 | |||
328 | /** |
||
329 | * {@inheritDoc} |
||
330 | */ |
||
331 | View Code Duplication | public function getListTableColumnsSQL($table, $database = null) |
|
343 | } |
||
344 | |||
345 | /** |
||
346 | * {@inheritDoc} |
||
347 | */ |
||
348 | View Code Duplication | public function getListTableForeignKeysSQL($table, $database = null) |
|
349 | { |
||
350 | if ($database) { |
||
351 | $database = "'" . $database . "'"; |
||
352 | } else { |
||
353 | $database = 'DATABASE()'; |
||
354 | } |
||
355 | |||
356 | return "SELECT CONSTRAINT_NAME, CONSTRAINT_COLUMNS, REFERENCED_TABLE_NAME, REFERENCED_TABLE_COLUMNS, UPDATE_RULE, DELETE_RULE" . |
||
357 | " FROM DATA_DICTIONARY.FOREIGN_KEYS" . |
||
358 | " WHERE CONSTRAINT_SCHEMA=" . $database . " AND CONSTRAINT_TABLE='" . $table . "'"; |
||
359 | } |
||
360 | |||
361 | /** |
||
362 | * {@inheritDoc} |
||
363 | */ |
||
364 | View Code Duplication | public function getListTableIndexesSQL($table, $database = null) |
|
365 | { |
||
366 | if ($database) { |
||
367 | $database = "'" . $database . "'"; |
||
368 | } else { |
||
369 | $database = 'DATABASE()'; |
||
370 | } |
||
371 | |||
372 | return "SELECT INDEX_NAME AS 'key_name', COLUMN_NAME AS 'column_name', IS_USED_IN_PRIMARY AS 'primary', IS_UNIQUE=0 AS 'non_unique'" . |
||
373 | " FROM DATA_DICTIONARY.INDEX_PARTS" . |
||
374 | " WHERE TABLE_SCHEMA=" . $database . " AND TABLE_NAME='" . $table . "'"; |
||
375 | } |
||
376 | |||
377 | /** |
||
378 | * {@inheritDoc} |
||
379 | */ |
||
380 | public function prefersIdentityColumns() |
||
381 | { |
||
382 | return true; |
||
383 | } |
||
384 | |||
385 | /** |
||
386 | * {@inheritDoc} |
||
387 | */ |
||
388 | public function supportsIdentityColumns() |
||
389 | { |
||
390 | return true; |
||
391 | } |
||
392 | |||
393 | /** |
||
394 | * {@inheritDoc} |
||
395 | */ |
||
396 | public function supportsInlineColumnComments() |
||
397 | { |
||
398 | return true; |
||
399 | } |
||
400 | |||
401 | /** |
||
402 | * {@inheritDoc} |
||
403 | */ |
||
404 | public function supportsViews() |
||
405 | { |
||
406 | return false; |
||
407 | } |
||
408 | |||
409 | /** |
||
410 | * {@inheritdoc} |
||
411 | */ |
||
412 | public function supportsColumnCollation() |
||
413 | { |
||
414 | return true; |
||
415 | } |
||
416 | |||
417 | /** |
||
418 | * {@inheritDoc} |
||
419 | */ |
||
420 | View Code Duplication | public function getDropIndexSQL($index, $table=null) |
|
421 | { |
||
422 | if ($index instanceof Index) { |
||
423 | $indexName = $index->getQuotedName($this); |
||
424 | } elseif (is_string($index)) { |
||
425 | $indexName = $index; |
||
426 | } else { |
||
427 | throw new \InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $index parameter to be string or \Doctrine\DBAL\Schema\Index.'); |
||
428 | } |
||
429 | |||
430 | if ($table instanceof Table) { |
||
431 | $table = $table->getQuotedName($this); |
||
432 | } elseif (!is_string($table)) { |
||
433 | throw new \InvalidArgumentException('DrizzlePlatform::getDropIndexSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); |
||
434 | } |
||
435 | |||
436 | if ($index instanceof Index && $index->isPrimary()) { |
||
437 | // drizzle primary keys are always named "PRIMARY", |
||
438 | // so we cannot use them in statements because of them being keyword. |
||
439 | return $this->getDropPrimaryKeySQL($table); |
||
440 | } |
||
441 | |||
442 | return 'DROP INDEX ' . $indexName . ' ON ' . $table; |
||
443 | } |
||
444 | |||
445 | /** |
||
446 | * {@inheritDoc} |
||
447 | */ |
||
448 | protected function getDropPrimaryKeySQL($table) |
||
449 | { |
||
450 | return 'ALTER TABLE ' . $table . ' DROP PRIMARY KEY'; |
||
451 | } |
||
452 | |||
453 | /** |
||
454 | * {@inheritDoc} |
||
455 | */ |
||
456 | View Code Duplication | public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) |
|
463 | } |
||
464 | |||
465 | /** |
||
466 | * {@inheritDoc} |
||
467 | */ |
||
468 | public function getTimeTypeDeclarationSQL(array $fieldDeclaration) |
||
469 | { |
||
470 | return 'TIME'; |
||
471 | } |
||
472 | |||
473 | /** |
||
474 | * {@inheritDoc} |
||
475 | */ |
||
476 | public function getDateTypeDeclarationSQL(array $fieldDeclaration) |
||
477 | { |
||
478 | return 'DATE'; |
||
479 | } |
||
480 | |||
481 | /** |
||
482 | * {@inheritDoc} |
||
483 | */ |
||
484 | public function getAlterTableSQL(TableDiff $diff) |
||
485 | { |
||
486 | $columnSql = []; |
||
487 | $queryParts = []; |
||
488 | |||
489 | if ($diff->newName !== false) { |
||
490 | $queryParts[] = 'RENAME TO ' . $diff->getNewName()->getQuotedName($this); |
||
491 | } |
||
492 | |||
493 | View Code Duplication | foreach ($diff->addedColumns as $column) { |
|
494 | if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { |
||
495 | continue; |
||
496 | } |
||
497 | |||
498 | $columnArray = $column->toArray(); |
||
499 | $columnArray['comment'] = $this->getColumnComment($column); |
||
500 | $queryParts[] = 'ADD ' . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); |
||
501 | } |
||
502 | |||
503 | View Code Duplication | foreach ($diff->removedColumns as $column) { |
|
504 | if ($this->onSchemaAlterTableRemoveColumn($column, $diff, $columnSql)) { |
||
505 | continue; |
||
506 | } |
||
507 | |||
508 | $queryParts[] = 'DROP ' . $column->getQuotedName($this); |
||
509 | } |
||
510 | |||
511 | View Code Duplication | foreach ($diff->changedColumns as $columnDiff) { |
|
512 | if ($this->onSchemaAlterTableChangeColumn($columnDiff, $diff, $columnSql)) { |
||
513 | continue; |
||
514 | } |
||
515 | |||
516 | /* @var $columnDiff \Doctrine\DBAL\Schema\ColumnDiff */ |
||
517 | $column = $columnDiff->column; |
||
518 | $columnArray = $column->toArray(); |
||
519 | |||
520 | // Do not generate column alteration clause if type is binary and only fixed property has changed. |
||
521 | // Drizzle only supports binary type columns with variable length. |
||
522 | // Avoids unnecessary table alteration statements. |
||
523 | if ($columnArray['type'] instanceof BinaryType && |
||
524 | $columnDiff->hasChanged('fixed') && |
||
525 | count($columnDiff->changedProperties) === 1 |
||
526 | ) { |
||
527 | continue; |
||
528 | } |
||
529 | |||
530 | $columnArray['comment'] = $this->getColumnComment($column); |
||
531 | $queryParts[] = 'CHANGE ' . ($columnDiff->getOldColumnName()->getQuotedName($this)) . ' ' |
||
532 | . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); |
||
533 | } |
||
534 | |||
535 | View Code Duplication | foreach ($diff->renamedColumns as $oldColumnName => $column) { |
|
536 | if ($this->onSchemaAlterTableRenameColumn($oldColumnName, $column, $diff, $columnSql)) { |
||
537 | continue; |
||
538 | } |
||
539 | |||
540 | $oldColumnName = new Identifier($oldColumnName); |
||
541 | |||
542 | $columnArray = $column->toArray(); |
||
543 | $columnArray['comment'] = $this->getColumnComment($column); |
||
544 | $queryParts[] = 'CHANGE ' . $oldColumnName->getQuotedName($this) . ' ' |
||
545 | . $this->getColumnDeclarationSQL($column->getQuotedName($this), $columnArray); |
||
546 | } |
||
547 | |||
548 | $sql = []; |
||
549 | $tableSql = []; |
||
550 | |||
551 | View Code Duplication | if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { |
|
552 | if (count($queryParts) > 0) { |
||
553 | $sql[] = 'ALTER TABLE ' . $diff->getName($this)->getQuotedName($this) . ' ' . implode(", ", $queryParts); |
||
554 | } |
||
555 | $sql = array_merge( |
||
556 | $this->getPreAlterTableIndexForeignKeySQL($diff), |
||
557 | $sql, |
||
558 | $this->getPostAlterTableIndexForeignKeySQL($diff) |
||
559 | ); |
||
560 | } |
||
561 | |||
562 | return array_merge($sql, $tableSql, $columnSql); |
||
563 | } |
||
564 | |||
565 | /** |
||
566 | * {@inheritDoc} |
||
567 | */ |
||
568 | View Code Duplication | public function getDropTemporaryTableSQL($table) |
|
569 | { |
||
570 | if ($table instanceof Table) { |
||
571 | $table = $table->getQuotedName($this); |
||
572 | } elseif (!is_string($table)) { |
||
573 | throw new \InvalidArgumentException('getDropTableSQL() expects $table parameter to be string or \Doctrine\DBAL\Schema\Table.'); |
||
574 | } |
||
575 | |||
576 | return 'DROP TEMPORARY TABLE ' . $table; |
||
577 | } |
||
578 | |||
579 | /** |
||
580 | * {@inheritDoc} |
||
581 | */ |
||
582 | View Code Duplication | public function convertBooleans($item) |
|
595 | } |
||
596 | |||
597 | /** |
||
598 | * {@inheritDoc} |
||
599 | */ |
||
600 | View Code Duplication | public function getLocateExpression($str, $substr, $startPos = false) |
|
601 | { |
||
602 | if ($startPos == false) { |
||
603 | return 'LOCATE(' . $substr . ', ' . $str . ')'; |
||
604 | } |
||
605 | |||
606 | return 'LOCATE(' . $substr . ', ' . $str . ', '.$startPos.')'; |
||
607 | } |
||
608 | |||
609 | /** |
||
610 | * {@inheritDoc} |
||
611 | */ |
||
612 | public function getGuidExpression() |
||
615 | } |
||
616 | |||
617 | /** |
||
618 | * {@inheritDoc} |
||
619 | */ |
||
620 | public function getRegexpExpression() |
||
621 | { |
||
622 | return 'RLIKE'; |
||
623 | } |
||
624 | } |
||
625 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.