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 COMMENTLIST 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 COMMENTLIST, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 30 | class COMMENTLIST { |
||
|
|
|||
| 31 | |||
| 32 | public function __construct() { |
||
| 33 | global $this_page; |
||
| 34 | |||
| 35 | $this->db = new ParlDB; |
||
| 36 | |||
| 37 | // We use this to create permalinks to comments. For the moment we're |
||
| 38 | // assuming they're on the same page we're currently looking at: |
||
| 39 | // debate, wran, etc. |
||
| 40 | $this->page = $this_page; |
||
| 41 | |||
| 42 | } |
||
| 43 | |||
| 44 | |||
| 45 | public function display ($view, $args=array(), $format='html') { |
||
| 46 | // $view is what we're viewing by: |
||
| 47 | // 'ep' is all the comments attached to an epobject. |
||
| 48 | // 'user' is all the comments written by a user. |
||
| 49 | // 'recent' is the most recent comments. |
||
| 50 | |||
| 51 | // $args is an associative array of stuff like |
||
| 52 | // 'epobject_id' => '37' |
||
| 53 | // Where 'epobject_id' is an epobject_id. |
||
| 54 | // Or 'gid' is a hansard item gid. |
||
| 55 | |||
| 56 | // Replace a hansard object gid with an epobject_id. |
||
| 57 | // $args = $this->_fix_gid($args); |
||
| 58 | |||
| 59 | // $format is the format the data should be rendered in. |
||
| 60 | |||
| 61 | if ($view == 'ep' || $view == 'user' || $view == 'recent' || $view == 'search' || $view == 'dates') { |
||
| 62 | // What function do we call for this view? |
||
| 63 | $function = '_get_data_by_'.$view; |
||
| 64 | // Get all the dta that's to be rendered. |
||
| 65 | $data = $this->$function($args); |
||
| 66 | |||
| 67 | } else { |
||
| 68 | // Don't have a valid $view; |
||
| 69 | $PAGE->error_message ("You haven't specified a view type."); |
||
| 70 | return false; |
||
| 71 | } |
||
| 72 | |||
| 73 | if ($view == 'user') { |
||
| 74 | $template = 'comments_user'; |
||
| 75 | } elseif ($view == 'recent' or $view == 'dates') { |
||
| 76 | $template = 'comments_recent'; |
||
| 77 | } elseif ($view == 'search') { |
||
| 78 | $template = 'comments_search'; |
||
| 79 | } else { |
||
| 80 | $template = 'comments'; |
||
| 81 | } |
||
| 82 | |||
| 83 | $this->render($data, $format, $template); |
||
| 84 | |||
| 85 | return true; |
||
| 86 | } |
||
| 87 | |||
| 88 | public function render($data, $format='html', $template='comments') { |
||
| 89 | include (INCLUDESPATH."easyparliament/templates/$format/$template.php"); |
||
|
1 ignored issue
–
show
|
|||
| 90 | } |
||
| 91 | |||
| 92 | public function _get_data_by_ep($args) { |
||
| 93 | // Get all the data attached to an epobject. |
||
| 94 | global $PAGE; |
||
| 95 | |||
| 96 | twfy_debug (get_class($this), "getting data by epobject"); |
||
| 97 | |||
| 98 | // What we return. |
||
| 99 | $data = array(); |
||
| 100 | if (!is_numeric($args['epobject_id'])) { |
||
| 101 | $PAGE->error_message ("Sorry, we don't have a valid epobject id"); |
||
| 102 | return $data; |
||
| 103 | } |
||
| 104 | |||
| 105 | // For getting the data. |
||
| 106 | $input = array ( |
||
| 107 | 'amount' => array ( |
||
| 108 | 'user' => true |
||
| 109 | ), |
||
| 110 | 'where' => array ( |
||
| 111 | 'comments.epobject_id=' => $args['epobject_id'], |
||
| 112 | #'visible=' => '1' |
||
| 113 | ), |
||
| 114 | 'order' => 'posted ASC' |
||
| 115 | ); |
||
| 116 | |||
| 117 | $commentsdata = $this->_get_comment_data($input); |
||
| 118 | |||
| 119 | $data['comments'] = $commentsdata; |
||
| 120 | |||
| 121 | if (isset($args['user_id']) && $args['user_id'] != '') { |
||
| 122 | // We'll pass this on to the template so it can highlight the user's comments. |
||
| 123 | $data['info']['user_id'] = $args['user_id']; |
||
| 124 | } |
||
| 125 | |||
| 126 | return $data; |
||
| 127 | |||
| 128 | } |
||
| 129 | |||
| 130 | |||
| 131 | |||
| 132 | public function _get_data_by_user($args) { |
||
| 255 | |||
| 256 | } |
||
| 257 | |||
| 258 | |||
| 259 | |||
| 260 | public function _get_data_by_recent($args) { |
||
| 317 | } |
||
| 318 | |||
| 319 | public function _get_data_by_dates($args) { |
||
| 320 | // $args should contain start_date and end_date |
||
| 321 | |||
| 322 | twfy_debug (get_class($this), "getting data by recent"); |
||
| 323 | $data = array(); |
||
| 324 | $where = array( |
||
| 325 | 'visible=' => '1', |
||
| 326 | 'date(posted)>=' => $args['start_date'], |
||
| 327 | 'date(posted)<=' => $args['end_date'] |
||
| 328 | ); |
||
| 329 | $input = array ( |
||
| 330 | 'amount' => array ( |
||
| 331 | 'user' => true |
||
| 332 | ), |
||
| 333 | 'where' => $where, |
||
| 334 | 'order' => 'posted DESC' |
||
| 335 | ); |
||
| 336 | $commentsdata = $this->_get_comment_data($input); |
||
| 337 | $data['comments'] = $commentsdata; |
||
| 338 | return $data; |
||
| 339 | } |
||
| 340 | |||
| 341 | public function _get_data_by_search($args) { |
||
| 342 | // $args should contain 'num', indicating how many to get. |
||
| 343 | |||
| 344 | twfy_debug (get_class($this), "getting data by search"); |
||
| 345 | |||
| 346 | // What we return. |
||
| 347 | $data = array(); |
||
| 348 | |||
| 349 | if (isset($args['num']) && is_numeric($args['num'])) { |
||
| 350 | $num = $args['num']; |
||
| 351 | } else { |
||
| 352 | $num = 10; |
||
| 353 | } |
||
| 354 | |||
| 355 | if (isset($args['page']) && is_numeric($args['page'])) { |
||
| 356 | $page = $args['page']; |
||
| 357 | } else { |
||
| 358 | $page = 1; |
||
| 359 | } |
||
| 360 | |||
| 361 | $limit = $num*($page-1) . ',' . $num; |
||
| 362 | |||
| 363 | $input = array ( |
||
| 364 | 'amount' => array ( |
||
| 365 | 'user'=> true |
||
| 366 | ), |
||
| 367 | 'where' => array ( |
||
| 368 | 'comments.body LIKE' => "%$args[s]%" |
||
| 369 | ), |
||
| 370 | 'order' => 'posted DESC', |
||
| 371 | 'limit' => $limit |
||
| 372 | ); |
||
| 373 | |||
| 374 | $commentsdata = $this->_get_comment_data($input); |
||
| 375 | |||
| 376 | $data['comments'] = $commentsdata; |
||
| 377 | $data['search'] = $args['s']; |
||
| 378 | # $data['results_per_page'] = $num; |
||
| 379 | # $data['page'] = $page; |
||
| 380 | # $q = $this->db->query('SELECT COUNT(*) AS count FROM comments WHERE visible=1'); |
||
| 381 | # $data['total_results'] = $q->field(0, 'count'); |
||
| 382 | return $data; |
||
| 383 | } |
||
| 384 | |||
| 385 | |||
| 386 | public function _comment_url($urldata) { |
||
| 387 | global $hansardmajors; |
||
| 388 | |||
| 389 | // Pass it the major and gid of the comment's epobject and the comment_id. |
||
| 390 | // And optionally the user's id, for highlighting the comments on the destination page. |
||
| 391 | // It returns the URL for the comment. |
||
| 392 | |||
| 393 | $major = $urldata['major']; |
||
| 394 | $gid = $urldata['gid']; |
||
| 395 | $comment_id = $urldata['comment_id']; |
||
| 396 | $user_id = isset($urldata['user_id']) ? $urldata['user_id'] : false; |
||
| 397 | |||
| 398 | // If you change stuff here, you might have to change it in |
||
| 399 | // $COMMENT->_set_url() too... |
||
| 400 | |||
| 401 | // We'll generate permalinks for each comment. |
||
| 402 | // Assuming every comment is from the same major... |
||
| 403 | $page = $hansardmajors[$major]['page']; |
||
| 404 | |||
| 405 | $URL = new \MySociety\TheyWorkForYou\Url($page); |
||
| 406 | |||
| 407 | $gid = fix_gid_from_db($gid); // In includes/utility.php |
||
| 408 | $URL->insert(array('id' => $gid )); |
||
| 409 | if ($user_id) { |
||
| 410 | $URL->insert(array('u' => $user_id)); |
||
| 411 | } |
||
| 412 | $url = $URL->generate() . '#c' . $comment_id; |
||
| 413 | |||
| 414 | return $url; |
||
| 415 | } |
||
| 416 | |||
| 417 | |||
| 418 | |||
| 419 | /* function _fix_gid($args) { |
||
| 420 | |||
| 421 | // Replace a hansard object gid with an epobject_id. |
||
| 422 | // $args may have a 'gid' element. If so, we replace it |
||
| 423 | // with the hansard object's epobject_id as 'epobject_id', because |
||
| 424 | // comments are tied to epobject_ids. |
||
| 425 | // Returns the corrected $args array. |
||
| 426 | |||
| 427 | global $this_page; |
||
| 428 | |||
| 429 | if (isset($args['gid']) && !isset($args['epobject_id'])) { |
||
| 430 | |||
| 431 | if ($this_page == 'wran' || $this_page == 'wrans') { |
||
| 432 | $gidextra = 'wrans'; |
||
| 433 | } else { |
||
| 434 | $gidextra = 'debate'; |
||
| 435 | } |
||
| 436 | |||
| 437 | $q = $this->db->query ("SELECT epobject_id FROM hansard WHERE gid = 'uk.org.publicwhip/" . $gidextra . '/' . addslashes($args['gid']) . "'"); |
||
| 438 | |||
| 439 | if ($q->rows() > 0) { |
||
| 440 | unset($args['gid']); |
||
| 441 | $args['epobject_id'] = $q->field(0, 'epobject_id'); |
||
| 442 | } |
||
| 443 | } |
||
| 444 | |||
| 445 | return $args; |
||
| 446 | |||
| 447 | } |
||
| 448 | */ |
||
| 449 | |||
| 450 | public function _get_comment_data($input) { |
||
| 595 | |||
| 596 | } |
||
| 597 | |||
| 598 | |||
| 599 | } |
||
| 600 |
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.