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:
| 1 | <?php |
||
| 15 | class AdminStats extends Model |
||
| 16 | { |
||
| 17 | /** @var Project Project associated with this AdminStats instance. */ |
||
| 18 | protected $project; |
||
| 19 | |||
| 20 | /** @var string[] Keyed by user name, values are arrays containing actions and counts. */ |
||
| 21 | protected $adminStats; |
||
| 22 | |||
| 23 | /** |
||
| 24 | * Keys are user names, values are their abbreviated user groups. |
||
| 25 | * If abbreviations are turned on, this will instead be a string of the abbreviated |
||
| 26 | * user groups, separated by slashes. |
||
| 27 | * @var string[]|string |
||
| 28 | */ |
||
| 29 | protected $adminsAndGroups; |
||
| 30 | |||
| 31 | /** @var int Number of admins (sysops) who haven't made any actions within the time period. */ |
||
| 32 | protected $adminsWithoutActions = 0; |
||
| 33 | |||
| 34 | /** @var int Number of actual admins (sysops), not users with admin-like actions. */ |
||
| 35 | protected $numSysops = 0; |
||
| 36 | |||
| 37 | /** @var int Start of time period as UTC timestamp */ |
||
| 38 | protected $start; |
||
| 39 | |||
| 40 | /** @var int End of time period as UTC timestamp */ |
||
| 41 | protected $end; |
||
| 42 | |||
| 43 | /** |
||
| 44 | * TopEdits constructor. |
||
| 45 | * @param Project $project |
||
| 46 | * @param int $start as UTC timestamp. |
||
| 47 | * @param int $end as UTC timestamp. |
||
| 48 | */ |
||
| 49 | 3 | public function __construct(Project $project, $start = null, $end = null) |
|
| 55 | |||
| 56 | /** |
||
| 57 | * Get users of the project that are capable of making 'admin actions', |
||
| 58 | * keyed by user name with abbreviations for the user groups as the values. |
||
| 59 | * @param string $abbreviate If set, the keys of the result with be a string containing |
||
| 60 | * abbreviated versions of their user groups, such as 'A' instead of administrator, |
||
| 61 | * 'CU' instead of CheckUser, etc. If $abbreviate is false, the keys of the result |
||
| 62 | * will be an array of the full-named user groups. |
||
| 63 | * @see Project::getAdmins() |
||
| 64 | * @return string[] |
||
| 65 | */ |
||
| 66 | 3 | public function getAdminsAndGroups($abbreviate = true) |
|
| 121 | |||
| 122 | /** |
||
| 123 | * The number of days we're spanning between the start and end date. |
||
| 124 | * @return int |
||
| 125 | */ |
||
| 126 | 1 | public function numDays() |
|
| 130 | |||
| 131 | /** |
||
| 132 | * Get the array of statistics for each qualifying user. This may be called |
||
| 133 | * ahead of self::getStats() so certain class-level properties will be supplied |
||
| 134 | * (such as self::numUsers(), which is called in the view before iterating |
||
| 135 | * over the master array of statistics). |
||
| 136 | * @param boolean $abbreviateGroups If set, the 'groups' list will be |
||
| 137 | * a string with abbreivated user groups names, as opposed to an array |
||
| 138 | * of full-named user groups. |
||
| 139 | * @return string[] |
||
| 140 | */ |
||
| 141 | 2 | public function prepareStats($abbreviateGroups = true) |
|
| 167 | |||
| 168 | /** |
||
| 169 | * Get the master array of statistics for each qualifying user. |
||
| 170 | * @param boolean $abbreviateGroups If set, the 'groups' list will be |
||
| 171 | * a string with abbreivated user groups names, as opposed to an array |
||
| 172 | * of full-named user groups. |
||
| 173 | * @return string[] |
||
| 174 | */ |
||
| 175 | 1 | public function getStats($abbreviateGroups = true) |
|
| 182 | |||
| 183 | /** |
||
| 184 | * Given the data returned by AdminStatsRepository::getStats, |
||
| 185 | * return the stats keyed by user name, adding in a key/value for user groups. |
||
| 186 | * @param string[] $data As retrieved by AdminStatsRepository::getStats |
||
| 187 | * @param boolean $abbreviateGroups If set, the 'groups' list will be |
||
| 188 | * a string with abbreivated user groups names, as opposed to an array |
||
| 189 | * of full-named user groups. |
||
| 190 | * @return string[] Stats keyed by user name. |
||
| 191 | * Functionality covered in test for self::getStats(). |
||
| 192 | * @codeCoverageIgnore |
||
| 193 | */ |
||
| 194 | private function groupAdminStatsByUsername($data, $abbreviateGroups = true) |
||
| 226 | |||
| 227 | /** |
||
| 228 | * Fill in inactive admins (no actions within time period), given the list of |
||
| 229 | * remaining $adminsAndGroups from processing within self::groupAdminStatsByUsername(). |
||
| 230 | * @param string[] $users As computed by self::groupAdminStatsByUsername(). |
||
| 231 | * @param string[] $adminsAndGroups Remaining from self::getAdminsAndGroups(). |
||
| 232 | * @return string[] |
||
| 233 | * @codeCoverageIgnore |
||
| 234 | */ |
||
| 235 | private function fillInactiveAdmins($users, $adminsAndGroups) |
||
| 256 | |||
| 257 | /** |
||
| 258 | * Get the formatted start date. |
||
| 259 | * @return string |
||
| 260 | */ |
||
| 261 | 1 | public function getStart() |
|
| 265 | |||
| 266 | /** |
||
| 267 | * Get the formatted end date. |
||
| 268 | * @return string |
||
| 269 | */ |
||
| 270 | 1 | public function getEnd() |
|
| 274 | |||
| 275 | /** |
||
| 276 | * Get the total number of admins (users currently with qualifying permissions). |
||
| 277 | * @return int |
||
| 278 | */ |
||
| 279 | 1 | public function numAdmins() |
|
| 283 | |||
| 284 | /** |
||
| 285 | * Get the total number of users we're reporting as having made admin actions. |
||
| 286 | * @return int |
||
| 287 | */ |
||
| 288 | 1 | public function numUsers() |
|
| 292 | |||
| 293 | /** |
||
| 294 | * Number of admins who did make actions within the time period. |
||
| 295 | * @return int |
||
| 296 | */ |
||
| 297 | 1 | public function getNumAdminsWithActions() |
|
| 301 | |||
| 302 | /** |
||
| 303 | * Number of admins who did not make any actions within the time period. |
||
| 304 | * @return int |
||
| 305 | */ |
||
| 306 | 1 | public function getNumAdminsWithoutActions() |
|
| 310 | } |
||
| 311 |