Failed Conditions
Push — master ( dc3899...a0ee18 )
by
unknown
07:45
created

User::getSwissSailingType()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
ccs 0
cts 2
cp 0
crap 2
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Model;
6
7
use Application\Api\Exception;
8
use Application\DBAL\Types\BillingTypeType;
9
use Application\DBAL\Types\RelationshipType;
10
use Application\ORM\Query\Filter\AclFilter;
11
use Application\Traits\HasAddress;
12
use Application\Traits\HasDoorAccess;
13
use Application\Traits\HasIban;
14
use Application\Traits\HasRemarks;
15
use Cake\Chronos\Chronos;
16
use Cake\Chronos\Date;
17
use Doctrine\Common\Collections\ArrayCollection;
18
use Doctrine\Common\Collections\Collection;
19
use Doctrine\ORM\Mapping as ORM;
20
use GraphQL\Doctrine\Annotation as API;
21
22
/**
23
 * User
24
 *
25
 * @ORM\Entity(repositoryClass="Application\Repository\UserRepository")
26
 * @ORM\AssociationOverrides({
27
 *     @ORM\AssociationOverride(name="owner", inversedBy="users")
28
 * })
29
 */
30
class User extends AbstractModel
31
{
32
    const ROLE_ANONYMOUS = 'anonymous';
33
    const ROLE_BOOKING_ONLY = 'booking_only';
34
    const ROLE_INDIVIDUAL = 'individual';
35
    const ROLE_MEMBER = 'member';
36
    const ROLE_RESPONSIBLE = 'responsible';
37
    const ROLE_ADMINISTRATOR = 'administrator';
38
39
    const STATUS_INACTIVE = 'inactive';
40
    const STATUS_NEW = 'new';
41
    const STATUS_ACTIVE = 'active';
42
    const STATUS_ARCHIVED = 'archived';
43
44
    use HasDoorAccess;
45
    use HasRemarks;
46
    use HasAddress;
47
    use HasIban;
48
49
    /**
50
     * @var User
51
     */
52
    private static $currentUser;
53
54
    /**
55
     * Set currently logged in user
56
     * WARNING: this method should only be called from \Application\Authentication\AuthenticationListener
57
     *
58
     * @param \Application\Model\User $user
59
     */
60 132
    public static function setCurrent(?self $user): void
61
    {
62 132
        self::$currentUser = $user;
63
64
        // Initalize ACL filter with current user if a logged in one exists
65 132
        _em()->getFilters()->getFilter(AclFilter::class)->setUser($user);
66 132
    }
67
68
    /**
69
     * Returns currently logged user or null
70
     *
71
     * @return null|self
72
     */
73 59
    public static function getCurrent(): ?self
74
    {
75 59
        return self::$currentUser;
76
    }
77
78
    /**
79
     * @var null|string
80
     *
81
     * @ORM\Column(type="string", length=50, nullable=true, unique=true)
82
     */
83
    private $login;
84
85
    /**
86
     * @var string
87
     * @ORM\Column(type="string", length=191)
88
     */
89
    private $firstName = '';
90
91
    /**
92
     * @var string
93
     * @ORM\Column(type="string", length=191)
94
     */
95
    private $lastName = '';
96
97
    /**
98
     * @var string
99
     *
100
     * @ORM\Column(type="string", length=255)
101
     */
102
    private $password = '';
103
104
    /**
105
     * @var null|string
106
     * @ORM\Column(type="string", length=191, nullable=true, unique=true)
107
     */
108
    private $email;
109
110
    /**
111
     * @var string
112
     * @ORM\Column(type="UserRole", options={"default" = User::ROLE_INDIVIDUAL})
113
     */
114
    private $role = self::ROLE_INDIVIDUAL;
115
116
    /**
117
     * @var string
118
     * @ORM\Column(type="UserStatus", options={"default" = User::STATUS_NEW})
119
     */
120
    private $status = self::STATUS_NEW;
121
122
    /**
123
     * @var null|Chronos
124
     * @ORM\Column(type="datetime", nullable=true)
125
     */
126
    private $lastLogin;
127
128
    /**
129
     * @var null|Chronos
130
     * @ORM\Column(type="datetime", nullable=true)
131
     */
132
    private $welcomeSessionDate;
133
134
    /**
135
     * @var int sex
136
     * @ORM\Column(type="smallint", options={"default" = 0}))
137
     */
138
    private $sex = 0;
139
140
    /**
141
     * @var string
142
     * @ORM\Column(type="string", length=25, options={"default" = ""})
143
     */
144
    private $phone = '';
145
146
    /**
147
     * @var string
148
     * @ORM\Column(type="string", length=25, options={"default" = ""})
149
     */
150
    private $mobilePhone = '';
151
152
    /**
153
     * @var string
154
     * @ORM\Column(type="string", length=25, options={"default" = ""})
155
     */
156
    private $swissSailing = '';
157
158
    /**
159
     * @var string
160
     * @ORM\Column(type="SwissSailingType", nullable=true)
161
     */
162
    private $swissSailingType;
163
164
    /**
165
     * @var string
166
     * @ORM\Column(type="SwissWindsurfType", nullable=true)
167
     */
168
    private $swissWindsurfType;
169
170
    /**
171
     * @var null|Date
172
     * @ORM\Column(type="date", nullable=true)
173
     */
174
    private $birthday;
175
176
    /**
177
     * @var bool
178
     * @ORM\Column(type="boolean", options={"default" = 0})
179
     */
180
    private $termsAgreement = false;
181
182
    /**
183
     * @var bool
184
     * @ORM\Column(type="boolean", options={"default" = 0})
185
     */
186
    private $hasInsurance = false;
187
188
    /**
189
     * @var bool
190
     * @ORM\Column(type="boolean", options={"default" = 0})
191
     */
192
    private $receivesNewsletter = false;
193
194
    /**
195
     * @var string
196
     * @ORM\Column(type="Relationship", options={"default" = RelationshipType::HOUSEHOLDER})
197
     */
198
    private $familyRelationship = RelationshipType::HOUSEHOLDER;
199
200
    /**
201
     * @var string
202
     * @ORM\Column(type="BillingType", options={"default" = BillingTypeType::ELECTRONIC})
203
     */
204
    private $billingType = BillingTypeType::ELECTRONIC;
205
206
    /**
207
     * @var null|string
208
     * @ORM\Column(type="string", length=32, nullable=true, unique=true)
209
     */
210
    private $token;
211
212
    /**
213
     * @var null|Chronos
214
     *
215
     * @ORM\Column(type="datetime", nullable=true)
216
     */
217
    private $tokenCreationDate;
218
219
    /**
220
     * @var Collection
221
     * @ORM\OneToMany(targetEntity="Booking", mappedBy="owner")
222
     */
223
    private $bookings;
224
225
    /**
226
     * @var Collection
227
     * @ORM\ManyToMany(targetEntity="License", mappedBy="users")
228
     */
229
    private $licenses;
230
231
    /**
232
     * @var Collection
233
     * @ORM\ManyToMany(targetEntity="UserTag", mappedBy="users")
234
     */
235
    private $userTags;
236
237
    /**
238
     * @var Collection
239
     * @ORM\OneToMany(targetEntity="Message", mappedBy="recipient")
240
     */
241
    private $messages;
242
243
    /**
244
     * There is actually 0 to 1 account, never more. And this is
245
     * enforced by DB unique constraints
246
     *
247
     * @var Collection
248
     * @ORM\OneToMany(targetEntity="Account", mappedBy="owner")
249
     */
250
    private $accounts;
251
252
    /**
253
     * @var Collection
254
     * @ORM\OneToMany(targetEntity="User", mappedBy="owner")
255
     */
256
    private $users;
257
258
    /**
259
     * Constructor
260
     *
261
     * @param string $role role for new user
262
     */
263 37
    public function __construct(string $role = self::ROLE_INDIVIDUAL)
264
    {
265 37
        $this->role = $role;
266 37
        $this->bookings = new ArrayCollection();
267 37
        $this->accounts = new ArrayCollection();
268 37
        $this->licenses = new ArrayCollection();
269 37
        $this->userTags = new ArrayCollection();
270 37
        $this->messages = new ArrayCollection();
271 37
        $this->users = new ArrayCollection();
272 37
    }
273
274
    /**
275
     * Set login (eg: johndoe)
276
     *
277
     * @API\Input(type="Login")
278
     *
279
     * @param string $login
280
     */
281 2
    public function setLogin(string $login): void
282
    {
283 2
        $this->login = $login;
284 2
    }
285
286
    /**
287
     * Get login (eg: johndoe)
288
     *
289
     * @API\Field(type="?Login")
290
     *
291
     * @return null|string
292
     */
293 11
    public function getLogin(): ?string
294
    {
295 11
        return $this->login;
296
    }
297
298
    /**
299
     * Hash and change the user password
300
     *
301
     * @param string $password
302
     */
303 6
    public function setPassword(string $password): void
304
    {
305
        // Ignore empty password that could be sent "by mistake" by the client
306
        // when agreeing to terms
307 6
        if ($password === '') {
308 1
            return;
309
        }
310
311 6
        $this->revokeToken();
312
313 6
        $this->password = password_hash($password, PASSWORD_DEFAULT);
314 6
    }
315
316
    /**
317
     * Returns the hashed password
318
     *
319
     * @API\Exclude
320
     *
321
     * @return string
322
     */
323 3
    public function getPassword(): string
324
    {
325 3
        return $this->password;
326
    }
327
328
    /**
329
     * Set first name
330
     *
331
     * @param string $firstName
332
     */
333 3
    public function setFirstName($firstName): void
334
    {
335 3
        $this->firstName = $firstName;
336 3
    }
337
338
    /**
339
     * Get first name
340
     *
341
     * @return string
342
     */
343 7
    public function getFirstName(): string
344
    {
345 7
        return (string) $this->firstName;
346
    }
347
348
    /**
349
     * Set last name
350
     *
351
     * @param string $lastName
352
     */
353 3
    public function setLastName($lastName): void
354
    {
355 3
        $this->lastName = $lastName;
356 3
    }
357
358
    /**
359
     * Get last name
360
     *
361
     * @return string
362
     */
363 4
    public function getLastName(): string
364
    {
365 4
        return (string) $this->lastName;
366
    }
367
368
    /**
369
     * Get full name
370
     *
371
     * @return string
372
     */
373 4
    public function getName(): string
374
    {
375 4
        return implode(' ', [$this->getFirstName(), $this->getLastName()]);
376
    }
377
378
    /**
379
     * Set email
380
     *
381
     * @API\Input(type="?Email")
382
     *
383
     * @param string $email
384
     */
385 3
    public function setEmail(string $email): void
386
    {
387 3
        $this->email = $email;
388 3
    }
389
390
    /**
391
     * Get email
392
     *
393
     * @API\Field(type="?Email")
394
     *
395
     * @return null|string
396
     */
397 11
    public function getEmail(): ?string
398
    {
399 11
        return $this->email;
400
    }
401
402
    /**
403
     * Returns whether the user is administrator and thus have can do anything.
404
     *
405
     * @API\Field(type="Application\Api\Enum\UserRoleType")
406
     */
407 69
    public function getRole(): string
408
    {
409 69
        return $this->role;
410
    }
411
412
    /**
413
     * Sets the user role
414
     *
415
     * The current user is allowed to promote another user up to the same role as himself. So
416
     * a Responsible can promote a Member to Responsible. Or an Admin can promote a Individual to Admin.
417
     *
418
     * But the current user is **not** allowed to demote a user who has a higher role than himself.
419
     * That means that a Responsible cannot demote an Admin to Individual.
420
     *
421
     * @param string $role
422
     */
423 7
    public function setRole(string $role): void
424
    {
425 7
        if ($role === $this->role) {
426 2
            return;
427
        }
428
429 5
        $currentRole = self::getCurrent() ? self::getCurrent()->getRole() : self::ROLE_ANONYMOUS;
430
        $orderedRoles = [
431 5
            self::ROLE_ANONYMOUS,
432 5
            self::ROLE_INDIVIDUAL,
433 5
            self::ROLE_MEMBER,
434 5
            self::ROLE_RESPONSIBLE,
435 5
            self::ROLE_ADMINISTRATOR,
436
        ];
437
438 5
        $newFound = false;
439 5
        $oldFound = false;
440 5
        foreach ($orderedRoles as $r) {
441 5
            if ($r === $this->role) {
442 3
                $oldFound = true;
443
            }
444 5
            if ($r === $role) {
445 2
                $newFound = true;
446
            }
447
448 5
            if ($r === $currentRole) {
449 5
                break;
450
            }
451
        }
452
453 5
        if (!$newFound || !$oldFound) {
454 3
            throw new Exception($currentRole . ' is not allowed to change role from ' . $this->role . ' to ' . $role);
455
        }
456
457 2
        $this->role = $role;
458 2
    }
459
460 7
    public function setOwner(self $owner = null): void
461
    {
462 7
        if ($owner && $owner !== $this) {
463 4
            if ($owner->getOwner() && $owner !== $owner->getOwner()) {
464 1
                throw new Exception('This user cannot be owned by a user who is himself owned by somebody else');
465
            }
466
467 4
            if ($this->users->count()) {
468 1
                throw new Exception('This user owns other users, so he cannot himself be owned by somebody else');
469
            }
470
        }
471
472 7
        if ($this->getOwner()) {
473 1
            $this->getOwner()->getEmail(); // Trigger lazy loading
474 1
            $this->getOwner()->users->removeElement($this);
475
        }
476
477 7
        parent::setOwner($owner);
478
479 7
        if ($this->getOwner()) {
480 5
            $this->getOwner()->getEmail(); // Trigger lazy loading
481 5
            $this->getOwner()->users->add($this);
482 5
            $this->setStatus($this->getOwner()->getStatus());
483
        }
484 7
    }
485
486
    /**
487
     * @API\Field(type="Application\Api\Enum\UserStatusType")
488
     *
489
     * @return string
490
     */
491 7
    public function getStatus(): string
492
    {
493 7
        return $this->status;
494
    }
495
496
    /**
497
     * @API\Input(type="Application\Api\Enum\UserStatusType")
498
     *
499
     * @param string $status
500
     */
501 14
    public function setStatus(string $status): void
502
    {
503 14
        $this->status = $status;
504 14
        $this->revokeToken();
505
506 14
        foreach ($this->users as $user) {
507 4
            if ($user !== $this) {
508 1
                $user->setStatus($status);
509
            }
510
        }
511 14
    }
512
513 1
    public function activate(): void
514
    {
515 1
        $this->role = self::ROLE_MEMBER; // Bypass security
516 1
        $this->setStatus(self::STATUS_ACTIVE);
517 1
    }
518
519
    /**
520
     * @return string
521
     */
522
    public function getPhone(): string
523
    {
524
        return $this->phone;
525
    }
526
527
    /**
528
     * @param string $phone
529
     */
530
    public function setPhone(string $phone): void
531
    {
532
        $this->phone = $phone;
533
    }
534
535
    /**
536
     * @return string
537
     */
538
    public function getMobilePhone(): string
539
    {
540
        return $this->mobilePhone;
541
    }
542
543
    /**
544
     * @param string $mobilePhone
545
     */
546
    public function setMobilePhone(string $mobilePhone): void
547
    {
548
        $this->mobilePhone = $mobilePhone;
549
    }
550
551
    /**
552
     * @return null|Date
553
     */
554
    public function getBirthday(): ?Date
555
    {
556
        return $this->birthday;
557
    }
558
559
    /**
560
     * @param null|Date $birthday
561
     */
562
    public function setBirthday(?Date $birthday): void
563
    {
564
        $this->birthday = $birthday;
565
    }
566
567
    /**
568
     * Get bookings
569
     *
570
     * @return Collection
571
     */
572 2
    public function getBookings(): Collection
573
    {
574 2
        return $this->bookings;
575
    }
576
577
    /**
578
     * Notify the user that it has a new booking.
579
     * This should only be called by Booking::setResponsible()
580
     *
581
     * @param Booking $booking
582
     */
583 8
    public function bookingAdded(Booking $booking): void
584
    {
585 8
        $this->bookings->add($booking);
586 8
    }
587
588
    /**
589
     * Notify the user that it has a booking was removed.
590
     * This should only be called by Booking::setResponsible()
591
     *
592
     * @param Booking $booking
593
     */
594 4
    public function bookingRemoved(Booking $booking): void
595
    {
596 4
        $this->bookings->removeElement($booking);
597 4
    }
598
599
    /**
600
     * @return Collection
601
     */
602 1
    public function getLicenses(): Collection
603
    {
604 1
        return $this->licenses;
605
    }
606
607
    /**
608
     * @return Collection
609
     */
610 1
    public function getUserTags(): Collection
611
    {
612 1
        return $this->userTags;
613
    }
614
615
    /**
616
     * Notify the user that it has a new license.
617
     * This should only be called by License::addUser()
618
     *
619
     * @param License $license
620
     */
621 1
    public function licenseAdded(License $license): void
622
    {
623 1
        $this->licenses->add($license);
624 1
    }
625
626
    /**
627
     * Notify the user that it a license was removed.
628
     * This should only be called by License::removeUser()
629
     *
630
     * @param License $license
631
     */
632 1
    public function licenseRemoved(License $license): void
633
    {
634 1
        $this->licenses->removeElement($license);
635 1
    }
636
637
    /**
638
     * Notify the user that it has a new userTag.
639
     * This should only be called by UserTag::addUser()
640
     *
641
     * @param UserTag $userTag
642
     */
643 1
    public function userTagAdded(UserTag $userTag): void
644
    {
645 1
        $this->userTags->add($userTag);
646 1
    }
647
648
    /**
649
     * Notify the user that a userTag was removed.
650
     * This should only be called by UserTag::removeUser()
651
     *
652
     * @param UserTag $userTag
653
     */
654 1
    public function userTagRemoved(UserTag $userTag): void
655
    {
656 1
        $this->userTags->removeElement($userTag);
657 1
    }
658
659
    /**
660
     * @return bool
661
     */
662
    public function isTermsAgreement(): bool
663
    {
664
        return $this->termsAgreement;
665
    }
666
667
    /**
668
     * @param bool $termsAgreement
669
     */
670 1
    public function setTermsAgreement(bool $termsAgreement): void
671
    {
672 1
        $this->termsAgreement = $termsAgreement;
673 1
    }
674
675
    /**
676
     * @return bool
677
     */
678
    public function getHasInsurance(): bool
679
    {
680
        return $this->hasInsurance;
681
    }
682
683
    /**
684
     * @param bool $hasInsurance
685
     */
686 1
    public function setHasInsurance(bool $hasInsurance): void
687
    {
688 1
        $this->hasInsurance = $hasInsurance;
689 1
    }
690
691
    /**
692
     * @return null|Chronos
693
     */
694
    public function getWelcomeSessionDate(): ?Chronos
695
    {
696
        return $this->welcomeSessionDate;
697
    }
698
699
    /**
700
     * @param null|Chronos $welcomeSessionDate
701
     */
702
    public function setWelcomeSessionDate(?Chronos $welcomeSessionDate): void
703
    {
704
        $this->welcomeSessionDate = $welcomeSessionDate;
705
    }
706
707
    /**
708
     * @return bool
709
     */
710
    public function isReceivesNewsletter(): bool
711
    {
712
        return $this->receivesNewsletter;
713
    }
714
715
    /**
716
     * @param bool $receivesNewsletter
717
     */
718
    public function setReceivesNewsletter(bool $receivesNewsletter): void
719
    {
720
        $this->receivesNewsletter = $receivesNewsletter;
721
    }
722
723
    /**
724
     * Get the sex
725
     *
726
     * @API\Field(type="Sex")
727
     *
728
     * @return int
729
     */
730
    public function getSex(): int
731
    {
732
        return $this->sex;
733
    }
734
735
    /**
736
     * Set the sex
737
     *
738
     * @API\Input(type="Sex")
739
     *
740
     * @param int $sex
741
     */
742
    public function setSex(int $sex): void
743
    {
744
        $this->sex = $sex;
745
    }
746
747
    /**
748
     * Get the Swiss Sailing licence number
749
     *
750
     * @return string
751
     */
752
    public function getSwissSailing(): string
753
    {
754
        return $this->swissSailing;
755
    }
756
757
    /**
758
     * @param string $swissSailing
759
     */
760
    public function setSwissSailing(string $swissSailing): void
761
    {
762
        $this->ichtusSwissSailing = $ichtusSwissSailing;
0 ignored issues
show
Bug Best Practice introduced by
The property ichtusSwissSailing does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
Comprehensibility Best Practice introduced by
The variable $ichtusSwissSailing seems to be never defined.
Loading history...
763
    }
764
765
    /**
766
     * Get the Swiss Sailing licence type
767
     *
768
     * @API\Field(type="?SwissSailingType")
769
     *
770
     * @return null|string
771
     */
772
    public function getSwissSailingType(): ?string
773
    {
774
        return $this->swissSailingType;
775
    }
776
777
    /**
778
     * Set the Swiss Sailing licence type
779
     *
780
     * @API\Input(type="?SwissSailingType")
781
     *
782
     * @param null|string $swissSailingType
783
     */
784
    public function setSwissSailingType(?string $swissSailingType): void
785
    {
786
        $this->swissSailingType = $swissSailingType;
787
    }
788
789
    /**
790
     * Get the Swiss Windsurf licence type
791
     *
792
     * @API\Field(type="?SwissWindsurfType")
793
     *
794
     * @return null|string
795
     */
796
    public function getSwissWindsurfType(): ?string
797
    {
798
        return $this->swissWindsurfType;
799
    }
800
801
    /**
802
     * Set the Swiss Windsurf licence type
803
     *
804
     * @API\Input(type="?SwissWindsurfType")
805
     *
806
     * @param null|string $swissWindsurfType
807
     */
808
    public function setSwissWindsurfType(?string $swissWindsurfType): void
809
    {
810
        $this->swissWindsurfType = $swissWindsurfType;
811
    }
812
813
    /**
814
     * Get the last login
815
     *
816
     * @return null|Chronos
817
     */
818
    public function getLastLogin(): ?Chronos
819
    {
820
        return $this->lastLogin;
821
    }
822
823
    /**
824
     * @param null|Chronos $lastLogin
825
     */
826 3
    public function setLastLogin(?Chronos $lastLogin): void
827
    {
828 3
        $this->lastLogin = $lastLogin;
829 3
        $this->revokeToken();
830 3
    }
831
832
    /**
833
     * @API\Field(type="Relationship")
834
     *
835
     * @return string
836
     */
837 1
    public function getFamilyRelationship(): string
838
    {
839 1
        return $this->familyRelationship;
840
    }
841
842
    /**
843
     * @API\Input(type="Relationship")
844
     *
845
     * @param string $familyRelationship
846
     */
847 1
    public function setFamilyRelationship(string $familyRelationship): void
848
    {
849 1
        $this->familyRelationship = $familyRelationship;
850 1
    }
851
852
    /**
853
     * @API\Field(type="BillingType")
854
     *
855
     * @return string
856
     */
857
    public function getBillingType(): string
858
    {
859
        return $this->billingType;
860
    }
861
862
    /**
863
     * @API\Input(type="BillingType")
864
     *
865
     * @param string $billingType
866
     */
867
    public function setBillingType(string $billingType): void
868
    {
869
        $this->billingType = $billingType;
870
    }
871
872
    /**
873
     * Get the user transaction account
874
     *
875
     * @return null|Account
876
     */
877 2
    public function getAccount(): ?Account
878
    {
879 2
        return $this->accounts->count() ? $this->accounts->first() : null;
880
    }
881
882
    /**
883
     * Notify the user that it has a new account
884
     * This should only be called by Account::setOwner()
885
     *
886
     * @param Account $account
887
     */
888 3
    public function accountAdded(Account $account): void
889
    {
890 3
        $this->accounts->clear();
891 3
        $this->accounts->add($account);
892 3
    }
893
894
    /**
895
     * Notify the user that a account was removed
896
     * This should only be called by Account::setOwner()
897
     */
898 2
    public function accountRemoved(): void
899
    {
900 2
        $this->accounts->clear();
901 2
    }
902
903
    /**
904
     * Get messages sent to the user
905
     *
906
     * @return Collection
907
     */
908 1
    public function getMessages(): Collection
909
    {
910 1
        return $this->messages;
911
    }
912
913
    /**
914
     * Notify the user that it has a new message
915
     * This should only be called by Message::setRecipient()
916
     *
917
     * @param Message $message
918
     */
919 5
    public function messageAdded(Message $message): void
920
    {
921 5
        $this->messages->add($message);
922 5
    }
923
924
    /**
925
     * Notify the user that a message was removed
926
     * This should only be called by Message::setRecipient()
927
     *
928
     * @param Message $message
929
     */
930 1
    public function messageRemoved(Message $message): void
931
    {
932 1
        $this->messages->removeElement($message);
933 1
    }
934
935
    /**
936
     * Generate a new random token to reset password
937
     */
938 4
    public function createToken(): string
939
    {
940 4
        $this->token = bin2hex(random_bytes(16));
941 4
        $this->tokenCreationDate = new Chronos();
942
943 4
        return $this->token;
944
    }
945
946
    /**
947
     * Destroy existing token
948
     */
949 18
    private function revokeToken(): void
950
    {
951 18
        $this->token = null;
952 18
        $this->tokenCreationDate = null;
953 18
    }
954
955
    /**
956
     * Check if token is valid.
957
     *
958
     * @API\Exclude
959
     *
960
     * @return bool
961
     */
962 3
    public function isTokenValid(): bool
963
    {
964 3
        if (!$this->tokenCreationDate) {
965 1
            return false;
966
        }
967
968 3
        $timeLimit = $this->tokenCreationDate->addMinutes(30);
969
970 3
        return $timeLimit->isFuture();
971
    }
972
973
    /**
974
     * Check if the user can *really* open a door
975
     * This also takes into account the user status, role and IP address
976
     *
977
     * @API\Field(args={@API\Argument(name="door", type="?Application\Api\Enum\DoorType")})
978
     *
979
     * @param null|string $door a particular door, or null for any
980
     *
981
     * @return bool
982
     */
983 6
    public function getCanOpenDoor(?string $door = null): bool
984
    {
985 6
        global $container;
986
987 6
        $allowedStatus = [self::STATUS_ACTIVE];
988 6
        $allowedRoles = [self::ROLE_MEMBER, self::ROLE_RESPONSIBLE, self::ROLE_ADMINISTRATOR];
989 6
        if ($door && !$this->$door) {
990 3
            return false;
991
        }
992 6
        if (!in_array($this->status, $allowedStatus, true) || !in_array($this->role, $allowedRoles, true)) {
993 2
            return false;
994
        }
995 4
        $apiConfig = $container->get('config')['doorsApi'];
996 4
        foreach ($apiConfig['authorizedIps'] as $host) {
997 4
            if (filter_var($host, FILTER_VALIDATE_DOMAIN) && in_array($_SERVER['REMOTE_ADDR'], gethostbynamel($host), true)) {
998 3
                return true;
999
            }
1000 1
            if (filter_var($host, FILTER_VALIDATE_IP) && $_SERVER['REMOTE_ADDR'] === $host) {
1001
                return true;
1002
            }
1003
        }
1004
1005 1
        return false;
1006
    }
1007
}
1008