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 cache 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 cache, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 10 | class cache |
||
|
|
|||
| 11 | { |
||
| 12 | public $nCacheId = 0; |
||
| 13 | |||
| 14 | public $reCache; |
||
| 15 | |||
| 16 | /** |
||
| 17 | * @param $wp |
||
| 18 | * @return int|null |
||
| 19 | */ |
||
| 20 | public static function cacheIdFromWP($wp) |
||
| 21 | { |
||
| 22 | if (mb_strtoupper(mb_substr($wp, 0, 2)) === 'GC') { |
||
| 23 | $rs = sql("SELECT `cache_id` FROM `caches` WHERE `wp_gc_maintained`='&1'", $wp); |
||
| 24 | if (sql_num_rows($rs) !== 1) { |
||
| 25 | sql_free_result($rs); |
||
| 26 | |||
| 27 | return null; |
||
| 28 | } |
||
| 29 | $r = sql_fetch_assoc($rs); |
||
| 30 | sql_free_result($rs); |
||
| 31 | |||
| 32 | $cacheId = $r['cache_id']; |
||
| 33 | } else { |
||
| 34 | $cacheId = sql_value("SELECT `cache_id` FROM `caches` WHERE `wp_oc`='&1'", 0, $wp); |
||
| 35 | } |
||
| 36 | |||
| 37 | return $cacheId; |
||
| 38 | } |
||
| 39 | |||
| 40 | /** |
||
| 41 | * @param $wp |
||
| 42 | * @return cache|null |
||
| 43 | */ |
||
| 44 | public static function fromWP($wp) |
||
| 45 | { |
||
| 46 | $cacheId = self::cacheIdFromWP($wp); |
||
| 47 | if ($cacheId === 0) { |
||
| 48 | return null; |
||
| 49 | } |
||
| 50 | |||
| 51 | return new cache($cacheId); |
||
| 52 | } |
||
| 53 | |||
| 54 | /** |
||
| 55 | * @param $uuid |
||
| 56 | * @return mixed |
||
| 57 | */ |
||
| 58 | public static function cacheIdFromUUID($uuid) |
||
| 59 | { |
||
| 60 | $cacheId = sql_value("SELECT `cache_id` FROM `caches` WHERE `uuid`='&1'", 0, $uuid); |
||
| 61 | |||
| 62 | return $cacheId; |
||
| 63 | } |
||
| 64 | |||
| 65 | /** |
||
| 66 | * @param $uuid |
||
| 67 | * @return cache|null |
||
| 68 | */ |
||
| 69 | public static function fromUUID($uuid) |
||
| 70 | { |
||
| 71 | $cacheId = self::cacheIdFromUUID($uuid); |
||
| 72 | if ($cacheId === 0) { |
||
| 73 | return null; |
||
| 74 | } |
||
| 75 | |||
| 76 | return new cache($cacheId); |
||
| 77 | } |
||
| 78 | |||
| 79 | public function __construct($nNewCacheId = ID_NEW) |
||
| 124 | |||
| 125 | /** |
||
| 126 | * @return bool |
||
| 127 | */ |
||
| 128 | public function exist() |
||
| 129 | { |
||
| 130 | return $this->reCache->exist(); |
||
| 131 | } |
||
| 132 | |||
| 133 | /** |
||
| 134 | * @return int |
||
| 135 | */ |
||
| 136 | public function getCacheId() |
||
| 137 | { |
||
| 138 | return $this->nCacheId; |
||
| 139 | } |
||
| 140 | |||
| 141 | public function getStatus() |
||
| 142 | { |
||
| 143 | return $this->reCache->getValue('status'); |
||
| 144 | } |
||
| 145 | |||
| 146 | public function getType() |
||
| 147 | { |
||
| 148 | return $this->reCache->getValue('type'); |
||
| 149 | } |
||
| 150 | |||
| 151 | public function getName() |
||
| 152 | { |
||
| 153 | return $this->reCache->getValue('name'); |
||
| 154 | } |
||
| 155 | |||
| 156 | public function getLongitude() |
||
| 157 | { |
||
| 158 | return $this->reCache->getValue('longitude'); |
||
| 159 | } |
||
| 160 | |||
| 161 | public function getLatitude() |
||
| 162 | { |
||
| 163 | return $this->reCache->getValue('latitude'); |
||
| 164 | } |
||
| 165 | |||
| 166 | public function getUserId() |
||
| 167 | { |
||
| 168 | return $this->reCache->getValue('user_id'); |
||
| 169 | } |
||
| 170 | |||
| 171 | public function getUsername() |
||
| 172 | { |
||
| 173 | return sql_value("SELECT `username` FROM `user` WHERE `user_id`='&1'", '', $this->getUserId()); |
||
| 174 | } |
||
| 175 | |||
| 176 | public function getWPOC() |
||
| 177 | { |
||
| 178 | return $this->reCache->getValue('wp_oc'); |
||
| 179 | } |
||
| 180 | |||
| 181 | public function getWPGC() |
||
| 182 | { |
||
| 183 | return $this->reCache->getValue('wp_gc'); |
||
| 184 | } |
||
| 185 | |||
| 186 | public function getWPGC_maintained() |
||
| 187 | { |
||
| 188 | return $this->reCache->getValue('wp_gc_maintained'); |
||
| 189 | } |
||
| 190 | |||
| 191 | public function getUUID() |
||
| 192 | { |
||
| 193 | return $this->reCache->getValue('uuid'); |
||
| 194 | } |
||
| 195 | |||
| 196 | public function getDateCreated() |
||
| 197 | { |
||
| 198 | return $this->reCache->getValue('date_created'); |
||
| 199 | } |
||
| 200 | |||
| 201 | public function getLastModified() |
||
| 202 | { |
||
| 203 | return $this->reCache->getValue('last_modified'); |
||
| 204 | } |
||
| 205 | |||
| 206 | public function getListingLastModified() |
||
| 207 | { |
||
| 208 | return $this->reCache->getValue('listing_last_modified'); |
||
| 209 | } |
||
| 210 | |||
| 211 | public function getNode() |
||
| 212 | { |
||
| 213 | return $this->reCache->getValue('node'); |
||
| 214 | } |
||
| 215 | |||
| 216 | public function setNode($value) |
||
| 217 | { |
||
| 218 | return $this->reCache->setValue('node', $value); |
||
| 219 | } |
||
| 220 | |||
| 221 | public function setStatus($value) |
||
| 222 | { |
||
| 223 | global $login; |
||
| 224 | if (sql_value("SELECT COUNT(*) FROM `cache_status` WHERE `id`='&1'", 0, $value) == 1) { |
||
| 225 | sql("SET @STATUS_CHANGE_USER_ID='&1'", $login->userid); |
||
| 226 | |||
| 227 | return $this->reCache->setValue('status', $value); |
||
| 228 | } else { |
||
| 229 | return false; |
||
| 230 | } |
||
| 231 | } |
||
| 232 | |||
| 233 | public function getDescLanguages() |
||
| 234 | { |
||
| 235 | return explode($this->reCache->getValue('desc_languages'), ','); |
||
| 236 | } |
||
| 237 | |||
| 238 | public function getDefaultDescLanguage() |
||
| 239 | { |
||
| 240 | return $this->reCache->getValue('default_desclang'); |
||
| 241 | } |
||
| 242 | |||
| 243 | public function getProtectOldCoords() |
||
| 244 | { |
||
| 245 | return $this->reCache->getValue('protect_old_coords'); |
||
| 246 | } |
||
| 247 | |||
| 248 | public function setProtectOldCoords($value) |
||
| 249 | { |
||
| 250 | return $this->reCache->setValue('protect_old_coords', $value); |
||
| 251 | } |
||
| 252 | |||
| 253 | // cache condition flags |
||
| 254 | public function getNeedsMaintenance() |
||
| 255 | { |
||
| 256 | return $this->reCache->getValue('needs_maintenance'); |
||
| 257 | } |
||
| 258 | |||
| 259 | public function setNeedsMaintenance($value) |
||
| 260 | { |
||
| 261 | return $this->reCache->setValue('needs_maintenance', $value); |
||
| 262 | } |
||
| 263 | |||
| 264 | public function getListingOutdated() |
||
| 265 | { |
||
| 266 | return $this->reCache->getValue('listing_outdated'); |
||
| 267 | } |
||
| 268 | |||
| 269 | public function getListingOutdatedLogUrl() |
||
| 270 | { |
||
| 271 | $url = ''; |
||
| 272 | $rs = sql( |
||
| 273 | "SELECT `id`, `listing_outdated` |
||
| 274 | FROM `cache_logs` |
||
| 275 | WHERE `cache_id`='&1' |
||
| 276 | AND `listing_outdated`>0 |
||
| 277 | ORDER BY `order_date` DESC, `date_created` DESC, `id` DESC", |
||
| 278 | // same sorting order as in DB function sp_update_logstat() |
||
| 279 | $this->getCacheId() |
||
| 280 | ); |
||
| 281 | if ($r = sql_fetch_assoc($rs)) { |
||
| 282 | if ($r['listing_outdated'] == 2) { |
||
| 283 | $url = 'viewlogs.php?cacheid=' . $this->getCacheId() . '#log' . $r['id']; |
||
| 284 | } |
||
| 285 | } |
||
| 286 | sql_free_result($rs); |
||
| 287 | |||
| 288 | return $url; |
||
| 289 | } |
||
| 290 | |||
| 291 | // test if af the time of insertion of an existing log the listing |
||
| 292 | // was outdated and there is no newer listing-[not]-outdated-log |
||
| 293 | |||
| 294 | public function getListingOutdatedRelativeToLog($logId) |
||
| 322 | |||
| 323 | public function setListingOutdated($value) |
||
| 324 | { |
||
| 325 | return $this->reCache->setValue('listing_outdated', $value); |
||
| 326 | } |
||
| 327 | |||
| 328 | public function getConditionHistory() |
||
| 329 | { |
||
| 330 | $cache_id = $this->nCacheId; |
||
| 331 | $rs = sql( |
||
| 332 | "SELECT `date`, `needs_maintenance`, `listing_outdated` |
||
| 333 | FROM `cache_logs` |
||
| 334 | WHERE `cache_id`='&1' AND (`needs_maintenance` IS NOT NULL OR `listing_outdated` IS NOT NULL) |
||
| 335 | ORDER BY `date`, `id`", |
||
| 336 | $cache_id |
||
| 337 | ); |
||
| 338 | $nm = $lo = 0; |
||
| 339 | $cond = [ |
||
| 340 | [ |
||
| 341 | 'needs_maintenance' => $nm, |
||
| 342 | 'listing_outdated' => $lo, |
||
| 343 | 'date' => '0000-00-00 00:00:00' |
||
| 344 | ] |
||
| 345 | ]; |
||
| 346 | while ($r = sql_fetch_assoc($rs)) { |
||
| 347 | if ($r['needs_maintenance'] != $nm || $r['listing_outdated'] != $lo) { |
||
| 348 | $nm = $r['needs_maintenance']; |
||
| 349 | $lo = $r['listing_outdated']; |
||
| 350 | $cond[] = [ |
||
| 351 | 'needs_maintenance' => $nm, |
||
| 352 | 'listing_outdated' => $lo, |
||
| 353 | 'date' => $r['date'] |
||
| 354 | ]; |
||
| 355 | } |
||
| 356 | } |
||
| 357 | sql_free_result($rs); |
||
| 358 | $cond[] = [ |
||
| 359 | 'needs_maintenance' => $nm, |
||
| 360 | 'listing_outdated' => $lo, |
||
| 361 | 'date' => '9999-12-31 23:59:59' |
||
| 362 | ]; |
||
| 363 | |||
| 364 | return $cond; |
||
| 365 | } |
||
| 366 | |||
| 367 | /** |
||
| 368 | * @param int $attr_id |
||
| 369 | * @return bool |
||
| 370 | */ |
||
| 371 | public function hasAttribute($attr_id) |
||
| 383 | |||
| 384 | // other |
||
| 385 | public function getAnyChanged() |
||
| 386 | { |
||
| 387 | return $this->reCache->getAnyChanged(); |
||
| 388 | } |
||
| 389 | |||
| 390 | // return if successful (with insert) |
||
| 391 | public function save() |
||
| 401 | |||
| 402 | public function requireLogPW() |
||
| 403 | { |
||
| 404 | return $this->reCache->getValue('logpw') != ''; |
||
| 405 | } |
||
| 406 | |||
| 407 | // TODO: use prepared one way hash |
||
| 408 | public function validateLogPW($nLogType, $sLogPW) |
||
| 409 | { |
||
| 410 | if (!$this->requireLogPW()) { |
||
| 411 | return true; |
||
| 412 | } |
||
| 413 | |||
| 414 | if (sql_value("SELECT `require_password` FROM `log_types` WHERE `id`='&1'", 0, $nLogType) == 0) { |
||
| 415 | return true; |
||
| 416 | } |
||
| 417 | |||
| 418 | return ($sLogPW == $this->reCache->getValue('logpw')); |
||
| 419 | } |
||
| 420 | |||
| 421 | /** |
||
| 422 | * @param $nVisitUserId |
||
| 423 | * @param $sRemoteAddr |
||
| 424 | * @param $nCacheId |
||
| 425 | * @return void |
||
| 426 | */ |
||
| 427 | public static function visitCounter($nVisitUserId, $sRemoteAddr, $nCacheId) |
||
| 428 | { |
||
| 429 | global $opt, $_SERVER; |
||
| 430 | |||
| 431 | // delete cache_visits older 1 day 60*60*24 = 86400 |
||
| 432 | sql( |
||
| 433 | "DELETE FROM `cache_visits` |
||
| 434 | WHERE `cache_id`='&1' |
||
| 435 | AND `user_id_ip`!='0' |
||
| 436 | AND NOW()-`last_modified`>86400", |
||
| 437 | $nCacheId |
||
| 438 | ); |
||
| 439 | |||
| 440 | if ($nVisitUserId == 0) { |
||
| 441 | $se = explode(';', $opt['logic']['search_engines']); |
||
| 442 | $ua = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ""; |
||
| 443 | foreach ($se as $s) { |
||
| 444 | if (strpos($ua, $s) !== false) { |
||
| 445 | return; |
||
| 446 | } |
||
| 447 | } // do not count search engine views |
||
| 448 | |||
| 449 | $sIdentifier = $sRemoteAddr; |
||
| 450 | } else { |
||
| 451 | $sIdentifier = $nVisitUserId; |
||
| 452 | } |
||
| 453 | |||
| 454 | // note the visit of this user |
||
| 455 | sql( |
||
| 456 | "INSERT INTO `cache_visits` (`cache_id`, `user_id_ip`, `count`) |
||
| 457 | VALUES (&1, '&2', 1) |
||
| 458 | ON DUPLICATE KEY UPDATE `count`=`count`+1", |
||
| 459 | $nCacheId, |
||
| 460 | $sIdentifier |
||
| 461 | ); |
||
| 462 | |||
| 463 | // if the previous statement does an INSERT, it was the first visit for this user today |
||
| 464 | if (sql_affected_rows() == 1) { |
||
| 465 | if ($nVisitUserId != sql_value("SELECT `user_id` FROM `caches` WHERE `cache_id`='&1'", 0, $nCacheId)) { |
||
| 466 | // increment the counter for this cache |
||
| 467 | sql( |
||
| 468 | "INSERT INTO `cache_visits` (`cache_id`, `user_id_ip`, `count`) |
||
| 469 | VALUES (&1, '0', 1) |
||
| 470 | ON DUPLICATE KEY UPDATE `count`=`count`+1", |
||
| 471 | $nCacheId |
||
| 472 | ); |
||
| 473 | } |
||
| 474 | } |
||
| 475 | } |
||
| 476 | |||
| 477 | /** |
||
| 478 | * @param $cacheId |
||
| 479 | * @return array |
||
| 480 | */ |
||
| 481 | public static function getLogsCount($cacheId) |
||
| 482 | { |
||
| 483 | //prepare the logs |
||
| 484 | $rsLogs = sql("SELECT COUNT(*) FROM `cache_logs` WHERE `cache_id`='&1'", $cacheId); |
||
| 485 | $rLog = sql_fetch_assoc($rsLogs); |
||
| 486 | sql_free_result($rsLogs); |
||
| 487 | |||
| 488 | return $rLog; |
||
| 489 | } |
||
| 490 | |||
| 491 | /** |
||
| 492 | * @param integer $start |
||
| 493 | * @param integer $count |
||
| 494 | * @param bool $deleted |
||
| 495 | * @param bool $protect_old_coords |
||
| 496 | * @return array |
||
| 497 | */ |
||
| 498 | public function getLogsArray($start, $count, $deleted = false, $protect_old_coords = false) |
||
| 499 | { |
||
| 500 | global $login, $translate; |
||
| 501 | |||
| 502 | // negative or abornally high numbers like 1.0E+15 can crash the LIMIT statement |
||
| 503 | if ($count <= 0 || $count > 10000) { |
||
| 504 | return []; |
||
| 505 | } |
||
| 506 | |||
| 507 | $coords = []; |
||
| 508 | if ($this->getType() != 7 && $this->getType() != 8 && // quiz cache |
||
| 509 | $this->hasAttribute(61) != true && // safari cache |
||
| 510 | $this->getStatus() != 5 // unpublished cache |
||
| 511 | ) { |
||
| 512 | $rsCoords = sql( |
||
| 513 | "SELECT |
||
| 514 | `date_created` `date`, |
||
| 515 | `date_created` - INTERVAL 4 SECOND AS `adjusted_date_created`, |
||
| 516 | /* |
||
| 517 | The first cache_coordinates entry is created immediately after |
||
| 518 | inserting the cache into caches table. This usually takes |
||
| 519 | a few milliseconds. We apply a 4 seconds 'safety margin' for |
||
| 520 | detecting the original coords. In the extremly unlikely case that |
||
| 521 | it took more than 4 seconds AND the owner did a coordinate change |
||
| 522 | before publish AND someone posts a log entry with date inbetween |
||
| 523 | the coord change and the publish, the coords before the change |
||
| 524 | will be exposed (which would be unpleasant but not critical). |
||
| 525 | |||
| 526 | Increasing the 4 seconds lag would increase the chance that |
||
| 527 | original coords which were set immediately before publish are |
||
| 528 | hidden (which would be unpleasant but not critical). |
||
| 529 | |||
| 530 | 4 seconds was chosen as estimated shortest interval someone will |
||
| 531 | need to change coordinates of an unpublished cache AND publish |
||
| 532 | it, minus 1 second. |
||
| 533 | */ |
||
| 534 | `latitude`, |
||
| 535 | `longitude` |
||
| 536 | FROM `cache_coordinates` |
||
| 537 | WHERE `cache_id`='&1' |
||
| 538 | ORDER BY `date_created` DESC", |
||
| 539 | $this->nCacheId |
||
| 540 | ); |
||
| 541 | $publish_date = $this->getDateCreated(); |
||
| 542 | while ($rCoord = sql_fetch_assoc($rsCoords)) { |
||
| 543 | $coords[] = $rCoord; |
||
| 544 | if (strtotime($rCoord['adjusted_date_created']) <= $publish_date) { |
||
| 545 | // This are the cache coords at publish time, which we will |
||
| 546 | // show as "original coords". Older coordinate changes |
||
| 547 | // (before publish) are discarded. |
||
| 548 | break; |
||
| 549 | } |
||
| 550 | } |
||
| 551 | sql_free_result($rsCoords); |
||
| 552 | } |
||
| 553 | |||
| 554 | if ($deleted && ($login->admin && ADMIN_USER) > 0) { |
||
| 555 | // admins may view owner-deleted logs |
||
| 556 | $table = 'cache_logs_archived'; |
||
| 557 | $delfields = 'IFNULL(`u2`.`username`,"") AS `deleted_by_name`, `deletion_date`, "1" AS `deleted`'; |
||
| 558 | $addjoin = 'LEFT JOIN `user` `u2` ON `u2`.`user_id`=`cache_logs`.`deleted_by`'; |
||
| 559 | } else { |
||
| 560 | $table = 'cache_logs'; |
||
| 561 | $delfields = '"" AS `deleted_by_name`, NULL AS `deletion_date`, "0" AS `deleted`'; |
||
| 562 | $addjoin = ''; |
||
| 563 | } |
||
| 564 | |||
| 565 | $rsLogs = sql( |
||
| 566 | "SELECT `cache_logs`.`user_id` AS `userid`, |
||
| 567 | `cache_logs`.`id` AS `id`, |
||
| 568 | `cache_logs`.`uuid` AS `uuid`, |
||
| 569 | `cache_logs`.`date` AS `date`, |
||
| 570 | `cache_logs`.`order_date` AS `order_date`, |
||
| 571 | `cache_logs`.`entry_last_modified`, |
||
| 572 | (`cache_logs`.`node` != 1 OR `cache_logs`.`entry_last_modified` != '2017-02-14 22:49:20') /* see redmine #1109 */ |
||
| 573 | AND DATEDIFF(`cache_logs`.`entry_last_modified`, `cache_logs`.`date_created`) >= 1 AS `late_modified`, |
||
| 574 | substr(`cache_logs`.`date`,12) AS `time`, /* 00:00:01 = 00:00 logged, 00:00:00 = no time */ |
||
| 575 | `cache_logs`.`type` AS `type`, |
||
| 576 | `cache_logs`.`oc_team_comment` AS `oc_team_comment`, |
||
| 577 | `cache_logs`.`needs_maintenance` AS `needs_maintenance`, |
||
| 578 | `cache_logs`.`listing_outdated` AS `listing_outdated`, |
||
| 579 | `cache_logs`.`text` AS `text`, |
||
| 580 | `cache_logs`.`text_html` AS `texthtml`, |
||
| 581 | `cache_logs`.`picture`, |
||
| 582 | " . $delfields . ", |
||
| 583 | `user`.`username` AS `username`, |
||
| 584 | IF(ISNULL(`cache_rating`.`cache_id`), 0, `cache_logs`.`type` IN (1,7)) AS `recommended`, |
||
| 585 | FALSE AS `cache_moved` |
||
| 586 | FROM $table AS `cache_logs` |
||
| 587 | INNER JOIN `user` |
||
| 588 | ON `user`.`user_id` = `cache_logs`.`user_id` |
||
| 589 | LEFT JOIN `cache_rating` |
||
| 590 | ON `cache_logs`.`cache_id`=`cache_rating`.`cache_id` |
||
| 591 | AND `cache_logs`.`user_id`=`cache_rating`.`user_id` |
||
| 592 | AND `cache_logs`.`date`=`cache_rating`.`rating_date` |
||
| 593 | " . $addjoin . " |
||
| 594 | WHERE `cache_logs`.`cache_id`='&1' |
||
| 595 | ORDER BY `cache_logs`.`order_date` DESC, `cache_logs`.`date_created` DESC, `id` DESC |
||
| 596 | LIMIT &2, &3", |
||
| 597 | $this->nCacheId, |
||
| 598 | $start + 0, |
||
| 599 | $count + 0 |
||
| 600 | ); |
||
| 601 | |||
| 602 | $logs = []; |
||
| 603 | $coord_changes = (count($coords) > 1); |
||
| 604 | if ($coord_changes) { |
||
| 605 | $coordpos = 0; |
||
| 606 | $current_coord = new coordinate($coords[0]['latitude'], $coords[0]['longitude']); |
||
| 607 | } |
||
| 608 | $displayed_coord_changes = 0; |
||
| 609 | |||
| 610 | while ($rLog = sql_fetch_assoc($rsLogs)) { |
||
| 611 | $pictures = []; |
||
| 612 | $rsPictures = sql( |
||
| 613 | "SELECT `url`, `title`, `uuid`, `id`, `spoiler` |
||
| 614 | FROM `pictures` |
||
| 615 | WHERE `object_id`='&1' |
||
| 616 | AND `object_type`=1 |
||
| 617 | ORDER BY `seq`", |
||
| 618 | $rLog['id'] |
||
| 619 | ); |
||
| 620 | while ($rPicture = sql_fetch_assoc($rsPictures)) { |
||
| 621 | if (trim($rPicture['title']) == '') { |
||
| 622 | $rPicture['title'] = $translate->t('Picture', '', '', 0) . ' ' . (count($pictures) + 1); |
||
| 623 | } |
||
| 624 | $rPicture['url'] = use_current_protocol($rPicture['url']); |
||
| 625 | $pictures[] = $rPicture; |
||
| 626 | } |
||
| 627 | sql_free_result($rsPictures); |
||
| 628 | $rLog['pictures'] = $pictures; |
||
| 629 | $rLog['text'] = use_current_protocol_in_html($rLog['text']); |
||
| 630 | |||
| 631 | if ($coord_changes) { |
||
| 632 | $newcoord = false; |
||
| 633 | while ($coordpos < count($coords) && $coords[$coordpos]['date'] > $rLog['order_date']) { |
||
| 634 | if (!$newcoord) { |
||
| 635 | $newcoord = new coordinate($coords[$coordpos]['latitude'], $coords[$coordpos]['longitude']); |
||
| 636 | } |
||
| 637 | ++$coordpos; |
||
| 638 | } |
||
| 639 | if ($newcoord) { |
||
| 640 | if ($coordpos < count($coords)) { |
||
| 641 | $distance = geomath::calcDistance( |
||
| 642 | $newcoord->nLat, |
||
| 643 | $newcoord->nLon, |
||
| 644 | $coords[$coordpos]['latitude'], |
||
| 645 | $coords[$coordpos]['longitude'] |
||
| 646 | ); |
||
| 647 | if (abs($distance) > 0.005) { |
||
| 648 | $rLog['newcoord'] = $newcoord->getDecimalMinutes($protect_old_coords && $new != $current_coord); |
||
| 649 | if ($protect_old_coords) { |
||
| 650 | $rLog['movedbykm'] = false; |
||
| 651 | } elseif ($distance <= 1) { |
||
| 652 | $rLog['movedbym'] = floor($distance * 1000); |
||
| 653 | } elseif ($distance < 10) { |
||
| 654 | $rLog['movedbykm'] = sprintf('%1.1f', $distance); |
||
| 655 | } else { |
||
| 656 | $rLog['movedbykm'] = round($distance); |
||
| 657 | } |
||
| 658 | $rLog['cache_moved'] = true; |
||
| 659 | ++$displayed_coord_changes; |
||
| 660 | } |
||
| 661 | } else { |
||
| 662 | // This is the original coord of the cache. |
||
| 663 | $rLog['newcoord'] = $newcoord->getDecimalMinutes($protect_old_coords); |
||
| 664 | $rLog['cache_moved'] = false; |
||
| 665 | } |
||
| 666 | } |
||
| 667 | } |
||
| 668 | |||
| 669 | $logs[] = $rLog; |
||
| 670 | } |
||
| 671 | sql_free_result($rsLogs); |
||
| 672 | |||
| 673 | // Append a dummy log entry for the original coordinate, if it was |
||
| 674 | // not added to a a real log entry because there are logs older than the |
||
| 675 | // OC cache listing (cmp. https://redmine.opencaching.de/issues/1102): |
||
| 676 | |||
| 677 | if ($displayed_coord_changes > 0 && $coordpos < count($coords) && count($logs) > 0) { |
||
| 678 | $coord = new coordinate($coords[$coordpos]['latitude'], $coords[$coordpos]['longitude']); |
||
| 679 | $logs[] = [ |
||
| 680 | 'newcoord' => $coord->getDecimalMinutes($protect_old_coords), |
||
| 681 | 'cache_moved' => false, |
||
| 682 | 'type' => false |
||
| 683 | ]; |
||
| 684 | } |
||
| 685 | |||
| 686 | return $logs; |
||
| 687 | } |
||
| 688 | |||
| 689 | /** |
||
| 690 | * @param $userId |
||
| 691 | * @param $reportReason |
||
| 692 | * @param $reportNote |
||
| 693 | * @return bool |
||
| 694 | */ |
||
| 695 | public function report($userId, $reportReason, $reportNote) |
||
| 696 | { |
||
| 697 | sql( |
||
| 698 | "INSERT INTO cache_reports (`cacheid`, `userid`, `reason`, `note`) |
||
| 699 | VALUES(&1, &2, &3, '&4')", |
||
| 700 | $this->nCacheId, |
||
| 701 | $userId, |
||
| 702 | $reportReason, |
||
| 703 | $reportNote |
||
| 704 | ); |
||
| 705 | |||
| 706 | return true; |
||
| 707 | } |
||
| 708 | |||
| 709 | /** |
||
| 710 | * @param $userId |
||
| 711 | * @return bool|string |
||
| 712 | */ |
||
| 713 | public function addAdoption($userId) |
||
| 714 | { |
||
| 715 | if ($this->allowEdit() == false) { |
||
| 716 | return "noaccess"; |
||
| 717 | } |
||
| 718 | |||
| 719 | if (sql_value("SELECT COUNT(*) FROM `user` WHERE `user_id`='&1'", 0, $userId) == 0) { |
||
| 720 | return "userunknown"; |
||
| 721 | } |
||
| 722 | |||
| 723 | if (sql_value("SELECT COUNT(*) FROM `user` WHERE `user_id`='&1' AND `is_active_flag`=1", 0, $userId) == 0) { |
||
| 724 | return "userdisabled"; |
||
| 725 | } |
||
| 726 | |||
| 727 | // same user? |
||
| 728 | if ($this->getUserId() == $userId) { |
||
| 729 | return "self"; |
||
| 730 | } |
||
| 731 | |||
| 732 | sql( |
||
| 733 | "INSERT IGNORE INTO `cache_adoption` (`cache_id`, `user_id`) |
||
| 734 | VALUES ('&1', '&2')", |
||
| 735 | $this->nCacheId, |
||
| 736 | $userId |
||
| 737 | ); |
||
| 738 | |||
| 739 | return true; |
||
| 740 | } |
||
| 741 | |||
| 742 | /** |
||
| 743 | * @param int $userId |
||
| 744 | * @return bool |
||
| 745 | */ |
||
| 746 | public function cancelAdoption($userId) |
||
| 747 | { |
||
| 748 | global $login; |
||
| 749 | |||
| 750 | if ($this->allowEdit() == false && $login->userid != $userId) { |
||
| 751 | return false; |
||
| 752 | } |
||
| 753 | |||
| 754 | sql( |
||
| 755 | "DELETE FROM `cache_adoption` |
||
| 756 | WHERE `user_id`='&1' |
||
| 757 | AND `cache_id`='&2'", |
||
| 758 | $userId, |
||
| 759 | $this->nCacheId |
||
| 760 | ); |
||
| 761 | |||
| 762 | return true; |
||
| 763 | } |
||
| 764 | |||
| 765 | /** |
||
| 766 | * @param int $userId |
||
| 767 | * @return bool |
||
| 768 | */ |
||
| 769 | public function commitAdoption($userId) |
||
| 770 | { |
||
| 771 | global $login; |
||
| 772 | |||
| 773 | // cache_adoption exists? |
||
| 774 | if (sql_value( |
||
| 775 | "SELECT COUNT(*) FROM `cache_adoption` WHERE `cache_id`='&1' AND `user_id`='&2'", |
||
| 776 | 0, |
||
| 777 | $this->nCacheId, |
||
| 778 | $userId |
||
| 779 | ) == 0 |
||
| 780 | ) { |
||
| 781 | return false; |
||
| 782 | } |
||
| 783 | |||
| 784 | // new user active? |
||
| 785 | if (sql_value("SELECT `is_active_flag` FROM `user` WHERE `user_id`='&1'", 0, $userId) != 1) { |
||
| 786 | return false; |
||
| 787 | } |
||
| 788 | |||
| 789 | sql( |
||
| 790 | "INSERT INTO `logentries` (`module`, `eventid`, `userid`, `objectid1`, `objectid2`, `logtext`) |
||
| 791 | VALUES ('cache', 5, '&1', '&2', '&3', '&4')", |
||
| 792 | $login->userid, |
||
| 793 | $this->nCacheId, |
||
| 794 | 0, |
||
| 795 | 'Cache ' . sql_escape($this->nCacheId) . ' has changed the owner from userid ' . sql_escape( |
||
| 796 | $this->getUserId() |
||
| 797 | ) . ' to ' . sql_escape($userId) . ' by ' . sql_escape($login->userid) |
||
| 798 | ); |
||
| 799 | // Adoptions now are recorded by trigger in cache_adoptions table. |
||
| 800 | // Recording adoptions in 'logentries' may be discarded after ensuring that the |
||
| 801 | // log entries are not used anywhere. |
||
| 802 | sql("UPDATE `caches` SET `user_id`='&1' WHERE `cache_id`='&2'", $userId, $this->nCacheId); |
||
| 803 | sql("DELETE FROM `cache_adoption` WHERE `cache_id`='&1'", $this->nCacheId); |
||
| 804 | |||
| 805 | $this->reCache->setValue('user_id', $userId); |
||
| 806 | |||
| 807 | return true; |
||
| 808 | } |
||
| 809 | |||
| 810 | // checks if $userId has adopted this cache |
||
| 811 | public function hasAdopted($userId) |
||
| 812 | { |
||
| 813 | // cache_adoption exists? |
||
| 814 | return sql_value( |
||
| 815 | "SELECT COUNT(*) |
||
| 816 | FROM `cache_adoption` |
||
| 817 | WHERE `cache_id`='&1' |
||
| 818 | AND `user_id`='&2'", |
||
| 819 | 0, |
||
| 820 | $this->nCacheId, |
||
| 821 | $userId |
||
| 822 | ) != 0; |
||
| 823 | } |
||
| 824 | |||
| 825 | // true if anyone can view the cache |
||
| 826 | public function isPublic() |
||
| 827 | { |
||
| 828 | return (sql_value("SELECT `allow_user_view` FROM `cache_status` WHERE `id`='&1'", 0, $this->getStatus()) == 1); |
||
| 829 | } |
||
| 830 | |||
| 831 | public function allowView() |
||
| 832 | { |
||
| 833 | global $login; |
||
| 834 | |||
| 835 | if ($this->isPublic()) { |
||
| 836 | return true; |
||
| 837 | } |
||
| 838 | |||
| 839 | $login->verify(); |
||
| 840 | |||
| 841 | if (($login->admin & ADMIN_USER) == ADMIN_USER) { |
||
| 842 | return true; |
||
| 843 | } elseif ($this->getUserId() == $login->userid) { |
||
| 844 | return true; |
||
| 845 | } |
||
| 846 | |||
| 847 | return false; |
||
| 848 | } |
||
| 849 | |||
| 850 | View Code Duplication | public function allowEdit() |
|
| 851 | { |
||
| 852 | global $login; |
||
| 853 | |||
| 854 | $login->verify(); |
||
| 855 | if ($this->getUserId() == $login->userid) { |
||
| 856 | return true; |
||
| 857 | } |
||
| 858 | |||
| 859 | return false; |
||
| 860 | } |
||
| 861 | |||
| 862 | public function allowLog() |
||
| 863 | { |
||
| 864 | global $login; |
||
| 865 | |||
| 866 | $login->verify(); |
||
| 867 | if ($this->getUserId() == $login->userid || $login->hasAdminPriv(ADMIN_USER)) { |
||
| 868 | return true; |
||
| 869 | } |
||
| 870 | |||
| 871 | return (sql_value("SELECT `allow_user_log` FROM `cache_status` WHERE `id`='&1'", 0, $this->getStatus()) == 1); |
||
| 872 | } |
||
| 873 | |||
| 874 | public function isRecommendedByUser($nUserId) |
||
| 875 | { |
||
| 876 | return sql_value( |
||
| 877 | "SELECT COUNT(*) FROM `cache_rating` WHERE `cache_id`='&1' AND `user_id`='&2'", |
||
| 878 | 0, |
||
| 879 | $this->nCacheId, |
||
| 880 | $nUserId |
||
| 881 | ) > 0; |
||
| 882 | } |
||
| 883 | |||
| 884 | public function addRecommendation($nUserId, $logdate) |
||
| 885 | { |
||
| 886 | // rating_date will be set to NOW() by Insert-trigger |
||
| 887 | sql( |
||
| 888 | "INSERT IGNORE INTO `cache_rating` (`cache_id`, `user_id`, `rating_date`) VALUES ('&1', '&2', '&3')", |
||
| 889 | $this->nCacheId, |
||
| 890 | $nUserId, |
||
| 891 | $logdate |
||
| 892 | ); |
||
| 893 | } |
||
| 894 | |||
| 895 | public function removeRecommendation($nUserId) |
||
| 896 | { |
||
| 897 | sql("DELETE FROM `cache_rating` WHERE `cache_id`='&1' AND `user_id`='&2'", $this->nCacheId, $nUserId); |
||
| 898 | } |
||
| 899 | |||
| 900 | // retrieves admin cache history data and stores it to template variables |
||
| 901 | // for display by adminhistory.tpl and adminreports.tpl |
||
| 902 | public function setTplHistoryData($exclude_report_id) |
||
| 903 | { |
||
| 904 | global $opt, $tpl; |
||
| 905 | |||
| 906 | // (other) reports for this cache |
||
| 907 | $rs = sql( |
||
| 908 | "SELECT `cr`.`id`, |
||
| 909 | `cr`.`date_created`, |
||
| 910 | `cr`.`lastmodified`, |
||
| 911 | `cr`.`userid`, |
||
| 912 | `cr`.`adminid`, |
||
| 913 | `users`.`username` AS `usernick`, |
||
| 914 | `admins`.`username` AS `adminnick`, |
||
| 915 | IFNULL(`tt`.`text`, `crs`.`name`) AS `status`, |
||
| 916 | IFNULL(`tt2`.`text`, `crr`.`name`) AS `reason` |
||
| 917 | FROM `cache_reports` AS `cr` |
||
| 918 | LEFT JOIN `cache_report_reasons` AS `crr` |
||
| 919 | ON `cr`.`reason`=`crr`.`id` |
||
| 920 | LEFT JOIN `user` AS `users` |
||
| 921 | ON `users`.`user_id`=`cr`.`userid` |
||
| 922 | LEFT JOIN `user` AS `admins` |
||
| 923 | ON `admins`.`user_id`=`cr`.`adminid` |
||
| 924 | LEFT JOIN `cache_report_status` AS `crs` |
||
| 925 | ON `cr`.`status`=`crs`.`id` |
||
| 926 | LEFT JOIN `sys_trans_text` AS `tt` |
||
| 927 | ON `crs`.`trans_id`=`tt`.`trans_id` |
||
| 928 | AND `tt`.`lang`='&2' |
||
| 929 | LEFT JOIN `sys_trans_text` AS `tt2` |
||
| 930 | ON `crr`.`trans_id`=`tt2`.`trans_id` |
||
| 931 | AND `tt2`.`lang`='&2' |
||
| 932 | WHERE `cr`.`cacheid`='&1' |
||
| 933 | AND `cr`.`id`<>'&3' |
||
| 934 | ORDER BY `cr`.`status`,`cr`.`id` DESC", |
||
| 935 | $this->getCacheId(), |
||
| 936 | $opt['template']['locale'], |
||
| 937 | $exclude_report_id |
||
| 938 | ); |
||
| 939 | $tpl->assign_rs('reports', $rs); |
||
| 940 | sql_free_result($rs); |
||
| 941 | |||
| 942 | // user; deleted logs |
||
| 943 | $rs = sql("SELECT * FROM `caches` WHERE `cache_id`='&1'", $this->getCacheId()); |
||
| 944 | $rCache = sql_fetch_array($rs); |
||
| 945 | $tpl->assign('cache', $rCache); |
||
| 946 | sql_free_result($rs); |
||
| 947 | $tpl->assign( |
||
| 948 | 'ownername', |
||
| 949 | sql_value("SELECT `username` FROM `user` WHERE `user_id`='&1'", "", $rCache['user_id']) |
||
| 950 | ); |
||
| 951 | |||
| 952 | $tpl->assign('deleted_logs', $this->getLogsArray(0, 1000, true)); |
||
| 953 | |||
| 954 | // status changes |
||
| 955 | $rs = sql( |
||
| 956 | "SELECT `csm`.`date_modified`, |
||
| 957 | `csm`.`old_state` AS `old_status_id`, |
||
| 958 | `csm`.`new_state` AS `new_status_id`, |
||
| 959 | `user`.`username`, |
||
| 960 | `user`.`user_id`, |
||
| 961 | IFNULL(`stt_old`.`text`,`cs_old`.`name`) AS `old_status`, |
||
| 962 | IFNULL(`stt_new`.`text`,`cs_new`.`name`) AS `new_status` |
||
| 963 | FROM `cache_status_modified` `csm` |
||
| 964 | LEFT JOIN `cache_status` `cs_old` |
||
| 965 | ON `cs_old`.`id`=`csm`.`old_state` |
||
| 966 | LEFT JOIN `sys_trans_text` `stt_old` |
||
| 967 | ON `stt_old`.`trans_id`=`cs_old`.`trans_id` |
||
| 968 | AND `stt_old`.`lang`='&2' |
||
| 969 | LEFT JOIN `cache_status` `cs_new` |
||
| 970 | ON `cs_new`.`id`=`csm`.`new_state` |
||
| 971 | LEFT JOIN `sys_trans_text` `stt_new` |
||
| 972 | ON `stt_new`.`trans_id`=`cs_new`.`trans_id` |
||
| 973 | AND `stt_new`.`lang`='&2' |
||
| 974 | LEFT JOIN `user` |
||
| 975 | ON `user`.`user_id`=`csm`.`user_id` |
||
| 976 | WHERE `cache_id`='&1' |
||
| 977 | ORDER BY `date_modified` DESC", |
||
| 978 | $this->getCacheId(), |
||
| 979 | $opt['template']['locale'] |
||
| 980 | ); |
||
| 981 | $tpl->assign_rs('status_changes', $rs); |
||
| 982 | sql_free_result($rs); |
||
| 983 | |||
| 984 | // coordinate changes |
||
| 985 | $rs = sql( |
||
| 986 | "SELECT `cc`.`date_created`, `cc`.`longitude`, `cc`.`latitude`, |
||
| 987 | IFNULL(`admin`.`user_id`, `owner`.`user_id`) AS `user_id`, |
||
| 988 | IFNULL(`admin`.`username`, `owner`.`username`) AS `username` |
||
| 989 | FROM `cache_coordinates` `cc` |
||
| 990 | LEFT JOIN `caches` ON `caches`.`cache_id`=`cc`.`cache_id` |
||
| 991 | LEFT JOIN `user` `owner` ON `owner`.`user_id`=`caches`.`user_id` |
||
| 992 | LEFT JOIN `user` `admin` ON `admin`.`user_id`=`cc`.`restored_by` |
||
| 993 | WHERE `cc`.`cache_id`='&1' |
||
| 994 | ORDER BY `cc`.`date_created` DESC", |
||
| 995 | $this->getCacheId() |
||
| 996 | ); |
||
| 997 | $coords = []; |
||
| 998 | while ($rCoord = sql_fetch_assoc($rs)) { |
||
| 999 | $coord = new coordinate($rCoord['latitude'], $rCoord['longitude']); |
||
| 1000 | $coords[] = [ |
||
| 1001 | 'date' => $rCoord['date_created'], |
||
| 1002 | 'coord' => $coord->getDecimalMinutes(), |
||
| 1003 | 'user_id' => $rCoord['user_id'], |
||
| 1004 | 'username' => $rCoord['username'] |
||
| 1005 | ]; |
||
| 1006 | } |
||
| 1007 | sql_free_result($rs); |
||
| 1008 | $tpl->assign('coordinates', $coords); |
||
| 1009 | |||
| 1010 | // Adoptions |
||
| 1011 | $rs = sql( |
||
| 1012 | "SELECT `cache_adoptions`.`date`, |
||
| 1013 | `cache_adoptions`.`from_user_id`, |
||
| 1014 | `cache_adoptions`.`to_user_id`, |
||
| 1015 | `from_user`.`username` AS `from_username`, |
||
| 1016 | `to_user`.`username` AS `to_username` |
||
| 1017 | FROM `cache_adoptions` |
||
| 1018 | LEFT JOIN `user` `from_user` ON `from_user`.`user_id`=`from_user_id` |
||
| 1019 | LEFT JOIN `user` `to_user` ON `to_user`.`user_id`=`to_user_id` |
||
| 1020 | WHERE `cache_id`='&1' |
||
| 1021 | ORDER BY `cache_adoptions`.`date`, `cache_adoptions`.`id`", |
||
| 1022 | $this->getCacheId() |
||
| 1023 | ); |
||
| 1024 | $tpl->assign_rs('adoptions', $rs); |
||
| 1025 | sql_free_result($rs); |
||
| 1026 | } |
||
| 1027 | |||
| 1028 | public function logTypeAllowed($logType, $oldLogType = 0) |
||
| 1029 | { |
||
| 1030 | // check if given logType is valid for this cache type |
||
| 1031 | return logtype_ok($this->getCacheId(), $logType, $oldLogType); |
||
| 1032 | } |
||
| 1033 | |||
| 1034 | /** |
||
| 1035 | * @param int $logId |
||
| 1036 | * @param int $oldLogType |
||
| 1037 | * @param int $newLogType |
||
| 1038 | */ |
||
| 1039 | public function updateCacheStatusFromLatestLog($logId, $oldLogType, $newLogType) |
||
| 1100 | |||
| 1101 | // $userLogType: |
||
| 1102 | // Logtype selected by the user, or null if not applicable |
||
| 1103 | |||
| 1104 | public function getUserLogTypes($userLogType, $oldLogType = 0, $statusLogs = true) |
||
| 1105 | { |
||
| 1106 | $logTypes = []; |
||
| 1107 | |||
| 1108 | $logtypeNames = get_logtype_names(); |
||
| 1109 | $allowedLogtypes = get_cache_log_types($this->getCacheId(), $oldLogType, $statusLogs); |
||
| 1110 | $defaultLogType = $userLogType; |
||
| 1111 | if (!logtype_ok($this->getCacheId(), $defaultLogType, $oldLogType, $statusLogs)) { |
||
| 1112 | $defaultLogType = $allowedLogtypes[0]; |
||
| 1113 | } |
||
| 1114 | |||
| 1115 | // prepare array |
||
| 1116 | $i = 0; |
||
| 1117 | foreach ($allowedLogtypes as $logtype) { |
||
| 1118 | $logTypes[$i]['selected'] = ($logtype == $defaultLogType) ? true : false; |
||
| 1119 | $logTypes[$i]['name'] = $logtypeNames[$logtype]; |
||
| 1120 | $logTypes[$i]['id'] = $logtype; |
||
| 1121 | $i++; |
||
| 1122 | } |
||
| 1123 | |||
| 1124 | // return |
||
| 1125 | return $logTypes; |
||
| 1126 | } |
||
| 1127 | |||
| 1128 | public function teamcommentAllowed($logType, $oldTeamComment = false) |
||
| 1129 | { |
||
| 1130 | // checks if teamcomment is allowed |
||
| 1131 | return teamcomment_allowed($this->getCacheId(), $logType, $oldTeamComment); |
||
| 1132 | } |
||
| 1133 | |||
| 1134 | public function statusUserLogAllowed() |
||
| 1135 | { |
||
| 1136 | return sql_value( |
||
| 1137 | "SELECT `cache_status`.`allow_user_log` |
||
| 1138 | FROM `cache_status`,`caches` |
||
| 1139 | WHERE `caches`.`status`=`cache_status`.`id` |
||
| 1140 | AND `caches`.`cache_id`='&1'", |
||
| 1141 | 0, |
||
| 1142 | $this->getCacheId() |
||
| 1143 | ) == 1; |
||
| 1144 | } |
||
| 1145 | |||
| 1146 | /** |
||
| 1147 | * @param $logId |
||
| 1148 | * @return bool |
||
| 1149 | */ |
||
| 1150 | public function statusChangeAllowedForLog($logId) |
||
| 1163 | } |
||
| 1164 |
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.