| Total Complexity | 324 | 
| Total Lines | 2531 | 
| Duplicated Lines | 0 % | 
| Coverage | 43.4% | 
| Changes | 0 | ||
Complex classes like HANSARDLIST 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 HANSARDLIST, and based on these observations, apply Extract Interface, too.
| 1 | <?php | ||
| 53 | class HANSARDLIST { | ||
| 54 | // This will be used to cache information about speakers on this page | ||
| 55 | // so we don't have to keep fetching the same data from the DB. | ||
| 56 | public $speakers = array (); | ||
| 57 | /* | ||
| 58 | $this->speakers[ $person_id ] = array ( | ||
| 59 | "name" => $name, | ||
| 60 | "constituency" => $constituency, | ||
| 61 | "party" => $party, | ||
| 62 | "person_id" => $person_id, | ||
| 63 | "url" => "/member/?p=$person_id" | ||
| 64 | ); | ||
| 65 | */ | ||
| 66 | |||
| 67 | // This will be used to cache mappings from epobject_id to gid, | ||
| 68 | // so we don't have to continually fetch the same data in get_hansard_data(). | ||
| 69 | public $epobjectid_to_gid = array (); | ||
| 70 | /* | ||
| 71 | $this->epobjectid_to_gid[ $epobject_id ] => $gid; | ||
| 72 | */ | ||
| 73 | |||
| 74 | # Similarly, cache bill lookups | ||
| 75 | public $bill_lookup = array(); | ||
| 76 | |||
| 77 | // This is so we can tell what type of thing we're displaying from outside | ||
| 78 | // the object. eg, so we know if we should be able to post comments to the | ||
| 79 | // item. It will have a value set if we are displaying by 'gid' (not 'date'). | ||
| 80 | // Use htype() to access it. | ||
| 81 | public $htype; | ||
| 82 | |||
| 83 | |||
| 84 | // Reset to the relevant major ID in DEBATELIST or WRANSLIST | ||
| 85 | public $major; | ||
| 86 | |||
| 87 | |||
| 88 | // When we view a particular item, we set these to the epobject_id and gid | ||
| 89 | // of the item so we can attach Trackbacks etc to it from outside. | ||
| 90 | public $epobject_id; | ||
| 91 | public $gid; | ||
| 92 | |||
| 93 | |||
| 94 | // This will be set if $this->most_recent_day() is called. Just so we | ||
| 95 | // don't need to call it and it's lengthy query again. | ||
| 96 | public $most_recent_day; | ||
| 97 | |||
| 98 | // This prefix is used to pick out unique things by type | ||
| 99 | public $gidprefix; | ||
| 100 | |||
| 101 | // These are used to specify the pages for each subclass | ||
| 102 | public $listpage; | ||
| 103 | public $commentspage; | ||
| 104 | |||
| 105 | # Only used by StandingCommittee subclass | ||
| 106 | public $bill_title; | ||
| 107 | public $url; | ||
| 108 | |||
| 109 | public $db; | ||
| 110 | |||
| 111 | 6 |     public function __construct() { | |
| 112 | 6 | $this->db = new ParlDB; | |
| 113 | 6 | } | |
| 114 | |||
| 115 | |||
| 116 | |||
| 117 |     public function display ($view, $args=array(), $format='html') { | ||
| 118 | |||
| 119 | // $view is what we're viewing by: | ||
| 120 | // 'gid' is the gid of a hansard object, | ||
| 121 | // 'date' is all items on a date, | ||
| 122 | // 'person' is a person's recent debates/wrans, | ||
| 123 | // 'recent' is a number of recent dates with items in. | ||
| 124 | // 'recent_mostvotes' is the speeches with the most votes in the last x days. | ||
| 125 | // 'search' is all debates/wrans that match a search term. | ||
| 126 | // 'biggest_debates' is biggest recent debates (obviously only for DEBATESLIST). | ||
| 127 | // 'recent_wrans' is some recent written answers (obv only for WRANSLIST). | ||
| 128 | |||
| 129 | // $args is an associative array of stuff like | ||
| 130 | // 'gid' => '2003-10-30.422.4' or | ||
| 131 | // 'd' => '2003-12-31' or | ||
| 132 | // 's' => 'my search term' | ||
| 133 | // 'o' => Sort order: 'r' for relevance, 'd' for date | ||
| 134 | |||
| 135 | // $format is the format the data should be rendered in, | ||
| 136 | // using that set of templates (or 'none' for just returning | ||
| 137 | // the data). | ||
| 138 | |||
| 139 | global $PAGE; | ||
| 140 | |||
| 141 |         if ($view == 'search' && (!defined('FRONT_END_SEARCH') || !FRONT_END_SEARCH)) | ||
| 1 ignored issue–
                            show | |||
| 142 | return false; | ||
| 143 | |||
| 144 |         $validviews = array ('calendar', 'date', 'gid', 'person', 'search', 'search_min', 'search_video', 'recent', 'recent_mostvotes', 'biggest_debates', 'recent_wrans', 'recent_wms', 'column', 'mp', 'bill', 'session', 'recent_debates', 'recent_pbc_debates', 'featured_gid'); | ||
| 145 |         if (in_array($view, $validviews)) { | ||
| 146 | |||
| 147 | // What function do we call for this view? | ||
| 148 | $function = '_get_data_by_'.$view; | ||
| 149 | // Get all the data that's to be rendered. | ||
| 150 | $data = $this->$function($args); | ||
| 151 | |||
| 152 |         } else { | ||
| 153 | // Don't have a valid $view. | ||
| 154 |             $PAGE->error_message ("You haven't specified a view type."); | ||
| 155 | return false; | ||
| 156 | } | ||
| 157 | |||
| 158 | // Set the values of this page's headings depending on the data we've fetched. | ||
| 159 |         if (isset($PAGE) && isset($data['info'])) { | ||
| 160 | $PAGE->set_hansard_headings($data['info']); | ||
| 161 | } | ||
| 162 | |||
| 163 | // Glossary $view_override (to avoid too much code duplication...) | ||
| 164 |         if (isset($args['view_override'])) { | ||
| 165 | $view = $args['view_override']; | ||
| 166 | } | ||
| 167 | |||
| 168 | $return = $this->render($view, $data, $format); | ||
| 169 | |||
| 170 | return $return; | ||
| 171 | } | ||
| 172 | |||
| 173 | |||
| 174 | |||
| 175 |     public function render($view, $data, $format='html') { | ||
| 176 | // Once we have the data that's to be rendered, | ||
| 177 | // include the template. | ||
| 178 | |||
| 179 | // No format, so don't use the template sets. | ||
| 180 |         if ($format == 'none') { | ||
| 181 | return $data; | ||
| 182 | } | ||
| 183 | |||
| 184 | include (INCLUDESPATH."easyparliament/templates/$format/hansard_$view" . ".php"); | ||
| 1 ignored issue–
                            show | |||
| 185 | return true; | ||
| 186 | |||
| 187 | } | ||
| 188 | |||
| 189 | |||
| 190 |     public function total_items() { | ||
| 191 | // Returns number of items in debates or wrans, depending on which class this is, | ||
| 192 | // DEBATELIST or WRANSLIST. | ||
| 193 | |||
| 194 |         $q = $this->db->query("SELECT COUNT(*) AS count FROM hansard WHERE major = :major", array(':major' => $this->major)); | ||
| 195 | |||
| 196 | return $q->field(0, 'count'); | ||
| 197 | } | ||
| 198 | |||
| 199 | |||
| 200 | |||
| 201 | 1 |     public function most_recent_day() { | |
| 202 | // Very simple. Returns an array of stuff about the most recent data | ||
| 203 | // for this major: | ||
| 204 | |||
| 205 | // array ( | ||
| 206 | // 'hdate' => 'YYYY-MM-DD', | ||
| 207 | // 'timestamp' => 124453679, | ||
| 208 | // 'listurl' => '/foo/?id=bar' | ||
| 209 | // ) | ||
| 210 | |||
| 211 | // When we do this function the first time we cache the | ||
| 212 | // results in this variable. As it's an expensive query. | ||
| 213 | 1 |         if (isset($this->most_recent_day)) { | |
| 214 | return $this->most_recent_day; | ||
| 215 | } | ||
| 216 | |||
| 217 | // What we return. | ||
| 218 | 1 | $data = array(); | |
| 219 | |||
| 220 | 1 |         $q = $this->db->query("SELECT MAX(hdate) AS hdate | |
| 221 | FROM hansard | ||
| 222 | WHERE major = :major | ||
| 223 | 1 |                         ", array(':major' => $this->major)); | |
| 224 | 1 |         if ($q->rows() > 0) { | |
| 225 | |||
| 226 | 1 | $hdate = $q->field(0, 'hdate'); | |
| 227 | 1 |             if ($hdate) { | |
| 228 | 1 | $URL = new \MySociety\TheyWorkForYou\Url($this->listpage); | |
| 229 | 1 |                 $URL->insert( array('d'=>$hdate) ); | |
| 230 | |||
| 231 | // Work out a timestamp which is handy for comparing to now. | ||
| 232 | 1 |                 list($year, $month, $date) = explode('-', $hdate); | |
| 233 | 1 | $timestamp = gmmktime (0, 0, 0, $month, $date, $year); | |
| 234 | |||
| 235 | $data = array ( | ||
| 236 | 1 | 'hdate' => $hdate, | |
| 237 | 1 | 'timestamp' => $timestamp, | |
| 238 | 1 | 'listurl' => $URL->generate() | |
| 239 | 1 | ); | |
| 240 | |||
| 241 | // This is just because it's an expensive query | ||
| 242 | // and we really want to avoid doing it more than once. | ||
| 243 | // So we're caching it. | ||
| 244 | 1 | $this->most_recent_day = $data; | |
| 245 | 1 | } | |
| 246 | 1 | } | |
| 247 | |||
| 248 | 1 | return $data; | |
| 249 | } | ||
| 250 | |||
| 251 | |||
| 252 |     public function htype() { | ||
| 253 | return $this->htype; | ||
| 254 | } | ||
| 255 | |||
| 256 |     public function epobject_id() { | ||
| 257 | return $this->epobject_id; | ||
| 258 | } | ||
| 259 | |||
| 260 |     public function gid() { | ||
| 261 | return $this->gid; | ||
| 262 | } | ||
| 263 | |||
| 264 | |||
| 265 | 2 |     public function _get_section($itemdata) { | |
| 266 | // Pass it an array of data about an item and it will return an | ||
| 267 | // array of data about the item's section heading. | ||
| 268 | |||
| 269 | 2 | twfy_debug (get_class($this), "getting an item's section"); | |
| 270 | |||
| 271 | 2 |         if ($itemdata['htype'] != '10') { | |
| 272 | |||
| 273 | // This item is a subsection, speech or procedural, | ||
| 274 | // or a wrans questions/answer, | ||
| 275 | // so get the section info above this item. | ||
| 276 | |||
| 277 | // For getting hansard data. | ||
| 278 | $input = array ( | ||
| 279 | 'amount' => array ( | ||
| 280 | 'body' => true | ||
| 281 | ), | ||
| 282 | 'where' => array ( | ||
| 283 | 'hansard.epobject_id=' => $itemdata['section_id'] | ||
| 284 | ) | ||
| 285 | ); | ||
| 286 | |||
| 287 | $sectiondata = $this->_get_hansard_data($input); | ||
| 288 | |||
| 289 |             if (count($sectiondata) > 0) { | ||
| 290 | $sectiondata = $sectiondata[0]; | ||
| 291 | } | ||
| 292 | |||
| 293 |         } else { | ||
| 294 | // This item *is* a section, so just return that. | ||
| 295 | |||
| 296 | 2 | $sectiondata = $itemdata; | |
| 297 | |||
| 298 | } | ||
| 299 | |||
| 300 | 2 | return $sectiondata; | |
| 301 | } | ||
| 302 | |||
| 303 | |||
| 304 | |||
| 305 | 1 |     public function _get_subsection($itemdata) { | |
| 306 | // Pass it an array of data about an item and it will return an | ||
| 307 | // array of data about the item's subsection heading. | ||
| 308 | |||
| 309 | 1 | twfy_debug (get_class($this), "getting an item's subsection"); | |
| 310 | |||
| 311 | // What we return. | ||
| 312 | 1 | $subsectiondata = array (); | |
| 313 | |||
| 314 | 1 |         if ($itemdata['htype'] == '12' || $itemdata['htype'] == '13') { | |
| 315 | // This item is a speech or procedural, so get the | ||
| 316 | // subsection info above this item. | ||
| 317 | |||
| 318 | // For getting hansard data. | ||
| 319 | $input = array ( | ||
| 320 | 'amount' => array ( | ||
| 321 | 'body' => true | ||
| 322 | ), | ||
| 323 | 'where' => array ( | ||
| 324 | 'hansard.epobject_id=' => $itemdata['subsection_id'] | ||
| 325 | ) | ||
| 326 | ); | ||
| 327 | |||
| 328 | $subsectiondata = $this->_get_hansard_data($input); | ||
| 329 | if (count($subsectiondata) == 0) | ||
| 330 | $subsectiondata = null; | ||
| 331 | else | ||
| 332 | $subsectiondata = $subsectiondata[0]; | ||
| 333 | |||
| 334 | 1 |         } elseif ($itemdata['htype'] == '11') { | |
| 335 | // It's a subsection, so use the item itself. | ||
| 336 | $subsectiondata = $itemdata; | ||
| 337 | } | ||
| 338 | |||
| 339 | 1 | return $subsectiondata; | |
| 340 | } | ||
| 341 | |||
| 342 | |||
| 343 | |||
| 344 | 1 |     public function _get_nextprev_items($itemdata) { | |
| 524 | } | ||
| 525 | |||
| 526 | |||
| 527 | 1 |     public function _get_nextprev_dates($date) { | |
| 528 | 1 | global $hansardmajors; | |
| 529 | // Pass it a yyyy-mm-dd date and it'll return an array | ||
| 530 | // containing the next/prev dates that contain items from | ||
| 531 | // $this->major of hansard object. | ||
| 532 | |||
| 533 | 1 | twfy_debug (get_class($this), "getting next/prev dates"); | |
| 534 | |||
| 535 | // What we return. | ||
| 536 | 1 | $nextprevdata = array (); | |
| 537 | |||
| 538 | 1 | $URL = new \MySociety\TheyWorkForYou\Url($this->listpage); | |
| 539 | |||
| 540 | 1 |         $looper = array ("next", "prev"); | |
| 541 | |||
| 542 | 1 |         foreach ($looper as $n => $nextorprev) { | |
| 543 | |||
| 544 | 1 | $URL->reset(); | |
| 545 | |||
| 546 | 1 |             $params = array(':major' => $this->major, | |
| 547 | 1 | ':date' => $date); | |
| 548 | 1 |             if ($nextorprev == 'next') { | |
| 549 | 1 |                 $q = $this->db->query("SELECT MIN(hdate) AS hdate | |
| 550 | FROM hansard | ||
| 551 | WHERE major = :major | ||
| 552 | 1 | AND hdate > :date", $params); | |
| 553 | 1 |             } else { | |
| 554 | 1 |                 $q = $this->db->query("SELECT MAX(hdate) AS hdate | |
| 555 | FROM hansard | ||
| 556 | WHERE major = :major | ||
| 557 | 1 | AND hdate < :date", $params); | |
| 558 | } | ||
| 559 | |||
| 560 | // The '!= NULL' bit is needed otherwise I was getting errors | ||
| 561 | // when displaying the first day of debates. | ||
| 562 | 1 |             if ($q->rows() > 0 && $q->field(0, 'hdate') != NULL) { | |
| 563 | |||
| 564 | 1 | $URL->insert( array( 'd'=>$q->field(0, 'hdate') ) ); | |
| 565 | |||
| 566 | 1 |                 if ($nextorprev == 'next') { | |
| 567 | 1 | $body = 'Next day'; | |
| 568 | 1 |                 } else { | |
| 569 | $body = 'Previous day'; | ||
| 570 | } | ||
| 571 | |||
| 572 | 1 | $title = format_date($q->field(0, 'hdate'), SHORTDATEFORMAT); | |
| 573 | |||
| 574 | 1 | $nextprevdata[$nextorprev] = array ( | |
| 575 | 1 | 'hdate' => $q->field(0, 'hdate'), | |
| 576 | 1 | 'url' => $URL->generate(), | |
| 577 | 1 | 'body' => $body, | |
| 578 | 'title' => $title | ||
| 579 | 1 | ); | |
| 580 | 1 | } | |
| 581 | 1 | } | |
| 582 | |||
| 583 | 1 | $year = substr($date, 0, 4); | |
| 584 | 1 | $URL = new \MySociety\TheyWorkForYou\Url($hansardmajors[$this->major]['page_year']); | |
| 585 | 1 | $thing = $hansardmajors[$this->major]['plural']; | |
| 586 | 1 |         $URL->insert(array('y'=>$year)); | |
| 587 | |||
| 588 | 1 | $nextprevdata['up'] = array ( | |
| 589 | 1 | 'body' => "All of $year's $thing", | |
| 590 | 1 | 'title' => '', | |
| 591 | 1 | 'url' => $URL->generate() | |
| 592 | 1 | ); | |
| 593 | |||
| 594 | 1 | return $nextprevdata; | |
| 595 | |||
| 596 | } | ||
| 597 | |||
| 598 | |||
| 599 | |||
| 600 | 1 |     public function _validate_date($args) { | |
| 601 | // Used when we're viewing things by (_get_data_by_date() functions). | ||
| 602 | // If $args['date'] is a valid yyyy-mm-dd date, it is returned. | ||
| 603 | // Else false is returned. | ||
| 604 | 1 | global $PAGE; | |
| 605 | |||
| 606 | 1 |         if (isset($args['date'])) { | |
| 607 | 1 | $date = $args['date']; | |
| 608 | 1 |         } else { | |
| 609 |             $PAGE->error_message ("Sorry, we don't have a date."); | ||
| 610 | return false; | ||
| 611 | } | ||
| 612 | |||
| 613 | 1 |         if (!preg_match("/^(\d\d\d\d)-(\d{1,2})-(\d{1,2})$/", $date, $matches)) { | |
| 614 |             $PAGE->error_message ("Sorry, '" . _htmlentities($date) . "' isn't of the right format (YYYY-MM-DD)."); | ||
| 615 | return false; | ||
| 616 | } | ||
| 617 | |||
| 618 | 1 | list(, $year, $month, $day) = $matches; | |
| 619 | |||
| 620 | 1 |         if (!checkdate($month, $day, $year)) { | |
| 621 |             $PAGE->error_message ("Sorry, '" . _htmlentities($date) . "' isn't a valid date."); | ||
| 622 | return false; | ||
| 623 | } | ||
| 624 | |||
| 625 | 1 |         $day = substr("0$day", -2); | |
| 626 | 1 |         $month = substr("0$month", -2); | |
| 627 | 1 | $date = "$year-$month-$day"; | |
| 628 | |||
| 629 | // Valid date! | ||
| 630 | 1 | return $date; | |
| 631 | } | ||
| 632 | |||
| 633 | |||
| 634 | |||
| 635 | 2 |     public function _get_item($args) { | |
| 636 | 2 | global $PAGE; | |
| 637 | |||
| 638 | 2 |         if (!isset($args['gid']) && $args['gid'] == '') { | |
| 639 |             $PAGE->error_message ("Sorry, we don't have an item gid."); | ||
| 640 | return false; | ||
| 641 | } | ||
| 642 | |||
| 643 | |||
| 644 | // Get all the data just for this epobject_id. | ||
| 645 | $input = array ( | ||
| 646 | 'amount' => array ( | ||
| 647 | 2 | 'body' => true, | |
| 648 | 2 | 'speaker' => true, | |
| 649 | 2 | 'comment' => true, | |
| 650 | 'votes' => true | ||
| 651 | 2 | ), | |
| 652 | 'where' => array ( | ||
| 653 | // Need to add the 'uk.org.publicwhip/debate/' or whatever on before | ||
| 654 | // looking in the DB. | ||
| 655 | 2 | 'gid=' => $this->gidprefix . $args['gid'] | |
| 656 | 2 | ) | |
| 657 | 2 | ); | |
| 658 | |||
| 659 | 2 | twfy_debug (get_class($this), "looking for redirected gid"); | |
| 660 | 2 | $gid = $this->gidprefix . $args['gid']; | |
| 661 | 2 |         $q = $this->db->query ("SELECT gid_to FROM gidredirect WHERE gid_from = :gid", array(':gid' => $gid)); | |
| 662 | 2 |         if ($q->rows() == 0) { | |
| 663 | 2 | $itemdata = $this->_get_hansard_data($input); | |
| 664 | 2 |         } else { | |
| 665 |             do { | ||
| 666 | $gid = $q->field(0, 'gid_to'); | ||
| 667 |                 $q = $this->db->query("SELECT gid_to FROM gidredirect WHERE gid_from = :gid", array(':gid' => $gid)); | ||
| 668 | } while ($q->rows() > 0); | ||
| 669 | twfy_debug (get_class($this), "found redirected gid $gid" ); | ||
| 670 |             $input['where'] = array('gid=' => $gid); | ||
| 671 | $itemdata = $this->_get_hansard_data($input); | ||
| 672 |             if (count($itemdata) > 0 ) { | ||
| 673 | throw new RedirectException(fix_gid_from_db($gid)); | ||
| 674 | } | ||
| 675 | } | ||
| 676 | |||
| 677 | 2 |         if (count($itemdata) > 0) { | |
| 678 | 2 | $itemdata = $itemdata[0]; | |
| 679 | 2 | } | |
| 680 | |||
| 681 | 2 |         if (count($itemdata) == 0) { | |
| 682 | /* Deal with old links to some Lords pages. Somewhere. I can't remember where */ | ||
| 683 | $this->check_gid_change($args['gid'], 'a', ''); | ||
| 684 | |||
| 685 |             if (substr($args['gid'], -1) == 'L') { | ||
| 686 |                 $letts = array('a','b','c','d','e'); | ||
| 687 |                 for ($i=0; $i<4; $i++) { | ||
| 688 | $this->check_gid_change($args['gid'], $letts[$i], $letts[$i+1]); | ||
| 689 | } | ||
| 690 | } | ||
| 691 | |||
| 692 | /* A lot of written answers were moved from 10th to 11th May and 11th May to 12th May. | ||
| 693 | Deal with the bots who have stored links to those now non-existant written answers. */ | ||
| 694 | /* 2007-05-31: And then they were moved BACK in the volume edition, ARGH */ | ||
| 695 | $this->check_gid_change($args['gid'], '2006-05-10a', '2006-05-10c'); | ||
| 696 | $this->check_gid_change($args['gid'], '2006-05-10a', '2006-05-11d'); | ||
| 697 | $this->check_gid_change($args['gid'], '2006-05-11b', '2006-05-11d'); | ||
| 698 | $this->check_gid_change($args['gid'], '2006-05-11b', '2006-05-12c'); | ||
| 699 | $this->check_gid_change($args['gid'], '2006-05-11c', '2006-05-10c'); | ||
| 700 | $this->check_gid_change($args['gid'], '2006-05-12b', '2006-05-11d'); | ||
| 701 | |||
| 702 | $this->check_gid_change($args['gid'], '2007-01-08', '2007-01-05'); | ||
| 703 | $this->check_gid_change($args['gid'], '2007-02-19', '2007-02-16'); | ||
| 704 | |||
| 705 | /* More movearounds... */ | ||
| 706 | $this->check_gid_change($args['gid'], '2005-10-10d', '2005-09-12a'); | ||
| 707 | $this->check_gid_change($args['gid'], '2005-10-14a', '2005-10-13b'); | ||
| 708 | $this->check_gid_change($args['gid'], '2005-10-18b', '2005-10-10e'); | ||
| 709 | $this->check_gid_change($args['gid'], '2005-11-17b', '2005-11-15c'); | ||
| 710 | |||
| 711 | $this->check_gid_change($args['gid'], '2007-01-08a', '2007-01-08e'); | ||
| 712 | |||
| 713 | /* Right back when Lords began, we sent out email alerts when they weren't on the site. So this was to work that. */ | ||
| 714 | #$lord_gid_like = 'uk.org.publicwhip/lords/' . $args['gid'] . '%'; | ||
| 715 |             #$q = $this->db->query('SELECT source_url FROM hansard WHERE gid LIKE :lord_gid_like', array(':lord_gid_like' => $lord_gid_like)); | ||
| 716 | #$u = ''; | ||
| 717 |             #if ($q->rows()) { | ||
| 718 | # $u = $q->field(0, 'source_url'); | ||
| 719 | # $u = '<br><a href="'. $u . '">' . $u . '</a>'; | ||
| 720 | #} | ||
| 721 |             $PAGE->error_message ("Sorry, there is no Hansard object with a gid of '" . _htmlentities($args['gid']) . "'."); | ||
| 722 | return false; | ||
| 723 | } | ||
| 724 | |||
| 725 | 2 | return $itemdata; | |
| 726 | |||
| 727 | } | ||
| 728 | |||
| 729 |     private function check_gid_change($gid, $from, $to) { | ||
| 730 | $input = array ( | ||
| 731 | 'amount' => array ( | ||
| 732 | 'body' => true, | ||
| 733 | 'speaker' => true, | ||
| 734 | 'comment' => true, | ||
| 735 | 'votes' => true | ||
| 736 | ) | ||
| 737 | ); | ||
| 738 |         if (strstr($gid, $from)) { | ||
| 739 | $check_gid = str_replace($from, $to, $gid); | ||
| 740 |             $input['where'] = array('gid=' => $this->gidprefix . $check_gid); | ||
| 741 | $itemdata = $this->_get_hansard_data($input); | ||
| 742 |             if (count($itemdata) > 0) { | ||
| 743 | throw new RedirectException($check_gid); | ||
| 744 | } | ||
| 745 | } | ||
| 746 | } | ||
| 747 | |||
| 748 | |||
| 749 | 1 |     public function _get_data_by_date($args) { | |
| 750 | // For displaying the section and subsection headings as | ||
| 751 | // links for an entire day of debates/wrans. | ||
| 752 | |||
| 753 | 1 | global $DATA, $this_page; | |
| 754 | |||
| 755 | 1 | twfy_debug (get_class($this), "getting data by date"); | |
| 756 | |||
| 757 | // Where we'll put all the data we want to render. | ||
| 758 | 1 | $data = array (); | |
| 759 | |||
| 760 | 1 | $date = $this->_validate_date($args); | |
| 761 | |||
| 762 | 1 |         if ($date) { | |
| 763 | |||
| 764 | 1 | $nextprev = $this->_get_nextprev_dates($date); | |
| 765 | |||
| 766 | // We can then access this from $PAGE and the templates. | ||
| 767 | 1 | $DATA->set_page_metadata($this_page, 'nextprev', $nextprev); | |
| 768 | |||
| 769 | |||
| 770 | // Get all the sections for this date. | ||
| 771 | // Then for each of those we'll get the subsections and rows. | ||
| 772 | $input = array ( | ||
| 773 | 'amount' => array ( | ||
| 774 | 1 | 'body' => true, | |
| 775 | 1 | 'comment' => true, | |
| 776 | 'excerpt' => true | ||
| 777 | 1 | ), | |
| 778 | 'where' => array ( | ||
| 779 | 1 | 'hdate=' => "$date", | |
| 780 | 1 | 'htype=' => '10', | |
| 781 | 1 | 'major=' => $this->major | |
| 782 | 1 | ), | |
| 783 | 'order' => 'hpos' | ||
| 784 | 1 | ); | |
| 785 | |||
| 786 | 1 | $sections = $this->_get_hansard_data($input); | |
| 787 | |||
| 788 | 1 |             if (count($sections) > 0) { | |
| 789 | |||
| 790 | // Where we'll keep the full list of sections and subsections. | ||
| 791 | 1 | $data['rows'] = array(); | |
| 792 | |||
| 793 | 1 | $num_sections = count($sections); | |
| 794 | 1 |                 for ($n=0; $n<$num_sections; $n++) { | |
| 795 | // For each section on this date, get the subsections within it. | ||
| 796 | |||
| 797 | // Get all the section data. | ||
| 798 | 1 | $sectionrow = $this->_get_section($sections[$n]); | |
| 799 | |||
| 800 | // Get the subsections within the section. | ||
| 801 | $input = array ( | ||
| 802 | 'amount' => array ( | ||
| 803 | 1 | 'body' => true, | |
| 804 | 1 | 'comment' => true, | |
| 805 | 'excerpt' => true | ||
| 806 | 1 | ), | |
| 807 | 'where' => array ( | ||
| 808 | 1 | 'section_id=' => $sections[$n]['epobject_id'], | |
| 809 | 1 | 'htype=' => '11', | |
| 810 | 1 | 'major=' => $this->major | |
| 811 | 1 | ), | |
| 812 | 'order' => 'hpos' | ||
| 813 | 1 | ); | |
| 814 | |||
| 815 | 1 | $rows = $this->_get_hansard_data($input); | |
| 816 | |||
| 817 | // Put the section at the top of the rows array. | ||
| 818 | 1 | array_unshift ($rows, $sectionrow); | |
| 819 | |||
| 820 | // Add the section heading and the subsections to the full list. | ||
| 821 | 1 | $data['rows'] = array_merge ($data['rows'], $rows); | |
| 822 | 1 | } | |
| 823 | 1 | } | |
| 824 | |||
| 825 | // For page headings etc. | ||
| 826 | 1 | $data['info']['date'] = $date; | |
| 827 | 1 | $data['info']['major'] = $this->major; | |
| 828 | 1 | } | |
| 829 | |||
| 830 | 1 | return $data; | |
| 831 | } | ||
| 832 | |||
| 833 | |||
| 834 |     public function _get_data_by_recent($args) { | ||
| 835 | // Like _get_data_by_id() and _get_data_by_date() | ||
| 836 | // this returns a $data array suitable for sending to a template. | ||
| 837 | // It lists recent dates with debates/wrans on them, with links. | ||
| 838 | |||
| 839 | $params = array(); | ||
| 840 | |||
| 841 |         if (isset($args['days']) && is_numeric($args['days'])) { | ||
| 842 | $limit = 'LIMIT :limit'; | ||
| 843 | $params[':limit'] = $args['days']; | ||
| 844 |         } else { | ||
| 845 | $limit = ''; | ||
| 846 | } | ||
| 847 | |||
| 848 |         if ($this->major != '') { | ||
| 849 | // We must be in DEBATELIST or WRANSLIST. | ||
| 850 | |||
| 851 | $major = 'WHERE major = :major'; | ||
| 852 | $params[':major'] = $this->major; | ||
| 853 |         } else { | ||
| 854 | $major = ''; | ||
| 855 | } | ||
| 856 | |||
| 857 | $data = array (); | ||
| 858 | |||
| 859 |         $q = $this->db->query ("SELECT DISTINCT(hdate) | ||
| 860 | FROM hansard | ||
| 861 | $major | ||
| 862 | ORDER BY hdate DESC | ||
| 863 | $limit | ||
| 864 | ", $params); | ||
| 865 | |||
| 866 |         if ($q->rows() > 0) { | ||
| 867 | |||
| 868 | $URL = new \MySociety\TheyWorkForYou\Url($this->listpage); | ||
| 869 | |||
| 870 |             for ($n=0; $n<$q->rows(); $n++) { | ||
| 871 | $rowdata = array(); | ||
| 872 | |||
| 873 | $rowdata['body'] = format_date($q->field($n, 'hdate'), SHORTDATEFORMAT); | ||
| 874 |                 $URL->insert(array('d'=>$q->field($n, 'hdate'))); | ||
| 875 | $rowdata['listurl'] = $URL->generate(); | ||
| 876 | |||
| 877 | $data['rows'][] = $rowdata; | ||
| 878 | } | ||
| 879 | } | ||
| 880 | |||
| 881 | $data['info']['text'] = 'Recent dates'; | ||
| 882 | |||
| 883 | |||
| 884 | return $data; | ||
| 885 | } | ||
| 886 | |||
| 887 | # Display a person's most recent debates. | ||
| 888 | # Only used by MP RSS generator now, MP pages use Xapian search | ||
| 889 | # XXX: Abolish this entirely? | ||
| 890 | |||
| 891 | 1 |     public function _get_data_by_person($args) { | |
| 980 | } | ||
| 981 | |||
| 982 | |||
| 983 |     public function _get_data_by_search_min($args) { | ||
| 984 | return $this->_get_data_by_search($args); | ||
| 985 | } | ||
| 986 |     public function _get_data_by_search_video($args) { | ||
| 987 | return $this->_get_data_by_search($args); | ||
| 988 | } | ||
| 989 |     public function _get_data_by_search($args) { | ||
| 1284 | } | ||
| 1285 | |||
| 1286 |     public function prepare_search_result_for_display($body) { | ||
| 1287 | global $SEARCHENGINE; | ||
| 1288 | // We want to trim the body to an extract that is centered | ||
| 1289 | // around the position of the first search word. | ||
| 1290 | |||
| 1291 | // we don't use strip_tags as it doesn't replace tags with spaces, | ||
| 1292 | // which means some words end up stuck together | ||
| 1293 | $extract = strip_tags_tospaces($body); | ||
| 1294 | |||
| 1295 | // $bestpos is the position of the first search word | ||
| 1296 | $bestpos = $SEARCHENGINE->position_of_first_word($extract); | ||
| 1297 | |||
| 1298 | // Where do we want to extract from the $body to start? | ||
| 1299 | $length_of_extract = 400; // characters. | ||
| 1300 | $startpos = $bestpos - ($length_of_extract / 2); | ||
| 1301 |         if ($startpos < 0) { | ||
| 1302 | $startpos = 0; | ||
| 1303 | } | ||
| 1304 | |||
| 1305 | // Trim it to length and position, adding ellipses. | ||
| 1306 | $extract = trim_characters ($extract, $startpos, $length_of_extract); | ||
| 1307 | |||
| 1308 | // Highlight search words | ||
| 1309 | $extract = $SEARCHENGINE->highlight($extract); | ||
| 1310 | |||
| 1311 | return $extract; | ||
| 1312 | } | ||
| 1313 | |||
| 1314 |     public function _get_data_by_calendar($args) { | ||
| 1315 | // We should have come here via _get_data_by_calendar() in | ||
| 1316 | // DEBATELIST or WRANLIST, so $this->major should now be set. | ||
| 1317 | |||
| 1318 | // You can ask for: | ||
| 1319 | // * The most recent n months - $args['months'] => n | ||
| 1320 | // * All months from one year - $args['year'] => 2004 | ||
| 1321 | // * One month - $args['year'] => 2004, $args['month'] => 8 | ||
| 1322 | // * The months from this year so far (no $args variables needed). | ||
| 1323 | |||
| 1324 | // $args['onday'] may be like '2004-04-20' - if it appears in the | ||
| 1325 | // calendar, this date will be highlighted and will have no link. | ||
| 1326 | |||
| 1327 | // Returns a data structure of years, months and dates: | ||
| 1328 | // $data = array( | ||
| 1329 | // 'info' => array ( | ||
| 1330 | // 'page' => 'debates', | ||
| 1331 | // 'major' => 1 | ||
| 1332 | // 'onpage' => '2004-02-01' | ||
| 1333 | // ), | ||
| 1334 | // 'years' => array ( | ||
| 1335 | // '2004' => array ( | ||
| 1336 |         //				'01' => array ('01', '02', '03' ... '31'), | ||
| 1337 | // '02' => etc... | ||
| 1338 | // ) | ||
| 1339 | // ) | ||
| 1340 | // ) | ||
| 1341 | // It will just have entries for days for which we have relevant | ||
| 1342 | // hansard data. | ||
| 1343 | // But months that have no data will still have a month array (empty). | ||
| 1344 | |||
| 1345 | // $data['info'] may have 'prevlink' => '/debates/?y=2003' or something | ||
| 1346 | // if we're viewing recent months. | ||
| 1347 | |||
| 1348 | global $DATA, $this_page, $PAGE, $hansardmajors; | ||
| 1349 | |||
| 1350 | // What we return. | ||
| 1351 | $data = array( | ||
| 1352 | 'info' => array( | ||
| 1353 | 'page' => $this->listpage, | ||
| 1354 | 'major' => $this->major | ||
| 1355 | ) | ||
| 1356 | ); | ||
| 1357 | |||
| 1358 | // Set a variable so we know what we're displaying... | ||
| 1359 |         if (isset($args['months']) && is_numeric($args['months'])) { | ||
| 1360 | |||
| 1361 | // A number of recent months (may wrap around to previous year). | ||
| 1362 | $action = 'recentmonths'; | ||
| 1363 | |||
| 1364 | // A check to prevent anyone requestion 500000 months. | ||
| 1365 |             if ($args['months'] > 12) { | ||
| 1366 |                 $PAGE->error_message("Sorry, you can't view " . $args['months'] . " months."); | ||
| 1367 | return $data; | ||
| 1368 | } | ||
| 1369 | |||
| 1370 |         } elseif (isset($args['year']) && is_numeric($args['year'])) { | ||
| 1371 | |||
| 1372 |             if (isset($args['month']) && is_numeric($args['month'])) { | ||
| 1373 | // A particular month. | ||
| 1374 | $action = 'month'; | ||
| 1375 |             } else { | ||
| 1376 | // A single year. | ||
| 1377 | $action = 'year'; | ||
| 1378 | } | ||
| 1379 | |||
| 1380 |         } else { | ||
| 1381 | // The year to date so far. | ||
| 1382 | $action = 'recentyear'; | ||
| 1383 | } | ||
| 1384 | |||
| 1385 |         if (isset($args['onday'])) { | ||
| 1386 | // Will be highlighted. | ||
| 1387 | $data['info']['onday'] = $args['onday']; | ||
| 1388 | } | ||
| 1389 | |||
| 1390 | // This first if/else section is simply to fill out these variables: | ||
| 1391 | |||
| 1392 |         if ($action == 'recentmonths' || $action == 'recentyear') { | ||
| 1393 | |||
| 1394 | // We're either getting the most recent $args['months'] data | ||
| 1395 | // Or the most recent year's data. | ||
| 1396 | // (Not necessarily recent to *now* but compared to the most | ||
| 1397 | // recent date for which we have relevant hansard data.) | ||
| 1398 | // 'recentyear' will include all the months that haven't happened yet. | ||
| 1399 | |||
| 1400 | // Find the most recent date we have data for. | ||
| 1401 |             $q = $this->db->query("SELECT MAX(hdate) AS hdate | ||
| 1402 | FROM hansard | ||
| 1403 | WHERE major = :major", | ||
| 1404 |                 array(':major' => $this->major)); | ||
| 1405 | |||
| 1406 |             if ($q->field(0, 'hdate') != NULL) { | ||
| 1407 | $recentdate = $q->field(0, 'hdate'); | ||
| 1408 |             } else { | ||
| 1409 |                 $PAGE->error_message("Couldn't find the most recent date"); | ||
| 1410 | return $data; | ||
| 1411 | } | ||
| 1412 | |||
| 1413 | // What's the first date of data we need to fetch? | ||
| 1414 |             list($finalyear, $finalmonth, $day) = explode('-', $recentdate); | ||
| 1415 | |||
| 1416 | $finalyear = intval($finalyear); | ||
| 1417 | $finalmonth = intval($finalmonth); | ||
| 1418 | |||
| 1419 |             if ($action == 'recentmonths') { | ||
| 1420 | |||
| 1421 | // We're getting this many recent months. | ||
| 1422 | $months_to_fetch = $args['months']; | ||
| 1423 | |||
| 1424 | // The month we need to start getting data. | ||
| 1425 | $firstmonth = intval($finalmonth) - $months_to_fetch + 1; | ||
| 1426 | |||
| 1427 | $firstyear = $finalyear; | ||
| 1428 | |||
| 1429 |                 if ($firstmonth < 1) { | ||
| 1430 | // Wrap round to previous year. | ||
| 1431 | $firstyear--; | ||
| 1432 | // $firstmonth is negative, hence the '+'. | ||
| 1433 | $firstmonth = 12 + $firstmonth; // () | ||
| 1434 | }; | ||
| 1435 | |||
| 1436 |             } else { | ||
| 1437 | // $action == 'recentyear' | ||
| 1438 | |||
| 1439 | // Get the most recent year's results. | ||
| 1440 | $firstyear = $finalyear; | ||
| 1441 | $firstmonth = 1; | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | |||
| 1445 | |||
| 1446 |         } else { | ||
| 1447 | // $action == 'year' or 'month'. | ||
| 1448 | |||
| 1449 | $firstyear = $args['year']; | ||
| 1450 | $finalyear = $args['year']; | ||
| 1451 | |||
| 1452 |             if ($action == 'month') { | ||
| 1453 | $firstmonth = intval($args['month']); | ||
| 1454 | $finalmonth = intval($args['month']); | ||
| 1455 |             } else { | ||
| 1456 | $firstmonth = 1; | ||
| 1457 | $finalmonth = 12; | ||
| 1458 | } | ||
| 1459 | |||
| 1460 | $params = array( | ||
| 1461 | ':firstdate' => $firstyear . '-' . $firstmonth . '-01', | ||
| 1462 | ':finaldate' => $finalyear . '-' . $finalmonth . '-31'); | ||
| 1463 | |||
| 1464 | // Check there are some dates for this year/month. | ||
| 1465 |             $q = $this->db->query("SELECT epobject_id | ||
| 1466 | FROM hansard | ||
| 1467 | WHERE hdate >= :firstdate | ||
| 1468 | AND hdate <= :finaldate | ||
| 1469 | LIMIT 1 | ||
| 1470 | ", $params); | ||
| 1471 | |||
| 1472 |             if ($q->rows() == 0) { | ||
| 1473 | // No data in db, so return empty array! | ||
| 1474 | return $data; | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | } | ||
| 1478 | |||
| 1479 | // OK, Now we have $firstyear, $firstmonth, $finalyear, $finalmonth set up. | ||
| 1480 | |||
| 1481 | // Get the data... | ||
| 1482 | |||
| 1483 | $where = ''; | ||
| 1484 | $params = array(); | ||
| 1485 | |||
| 1486 |         if ($finalyear > $firstyear || $finalmonth >= $firstmonth) { | ||
| 1487 | $params[':finaldate'] = $finalyear . '-' . $finalmonth . '-31'; | ||
| 1488 | $where = 'AND hdate <= :finaldate'; | ||
| 1489 | } | ||
| 1490 | |||
| 1491 | $params[':major'] = $this->major; | ||
| 1492 | $params[':firstdate'] = $firstyear . '-' . $firstmonth . '-01'; | ||
| 1493 |         $q =  $this->db->query("SELECT 	DISTINCT(hdate) AS hdate | ||
| 1494 | FROM hansard | ||
| 1495 | WHERE major = :major | ||
| 1496 | AND hdate >= :firstdate | ||
| 1497 | $where | ||
| 1498 | ORDER BY hdate ASC | ||
| 1499 | ", $params); | ||
| 1500 | |||
| 1501 |         if ($q->rows() > 0) { | ||
| 1502 | |||
| 1503 | // We put the data in this array. See top of function for the structure. | ||
| 1504 | $years = array(); | ||
| 1505 | |||
| 1506 |             for ($row=0; $row<$q->rows(); $row++) { | ||
| 1507 | |||
| 1508 |                 list($year, $month, $day) = explode('-', $q->field($row, 'hdate')); | ||
| 1509 | |||
| 1510 | $month = intval($month); | ||
| 1511 | $day = intval($day); | ||
| 1512 | |||
| 1513 | // Add as a link. | ||
| 1514 | $years[$year][$month][] = $day; | ||
| 1515 | } | ||
| 1516 | |||
| 1517 | // If nothing happened on one month we'll have fetched nothing for it. | ||
| 1518 | // So now we need to fill in any gaps with blank months. | ||
| 1519 | |||
| 1520 | // We cycle through every year and month we're supposed to have fetched. | ||
| 1521 | // If it doesn't have an array in $years, we create an empty one for that | ||
| 1522 | // month. | ||
| 1523 |             for ($y = $firstyear; $y <= $finalyear; $y++) { | ||
| 1524 | |||
| 1525 |                 if (!isset($years[$y])) { | ||
| 1526 | $years[$y] = array(1=>array(), 2=>array(), 3=>array(), 4=>array(), 5=>array(), 6=>array(), 7=>array(), 8=>array(), 9=>array(), 10=>array(), 11=>array(), 12=>array()); | ||
| 1527 |                 } else { | ||
| 1528 | |||
| 1529 | // This year is set. Check it has all the months... | ||
| 1530 | |||
| 1531 | $minmonth = $y == $firstyear ? $firstmonth : 1; | ||
| 1532 | $maxmonth = $y == $finalyear ? $finalmonth : 12; | ||
| 1533 | |||
| 1534 |                     for ($m = $minmonth; $m <= $maxmonth; $m++) { | ||
| 1535 |                         if (!isset($years[$y][$m])) { | ||
| 1536 | $years[$y][$m] = array(); | ||
| 1537 | } | ||
| 1538 | } | ||
| 1539 | ksort($years[$y]); | ||
| 1540 | |||
| 1541 | } | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | $data['years'] = $years; | ||
| 1545 | } | ||
| 1546 | |||
| 1547 | // Set the next/prev links. | ||
| 1548 | |||
| 1549 | $YEARURL = new \MySociety\TheyWorkForYou\Url($hansardmajors[$this->major]['page_year']); | ||
| 1550 | |||
| 1551 |         if (substr($this_page, -4) == 'year') { | ||
| 1552 | // Only need next/prev on these pages. | ||
| 1553 | // Not sure this is the best place for this, but... | ||
| 1554 | |||
| 1555 | $nextprev = array(); | ||
| 1556 | |||
| 1557 |             if ($action == 'recentyear') { | ||
| 1558 | // Assuming there will be a previous year! | ||
| 1559 | |||
| 1560 |                 $YEARURL->insert(array('y'=> $firstyear-1)); | ||
| 1561 | |||
| 1562 | $nextprev['prev'] = array ( | ||
| 1563 | 'body' => 'Previous year', | ||
| 1564 | 'title' => $firstyear - 1, | ||
| 1565 | 'url' => $YEARURL->generate() | ||
| 1566 | ); | ||
| 1567 | |||
| 1568 |             } else { // action is 'year'. | ||
| 1569 | |||
| 1570 |                 $nextprev['prev'] = array ('body' => 'Previous year'); | ||
| 1571 |                 $nextprev['next'] = array ('body' => 'Next year'); | ||
| 1572 | |||
| 1573 |                 $q = $this->db->query("SELECT DATE_FORMAT(hdate, '%Y') AS year | ||
| 1574 | FROM hansard WHERE major = :major | ||
| 1575 | AND year(hdate) < :firstyear | ||
| 1576 | ORDER BY hdate DESC | ||
| 1577 | LIMIT 1", array( | ||
| 1578 | ':major' => $this->major, | ||
| 1579 | ':firstyear' => $firstyear | ||
| 1580 | )); | ||
| 1581 | |||
| 1582 | $prevyear = $q->field(0, 'year'); | ||
| 1583 |                 $q = $this->db->query("SELECT DATE_FORMAT(hdate, '%Y') AS year | ||
| 1584 | FROM hansard WHERE major = :major | ||
| 1585 | AND year(hdate) > :finalyear | ||
| 1586 | ORDER BY hdate | ||
| 1587 | LIMIT 1", array( | ||
| 1588 | ':major' => $this->major, | ||
| 1589 | ':finalyear' => $finalyear | ||
| 1590 | )); | ||
| 1591 | $nextyear = $q->field(0, 'year'); | ||
| 1592 | |||
| 1593 |                 if ($action == 'year' && $prevyear) { | ||
| 1594 |                     $YEARURL->insert(array('y'=>$prevyear)); | ||
| 1595 | $nextprev['prev']['title'] = $prevyear; | ||
| 1596 | $nextprev['prev']['url'] = $YEARURL->generate(); | ||
| 1597 | } | ||
| 1598 |                 if ($nextyear) { | ||
| 1599 |                     $YEARURL->insert(array('y'=>$nextyear)); | ||
| 1600 | $nextprev['next']['title'] = $nextyear; | ||
| 1601 | $nextprev['next']['url'] = $YEARURL->generate(); | ||
| 1602 | } | ||
| 1603 | } | ||
| 1604 | |||
| 1605 | // Will be used in $PAGE. | ||
| 1606 | $DATA->set_page_metadata($this_page, 'nextprev', $nextprev); | ||
| 1607 | } | ||
| 1608 | |||
| 1609 | return $data; | ||
| 1610 | |||
| 1611 | } | ||
| 1612 | |||
| 1613 |     public function _get_mentions($spid) { | ||
| 1614 | $result = array(); | ||
| 1615 |         $q = $this->db->query("select gid, type, date, url, mentioned_gid | ||
| 1616 | from mentions where gid like 'uk.org.publicwhip/spq/$spid' | ||
| 1617 | order by date, type"); | ||
| 1618 | $nrows = $q->rows(); | ||
| 1619 |         for ($i=0; $i < $nrows; $i++) { | ||
| 1620 | $result[$i] = $q->row($i); | ||
| 1621 | } | ||
| 1622 | return $result; | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | 3 |     protected function _get_hansard_data($input) { | |
| 1626 | 3 | global $hansardmajors; | |
| 1627 | // Generic function for getting hansard data from the DB. | ||
| 1628 | // It returns an empty array if no data was found. | ||
| 1629 | // It returns an array of items if 1 or more were found. | ||
| 1630 | // Each item is an array of key/value pairs. | ||
| 1631 | // eg: | ||
| 1632 | /* | ||
| 1633 | array ( | ||
| 1634 | 0 => array ( | ||
| 1635 | 'epobject_id' => '2', | ||
| 1636 | 'htype' => '10', | ||
| 1637 | 'section_id' => '0', | ||
| 1638 | etc... | ||
| 1639 | ), | ||
| 1640 | 1 => array ( | ||
| 1641 | 'epobject_id' => '3', | ||
| 1642 | etc... | ||
| 1643 | ) | ||
| 1644 | ); | ||
| 1645 | */ | ||
| 1646 | |||
| 1647 | // $input['amount'] is an associative array indicating what data should be fetched. | ||
| 1648 | // It has the structure | ||
| 1649 | // 'key' => true | ||
| 1650 | // Where 'true' indicates the data of type 'key' should be fetched. | ||
| 1651 | // Leaving a key/value pair out is the same as setting a key to false. | ||
| 1652 | |||
| 1653 | // $input['amount'] can have any or all these keys: | ||
| 1654 | // 'body' - Get the body text from the epobject table. | ||
| 1655 | // 'comment' - Get the first comment (and totalcomments count) for this item. | ||
| 1656 | // 'votes' - Get the user votes for this item. | ||
| 1657 | // 'speaker' - Get the speaker for this item, where applicable. | ||
| 1658 | // 'excerpt' - For sub/sections get the body text for the first item within them. | ||
| 1659 | |||
| 1660 | // $input['wherearr'] is an associative array of stuff for the WHERE clause, eg: | ||
| 1661 |         // 	array ('id=' => '37', 'date>' => '2003-12-31'); | ||
| 1662 | // $input['order'] is a string for the $order clause, eg 'hpos DESC'. | ||
| 1663 | // $input['limit'] as a string for the $limit clause, eg '21,20'. | ||
| 1664 | |||
| 1665 | 3 | $amount = isset($input['amount']) ? $input['amount'] : array(); | |
| 1666 | 3 | $wherearr = isset($input['where']) ? $input['where'] : array(); | |
| 1667 | 3 | $order = isset($input['order']) ? $input['order'] : ''; | |
| 1668 | 3 | $limit = isset($input['limit']) ? $input['limit'] : ''; | |
| 1669 | |||
| 1670 | |||
| 1671 |         // The fields to fetch from db. 'table' => array ('field1', 'field2'). | ||
| 1672 | $fieldsarr = array ( | ||
| 1673 | 3 |             'hansard' => array ('epobject_id', 'htype', 'gid', 'hpos', 'section_id', 'subsection_id', 'hdate', 'htime', 'source_url', 'major', 'minor', 'video_status', 'colnum') | |
| 1674 | 3 | ); | |
| 1675 | |||
| 1676 | 3 | $params = array(); | |
| 1677 | |||
| 1678 | 3 |         if (isset($amount['speaker']) && $amount['speaker'] == true) { | |
| 1679 | 2 | $fieldsarr['hansard'][] = 'person_id'; | |
| 1680 | 2 | } | |
| 1681 | |||
| 1682 | 3 | if ((isset($amount['body']) && $amount['body'] == true) || | |
| 1683 | (isset($amount['comment']) && $amount['comment'] == true) | ||
| 1684 | 3 |             ) { | |
| 1685 | 3 |             $fieldsarr['epobject'] = array ('body'); | |
| 1686 | 3 | $join = 'LEFT OUTER JOIN epobject ON hansard.epobject_id = epobject.epobject_id'; | |
| 1687 | 3 |         } else { | |
| 1688 | $join = ''; | ||
| 1689 | } | ||
| 1690 | |||
| 1691 | |||
| 1692 | 3 | $fieldsarr2 = array (); | |
| 1693 | // Construct the $fields clause. | ||
| 1694 | 3 |         foreach ($fieldsarr as $table => $tablesfields) { | |
| 1695 | 3 |             foreach ($tablesfields as $n => $field) { | |
| 1696 | 3 | $fieldsarr2[] = $table.'.'.$field; | |
| 1697 | 3 | } | |
| 1698 | 3 | } | |
| 1699 | 3 |         $fields = implode(', ', $fieldsarr2); | |
| 1700 | |||
| 1701 | 3 | $wherearr2 = array (); | |
| 1702 | // Construct the $where clause. | ||
| 1703 | 3 | $i = 0; | |
| 1704 | 3 |         foreach ($wherearr as $key => $val) { | |
| 1705 | 3 | $params[":where$i"] = $val; | |
| 1706 | 3 | $wherearr2[] = "$key :where$i"; | |
| 1707 | 3 | $i++; | |
| 1708 | 3 | } | |
| 1709 | 3 |         $where = implode (" AND ", $wherearr2); | |
| 1710 | |||
| 1711 | |||
| 1712 | 3 |         if ($order != '') { | |
| 1713 | # You can't use parameters for order by clauses | ||
| 1714 | 2 | $order_by_clause = "ORDER BY $order"; | |
| 1715 | 2 |         } else { | |
| 1716 | 2 | $order_by_clause = ''; | |
| 1717 | } | ||
| 1718 | |||
| 1719 | 3 |         if ($limit != '') { | |
| 1720 | 1 | $params[':limit'] = $limit; | |
| 1721 | 1 | $limit = "LIMIT :limit"; | |
| 1722 | 1 |         } else { | |
| 1723 | 3 | $limit = ''; | |
| 1724 | } | ||
| 1725 | |||
| 1726 | // Finally, do the query! | ||
| 1727 | 3 |         $q = $this->db->query ("SELECT $fields | |
| 1728 | FROM hansard | ||
| 1729 | 3 | $join | |
| 1730 | 3 | WHERE $where | |
| 1731 | 3 | $order_by_clause | |
| 1732 | 3 | $limit | |
| 1733 | 3 | ", $params); | |
| 1734 | |||
| 1735 | // Format the data into an array for returning. | ||
| 1736 | 3 | $data = array (); | |
| 1737 | |||
| 1738 | 3 |         if ($q->rows() > 0) { | |
| 1739 | |||
| 1740 | 3 |             for ($n=0; $n<$q->rows(); $n++) { | |
| 1741 | |||
| 1742 | // Where we'll store the data for this item before adding | ||
| 1743 | // it to $data. | ||
| 1744 | 3 | $item = array(); | |
| 1745 | |||
| 1746 | // Put each row returned into its own array in $data. | ||
| 1747 | 3 |                 foreach ($fieldsarr as $table => $tablesfields) { | |
| 1748 | 3 |                     foreach ($tablesfields as $m => $field) { | |
| 1749 | 3 | $item[$field] = $q->field($n, $field); | |
| 1750 | 3 | } | |
| 1751 | 3 | } | |
| 1752 | |||
| 1753 | 3 |                 if (isset($item['gid'])) { | |
| 1754 | // Remove the "uk.org.publicwhip/blah/" from the gid: | ||
| 1755 | // (In includes/utility.php) | ||
| 1756 | 3 | $item['gid'] = fix_gid_from_db( $item['gid'] ); | |
| 1757 | 3 | } | |
| 1758 | |||
| 1759 | // Add mentions if (a) it's a question in the written | ||
| 1760 | // answer section or (b) it's in the official reports | ||
| 1761 | // and the body text ends in a bracketed SPID. | ||
| 1762 | 3 |                 if (($this->major && $hansardmajors[$this->major]['page']=='spwrans') && ($item['htype'] == '12' && $item['minor'] == '1')) { | |
| 1763 | // Get out the SPID: | ||
| 1764 |                     if ( preg_match('#\d{4}-\d\d-\d\d\.(.*?)\.q#', $item['gid'], $m) ) { | ||
| 1765 | $item['mentions'] = $this->_get_mentions($m[1]); | ||
| 1766 | } | ||
| 1767 | } | ||
| 1768 | |||
| 1769 | // The second case (b): | ||
| 1770 | 3 |                 if (($this->major && $hansardmajors[$this->major]['page']=='spdebates') && isset($item['body'])) { | |
| 1771 |                     $stripped_body = preg_replace('/<[^>]+>/ms','',$item['body']); | ||
| 1772 |                     if ( preg_match('/\((S\d+\w+-\d+)\)/ms',$stripped_body,$m) ) { | ||
| 1773 | $item['mentions'] = $this->_get_mentions($m[1]); | ||
| 1774 | } | ||
| 1775 | } | ||
| 1776 | |||
| 1777 | 3 |                 if ($item['epobject_id'] == 15674958 || $item['epobject_id'] == 15674959) { | |
| 1778 | global $DATA, $this_page; | ||
| 1779 | $DATA->set_page_metadata($this_page, 'robots', 'noindex'); | ||
| 1780 | } | ||
| 1781 | |||
| 1782 | // Get the number of items within a section or subsection. | ||
| 1783 | // It could be that we can do this in the main query? | ||
| 1784 | // Not sure. | ||
| 1785 | 3 |                 if ( ($this->major && $hansardmajors[$this->major]['type']=='debate') && ($item['htype'] == '10' || $item['htype'] == '11') ) { | |
| 1786 | |||
| 1787 | 3 |                     if ($item['htype'] == '10') { | |
| 1788 | // Section - get a count of items within this section that | ||
| 1789 | // don't have a subsection heading. | ||
| 1790 | 3 | $where = "section_id = '" . $item['epobject_id'] . "' | |
| 1791 | 3 | AND subsection_id = '" . $item['epobject_id'] . "'"; | |
| 1792 | |||
| 1793 | 3 |                     } else { | |
| 1794 | // Subsection - get a count of items within this subsection. | ||
| 1795 | 1 | $where = "subsection_id = '" . $item['epobject_id'] . "'"; | |
| 1796 | } | ||
| 1797 | |||
| 1798 | 3 |                     $r = $this->db->query("SELECT COUNT(*) AS count | |
| 1799 | FROM hansard | ||
| 1800 | WHERE $where | ||
| 1801 | AND htype = 12 | ||
| 1802 | 3 | "); | |
| 1803 | |||
| 1804 | 3 |                     if ($r->rows() > 0) { | |
| 1805 | 3 | $item['contentcount'] = $r->field(0, 'count'); | |
| 1806 | 3 |                     } else { | |
| 1807 | $item['contentcount'] = '0'; | ||
| 1808 | } | ||
| 1809 | 3 | } | |
| 1810 | |||
| 1811 | // Get the body of the first item with the section or | ||
| 1812 | // subsection. This can then be printed as an excerpt | ||
| 1813 | // on the daily list pages. | ||
| 1814 | |||
| 1815 | 3 | if ((isset($amount['excerpt']) && $amount['excerpt'] == true) && | |
| 1816 | 1 | ($item['htype'] == '10' || | |
| 1817 | $item['htype'] == '11') | ||
| 1818 | 3 |                     ) { | |
| 1819 | 1 |                     $params = array(':epobject_id' => $item['epobject_id']); | |
| 1820 | 1 |                     if ($item['htype'] == '10') { | |
| 1821 | $where = 'hansard.section_id = :epobject_id | ||
| 1822 | 1 | AND hansard.subsection_id = :epobject_id'; | |
| 1823 | 1 |                     } elseif ($item['htype'] == '11') { | |
| 1824 | $where = 'hansard.subsection_id = :epobject_id'; | ||
| 1825 | } | ||
| 1826 | |||
| 1827 | 1 |                     $r = $this->db->query("SELECT epobject.body | |
| 1828 | FROM hansard, | ||
| 1829 | epobject | ||
| 1830 | WHERE $where | ||
| 1831 | AND hansard.epobject_id = epobject.epobject_id | ||
| 1832 | ORDER BY hansard.hpos ASC | ||
| 1833 | 1 | LIMIT 1", $params); | |
| 1834 | |||
| 1835 | 1 |                     if ($r->rows() > 0) { | |
| 1836 | $item['excerpt'] = $r->field(0, 'body'); | ||
| 1837 | } | ||
| 1838 | 1 | } | |
| 1839 | |||
| 1840 | |||
| 1841 | // We generate two permalinks for each item: | ||
| 1842 | // 'listurl' is the URL of the item in the full list view. | ||
| 1843 | // 'commentsurl' is the URL of the item on its own page, with comments. | ||
| 1844 | |||
| 1845 | // All the things we need to work out a listurl! | ||
| 1846 | $item_data = array ( | ||
| 1847 | 3 | 'major' => $this->major, | |
| 1848 | 3 | 'minor' => $item['minor'], | |
| 1849 | 3 | 'htype' => $item['htype'], | |
| 1850 | 3 | 'gid' => $item['gid'], | |
| 1851 | 3 | 'section_id' => $item['section_id'], | |
| 1852 | 3 | 'subsection_id' => $item['subsection_id'] | |
| 1853 | 3 | ); | |
| 1854 | |||
| 1855 | |||
| 1856 | 3 | $item['listurl'] = $this->_get_listurl($item_data); | |
| 1857 | |||
| 1858 | |||
| 1859 | // Create a URL for where we can see all the comments for this item. | ||
| 1860 | 3 |                 if (isset($this->commentspage)) { | |
| 1861 | $COMMENTSURL = new \MySociety\TheyWorkForYou\Url($this->commentspage); | ||
| 1862 |                     if ($this->major == 6) { | ||
| 1863 | # Another hack... | ||
| 1864 |                         $COMMENTSURL->remove(array('id')); | ||
| 1865 |                         $id = preg_replace('#^.*?_.*?_#', '', $item['gid']); | ||
| 1866 | $fragment = $this->url . $id; | ||
| 1867 | $item['commentsurl'] = $COMMENTSURL->generate() . $fragment; | ||
| 1868 |                     } else { | ||
| 1869 |                         $COMMENTSURL->insert(array('id' => $item['gid'])); | ||
| 1870 | $item['commentsurl'] = $COMMENTSURL->generate(); | ||
| 1871 | } | ||
| 1872 | } | ||
| 1873 | |||
| 1874 | // Get the user/anon votes items that have them. | ||
| 1875 | 3 | if (($this->major == 3 || $this->major == 8) && (isset($amount['votes']) && $amount['votes'] == true) && | |
| 1876 | 3 |                     $item['htype'] == '12') { | |
| 1877 | // Debate speech or written answers (not questions). | ||
| 1878 | |||
| 1879 | $item['votes'] = $this->_get_votes( $item['epobject_id'] ); | ||
| 1880 | } | ||
| 1881 | |||
| 1882 | // Get the speaker for this item, if applicable. | ||
| 1883 | 3 | if ( (isset($amount['speaker']) && $amount['speaker'] == true) && | |
| 1884 | 3 |                     $item['person_id'] != '') { | |
| 1885 | |||
| 1886 | 2 | $item['speaker'] = $this->_get_speaker($item['person_id'], $item['hdate'], $item['htime'], $item['major']); | |
| 1887 | 2 | } | |
| 1888 | |||
| 1889 | |||
| 1890 | // Get comment count and (if any) most recent comment for each item. | ||
| 1891 | 3 |                 if (isset($amount['comment']) && $amount['comment'] == true) { | |
| 1892 | |||
| 1893 | // All the things we need to get the comment data. | ||
| 1894 | $item_data = array ( | ||
| 1895 | 3 | 'htype' => $item['htype'], | |
| 1896 | 3 | 'epobject_id' => $item['epobject_id'] | |
| 1897 | 3 | ); | |
| 1898 | |||
| 1899 | 3 | $commentdata = $this->_get_comment($item_data); | |
| 1900 | 3 | $item['totalcomments'] = $commentdata['totalcomments']; | |
| 1901 | 3 | $item['comment'] = $commentdata['comment']; | |
| 1902 | 3 | } | |
| 1903 | |||
| 1904 | |||
| 1905 | // Add this item on to the array of items we're returning. | ||
| 1906 | 3 | $data[$n] = $item; | |
| 1907 | 3 | } | |
| 1908 | 3 | } | |
| 1909 | |||
| 1910 | 3 | return $data; | |
| 1911 | } | ||
| 1912 | |||
| 1913 | |||
| 1914 |     public function _get_votes($epobject_id) { | ||
| 1915 | // Called from _get_hansard_data(). | ||
| 1916 | // Separated out here just for clarity. | ||
| 1917 | // Returns an array of user and anon yes/no votes for an epobject. | ||
| 1918 | |||
| 1919 | $votes = array(); | ||
| 1920 | |||
| 1921 | // YES user votes. | ||
| 1922 |         $q = $this->db->query("SELECT COUNT(vote) as totalvotes | ||
| 1923 | FROM uservotes | ||
| 1924 | WHERE epobject_id = :epobject_id | ||
| 1925 | AND vote = '1' | ||
| 1926 |                         GROUP BY epobject_id", array(':epobject_id' => $epobject_id)); | ||
| 1927 | |||
| 1928 |         if ($q->rows() > 0) { | ||
| 1929 | $votes['user']['yes'] = $q->field(0, 'totalvotes'); | ||
| 1930 |         } else { | ||
| 1931 | $votes['user']['yes'] = '0'; | ||
| 1932 | } | ||
| 1933 | |||
| 1934 | // NO user votes. | ||
| 1935 |         $q = $this->db->query("SELECT COUNT(vote) as totalvotes | ||
| 1936 | FROM uservotes | ||
| 1937 | WHERE epobject_id = :epobject_id | ||
| 1938 | AND vote = '0' | ||
| 1939 |                         GROUP BY epobject_id", array(':epobject_id' => $epobject_id)); | ||
| 1940 | |||
| 1941 |         if ($q->rows() > 0) { | ||
| 1942 | $votes['user']['no'] = $q->field(0, 'totalvotes'); | ||
| 1943 |         } else { | ||
| 1944 | $votes['user']['no'] = '0'; | ||
| 1945 | } | ||
| 1946 | |||
| 1947 | |||
| 1948 | // Get the anon votes for each item. | ||
| 1949 | |||
| 1950 |         $q = $this->db->query("SELECT yes_votes, | ||
| 1951 | no_votes | ||
| 1952 | FROM anonvotes | ||
| 1953 | WHERE epobject_id = :epobject_id", | ||
| 1954 |             array(':epobject_id' => $epobject_id)); | ||
| 1955 | |||
| 1956 |         if ($q->rows() > 0) { | ||
| 1957 | $votes['anon']['yes'] = $q->field(0, 'yes_votes'); | ||
| 1958 | $votes['anon']['no'] = $q->field(0, 'no_votes'); | ||
| 1959 |         } else { | ||
| 1960 | $votes['anon']['yes'] = '0'; | ||
| 1961 | $votes['anon']['no'] = '0'; | ||
| 1962 | } | ||
| 1963 | |||
| 1964 | return $votes; | ||
| 1965 | } | ||
| 1966 | |||
| 1967 | |||
| 1968 | 4 |     public function _get_listurl ($id_data, $url_args=array(), $encode='html') { | |
| 1969 | 4 | global $hansardmajors; | |
| 1970 | // Generates an item's listurl - this is the 'contextual' url | ||
| 1971 | // for an item, in the full list view with an anchor (if appropriate). | ||
| 1972 | |||
| 1973 | // $id_data is like this: | ||
| 1974 | // $id_data = array ( | ||
| 1975 | // 'major' => 1, | ||
| 1976 | // 'htype' => 12, | ||
| 1977 | // 'gid' => 2003-10-30.421.4h2, | ||
| 1978 | // 'section_id' => 345, | ||
| 1979 | // 'subsection_id' => 346 | ||
| 1980 | // ); | ||
| 1981 | |||
| 1982 | // $url_args is an array of other key/value pairs to be appended in the GET string. | ||
| 1983 | 4 | if ($id_data['major']) | |
| 1984 | 4 | $LISTURL = new \MySociety\TheyWorkForYou\Url($hansardmajors[$id_data['major']]['page_all']); | |
| 1985 | else | ||
| 1986 |             $LISTURL = new \MySociety\TheyWorkForYou\Url('wrans'); | ||
| 1987 | |||
| 1988 | 4 | $fragment = ''; | |
| 1989 | |||
| 1990 | 4 |         if ($id_data['htype'] == '11' || $id_data['htype'] == '10') { | |
| 1991 | 4 |             if ($this->major == 6) { | |
| 1992 |                 $id = preg_replace('#^.*?_.*?_#', '', $id_data['gid']); | ||
| 1993 | global $DATA; | ||
| 1994 |                 $DATA->set_page_metadata('pbc_clause', 'url', 'pbc/' . $this->url . $id); | ||
| 1995 |                 $LISTURL->remove(array('id')); | ||
| 1996 |             } else { | ||
| 1997 | 4 | $LISTURL->insert( array( 'id' => $id_data['gid'] ) ); | |
| 1998 | } | ||
| 1999 | 4 |         } else { | |
| 2000 | // A debate speech or question/answer, etc. | ||
| 2001 | // We need to get the gid of the parent (sub)section for this item. | ||
| 2002 | // We use this with the gid of the item itself as an #anchor. | ||
| 2003 | |||
| 2004 | $parent_epobject_id = $id_data['subsection_id']; | ||
| 2005 | $minor = $id_data['minor']; | ||
| 2006 | |||
| 2007 | // Find the gid of this item's (sub)section. | ||
| 2008 | $parent_gid = ''; | ||
| 2009 | |||
| 2010 |             if (isset($this->epobjectid_to_gid[ $parent_epobject_id ])) { | ||
| 2011 | // We've previously cached the gid for this epobject_id, so use that. | ||
| 2012 | |||
| 2013 | $parent_gid = $this->epobjectid_to_gid[ $parent_epobject_id ]; | ||
| 2014 | |||
| 2015 |             } else { | ||
| 2016 | // We haven't cached the gid, so fetch from db. | ||
| 2017 | |||
| 2018 |                 $r = $this->db->query("SELECT gid | ||
| 2019 | FROM hansard | ||
| 2020 | WHERE epobject_id = :epobject_id", | ||
| 2021 |                     array(':epobject_id' => $parent_epobject_id)); | ||
| 2022 | |||
| 2023 |                 if ($r->rows() > 0) { | ||
| 2024 | // Remove the "uk.org.publicwhip/blah/" from the gid: | ||
| 2025 | // (In includes/utility.php) | ||
| 2026 | $parent_gid = fix_gid_from_db( $r->field(0, 'gid') ); | ||
| 2027 | |||
| 2028 | // Cache it for if we need it again: | ||
| 2029 | $this->epobjectid_to_gid[ $parent_epobject_id ] = $parent_gid; | ||
| 2030 | } | ||
| 2031 | } | ||
| 2032 | |||
| 2033 |             if ($parent_gid != '') { | ||
| 2034 | // We have a gid so add to the URL. | ||
| 2035 |                 if ($id_data['major'] == 6) { | ||
| 2036 |                     if (isset($this->bill_lookup[$minor])) { | ||
| 2037 | list($title, $session) = $this->bill_lookup[$minor]; | ||
| 2038 |                     } else { | ||
| 2039 |                         $qq = $this->db->query('select title, session from bills where id='.$minor); | ||
| 2040 | $title = $qq->field(0, 'title'); | ||
| 2041 | $session = $qq->field(0, 'session'); | ||
| 2042 | $this->bill_lookup[$minor] = array($title, $session); | ||
| 2043 | } | ||
| 2044 |                     $url = "$session/" . urlencode(str_replace(' ','_',$title)); | ||
| 2045 |                     $parent_gid = preg_replace('#^.*?_.*?_#', '', $parent_gid); | ||
| 2046 | global $DATA; | ||
| 2047 |                     $DATA->set_page_metadata('pbc_clause', 'url', "pbc/$url/$parent_gid"); | ||
| 2048 |                     $LISTURL->remove(array('id')); | ||
| 2049 |                 } else { | ||
| 2050 | $LISTURL->insert( array( 'id' => $parent_gid ) ); | ||
| 2051 | } | ||
| 2052 | // Use a truncated form of this item's gid for the anchor. | ||
| 2053 | $fragment = '#g' . gid_to_anchor($id_data['gid']); | ||
| 2054 | } | ||
| 2055 | } | ||
| 2056 | |||
| 2057 | 4 |         if (count($url_args) > 0) { | |
| 2058 | 1 | $LISTURL->insert( $url_args); | |
| 2059 | 1 | } | |
| 2060 | |||
| 2061 | 4 | return $LISTURL->generate($encode) . $fragment; | |
| 2062 | } | ||
| 2063 | |||
| 2064 | private $major_to_house = array( | ||
| 2065 | 1 => array(1), | ||
| 2066 | 2 => array(1), | ||
| 2067 | 3 => array(1, 2), | ||
| 2068 | 4 => array(1, 2), | ||
| 2069 | 5 => array(3), | ||
| 2070 | 6 => array(1), | ||
| 2071 | 7 => array(4), | ||
| 2072 | 8 => array(4), | ||
| 2073 | 101 => array(2), | ||
| 2074 | ); | ||
| 2075 | |||
| 2076 | 3 |     public function _get_speaker($person_id, $hdate, $htime, $major) { | |
| 2077 | 3 |         if ($person_id == 0) { | |
| 2078 | 1 | return array(); | |
| 2079 | } | ||
| 2080 | |||
| 2081 | # Special exemption below for when NI Speaker becomes Speaker | ||
| 2082 | # mid-debate, so we don't want to cache | ||
| 2083 | 3 |         if (isset($this->speakers["$person_id-$hdate"]) && !($person_id == 13831 && $hdate == '2015-01-12')) { | |
| 2084 | 1 | return $this->speakers["$person_id-$hdate"]; | |
| 2085 | } | ||
| 2086 | |||
| 2087 | # Special exemptions for people 'speaking' after they have died | ||
| 2088 | # Note identical code to this in search/index.pl | ||
| 2089 | 3 |         if ($person_id == 10170 && $hdate == '2014-09-08') { | |
| 2090 | $hdate = '2014-09-07'; | ||
| 2091 | 3 |         } elseif ($person_id == 11068 && substr($hdate, 0, 7) == '2008-09') { | |
| 2092 | $hdate = '2008-08-13'; | ||
| 2093 | 3 |         } elseif ($person_id == 25394 && $hdate == '2016-07-01') { | |
| 2094 | $hdate = '2016-06-16'; | ||
| 2095 | } | ||
| 2096 | |||
| 2097 | # check for a person redirect | ||
| 2098 | 3 |         $q = $this->db->query("SELECT gid_to FROM gidredirect | |
| 2099 | 3 | WHERE gid_from = :gid_from", | |
| 2100 | 3 |             array(':gid_from' => "uk.org.publicwhip/person/$person_id") | |
| 2101 | 3 | ); | |
| 2102 | 3 |         if ($q->rows > 0) { | |
| 2103 |             $person_id = str_replace('uk.org.publicwhip/person/', '', $q->field(0, 'gid_to')); | ||
| 2104 | } | ||
| 2105 | |||
| 2106 | 3 |         $q = $this->db->query("SELECT title, given_name, family_name, lordofname, | |
| 2107 | house, | ||
| 2108 | constituency, | ||
| 2109 | party, | ||
| 2110 | member_id | ||
| 2111 | FROM member m, person_names p | ||
| 2112 | WHERE m.person_id = :person_id | ||
| 2113 | AND entered_house <= :hdate AND :hdate <= left_house | ||
| 2114 | AND p.person_id = m.person_id AND p.type = 'name' | ||
| 2115 | AND p.start_date <= :hdate AND :hdate <= p.end_date | ||
| 2116 | 3 | ORDER BY entered_house", | |
| 2117 | 3 |             array(':person_id' => $person_id, ':hdate' => $hdate)); | |
| 2118 | 3 | $member = $this->_get_speaker_alone($q->data, $person_id, $hdate, $htime, $major); | |
| 2119 | |||
| 2120 | 3 | $URL = $this->_get_speaker_url($member['house']); | |
| 2121 | 3 |         $URL->insert( array ('p' => $person_id) ); | |
| 2122 | |||
| 2123 | 3 | $name = member_full_name($member['house'], $member['title'], $member['given_name'], $member['family_name'], $member['lordofname']); | |
| 2124 | $speaker = array ( | ||
| 2125 | 3 | 'member_id' => $member['member_id'], | |
| 2126 | 3 | "name" => $name, | |
| 2127 | 3 | 'house' => $member['house'], | |
| 2128 | 3 | "constituency" => $member["constituency"], | |
| 2129 | 3 | "party" => $member["party"], | |
| 2130 | 3 | "person_id" => $person_id, | |
| 2131 | 3 | "url" => $URL->generate(), | |
| 2132 | 3 | ); | |
| 2133 | |||
| 2134 | 3 | global $parties; | |
| 2135 | // Manual fix for Speakers. | ||
| 2136 | 3 |         if (isset($parties[$speaker['party']])) { | |
| 2137 | $speaker['party'] = $parties[$speaker['party']]; | ||
| 2138 | } | ||
| 2139 | |||
| 2140 | 3 | $speaker['office'] = $this->_get_speaker_offices($speaker, $hdate); | |
| 2141 | 3 | $this->speakers["$person_id-$hdate"] = $speaker; | |
| 2142 | 3 | return $speaker; | |
| 2143 | } | ||
| 2144 | |||
| 2145 | 3 |     private function _get_speaker_alone($members, $person_id, $hdate, $htime, $major) { | |
| 2146 | 3 |         if (count($members) > 1) { | |
| 2147 | 2 |             $members = array_filter($members, function($m) use ($major) { | |
| 2148 | 2 | return in_array($m['house'], $this->major_to_house[$major]); | |
| 2149 | 2 | }); | |
| 2150 | # Of course, remember PHP treats lists as dictionaries | ||
| 2151 | 2 | $members = array_values($members); | |
| 2152 | 2 | } | |
| 2153 | # Note identical code to this in search/index.pl | ||
| 2154 | 3 |         if (count($members) > 1) { | |
| 2155 | # Couple of special cases for the election of the NI Speaker | ||
| 2156 |             if ($person_id == 13799 && $hdate == '2007-05-08') { | ||
| 2157 | $members = array($members[$htime < '11:00' ? 0 : 1]); | ||
| 2158 |             } elseif ($person_id == 13831 && $hdate == '2015-01-12') { | ||
| 2159 | $members = array($members[$htime < '13:00' ? 0 : 1]); | ||
| 2160 | } | ||
| 2161 | } | ||
| 2162 | 3 |         if (count($members) != 1) { | |
| 2163 |             throw new \Exception('Wanted one result, but got ' . count($members) . " for $person_id, $hdate, $major."); | ||
| 2164 | } | ||
| 2165 | |||
| 2166 | 3 | return $members[0]; | |
| 2167 | } | ||
| 2168 | |||
| 2169 | 3 |     private function _get_speaker_url($house) { | |
| 2170 | 3 |         $URL = new \MySociety\TheyWorkForYou\Url('mp'); # Default, house=1 | |
| 2171 | 3 |         if ($house == HOUSE_TYPE_LORDS) { | |
| 2172 |             $URL = new \MySociety\TheyWorkForYou\Url('peer'); | ||
| 2173 | 3 |         } elseif ($house == HOUSE_TYPE_NI) { | |
| 2174 |             $URL = new \MySociety\TheyWorkForYou\Url('mla'); | ||
| 2175 | 3 |         } elseif ($house == HOUSE_TYPE_SCOTLAND) { | |
| 2176 |             $URL = new \MySociety\TheyWorkForYou\Url('msp'); | ||
| 2177 | 3 |         } elseif ($house == HOUSE_TYPE_ROYAL) { | |
| 2178 |             $URL = new \MySociety\TheyWorkForYou\Url('royal'); | ||
| 2179 | } | ||
| 2180 | 3 | return $URL; | |
| 2181 | } | ||
| 2182 | |||
| 2183 | 3 |     private function _get_speaker_offices($speaker, $hdate) { | |
| 2211 | } | ||
| 2212 | |||
| 2213 | 3 |     public function _get_comment($item_data) { | |
| 2214 | // Pass it some variables belonging to an item and the function | ||
| 2215 | // returns an array containing: | ||
| 2216 | // 1) A count of the comments within this item. | ||
| 2217 | // 2) The details of the most recent comment posted to this item. | ||
| 2218 | |||
| 2219 | // Sections/subsections have (1) (the sum of the comments | ||
| 2220 | // of all contained items), but not (2). | ||
| 2221 | |||
| 2222 | // What we return. | ||
| 2223 | 3 | $totalcomments = $this->_get_comment_count_for_epobject($item_data); | |
| 2224 | 3 | $comment = array(); | |
| 2225 | |||
| 2226 | 3 |         if ($item_data['htype'] == '12' || $item_data['htype'] == '13') { | |
| 2227 | |||
| 2228 | // Things which can have comments posted directly to them. | ||
| 2229 | |||
| 2230 |             if ($totalcomments > 0) { | ||
| 2231 | |||
| 2232 | // Get the first comment. | ||
| 2233 | |||
| 2234 | // Not doing this for Wrans sections because we don't | ||
| 2235 | // need it anywhere. Arbitrary but it'll save us MySQL time! | ||
| 2236 | |||
| 2237 |                 $q = $this->db->query("SELECT c.comment_id, | ||
| 2238 | c.user_id, | ||
| 2239 | c.body, | ||
| 2240 | c.posted, | ||
| 2241 | u.firstname, | ||
| 2242 | u.lastname | ||
| 2243 | FROM comments c, users u | ||
| 2244 | WHERE c.epobject_id = :epobject_id | ||
| 2245 | AND c.user_id = u.user_id | ||
| 2246 | AND c.visible = 1 | ||
| 2247 | ORDER BY c.posted ASC | ||
| 2248 | LIMIT 1", | ||
| 2249 |                     array(':epobject_id' => $item_data['epobject_id'])); | ||
| 2250 | |||
| 2251 | // Add this comment to the data structure. | ||
| 2252 | $comment = array ( | ||
| 2253 | 'comment_id' => $q->field(0, 'comment_id'), | ||
| 2254 | 'user_id' => $q->field(0, 'user_id'), | ||
| 2255 | 'body' => $q->field(0, 'body'), | ||
| 2256 | 'posted' => $q->field(0, 'posted'), | ||
| 2257 | 'username' => $q->field(0, 'firstname') .' '. $q->field(0, 'lastname') | ||
| 2258 | ); | ||
| 2259 | } | ||
| 2260 | |||
| 2261 | } | ||
| 2262 | |||
| 2263 | // We don't currently allow people to post comments to a section | ||
| 2264 | // or subsection itself, only the items within them. So | ||
| 2265 | // we don't get the most recent comment. Because there isn't one. | ||
| 2266 | |||
| 2267 | $return = array ( | ||
| 2268 | 3 | 'totalcomments' => $totalcomments, | |
| 2269 | 'comment' => $comment | ||
| 2270 | 3 | ); | |
| 2271 | |||
| 2272 | 3 | return $return; | |
| 2273 | } | ||
| 2274 | |||
| 2275 | |||
| 2276 | 3 |     public function _get_comment_count_for_epobject($item_data) { | |
| 2309 | } | ||
| 2310 | |||
| 2311 | |||
| 2312 | /* | ||
| 2313 |     public function _get_trackback_data($itemdata) { | ||
| 2314 | // Returns a array of data we need to create the Trackback Auto-discovery | ||
| 2315 | // RDF on a page. | ||
| 2316 | |||
| 2317 | // We're assuming that we're only using this on a page where there's only | ||
| 2318 | // one 'thing' to be trackbacked to. ie, we don't add #anchor data onto the | ||
| 2319 | // end of the URL so we can include this RDF in full lists of debate speeches. | ||
| 2320 | |||
| 2321 | $trackback = array(); | ||
| 2322 | |||
| 2323 | $title = ''; | ||
| 2324 | |||
| 2325 |         if (isset($itemdata['speaker']) && isset($itemdata['speaker']['name'])) { | ||
| 2326 | // This is probably a debate speech. | ||
| 2327 | $title .= $itemdata['speaker']['name'] . ': '; | ||
| 2328 | } | ||
| 2329 | |||
| 2330 | $trackback['title'] = $title . trim_characters($itemdata['body'], 0, 200); | ||
| 2331 | |||
| 2332 | // We're just saying this was in GMT... | ||
| 2333 | $trackback['date'] = $itemdata['hdate'] . 'T' . $itemdata['htime'] . '+00:00'; | ||
| 2334 | |||
| 2335 | // The URL of this particular item. | ||
| 2336 | // For (sub)sections we link to their listing page. | ||
| 2337 | // For everything else, to their individual pages. | ||
| 2338 | if ($itemdata['htype'] == '10' || | ||
| 2339 | $itemdata['htype'] == '11' | ||
| 2340 |             ) { | ||
| 2341 | $url = $itemdata['listurl']; | ||
| 2342 |         } else { | ||
| 2343 | $url = $itemdata['commentsurl']; | ||
| 2344 | } | ||
| 2345 | $trackback['itemurl'] = 'https://' . DOMAIN . $url; | ||
| 2346 | |||
| 2347 | // Getting the URL the user needs to ping for this item. | ||
| 2348 |         $URL = new \MySociety\TheyWorkForYou\Url('trackback'); | ||
| 2349 |         $URL->insert(array('e'=>$itemdata['epobject_id'])); | ||
| 2350 | |||
| 2351 |         $trackback['pingurl'] = 'https://' . DOMAIN . $URL->generate('html'); | ||
| 2352 | |||
| 2353 | |||
| 2354 | return $trackback; | ||
| 2355 | |||
| 2356 | } | ||
| 2357 | */ | ||
| 2358 | |||
| 2359 | 1 |     public function _get_data_by_gid($args) { | |
| 2561 | |||
| 2562 | } | ||
| 2563 | |||
| 2564 |     public function _get_data_by_column($args) { | ||
| 2584 | } | ||
| 2585 | |||
| 2586 | } | ||
| 2587 | |||
| 2588 | class WMSLIST extends WRANSLIST { | ||
| 2589 | public $major = 4; | ||
| 2590 | public $listpage = 'wms'; | ||
| 2591 | public $commentspage = 'wms'; | ||
| 2592 | public $gidprefix = 'uk.org.publicwhip/wms/'; | ||
| 2593 | |||
| 2594 |     public function _get_data_by_recent_wms($args = array()) { | ||
| 2595 | return $this->_get_data_by_recent_wrans($args); | ||
| 2596 | } | ||
| 3504 | 
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.