AdvancedUserAccount   F
last analyzed

Complexity

Total Complexity 61

Size/Duplication

Total Lines 603
Duplicated Lines 0 %

Coupling/Cohesion

Components 8
Dependencies 1

Importance

Changes 0
Metric Value
wmc 61
lcom 8
cbo 1
dl 0
loc 603
rs 3.517
c 0
b 0
f 0

48 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 1
A setName() 0 6 1
A getName() 0 4 1
A addRole() 0 13 3
A serialize() 0 16 1
A unserialize() 0 19 1
A eraseCredentials() 0 4 1
A getId() 0 4 1
A getSalt() 0 4 1
A getEmail() 0 4 1
A setUsername() 0 6 1
A getUsername() 0 4 1
A getPassword() 0 4 1
A getPlainPassword() 0 4 1
A getLastLogin() 0 4 1
A getConfirmationToken() 0 4 1
A getRoles() 0 9 1
A hasRole() 0 4 1
A isAccountNonExpired() 0 12 4
A isAccountNonLocked() 0 4 1
A isCredentialsNonExpired() 0 12 4
A isCredentialsExpired() 0 4 1
A isEnabled() 0 4 1
A isExpired() 0 4 1
A isLocked() 0 4 1
A isSuperAdmin() 0 4 1
A isAccount() 0 4 2
A removeRole() 0 9 2
A setCredentialsExpireAt() 0 6 1
A setCredentialsExpired() 0 6 1
A setEmail() 0 6 1
A setEnabled() 0 6 1
A setExpired() 0 6 1
A setExpiresAt() 0 6 1
A setPassword() 0 6 1
A setSuperAdmin() 0 10 2
A setPlainPassword() 0 6 1
A setLastLogin() 0 6 1
A setLocked() 0 6 1
A setConfirmationToken() 0 6 1
A setPasswordRequestedAt() 0 6 1
A getPasswordRequestedAt() 0 4 1
A isPasswordRequestNonExpired() 0 5 2
A setRoles() 0 10 2
A getLocale() 0 4 1
A setLocale() 0 6 1
A __toString() 0 4 1
A canonicalize() 0 4 1

How to fix   Complexity   

Complex Class

Complex classes like AdvancedUserAccount 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 AdvancedUserAccount, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace BWC\Share\Symfony\Security\User;
4
5
use Symfony\Component\Security\Core\Role\Role;
6
7
class AdvancedUserAccount implements AdvancedUserAccountInterface
8
{
9
    /** @var int */
10
    protected $id;
11
12
    /** @var  string */
13
    protected $username;
14
15
    /** @var string */
16
    protected $email;
17
18
    /** @var string */
19
    protected $name;
20
21
    /** @var boolean */
22
    protected $enabled;
23
24
    /** @var string */
25
    protected $salt;
26
27
    /**
28
     * Encrypted password. Must be persisted.
29
     * @var string
30
     */
31
    protected $password;
32
33
    /**
34
     * Plain password. Used for model validation. Must not be persisted.
35
     * @var string
36
     */
37
    protected $plainPassword;
38
39
    /** @var \DateTime */
40
    protected $lastLogin;
41
42
    /**
43
     * Random string sent to the user email address in order to verify it
44
     *
45
     * @var string
46
     */
47
    protected $confirmationToken;
48
49
    /** @var \DateTime */
50
    protected $passwordRequestedAt;
51
52
    /** @var boolean */
53
    protected $locked;
54
55
    /** @var boolean */
56
    protected $expired;
57
58
    /** @var \DateTime */
59
    protected $expiresAt;
60
61
    /** @var array */
62
    protected $roles;
63
64
    /** @var boolean */
65
    protected $credentialsExpired;
66
67
    /** @var \DateTime */
68
    protected $credentialsExpireAt;
69
70
    /** @var  string */
71
    protected $locale;
72
73
74
75
76
77
    public function __construct()
78
    {
79
        $this->salt = base_convert(sha1(uniqid(mt_rand(), true)), 16, 36);
80
        $this->enabled = false;
81
        $this->locked = false;
82
        $this->expired = false;
83
        $this->roles = array();
84
        $this->credentialsExpired = false;
85
    }
86
87
88
89
    /**
90
     * @param string $name
91
     * @return AdvancedUserAccountInterface|$this
92
     */
93
    public function setName($name)
94
    {
95
        $this->name = $name;
96
97
        return $this;
98
    }
99
100
    /**
101
     * @return string
102
     */
103
    public function getName()
104
    {
105
        return $this->name;
106
    }
107
108
    /**
109
     * @param string|Role $role
110
     * @return $this|AdvancedUserAccountInterface
111
     */
112
    public function addRole($role)
113
    {
114
        $role = strtoupper($role);
115
        if ($role === static::ROLE_DEFAULT) {
116
            return $this;
117
        }
118
119
        if (!in_array($role, $this->roles, true)) {
120
            $this->roles[] = $role;
121
        }
122
123
        return $this;
124
    }
125
126
    /**
127
     * Serializes the user.
128
     *
129
     * The serialized data have to contain the fields used by the equals method and the username.
130
     *
131
     * @return string
132
     */
133
    public function serialize()
134
    {
135
        return serialize(
136
            array(
137
                $this->id,
138
                $this->password,
139
                $this->salt,
140
                $this->name,
141
                $this->expired,
142
                $this->locked,
143
                $this->credentialsExpired,
144
                $this->enabled,
145
                $this->locale,
146
            )
147
        );
148
    }
149
150
    /**
151
     * Unserializes the user.
152
     *
153
     * @param string $serialized
154
     */
155
    public function unserialize($serialized)
156
    {
157
        $data = unserialize($serialized);
158
        // add a few extra elements in the array to ensure that we have enough keys when unserializing
159
        // older data which does not include all properties.
160
        $data = array_merge($data, array_fill(0, 2, null));
161
162
        list(
163
            $this->id,
164
            $this->password,
165
            $this->salt,
166
            $this->name,
167
            $this->expired,
168
            $this->locked,
169
            $this->credentialsExpired,
170
            $this->enabled,
171
            $this->locale
172
            ) = $data;
173
    }
174
175
    /**
176
     * Removes sensitive data from the user.
177
     */
178
    public function eraseCredentials()
179
    {
180
        $this->plainPassword = null;
181
    }
182
183
    /**
184
     * @return mixed
185
     */
186
    public function getId()
187
    {
188
        return $this->id;
189
    }
190
191
    /**
192
     * @return string
193
     */
194
    public function getSalt()
195
    {
196
        return $this->salt;
197
    }
198
199
    /**
200
     * @return string
201
     */
202
    public function getEmail()
203
    {
204
        return $this->email;
205
    }
206
207
    /**
208
     * @param string $username
209
     * @return AdvancedUserAccountInterface
210
     */
211
    public function setUsername($username)
212
    {
213
        $this->username = $username;
214
215
        return $this;
216
    }
217
218
    /**
219
     * Returns the username used to authenticate the user.
220
     *
221
     * @return string The username
222
     */
223
    public function getUsername()
224
    {
225
        return $this->username;
226
    }
227
228
229
    /**
230
     * Gets the encrypted password.
231
     * @return string
232
     */
233
    public function getPassword()
234
    {
235
        return $this->password;
236
    }
237
238
    /**
239
     * @return string
240
     */
241
    public function getPlainPassword()
242
    {
243
        return $this->plainPassword;
244
    }
245
246
    /**
247
     * @return \DateTime
248
     */
249
    public function getLastLogin()
250
    {
251
        return $this->lastLogin;
252
    }
253
254
    /**
255
     * @return string
256
     */
257
    public function getConfirmationToken()
258
    {
259
        return $this->confirmationToken;
260
    }
261
262
    /**
263
     * @return array The roles
264
     */
265
    public function getRoles()
266
    {
267
        $roles = $this->roles;
268
269
        // we need to make sure to have at least one role
270
        $roles[] = static::ROLE_DEFAULT;
271
272
        return array_unique($roles);
273
    }
274
275
    /**
276
     * Never use this to check if this user has access to anything!
277
     *
278
     * Use the SecurityContext, or an implementation of AccessDecisionManager
279
     * instead, e.g.
280
     *
281
     *         $securityContext->isGranted('ROLE_USER');
282
     *
283
     * @param string $role
284
     *
285
     * @return boolean
286
     */
287
    public function hasRole($role)
288
    {
289
        return in_array(strtoupper($role), $this->getRoles(), true);
290
    }
291
292
    /**
293
     * @return bool
294
     */
295
    public function isAccountNonExpired()
296
    {
297
        if (true === $this->expired) {
298
            return false;
299
        }
300
301
        if (null !== $this->expiresAt && $this->expiresAt->getTimestamp() < time()) {
302
            return false;
303
        }
304
305
        return true;
306
    }
307
308
    /**
309
     * @return bool
310
     */
311
    public function isAccountNonLocked()
312
    {
313
        return !$this->locked;
314
    }
315
316
    /**
317
     * @return bool
318
     */
319
    public function isCredentialsNonExpired()
320
    {
321
        if (true === $this->credentialsExpired) {
322
            return false;
323
        }
324
325
        if (null !== $this->credentialsExpireAt && $this->credentialsExpireAt->getTimestamp() < time()) {
326
            return false;
327
        }
328
329
        return true;
330
    }
331
332
    /**
333
     * @return bool
334
     */
335
    public function isCredentialsExpired()
336
    {
337
        return !$this->isCredentialsNonExpired();
338
    }
339
340
    /**
341
     * @return bool
342
     */
343
    public function isEnabled()
344
    {
345
        return $this->enabled;
346
    }
347
348
    /**
349
     * @return bool
350
     */
351
    public function isExpired()
352
    {
353
        return !$this->isAccountNonExpired();
354
    }
355
356
    /**
357
     * @return bool
358
     */
359
    public function isLocked()
360
    {
361
        return !$this->isAccountNonLocked();
362
    }
363
364
    /**
365
     * @return bool
366
     */
367
    public function isSuperAdmin()
368
    {
369
        return $this->hasRole(static::ROLE_SUPER_ADMIN);
370
    }
371
372
    /**
373
     * @param AdvancedUserAccountInterface $account
374
     * @return bool
375
     */
376
    public function isAccount(AdvancedUserAccountInterface $account = null)
377
    {
378
        return null !== $account && $this->getId() === $account->getId();
379
    }
380
381
    /**
382
     * @param string $role
383
     * @return $this|AdvancedUserAccountInterface
384
     */
385
    public function removeRole($role)
386
    {
387
        if (false !== $key = array_search(strtoupper($role), $this->roles, true)) {
388
            unset($this->roles[$key]);
389
            $this->roles = array_values($this->roles);
390
        }
391
392
        return $this;
393
    }
394
395
    /**
396
     * @param \DateTime $date
397
     * @return $this|AdvancedUserAccountInterface
398
     */
399
    public function setCredentialsExpireAt(\DateTime $date)
400
    {
401
        $this->credentialsExpireAt = $date;
402
403
        return $this;
404
    }
405
406
    /**
407
     * @param boolean $boolean
408
     * @return $this|AdvancedUserAccountInterface
409
     */
410
    public function setCredentialsExpired($boolean)
411
    {
412
        $this->credentialsExpired = $boolean;
413
414
        return $this;
415
    }
416
417
    /**
418
     * @param string $email
419
     * @return $this|AdvancedUserAccountInterface
420
     */
421
    public function setEmail($email)
422
    {
423
        $this->email = $this->canonicalize($email);
424
425
        return $this;
426
    }
427
428
    public function setEnabled($boolean)
429
    {
430
        $this->enabled = (Boolean) $boolean;
431
432
        return $this;
433
    }
434
435
    /**
436
     * @param Boolean $boolean
437
     * @return $this|AdvancedUserAccountInterface
438
     */
439
    public function setExpired($boolean)
440
    {
441
        $this->expired = (Boolean) $boolean;
442
443
        return $this;
444
    }
445
446
    /**
447
     * @param \DateTime $date
448
     * @return $this|AdvancedUserAccountInterface
449
     */
450
    public function setExpiresAt(\DateTime $date)
451
    {
452
        $this->expiresAt = $date;
453
454
        return $this;
455
    }
456
457
    /**
458
     * @param string $password
459
     * @return $this|AdvancedUserAccountInterface
460
     */
461
    public function setPassword($password)
462
    {
463
        $this->password = $password;
464
465
        return $this;
466
    }
467
468
    /**
469
     * @param bool $boolean
470
     * @return $this|AdvancedUserAccountInterface
471
     */
472
    public function setSuperAdmin($boolean)
473
    {
474
        if (true === $boolean) {
475
            $this->addRole(static::ROLE_SUPER_ADMIN);
476
        } else {
477
            $this->removeRole(static::ROLE_SUPER_ADMIN);
478
        }
479
480
        return $this;
481
    }
482
483
    /**
484
     * @param string $password
485
     * @return $this|AdvancedUserAccountInterface
486
     */
487
    public function setPlainPassword($password)
488
    {
489
        $this->plainPassword = $password;
490
491
        return $this;
492
    }
493
494
    /**
495
     * @param \DateTime $time
496
     * @return $this|AdvancedUserAccountInterface
497
     */
498
    public function setLastLogin(\DateTime $time)
499
    {
500
        $this->lastLogin = $time;
501
502
        return $this;
503
    }
504
505
    /**
506
     * @param bool $boolean
507
     * @return $this|AdvancedUserAccountInterface
508
     */
509
    public function setLocked($boolean)
510
    {
511
        $this->locked = $boolean;
512
513
        return $this;
514
    }
515
516
    /**
517
     * @param string $confirmationToken
518
     * @return $this|AdvancedUserAccountInterface
519
     */
520
    public function setConfirmationToken($confirmationToken)
521
    {
522
        $this->confirmationToken = $confirmationToken;
523
524
        return $this;
525
    }
526
527
    /**
528
     * @param \DateTime $date
529
     * @return $this|AdvancedUserAccountInterface
530
     */
531
    public function setPasswordRequestedAt(\DateTime $date = null)
532
    {
533
        $this->passwordRequestedAt = $date;
534
535
        return $this;
536
    }
537
538
    /**
539
     * @return null|\DateTime
540
     */
541
    public function getPasswordRequestedAt()
542
    {
543
        return $this->passwordRequestedAt;
544
    }
545
546
    /**
547
     * @param int $ttl
548
     * @return bool
549
     */
550
    public function isPasswordRequestNonExpired($ttl)
551
    {
552
        return $this->getPasswordRequestedAt() instanceof \DateTime &&
553
        $this->getPasswordRequestedAt()->getTimestamp() + $ttl > time();
554
    }
555
556
    /**
557
     * @param array $roles
558
     * @return $this|AdvancedUserAccountInterface
559
     */
560
    public function setRoles(array $roles)
561
    {
562
        $this->roles = array();
563
564
        foreach ($roles as $role) {
565
            $this->addRole($role);
566
        }
567
568
        return $this;
569
    }
570
571
    /**
572
     * @return string
573
     */
574
    public function getLocale()
575
    {
576
        return $this->locale;
577
    }
578
579
    /**
580
     * @param string $locale
581
     * @return AdvancedUserAccountInterface|$this
582
     */
583
    public function setLocale($locale)
584
    {
585
        $this->locale = $locale;
586
587
        return $this;
588
    }
589
590
591
592
    /**
593
     * @return string
594
     */
595
    public function __toString()
596
    {
597
        return (string) $this->getUsername();
598
    }
599
600
601
    /**
602
     * @param $string
603
     * @return string
604
     */
605
    protected function canonicalize($string)
606
    {
607
        return mb_convert_case($string, MB_CASE_LOWER, mb_detect_encoding($string));
608
    }
609
}