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 QueryManagerMysqlMonocleAlternate 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 QueryManagerMysqlMonocleAlternate, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 3 | class QueryManagerMysqlMonocleAlternate extends QueryManagerMysql { |
||
|
|
|||
| 4 | |||
| 5 | public function __construct() { |
||
| 8 | |||
| 9 | public function __destruct() { |
||
| 12 | |||
| 13 | /////////// |
||
| 14 | // Tester |
||
| 15 | /////////// |
||
| 16 | |||
| 17 | View Code Duplication | function testTotalPokemon() { |
|
| 32 | |||
| 33 | View Code Duplication | function testTotalGyms() { |
|
| 48 | |||
| 49 | View Code Duplication | function testTotalPokestops() { |
|
| 64 | |||
| 65 | |||
| 66 | ///////////// |
||
| 67 | // Homepage |
||
| 68 | ///////////// |
||
| 69 | |||
| 70 | function getTotalPokemon() { |
||
| 76 | |||
| 77 | function getTotalLures() { |
||
| 81 | |||
| 82 | function getTotalGyms() { |
||
| 88 | |||
| 89 | function getTotalRaids() { |
||
| 95 | |||
| 96 | |||
| 97 | function getTotalGymsForTeam($team_id) { |
||
| 103 | |||
| 104 | function getRecentAll() { |
||
| 119 | |||
| 120 | function getRecentMythic($mythic_pokemon) { |
||
| 136 | |||
| 137 | /////////////////// |
||
| 138 | // Single Pokemon |
||
| 139 | /////////////////// |
||
| 140 | |||
| 141 | View Code Duplication | function getGymsProtectedByPokemon($pokemon_id) { |
|
| 147 | |||
| 148 | View Code Duplication | function getPokemonLastSeen($pokemon_id) { |
|
| 158 | |||
| 159 | function getTop50Pokemon($pokemon_id, $top_order_by, $top_direction) { |
||
| 175 | |||
| 176 | View Code Duplication | function getTop50Trainers($pokemon_id, $best_order_by, $best_direction) { |
|
| 177 | $trainer_blacklist = ""; |
||
| 178 | if (!empty(self::$config->system->trainer_blacklist)) { |
||
| 179 | $trainer_blacklist = " AND owner_name NOT IN ('" . implode("','", self::$config->system->trainer_blacklist) . "')"; |
||
| 180 | } |
||
| 181 | |||
| 182 | $req = "SELECT owner_name as trainer_name, ROUND((100*((atk_iv)+(def_iv)+(sta_iv))/45),1) AS IV, move_1, move_2, cp as cp, |
||
| 183 | FROM_UNIXTIME(last_modified) AS lasttime, last_modified as last_seen |
||
| 184 | FROM gym_defenders |
||
| 185 | WHERE pokemon_id = '" . $pokemon_id . "'" . $trainer_blacklist . " |
||
| 186 | ORDER BY $best_order_by $best_direction, owner_name ASC |
||
| 187 | LIMIT 0,50"; |
||
| 188 | |||
| 189 | $result = $this->mysqli->query($req); |
||
| 190 | $toptrainer = array(); |
||
| 191 | while ($data = $result->fetch_object()) { |
||
| 192 | $toptrainer[] = $data; |
||
| 193 | } |
||
| 194 | return $toptrainer; |
||
| 195 | } |
||
| 196 | |||
| 197 | View Code Duplication | public function getPokemonHeatmap($pokemon_id, $start, $end) { |
|
| 198 | $where = " WHERE pokemon_id = ".$pokemon_id." " |
||
| 199 | . "AND FROM_UNIXTIME(expire_timestamp) BETWEEN '".$start."' AND '".$end."'"; |
||
| 200 | $req = "SELECT lat AS latitude, lon AS longitude FROM sightings".$where." ORDER BY expire_timestamp DESC LIMIT 100000"; |
||
| 201 | $result = $this->mysqli->query($req); |
||
| 202 | $points = array(); |
||
| 203 | while ($data = $result->fetch_object()) { |
||
| 204 | $points[] = $data; |
||
| 205 | } |
||
| 206 | return $points; |
||
| 207 | } |
||
| 208 | |||
| 209 | View Code Duplication | public function getPokemonGraph($pokemon_id) { |
|
| 210 | $req = "SELECT COUNT(*) AS total, HOUR(disappear_time) AS disappear_hour |
||
| 211 | FROM (SELECT FROM_UNIXTIME(expire_timestamp) as disappear_time FROM sightings WHERE pokemon_id = '".$pokemon_id."' ORDER BY disappear_time LIMIT 100000) AS pokemonFiltered |
||
| 212 | GROUP BY disappear_hour |
||
| 213 | ORDER BY disappear_hour"; |
||
| 214 | $result = $this->mysqli->query($req); |
||
| 215 | $array = array_fill(0, 24, 0); |
||
| 216 | while ($result && $data = $result->fetch_object()) { |
||
| 217 | $array[$data->disappear_hour] = $data->total; |
||
| 218 | } |
||
| 219 | // shift array because AM/PM starts at 1AM not 0:00 |
||
| 220 | $array[] = $array[0]; |
||
| 221 | array_shift($array); |
||
| 222 | return $array; |
||
| 223 | } |
||
| 224 | |||
| 225 | View Code Duplication | public function getPokemonLive($pokemon_id, $ivMin, $ivMax, $inmap_pokemons) { |
|
| 226 | $inmap_pkms_filter = ""; |
||
| 227 | $where = " WHERE expire_timestamp >= UNIX_TIMESTAMP() AND pokemon_id = " . $pokemon_id; |
||
| 228 | |||
| 229 | $reqTestIv = "SELECT MAX(atk_iv) AS iv FROM sightings " . $where; |
||
| 230 | $resultTestIv = $this->mysqli->query($reqTestIv); |
||
| 231 | $testIv = $resultTestIv->fetch_object(); |
||
| 232 | if (!is_null($inmap_pokemons) && ($inmap_pokemons != "")) { |
||
| 233 | foreach ($inmap_pokemons as $inmap) { |
||
| 234 | $inmap_pkms_filter .= "'".$inmap."',"; |
||
| 235 | } |
||
| 236 | $inmap_pkms_filter = rtrim($inmap_pkms_filter, ","); |
||
| 237 | $where .= " AND encounter_id NOT IN (" . $inmap_pkms_filter . ") "; |
||
| 238 | } |
||
| 239 | if ($testIv->iv != null && !is_null($ivMin) && ($ivMin != "")) { |
||
| 240 | $where .= " AND ((100/45)*(atk_iv + def_iv + sta_iv)) >= (" . $ivMin . ") "; |
||
| 241 | } |
||
| 242 | if ($testIv->iv != null && !is_null($ivMax) && ($ivMax != "")) { |
||
| 243 | $where .= " AND ((100/45)*(atk_iv + def_iv + sta_iv)) <= (" . $ivMax . ") "; |
||
| 244 | } |
||
| 245 | $req = "SELECT pokemon_id, lat AS latitude, lon AS longitude, |
||
| 246 | FROM_UNIXTIME(expire_timestamp) AS disappear_time, |
||
| 247 | FROM_UNIXTIME(expire_timestamp) AS disappear_time_real, |
||
| 248 | atk_iv AS individual_attack, def_iv AS individual_defense, sta_iv AS individual_stamina, |
||
| 249 | move_1, move_2 |
||
| 250 | FROM sightings " . $where . " |
||
| 251 | ORDER BY disappear_time DESC |
||
| 252 | LIMIT 5000"; |
||
| 253 | $result = $this->mysqli->query($req); |
||
| 254 | $spawns = array(); |
||
| 255 | while ($data = $result->fetch_object()) { |
||
| 256 | $spawns[] = $data; |
||
| 257 | } |
||
| 258 | return $spawns; |
||
| 259 | } |
||
| 260 | |||
| 261 | public function getPokemonSliderMinMax() { |
||
| 262 | $req = "SELECT FROM_UNIXTIME(MIN(expire_timestamp)) AS min, FROM_UNIXTIME(MAX(expire_timestamp)) AS max FROM sightings"; |
||
| 263 | $result = $this->mysqli->query($req); |
||
| 264 | $data = $result->fetch_object(); |
||
| 265 | return $data; |
||
| 266 | } |
||
| 267 | |||
| 268 | public function getMapsCoords() { |
||
| 269 | $req = "SELECT MAX(lat) AS max_latitude, MIN(lat) AS min_latitude, MAX(lon) AS max_longitude, MIN(lon) as min_longitude FROM spawnpoints"; |
||
| 270 | $result = $this->mysqli->query($req); |
||
| 271 | $data = $result->fetch_object(); |
||
| 272 | return $data; |
||
| 273 | } |
||
| 274 | |||
| 275 | |||
| 276 | /////////////// |
||
| 277 | // Pokestops |
||
| 278 | ////////////// |
||
| 279 | |||
| 280 | |||
| 281 | function getTotalPokestops() { |
||
| 282 | $req = "SELECT COUNT(*) as total FROM pokestops"; |
||
| 283 | $result = $this->mysqli->query($req); |
||
| 284 | $data = $result->fetch_object(); |
||
| 285 | return $data; |
||
| 286 | } |
||
| 287 | |||
| 288 | public function getAllPokestops() { |
||
| 289 | $req = "SELECT lat as latitude, lon as longitude, null AS lure_expiration, UNIX_TIMESTAMP() AS now, null AS lure_expiration_real FROM pokestops"; |
||
| 290 | $result = $this->mysqli->query($req); |
||
| 291 | $pokestops = array(); |
||
| 292 | while ($data = $result->fetch_object()) { |
||
| 293 | $pokestops[] = $data; |
||
| 294 | } |
||
| 295 | return $pokestops; |
||
| 296 | } |
||
| 297 | |||
| 298 | |||
| 299 | ///////// |
||
| 300 | // Gyms |
||
| 301 | ///////// |
||
| 302 | |||
| 303 | function getTeamGuardians($team_id) { |
||
| 304 | $req = "SELECT COUNT(*) AS total, guard_pokemon_id FROM fort_sightings WHERE team = '".$team_id."' GROUP BY guard_pokemon_id ORDER BY total DESC LIMIT 0,3"; |
||
| 305 | $result = $this->mysqli->query($req); |
||
| 306 | |||
| 307 | $datas = array(); |
||
| 308 | while ($data = $result->fetch_object()) { |
||
| 309 | $datas[] = $data; |
||
| 310 | } |
||
| 311 | |||
| 312 | return $datas; |
||
| 313 | } |
||
| 314 | |||
| 315 | function getOwnedAndPoints($team_id) { |
||
| 316 | $req = "SELECT COUNT(DISTINCT(fs.fort_id)) AS total, ROUND((SUM(gd.cp)) / COUNT(DISTINCT(fs.fort_id)),0) AS average_points |
||
| 317 | FROM fort_sightings fs |
||
| 318 | JOIN gym_defenders gd ON fs.fort_id = gd.fort_id |
||
| 319 | WHERE fs.team = '" . $team_id . "'"; |
||
| 320 | $result = $this->mysqli->query($req); |
||
| 321 | $data = $result->fetch_object(); |
||
| 322 | return $data; |
||
| 323 | } |
||
| 324 | |||
| 325 | function getAllGyms() { |
||
| 326 | $req = "SELECT f.id as gym_id, team as team_id, f.lat as latitude, f.lon as longitude, updated as last_scanned, (6 - fs.slots_available) AS level FROM forts f LEFT JOIN fort_sightings fs ON f.id = fs.fort_id;"; |
||
| 327 | $result = $this->mysqli->query($req); |
||
| 328 | $gyms = array(); |
||
| 329 | while ($data = $result->fetch_object()) { |
||
| 330 | $gyms[] = $data; |
||
| 331 | } |
||
| 332 | return $gyms; |
||
| 333 | } |
||
| 334 | |||
| 335 | public function getGymData($gym_id) { |
||
| 336 | $req = "SELECT f.name AS name, null AS description, f.url AS url, fs.team AS team, FROM_UNIXTIME(fs.updated) AS last_scanned, fs.guard_pokemon_id AS guard_pokemon_id, (6 - fs.slots_available) AS level, SUM(gd.cp) as total_cp |
||
| 337 | FROM fort_sightings fs |
||
| 338 | LEFT JOIN forts f ON f.id = fs.fort_id |
||
| 339 | LEFT JOIN gym_defenders gd ON f.id = gd.fort_id |
||
| 340 | WHERE f.id ='".$gym_id."' |
||
| 341 | GROUP BY f.name, f.url, fs.team, fs.updated, fs.guard_pokemon_id, fs.slots_available, gd.cp"; |
||
| 342 | $result = $this->mysqli->query($req); |
||
| 343 | $data = $result->fetch_object(); |
||
| 344 | return $data; |
||
| 345 | } |
||
| 346 | |||
| 347 | public function getGymDefenders($gym_id) { |
||
| 359 | |||
| 360 | |||
| 361 | /////////// |
||
| 362 | // Raids |
||
| 363 | /////////// |
||
| 364 | |||
| 365 | View Code Duplication | public function getAllRaids($page) { |
|
| 380 | |||
| 381 | |||
| 382 | |||
| 383 | //////////////// |
||
| 384 | // Gym History |
||
| 385 | //////////////// |
||
| 386 | |||
| 387 | public function getGymHistories($gym_name, $team, $page, $ranking) |
||
| 388 | { |
||
| 389 | // TODO: Implement |
||
| 390 | return array(); |
||
| 391 | } |
||
| 392 | |||
| 393 | public function getGymHistoriesPokemon($gym_id) |
||
| 398 | |||
| 399 | public function getHistoryForGym($page, $gym_id) |
||
| 404 | |||
| 405 | public function getHistoryForGymPokemon($pkm_uids) |
||
| 410 | |||
| 411 | |||
| 412 | |||
| 413 | ////////////// |
||
| 414 | // Trainers |
||
| 415 | ////////////// |
||
| 416 | |||
| 417 | public function getTrainers($trainer_name, $team, $page, $ranking) { |
||
| 420 | |||
| 421 | View Code Duplication | public function getTrainerLevelCount($team_id) { |
|
| 430 | |||
| 431 | |||
| 432 | ///////// |
||
| 433 | // Cron |
||
| 434 | ///////// |
||
| 435 | |||
| 436 | public function getPokemonCountsActive() { |
||
| 445 | |||
| 446 | public function getPokemonCountsLastDay() { |
||
| 459 | |||
| 460 | View Code Duplication | public function getPokemonSinceLastUpdate($pokemon_id, $last_update) { |
|
| 477 | |||
| 478 | View Code Duplication | public function getRaidsSinceLastUpdate($pokemon_id, $last_update) { |
|
| 495 | |||
| 496 | public function getCaptchaCount() { |
||
| 502 | |||
| 503 | View Code Duplication | public function getNestData() { |
|
| 523 | |||
| 524 | } |
||
| 525 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.