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 DeleteLogFormatter 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 DeleteLogFormatter, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 31 | class DeleteLogFormatter extends LogFormatter { |
||
| 32 | protected function getMessageKey() { |
||
| 44 | |||
| 45 | protected function getMessageParameters() { |
||
| 46 | if ( isset( $this->parsedParametersDeleteLog ) ) { |
||
| 47 | return $this->parsedParametersDeleteLog; |
||
|
|
|||
| 48 | } |
||
| 49 | |||
| 50 | $params = parent::getMessageParameters(); |
||
| 51 | $subtype = $this->entry->getSubtype(); |
||
| 52 | if ( in_array( $subtype, [ 'event', 'revision' ] ) ) { |
||
| 53 | // $params[3] here is 'revision' or 'archive' for page revisions, 'oldimage' or |
||
| 54 | // 'filearchive' for file versions, or a comma-separated list of log_ids for log |
||
| 55 | // entries. $subtype here is 'revision' for page revisions and file |
||
| 56 | // versions, or 'event' for log entries. |
||
| 57 | if ( |
||
| 58 | ( $subtype === 'event' && count( $params ) === 6 ) |
||
| 59 | || ( |
||
| 60 | $subtype === 'revision' && isset( $params[3] ) |
||
| 61 | && in_array( $params[3], [ 'revision', 'archive', 'oldimage', 'filearchive' ] ) |
||
| 62 | ) |
||
| 63 | ) { |
||
| 64 | // See RevDelList::getLogParams()/RevDelLogList::getLogParams() |
||
| 65 | $paramStart = $subtype === 'revision' ? 4 : 3; |
||
| 66 | |||
| 67 | $old = $this->parseBitField( $params[$paramStart + 1] ); |
||
| 68 | $new = $this->parseBitField( $params[$paramStart + 2] ); |
||
| 69 | list( $hid, $unhid, $extra ) = RevisionDeleter::getChanges( $new, $old ); |
||
| 70 | $changes = []; |
||
| 71 | // messages used: revdelete-content-hid, revdelete-summary-hid, revdelete-uname-hid |
||
| 72 | foreach ( $hid as $v ) { |
||
| 73 | $changes[] = $this->msg( "$v-hid" )->plain(); |
||
| 74 | } |
||
| 75 | // messages used: revdelete-content-unhid, revdelete-summary-unhid, |
||
| 76 | // revdelete-uname-unhid |
||
| 77 | foreach ( $unhid as $v ) { |
||
| 78 | $changes[] = $this->msg( "$v-unhid" )->plain(); |
||
| 79 | } |
||
| 80 | foreach ( $extra as $v ) { |
||
| 81 | $changes[] = $this->msg( $v )->plain(); |
||
| 82 | } |
||
| 83 | $changeText = $this->context->getLanguage()->listToText( $changes ); |
||
| 84 | |||
| 85 | $newParams = array_slice( $params, 0, 3 ); |
||
| 86 | $newParams[3] = $changeText; |
||
| 87 | $ids = is_array( $params[$paramStart] ) |
||
| 88 | ? $params[$paramStart] |
||
| 89 | : explode( ',', $params[$paramStart] ); |
||
| 90 | $newParams[4] = $this->context->getLanguage()->formatNum( count( $ids ) ); |
||
| 91 | |||
| 92 | $this->parsedParametersDeleteLog = $newParams; |
||
| 93 | return $this->parsedParametersDeleteLog; |
||
| 94 | } else { |
||
| 95 | $this->parsedParametersDeleteLog = array_slice( $params, 0, 3 ); |
||
| 96 | return $this->parsedParametersDeleteLog; |
||
| 97 | } |
||
| 98 | } |
||
| 99 | |||
| 100 | $this->parsedParametersDeleteLog = $params; |
||
| 101 | return $this->parsedParametersDeleteLog; |
||
| 102 | } |
||
| 103 | |||
| 104 | protected function parseBitField( $string ) { |
||
| 114 | |||
| 115 | public function getActionLinks() { |
||
| 224 | |||
| 225 | protected function getParametersForApi() { |
||
| 279 | |||
| 280 | View Code Duplication | public function formatParametersForApi() { |
|
| 287 | } |
||
| 288 |
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: