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 SqlitePlatform 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
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 SqlitePlatform, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 42 | class SqlitePlatform extends AbstractPlatform |
||
| 43 | { |
||
| 44 | /** |
||
| 45 | * {@inheritDoc} |
||
| 46 | */ |
||
| 47 | 1 | public function getRegexpExpression() |
|
| 51 | |||
| 52 | /** |
||
| 53 | * {@inheritDoc} |
||
| 54 | */ |
||
| 55 | 2 | public function getGuidExpression() |
|
| 62 | |||
| 63 | /** |
||
| 64 | * {@inheritDoc} |
||
| 65 | */ |
||
| 66 | public function getNowExpression($type = 'timestamp') |
||
| 78 | |||
| 79 | /** |
||
| 80 | * {@inheritDoc} |
||
| 81 | */ |
||
| 82 | 36 | public function getTrimExpression($str, $pos = self::TRIM_UNSPECIFIED, $char = false) |
|
| 101 | |||
| 102 | /** |
||
| 103 | * {@inheritDoc} |
||
| 104 | * |
||
| 105 | * SQLite only supports the 2 parameter variant of this function |
||
| 106 | */ |
||
| 107 | 1 | View Code Duplication | public function getSubstringExpression($value, $position, $length = null) |
| 115 | |||
| 116 | /** |
||
| 117 | * {@inheritDoc} |
||
| 118 | */ |
||
| 119 | 1 | View Code Duplication | public function getLocateExpression($str, $substr, $startPos = false) |
| 127 | |||
| 128 | /** |
||
| 129 | * {@inheritdoc} |
||
| 130 | */ |
||
| 131 | 1 | protected function getDateArithmeticIntervalExpression($date, $operator, $interval, $unit) |
|
| 155 | |||
| 156 | /** |
||
| 157 | * {@inheritDoc} |
||
| 158 | */ |
||
| 159 | 1 | public function getDateDiffExpression($date1, $date2) |
|
| 163 | |||
| 164 | /** |
||
| 165 | * {@inheritDoc} |
||
| 166 | */ |
||
| 167 | 1 | View Code Duplication | protected function _getTransactionIsolationLevelSQL($level) |
| 180 | |||
| 181 | /** |
||
| 182 | * {@inheritDoc} |
||
| 183 | */ |
||
| 184 | 1 | public function getSetTransactionIsolationSQL($level) |
|
| 188 | |||
| 189 | /** |
||
| 190 | * {@inheritDoc} |
||
| 191 | */ |
||
| 192 | 2 | public function prefersIdentityColumns() |
|
| 196 | |||
| 197 | /** |
||
| 198 | * {@inheritDoc} |
||
| 199 | */ |
||
| 200 | 16 | public function getBooleanTypeDeclarationSQL(array $field) |
|
| 204 | |||
| 205 | /** |
||
| 206 | * {@inheritDoc} |
||
| 207 | */ |
||
| 208 | 144 | public function getIntegerTypeDeclarationSQL(array $field) |
|
| 212 | |||
| 213 | /** |
||
| 214 | * {@inheritDoc} |
||
| 215 | */ |
||
| 216 | 18 | View Code Duplication | public function getBigIntTypeDeclarationSQL(array $field) |
| 225 | |||
| 226 | /** |
||
| 227 | * {@inheritDoc} |
||
| 228 | */ |
||
| 229 | 2 | View Code Duplication | public function getTinyIntTypeDeclarationSql(array $field) |
| 238 | |||
| 239 | /** |
||
| 240 | * {@inheritDoc} |
||
| 241 | */ |
||
| 242 | 4 | View Code Duplication | public function getSmallIntTypeDeclarationSQL(array $field) |
| 251 | |||
| 252 | /** |
||
| 253 | * {@inheritDoc} |
||
| 254 | */ |
||
| 255 | 1 | View Code Duplication | public function getMediumIntTypeDeclarationSql(array $field) |
| 264 | |||
| 265 | /** |
||
| 266 | * {@inheritDoc} |
||
| 267 | */ |
||
| 268 | 19 | public function getDateTimeTypeDeclarationSQL(array $fieldDeclaration) |
|
| 272 | |||
| 273 | /** |
||
| 274 | * {@inheritDoc} |
||
| 275 | */ |
||
| 276 | 18 | public function getDateTypeDeclarationSQL(array $fieldDeclaration) |
|
| 280 | |||
| 281 | /** |
||
| 282 | * {@inheritDoc} |
||
| 283 | */ |
||
| 284 | 18 | public function getTimeTypeDeclarationSQL(array $fieldDeclaration) |
|
| 288 | |||
| 289 | /** |
||
| 290 | * {@inheritDoc} |
||
| 291 | */ |
||
| 292 | 144 | protected function _getCommonIntegerTypeDeclarationSQL(array $columnDef) |
|
| 301 | |||
| 302 | /** |
||
| 303 | * {@inheritDoc} |
||
| 304 | */ |
||
| 305 | 6 | public function getForeignKeyDeclarationSQL(ForeignKeyConstraint $foreignKey) |
|
| 315 | |||
| 316 | /** |
||
| 317 | * {@inheritDoc} |
||
| 318 | */ |
||
| 319 | 147 | protected function _getCreateTableSQL($name, array $columns, array $options = []) |
|
| 361 | |||
| 362 | /** |
||
| 363 | * {@inheritDoc} |
||
| 364 | */ |
||
| 365 | 80 | protected function getVarcharTypeDeclarationSQLSnippet($length, $fixed) |
|
| 370 | |||
| 371 | /** |
||
| 372 | * {@inheritdoc} |
||
| 373 | */ |
||
| 374 | 2 | protected function getBinaryTypeDeclarationSQLSnippet($length, $fixed) |
|
| 378 | |||
| 379 | /** |
||
| 380 | * {@inheritdoc} |
||
| 381 | */ |
||
| 382 | 6 | public function getBinaryMaxLength() |
|
| 386 | |||
| 387 | /** |
||
| 388 | * {@inheritdoc} |
||
| 389 | */ |
||
| 390 | 3 | public function getBinaryDefaultLength() |
|
| 394 | |||
| 395 | /** |
||
| 396 | * {@inheritDoc} |
||
| 397 | */ |
||
| 398 | 43 | public function getClobTypeDeclarationSQL(array $field) |
|
| 402 | |||
| 403 | /** |
||
| 404 | * {@inheritDoc} |
||
| 405 | */ |
||
| 406 | 1 | public function getListTableConstraintsSQL($table) |
|
| 413 | |||
| 414 | /** |
||
| 415 | * {@inheritDoc} |
||
| 416 | */ |
||
| 417 | 39 | View Code Duplication | public function getListTableColumnsSQL($table, $currentDatabase = null) |
| 424 | |||
| 425 | /** |
||
| 426 | * {@inheritDoc} |
||
| 427 | */ |
||
| 428 | 32 | View Code Duplication | public function getListTableIndexesSQL($table, $currentDatabase = null) |
| 435 | |||
| 436 | /** |
||
| 437 | * {@inheritDoc} |
||
| 438 | */ |
||
| 439 | 14 | public function getListTablesSQL() |
|
| 445 | |||
| 446 | /** |
||
| 447 | * {@inheritDoc} |
||
| 448 | */ |
||
| 449 | 1 | public function getListViewsSQL($database) |
|
| 453 | |||
| 454 | /** |
||
| 455 | * {@inheritDoc} |
||
| 456 | */ |
||
| 457 | 1 | public function getCreateViewSQL($name, $sql) |
|
| 461 | |||
| 462 | /** |
||
| 463 | * {@inheritDoc} |
||
| 464 | */ |
||
| 465 | 1 | public function getDropViewSQL($name) |
|
| 469 | |||
| 470 | /** |
||
| 471 | * {@inheritDoc} |
||
| 472 | */ |
||
| 473 | 6 | public function getAdvancedForeignKeyOptionsSQL(ForeignKeyConstraint $foreignKey) |
|
| 482 | |||
| 483 | /** |
||
| 484 | * {@inheritDoc} |
||
| 485 | */ |
||
| 486 | 3 | public function supportsIdentityColumns() |
|
| 490 | |||
| 491 | /** |
||
| 492 | * {@inheritDoc} |
||
| 493 | */ |
||
| 494 | 1 | public function supportsColumnCollation() |
|
| 498 | |||
| 499 | /** |
||
| 500 | * {@inheritDoc} |
||
| 501 | */ |
||
| 502 | 151 | public function supportsInlineColumnComments() |
|
| 506 | |||
| 507 | /** |
||
| 508 | * {@inheritDoc} |
||
| 509 | */ |
||
| 510 | 62 | public function getName() |
|
| 514 | |||
| 515 | /** |
||
| 516 | * {@inheritDoc} |
||
| 517 | */ |
||
| 518 | 12 | public function getTruncateTableSQL($tableName, $cascade = false) |
|
| 525 | |||
| 526 | /** |
||
| 527 | * User-defined function for Sqlite that is used with PDO::sqliteCreateFunction(). |
||
| 528 | * |
||
| 529 | * @param integer|float $value |
||
| 530 | * |
||
| 531 | * @return float |
||
| 532 | */ |
||
| 533 | public static function udfSqrt($value) |
||
| 537 | |||
| 538 | /** |
||
| 539 | * User-defined function for Sqlite that implements MOD(a, b). |
||
| 540 | * |
||
| 541 | * @param integer $a |
||
| 542 | * @param integer $b |
||
| 543 | * |
||
| 544 | * @return integer |
||
| 545 | */ |
||
| 546 | public static function udfMod($a, $b) |
||
| 550 | |||
| 551 | /** |
||
| 552 | * @param string $str |
||
| 553 | * @param string $substr |
||
| 554 | * @param integer $offset |
||
| 555 | * |
||
| 556 | * @return integer |
||
| 557 | */ |
||
| 558 | 1 | public static function udfLocate($str, $substr, $offset = 0) |
|
| 574 | |||
| 575 | /** |
||
| 576 | * {@inheritDoc} |
||
| 577 | */ |
||
| 578 | public function getForUpdateSql() |
||
| 582 | |||
| 583 | /** |
||
| 584 | * {@inheritDoc} |
||
| 585 | */ |
||
| 586 | 36 | public function getInlineColumnCommentSQL($comment) |
|
| 590 | |||
| 591 | /** |
||
| 592 | * {@inheritDoc} |
||
| 593 | */ |
||
| 594 | 7 | protected function initializeDoctrineTypeMappings() |
|
| 631 | |||
| 632 | /** |
||
| 633 | * {@inheritDoc} |
||
| 634 | */ |
||
| 635 | 49 | protected function getReservedKeywordsClass() |
|
| 639 | |||
| 640 | /** |
||
| 641 | * {@inheritDoc} |
||
| 642 | */ |
||
| 643 | 25 | protected function getPreAlterTableIndexForeignKeySQL(TableDiff $diff) |
|
| 658 | |||
| 659 | /** |
||
| 660 | * {@inheritDoc} |
||
| 661 | */ |
||
| 662 | 25 | protected function getPostAlterTableIndexForeignKeySQL(TableDiff $diff) |
|
| 680 | |||
| 681 | /** |
||
| 682 | * {@inheritDoc} |
||
| 683 | */ |
||
| 684 | 11 | protected function doModifyLimitQuery($query, $limit, $offset) |
|
| 692 | |||
| 693 | /** |
||
| 694 | * {@inheritDoc} |
||
| 695 | */ |
||
| 696 | 6 | public function getBlobTypeDeclarationSQL(array $field) |
|
| 700 | |||
| 701 | /** |
||
| 702 | * {@inheritDoc} |
||
| 703 | */ |
||
| 704 | 2 | public function getTemporaryTableName($tableName) |
|
| 710 | |||
| 711 | /** |
||
| 712 | * {@inheritDoc} |
||
| 713 | * |
||
| 714 | * Sqlite Platform emulates schema by underscoring each dot and generating tables |
||
| 715 | * into the default database. |
||
| 716 | * |
||
| 717 | * This hack is implemented to be able to use SQLite as testdriver when |
||
| 718 | * using schema supporting databases. |
||
| 719 | */ |
||
| 720 | public function canEmulateSchemas() |
||
| 724 | |||
| 725 | /** |
||
| 726 | * {@inheritDoc} |
||
| 727 | */ |
||
| 728 | 34 | public function supportsForeignKeyConstraints() |
|
| 732 | |||
| 733 | /** |
||
| 734 | * {@inheritDoc} |
||
| 735 | */ |
||
| 736 | public function getCreatePrimaryKeySQL(Index $index, $table) |
||
| 740 | |||
| 741 | /** |
||
| 742 | * {@inheritdoc} |
||
| 743 | */ |
||
| 744 | 2 | public function getCreateForeignKeySQL(ForeignKeyConstraint $foreignKey, $table) |
|
| 748 | |||
| 749 | /** |
||
| 750 | * {@inheritdoc} |
||
| 751 | */ |
||
| 752 | public function getDropForeignKeySQL($foreignKey, $table) |
||
| 756 | |||
| 757 | /** |
||
| 758 | * {@inheritDoc} |
||
| 759 | */ |
||
| 760 | 1 | public function getCreateConstraintSQL(Constraint $constraint, $table) |
|
| 764 | |||
| 765 | /** |
||
| 766 | * {@inheritDoc} |
||
| 767 | */ |
||
| 768 | 148 | public function getCreateTableSQL(Table $table, $createFlags = null) |
|
| 774 | |||
| 775 | /** |
||
| 776 | * {@inheritDoc} |
||
| 777 | */ |
||
| 778 | 2 | View Code Duplication | public function getListTableForeignKeysSQL($table, $database = null) |
| 785 | |||
| 786 | /** |
||
| 787 | * {@inheritDoc} |
||
| 788 | */ |
||
| 789 | 33 | public function getAlterTableSQL(TableDiff $diff) |
|
| 895 | |||
| 896 | /** |
||
| 897 | * @param \Doctrine\DBAL\Schema\TableDiff $diff |
||
| 898 | * |
||
| 899 | * @return array|bool |
||
| 900 | */ |
||
| 901 | 33 | private function getSimpleAlterTableSQL(TableDiff $diff) |
|
| 902 | { |
||
| 903 | // Suppress changes on integer type autoincrement columns. |
||
| 904 | 33 | foreach ($diff->changedColumns as $oldColumnName => $columnDiff) { |
|
| 905 | 23 | if ( ! $columnDiff->fromColumn instanceof Column || |
|
| 906 | 19 | ! $columnDiff->column instanceof Column || |
|
| 907 | 19 | ! $columnDiff->column->getAutoincrement() || |
|
| 908 | 23 | ! $columnDiff->column->getType() instanceof Types\IntegerType |
|
| 909 | ) { |
||
| 910 | 18 | continue; |
|
| 911 | } |
||
| 912 | |||
| 913 | 5 | if ( ! $columnDiff->hasChanged('type') && $columnDiff->hasChanged('unsigned')) { |
|
| 914 | 1 | unset($diff->changedColumns[$oldColumnName]); |
|
| 915 | |||
| 916 | 1 | continue; |
|
| 917 | } |
||
| 918 | |||
| 919 | 4 | $fromColumnType = $columnDiff->fromColumn->getType(); |
|
| 920 | |||
| 921 | 4 | if ($fromColumnType instanceof Types\SmallIntType || $fromColumnType instanceof Types\BigIntType) { |
|
| 922 | 4 | unset($diff->changedColumns[$oldColumnName]); |
|
| 923 | } |
||
| 924 | } |
||
| 925 | |||
| 926 | 33 | if ( ! empty($diff->renamedColumns) || ! empty($diff->addedForeignKeys) || ! empty($diff->addedIndexes) |
|
| 927 | 28 | || ! empty($diff->changedColumns) || ! empty($diff->changedForeignKeys) || ! empty($diff->changedIndexes) |
|
| 928 | 12 | || ! empty($diff->removedColumns) || ! empty($diff->removedForeignKeys) || ! empty($diff->removedIndexes) |
|
| 929 | 33 | || ! empty($diff->renamedIndexes) |
|
| 930 | ) { |
||
| 931 | 25 | return false; |
|
| 932 | } |
||
| 933 | |||
| 934 | 8 | $table = new Table($diff->name); |
|
| 935 | |||
| 936 | 8 | $sql = []; |
|
| 937 | 8 | $tableSql = []; |
|
| 938 | 8 | $columnSql = []; |
|
| 939 | |||
| 940 | 8 | foreach ($diff->addedColumns as $column) { |
|
| 941 | 2 | if ($this->onSchemaAlterTableAddColumn($column, $diff, $columnSql)) { |
|
| 942 | continue; |
||
| 943 | } |
||
| 944 | |||
| 945 | 2 | $field = array_merge(['unique' => null, 'autoincrement' => null, 'default' => null], $column->toArray()); |
|
| 946 | 2 | $type = $field['type']; |
|
| 947 | switch (true) { |
||
| 948 | 2 | case isset($field['columnDefinition']) || $field['autoincrement'] || $field['unique']: |
|
| 949 | 2 | case $type instanceof Types\DateTimeType && $field['default'] == $this->getCurrentTimestampSQL(): |
|
| 950 | 2 | case $type instanceof Types\DateType && $field['default'] == $this->getCurrentDateSQL(): |
|
| 951 | 1 | case $type instanceof Types\TimeType && $field['default'] == $this->getCurrentTimeSQL(): |
|
| 952 | 1 | return false; |
|
| 953 | } |
||
| 954 | |||
| 955 | 1 | $field['name'] = $column->getQuotedName($this); |
|
| 956 | 1 | if ($type instanceof StringType && $field['length'] === null) { |
|
| 957 | $field['length'] = 255; |
||
| 958 | } |
||
| 959 | |||
| 960 | 1 | $sql[] = 'ALTER TABLE '.$table->getQuotedName($this).' ADD COLUMN '.$this->getColumnDeclarationSQL($field['name'], $field); |
|
| 961 | } |
||
| 962 | |||
| 963 | 7 | if ( ! $this->onSchemaAlterTable($diff, $tableSql)) { |
|
| 964 | 7 | if ($diff->newName !== false) { |
|
| 965 | 1 | $newTable = new Identifier($diff->newName); |
|
| 966 | 1 | $sql[] = 'ALTER TABLE '.$table->getQuotedName($this).' RENAME TO '.$newTable->getQuotedName($this); |
|
| 967 | } |
||
| 968 | } |
||
| 969 | |||
| 970 | 7 | return array_merge($sql, $tableSql, $columnSql); |
|
| 971 | } |
||
| 972 | |||
| 973 | /** |
||
| 974 | * @param \Doctrine\DBAL\Schema\TableDiff $diff |
||
| 975 | * |
||
| 976 | * @return array |
||
| 977 | */ |
||
| 978 | 25 | private function getColumnNamesInAlteredTable(TableDiff $diff) |
|
| 1011 | |||
| 1012 | /** |
||
| 1013 | * @param \Doctrine\DBAL\Schema\TableDiff $diff |
||
| 1014 | * |
||
| 1015 | * @return \Doctrine\DBAL\Schema\Index[] |
||
| 1016 | */ |
||
| 1017 | 25 | private function getIndexesInAlteredTable(TableDiff $diff) |
|
| 1067 | |||
| 1068 | /** |
||
| 1069 | * @param \Doctrine\DBAL\Schema\TableDiff $diff |
||
| 1070 | * |
||
| 1071 | * @return array |
||
| 1072 | */ |
||
| 1073 | 25 | private function getForeignKeysInAlteredTable(TableDiff $diff) |
|
| 1117 | |||
| 1118 | /** |
||
| 1119 | * @param \Doctrine\DBAL\Schema\TableDiff $diff |
||
| 1120 | * |
||
| 1121 | * @return array |
||
| 1122 | */ |
||
| 1123 | 25 | private function getPrimaryIndexInAlteredTable(TableDiff $diff) |
|
| 1135 | } |
||
| 1136 |
When comparing two booleans, it is generally considered safer to use the strict comparison operator.