Completed
Push — master ( 922be9...285e65 )
by Nick
41s queued 31s
created

People   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 273
Duplicated Lines 0 %

Test Coverage

Coverage 55.81%

Importance

Changes 0
Metric Value
eloc 178
dl 0
loc 273
ccs 96
cts 172
cp 0.5581
rs 8.64
c 0
b 0
f 0
wmc 47

11 Methods

Rating   Name   Duplication   Size   Complexity  
A getCSVRow() 0 7 1
A getCSVHeaders() 0 2 1
A getRegionalReps() 0 2 1
A __construct() 0 4 1
A addImagesToData() 0 9 2
A getData() 0 17 3
A sendAsCSV() 0 20 4
B getArgs() 0 31 7
A setMetaData() 0 9 3
F _get_data_by_group() 0 110 22
A addUrlsToData() 0 29 2

How to fix   Complexity   

Complex Class

Complex classes like People 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 People, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * People Class
4
 *
5
 * @package TheyWorkForYou
6
 */
7
8
namespace MySociety\TheyWorkForYou;
9
10
/**
11
 * People
12
 */
13
14
class People {
15
16
    public $type;
17
    public $rep_name;
18
    public $rep_plural;
19
    public $house;
20
    public $cons_type;
21
    public $reg_cons_type;
22
    public $subs_missing_image = true;
23
    public $db;
24
25 4
    public function __construct() {
26 4
        global $this_page;
27 4
        $this_page = $this->type;
28 4
        $this->db = new \ParlDB();
29 4
    }
30
31 2
    protected function getRegionalReps($user) {
32 2
        return $user->getRegionalReps($this->reg_cons_type, $this->house);
33
    }
34
35 4
    public function getData($args = array()) {
36 4
        $data = $this->_get_data_by_group($args);
37
38 4
        $user = new User();
39 4
        if ( $reps = $this->getRegionalReps($user) ) {
40
            $data['reps'] = $reps;
41
        }
42
43 4
        $data['mp_data'] = $user->getRep($this->cons_type, $this->house);
44 4
        $data['data'] = $this->addImagesToData($data['data']);
45 4
        $data['urls'] = $this->addUrlsToData();
46 4
        $data['order'] = isset($args['order']) ? $args['order'] : 'l';
47 4
        $data['rep_plural'] = $this->rep_plural;
48 4
        $data['rep_name'] = $this->rep_name;
49 4
        $data['type'] = $this->type;
50
51 4
        return $data;
52
    }
53
54
    public function getArgs() {
55
        $args = array();
56
57
        if (get_http_var('f') == 'csv') {
58
            $args['f'] = 'csv';
59
        }
60
61
        $date = get_http_var('date');
62
        if ($date) {
63
            $date = parse_date($date);
64
            if ($date) {
65
                $args['date'] = $date['iso'];
66
            }
67
        } elseif (get_http_var('all')) {
68
            $args['all'] = true;
69
        }
70
71
        if ( $this->type == 'peers' ) {
72
            $args['order'] = 'name';
73
        }
74
75
        $order = get_http_var('o');
76
        $orders = array(
77
            'n' => 'name', 'f' => 'given_name', 'l' => 'family_name',
78
            'c' => 'constituency', 'p' => 'party', 'd' => 'debates',
79
        );
80
        if (array_key_exists($order, $orders)) {
81
            $args['order'] = $orders[$order];
82
        }
83
84
        return $args;
85
    }
86
87
    public function setMetaData($args) {
88
        global $this_page, $DATA;
89
90
        if (isset($args['date'])) {
91
            $DATA->set_page_metadata($this_page, 'title', $this->rep_plural . ', as on ' . format_date($args['date'], LONGDATEFORMAT));
92
        } elseif (isset($args['all'])) {
93
            $DATA->set_page_metadata($this_page, 'title', 'All ' . $this->rep_plural . ', including former ones');
94
        } else {
95
            $DATA->set_page_metadata($this_page, 'title', 'All ' . $this->rep_plural);
96
        }
97
    }
98
99
    protected function getCSVHeaders() {
100
        return array('Person ID', 'Name', 'Party', 'Constituency', 'URI');
101
    }
102
103
    protected function getCSVRow($details) {
104
        return array(
105
            $details['person_id'],
106
            $details['name'],
107
            $details['party'],
108
            $details['constituency'],
109
            'https://www.theyworkforyou.com/mp/' . $details['url']
110
        );
111
    }
112
113
    public function sendAsCSV($data) {
114
        header('Content-Disposition: attachment; filename=' . $this->type . '.csv');
115
        header('Content-Type: text/csv');
116
        $out = fopen('php://output', 'w');
117
118
        $headers = $this->getCSVHeaders();
119
        if ($data['info']['order'] == 'debates') {
120
            $headers[] = 'Debates spoken in the last year';
121
        }
122
        fputcsv($out, $headers);
0 ignored issues
show
Bug introduced by
It seems like $out can also be of type false; however, parameter $handle of fputcsv() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

122
        fputcsv(/** @scrutinizer ignore-type */ $out, $headers);
Loading history...
123
124
        foreach ($data['data'] as $pid => $details) {
125
            $row = $this->getCSVRow($details);
126
            if ($data['info']['order'] == 'debates') {
127
                $row[] = $details['data_value'];
128
            }
129
            fputcsv($out, $row);
130
        }
131
132
        fclose($out);
0 ignored issues
show
Bug introduced by
It seems like $out can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

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

132
        fclose(/** @scrutinizer ignore-type */ $out);
Loading history...
133
    }
134
135 4
    private function addImagesToData($data) {
136 4
        $new_data = array();
137 4
        foreach ( $data as $pid => $details ) {
138 4
            list($image, ) = Utility\Member::findMemberImage($pid, true, $this->subs_missing_image);
139 4
            $details['image'] = $image;
140 4
            $new_data[$pid] = $details;
141
        }
142
143 4
        return $new_data;
144
    }
145
146 4
    private function addUrlsToData() {
147 4
        global $this_page;
148
149 4
        $urls = array();
150
151 4
        $URL = new Url($this_page);
152
153 4
        $urls['plain'] = $URL->generate();
154
155 4
        $URL->insert(array( 'o' => 'n'));
156 4
        $urls['by_name'] = $URL->generate();
157
158 4
        $URL->insert(array( 'o' => 'l'));
159 4
        $urls['by_last'] = $URL->generate();
160
161 4
        $URL->insert(array( 'o' => 'f'));
162 4
        $urls['by_first'] = $URL->generate();
163
164 4
        $URL->insert(array( 'o' => 'p'));
165 4
        $urls['by_party'] = $URL->generate();
166
167 4
        $URL->insert(array( 'f' => 'csv'));
168 4
        $URL->remove(array( 'o'));
169 4
        if ( $date = get_http_var('date') ) {
170
            $URL->insert(array('date' => $date));
171
        }
172 4
        $urls['by_csv'] = $URL->generate();
173
174 4
        return $urls;
175
    }
176
177 4
    private function _get_data_by_group($args) {
178
        // $args can have an optional 'order' element.
179
180 4
        $use_extracol = (isset($args['order']) && in_array($args['order'], array('debates')));
181 4
        $use_personinfo = $use_extracol;
182
183
        # Defaults
184 4
        $order = 'family_name';
185 4
        $sqlorder = 'family_name, given_name';
186
187 4
        $params = array();
188 4
        $query = 'SELECT distinct member.person_id, title, given_name, family_name, lordofname, constituency, party, left_reason, dept, position ';
189 4
        if ($use_extracol) {
190
            $query .= ', data_value ';
191
            $order = $args['order'];
192
            $sqlorder = 'data_value+0 DESC, family_name, given_name';
193
            unset($args['date']);
194
            $key_lookup = array(
195
                'debates' => 'debate_sectionsspoken_inlastyear',
196
            );
197
            $personinfo_key = $key_lookup[$order];
198
        }
199 4
        $query .= 'FROM member LEFT OUTER JOIN moffice ON member.person_id = moffice.person ';
200 4
        if (isset($args['date'])) {
201
            $query .= 'AND from_date <= :date AND :date <= to_date ';
202
            $params[':date'] = $args['date'];
203
        } else {
204 4
            $query .= 'AND to_date="9999-12-31" ';
205
        }
206 4
        if ($use_personinfo) {
207
            $query .= 'LEFT OUTER JOIN personinfo ON member.person_id = personinfo.person_id AND data_key="' . $personinfo_key . '" ';
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $personinfo_key does not seem to be defined for all execution paths leading up to this point.
Loading history...
208
        }
209 4
        $query .= ' JOIN person_names p ON p.person_id = member.person_id AND p.type = "name" ';
210 4
        if (isset($args['date']))
211
            $query .= 'AND start_date <= :date AND :date <= end_date ';
212
        else
213 4
            $query .= 'AND end_date="9999-12-31" ';
214 4
        $query .= 'WHERE house=' . $this->house . ' ';
215 4
        if (isset($args['date']))
216
            $query .= 'AND entered_house <= :date AND :date <= left_house ';
217 4
        elseif (!isset($args['all']) || $this->house == HOUSE_TYPE_COMMONS)
218 4
            $query .= 'AND left_house = (SELECT MAX(left_house) FROM member) ';
219
220 4
        if (isset($args['order'])) {
221
            $order = $args['order'];
222
            if ($args['order'] == 'given_name') {
223
                $sqlorder = 'given_name, family_name';
224
            } elseif ($args['order'] == 'constituency') {
225
                $sqlorder = 'constituency';
226
            } elseif ($args['order'] == 'party') {
227
                $sqlorder = 'party, family_name, given_name, constituency';
228
            }
229
        }
230
231 4
        $q = $this->db->query($query . "ORDER BY $sqlorder", $params);
232
233 4
        $data = array();
234 4
        foreach ($q as $row) {
235 4
            $p_id = $row['person_id'];
236 4
            $dept = $row['dept'];
237 4
            $pos = $row['position'];
238 4
            if (isset($data[$p_id])) {
239
                $data[$p_id]['dept'] = array_merge((array) $data[$p_id]['dept'], (array) $dept);
240
                $data[$p_id]['pos'] = array_merge((array) $data[$p_id]['pos'], (array) $pos);
241
            } else {
242 4
                $name = member_full_name($this->house, $row['title'], $row['given_name'], $row['family_name'], $row['lordofname']);
243 4
                $constituency = $row['constituency'];
244 4
                $url = make_member_url($name, $constituency, $this->house, $p_id);
245
                $narray = array (
246 4
                    'person_id' 	=> $p_id,
247 4
                    'given_name' => $row['given_name'],
248 4
                    'family_name' => $row['family_name'],
249 4
                    'lordofname' => $row['lordofname'],
250 4
                    'name' => $name,
251 4
                    'url' => $url,
252 4
                    'constituency' 	=> $constituency,
253 4
                    'party' 	=> $row['party'],
254 4
                    'left_reason' 	=> $row['left_reason'],
255 4
                    'dept'		=> $dept,
256 4
                    'pos'		=> $pos
257
                );
258 4
                if ($use_extracol) {
259
                    $narray['data_value'] = $row['data_value'];
260
                }
261
262 4
                if ($narray['party'] == 'SPK') {
263 1
                    $narray['party'] = '-';
264 1
                    $narray['pos'] = 'Speaker';
265 1
                    $narray['dept'] = 'House of Commons';
266 4
                } elseif ($narray['party'] == 'CWM' || $narray['party'] == 'DCWM') {
267
                    $narray['party'] = '-';
268
                    $narray['pos'] = 'Deputy Speaker';
269
                    $narray['dept'] = 'House of Commons';
270
                }
271
272 4
                $data[$p_id] = $narray;
273
            }
274
        }
275 4
        if ($this->house == HOUSE_TYPE_LORDS && ($order == 'name' || $order == 'constituency')) {
276
            uasort($data, 'by_peer_name');
277
        }
278
279
        $data = array (
280
            'info' => array (
281 4
                'order' => $order
282
            ),
283 4
            'data' => $data
284
        );
285
286 4
        return $data;
287
288
    }
289
290
}
291