Failed Conditions
Branch master (3ce7e2)
by Nick
14:43
created

MEMBER::load_extra_info()   F

Complexity

Conditions 25
Paths 10754

Size

Total Lines 115
Code Lines 74

Duplication

Lines 13
Ratio 11.3 %

Code Coverage

Tests 56
CRAP Score 56.8639

Importance

Changes 0
Metric Value
cc 25
eloc 74
nc 10754
nop 2
dl 13
loc 115
rs 2
c 0
b 0
f 0
ccs 56
cts 89
cp 0.6292
crap 56.8639

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 5 and the first side effect is on line 3.

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.

Loading history...
2
3
include_once INCLUDESPATH."easyparliament/glossary.php";
1 ignored issue
show
Bug introduced by
The constant INCLUDESPATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
4
5
class MEMBER {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
6
7
    public $valid = false;
8
    public $member_id;
9
    public $person_id;
10
    public $title;
11
    public $given_name;
12
    public $family_name;
13
    public $lordofname;
14
    public $constituency;
15
    public $party;
16
    public $other_parties = array();
17
    public $other_constituencies;
18
    public $houses = array();
19
    public $entered_house = array();
20
    public $left_house = array();
21
    public $extra_info = array();
22
    // Is this MP THEUSERS's MP?
23
    public $the_users_mp = false;
24
    public $house_disp = 0; # Which house we should display this person in
25
26
    // Mapping member table 'house' numbers to text.
27
    public $houses_pretty = array(
28
        0 => 'Royal Family',
29
        1 => 'House of Commons',
30
        2 => 'House of Lords',
31
        3 => 'Northern Ireland Assembly',
32
        4 => 'Scottish Parliament',
33
    );
34
35
    // Mapping member table reasons to text.
36
    public $reasons = array(
37
        'became_peer'		=> 'Became peer',
38
        'by_election'		=> 'Byelection',
39
        'changed_party'		=> 'Changed party',
40
        'changed_name' 		=> 'Changed name',
41
        'declared_void'		=> 'Declared void',
42
        'died'			=> 'Died',
43
        'disqualified'		=> 'Disqualified',
44
        'general_election' 	=> 'General election',
45
        'general_election_standing' 	=> array('General election (standing again)', 'General election (stood again)'),
46
        'general_election_not_standing' 	=> 'did not stand for re-election',
47
        'reinstated'		=> 'Reinstated',
48
        'resigned'		=> 'Resigned',
49
        'still_in_office'	=> 'Still in office',
50
        'dissolution'		=> 'Dissolved for election',
51
        'regional_election'	=> 'Election', # Scottish Parliament
52
        'replaced_in_region'	=> 'Appointed, regional replacement',
53
54
    );
55
56 16
    public function __construct($args) {
57
        // $args is a hash like one of:
58
        // member_id 		=> 237
59
        // person_id 		=> 345
60
        // constituency 	=> 'Braintree'
61
        // postcode			=> 'e9 6dw'
62
63
        // If just a constituency we currently just get the current member for
64
        // that constituency.
65
66 16
        global $this_page;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
67
68 16
        $house = isset($args['house']) ? $args['house'] : null;
69
70 16
        $this->db = new ParlDB;
0 ignored issues
show
Bug Best Practice introduced by
The property db does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
71 16
        $person_id = '';
72 16
        if (isset($args['member_id']) && is_numeric($args['member_id'])) {
73 1
            $person_id = $this->member_id_to_person_id($args['member_id']);
74 16
        } elseif (isset($args['name'])) {
75 3
            $con = isset($args['constituency']) ? $args['constituency'] : '';
76 3
            $person_id = $this->name_to_person_id($args['name'], $con);
77 14
        } elseif (isset($args['constituency'])) {
78 1
            $still_in_office = isset($args['still_in_office']) ? $args['still_in_office'] : false;
79 1
            $person_id = $this->constituency_to_person_id($args['constituency'], $house, $still_in_office);
0 ignored issues
show
Unused Code introduced by
The call to MEMBER::constituency_to_person_id() has too many arguments starting with $still_in_office. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

79
            /** @scrutinizer ignore-call */ 
80
            $person_id = $this->constituency_to_person_id($args['constituency'], $house, $still_in_office);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
80 12
        } elseif (isset($args['postcode'])) {
81
            $person_id = $this->postcode_to_person_id($args['postcode'], $house);
82 11
        } elseif (isset($args['person_id']) && is_numeric($args['person_id'])) {
83 11
            $person_id = $args['person_id'];
84 11
            $q = $this->db->query("SELECT gid_to FROM gidredirect
85 11
                    WHERE gid_from = :gid_from",
86 11
                array(':gid_from' => "uk.org.publicwhip/person/$person_id")
87 11
            );
88 11
            if ($q->rows > 0) {
89
                $person_id = str_replace('uk.org.publicwhip/person/', '', $q->field(0, 'gid_to'));
90
            }
91 11
        }
92
93 15
        if (!$person_id) {
94
            return;
95
        }
96
97 15
        $q = $this->db->query("SELECT member_id, house, title,
98
            given_name, family_name, lordofname, constituency, party, lastupdate,
99
            entered_house, left_house, entered_reason, left_reason, member.person_id
100
            FROM member, person_names pn
101
            WHERE member.person_id = :person_id
102
                AND member.person_id = pn.person_id AND pn.type = 'name' AND pn.start_date <= left_house AND left_house <= pn.end_date
103 15
            ORDER BY left_house DESC, house", array(
104
                ':person_id' => $person_id
105 15
            ));
106
107 15
        if (!$q->rows() > 0) {
108
            return;
109
        }
110
111 15
        $this->valid = true;
112
113 15
        $this->house_disp = 0;
114 15
        $last_party = null;
115 15
        for ($row=0; $row<$q->rows(); $row++) {
116 15
            $house          = $q->field($row, 'house');
117 15
            if (!in_array($house, $this->houses)) $this->houses[] = $house;
118 15
            $const          = $q->field($row, 'constituency');
119 15
            $party		= $q->field($row, 'party');
120 15
            $entered_house	= $q->field($row, 'entered_house');
121 15
            $left_house	= $q->field($row, 'left_house');
122 15
            $entered_reason	= $q->field($row, 'entered_reason');
123 15
            $left_reason	= $q->field($row, 'left_reason');
124
125 15
            if (!isset($this->entered_house[$house]) || $entered_house < $this->entered_house[$house]['date']) {
126 15
                $this->entered_house[$house] = array(
127 15
                    'date' => $entered_house,
128 15
                    'date_pretty' => $this->entered_house_text($entered_house),
129 15
                    'reason' => $this->entered_reason_text($entered_reason),
130
                );
131 15
            }
132
133 15
            if (!isset($this->left_house[$house])) {
134 15
                $this->left_house[$house] = array(
135 15
                    'date' => $left_house,
136 15
                    'date_pretty' => $this->left_house_text($left_house),
137 15
                    'reason' => $this->left_reason_text($left_reason, $left_house, $house),
138 15
                    'constituency' => $const,
139 15
                    'party' => $this->party_text($party)
140 15
                );
141 15
            }
142
143
            if ( $house==HOUSE_TYPE_ROYAL 					# The Monarch
144 15
                || (!$this->house_disp && $house==HOUSE_TYPE_SCOTLAND)	# MSPs and
145 14
                || (!$this->house_disp && $house==HOUSE_TYPE_NI)	# MLAs have lowest priority
146 12
                || ($this->house_disp!=HOUSE_TYPE_LORDS && $house==HOUSE_TYPE_LORDS)	# Lords have highest priority
147 11
                || (!$this->house_disp && $house==HOUSE_TYPE_COMMONS) # MPs
148 15
            ) {
149 15
                $this->house_disp = $house;
150 15
                $this->constituency = $const;
151 15
                $this->party = $party;
152
153 15
                $this->member_id	= $q->field($row, 'member_id');
154 15
                $this->title		= $q->field($row, 'title');
155 15
                $this->given_name = $q->field($row, 'given_name');
156 15
                $this->family_name = $q->field($row, 'family_name');
157 15
                $this->lordofname = $q->field($row, 'lordofname');
158 15
                $this->person_id	= $q->field($row, 'person_id');
159 15
            }
160
161 15
            if (($last_party && $party && $party != $last_party) || $left_reason == 'changed_party') {
162
                $this->other_parties[] = array(
163
                    'from' => $this->party_text($party),
164
                    'date' => $left_house,
165
                );
166
            }
167 15
            $last_party = $party;
168
169 15
            if ($const != $this->constituency) {
170 1
                $this->other_constituencies[$const] = true;
171 1
            }
172 15
        }
173 15
        $this->other_parties = array_reverse($this->other_parties);
174
175
        // Loads extra info from DB - you now have to call this from outside
176
            // when you need it, as some uses of MEMBER are lightweight (e.g.
177
            // in searchengine.php)
178
        // $this->load_extra_info();
0 ignored issues
show
Unused Code Comprehensibility introduced by
72% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
179
180 15
        $this->set_users_mp();
181 15
    }
182
183 1
    public function member_id_to_person_id($member_id) {
184 1
        $q = $this->db->query("SELECT person_id FROM member
185 1
                    WHERE member_id = :member_id",
186 1
            array(':member_id' => $member_id)
187 1
        );
188 1
        if ($q->rows == 0) {
189
            $q = $this->db->query("SELECT person_id FROM gidredirect, member
190
                    WHERE gid_from = :gid_from AND
191
                        CONCAT('uk.org.publicwhip/member/', member_id) = gid_to",
192
                array(':gid_from' => "uk.org.publicwhip/member/$member_id")
193
            );
194
        }
195 1
        if ($q->rows > 0) {
196 1
            return $q->field(0, 'person_id');
197
        } else {
198
            throw new MySociety\TheyWorkForYou\MemberException('Sorry, there is no member with a member ID of "' . _htmlentities($member_id) . '".');
199
        }
200
    }
201
202
    public function postcode_to_person_id($postcode, $house=null) {
203
        twfy_debug ('MP', "postcode_to_person_id converting postcode to person");
204
        $constituency = strtolower(MySociety\TheyWorkForYou\Utility\Postcode::postcodeToConstituency($postcode));
205
        return $this->constituency_to_person_id($constituency, $house);
206
    }
207
208 1
    public function constituency_to_person_id($constituency, $house=null) {
209 1
        if ($constituency == '') {
210
            throw new MySociety\TheyWorkForYou\MemberException('Sorry, no constituency was found.');
211
        }
212
213 1
        if ($constituency == 'Orkney ') {
214
            $constituency = 'Orkney & Shetland';
215
        }
216
217 1
        $normalised = MySociety\TheyWorkForYou\Utility\Constituencies::normaliseConstituencyName($constituency);
218 1
        if ($normalised) $constituency = $normalised;
219
220 1
        $params = array();
221
222 1
        $left = "left_reason = 'still_in_office'";
223 1
        if ($dissolution = MySociety\TheyWorkForYou\Dissolution::db()) {
224
            $left = "($left OR $dissolution[query])";
225
            $params = $dissolution['params'];
226
        }
227
        $query = "SELECT person_id FROM member
228
                WHERE constituency = :constituency
229 1
                AND $left";
230
231 1
        $params[':constituency'] = $constituency;
232
233 1
        if ($house) {
234
            $query .= ' AND house = :house';
235
            $params[':house'] = $house;
236
        }
237
238 1
        $q = $this->db->query($query, $params);
239
240 1
        if ($q->rows > 0) {
241 1
            return $q->field(0, 'person_id');
242
        } else {
243
            throw new MySociety\TheyWorkForYou\MemberException('Sorry, there is no current member for the "' . _htmlentities(ucwords($constituency)) . '" constituency.');
244
        }
245
    }
246
247 3
    public function name_to_person_id($name, $const='') {
248 3
        global $this_page;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
249 3
        if ($name == '') {
250
            throw new MySociety\TheyWorkForYou\MemberException('Sorry, no name was found.');
251
        }
252
253 3
        $params = array();
254 3
        $q = "SELECT person_id FROM person_names WHERE type = 'name' ";
255 3
        if ($this_page == 'peer') {
256
            $success = preg_match('#^(.*?) (.*?) of (.*?)$#', $name, $m);
257
            if (!$success)
258
                $success = preg_match('#^(.*?)() of (.*?)$#', $name, $m);
259
            if (!$success)
260
                $success = preg_match('#^(.*?) (.*?)()$#', $name, $m);
261
            if (!$success) {
262
                throw new MySociety\TheyWorkForYou\MemberException('Sorry, that name was not recognised.');
263
            }
264
            $params[':title'] = $m[1];
265
            $params[':family_name'] = $m[2];
266
            $params[':lordofname'] = $m[3];
267
            $q .= "AND title = :title AND family_name = :family_name AND lordofname = :lordofname";
268 3
        } elseif ($this_page == 'msp' || $this_page == 'mla' || strstr($this_page, 'mp')) {
269 3
            $success = preg_match('#^(.*?) (.*?) (.*?)$#', $name, $m);
270 3
            if (!$success)
271 3
                $success = preg_match('#^(.*?)() (.*)$#', $name, $m);
272 3
            if (!$success) {
273
                throw new MySociety\TheyWorkForYou\MemberException('Sorry, that name was not recognised.');
274
            }
275 3
            $params[':given_name'] = $m[1];
276 3
            $params[':middle_name'] = $m[2];
277 3
            $params[':family_name'] = $m[3];
278 3
            $params[':first_and_middle_names'] = $m[1] . ' ' . $m[2];
279 3
            $params[':middle_and_last_names'] = $m[2] . ' ' . $m[3];
280
            # Note this works only because MySQL ignores trailing whitespace
281
            $q .= "AND (
282
                (given_name=:first_and_middle_names AND family_name=:family_name)
283
                OR (given_name=:given_name AND family_name=:middle_and_last_names)
284
                OR (title=:given_name AND given_name=:middle_name AND family_name=:family_name)
285 3
            )";
286 3
        }
287
288 3
        $q = $this->db->query($q, $params);
289 3
        if (!$q->rows) {
290
            throw new MySociety\TheyWorkForYou\MemberException('Sorry, we could not find anyone with that name.');
291 3
        } elseif ($q->rows == 1) {
292 2
            return $q->field(0, 'person_id');
293
        }
294
295
        # More than one person ID matching the given name
296 1
        $person_ids = array();
297 1
        for ($i=0; $i<$q->rows; ++$i) {
298 1
            $pid = $q->field($i, 'person_id');
299 1
            $person_ids[$pid] = 1;
300 1
        }
301 1
        $pids = array_keys($person_ids);
302
303 1
        $params = array();
304 1
        if ($this_page == 'peer') {
305
            $params[':house'] = HOUSE_TYPE_LORDS;
306 1
        } elseif ($this_page == 'msp') {
307
            $params[':house'] = HOUSE_TYPE_SCOTLAND;
308 1
        } elseif ($this_page == 'mla') {
309
            $params[':house'] = HOUSE_TYPE_NI;
310 1
        } elseif ($this_page == 'royal') {
311
            $params[':house'] = HOUSE_TYPE_ROYAL;
312
        } else {
313 1
            $params[':house'] = HOUSE_TYPE_COMMONS;
314
        }
315
316 1
        $pids_str = join(',', $pids);
317 1
        $q = "SELECT person_id, constituency FROM member WHERE person_id IN ($pids_str) AND house = :house";
318 1
        if ($const) {
319
            $params[':constituency'] = $const;
320
            $q .= ' AND constituency=:constituency';
321
        }
322 1
        $q .= ' GROUP BY person_id';
323
324 1
        $q = $this->db->query($q, $params);
325 1
        if ($q->rows > 1) {
326 1
            $person_ids = array();
327 1
            for ($i=0; $i<$q->rows(); ++$i) {
328 1
                $person_ids[$q->field($i, 'person_id')] = $q->field($i, 'constituency');
329 1
            }
330 1
            throw new MySociety\TheyWorkForYou\MemberMultipleException($person_ids);
331
        } elseif ($q->rows > 0) {
332
            return $q->field(0, 'person_id');
333
        } elseif ($const) {
334
            return $this->name_to_person_id($name);
335
        } else {
336
            throw new MySociety\TheyWorkForYou\MemberException('Sorry, there is no current member with that name.');
337
        }
338
    }
339
340 15
    public function set_users_mp() {
341
        // Is this MP THEUSER's MP?
342 15
        global $THEUSER;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
343 15
        if (is_object($THEUSER) && $THEUSER->postcode_is_set() && $this->current_member(1)) {
344
            $pc = $THEUSER->postcode();
345
            twfy_debug ('MP', "set_users_mp converting postcode to person");
346
            $constituency = strtolower(MySociety\TheyWorkForYou\Utility\Postcode::postcodeToConstituency($pc));
347
            if ($constituency == strtolower($this->constituency())) {
348
                $this->the_users_mp = true;
349
            }
350
        }
351 15
    }
352
353
    // Grabs extra information (e.g. external links) from the database
354
    # DISPLAY is whether it's to be displayed on MP page.
355 1
    public function load_extra_info($display = false, $force = false) {
356 1
        $memcache = new MySociety\TheyWorkForYou\Memcache;
357 1
        $memcache_key = 'extra_info:' . $this->person_id . ($display ? '' : ':plain');
358 1
        $this->extra_info = $memcache->get($memcache_key);
359 1
        if (!DEVSITE && !$force && $this->extra_info) {
1 ignored issue
show
Bug introduced by
The constant DEVSITE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
360
            return;
361
        }
362 1
        $this->extra_info = array();
363
364 1
        $q = $this->db->query('SELECT * FROM moffice WHERE person=:person_id ORDER BY from_date DESC, moffice_id',
365 1
                              array(':person_id' => $this->person_id));
366 1
        for ($row=0; $row<$q->rows(); $row++) {
367 1
            $this->extra_info['office'][] = $q->row($row);
368 1
        }
369
370
        // Info specific to member id (e.g. attendance during that period of office)
371 1
        $q = $this->db->query("SELECT data_key, data_value
372
                        FROM 	memberinfo
373 1
                        WHERE	member_id = :member_id",
374 1
            array(':member_id' => $this->member_id));
375 1
        for ($row = 0; $row < $q->rows(); $row++) {
376 1
            $this->extra_info[$q->field($row, 'data_key')] = $q->field($row, 'data_value');
377
            #		if ($q->field($row, 'joint') > 1)
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
378
            #			$this->extra_info[$q->field($row, 'data_key').'_joint'] = true;
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
379 1
        }
380
381
        // Info specific to person id (e.g. their permanent page on the Guardian website)
382 1
        $q = $this->db->query("SELECT data_key, data_value
383
                        FROM 	personinfo
384 1
                        WHERE	person_id = :person_id",
385 1
            array(':person_id' => $this->person_id));
386 1
        for ($row = 0; $row < $q->rows(); $row++) {
387 1
            $this->extra_info[$q->field($row, 'data_key')] = $q->field($row, 'data_value');
388
        #	    if ($q->field($row, 'count') > 1)
0 ignored issues
show
Unused Code Comprehensibility introduced by
62% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
389
        #	    	$this->extra_info[$q->field($row, 'data_key').'_joint'] = true;
0 ignored issues
show
Unused Code Comprehensibility introduced by
64% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
390 1
        }
391
392
        // Info specific to constituency (e.g. election results page on Guardian website)
393 1
        if ($this->house(HOUSE_TYPE_COMMONS)) {
394
395 1
            $q = $this->db->query("SELECT data_key, data_value FROM consinfo
396 1
            WHERE constituency = :constituency",
397 1
                array(':constituency' => $this->constituency));
398 1
            for ($row = 0; $row < $q->rows(); $row++) {
399 1
                $this->extra_info[$q->field($row, 'data_key')] = $q->field($row, 'data_value');
400 1
            }
401 1
        }
402
403 1
        if (array_key_exists('public_whip_rebellions', $this->extra_info)) {
404
            $rebellions = $this->extra_info['public_whip_rebellions'];
405
            $rebel_desc = "<unknown>";
406
            if ($rebellions == 0)
407
                $rebel_desc = "never";
408
            elseif ($rebellions <= 1)
409
                $rebel_desc = "hardly ever";
410
            elseif ($rebellions <= 3)
411
                $rebel_desc = "occasionally";
412
            elseif ($rebellions <= 5)
413
                $rebel_desc = "sometimes";
414
            elseif ($rebellions > 5)
415
                $rebel_desc = "quite often";
416
            $this->extra_info['public_whip_rebel_description'] = $rebel_desc;
417
        }
418
419 1
        if (isset($this->extra_info['public_whip_attendrank'])) {
420
            $prefix = ($this->house(HOUSE_TYPE_LORDS) ? 'L' : '');
421
            $this->extra_info[$prefix.'public_whip_division_attendance_rank'] = $this->extra_info['public_whip_attendrank'];
422
            $this->extra_info[$prefix.'public_whip_division_attendance_rank_outof'] = $this->extra_info['public_whip_attendrank_outof'];
423
            $this->extra_info[$prefix.'public_whip_division_attendance_quintile'] = floor($this->extra_info['public_whip_attendrank'] / ($this->extra_info['public_whip_attendrank_outof']+1) * 5);
424
        }
425 1
        if ($this->house(HOUSE_TYPE_LORDS) && isset($this->extra_info['public_whip_division_attendance'])) {
426
            $this->extra_info['Lpublic_whip_division_attendance'] = $this->extra_info['public_whip_division_attendance'];
427
            unset($this->extra_info['public_whip_division_attendance']);
428
        }
429
430 1
        if ($display && array_key_exists('register_member_interests_html', $this->extra_info) && ($this->extra_info['register_member_interests_html'] != '')) {
431
            $args = array (
432
                "sort" => "regexp_replace"
433
            );
434
            $GLOSSARY = new GLOSSARY($args);
435
            $this->extra_info['register_member_interests_html'] =
436
        $GLOSSARY->glossarise($this->extra_info['register_member_interests_html']);
437
        }
438
439 1
        $q = $this->db->query('select count(*) as c from alerts where criteria like "%speaker:'.$this->person_id.'%" and confirmed and not deleted');
440 1
        $this->extra_info['number_of_alerts'] = $q->field(0, 'c');
441
442 1
        if (isset($this->extra_info['reading_ease'])) {
443
            $this->extra_info['reading_ease'] = round($this->extra_info['reading_ease'], 2);
444
            $this->extra_info['reading_year'] = round($this->extra_info['reading_year'], 0);
445
            $this->extra_info['reading_age'] = $this->extra_info['reading_year'] + 4;
446
            $this->extra_info['reading_age'] .= '&ndash;' . ($this->extra_info['reading_year'] + 5);
447
        }
448
449
        # Public Bill Committees
450 1
        $q = $this->db->query('select bill_id,session,title,sum(attending) as a,sum(chairman) as c
451
            from pbc_members, bills
452 1
            where bill_id = bills.id and person_id = ' . $this->person_id()
453 1
             . ' group by bill_id order by session desc');
454 1
        $this->extra_info['pbc'] = array();
455 1
        for ($i=0; $i<$q->rows(); $i++) {
456 1
            $bill_id = $q->field($i, 'bill_id');
457 1
            $c = $this->db->query('select count(*) as c from hansard where major=6 and minor='.$bill_id.' and htype=10');
458 1
            $c = $c->field(0, 'c');
459 1
            $title = $q->field($i, 'title');
460 1
            $attending = $q->field($i, 'a');
461 1
            $chairman = $q->field($i, 'c');
462 1
            $this->extra_info['pbc'][$bill_id] = array(
463 1
                'title' => $title, 'session' => $q->field($i, 'session'),
464 1
                'attending'=>$attending, 'chairman'=>($chairman>0), 'outof' => $c
465 1
            );
466 1
        }
467
468 1
        $memcache->set($memcache_key, $this->extra_info);
469 1
    }
470
471
    // Functions for accessing things about this Member.
472
473
    public function member_id() { return $this->member_id; }
474
    public function person_id() { return $this->person_id; }
475
    public function given_name() { return $this->given_name; }
476
    public function family_name() { return $this->family_name; }
477 6
    public function full_name($no_mp_title = false) {
478 6
        $title = $this->title;
479 6
        if ($no_mp_title && ($this->house_disp==HOUSE_TYPE_COMMONS || $this->house_disp==HOUSE_TYPE_NI || $this->house_disp==HOUSE_TYPE_SCOTLAND))
480 6
            $title = '';
481 6
        return member_full_name($this->house_disp, $title, $this->given_name, $this->family_name, $this->lordofname);
482
    }
483
    public function houses() {
484
        return $this->houses;
485
    }
486 12
    public function house($house) {
487 12
        return in_array($house, $this->houses) ? true : false;
488
    }
489
    public function house_text($house) {
490
        return $this->houses_pretty[$house];
491
    }
492
    public function constituency() { return $this->constituency; }
493
    public function party() { return $this->party; }
494 15
    public function party_text($party = null) {
495 15
        global $parties;
0 ignored issues
show
Compatibility Best Practice introduced by
Use of global functionality is not recommended; it makes your code harder to test, and less reusable.

Instead of relying on global state, we recommend one of these alternatives:

1. Pass all data via parameters

function myFunction($a, $b) {
    // Do something
}

2. Create a class that maintains your state

class MyClass {
    private $a;
    private $b;

    public function __construct($a, $b) {
        $this->a = $a;
        $this->b = $b;
    }

    public function myFunction() {
        // Do something
    }
}
Loading history...
496 15
        if (!$party)
497 15
            $party = $this->party;
498 15
        if (isset($parties[$party])) {
499 7
            return $parties[$party];
500
        } else {
501 8
            return $party;
502
        }
503
    }
