User   F
last analyzed

Complexity

Total Complexity 72

Size/Duplication

Total Lines 347
Duplicated Lines 0 %

Test Coverage

Coverage 5.11%

Importance

Changes 0
Metric Value
eloc 180
c 0
b 0
f 0
dl 0
loc 347
ccs 9
cts 176
cp 0.0511
rs 2.64
wmc 72

9 Methods

Rating   Name   Duplication   Size   Complexity  
A getPostCodeChangeURL() 0 8 2
A update() 0 36 5
A constructMPData() 0 18 2
A getRegionalReps() 0 13 5
A getRep() 0 28 6
B getUserDetails() 0 33 6
F getUpdateDetails() 0 62 15
F checkUpdateDetails() 0 116 29
A add() 0 16 2

How to fix   Complexity   

Complex Class

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

1
<?php
2
/**
3
 * User Class
4
 *
5
 * @package TheyWorkForYou
6
 */
7
8
namespace MySociety\TheyWorkForYou;
9
10
/**
11
 * User
12
 */
13
14
function calculateOptinValue($optin_service, $optin_stream, $optin_org) {
15
    // combine three booleans into a single integer to store in the database
16
    // +1 = optin_service
17
    // +2 = optin_stream
18
    // +4 = optin_org
19
20
    $value = 0;
21
22
    $value += $optin_service ? 1 : 0;
23
    $value += $optin_stream ? 2 : 0;
24
    $value += $optin_org ? 4 : 0;
25
26
    return $value;
27
}
28
29
function extractOptinValues($value) {
30
    // convert an integer into three seperate optin values ('Yes', 'No')
31
    return [
32
        'optin_service' => ($value & 1) ? "Yes" : "No",
33
        'optin_stream' => ($value & 2) ? "Yes" : "No",
34
        'optin_org' => ($value & 4) ? "Yes" : "No",
35
    ];
36
}
37
38
class User {
39
    public function getUserDetails($user_id = false) {
40
        global $THEUSER;
41
42
        $user = $THEUSER;
43
        if ($user_id && $user_id != $THEUSER->user_id()) {
44
            $user = new \USER();
45
            $valid = $user->init($user_id);
46
47
            if (!$valid || !$user->confirmed || $user->deleted()) {
48
                return ['error' => 'User does not exist'];
49
            }
50
        }
51
52
        $data = [];
53
        $data['firstname'] = $user->firstname();
54
        $data['lastname'] = $user->lastname();
55
        $data['name'] = $user->firstname() . " " . $user->lastname();
56
        $data['url'] = $user->url();
57
        $data['email'] = $user->email();
58
        $optin_values = extractOptinValues($user->optin());
59
        $data['optin_service'] = $optin_values['optin_service'];
60
        $data['optin_stream'] = $optin_values['optin_stream'];
61
        $data['optin_org'] = $optin_values['optin_org'];
62
        $data['postcode']	= $user->postcode();
63
        $data['website']	= $user->url();
64
        $data['registrationtime']	= $user->registrationtime();
65
        $data['status'] = $user->status();
66
        $data["deleted"] = $user->deleted();
67
        $data["confirmed"] = $user->confirmed();
68
        $data["status"] = $user->status();
69
        $data["facebook_id"] = $user->facebook_id();
70
        $data['facebook_user'] = $user->facebook_user();
71
        return $data;
72
    }
73
74
    public function getUpdateDetails($this_page, $user) {
75
        $details = [];
76
77
        if ($user->facebook_user) {
78
            $details = $this->getUserDetails();
79
            $details["password"] = '';
80
        } else {
81
            $details["firstname"] = trim(get_http_var("firstname"));
82
            $details["lastname"] = trim(get_http_var("lastname"));
83
84
            $details["password"] = trim(get_http_var("password"));
85
            $details["password2"] = trim(get_http_var("password2"));
86
87
            $details["email"] = trim(get_http_var("em"));
88
89
            $details["url"] = trim(get_http_var("url"));
90
91
            $optin_service = get_http_var("optin_service") == "true" ? true : false;
92
            $optin_stream = get_http_var("optin_stream") == "true" ? true : false;
93
            $optin_org = get_http_var("optin_org") == "true" ? true : false;
94
95
            $details["optin"] = calculateOptinValue($optin_service, $optin_stream, $optin_org);
96
97
            if (get_http_var("remember") != "") {
98
                $remember = get_http_var("remember");
99
                $details["remember"] = $remember[0] == "true" ? true : false;
100
            }
101
102
            if ($details['url'] != '' && !preg_match('/^http/', $details['url'])) {
103
                $details['url'] = 'https://' . $details['url'];
104
            }
105
106
            # these are used when displaying user details
107
            $details['name'] = $details["firstname"] . " " . $details["lastname"];
108
            $details["website"] = $details["url"];
109
            $details['registrationtime'] = $user->registrationtime();
110
            $details['status'] = $user->status();
111
        }
112
113
        $details['mp_alert'] = get_http_var('mp_alert') == 'true' ? true : false;
114
        $details["postcode"] = trim(get_http_var("postcode"));
115
116
        if ($this_page == "otheruseredit") {
117
            $details["user_id"] = trim(get_http_var("u"));
118
            $details["status"] = trim(get_http_var("status"));
119
120
            if (get_http_var("deleted") != "") {
121
                $deleted = get_http_var("deleted");
122
                $details["deleted"] = $deleted[0] == "true" ? true : false;
123
            } else {
124
                $details['deleted'] = false;
125
            }
126
127
            if (get_http_var("confirmed") != "") {
128
                $confirmed = get_http_var("confirmed");
129
                $details["confirmed"] = $confirmed[0] == "true" ? true : false;
130
            } else {
131
                $details['confirmed'] = false;
132
            }
133
        }
134
135
        return $details;
136
    }
137
138
    public function checkUpdateDetails($details) {
139
        global $THEUSER, $this_page;
140
141
        $errors = [];
142
143
        // Check each of the things the user has input.
144
        // If there is a problem with any of them, set an entry in the $errors array.
145
        // This will then be used to (a) indicate there were errors and (b) display
146
        // error messages when we show the form again.
147
148
        // facebook user's can only change their postcode so skip all this
149
        if (!isset($details['facebook_user'])) {
150
            // Check first name.
151
            if ($details["firstname"] == "") {
152
                $errors["firstname"] = "Please enter a first name";
153
            }
154
155
            // They don't need a last name. In case Madonna joins.
156
157
            // Check email address is valid and unique.
158
            if ($this_page == "otheruseredit" || $this_page == 'userjoin' || $this_page == 'useredit') {
159
                if ($details["email"] == "") {
160
                    $errors["email"] = "Please enter an email address";
161
162
                } elseif (!validate_email($details["email"])) {
163
                    // validate_email() is in includes/utilities.php
164
                    $errors["email"] = "Please enter a valid email address";
165
166
                } else {
167
168
                    $USER = new \USER();
169
                    $id_of_user_with_this_addresss = $USER->email_exists($details["email"], true);
170
171
                    if ($this_page == "useredit" &&
172
                        get_http_var("u") == "" &&
173
                        $THEUSER->isloggedin()) {
174
                        // User is updating their own info.
175
                        // Check no one else has this email.
176
177
                        if ($id_of_user_with_this_addresss &&
178
                            $id_of_user_with_this_addresss != $THEUSER->user_id()) {
179
                            $errors["email"] = "Someone else has already joined with this email address";
180
                        }
181
182
                    } else {
183
                        // User is joining. Check no one is already here with this email.
184
                        if ($this_page == "userjoin" && $id_of_user_with_this_addresss) {
185
                            $errors["email"] = "There is already a user with this email address";
186
                        }
187
                    }
188
                }
189
            }
190
191
            // Check passwords.
192
            if ($this_page == "userjoin") {
193
194
                // Only *must* enter a password if they're joining.
195
                if ($details["password"] == "") {
196
                    $errors["password"] = gettext("Please enter a password");
197
198
                } elseif (strlen($details["password"]) < 6) {
199
                    $errors["password"] = gettext("Please enter at least six characters");
200
                }
201
202
                if ($details["password2"] == "") {
203
                    $errors["password2"] = gettext("Please enter a password again");
204
                }
205
206
                if ($details["password"] != "" && $details["password2"] != "" && $details["password"] != $details["password2"]) {
207
                    $errors["password"] = gettext("The passwords did not match. Please try again.");
208
                }
209
210
            } else {
211
212
                // Update details pages.
213
214
                if ($details["password"] != "" && strlen($details["password"]) < 6) {
215
                    $errors["password"] = gettext("Please enter at least six characters");
216
                }
217
218
                if ($details["password"] != $details["password2"]) {
219
                    $errors["password"] = gettext("The passwords did not match. Please try again.");
220
                }
221
            }
222
        }
223
224
        // Check postcode (which is not a compulsory field).
225
        if ($details["postcode"] != "") {
226
            if (!validate_postcode($details["postcode"])) {
227
                $errors["postcode"] = gettext("Sorry, this isn't a valid UK postcode.");
228
            } else {
229
                try {
230
                    new \MySociety\TheyWorkForYou\Member([
231
                        'postcode' => $details['postcode'],
232
                        'house' => HOUSE_TYPE_COMMONS,
233
                    ]);
234
                } catch (MemberException $e) {
235
                    $errors["postcode"] = gettext("Sorry, we could not find an MP for that postcode.");
236
                }
237
            }
238
        }
239
240
        // No checking of URL.
241
242
243
        if ($this_page == "otheruseredit") {
244
245
            // We're editing another user's info.
246
247
            // Could check status here...?
248
249
250
        }
251
252
        // Send the array of any errors back...
253
        return $errors;
254
    }
255
256
    public function update($details) {
257
        global $THEUSER, $this_page, $PAGE;
258
259
        $results = [];
260
        // There were no errors when the edit user form was submitted,
261
        // so make the changes in the DB.
262
263
        // Who are we updating? $THEUSER or someone else?
264
        if ($this_page == "otheruseredit") {
265
            $who = 'the user&rsquo;s';
266
            $success = $THEUSER->update_other_user($details);
267
        } else {
268
            $who = 'your';
269
            $success = $THEUSER->update_self($details);
270
        }
271
272
273
        if ($success) {
274
            // No errors, all updated, show results.
275
276
            if ($this_page == 'otheruseredit') {
277
                $this_page = "userview";
278
            } else {
279
                $this_page = "userviewself";
280
            }
281
282
            if ($details['email'] != $THEUSER->email()) {
283
                $results['email_changed'] = true;
284
            }
285
286
287
        } else {
288
            $results['errors'] = ["db" => "Sorry, we were unable to update $who details. Please <a href=\"mailto:" . str_replace('@', '&#64;', CONTACTEMAIL) . "\">let us know</a> what you were trying to change. Thanks."];
289
        }
290
291
        return $results;
292
    }
293
294
    public function add($details) {
295
        global $THEUSER, $PAGE, $this_page;
296
297
298
        // If this goes well, the user will have their data
299
        // added to the database and a confirmation email
300
        // will be sent to them.
301
        $success = $THEUSER->add($details);
302
303
        $errors = [];
304
305
        if (!$success) {
306
            $errors["db"] = "Sorry, we were unable to create an account for you. Please <a href=\"mailto:" . str_replace('@', '&#64;', CONTACTEMAIL) . "\">let us know</a>. Thanks.";
307
        }
308
309
        return $errors;
310
    }
311
312 4
    public function getRep($cons_type, $mp_house) {
313 4
        global $THEUSER;
314 4
        if (!$THEUSER->has_postcode()) {
315 4
            return [];
316
        }
317
318
        // User is logged in and has a postcode, or not logged in with a cookied postcode.
319
320
        // (We don't allow the user to search for a postcode if they
321
        // already have one set in their prefs.)
322
323
        // this is for people who have e.g. an English postcode looking at the
324
        // Scottish homepage
325
        try {
326
            $constituencies = \MySociety\TheyWorkForYou\Utility\Postcode::postcodeToConstituencies($THEUSER->postcode());
327
            if (isset($constituencies[$cons_type])) {
328
                $constituency = $constituencies[$cons_type];
329
                $MEMBER = new Member(['constituency' => $constituency, 'house' => $mp_house]);
330
            }
331
        } catch (MemberException $e) {
332
            return [];
333
        }
334
335
        if (isset($MEMBER) && $MEMBER->valid) {
336
            return $this->constructMPData($MEMBER, $THEUSER, $mp_house);
337
        }
338
339
        return [];
340
    }
341
342
    private function constructMPData($member, $user, $mp_house) {
343
        $mp_data = [];
344
        $mp_data['name'] = $member->full_name();
345
        $mp_data['party'] = $member->party();
346
        $mp_data['constituency'] = $member->constituency();
347
        $left_house = $member->left_house();
348
        $mp_data['former'] = '';
349
        if ($left_house[$mp_house]['date'] != '9999-12-31') {
350
            $mp_data['former'] = 'former';
351
        }
352
        $mp_data['postcode'] = $user->postcode();
353
        $mp_data['mp_url'] = $member->url();
354
        $mp_data['change_url'] = $this->getPostCodeChangeURL();
355
356
        $image = $member->image();
357
        $mp_data['image'] = $image['url'];
358
359
        return $mp_data;
360
    }
361
362 2
    public function getRegionalReps($cons_type, $mp_house) {
363 2
        global $THEUSER;
364
365 2
        $mreg = [];
366 2
        if ($THEUSER->isloggedin() && $THEUSER->postcode() != '' || $THEUSER->postcode_is_set()) {
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ($THEUSER->isloggedin() ...USER->postcode_is_set(), Probably Intended Meaning: $THEUSER->isloggedin() &...SER->postcode_is_set())
Loading history...
367
            $reps = \MySociety\TheyWorkForYou\Member::getRegionalList($THEUSER->postcode, $mp_house, $cons_type);
368
            foreach ($reps as $rep) {
369
                $member = new \MySociety\TheyWorkForYou\Member(['person_id' => $rep['person_id']]);
370
                $mreg[$rep['person_id']] = $this->constructMPData($member, $THEUSER, $mp_house);
371
            }
372
        }
373
374 2
        return $mreg;
375
    }
376
377
    public function getPostCodeChangeURL() {
378
        global $THEUSER;
379
        $CHANGEURL = new Url('userchangepc');
380
        if ($THEUSER->isloggedin()) {
381
            $CHANGEURL = new Url('useredit');
382
        }
383
384
        return $CHANGEURL->generate();
385
    }
386
387
388
}
389