Complex classes like PostgreSqlSchemaManager 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 PostgreSqlSchemaManager, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 33 | class PostgreSqlSchemaManager extends AbstractSchemaManager |
||
| 34 | { |
||
| 35 | /** |
||
| 36 | * @var array |
||
| 37 | */ |
||
| 38 | private $existingSchemaPaths; |
||
| 39 | |||
| 40 | /** |
||
| 41 | * Gets all the existing schema names. |
||
| 42 | * |
||
| 43 | * @return array |
||
| 44 | */ |
||
| 45 | public function getSchemaNames() |
||
| 51 | |||
| 52 | /** |
||
| 53 | * Returns an array of schema search paths. |
||
| 54 | * |
||
| 55 | * This is a PostgreSQL only function. |
||
| 56 | * |
||
| 57 | * @return array |
||
| 58 | */ |
||
| 59 | public function getSchemaSearchPaths() |
||
| 70 | |||
| 71 | /** |
||
| 72 | * Gets names of all existing schemas in the current users search path. |
||
| 73 | * |
||
| 74 | * This is a PostgreSQL only function. |
||
| 75 | * |
||
| 76 | * @return array |
||
| 77 | */ |
||
| 78 | public function getExistingSchemaSearchPaths() |
||
| 86 | |||
| 87 | /** |
||
| 88 | * Sets or resets the order of the existing schemas in the current search path of the user. |
||
| 89 | * |
||
| 90 | * This is a PostgreSQL only function. |
||
| 91 | * |
||
| 92 | * @return void |
||
| 93 | */ |
||
| 94 | public function determineExistingSchemaSearchPaths() |
||
| 103 | |||
| 104 | /** |
||
| 105 | * {@inheritdoc} |
||
| 106 | */ |
||
| 107 | public function dropDatabase($database) |
||
| 108 | { |
||
| 109 | try { |
||
| 110 | parent::dropDatabase($database); |
||
| 111 | } catch (DriverException $exception) { |
||
| 112 | // If we have a SQLSTATE 55006, the drop database operation failed |
||
| 113 | // because of active connections on the database. |
||
| 114 | // To force dropping the database, we first have to close all active connections |
||
| 115 | // on that database and issue the drop database operation again. |
||
| 116 | if ($exception->getSQLState() !== '55006') { |
||
| 117 | throw $exception; |
||
| 118 | } |
||
| 119 | |||
| 120 | $this->_execSql( |
||
| 121 | [ |
||
| 122 | $this->_platform->getDisallowDatabaseConnectionsSQL($database), |
||
|
|
|||
| 123 | $this->_platform->getCloseActiveDatabaseConnectionsSQL($database), |
||
| 124 | ] |
||
| 125 | ); |
||
| 126 | |||
| 127 | parent::dropDatabase($database); |
||
| 128 | } |
||
| 129 | } |
||
| 130 | |||
| 131 | /** |
||
| 132 | * {@inheritdoc} |
||
| 133 | */ |
||
| 134 | protected function _getPortableTableForeignKeyDefinition($tableForeignKey) |
||
| 159 | |||
| 160 | /** |
||
| 161 | * {@inheritdoc} |
||
| 162 | */ |
||
| 163 | protected function _getPortableTriggerDefinition($trigger) |
||
| 167 | |||
| 168 | /** |
||
| 169 | * {@inheritdoc} |
||
| 170 | */ |
||
| 171 | protected function _getPortableViewDefinition($view) |
||
| 175 | |||
| 176 | /** |
||
| 177 | * {@inheritdoc} |
||
| 178 | */ |
||
| 179 | protected function _getPortableUserDefinition($user) |
||
| 186 | |||
| 187 | /** |
||
| 188 | * {@inheritdoc} |
||
| 189 | */ |
||
| 190 | protected function _getPortableTableDefinition($table) |
||
| 201 | |||
| 202 | /** |
||
| 203 | * {@inheritdoc} |
||
| 204 | * |
||
| 205 | * @license New BSD License |
||
| 206 | * @link http://ezcomponents.org/docs/api/trunk/DatabaseSchema/ezcDbSchemaPgsqlReader.html |
||
| 207 | */ |
||
| 208 | protected function _getPortableTableIndexesList($tableIndexes, $tableName=null) |
||
| 238 | |||
| 239 | /** |
||
| 240 | * {@inheritdoc} |
||
| 241 | */ |
||
| 242 | protected function _getPortableDatabaseDefinition($database) |
||
| 246 | |||
| 247 | /** |
||
| 248 | * {@inheritdoc} |
||
| 249 | */ |
||
| 250 | 1 | protected function _getPortableSequencesList($sequences) |
|
| 251 | { |
||
| 252 | 1 | $sequenceDefinitions = []; |
|
| 253 | |||
| 254 | 1 | foreach ($sequences as $sequence) { |
|
| 255 | 1 | if ($sequence['schemaname'] != 'public') { |
|
| 256 | 1 | $sequenceName = $sequence['schemaname'] . "." . $sequence['relname']; |
|
| 257 | } else { |
||
| 258 | $sequenceName = $sequence['relname']; |
||
| 259 | } |
||
| 260 | |||
| 261 | 1 | $sequenceDefinitions[$sequenceName] = $sequence; |
|
| 262 | } |
||
| 263 | |||
| 264 | 1 | $list = []; |
|
| 265 | |||
| 266 | 1 | foreach ($this->filterAssetNames(array_keys($sequenceDefinitions)) as $sequenceName) { |
|
| 267 | 1 | $list[] = $this->_getPortableSequenceDefinition($sequenceDefinitions[$sequenceName]); |
|
| 268 | } |
||
| 269 | |||
| 270 | 1 | return $list; |
|
| 271 | } |
||
| 272 | |||
| 273 | /** |
||
| 274 | * {@inheritdoc} |
||
| 275 | */ |
||
| 276 | protected function getPortableNamespaceDefinition(array $namespace) |
||
| 280 | |||
| 281 | /** |
||
| 282 | * {@inheritdoc} |
||
| 283 | */ |
||
| 284 | 1 | protected function _getPortableSequenceDefinition($sequence) |
|
| 296 | |||
| 297 | /** |
||
| 298 | * {@inheritdoc} |
||
| 299 | */ |
||
| 300 | protected function _getPortableTableColumnDefinition($tableColumn) |
||
| 454 | |||
| 455 | /** |
||
| 456 | * PostgreSQL 9.4 puts parentheses around negative numeric default values that need to be stripped eventually. |
||
| 457 | * |
||
| 458 | * @param mixed $defaultValue |
||
| 459 | * |
||
| 460 | * @return mixed |
||
| 461 | */ |
||
| 462 | private function fixVersion94NegativeNumericDefaultValue($defaultValue) |
||
| 470 | |||
| 471 | /** |
||
| 472 | * Un-escape a default value as given by PostgreSQL |
||
| 473 | * |
||
| 474 | * @param null|string $default |
||
| 475 | * |
||
| 476 | * @return null|string |
||
| 477 | */ |
||
| 478 | private function fixDefaultValueQuotes(?string $default): ?string |
||
| 489 | } |
||
| 490 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the parent class: