Completed
Push — master ( 22f213...24f6ce )
by Guilherme
17:25
created

Person::waitUpdate()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 13
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
nc 1
nop 2
dl 0
loc 13
rs 9.4285
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A Person::getGivenName() 0 4 1
1
<?php
2
/**
3
 * This file is part of the login-cidadao project or it's bundles.
4
 *
5
 * (c) Guilherme Donato <guilhermednt on github>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace LoginCidadao\CoreBundle\Entity;
12
13
use Doctrine\ORM\EntityManagerInterface;
14
use Doctrine\ORM\Mapping as ORM;
15
use Doctrine\Common\Collections\ArrayCollection;
16
use Doctrine\Common\Collections\Collection;
17
use libphonenumber\PhoneNumber;
18
use LoginCidadao\CoreBundle\Tests\LongPolling\LongPollableInterface;
19
use Symfony\Component\HttpFoundation\File\File;
20
use Symfony\Component\Validator\Constraints as Assert;
21
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
22
use Scheb\TwoFactorBundle\Model\Google\TwoFactorInterface;
23
use Scheb\TwoFactorBundle\Model\BackupCodeInterface;
24
use Vich\UploaderBundle\Mapping\Annotation as Vich;
25
use JMS\Serializer\Annotation as JMS;
26
use FOS\UserBundle\Model\User as BaseUser;
27
use LoginCidadao\OAuthBundle\Entity\Client;
28
use LoginCidadao\CoreBundle\Model\LocationSelectData;
29
use LoginCidadao\CoreBundle\LongPolling\LongPollingUtils;
30
use LoginCidadao\CoreBundle\Model\PersonInterface;
31
use LoginCidadao\OAuthBundle\Model\ClientInterface;
32
use LoginCidadao\ValidationBundle\Validator\Constraints as LCAssert;
33
use Donato\PathWellBundle\Validator\Constraints\PathWell;
34
use Misd\PhoneNumberBundle\Validator\Constraints\PhoneNumber as AssertPhoneNumber;
35
use Rollerworks\Bundle\PasswordStrengthBundle\Validator\Constraints as RollerworksPassword;
36
37
/**
38
 * @ORM\Entity(repositoryClass="LoginCidadao\CoreBundle\Entity\PersonRepository")
39
 * @ORM\Table(name="person")
40
 * @UniqueEntity("cpf", message="person.validation.cpf.already_used", groups={"LoginCidadaoRegistration", "Registration", "Profile", "LoginCidadaoProfile", "Dynamic", "Documents"})
41
 * @UniqueEntity("username")
42
 * @UniqueEntity(fields="emailCanonical", errorPath="email", message="fos_user.email.already_used", groups={"LoginCidadaoRegistration", "Registration", "LoginCidadaoEmailForm", "LoginCidadaoProfile", "Dynamic"})
43
 * @ORM\HasLifecycleCallbacks
44
 * @JMS\ExclusionPolicy("all")
45
 * @Vich\Uploadable
46
 */