504
505 2
    public function entered_house($house = 0) {
506 2
        if ($house) return array_key_exists($house, $this->entered_house) ? $this->entered_house[$house] : null;
507
        return $this->entered_house;
508
    }
509 15
    public function entered_house_text($entered_house) {
510 15
        if (!$entered_house) return '';
511 15
        list($year, $month, $day) = explode('-', $entered_house);
512 15
        if ($month==1 && $day==1 && $this->house(HOUSE_TYPE_LORDS)) {
513 1
            return $year;
514 14
        } elseif ($month==0 && $day==0) {
515
            return $year;
516 14
        } elseif (checkdate($month, $day, $year) && $year != '9999') {
0 ignored issues
show
Bug introduced by
$month of type string is incompatible with the type integer expected by parameter $month of checkdate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

516
        } elseif (checkdate(/** @scrutinizer ignore-type */ $month, $day, $year) && $year != '9999') {
Loading history...
Bug introduced by
$day of type string is incompatible with the type integer expected by parameter $day of checkdate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

516
        } elseif (checkdate($month, /** @scrutinizer ignore-type */ $day, $year) && $year != '9999') {
Loading history...
Bug introduced by
$year of type string is incompatible with the type integer expected by parameter $year of checkdate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

516
        } elseif (checkdate($month, $day, /** @scrutinizer ignore-type */ $year) && $year != '9999') {
Loading history...
517 14
            return format_date($entered_house, LONGDATEFORMAT);
518
        } else {
519
            return "n/a";
520
        }
521
    }
522
523 1
    public function left_house($house = null) {
524 1
        if (!is_null($house))
525 1
            return array_key_exists($house, $this->left_house) ? $this->left_house[$house] : null;
526
        return $this->left_house;
527
    }
