| Total Complexity | 70 | 
| Total Lines | 505 | 
| Duplicated Lines | 0 % | 
| Changes | 0 | ||
Complex classes like Divisions 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.
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 Divisions, and based on these observations, apply Extract Interface, too.
| 1 | <?php | ||
| 10 | class Divisions { | ||
| 11 | |||
| 12 | /** | ||
| 13 | * Member | ||
| 14 | */ | ||
| 15 | |||
| 16 | private $member; | ||
| 17 | |||
| 18 | /** | ||
| 19 | * DB handle | ||
| 20 | */ | ||
| 21 | private $db; | ||
| 22 | |||
| 23 | private $positions; | ||
| 24 | private $policies; | ||
| 25 | |||
| 26 | /** | ||
| 27 | * Constructor | ||
| 28 | * | ||
| 29 | * @param Member $member The member to get positions for. | ||
| 30 | */ | ||
| 31 | |||
| 32 | public function __construct(Member $member = NULL, PolicyPositions $positions = NULL, Policies $policies = NULL) | ||
| 33 |     { | ||
| 34 | $this->member = $member; | ||
| 35 | $this->positions = $positions; | ||
| 36 | $this->policies = $policies; | ||
| 37 | $this->db = new \ParlDB; | ||
| 38 | } | ||
| 39 | |||
| 40 |     public static function getMostRecentDivisionDate() { | ||
| 41 | $db = new \ParlDB; | ||
| 42 | $q = $db->query( | ||
| 43 | "SELECT policy_id, max(division_date) as recent from policydivisions GROUP BY policy_id" | ||
| 44 | ); | ||
| 45 | |||
| 46 | $policy_maxes = array(); | ||
| 47 | $row_count = $q->rows(); | ||
| 48 |       for ($n = 0; $n < $row_count; $n++) { | ||
| 49 | $policy_maxes[$q->field($n, 'policy_id')] = $q->field( $n, 'recent' ); | ||
| 50 | } | ||
| 51 | $policy_maxes['latest'] = $policy_maxes ? max(array_values($policy_maxes)) : ''; | ||
| 52 | return $policy_maxes; | ||
| 53 | } | ||
| 54 | |||
| 55 |     public function getRecentDivisions($number = 20) { | ||
| 56 | // Grab distinct divisions as sometimes we have the same division for more than one policy | ||
| 57 | // and we don't want to display it twice | ||
| 58 | $q = $this->db->query( | ||
| 59 | "SELECT distinct division_id, division_title, yes_text, no_text, division_date, division_number, gid, direction, majority_vote, | ||
| 60 | yes_total, no_total, absent_total, both_total | ||
| 61 | FROM policydivisions ORDER BY division_date DESC, division_number DESC LIMIT :count", | ||
| 62 | array( | ||
| 63 | ':count' => $number | ||
| 64 | ) | ||
| 65 | ); | ||
| 66 | |||
| 67 | $divisions = array(); | ||
| 68 |         foreach ($q->data as $division) { | ||
| 69 | $divisions[] = $this->getParliamentDivisionDetails($division); | ||
| 70 | } | ||
| 71 | |||
| 72 |         return array('divisions' => $divisions); | ||
| 73 | } | ||
| 74 | |||
| 75 |     public function getRecentDivisionsForPolicies($policies, $number = 20) { | ||
| 76 |         $args = array(':number' => $number); | ||
| 77 | |||
| 78 | $quoted = array(); | ||
| 79 |         foreach ($policies as $policy) { | ||
| 80 | $quoted[] = $this->db->quote($policy); | ||
| 81 | } | ||
| 82 |         $policies_str = implode(',', $quoted); | ||
| 83 | |||
| 84 | $q = $this->db->query( | ||
| 85 | "SELECT division_id, division_title, yes_text, no_text, division_date, division_number, gid, direction, majority_vote, | ||
| 86 | yes_total, no_total, absent_total, both_total | ||
| 87 | FROM policydivisions | ||
| 88 | WHERE policy_id in ($policies_str) | ||
| 89 | GROUP BY division_id | ||
| 90 | ORDER by division_date DESC LIMIT :number", | ||
| 91 | $args | ||
| 92 | ); | ||
| 93 | |||
| 94 | $divisions = array(); | ||
| 95 | $row_count = $q->rows(); | ||
| 96 |         for ($n = 0; $n < $row_count; $n++) { | ||
| 97 | $divisions[] = $this->getParliamentDivisionDetails($q->row($n)); | ||
| 98 | } | ||
| 99 | |||
| 100 | return $divisions; | ||
| 101 | } | ||
| 102 | |||
| 103 | /** | ||
| 104 | * | ||
| 105 | * Get a list of division votes related to a policy | ||
| 106 | * | ||
| 107 | * Returns an array with one key ( the policyID ) containing a hash | ||
| 108 | * with a policy_id key and a divisions key which contains an array | ||
| 109 | * with details of all the divisions. | ||
| 110 | * | ||
| 111 | * Each division is a hash with the following fields: | ||
| 112 | * division_id, date, vote, gid, url, text, strong | ||
| 113 | * | ||
| 114 | * @param $policyId The ID of the policy to get divisions for | ||
|  | |||
| 115 | */ | ||
| 116 | |||
| 117 |     public function getMemberDivisionsForPolicy($policyID = null) { | ||
| 118 | $where_extra = ''; | ||
| 119 |         $args = array(':person_id' => $this->member->person_id); | ||
| 120 |         if ( $policyID ) { | ||
| 121 | $where_extra = 'AND policy_id = :policy_id'; | ||
| 122 | $args[':policy_id'] = $policyID; | ||
| 123 | } | ||
| 124 | $q = $this->db->query( | ||
| 125 | "SELECT policy_id, division_id, division_title, yes_text, no_text, division_date, division_number, vote, gid, direction | ||
| 126 | FROM policydivisions JOIN persondivisionvotes USING(division_id) | ||
| 127 | WHERE person_id = :person_id AND direction <> 'abstention' $where_extra | ||
| 128 | ORDER by policy_id, division_date", | ||
| 129 | $args | ||
| 130 | ); | ||
| 131 | |||
| 132 | return $this->divisionsByPolicy($q); | ||
| 133 | } | ||
| 134 | |||
| 135 |     public function getMemberDivisionDetails() { | ||
| 136 |         $args = array(':person_id' => $this->member->person_id); | ||
| 137 | |||
| 138 | $policy_divisions = array(); | ||
| 139 | |||
| 140 | $q = $this->db->query( | ||
| 141 | "SELECT policy_id, policy_vote, vote, count(division_id) as total, | ||
| 142 | max(year(division_date)) as latest, min(year(division_date)) as earliest | ||
| 143 | FROM policydivisions JOIN persondivisionvotes USING(division_id) | ||
| 144 | WHERE person_id = :person_id AND direction <> 'abstention' | ||
| 145 | GROUP BY policy_id, policy_vote, vote", | ||
| 146 | $args | ||
| 147 | ); | ||
| 148 | |||
| 149 | $row_count = $q->rows(); | ||
| 150 |         for ($n = 0; $n < $row_count; $n++) { | ||
| 151 | $policy_id = $q->field($n, 'policy_id'); | ||
| 152 | |||
| 153 |           if (!array_key_exists($policy_id, $policy_divisions)) { | ||
| 154 | $summary = array( | ||
| 155 | 'max' => $q->field($n, 'latest'), | ||
| 156 | 'min' => $q->field($n, 'earliest'), | ||
| 157 | 'total' => $q->field($n, 'total'), | ||
| 158 | 'for' => 0, 'against' => 0, 'absent' => 0, 'both' => 0, 'tell' => 0 | ||
| 159 | ); | ||
| 160 | |||
| 161 | $policy_divisions[$policy_id] = $summary; | ||
| 162 | } | ||
| 163 | |||
| 164 | $summary = $policy_divisions[$policy_id]; | ||
| 165 | |||
| 166 | $summary['total'] += $q->field($n, 'total'); | ||
| 167 |           if ($summary['max'] < $q->field($n, 'latest')) { | ||
| 168 | $summary['max'] = $q->field($n, 'latest'); | ||
| 169 | } | ||
| 170 |           if ($summary['min'] > $q->field($n, 'latest')) { | ||
| 171 | $summary['min'] = $q->field($n, 'latest'); | ||
| 172 | } | ||
| 173 | |||
| 174 | $vote = $q->field($n, 'vote'); | ||
| 175 |           $policy_vote = str_replace('3', '', $q->field($n, 'policy_vote')); | ||
| 176 |           if ( $vote == 'absent' ) { | ||
| 177 | $summary['absent'] += $q->field($n, 'total'); | ||
| 178 |           } else if ( $vote == 'both' ) { | ||
| 179 | $summary['both'] += $q->field($n, 'total'); | ||
| 180 |           } else if ( strpos($vote, 'tell') !== FALSE ) { | ||
| 181 | $summary['tell'] += $q->field($n, 'total'); | ||
| 182 |           } else if ( $policy_vote == $vote ) { | ||
| 183 | $summary['for'] += $q->field($n, 'total'); | ||
| 184 |           } else if ( $policy_vote != $vote ) { | ||
| 185 | $summary['against'] += $q->field($n, 'total'); | ||
| 186 | } | ||
| 187 | |||
| 188 | $policy_divisions[$policy_id] = $summary; | ||
| 189 | } | ||
| 190 | |||
| 191 | return $policy_divisions; | ||
| 192 | } | ||
| 193 | |||
| 194 |     public function getDivisionResults($division_id) { | ||
| 195 | $args = array( | ||
| 196 | ':division_id' => $division_id | ||
| 197 | ); | ||
| 198 | $q = $this->db->query( | ||
| 199 | "SELECT division_id, division_title, yes_text, no_text, division_date, division_number, gid, direction, | ||
| 200 | yes_total, no_total, absent_total, both_total, majority_vote | ||
| 201 | FROM policydivisions | ||
| 202 | WHERE division_id = :division_id", | ||
| 203 | $args | ||
| 204 | ); | ||
| 205 | |||
| 206 |         if ($q->rows == 0) { | ||
| 207 | return false; | ||
| 208 | } | ||
| 209 | |||
| 210 | $details = $this->getParliamentDivisionDetails($q->row(0)); | ||
| 211 | $details['division_title'] = $q->row(0)['division_title']; | ||
| 212 | |||
| 213 | $q = $this->db->query( | ||
| 214 | "SELECT person_id, vote, given_name, family_name | ||
| 215 | FROM persondivisionvotes JOIN person_names USING(person_id) | ||
| 216 | WHERE division_id = :division_id | ||
| 217 | ORDER by family_name", | ||
| 218 | $args | ||
| 219 | ); | ||
| 220 | |||
| 221 | $votes = array( | ||
| 222 | 'yes_votes' => array(), | ||
| 223 | 'no_votes' => array(), | ||
| 224 | 'absent_votes' => array(), | ||
| 225 | 'both_votes' => array() | ||
| 226 | ); | ||
| 227 | |||
| 228 |         foreach ($q->data as $vote) { | ||
| 229 | $detail = array( | ||
| 230 | 'person_id' => $vote['person_id'], | ||
| 231 | 'name' => $vote['given_name'] . ' ' . $vote['family_name'], | ||
| 232 | 'teller' => false | ||
| 233 | ); | ||
| 234 | |||
| 235 |             if (strpos($vote['vote'], 'tell') !== FALSE) { | ||
| 236 | $detail['teller'] = true; | ||
| 237 | } | ||
| 238 | |||
| 239 |             if ($vote['vote'] == 'aye' or $vote['vote'] == 'tellaye') { | ||
| 240 | $votes['yes_votes'][] = $detail; | ||
| 241 |             } else if ($vote['vote'] == 'no' or $vote['vote'] == 'tellno') { | ||
| 242 | $votes['no_votes'][] = $detail; | ||
| 243 |             } else if ($vote['vote'] == 'absent') { | ||
| 244 | $votes['absent_votes'][] = $detail; | ||
| 245 |             } else if ($vote['vote'] == 'both') { | ||
| 246 | $votes['both_votes'][] = $detail; | ||
| 247 | } | ||
| 248 | |||
| 249 | } | ||
| 250 | |||
| 251 | $details = array_merge($details, $votes); | ||
| 252 | |||
| 253 | return $details; | ||
| 254 | } | ||
| 255 | |||
| 256 |     public function getDivisionResultsForMember($division_id, $person_id) { | ||
| 257 | $args = array( | ||
| 258 | ':division_id' => $division_id, | ||
| 259 | ':person_id' => $person_id | ||
| 260 | ); | ||
| 261 | $q = $this->db->query( | ||
| 262 | "SELECT division_id, division_title, yes_text, no_text, division_date, division_number, gid, direction, vote | ||
| 263 | FROM policydivisions JOIN persondivisionvotes USING(division_id) | ||
| 264 | WHERE division_id = :division_id AND person_id = :person_id", | ||
| 265 | $args | ||
| 266 | ); | ||
| 267 | |||
| 268 | // if the vote was before or after the MP was in Parliament | ||
| 269 | // then there won't be a row | ||
| 270 |         if ($q->rows == 0) { | ||
| 271 | return false; | ||
| 272 | } | ||
| 273 | |||
| 274 | $details = $this->getDivisionDetails($q->row(0)); | ||
| 275 | return $details; | ||
| 276 | } | ||
| 277 | |||
| 278 |     public function generateSummary($votes) { | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | /** | ||
| 301 | * | ||
| 302 | * Get all the divisions a member has voted in keyed by policy | ||
| 303 | * | ||
| 304 | * Returns an array with keys for each policyID, each of these contains | ||
| 305 | * the same structure as getMemberDivisionsForPolicy | ||
| 306 | * | ||
| 307 | */ | ||
| 308 | |||
| 309 |     public function getAllMemberDivisionsByPolicy() { | ||
| 310 | return $this->getMemberDivisionsForPolicy(); | ||
| 311 | } | ||
| 312 | |||
| 313 | |||
| 314 | /** | ||
| 315 | * Get the last n votes for a member | ||
| 316 | * | ||
| 317 | * @param $number int - How many divisions to return. Defaults to 20 | ||
| 318 | * @param $context string - The context of the page the results are being presented in. | ||
| 319 | * This affects the summary details and can either be 'Parliament' in which case the | ||
| 320 | * overall vote for all MPs is returned, plus additional information on how the MP passed | ||
| 321 | * in to the constructor voted, or the default of 'MP' which is just the vote of the | ||
| 322 | * MP passed in to the constructor. | ||
| 323 | * | ||
| 324 | * Returns an array of divisions | ||
| 325 | */ | ||
| 326 |     public function getRecentMemberDivisions($number = 20, $context = 'MP') { | ||
| 327 |         $args = array(':person_id' => $this->member->person_id, ':number' => $number); | ||
| 328 | $q = $this->db->query( | ||
| 329 | "SELECT division_id, division_title, yes_text, no_text, division_date, division_number, vote, gid, direction, | ||
| 330 | yes_total, no_total, absent_total, both_total, majority_vote | ||
| 331 | FROM policydivisions JOIN persondivisionvotes USING(division_id) | ||
| 332 | WHERE person_id = :person_id | ||
| 333 | GROUP BY division_id | ||
| 334 | ORDER by division_date DESC, division_id DESC LIMIT :number", | ||
| 335 | $args | ||
| 336 | ); | ||
| 337 | |||
| 338 | $divisions = array(); | ||
| 339 | $row_count = $q->rows(); | ||
| 340 |         for ($n = 0; $n < $row_count; $n++) { | ||
| 341 |           if ($context == 'Parliament') { | ||
| 342 | $divisions[] = $this->getParliamentDivisionDetails($q->row($n)); | ||
| 343 |           } else { | ||
| 344 | $divisions[] = $this->getDivisionDetails($q->row($n)); | ||
| 345 | } | ||
| 346 | } | ||
| 347 | |||
| 348 | return $divisions; | ||
| 349 | } | ||
| 350 | |||
| 351 | |||
| 352 |     private function constructYesNoVoteDescription($direction, $title, $short_text) { | ||
| 353 | $text = ' voted '; | ||
| 354 |         if ( $short_text ) { | ||
| 355 | $text .= $short_text; | ||
| 356 |         } else { | ||
| 357 | $text .= "$direction on <em>$title</em>"; | ||
| 358 | } | ||
| 359 | |||
| 360 | return $text; | ||
| 361 | } | ||
| 362 | |||
| 363 | |||
| 364 |     private function constructVoteDescription($vote, $yes_text, $no_text, $division_title) { | ||
| 365 | /* | ||
| 366 | * for most post 2010 votes we have nice single sentence summaries of | ||
| 367 | * what voting for or against means so we use that if it's there, however | ||
| 368 | * we don't have anything nice for people being absent or for pre 2010 | ||
| 369 | * votes so we need to generate some text using the title of the division | ||
| 370 | */ | ||
| 371 | |||
| 372 |         switch ( strtolower($vote) ) { | ||
| 373 | case 'yes': | ||
| 374 | case 'aye': | ||
| 375 |                 $description = $this->constructYesNoVoteDescription('yes', $division_title, $yes_text); | ||
| 376 | break; | ||
| 377 | case 'no': | ||
| 378 |                 $description = $this->constructYesNoVoteDescription('no', $division_title, $no_text); | ||
| 379 | break; | ||
| 380 | case 'absent': | ||
| 381 | $description = ' was absent for a vote on <em>' . $division_title . '</em>'; | ||
| 382 | break; | ||
| 383 | case 'both': | ||
| 384 | $description = ' abstained on a vote on <em>' . $division_title . '</em>'; | ||
| 385 | break; | ||
| 386 | case 'tellyes': | ||
| 387 | case 'tellno': | ||
| 388 | case 'tellaye': | ||
| 389 | $description = ' acted as teller for a vote on <em>' . $division_title . '</em>'; | ||
| 390 | break; | ||
| 391 | default: | ||
| 392 | $description = $division_title; | ||
| 393 | } | ||
| 394 | |||
| 395 | return $description; | ||
| 396 | } | ||
| 397 | |||
| 398 |     private function getBasicDivisionDetails($row, $vote) { | ||
| 430 | } | ||
| 431 | |||
| 432 |     private function getDivisionDetails($row) { | ||
| 433 | $vote = $row['vote']; | ||
| 434 | $division = $this->getBasicDivisionDetails($row, $vote); | ||
| 435 | |||
| 436 | $division['vote'] = $vote; | ||
| 437 | |||
| 438 | return $division; | ||
| 439 | } | ||
| 440 | |||
| 441 |     private function getParliamentDivisionDetails($row) { | ||
| 465 | } | ||
| 466 | |||
| 467 |     private function divisionsByPolicy($q) { | ||
| 468 | $policies = array(); | ||
| 469 | |||
| 470 | $row_count = $q->rows(); | ||
| 471 |         for ($n = 0; $n < $row_count; $n++) { | ||
| 472 | $policy_id = $q->field($n, 'policy_id'); | ||
| 473 | |||
| 474 |             if ( !array_key_exists($policy_id, $policies) ) { | ||
| 475 | $policies[$policy_id] = array( | ||
| 476 | 'policy_id' => $policy_id, | ||
| 477 | 'weak_count' => 0, | ||
| 478 | 'divisions' => array() | ||
| 479 | ); | ||
| 480 |                 if ( $this->policies ) { | ||
| 481 | $policies[$policy_id]['desc'] = $this->policies->getPolicies()[$policy_id]; | ||
| 482 | $policies[$policy_id]['header'] = $this->policies->getPolicyDetails($policy_id); | ||
| 483 | } | ||
| 484 |                 if ( $this->positions ) { | ||
| 485 | $policies[$policy_id]['position'] = $this->positions->positionsById[$policy_id]; | ||
| 486 | } | ||
| 487 | } | ||
| 488 | |||
| 489 | $division = $this->getDivisionDetails($q->row($n)); | ||
| 490 | |||
| 491 |             if ( !$division['strong'] ) { | ||
| 492 | $policies[$policy_id]['weak_count']++; | ||
| 493 | } | ||
| 494 | |||
| 495 | $policies[$policy_id]['divisions'][] = $division; | ||
| 496 | }; | ||
| 497 | |||
| 498 | return $policies; | ||
| 499 | } | ||
| 500 | |||
| 501 |     private function divisionUrlFromGid($gid) { | ||
| 515 | } | ||
| 516 | } | ||
| 517 | 
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths