Passed
Push — master ( bf47d9...8e5e80 )
by Adrien
07:36
created

User   F

Complexity

Total Complexity 94

Size/Duplication

Total Lines 804
Duplicated Lines 0 %

Test Coverage

Coverage 80.32%

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 94
eloc 175
c 3
b 0
f 0
dl 0
loc 804
ccs 151
cts 188
cp 0.8032
rs 2

69 Methods

Rating   Name   Duplication   Size   Complexity  
A getWelcomeSessionDate() 0 3 1
A getLicenses() 0 3 1
A setFirstName() 0 3 1
A getName() 0 3 1
A setLogin() 0 3 1
A setFamilyRelationship() 0 3 1
A getBillingType() 0 3 1
A getLastName() 0 3 1
A setLastName() 0 3 1
A getRole() 0 3 1
A getFirstName() 0 3 1
A getCurrent() 0 3 1
A setCurrent() 0 11 1
A setRole() 0 9 3
A setWelcomeSessionDate() 0 3 1
A licenseRemoved() 0 3 1
A setEmail() 0 3 1
A setSwissWindsurfType() 0 3 1
A getBookings() 0 3 1
A getCanOpenDoor() 0 22 5
A messageRemoved() 0 3 1
A getAge() 0 7 2
A getUserTags() 0 3 1
A getMobilePhone() 0 3 1
A getLogin() 0 3 1
A isFamilyOwner() 0 3 1
A accountAdded() 0 4 1
A getBirthday() 0 3 1
A getReceivesNewsletter() 0 3 1
A isTermsAgreement() 0 3 1
A userTagAdded() 0 3 1
A getStatus() 0 3 1
A getMessages() 0 3 1
A userTagRemoved() 0 3 1
A initialize() 0 4 1
A setMobilePhone() 0 3 1
A hasInsurance() 0 3 1
A getEmail() 0 3 1
B setStatus() 0 14 7
A getPhone() 0 3 1
A setHasInsurance() 0 3 1
A recordLogin() 0 10 2
A __construct() 0 9 1
A bookingRemoved() 0 3 1
A setBillingType() 0 3 1
A getOwnerForCreation() 0 3 1
A getSwissSailingType() 0 3 1
A bookingAdded() 0 3 1
A getSwissSailing() 0 3 1
A getSex() 0 3 1
A getRunningBookings() 0 3 2
A getResignDate() 0 3 1
A setSwissSailingType() 0 3 1
A accountRemoved() 0 3 1
A setTermsAgreement() 0 3 1
A getAccount() 0 7 4
B setOwner() 0 25 8
A setReceivesNewsletter() 0 3 1
A setBirthday() 0 3 1
A setResignDate() 0 3 1
A setSwissSailing() 0 3 1
A licenseAdded() 0 3 1
A getFamilyRelationship() 0 3 1
A setPhone() 0 3 1
A getSwissWindsurfType() 0 3 1
A setSex() 0 3 1
A messageAdded() 0 3 1
A getLastLogin() 0 3 1
A getFirstLogin() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like User often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use User, and based on these observations, apply Extract Interface, too.

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