47
class Person extends BaseUser implements PersonInterface, BackupCodeInterface
48
{
49
    /**
50
     * @ORM\Id
51
     * @ORM\Column(type="integer")
52
     * @ORM\GeneratedValue(strategy="AUTO")
53
     * @JMS\Since("1.0")
54
     */
55
    protected $id;
56
57
    /**
58
     * @JMS\Expose
59
     * @JMS\Groups({"first_name","full_name","public_profile","given_name","name"})
60
     * @ORM\Column(type="string", nullable=true)
61
     * @Assert\NotBlank(message="Please enter your name.", groups={"Profile", "LoginCidadaoProfile"})
62
     * @Assert\Length(
63
     *     min=3,
64
     *     max="255",
65
     *     minMessage="The name is too short.",
66
     *     maxMessage="The name is too long.",
67
     *     groups={"Registration", "Profile", "LoginCidadaoProfile"}
68
     * )
69
     * @JMS\Since("1.0")
70
     */
71
    protected $firstName;
72
73
    /**
74
     * @JMS\Expose
75
     * @JMS\Groups({"last_name","full_name","family_name","middle_name","name"})
76
     * @ORM\Column(type="string", nullable=true)
77
     * @Assert\NotBlank(message="Please enter your surname.", groups={"Profile", "LoginCidadaoProfile"})
78
     * @Assert\Length(
79
     *     min=1,
80
     *     max="255",
81
     *     minMessage="The surname is too short.",
82
     *     maxMessage="The surname is too long.",
83
     *     groups={"Registration", "Profile", "LoginCidadaoProfile"}
84
     * )
85
     * @JMS\Since("1.0")
86
     */
87
    protected $surname;
88
89
    /**
90
     * @JMS\Expose
91
     * @JMS\Groups({"username","preferred_username"})
92
     * @Assert\NotBlank
93
     * @Assert\Length(
94
     *     min="1",
95
     *     max="40",
96
     *     groups={"Registration", "Profile", "LoginCidadaoProfile"}
97
     * )
98
     * @JMS\Since("1.0")
99
     */
100
    protected $username;
101
102
    /**
103
     * @JMS\Exclude
104
     * @PathWell(
105
     *     groups={"Registration", "ResetPassword", "ChangePassword", "LoginCidadaoRegistration"}
106
     * )
107
     * @RollerworksPassword\PasswordRequirements(
108
     *     minLength=false,
109
     *     requireLetters=true,
110
     *     requireNumbers=true,
111
     *     missingLettersMessage="person.validation.password.missingLetters",
112
     *     missingNumbersMessage="person.validation.password.missingNumbers",
113
     *     groups={"Registration", "ResetPassword", "ChangePassword", "LoginCidadaoRegistration"}
114
     * )
115
     * @Assert\Length(
116
     *     min=8,
117
     *     max=72,
118
     *     maxMessage="person.validation.password.length.max",
119
     *     minMessage="person.validation.password.length.min",
120
     *     groups={"Registration", "ResetPassword", "ChangePassword", "LoginCidadaoRegistration"}
121
     * )
122
     * @Assert\NotBlank(message="person.validation.password.not_blank", groups={"Registration", "ResetPassword", "ChangePassword", "LoginCidadaoRegistration"})
123
     */
124
    protected $plainPassword;
125
126
    /**
127
     * @JMS\Expose
128
     * @JMS\Groups({"cpf"})
129
     * @ORM\Column(type="string", nullable=true, unique=true)
130
     * @LCAssert\CPF(groups={"Documents", "Dynamic", "LoginCidadaoRegistration"})
131
     * @JMS\Since("1.0")
132
     */
133
    protected $cpf;
134
135
    /**
136
     * @JMS\Expose
137
     * @JMS\Groups({"email"})
138
     * @JMS\Since("1.0")
139
     * @Assert\Email(strict=true, groups={"Profile", "LoginCidadaoProfile", "Registration", "ResetPassword", "ChangePassword", "LoginCidadaoRegistration", "LoginCidadaoEmailForm"})
140
     * @Assert\NotBlank(message="person.validation.email.not_blank", groups={"Profile", "LoginCidadaoProfile", "Registration", "ResetPassword", "ChangePassword", "LoginCidadaoRegistration", "LoginCidadaoEmailForm"})
141
     */
142
    protected $email;
143
144
    /**
145
     * @JMS\Expose
146
     * @JMS\Groups({"birthdate"})
147
     * @ORM\Column(type="date", nullable=true)
148
     * @JMS\Since("1.0")
149
     * @LCAssert\Age(max="150", groups={"Profile", "LoginCidadaoProfile", "Registration", "ResetPassword", "ChangePassword", "LoginCidadaoRegistration", "LoginCidadaoEmailForm"})
150
     */
151
    protected $birthdate;
152
153
    /**
154
     * @ORM\Column(name="email_expiration", type="datetime", nullable=true)
155
     * @JMS\Since("1.0")
156
     */
157
    protected $emailExpiration;
158
159
    /**
160
     * @JMS\Expose
161
     * @JMS\Groups({"mobile","phone_number"})
162
     * @JMS\Type("libphonenumber\PhoneNumber")
163
     * @ORM\Column(type="phone_number", nullable=true)
164
     * @JMS\Since("1.0")
165
     * @LCAssert\E164PhoneNumber(
166
     *     maxMessage="person.validation.mobile.length.max",
167
     *     groups={"Registration", "LoginCidadaoRegistration", "Dynamic", "Profile", "LoginCidadaoProfile"}
168
     * )
169
     * @LCAssert\MobilePhoneNumber(
170
     *     missing9thDigit="person.validation.mobile.9thDigit",
171
     *     groups={"Registration", "LoginCidadaoRegistration", "Dynamic", "Profile", "LoginCidadaoProfile"}
172
     * )
173
     * @AssertPhoneNumber(
174
     *     type="mobile",
175
     *     groups={"Registration", "LoginCidadaoRegistration", "Dynamic", "Profile", "LoginCidadaoProfile"}
176
     * )
177
     */
178
    protected $mobile;
179
180
    /**
181
     * @ORM\Column(type="string", length=255, nullable=true)
182
     * @var string
183
     * @JMS\Since("1.0")
184
     */
185
    protected $twitterPicture;
186
187
    /**
188
     * @JMS\Expose
189
     * @JMS\Groups({"city"})
190
     * @ORM\ManyToOne(targetEntity="LoginCidadao\CoreBundle\Entity\City")
191
     * @ORM\JoinColumn(name="city_id", referencedColumnName="id")
192
     * @JMS\Since("1.0")
193
     */
194
    protected $city;
195
196
    /**
197
     * @var string
198
     *
199
     * @ORM\Column(name="facebookId", type="string", length=255, nullable=true, unique=true)
200
     * @JMS\Since("1.0")
201
     */
202
    protected $facebookId;
203
204
    /**
205
     * @var string
206
     *
207
     * @ORM\Column(name="facebookUsername", type="string", length=255, nullable=true)
208
     * @JMS\Since("1.0")
209
     */
210
    protected $facebookUsername;
211
212
    /**
213
     * @var string
214
     *
215
     * @ORM\Column(name="facebookAccessToken", type="string", length=255, nullable=true)
216
     * @JMS\Since("1.1")
217
     */
218
    protected $facebookAccessToken;
219
220
    /**
221
     * @var string
222
     *
223
     * @ORM\Column(name="twitterId", type="string", length=255, nullable=true, unique=true)
224
     * @JMS\Since("1.0")
225
     */
226
    protected $twitterId;
227
228
    /**
229
     * @var string
230
     *
231
     * @ORM\Column(name="twitterUsername", type="string", length=255, nullable=true)
232
     * @JMS\Since("1.0")
233
     */
234
    protected $twitterUsername;
235
236
    /**
237
     * @var string
238
     *
239
     * @ORM\Column(name="twitterAccessToken", type="string", length=255, nullable=true)
240
     * @JMS\Since("1.0")
241
     */
242
    protected $twitterAccessToken;
243
244
    /**
245
     * @ORM\OneToMany(targetEntity="Authorization", mappedBy="person", cascade={"remove"}, orphanRemoval=true)
246
     */
247
    protected $authorizations;
248
249
    /**
250
     * @ORM\Column(type="datetime", nullable=false)
251
     * @var \DateTime
252
     * @JMS\Since("1.0")
253
     */
254
    protected $createdAt;
255
256
    /**
257
     * @ORM\Column(type="datetime", nullable=true)
258
     * @var \DateTime
259
     * @JMS\Since("1.0")
260
     */
261
    protected $emailConfirmedAt;
262
263
    /**
264
     * @ORM\Column(type="string", length=255, nullable=true)
265
     * @var string
266
     * @JMS\Since("1.0")
267
     */
268
    protected $previousValidEmail;
269
270
    /**
271
     * @ORM\ManyToMany(targetEntity="LoginCidadao\OAuthBundle\Entity\Client", mappedBy="owners")
272
     */
273
    protected $clients;
274
275
    /**
276
     * @ORM\OneToMany(targetEntity="ClientSuggestion", mappedBy="person")
277
     */
278
    protected $suggestions;
279
280
    /**
281
     * @JMS\Expose
282
     * @JMS\Groups({"state"})
283
     * @ORM\ManyToOne(targetEntity="LoginCidadao\CoreBundle\Entity\State")
284
     * @ORM\JoinColumn(name="state_id", referencedColumnName="id")
285
     * @JMS\Since("1.0.2")
286
     */
287
    protected $state;
288
289
    /**
290
     * @JMS\Expose
291
     * @JMS\Groups({"country"})
292
     * @ORM\ManyToOne(targetEntity="LoginCidadao\CoreBundle\Entity\Country")
293
     * @ORM\JoinColumn(name="country_id", referencedColumnName="id")
294
     * @JMS\Since("1.0.2")
295
     */
296
    protected $country;
297
298
    /**
299
     * @Assert\File(
300
     *      maxSize="2M",
301
     *      maxSizeMessage="The maxmimum allowed file size is 2MB.",
302
     *      mimeTypes={"image/png", "image/jpeg", "image/pjpeg"},
303
     *      mimeTypesMessage="Only JPEG and PNG images are allowed."
304
     * )
305
     * @Vich\UploadableField(mapping="user_image", fileNameProperty="imageName")
306
     * @var File $image
307
     * @JMS\Since("1.0.2")
308
     */
309
    protected $image;
310
311
    /**
312
     * @ORM\Column(type="string", length=255, name="image_name", nullable=true)
313
     *
314
     * @var string $imageName
315
     * @JMS\Since("1.0.2")
316
     */
317
    protected $imageName;
318
319
    /**
320
     * @JMS\Expose
321
     * @JMS\Groups({"public_profile","picture"})
322
     * @JMS\Since("1.0.2")
323
     */
324
    protected $profilePictureUrl;
325
326
    /**
327
     * @ORM\Column(type="datetime", nullable=true)
328
     * @JMS\Expose
329
     * @JMS\Groups({"public_profile","updated_at"})
330
     * @var \DateTime $updatedAt
331
     * @JMS\Since("1.0.2")
332
     */
333
    protected $updatedAt;
334
335
    /**
336
     * @var string
337
     *
338
     * @ORM\Column(name="googleId", type="string", length=255, nullable=true, unique=true)
339
     * @JMS\Since("1.0.3")
340
     */
341
    protected $googleId;
342
343
    /**
344
     * @var string
345
     *
346
     * @ORM\Column(name="googleUsername", type="string", length=255, nullable=true)
347
     * @JMS\Since("1.0.3")
348
     */
349
    protected $googleUsername;
350
351
    /**
352
     * @var string
353
     *
354
     * @ORM\Column(name="googleAccessToken", type="string", length=255, nullable=true)
355
     * @JMS\Since("1.0.3")
356
     */
357
    protected $googleAccessToken;
358
359
    /**
360
     * @JMS\Expose
361
     * @JMS\Groups({"id_cards"})
362
     * @ORM\OneToMany(targetEntity="LoginCidadao\CoreBundle\Entity\IdCard", mappedBy="person")
363
     * @JMS\Since("1.0.3")
364
     */
365
    protected $idCards;
366
367
    /**
368
     * @JMS\Expose
369
     * @JMS\Groups({"public_profile"})
370
     * @var array
371
     */
372
    protected $badges = array();
373
374
    /**
375
     * @ORM\OneToMany(targetEntity="LoginCidadao\APIBundle\Entity\LogoutKey", mappedBy="person", cascade={"remove"}, orphanRemoval=true)
376
     */
377
    protected $logoutKeys;
378
379
    /**
380
     * @JMS\Expose
381
     * @JMS\Groups({"addresses","address"})
382
     * @ORM\OneToMany(targetEntity="LoginCidadao\CoreBundle\Entity\PersonAddress", mappedBy="person", cascade={"remove"}, orphanRemoval=true)
383
     */
384
    protected $addresses;
385
386
    /**
387
     * @ORM\Column(name="google_authenticator_secret", type="string", nullable=true)
388
     */
389
    protected $googleAuthenticatorSecret;
390
391
    /**
392
     * @JMS\Expose
393
     * @JMS\Groups({"nationality"})
394
     * @ORM\ManyToOne(targetEntity="LoginCidadao\CoreBundle\Entity\Country")
395
     * @ORM\JoinColumn(name="nationality_id", referencedColumnName="id")
396
     * @JMS\Since("1.0.2")
397
     */
398
    protected $nationality;
399
400
    /**
401
     * @JMS\Exclude
402
     * @ORM\OneToMany(targetEntity="BackupCode", mappedBy="person", cascade={"remove"}, orphanRemoval=true)
403
     */
404
    protected $backupCodes;
405
406
    /**
407
     * @JMS\Exclude
408
     * @ORM\Column(name="password_encoder_name", type="string", length=255, nullable=true)
409
     */
410
    protected $passwordEncoderName;
411
412
    /**
413
     * @JMS\Expose
414
     * @JMS\Groups({"public_profile"})
415
     * @JMS\SerializedName("phone_number_verified")
416
     * @var bool
417
     */
418
    protected $phoneNumberVerified = false;
419
420
    public function __construct()
421
    {
422
        parent::__construct();
423
        $this->authorizations = new ArrayCollection();
424
        $this->clients = new ArrayCollection();
425
        $this->logoutKeys = new ArrayCollection();
426
        $this->addresses = new ArrayCollection();
427
        $this->backupCodes = new ArrayCollection();
428
    }
429
430
    public function getEmail()
431
    {
432
        return $this->email;
433
    }
434
435
    public function setEmail($email)
436
    {
437
        $this->email = $email;
438
439
        return $this;
440
    }
441
442
    public function getFirstName()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
443
    {
444
        return $this->firstName;
445
    }
446
447
    public function setFirstName($firstName)
448
    {
449
        $this->firstName = $firstName;
450
451
        return $this;
452
    }
453
454
    public function getSurname()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
455
    {
456
        return $this->surname;
457
    }
458
459
    public function setSurname($suname)
460
    {
461
        $this->surname = $suname;
462
463
        return $this;
464
    }
465
466
    public function getBirthdate()
467
    {
468
        return $this->birthdate;
469
    }
470
471
    public function setBirthdate($birthdate)
472
    {
473
        $this->birthdate = $birthdate;
474
475
        return $this;
476
    }
477
478
    public function getMobile()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
479
    {
480
        return $this->mobile;
481
    }
482
483
    public function setMobile($mobile)
484
    {
485
        if (!($mobile instanceof PhoneNumber)) {
486
            $mobile = preg_replace('/[^0-9+]/', '', $mobile);
487
488
            // PhoneNumberBundle won't work with empty strings.
489
            // See https://github.com/misd-service-development/phone-number-bundle/issues/58
490
            if (strlen(trim($mobile)) === 0) {
491
                $mobile = null;
492
            }
493
        }
494
        $this->mobile = $mobile;
495
496
        return $this;
497
    }
498
499
    public function addAuthorization(Authorization $authorization)
500
    {
501
        $this->authorizations->add($authorization);
502
        $authorization->setPerson($this);
503
504
        return $this;
505
    }
506
507
    public function removeAuthorization(Authorization $authorization)
508
    {
509
        if ($this->authorizations->contains($authorization)) {
510
            $this->authorizations->removeElement($authorization);
511
        }
512
513
        return $this;
514
    }
515
516
    /**
517
     * @return Authorization[]
0 ignored issues
show
Documentation introduced by
Should the return type not be array|ArrayCollection? Also, consider making the array more specific, something like array<String>, or String[].

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
518
     */
519
    public function getAuthorizations($uidToIgnore = null)
520
    {
521
        if ($uidToIgnore !== null) {
522
            return array_filter(
523
                $this->authorizations->toArray(),
524
                function (Authorization $authorization) use ($uidToIgnore) {
525
                    return $authorization->getClient()->getUid() != $uidToIgnore;
526
                }
527
            );
528
        }
529
530
        return $this->authorizations;
531
    }
532
533
    /**
534
     * Checks if a given Client can access this Person's specified scope.
535
     * @param \LoginCidadao\OAuthBundle\Entity\Client $client
536
     * @param mixed $scope can be a single scope or an array with several.
537
     * @return boolean
538
     */
539
    public function isAuthorizedClient(Client $client, $scope)
540
    {
541
        $authorizations = $this->getAuthorizations();
542
        foreach ($authorizations as $auth) {
543
            $c = $auth->getClient();
544
            if ($c->getId() == $client->getId()) {
545
                return $auth->hasScopes($scope);
546
            }
547
        }
548
549
        return false;
550
    }
551
552
    /**
553
     * @param Client $client
554
     * @return array
555
     */
556
    public function getClientScope(Client $client)
557
    {
558
        $authorizations = $this->getAuthorizations();
559
        foreach ($authorizations as $auth) {
560
            $c = $auth->getClient();
561
            if ($c->getId() == $client->getId()) {
562
                return $auth->getScope();
563
            }
564
        }
565
566
        return null;
567
    }
568
569
    /**
570
     * Checks if this Person has any authorization for a given Client.
571
     * WARNING: Note that it does NOT validate scope!
572
     * @param \LoginCidadao\OAuthBundle\Entity\Client | integer $client
573
     */
574
    public function hasAuthorization($client)
575
    {
576
        if ($client instanceof ClientInterface) {
577
            $id = $client->getId();
578
        } else {
579
            $id = $client;
580
        }
581
        $authorizations = $this->getAuthorizations();
582
        if (is_array($authorizations) || $authorizations instanceof Collection) {
583
            foreach ($authorizations as $auth) {
584
                $c = $auth->getClient();
585
                if ($c->getId() == $id) {
586
                    return true;
587
                }
588
            }
589
        }
590
591
        return false;
592
    }
593
594
    public function setFacebookId($facebookId)
595
    {
596
        $this->facebookId = $facebookId;
597
598
        return $this;
599
    }
600
601
    public function getFacebookId()
602
    {
603
        return $this->facebookId;
604
    }
605
606
    public function setTwitterId($twitterId)
607
    {
608
        $this->twitterId = $twitterId;
609
610
        return $this;
611
    }
612
613
    public function getTwitterId()
614
    {
615
        return $this->twitterId;
616
    }
617
618
    public function setTwitterUsername($twitterUsername)
619
    {
620
        $this->twitterUsername = $twitterUsername;
621
622
        return $this;
623
    }
624
625
    public function getTwitterUsername()
626
    {
627
        return $this->twitterUsername;
628
    }
629
630
    public function setTwitterAccessToken($twitterAccessToken)
631
    {
632
        $this->twitterAccessToken = $twitterAccessToken;
633
634
        return $this;
635
    }
636
637
    public function getTwitterAccessToken()
638
    {
639
        return $this->twitterAccessToken;
640
    }
641
642
    public function serialize()
643
    {
644
        return serialize(array($this->facebookId, parent::serialize()));
645
    }
646
647
    public function unserialize($data)
648
    {
649
        list($this->facebookId, $parentData) = unserialize($data);
650
        parent::unserialize($parentData);
651
    }
652
653
    /**
654
     * Get the full name of the user (first + last name)
655
     * @JMS\Groups({"full_name", "name"})
656
     * @JMS\VirtualProperty
657
     * @JMS\SerializedName("full_name")
658
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
659
     */
660
    public function getFullName()
661
    {
662
        $fullName = array();
663
        if ($this->getFirstname() !== null) {
664
            $fullName[] = $this->getFirstname();
665
        }
666
        if ($this->getSurname() !== null) {
667
            $fullName[] = $this->getSurname();
668
        }
669
670
        if (count($fullName) > 0) {
671
            return implode(' ', $fullName);
672
        } else {
673
            return null;
674
        }
675
    }
676
677
    /**
678
     * Get the full name of the user (first + last name)
679
     * @JMS\Groups({"full_name", "name"})
680
     * @JMS\VirtualProperty
681
     * @JMS\SerializedName("name")
682
     * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be string|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
683
     */
684
    public function getOIDCName()
685
    {
686
        return $this->getFullName();
687
    }
688
689
    /**
690
     * @JMS\Groups({"badges", "public_profile"})
691
     * @JMS\VirtualProperty
692
     * @JMS\SerializedName("deprecated_badges")
693
     * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,boolean>.

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...
694
     */
695
    public function getDataValid()
696
    {
697
        $terms['cpf'] = is_numeric($this->cpf);
0 ignored issues
show
Coding Style Comprehensibility introduced by
$terms was never initialized. Although not strictly required by PHP, it is generally a good practice to add $terms = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
698
        $terms['email'] = is_null($this->getConfirmationToken());
699
700
        return $terms;
701
    }
702
703
    public function setCpf($cpf)
704
    {
705
        $cpf = trim(preg_replace('/[^0-9]/', '', $cpf));
706
707
        if ($cpf === '') {
708
            $cpf = null;
709
        }
710
711
        $this->cpf = $cpf;
712
713
        return $this;
714
    }
715
716
    public function getCpf()
717
    {
718
        return $this->cpf;
719
    }
720
721
    /**
722
     * @param \LoginCidadao\CoreBundle\Entity\City $city
0 ignored issues
show
Documentation introduced by
Should the type for parameter $city not be null|City?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
723
     * @return City
0 ignored issues
show
Documentation introduced by
Should the return type not be Person?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
724
     */
725
    public function setCity(\LoginCidadao\CoreBundle\Entity\City $city = null)
726
    {
727
        $this->city = $city;
728
729
        return $this;
730
    }
731
732
    /**
733
     * @return \LoginCidadao\CoreBundle\Entity\City
0 ignored issues
show
Documentation introduced by
Should the return type not be City|null?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
734
     */
735
    public function getCity()
736
    {
737
        return $this->city;
738
    }
739
740
    public function setCreatedAt(\DateTime $createdAt)
741
    {
742
        $this->createdAt = $createdAt;
743
744
        return $this;
745
    }
746
747
    public function getCreatedAt()
748
    {
749
        return $this->createdAt;
750
    }
751
752
    /**
753
     * @ORM\PrePersist
754
     */
755
    public function setCreatedAtValue()
756
    {
757
        if (!($this->getCreatedAt() instanceof \DateTime)) {
758
            $this->createdAt = new \DateTime();
759
        }
760
        if (!$this->updatedAt) {
761
            $this->updatedAt = new \DateTime();
762
        }
763
    }
764
765
    public function setEmailConfirmedAt(\DateTime $emailConfirmedAt = null)
766
    {
767
        $this->emailConfirmedAt = $emailConfirmedAt;
768
769
        return $this;
770
    }
771
772
    public function getEmailConfirmedAt()
773
    {
774
        return $this->emailConfirmedAt;
775
    }
776
777
    public function getSocialNetworksPicture()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
778
    {
779
        if (!is_null($this->getFacebookId())) {
780
            return "https://graph.facebook.com/{$this->getFacebookId()}/picture?height=245&width=245";
781
        }
782
783
        return null;
784
    }
785
786
    public function getClients()
787
    {
788
        return $this->clients;
789
    }
790
791
    public function setClients($var)
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
792
    {
793
        return $this->clients = $var;
794
    }
795
796
    public function setEmailExpiration($emailExpiration)
797
    {
798
        $this->emailExpiration = $emailExpiration;
799
800
        return $this;
801
    }
802
803
    public function getEmailExpiration()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
804
    {
805
        return $this->emailExpiration;
806
    }
807
808
    public function setFacebookUsername($facebookUsername)
809
    {
810
        $this->facebookUsername = $facebookUsername;
811
812
        return $this;
813
    }
814
815
    public function getFacebookUsername()
816
    {
817
        return $this->facebookUsername;
818
    }
819
820
    public function getFacebookAccessToken()
821
    {
822
        return $this->facebookAccessToken;
823
    }
824
825
    public function setFacebookAccessToken($facebookAccessToken)
826
    {
827
        $this->facebookAccessToken = $facebookAccessToken;
828
829
        return $this;
830
    }
831
832
    public function setPreviousValidEmail($previousValidEmail)
833
    {
834
        $this->previousValidEmail = $previousValidEmail;
835
836
        return $this;
837
    }
838
839
    public function getPreviousValidEmail()
840
    {
841
        return $this->previousValidEmail;
842
    }
843
844
    public function hasPassword()
845
    {
846
        $password = $this->getPassword();
847
848
        return strlen($password) > 0;
849
    }
850
851
    public function setState(State $state = null)
852
    {
853
        $this->state = $state;
854
855
        return $this;
856
    }
857
858
    public function getState()
859
    {
860
        return $this->state;
861
    }
862
863
    /**
864
     * If manually uploading a file (i.e. not using Symfony Form) ensure an instance
865
     * of 'UploadedFile' is injected into this setter to trigger the  update. If this
866
     * bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
867
     * must be able to accept an instance of 'File' as the bundle will inject one here
868
     * during Doctrine hydration.
869
     *
870
     * @param File|\Symfony\Component\HttpFoundation\File\UploadedFile $image
871
     */
872
    public function setImage($image)
873
    {
874
        $this->image = $image;
875
876
        if ($this->image) {
877
            $this->updatedAt = new \DateTime('now');
878
        }
879
    }
880
881
    /**
882
     * @return File
883
     */
884
    public function getImage()
885
    {
886
        return $this->image;
887
    }
888
889
    /**
890
     * @param string $imageName
891
     */
892
    public function setImageName($imageName)
893
    {
894
        $this->imageName = $imageName;
895
    }
896
897
    /**
898
     * @return string
899
     */
900
    public function getImageName()
901
    {
902
        return $this->imageName;
903
    }
904
905
    public function setProfilePictureUrl($profilePictureUrl)
906
    {
907
        $this->profilePictureUrl = $profilePictureUrl;
908
909
        return $this;
910
    }
911
912
    public function getProfilePictureUrl()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
913
    {
914
        return $this->profilePictureUrl;
915
    }
916
917
    /**
918
     * @JMS\Groups({"public_profile"})
919
     * @JMS\VirtualProperty
920
     * @JMS\SerializedName("age_range")
921
     * @JMS\Type("array")
922
     * @return array
923
     */
924
    public function getAgeRange()
925
    {
926
        $today = new \DateTime('today');
927
        if (!$this->getBirthdate()) {
928
            return array();
929
        }
930
        $age = $this->getBirthdate()->diff($today)->y;
931
932
        $range = array();
933
        if ($age < 13) {
934
            $range['max'] = 13;
935
        }
936
        if ($age >= 13 && $age < 18) {
937
            $range['min'] = 13;
938
            $range['max'] = 17;
939
        }
940
        if ($age >= 18 && $age < 21) {
941
            $range['min'] = 18;
942
            $range['max'] = 20;
943
        }
944
        if ($age >= 21) {
945
            $range['min'] = 21;
946
        }
947
948
        return $range;
949
    }
950
951
    public function hasLocalProfilePicture()
952
    {
953
        return !is_null($this->getImageName());
954
    }
955
956
    public function getSuggestions()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
957
    {
958
        return $this->suggestions;
959
    }
960
961
    public function setSuggestions($suggestions)
962
    {
963
        $this->suggestions = $suggestions;
964
965
        return $this;
966
    }
967
968
    public function prepareAPISerialize(
969
        $imageHelper,
970
        $templateHelper,
971
        $isDev,
972
        $request
973
    ) {
974
        // User's profile picture
975
        if ($this->hasLocalProfilePicture()) {
976
            $picturePath = $imageHelper->asset($this, 'image');
977
            $pictureUrl = $request->getUriForPath($picturePath);
978
            if ($isDev) {
979
                $pictureUrl = str_replace('/app_dev.php', '', $pictureUrl);
980
            }
981
        } else {
982
            $pictureUrl = $this->getSocialNetworksPicture();
983
        }
984
        if (is_null($pictureUrl)) {
985
            // TODO: fix this and make it comply to DRY
986
            $picturePath = $templateHelper->getUrl('bundles/logincidadaocore/images/userav.png');
987
            $pictureUrl = $request->getUriForPath($picturePath);
988
            if ($isDev) {
989
                $pictureUrl = str_replace('/app_dev.php', '', $pictureUrl);
990
            }
991
        }
992
        $this->setProfilePictureUrl($pictureUrl);
993
        $this->serialize();
994
    }
995
996
    public function isClientAuthorized($app_id)
0 ignored issues
show
Coding Style Naming introduced by
The parameter $app_id is not named in camelCase.

This check marks parameter names that have not been written in camelCase.

In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes databaseConnectionString.

Loading history...
997
    {
998
        foreach ($this->getAuthorizations() as $auth) {
999
            if ($auth->getClient()->getPublicId() === $app_id) {
0 ignored issues
show
Coding Style introduced by
$app_id does not seem to conform to the naming convention (^[a-z][a-zA-Z0-9]*$).

This check examines a number of code elements and verifies that they conform to the given naming conventions.

You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.

Loading history...
1000
                return true;
1001
            }
1002
        }
1003
1004
        return false;
1005
    }
1006
1007
    /**
1008
     * @ORM\PreUpdate
1009
     */
1010
    public function setUpdatedAt($updatedAt = null)
1011
    {
1012
        if ($updatedAt instanceof \DateTime) {
1013
            $this->updatedAt = $updatedAt;
1014
        } else {
1015
            $this->updatedAt = new \DateTime('now');
1016
        }
1017
1018
        return $this;
1019
    }
1020
1021
    public function getUpdatedAt()
1022
    {
1023
        return $this->updatedAt;
1024
    }
1025
1026
    public function setGoogleId($var)
1027
    {
1028
        $this->googleId = $var;
1029
1030
        return $this;
1031
    }
1032
1033
    public function getGoogleId()
1034
    {
1035
        return $this->googleId;
1036
    }
1037
1038
    public function setGoogleUsername($var)
1039
    {
1040
        $this->googleUsername = $var;
1041
1042
        return $this;
1043
    }
1044
1045
    public function getGoogleUsername()
1046
    {
1047
        return $this->googleUsername;
1048
    }
1049
1050
    public function setGoogleAccessToken($var)
1051
    {
1052
        $this->googleAccessToken = $var;
1053
1054
        return $this;
1055
    }
1056
1057
    public function getGoogleAccessToken()
1058
    {
1059
        return $this->googleAccessToken;
1060
    }
1061
1062
    public function setCountry(Country $country = null)
1063
    {
1064
        $this->country = $country;
1065
1066
        return $this;
1067
    }
1068
1069
    public function getCountry()
1070
    {
1071
        return $this->country;
1072
    }
1073
1074
    public function setComplement($var)
1075
    {
1076
        $this->complement = $var;
0 ignored issues
show
Bug introduced by
The property complement does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
1077
1078
        return $this;
1079
    }
1080
1081
    public function getComplement()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1082
    {
1083
        return $this->complement;
1084
    }
1085
1086
    public function getIdCards()
1087
    {
1088
        return $this->idCards;
1089
    }
1090
1091
    public function getBadges()
1092
    {
1093
        return $this->badges;
1094
    }
1095
1096
    public function mergeBadges(array $badges)
1097
    {
1098
        $this->badges = array_merge($this->badges, $badges);
1099
1100
        return $this;
1101
    }
1102
1103
    public function getFullNameOrUsername()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1104
    {
1105
        if (null === $this->firstName) {
1106
            return $this->username;
1107
        }
1108
1109
        return $this->getFullName();
1110
    }
1111
1112
    public function getLogoutKeys()
1113
    {
1114
        return $this->logoutKeys;
1115
    }
1116
1117
    /**
1118
     * @return ArrayCollection
1119
     */
1120
    public function getAddresses()
1121
    {
1122
        return $this->addresses;
1123
    }
1124
1125
    public function setLogoutKeys($logoutKeys)
1126
    {
1127
        $this->logoutKeys = $logoutKeys;
1128
1129
        return $this;
1130
    }
1131
1132
    public function setAddresses($addresses)
1133
    {
1134
        $this->addresses = $addresses;
1135
1136
        return $this;
1137
    }
1138
1139
    /**
1140
     * Checks whether 2FA is enabled.
1141
     *
1142
     * @return boolean
1143
     */
1144
    public function isTwoFactorAuthenticationEnabled()
1145
    {
1146
        return $this->googleAuthenticatorSecret !== null;
1147
    }
1148
1149
    public function getGoogleAuthenticatorSecret()
1150
    {
1151
        return $this->googleAuthenticatorSecret;
1152
    }
1153
1154
    public function setGoogleAuthenticatorSecret($googleAuthenticatorSecret)
1155
    {
1156
        $this->googleAuthenticatorSecret = $googleAuthenticatorSecret;
1157
1158
        return $this;
1159
    }
1160
1161
    public function getBackupCodes()
1162
    {
1163
        return $this->backupCodes;
1164
    }
1165
1166
    public function setBackupCodes(ArrayCollection $backupCodes)
1167
    {
1168
        $this->backupCodes = $backupCodes;
1169
1170
        return $this;
1171
    }
1172
1173
    public function invalidateBackupCode($code)
1174
    {
1175
        $backupCode = $this->findBackupCode($code);
1176
        $backupCode->setUsed(true);
1177
1178
        return $this;
1179
    }
1180
1181
    public function isBackupCode($code)
1182
    {
1183
        $backupCode = $this->findBackupCode($code);
1184
1185
        return $backupCode !== false && $backupCode->getUsed() === false;
1186
    }
1187
1188
    /**
1189
     * @param string $code
1190
     * @return BackupCode
1191
     */
1192
    private function findBackupCode($code)
1193
    {
1194
        $backupCodes = $this->getBackupCodes();
1195
        foreach ($backupCodes as $backupCode) {
1196
            if ($backupCode->getCode() === $code) {
1197
                return $backupCode;
1198
            }
1199
        }
1200
1201
        return false;
1202
    }
1203
1204
    public function setNationality($var)
1205
    {
1206
        $this->nationality = $var;
1207
1208
        return $this;
1209
    }
1210
1211
    public function getNationality()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1212
    {
1213
        return $this->nationality;
1214
    }
1215
1216
    public function getPlaceOfBirth()
1217
    {
1218
        $location = new LocationSelectData();
1219
        $location->getFromObject($this);
1220
1221
        return $location;
1222
    }
1223
1224
    public function setPlaceOfBirth(LocationSelectData $location)
1225
    {
1226
        $location->toObject($this);
1227
    }
1228
1229
    /**
1230
     * @JMS\Groups({"public_profile"})
1231
     * @JMS\VirtualProperty
1232
     * @JMS\SerializedName("given_name")
1233
     */
1234
    public function getGivenName()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1235
    {
1236
        return $this->getFirstName();
1237
    }
1238
1239
    /**
1240
     * @JMS\Groups({"full_name","name"})
1241
     * @JMS\VirtualProperty
1242
     * @JMS\SerializedName("family_name")
1243
     */
1244
    public function getFamilyName()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1245
    {
1246
        return $this->getSurname();
1247
    }
1248
1249
    /**
1250
     * @JMS\Groups({"mobile", "phone_number"})
1251
     * @JMS\VirtualProperty
1252
     * @JMS\SerializedName("phone_number")
1253
     */
1254
    public function getPhoneNumber()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1255
    {
1256
        return $this->getMobile();
1257
    }
1258
1259
    /**
1260
     * @param bool $verified
1261
     * @return $this
1262
     */
1263
    public function setPhoneNumberVerified($verified = false)
1264
    {
1265
        $this->phoneNumberVerified = $verified;
1266
1267
        return $this;
1268
    }
1269
1270
    /**
1271
     * @return bool
1272
     */
1273
    public function getPhoneNumberVerified()
1274
    {
1275
        return $this->phoneNumberVerified;
1276
    }
1277
1278
    public function getPasswordEncoderName()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1279
    {
1280
        return $this->passwordEncoderName;
1281
    }
1282
1283
    public function setPasswordEncoderName($passwordEncoderName)
1284
    {
1285
        $this->passwordEncoderName = $passwordEncoderName;
1286
1287
        return $this;
1288
    }
1289
1290
    public function getEncoderName()
1291
    {
1292
        $encoder = $this->passwordEncoderName;
1293
1294
        // BC for PR #357
1295
        if ($encoder === null || strlen($encoder) < 1) {
1296
            return null;
1297
        }
1298
1299
        return $encoder;
1300
    }
1301
1302
    public function getLongDisplayName()
1303
    {
1304
        if ($this->getFullName()) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->getFullName() of type string|null is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1305
            return $this->getFullName();
1306
        } else {
1307
            return $this->getEmail();
1308
        }
1309
    }
1310
1311
    public function getShortDisplayName()
0 ignored issues
show
Documentation introduced by
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
1312
    {
1313
        if ($this->getGivenName()) {
1314
            return $this->getGivenName();
1315
        } else {
1316
            return $this->getEmail();
1317
        }
1318
    }
1319
}
1320