Failed Conditions
Push — master ( 7ddf51...0a0c4a )
by Adrien
06:37
created

User::setAccount()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 16
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4.0218

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 5
nop 1
dl 0
loc 16
ccs 8
cts 9
cp 0.8889
crap 4.0218
rs 10
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A User::accountRemoved() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Application\Model;
6
7
use Application\Acl\Acl;
8
use Application\Api\Exception;
9
use Application\DBAL\Types\BillingTypeType;
10
use Application\DBAL\Types\RelationshipType;
11
use Application\ORM\Query\Filter\AclFilter;
12
use Application\Traits\HasAddress;
13
use Application\Traits\HasDoorAccess;
14
use Application\Traits\HasRemarks;
15
use Application\Utility;
16
use Cake\Chronos\Chronos;
17
use Cake\Chronos\Date;
18
use Doctrine\Common\Collections\ArrayCollection;
19
use Doctrine\Common\Collections\Collection;
20
use Doctrine\ORM\Mapping as ORM;
21
use GraphQL\Doctrine\Annotation as API;
22
23
/**
24
 * User
25
 *
26
 * @ORM\Entity(repositoryClass="Application\Repository\UserRepository")
27
 */
28
class User extends AbstractModel
29
{
30
    const ROLE_ANONYMOUS = 'anonymous';
31
    const ROLE_BOOKING_ONLY = 'booking_only';
32
    const ROLE_INDIVIDUAL = 'individual';
33
    const ROLE_MEMBER = 'member';
34
    const ROLE_RESPONSIBLE = 'responsible';
35
    const ROLE_ADMINISTRATOR = 'administrator';
36
37
    const STATUS_INACTIVE = 'inactive';
38
    const STATUS_NEW = 'new';
39
    const STATUS_ACTIVE = 'active';
40
    const STATUS_ARCHIVED = 'archived';
41
42
    use HasDoorAccess;
43
    use HasRemarks;
44
    use HasAddress;
45
46
    /**
47
     * @var User
48
     */
49
    private static $currentUser;
50
51
    /**
52
     * Set currently logged in user
53
     * WARNING: this method should only be called from \Application\Authentication\AuthenticationListener
54
     *
55
     * @param \Application\Model\User $user
56
     */
57 42
    public static function setCurrent(?self $user): void
58
    {
59 42
        self::$currentUser = $user;
60
61
        // Initalize ACL filter with current user if a logged in one exists
62 42
        _em()->getFilters()->getFilter(AclFilter::class)->setUser($user);
63 42
    }
64
65
    /**
66
     * Returns currently logged user or null
67
     *
68
     * @return null|self
69
     */
70 32
    public static function getCurrent(): ?self
71
    {
72 32
        return self::$currentUser;
73
    }
74
75
    /**
76
     * @var string
77
     *
78
     * @ORM\Column(type="string", length=50, unique=true)
79
     */
80
    private $login;
81
82
    /**
83
     * @var string
84
     * @ORM\Column(type="string", length=191)
85
     */
86
    private $firstName;
87
88
    /**
89
     * @var string
90
     * @ORM\Column(type="string", length=191)
91
     */
92
    private $lastName;
93
94
    /**
95
     * @var null|string
96
     *
97
     * @ORM\Column(type="string", length=255)
98
     */
99
    private $password;
100
101
    /**
102
     * @var string
103
     * @ORM\Column(type="string", length=191)
104
     */
105
    private $email;
106
107
    /**
108
     * @var string
109
     * @ORM\Column(type="UserRole", options={"default" = User::ROLE_INDIVIDUAL})
110
     */
111
    private $role = self::ROLE_INDIVIDUAL;
112
113
    /**
114
     * @var string
115
     * @ORM\Column(type="UserStatus", options={"default" = User::STATUS_NEW})
116
     */
117
    private $status = self::STATUS_NEW;
118
119
    /**
120
     * @var null|Chronos
121
     * @ORM\Column(type="datetime", nullable=true)
122
     */
123
    private $lastLogin;
124
125
    /**
126
     * @var null|Chronos
127
     * @ORM\Column(type="datetime", nullable=true)
128
     */
129
    private $welcomeSessionDate;
130
131
    /**
132
     * @var int sex according to ISO/IEC 5218
133
     * @ORM\Column(type="smallint", options={"default" = 0}))
134
     */
135
    private $sex = 0;
136
137
    /**
138
     * @var string
139
     * @ORM\Column(type="string", length=25, options={"default" = ""})
140
     */
141
    private $phone = '';
142
143
    /**
144
     * @var string
145
     * @ORM\Column(type="string", length=25, options={"default" = ""})
146
     */
147
    private $mobilePhone = '';
148
149
    /**
150
     * @var string
151
     * @ORM\Column(type="string", length=25, options={"default" = ""})
152
     */
153
    private $ichtusSwissSailing = '';
154
155
    /**
156
     * @var null|Date
157
     * @ORM\Column(type="date", nullable=true)
158
     */
159
    private $birthday;
160
161
    /**
162
     * @var bool
163
     * @ORM\Column(type="boolean", options={"default" = 0})
164
     */
165
    private $termsAgreement = false;
166
167
    /**
168
     * @var bool
169
     * @ORM\Column(type="boolean", options={"default" = 0})
170
     */
171
    private $hasInsurance = false;
172
173
    /**
174
     * @var bool
175
     * @ORM\Column(type="boolean", options={"default" = 0})
176
     */
177
    private $receivesNewsletter = false;
178
179
    /**
180
     * @var string
181
     * @ORM\Column(type="Relationship", options={"default" = RelationshipType::HOUSEHOLDER})
182
     */
183
    private $familyRelationship = RelationshipType::HOUSEHOLDER;
184
185
    /**
186
     * @var string
187
     * @ORM\Column(type="BillingType", options={"default" = BillingTypeType::ALL_ELECTRONIC})
188
     */
189
    private $billingType = BillingTypeType::ALL_ELECTRONIC;
190
191
    /**
192
     * @var Collection
193
     * @ORM\OneToMany(targetEntity="Booking", mappedBy="owner")
194
     */
195
    private $bookings;
196
197
    /**
198
     * @var Collection
199
     * @ORM\ManyToMany(targetEntity="License", mappedBy="users")
200
     */
201
    private $licenses;
202
203
    /**
204
     * @var Collection
205
     * @ORM\ManyToMany(targetEntity="UserTag", mappedBy="users")
206
     */
207
    private $userTags;
208
209
    /**
210
     * @var Collection
211
     * @ORM\OneToMany(targetEntity="ExpenseClaim", mappedBy="user")
212
     */
213
    private $expenseClaims;
214
215
    /**
216
     * @var Collection
217
     * @ORM\OneToMany(targetEntity="Message", mappedBy="recipient")
218
     */
219
    private $messages;
220
221
    /**
222
     * There is actually at 0 to 1 account, never more. And this is
223
     * enforced by DB unique constraints
224
     *
225
     * @var Collection
226
     * @ORM\OneToMany(targetEntity="Account", mappedBy="owner")
227
     */
228
    private $accounts;
229
230
    /**
231
     * Constructor
232
     *
233
     * @param string $role role for new user
234
     */
235 23
    public function __construct(string $role = self::ROLE_INDIVIDUAL)
236
    {
237 23
        $this->role = $role;
238 23
        $this->bookings = new ArrayCollection();
239 23
        $this->accounts = new ArrayCollection();
240 23
        $this->licenses = new ArrayCollection();
241 23
        $this->userTags = new ArrayCollection();
242 23
        $this->expenseClaims = new ArrayCollection();
243 23
        $this->messages = new ArrayCollection();
244 23
    }
245
246
    /**
247
     * Set login (eg: johndoe)
248
     *
249
     * @API\Input(type="Application\Api\Scalar\LoginType")
250
     *
251
     * @param string $login
252
     */
253 1
    public function setLogin(string $login): void
254
    {
255 1
        $this->login = $login;
256 1
    }
257
258
    /**
259
     * Get login (eg: johndoe)
260
     *
261
     * @API\Field(type="Application\Api\Scalar\LoginType")
262
     *
263
     * @return string
264
     */
265 8
    public function getLogin(): string
266
    {
267 8
        return (string) $this->login;
268
    }
269
270
    /**
271
     * Encrypt and change the user password
272
     *
273
     * @param string $password
274
     */
275 3
    public function setPassword(string $password): void
276
    {
277
        // Ignore empty password that could be sent "by mistake" by the client
278
        // when agreeing to terms
279 3
        if ($password === '') {
280 1
            return;
281
        }
282
283 3
        $this->password = password_hash($password, PASSWORD_DEFAULT);
284 3
    }
285
286
    /**
287
     * Returns the hashed password
288
     *
289
     * @API\Exclude
290
     *
291
     * @return null|string
292
     */
293 3
    public function getPassword(): ?string
294
    {
295 3
        return $this->password;
296
    }
297
298
    /**
299
     * Set first name
300
     *
301
     * @param string $firstName
302
     */
303 1
    public function setFirstName($firstName): void
304
    {
305 1
        $this->firstName = $firstName;
306 1
    }
307
308
    /**
309
     * Get first name
310
     *
311
     * @return string
312
     */
313 1
    public function getFirstName(): string
314
    {
315 1
        return (string) $this->firstName;
316
    }
317
318
    /**
319
     * Set last name
320
     *
321
     * @param string $lastName
322
     */
323 1
    public function setLastName($lastName): void
324
    {
325 1
        $this->lastName = $lastName;
326 1
    }
327
328
    /**
329
     * Get last name
330
     *
331
     * @return string
332
     */
333 1
    public function getLastName(): string
334
    {
335 1
        return (string) $this->lastName;
336
    }
337
338
    /**
339
     * Get full name
340
     *
341
     * @return string
342
     */
343 1
    public function getName(): string
344
    {
345 1
        return implode(' ', [$this->getFirstName(), $this->getLastName()]);
346
    }
347
348
    /**
349
     * Set email
350
     *
351
     * @API\Input(type="Email")
352
     *
353
     * @param string $email
354
     */
355 1
    public function setEmail(string $email): void
356
    {
357 1
        $this->email = $email;
358 1
    }
359
360
    /**
361
     * Get email
362
     *
363
     * @API\Field(type="Email")
364
     *
365
     * @return string
366
     */
367 1
    public function getEmail(): string
368
    {
369 1
        return $this->email;
370
    }
371
372
    /**
373
     * Returns whether the user is administrator and thus have can do anything.
374
     *
375
     * @API\Field(type="Application\Api\Enum\UserRoleType")
376
     */
377 27
    public function getRole(): string
378
    {
379 27
        return $this->role;
380
    }
381
382
    /**
383
     * Sets the user role
384
     *
385
     * The current user is allowed to promote another user up to the same role as himself. So
386
     * a Senior can promote a Student to Senior. Or an Admin can promote a Junior to Admin.
387
     *
388
     * But the current user is **not** allowed to demote a user who has a higher role than himself.
389
     * That means that a Senior cannot demote an Admin to Student.
390
     *
391
     * @param string $role
392
     */
393 7
    public function setRole(string $role): void
394
    {
395 7
        if ($role === $this->role) {
396 2
            return;
397
        }
398
399 5
        $currentRole = self::getCurrent() ? self::getCurrent()->getRole() : self::ROLE_ANONYMOUS;
400
        $orderedRoles = [
401 5
            self::ROLE_ANONYMOUS,
402 5
            self::ROLE_INDIVIDUAL,
403 5
            self::ROLE_MEMBER,
404 5
            self::ROLE_RESPONSIBLE,
405 5
            self::ROLE_ADMINISTRATOR,
406
        ];
407
408 5
        $newFound = false;
409 5
        $oldFound = false;
410 5
        foreach ($orderedRoles as $r) {
411 5
            if ($r === $this->role) {
412 3
                $oldFound = true;
413
            }
414 5
            if ($r === $role) {
415 2
                $newFound = true;
416
            }
417
418 5
            if ($r === $currentRole) {
419 5
                break;
420
            }
421
        }
422
423 5
        if (!$newFound || !$oldFound) {
424 3
            throw new Exception($currentRole . ' is not allowed to change role to ' . $role);
425
        }
426
427 2
        $this->role = $role;
428 2
    }
429
430
    /**
431
     * @API\Field(type="Application\Api\Enum\UserStatusType")
432
     *
433
     * @return string
434
     */
435
    public function getStatus(): string
436
    {
437
        return $this->status;
438
    }
439
440
    /**
441
     * @API\Input(type="Application\Api\Enum\UserStatusType")
442
     *
443
     * @param string $status
444
     */
445
    public function setStatus(string $status): void
446
    {
447
        $this->status = $status;
448
    }
449
450
    /**
451
     * Get a list of global permissions for this user
452
     *
453
     * @API\Field(type="GlobalPermissionsList")
454
     *
455
     * @return array
456
     */
457 3
    public function getGlobalPermissions(): array
458
    {
459 3
        $acl = new Acl();
460
        $types = [
461 3
            Country::class,
462
            License::class,
463
            self::class,
464
        ];
465
466 3
        $permissions = ['create'];
467 3
        $result = [];
468
469 3
        $previousUser = self::getCurrent();
470 3
        self::setCurrent($this);
471 3
        foreach ($types as $type) {
472 3
            $instance = new $type();
473 3
            $sh = lcfirst(Utility::getShortClassName($instance));
474 3
            $result[$sh] = [];
475
476 3
            foreach ($permissions as $p) {
477 3
                $result[$sh][$p] = $acl->isCurrentUserAllowed($instance, $p);
478
            }
479
        }
480
481 3
        self::setCurrent($previousUser);
482
483 3
        return $result;
484
    }
485
486
    /**
487
     * @return string
488
     */
489
    public function getPhone(): string
490
    {
491
        return $this->phone;
492
    }
493
494
    /**
495
     * @param string $phone
496
     */
497
    public function setPhone(string $phone): void
498
    {
499
        $this->phone = $phone;
500
    }
501
502
    /**
503
     * @return string
504
     */
505
    public function getMobilePhone(): string
506
    {
507
        return $this->mobilePhone;
508
    }
509
510
    /**
511
     * @param string $mobilePhone
512
     */
513
    public function setMobilePhone(string $mobilePhone): void
514
    {
515
        $this->mobilePhone = $mobilePhone;
516
    }
517
518
    /**
519
     * @return null|Date
520
     */
521
    public function getBirthday(): ?Date
522
    {
523
        return $this->birthday;
524
    }
525
526
    /**
527
     * @param null|Date $birthday
528
     */
529
    public function setBirthday(?Date $birthday): void
530
    {
531
        $this->birthday = $birthday;
532
    }
533
534
    /**
535
     * Get bookings
536
     *
537
     * @return Collection
538
     */
539 1
    public function getBookings(): Collection
540
    {
541 1
        return $this->bookings;
542
    }
543
544
    /**
545
     * Notify the user that it has a new booking.
546
     * This should only be called by Booking::setResponsible()
547
     *
548
     * @param Booking $booking
549
     */
550 7
    public function bookingAdded(Booking $booking): void
551
    {
552 7
        $this->bookings->add($booking);
553 7
    }
554
555
    /**
556
     * Notify the user that it has a booking was removed.
557
     * This should only be called by Booking::setResponsible()
558
     *
559
     * @param Booking $booking
560
     */
561 3
    public function bookingRemoved(Booking $booking): void
562
    {
563 3
        $this->bookings->removeElement($booking);
564 3
    }
565
566
    /**
567
     * @return Collection
568
     */
569 1
    public function getLicenses(): Collection
570
    {
571 1
        return $this->licenses;
572
    }
573
574
    /**
575
     * @return Collection
576
     */
577 1
    public function getUserTags(): Collection
578
    {
579 1
        return $this->userTags;
580
    }
581
582
    /**
583
     * Notify the user that it has a new license.
584
     * This should only be called by License::addUser()
585
     *
586
     * @param License $license
587
     */
588 1
    public function licenseAdded(License $license): void
589
    {
590 1
        $this->licenses->add($license);
591 1
    }
592
593
    /**
594
     * Notify the user that it a license was removed.
595
     * This should only be called by License::removeUser()
596
     *
597
     * @param License $license
598
     */
599 1
    public function licenseRemoved(License $license): void
600
    {
601 1
        $this->licenses->removeElement($license);
602 1
    }
603
604
    /**
605
     * Notify the user that it has a new userTag.
606
     * This should only be called by UserTag::addUser()
607
     *
608
     * @param UserTag $userTag
609
     */
610 1
    public function userTagAdded(UserTag $userTag): void
611
    {
612 1
        $this->userTags->add($userTag);
613 1
    }
614
615
    /**
616
     * Notify the user that a userTag was removed.
617
     * This should only be called by UserTag::removeUser()
618
     *
619
     * @param UserTag $userTag
620
     */
621 1
    public function userTagRemoved(UserTag $userTag): void
622
    {
623 1
        $this->userTags->removeElement($userTag);
624 1
    }
625
626
    /**
627
     * @return bool
628
     */
629
    public function isTermsAgreement(): bool
630
    {
631
        return $this->termsAgreement;
632
    }
633
634
    /**
635
     * @param bool $termsAgreement
636
     */
637
    public function setTermsAgreement(bool $termsAgreement): void
638
    {
639
        $this->termsAgreement = $termsAgreement;
640
    }
641
642
    /**
643
     * @return bool
644
     */
645
    public function getHasInsurance(): bool
646
    {
647
        return $this->hasInsurance;
648
    }
649
650
    /**
651
     * @param bool $hasInsurance
652
     */
653
    public function setHasInsurance(bool $hasInsurance): void
654
    {
655
        $this->hasInsurance = $hasInsurance;
656
    }
657
658
    /**
659
     * @return null|Chronos
660
     */
661
    public function getWelcomeSessionDate(): ?Chronos
662
    {
663
        return $this->welcomeSessionDate;
664
    }
665
666
    /**
667
     * @param null|Chronos $welcomeSessionDate
668
     */
669
    public function setWelcomeSessionDate(?Chronos $welcomeSessionDate): void
670
    {
671
        $this->welcomeSessionDate = $welcomeSessionDate;
672
    }
673
674
    /**
675
     * @return bool
676
     */
677
    public function isReceivesNewsletter(): bool
678
    {
679
        return $this->receivesNewsletter;
680
    }
681
682
    /**
683
     * @param bool $receivesNewsletter
684
     */
685
    public function setReceivesNewsletter(bool $receivesNewsletter): void
686
    {
687
        $this->receivesNewsletter = $receivesNewsletter;
688
    }
689
690
    /**
691
     * Get the ISO/IEC 5218 sex
692
     *
693
     * @API\Field(type="Sex")
694
     *
695
     * @return int
696
     */
697
    public function getSex(): int
698
    {
699
        return $this->sex;
700
    }
701
702
    /**
703
     * Set the ISO/IEC 5218 sex
704
     *
705
     * @API\Input(type="Sex")
706
     *
707
     * @param int $sex
708
     */
709
    public function setSex(int $sex): void
710
    {
711
        $this->sex = $sex;
712
    }
713
714
    /**
715
     * @return string
716
     */
717
    public function getIchtusSwissSailing(): string
718
    {
719
        return $this->ichtusSwissSailing;
720
    }
721
722
    /**
723
     * @param string $ichtusSwissSailing
724
     */
725
    public function setIchtusSwissSailing(string $ichtusSwissSailing): void
726
    {
727
        $this->ichtusSwissSailing = $ichtusSwissSailing;
728
    }
729
730
    /**
731
     * Get the last login
732
     *
733
     * @return null|Chronos
734
     */
735
    public function getLastLogin(): ?Chronos
736
    {
737
        return $this->lastLogin;
738
    }
739
740
    /**
741
     * @param null|Chronos $lastLogin
742
     */
743 2
    public function setLastLogin(?Chronos $lastLogin): void
744
    {
745 2
        $this->lastLogin = $lastLogin;
746 2
    }
747
748
    /**
749
     * @API\Field(type="Relationship")
750
     *
751
     * @return string
752
     */
753
    public function getFamilyRelationship(): string
754
    {
755
        return $this->familyRelationship;
756
    }
757
758
    /**
759
     * @API\Input(type="Relationship")
760
     *
761
     * @param string $familyRelationship
762
     */
763
    public function setFamilyRelationship(string $familyRelationship): void
764
    {
765
        $this->familyRelationship = $familyRelationship;
766
    }
767
768
    /**
769
     * @return string
770
     */
771
    public function getBillingType(): string
772
    {
773
        return $this->billingType;
774
    }
775
776
    /**
777
     * @param string $billingType
778
     */
779
    public function setBillingType(string $billingType): void
780
    {
781
        $this->billingType = $billingType;
782
    }
783
784
    /**
785
     * Get the user transaction account
786
     *
787
     * @return null|Account
788
     */
789 1
    public function getAccount(): ?Account
790
    {
791 1
        return $this->accounts->count() ? $this->accounts->first() : null;
792
    }
793
794
    /**
795
     * Notify the user that it has a new account
796
     * This should only be called by Account::setOwner()
797
     *
798
     * @param Account $account
799
     */
800 1
    public function accountAdded(Account $account): void
801
    {
802 1
        $this->accounts->clear();
803 1
        $this->accounts->add($account);
804 1
    }
805
806
    /**
807
     * Notify the user that a account was removed
808
     * This should only be called by Account::setOwner()
809
     */
810 1
    public function accountRemoved(): void
811
    {
812 1
        $this->accounts->clear();
813 1
    }
814
815
    /**
816
     * Get messages sent to the user
817
     *
818
     * @return Collection
819
     */
820 1
    public function getMessages(): Collection
821
    {
822 1
        return $this->messages;
823
    }
824
825
    /**
826
     * Notify the user that it has a new message
827
     * This should only be called by Message::setRecipient()
828
     *
829
     * @param Message $message
830
     */
831 1
    public function messageAdded(Message $message): void
832
    {
833 1
        $this->messages->add($message);
834 1
    }
835
836
    /**
837
     * Notify the user that a message was removed
838
     * This should only be called by Message::setRecipient()
839
     *
840
     * @param Message $message
841
     */
842 1
    public function messageRemoved(Message $message): void
843
    {
844 1
        $this->messages->removeElement($message);
845 1
    }
846
847
    /**
848
     * Get expense claims submitted by the user
849
     *
850
     * @return Collection
851
     */
852 1
    public function getExpenseClaims(): Collection
853
    {
854 1
        return $this->expenseClaims;
855
    }
856
857
    /**
858
     * Notify the user when a new expense claim was added
859
     * This should only be called by ExpenseClaim::setUser()
860
     *
861
     * @param ExpenseClaim $expense
862
     */
863 1
    public function expenseClaimAdded(ExpenseClaim $expense): void
864
    {
865 1
        $this->expenseClaims->add($expense);
866 1
    }
867
868
    /**
869
     * Notify the user that when an expense claim was removed
870
     * This should only be called by ExpenseClaim::setUser()
871
     *
872
     * @param ExpenseClaim $expense
873
     */
874 1
    public function expenseClaimRemoved(ExpenseClaim $expense): void
875
    {
876 1
        $this->expenseClaims->removeElement($expense);
877 1
    }
878
}
879