Completed
Push — master ( a4bf3a...585786 )
by Sam
08:59 queued 03:28
created

People   B

Complexity

Total Complexity 43

Size/Duplication

Total Lines 253
Duplicated Lines 0 %

Test Coverage

Coverage 54.84%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 159
c 1
b 0
f 0
dl 0
loc 253
ccs 85
cts 155
cp 0.5484
rs 8.96
wmc 43

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
A addUrlsToData() 0 29 2
F _get_data_by_group() 0 90 18

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 ';
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 ';
200 4
        if ($use_personinfo) {
201
            $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...
202
        }
203 4
        $query .= ' JOIN person_names p ON p.person_id = member.person_id AND p.type = "name" ';
204 4
        if (isset($args['date'])) {
205
            $query .= 'AND start_date <= :date AND :date <= end_date ';
206
            $params[':date'] = $args['date'];
207
        } else {
208 4
            $query .= 'AND end_date="9999-12-31" ';
209
        }
210 4
        $query .= 'WHERE house=' . $this->house . ' ';
211 4
        if (isset($args['date'])) {
212
            $query .= 'AND entered_house <= :date AND :date <= left_house ';
213 4
        } elseif (!isset($args['all']) || $this->house == HOUSE_TYPE_COMMONS) {
214 4
            $query .= 'AND left_house = (SELECT MAX(left_house) FROM member) ';
215
        }
216
217 4
        if (isset($args['order'])) {
218
            $order = $args['order'];
219
            if ($args['order'] == 'given_name') {
220
                $sqlorder = 'given_name, family_name';
221
            } elseif ($args['order'] == 'constituency') {
222
                $sqlorder = 'constituency';
223
            } elseif ($args['order'] == 'party') {
224
                $sqlorder = 'party, family_name, given_name, constituency';
225
            }
226
        }
227
228 4
        $q = $this->db->query($query . "ORDER BY $sqlorder", $params);
229
230 4
        $data = array();
231 4
        foreach ($q as $row) {
232 4
            $p_id = $row['person_id'];
233 4
            if (!isset($data[$p_id])) {
234 4
                $name = member_full_name($this->house, $row['title'], $row['given_name'], $row['family_name'], $row['lordofname']);
235 4
                $constituency = $row['constituency'];
236 4
                $url = make_member_url($name, $constituency, $this->house, $p_id);
237
                $narray = array (
238 4
                    'person_id' 	=> $p_id,
239 4
                    'given_name' => $row['given_name'],
240 4
                    'family_name' => $row['family_name'],
241 4
                    'lordofname' => $row['lordofname'],
242 4
                    'name' => $name,
243 4
                    'url' => $url,
244 4
                    'constituency' 	=> $constituency,
245 4
                    'party' 	=> $row['party'],
246 4
                    'left_reason' 	=> $row['left_reason'],
247
                );
248 4
                if ($use_extracol) {
249
                    $narray['data_value'] = $row['data_value'];
250
                }
251
252 4
                $data[$p_id] = $narray;
253
            }
254
        }
255 4
        if ($this->house == HOUSE_TYPE_LORDS && ($order == 'name' || $order == 'constituency')) {
256
            uasort($data, 'by_peer_name');
257
        }
258
259
        $data = array (
260
            'info' => array (
261 4
                'order' => $order
262
            ),
263 4
            'data' => $data
264
        );
265
266 4
        return $data;
267
268
    }
269
270
}
271