Completed
Pull Request — master (#2737)
by
unknown
21:09
created

BaseUser::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
3
namespace Kunstmaan\AdminBundle\Entity;
4
5
use DateTime;
6
use Doctrine\Common\Collections\ArrayCollection;
7
use Doctrine\ORM\Mapping as ORM;
8
use FOS\UserBundle\Model\GroupInterface;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Kunstmaan\AdminBundle\Entity\GroupInterface.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
9
use Kunstmaan\AdminBundle\Validator\Constraints\PasswordRestrictions;
10
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
11
use Symfony\Component\Validator\Constraints\Email;
12
use Symfony\Component\Validator\Constraints\NotBlank;
13
use Symfony\Component\Validator\Mapping\ClassMetadata;
14
15
abstract class BaseUser implements UserInterface
16
{
17
    /**
18
     * @ORM\Id
19
     * @ORM\Column(type="integer")
20
     * @ORM\GeneratedValue(strategy="AUTO")
21
     */
22
    protected $id;
23
24
    /**
25
     * @var string
26
     *
27
     * @ORM\Column(type="string", length=180, unique=true)
28
     */
29
    protected $username;
30
31
    /**
32
     * Next Major: Remove attribute
33
     *
34
     * @var string
35
     *
36
     * @ORM\Column(type="string", length=180, unique=true)
37
     */
38
    protected $usernameCanonical;
39
40
    /**
41
     * The doctrine metadata is set dynamically in Kunstmaan\AdminBundle\EventListener\MappingListener
42
     */
43
    protected $groups;
44
45
    /**
46
     * @ORM\Column(type="string", name="admin_locale", length=5, nullable=true)
47
     */
48
    protected $adminLocale;
49
50
    /**
51
     * @ORM\Column(type="boolean", name="password_changed", nullable=true)
52
     */
53
    protected $passwordChanged;
54
55
    /**
56
     * @ORM\Column(name="google_id", type="string", length=255, nullable=true)
57
     */
58
    protected $googleId;
59
60
    /**
61
     * @var string
62
     *
63
     * @ORM\Column(type="string", length=180, unique=true)
64
     */
65
    protected $email;
66
67
    /**
68
     * Next Major: Remove attribute
69
     *
70
     * @var string
71
     *
72
     * @ORM\Column(type="string", length=180, unique=true)
73
     */
74
    protected $emailCanonical;
75
76
    /**
77
     * @var string
78
     *
79
     * @ORM\Column(name="password", type="string", length=100)
80
     */
81
    protected $password;
82
83
    /**
84
     * @var string|null
85
     */
86
    protected $plainPassword;
87
88
    /**
89
     * @var string|null
90
     *
91
     * @ORM\Column(type="string", length=255, nullable=true)
92
     */
93
    protected $confirmationToken;
94
95
    /**
96
     * @var string
97
     *
98
     * @ORM\Column(name="salt", type="string", length=100)
99
     */
100
    protected $salt;
101
102
    /**
103
     * @var \DateTime
104
     *
105
     * @ORM\Column(name="last_login", type="datetime", nullable=true)
106
     */
107
    protected $lastLogin;
108
109
    /**
110
     * @var array
111
     *
112
     * @ORM\Column(name="roles", type="array")
113
     */
114
    protected $roles;
115
116
    /**
117
     * @ORM\Column(name="enabled", type="boolean")
118
     */
119
    protected $enabled;
120
121
    /**
122
     * @var \DateTimeImmutable|null
123
     * @ORM\Column(name="created_at", type="datetime_immutable", nullable=true)
124
     */
125
    protected $createdAt;
126
127
    /**
128
     * @var string|null
129
     * @ORM\Column(name="created_by", type="string", nullable=true)
130
     */
131
    protected $createdBy;
132
133
    /**
134
     * Construct a new user
135
     */
136 35
    public function __construct()
137
    {
138 35
        $this->groups = new ArrayCollection();
139 35
        $this->roles = [];
140 35
        $this->createdAt = new \DateTimeImmutable();
141 35
    }
142
143
    /**
144
     * Get id
145
     *
146
     * @return int
147
     */
148 3
    public function getId()
149
    {
150 3
        return $this->id;
151
    }
152
153
    /**
154
     * Set id
155
     *
156
     * @param int $id
157
     *
158
     * @return BaseUser
159
     */
160 8
    public function setId($id)
161
    {
162 8
        $this->id = $id;
163
164 8
        return $this;
165
    }
166
167
    /**
168
     * Gets the groupIds for the user.
169
     *
170
     * @return array
171
     */
172 1
    public function getGroupIds()
173
    {
174 1
        $groups = $this->groups;
175
176 1
        $groupIds = [];
177 1
        if (\count($groups) > 0) {
178
            /* @var $group GroupInterface */
179 1
            foreach ($groups as $group) {
180 1
                $groupIds[] = $group->getId();
181
            }
182
        }
183
184 1
        return $groupIds;
185
    }
186
187
    /**
188
     * Gets the groups the user belongs to.
189
     *
190
     * @return ArrayCollection
191
     */
192 5
    public function getGroups()
193
    {
194 5
        return $this->groups;
195
    }
196
197
    /**
198
     * Get adminLocale
199
     *
200
     * @return string
201
     */
202 1
    public function getAdminLocale()
203
    {
204 1
        return $this->adminLocale;
205
    }
206
207
    /**
208
     * {@inheritdoc}
209
     */
210 2
    public function setEnabled($boolean)
211
    {
212 2
        $this->enabled = (bool) $boolean;
213
214 2
        return $this;
215
    }
216
217
    /**
218
     * Set adminLocale
219
     *
220
     * @param string $adminLocale
221
     *
222
     * @return BaseUser
223
     */
224 2
    public function setAdminLocale($adminLocale)
225
    {
226 2
        $this->adminLocale = $adminLocale;
227
228 2
        return $this;
229
    }
230
231
    /**
232
     * is passwordChanged
233
     *
234
     * @return bool
235
     */
236 1
    public function isPasswordChanged()
237
    {
238 1
        return $this->passwordChanged;
239
    }
240
241 2
    public function setPasswordChanged($passwordChanged)
242
    {
243 2
        $this->passwordChanged = $passwordChanged;
244
245 2
        return $this;
246
    }
247
248
    /**
249
     * @return mixed
250
     */
251 1
    public function getGoogleId()
252
    {
253 1
        return $this->googleId;
254
    }
255
256
    /**
257
     * @param mixed $googleId
258
     */
259 3
    public function setGoogleId($googleId)
260
    {
261 3
        $this->googleId = $googleId;
262 3
    }
263
264 1
    public static function loadValidatorMetadata(ClassMetadata $metadata)
265
    {
266 1
        $metadata->addPropertyConstraint('username', new NotBlank());
267 1
        $metadata->addPropertyConstraints(
268 1
            'plainPassword',
269
            [
270 1
                new NotBlank(['groups' => ['Registration']]),
271 1
                new PasswordRestrictions(['groups' => ['Registration', 'Default']]),
272
            ]
273
        );
274 1
        $metadata->addPropertyConstraint('email', new NotBlank());
275 1
        $metadata->addPropertyConstraint('email', new Email());
276 1
        $metadata->addConstraint(new UniqueEntity([
277 1
            'fields' => 'username',
278
            'message' => 'errors.user.loginexists',
279
        ]));
280 1
        $metadata->addConstraint(new UniqueEntity([
281 1
            'fields' => 'email',
282
            'message' => 'errors.user.emailexists',
283
        ]));
284 1
    }
285
286
    /**
287
     * Return class name of form type used to add & edit users
288
     *
289
     * @return string
290
     */
291
    abstract public function getFormTypeClass();
292
293
    /**
294
     * {@inheritdoc}
295
     */
296 1
    public function isAccountNonLocked()
297
    {
298 1
        return $this->isEnabled();
299
    }
300
301
    public function getEmail(): string
302
    {
303
        return $this->email;
304
    }
305
306 1
    public function setEmail($email)
307
    {
308 1
        $this->email = $email;
309
310 1
        return $this;
311
    }
312
313
    public function getPassword(): string
314
    {
315
        return $this->password;
316
    }
317
318
    public function setPassword($password)
319
    {
320
        $this->password = $password;
321
322
        return $this;
323
    }
324
325
    public function getPlainPassword(): ?string
326
    {
327
        return $this->plainPassword;
328
    }
329
330 1
    public function setPlainPassword($plainPassword)
331
    {
332 1
        $this->plainPassword = $plainPassword;
333
334 1
        return $this;
335
    }
336
337
    /**
338
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
339
     */
340 1
    public function getRoles()
341
    {
342 1
        $roles = $this->roles;
343
344 1
        foreach ($this->getGroups() as $group) {
345
            $roles = array_merge($roles, $group->getRoles());
346
        }
347
348
        // we need to make sure to have at least one role
349 1
        $roles[] = static::ROLE_DEFAULT;
350
351 1
        return array_unique($roles);
352
    }
353
354 1
    public function hasRole($role)
355
    {
356 1
        return in_array(strtoupper($role), $this->getRoles(), true);
357
    }
358
359
    /**
360
     * {@inheritdoc}
361
     */
362
    public function setRoles(array $roles)
363
    {
364
        $this->roles = [];
365
366
        foreach ($roles as $role) {
367
            $this->addRole($role);
368
        }
369
370
        return $this;
371
    }
372
373 1
    public function removeRole($role)
374
    {
375 1
        if (false !== $key = array_search(strtoupper($role), $this->roles, true)) {
376 1
            unset($this->roles[$key]);
377 1
            $this->roles = array_values($this->roles);
378
        }
379
380 1
        return $this;
381
    }
382
383
    public function getSalt(): ?string
384
    {
385
        return $this->salt;
386
    }
387
388
    public function setSalt($salt)
389
    {
390
        $this->salt = $salt;
391
392
        return $this;
393
    }
394
395 1
    public function isEnabled()
396
    {
397 1
        return $this->enabled;
398
    }
399
400
    /**
401
     * @return string The username
402
     */
403 7
    public function getUsername(): string
404
    {
405 7
        return $this->username;
406
    }
407
408 8
    public function setUsername($username)
409
    {
410 8
        $this->username = $username;
411
412 8
        return $this;
413
    }
414
415
    /**
416
     * Removes sensitive data from the user.
417
     */
418
    public function eraseCredentials(): void
419
    {
420
        $this->plainPassword = null;
421
    }
422
423
    /**
424
     * {@inheritdoc}
425
     */
426 1
    public function addRole($role)
427
    {
428 1
        $role = strtoupper($role);
429 1
        if ($role === static::ROLE_DEFAULT) {
430
            return $this;
431
        }
432
433 1
        if (!in_array($role, $this->roles, true)) {
434 1
            $this->roles[] = $role;
435
        }
436
437 1
        return $this;
438
    }
439
440
    /**
441
     * {@inheritdoc}
442
     */
443
    public function getGroupNames()
444
    {
445
        $names = [];
446
        foreach ($this->getGroups() as $group) {
447
            $names[] = $group->getName();
448
        }
449
450
        return $names;
451
    }
452
453
    /**
454
     * {@inheritdoc}
455
     */
456
    public function hasGroup($name)
457
    {
458
        return in_array($name, $this->getGroupNames());
459
    }
460
461
    /**
462
     * {@inheritdoc}
463
     */
464 4
    public function addGroup(GroupInterface $group)
465
    {
466 4
        if (!$this->getGroups()->contains($group)) {
467 4
            $this->getGroups()->add($group);
468
        }
469
470 4
        return $this;
471
    }
472
473
    /**
474
     * {@inheritdoc}
475
     */
476
    public function removeGroup(GroupInterface $group)
477
    {
478
        if ($this->getGroups()->contains($group)) {
479
            $this->getGroups()->removeElement($group);
480
        }
481
482
        return $this;
483
    }
484
485
    public function __toString()
486
    {
487
        return (string) $this->getUsername();
488
    }
489
490
    public function getUsernameCanonical()
491
    {
492
        // NEXT_MAJOR remove method
493
        @trigger_error(sprintf('Using method %s from class %s is deprecated since KunstmaanAdminBundle 5.8 and will be removed in KunstmaanAdminBundle 6.0.', __METHOD__, BaseUser::class), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
494
495
        return $this->usernameCanonical;
496
    }
497
498
    public function setUsernameCanonical($usernameCanonical)
499
    {
500
        // NEXT_MAJOR remove method
501
        @trigger_error(sprintf('Using method %s from class %s is deprecated since KunstmaanAdminBundle 5.8 and will be removed in KunstmaanAdminBundle 6.0.', __METHOD__, BaseUser::class), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
502
503
        $this->usernameCanonical = $usernameCanonical;
504
    }
505
506
    public function getEmailCanonical()
507
    {
508
        // NEXT_MAJOR remove method
509
        @trigger_error(sprintf('Using method %s from class %s is deprecated since KunstmaanAdminBundle 5.8 and will be removed in KunstmaanAdminBundle 6.0.', __METHOD__, BaseUser::class), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
510
511
        return $this->emailCanonical;
512
    }
513
514
    public function setEmailCanonical($emailCanonical)
515
    {
516
        // NEXT_MAJOR remove method
517
        @trigger_error(sprintf('Using method %s from class %s is deprecated since KunstmaanAdminBundle 5.8 and will be removed in KunstmaanAdminBundle 6.0.', __METHOD__, BaseUser::class), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
518
519
        $this->emailCanonical = $emailCanonical;
520
    }
521
522 1
    public function isSuperAdmin()
523
    {
524
        // NEXT_MAJOR remove method
525 1
        @trigger_error(sprintf('Using method %s from class %s is deprecated since KunstmaanAdminBundle 5.8 and will be removed in KunstmaanAdminBundle 6.0.', __METHOD__, BaseUser::class), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
526 1
    }
527
528
    public function setSuperAdmin($boolean)
529
    {
530
        // NEXT_MAJOR remove method
531
        @trigger_error(sprintf('Using method %s from class %s is deprecated since KunstmaanAdminBundle 5.8 and will be removed in KunstmaanAdminBundle 6.0.', __METHOD__, BaseUser::class), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
532
    }
533
534
    public function getConfirmationToken()
535
    {
536
        return $this->confirmationToken;
537
    }
538
539
    public function setConfirmationToken($confirmationToken)
540
    {
541
        $this->confirmationToken = $confirmationToken;
542
    }
543
544
    public function setPasswordRequestedAt(DateTime $date = null)
545
    {
546
        // NEXT_MAJOR remove method
547
        @trigger_error(sprintf('Using method %s from class %s is deprecated since KunstmaanAdminBundle 5.8 and will be removed in KunstmaanAdminBundle 6.0.', __METHOD__, BaseUser::class), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
548
    }
549
550
    public function getLastLogin()
551
    {
552
        return $this->lastLogin;
553
    }
554
555
    public function setLastLogin(?DateTime $lastLogin = null)
556
    {
557
        $this->lastLogin = $lastLogin;
558
559
        return $this;
560
    }
561
562
    public function getCreatedAt(): ?\DateTimeImmutable
563
    {
564
        return $this->createdAt;
565
    }
566
567
    public function getCreatedBy(): ?string
568
    {
569
        return $this->createdBy;
570
    }
571
572
    public function setCreatedBy(string $createdBy): void
573
    {
574
        $this->createdBy = $createdBy;
575
    }
576
577
    public function isAccountNonExpired()
578
    {
579
        // NEXT_MAJOR remove method
580
        @trigger_error(sprintf('Using method %s from class %s is deprecated since KunstmaanAdminBundle 5.8 and will be removed in KunstmaanAdminBundle 6.0.', __METHOD__, BaseUser::class), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
581
582
        return true;
583
    }
584
585
    public function isCredentialsNonExpired()
586
    {
587
        // NEXT_MAJOR remove method
588
        @trigger_error(sprintf('Using method %s from class %s is deprecated since KunstmaanAdminBundle 5.8 and will be removed in KunstmaanAdminBundle 6.0.', __METHOD__, BaseUser::class), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
589
590
        return true;
591
    }
592
593
    public function isPasswordRequestNonExpired($ttl)
594
    {
595
        // NEXT_MAJOR remove method
596
        @trigger_error(sprintf('Using method %s from class %s is deprecated since KunstmaanAdminBundle 5.8 and will be removed in KunstmaanAdminBundle 6.0.', __METHOD__, BaseUser::class), E_USER_DEPRECATED);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
597
598
        return false;
599
    }
600
601
    /**
602
     * {@inheritdoc}
603
     */
604
    public function serialize()
605
    {
606
        return serialize([
607
            $this->password,
608
            $this->salt,
609
            $this->username,
610
            $this->enabled,
611
            $this->id,
612
            $this->email,
613
        ]);
614
    }
615
616
    /**
617
     * {@inheritdoc}
618
     */
619
    public function unserialize($serialized)
620
    {
621
        $data = unserialize($serialized);
622
623
        [
624
            $this->password,
625
            $this->salt,
626
            $this->username,
627
            $this->enabled,
628
            $this->id,
629
            $this->email,
630
        ] = $data;
631
    }
632
}
633