528
529 15
    public function left_house_text($left_house) {
530 15
        if (!$left_house) return '';
531 15
        list($year, $month, $day) = explode('-', $left_house);
532 15
        if (checkdate($month, $day, $year) && $year != '9999') {
0 ignored issues
show
Bug introduced by
$month of type string is incompatible with the type integer expected by parameter $month of checkdate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

532
        if (checkdate(/** @scrutinizer ignore-type */ $month, $day, $year) && $year != '9999') {
Loading history...
Bug introduced by
$year of type string is incompatible with the type integer expected by parameter $year of checkdate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

532
        if (checkdate($month, $day, /** @scrutinizer ignore-type */ $year) && $year != '9999') {
Loading history...
Bug introduced by
$day of type string is incompatible with the type integer expected by parameter $day of checkdate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

532
        if (checkdate($month, /** @scrutinizer ignore-type */ $day, $year) && $year != '9999') {
Loading history...
533 2
            return format_date($left_house, LONGDATEFORMAT);
534 13
        } elseif ($month==0 && $day==0) {
535
            # Left house date is stored as 1942-00-00 to mean "at some point in 1941"
536
            return $year - 1;
537
        } else {
538 13
            return "n/a";
539
        }
540
    }
541
542
    public function entered_reason() { return $this->entered_reason; }
0 ignored issues
show
Bug introduced by
The property entered_reason does not exist on MEMBER. Did you mean entered_house?
Loading history...
543 15
    public function entered_reason_text($entered_reason) {
544 15
        if (isset($this->reasons[$entered_reason])) {
545 13
            return $this->reasons[$entered_reason];
546
        } else {
547 2
            return $entered_reason;
548
        }
549
    }
550
551
    public function left_reason() { return $this->left_reason; }
0 ignored issues
show
Bug Best Practice introduced by
The property left_reason does not exist on MEMBER. Did you maybe forget to declare it?
Loading history...
552 15
    public function left_reason_text($left_reason, $left_house, $house) {
553 15
        if (isset($this->reasons[$left_reason])) {
554 15
            $left_reason = $this->reasons[$left_reason];
555 15
            if (is_array($left_reason)) {
556
                $q = $this->db->query("SELECT MAX(left_house) AS max FROM member WHERE house=$house");
557
                $max = $q->field(0, 'max');
558
                if ($max == $left_house) {
559
                    return $left_reason[0];
560
                } else {
561
                    return $left_reason[1];
562
                }
563
            } else {
564 15
                return $left_reason;
565
            }
566
        } else {
567
            return $left_reason;
568
        }
569
    }
570
571
    public function extra_info() { return $this->extra_info; }
572
573 1
    public function current_member($house = 0) {
574 1
        $current = array();
575 1
        foreach (array_keys($this->houses_pretty) as $h) {
576 1
            $lh = $this->left_house($h);
577 1
            $current[$h] = ($lh['date'] == '9999-12-31');
578 1
        }
579 1
        if ($house) return $current[$house];
580
        return $current;
581
    }
582
583
    public function the_users_mp() { return $this->the_users_mp; }
584
585 6
    public function url($absolute = false) {
586 6
        $house = $this->house_disp;
587 6
        if ($house == HOUSE_TYPE_COMMONS) {
588 2
            $URL = new \MySociety\TheyWorkForYou\Url('mp');
589 6
        } elseif ($house == HOUSE_TYPE_LORDS) {
590 1
            $URL = new \MySociety\TheyWorkForYou\Url('peer');
591 4
        } elseif ($house == HOUSE_TYPE_NI) {
592 1
            $URL = new \MySociety\TheyWorkForYou\Url('mla');
593 3
        } elseif ($house == HOUSE_TYPE_SCOTLAND) {
594 1
            $URL = new \MySociety\TheyWorkForYou\Url('msp');
595 2
        } elseif ($house == HOUSE_TYPE_ROYAL) {
596 1
            $URL = new \MySociety\TheyWorkForYou\Url('royal');
597 1
        }
598 6
        $member_url = make_member_url($this->full_name(true), $this->constituency(), $house, $this->person_id());
599 6
        if ($absolute) {
600
            $protocol = 'https://';
601
            if (DEVSITE) {
1 ignored issue
show
Bug introduced by
The constant DEVSITE was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
602
                $protocol = 'http://';
603
            }
604
            return $protocol . DOMAIN . $URL->generate('none') . $member_url;
1 ignored issue
show
Bug introduced by
The constant DOMAIN was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
Comprehensibility Best Practice introduced by
The variable $URL does not seem to be defined for all execution paths leading up to this point.
Loading history...
605
        } else {
606 6
            return $URL->generate('none') . $member_url;
607
        }
608
    }
609
610
    private function _previous_future_mps_query($direction) {
611
        $entered_house = $this->entered_house(HOUSE_TYPE_COMMONS);
612
        if (is_null($entered_house)) return '';
613
        if ($direction == '>') {
614
            $order = '';
615
        } else {
616
            $order = 'DESC';
617
        }
618
        $q = $this->db->query('SELECT *
619
            FROM member, person_names pn
620
            WHERE member.person_id = pn.person_id AND pn.type = "name"
621
                AND pn.start_date <= member.left_house AND member.left_house <= pn.end_date
622
                AND house = :house AND constituency = :cons
623
                AND member.person_id != :pid AND entered_house ' . $direction . ' :date ORDER BY entered_house ' . $order,
624
            array(
625
                ':house' => HOUSE_TYPE_COMMONS,
626
                ':cons' => $this->constituency(),
627
                ':pid' => $this->person_id(),
628
                ':date' => $entered_house['date'],
629
            ));
630
        $mships = array(); $last_pid = null;
631
        for ($r = 0; $r < $q->rows(); $r++) {
632
            $pid = $q->field($r, 'person_id');
633
            $name = $q->field($r, 'given_name') . ' ' . $q->field($r, 'family_name');
634
            if ($last_pid != $pid) {
0 ignored issues
show
Bug Best Practice introduced by
It seems like you are loosely comparing $pid of type mixed|string against $last_pid of type mixed|string; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
635
                $mships[] = array(
636
                    'href' => WEBPATH . 'mp/?pid='.$pid,
1 ignored issue
show
Bug introduced by
The constant WEBPATH was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
637
                    'text' => $name
638
                );
639
                $last_pid = $pid;
640
            }
641
        }
642
        return $mships;
643
    }
644
645
    public function previous_mps() {
646
        return $this->_previous_future_mps_query('<');
647
    }
648
649
    public function future_mps() {
650
        return $this->_previous_future_mps_query('>');
651
    }
652
653
    public function current_member_anywhere() {
654
        $is_current = false;
655
        $current_memberships = $this->current_member();
656
        foreach ($current_memberships as $current_memberships) {
657
            if ($current_memberships === true) {
658
                $is_current = true;
659
            }
660
        }
661
662
        return $is_current;
663
    }
664
}
665