Passed
Push — master ( 9448f0...0fc317 )
by Yannick
08:30
created

User::setTeach()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 5
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Entity;
8
9
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
10
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
11
use ApiPlatform\Metadata\ApiFilter;
12
use ApiPlatform\Metadata\ApiProperty;
13
use ApiPlatform\Metadata\ApiResource;
14
use ApiPlatform\Metadata\Delete;
15
use ApiPlatform\Metadata\Get;
16
use ApiPlatform\Metadata\GetCollection;
17
use ApiPlatform\Metadata\Post;
18
use ApiPlatform\Metadata\Put;
19
use Chamilo\CoreBundle\Controller\Api\CreateUserOnAccessUrlAction;
20
use Chamilo\CoreBundle\Controller\Api\UserSkillsController;
21
use Chamilo\CoreBundle\Dto\CreateUserOnAccessUrlInput;
22
use Chamilo\CoreBundle\Entity\Listener\UserListener;
23
use Chamilo\CoreBundle\Filter\PartialSearchOrFilter;
24
use Chamilo\CoreBundle\Repository\Node\UserRepository;
25
use Chamilo\CoreBundle\Traits\UserCreatorTrait;
26
use Chamilo\CourseBundle\Entity\CGroupRelTutor;
27
use Chamilo\CourseBundle\Entity\CGroupRelUser;
28
use Chamilo\CourseBundle\Entity\CSurveyInvitation;
29
use DateTime;
30
use DateTimeInterface;
31
use Doctrine\Common\Collections\ArrayCollection;
32
use Doctrine\Common\Collections\Collection;
33
use Doctrine\Common\Collections\Criteria;
34
use Doctrine\Common\Collections\ReadableCollection;
35
use Doctrine\ORM\Mapping as ORM;
36
use Gedmo\Timestampable\Traits\TimestampableEntity;
37
use Stringable;
38
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
39
use Symfony\Component\Security\Core\User\EquatableInterface;
40
use Symfony\Component\Security\Core\User\LegacyPasswordAuthenticatedUserInterface;
41
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
42
use Symfony\Component\Security\Core\User\UserInterface;
43
use Symfony\Component\Serializer\Annotation\Groups;
44
use Symfony\Component\Uid\Uuid;
45
use Symfony\Component\Validator\Constraints as Assert;
46
use Symfony\Component\Validator\Mapping\ClassMetadata;
47
use UserManager;
48
49
#[ApiResource(
50
    types: ['http://schema.org/Person'],
51
    operations: [
52
        new Get(
53
            openapiContext: [
54
                'description' => 'Get details of one specific user, including name, e-mail and role.',
55
            ],
56
            security: "is_granted('VIEW', object)",
57
        ),
58
        new Put(security: "is_granted('EDIT', object)"),
59
        new Delete(security: "is_granted('DELETE', object)"),
60
        new GetCollection(security: "is_granted('ROLE_USER')"),
61
        new Post(security: "is_granted('ROLE_ADMIN')"),
62
        new GetCollection(
63
            uriTemplate: '/users/{id}/skills',
64
            controller: UserSkillsController::class,
65
            normalizationContext: ['groups' => ['user_skills:read']],
66
            name: 'get_user_skills'
67
        ),
68
        new Post(
69
            uriTemplate: '/advanced/create-user-on-access-url',
70
            controller: CreateUserOnAccessUrlAction::class,
71
            denormalizationContext: ['groups' => ['write']],
72
            security: "is_granted('ROLE_ADMIN') or is_granted('ROLE_SESSION_MANAGER')",
73
            input: CreateUserOnAccessUrlInput::class,
74
            output: User::class,
75
            deserialize: true,
76
            name: 'create_user_on_access_url'
77
        ),
78
    ],
79
    normalizationContext: ['groups' => ['user:read']],
80
    denormalizationContext: ['groups' => ['user:write']],
81
    security: 'is_granted("ROLE_USER")'
82
)]
83
#[ORM\Table(name: 'user')]
84
#[ORM\Index(columns: ['status'], name: 'status')]
85
#[UniqueEntity('username')]
86
#[ORM\Entity(repositoryClass: UserRepository::class)]
87
#[ORM\EntityListeners([UserListener::class])]
88
#[ApiFilter(
89
    filterClass: SearchFilter::class,
90
    properties: [
91
        'username' => 'partial',
92
        'firstname' => 'partial',
93
        'lastname' => 'partial',
94
    ]
95
)]
96
#[ApiFilter(PartialSearchOrFilter::class, properties: ['username', 'firstname', 'lastname'])]
97
#[ApiFilter(filterClass: BooleanFilter::class, properties: ['isActive'])]
98
class User implements UserInterface, EquatableInterface, ResourceInterface, ResourceIllustrationInterface, PasswordAuthenticatedUserInterface, LegacyPasswordAuthenticatedUserInterface, ExtraFieldItemInterface, Stringable
99
{
100
    use TimestampableEntity;
101
    use UserCreatorTrait;
102
103
    public const USERNAME_MAX_LENGTH = 100;
104
    public const ROLE_DEFAULT = 'ROLE_USER';
105
    public const ANONYMOUS = 6;
106
107
    /**
108
     * Global status for the fallback user.
109
     * This special status is used for a system user that acts as a placeholder
110
     * or fallback for content ownership when regular users are deleted.
111
     * This ensures data integrity and prevents orphaned content within the system.
112
     */
113
    public const ROLE_FALLBACK = 99;
114
115
    /*public const COURSE_MANAGER = 1;
116
      public const TEACHER = 1;
117
      public const SESSION_ADMIN = 3;
118
      public const DRH = 4;
119
      public const STUDENT = 5;
120
      public const ANONYMOUS = 6;*/
121
122
    // User active field constants
123
    public const ACTIVE = 1;
124
    public const INACTIVE = 0;
125
    public const INACTIVE_AUTOMATIC = -1;
126
    public const SOFT_DELETED = -2;
127
128
    #[Groups(['user_json:read'])]
129
    #[ORM\OneToOne(targetEntity: ResourceNode::class, cascade: ['persist'])]
130
    #[ORM\JoinColumn(name: 'resource_node_id', onDelete: 'CASCADE')]
131
    public ?ResourceNode $resourceNode = null;
132
133
    /**
134
     * Resource illustration URL - Property set by ResourceNormalizer.php.
135
     */
136
    #[ApiProperty(iris: ['http://schema.org/contentUrl'])]
137
    #[Groups([
138
        'user_export',
139
        'user:read',
140
        'resource_node:read',
141
        'document:read',
142
        'media_object_read',
143
        'course:read',
144
        'course_rel_user:read',
145
        'user_json:read',
146
        'message:read',
147
        'user_rel_user:read',
148
        'social_post:read',
149
        'user_subscriptions:sessions',
150
    ])]
151
    public ?string $illustrationUrl = null;
152
153
    #[Groups([
154
        'user:read',
155
        'course:read',
156
        'resource_node:read',
157
        'user_json:read',
158
        'message:read',
159
        'user_rel_user:read',
160
        'session:item:read',
161
    ])]
162
    #[ORM\Column(name: 'id', type: 'integer')]
163
    #[ORM\Id]
164
    #[ORM\GeneratedValue]
165
    protected ?int $id = null;
166
167
    #[Assert\NotBlank]
168
    #[Groups([
169
        'user_export',
170
        'user:read',
171
        'user:write',
172
        'course:read',
173
        'course_rel_user:read',
174
        'resource_node:read',
175
        'user_json:read',
176
        'message:read',
177
        'page:read',
178
        'user_rel_user:read',
179
        'social_post:read',
180
        'track_e_exercise:read',
181
        'user_subscriptions:sessions',
182
        'student_publication_rel_user:read',
183
    ])]
184
    #[ORM\Column(name: 'username', type: 'string', length: 100, unique: true)]
185
    protected string $username;
186
187
    #[ORM\Column(name: 'api_token', type: 'string', unique: true, nullable: true)]
188
    protected ?string $apiToken = null;
189
190
    #[ApiProperty(iris: ['http://schema.org/name'])]
191
    #[Assert\NotBlank]
192
    #[Groups(['user:read', 'user:write', 'resource_node:read', 'user_json:read', 'track_e_exercise:read', 'user_rel_user:read', 'user_subscriptions:sessions', 'student_publication_rel_user:read'])]
193
    #[ORM\Column(name: 'firstname', type: 'string', length: 64, nullable: true)]
194
    protected ?string $firstname = null;
195
196
    #[Groups(['user:read', 'user:write', 'resource_node:read', 'user_json:read', 'track_e_exercise:read', 'user_rel_user:read', 'user_subscriptions:sessions', 'student_publication_rel_user:read'])]
197
    #[ORM\Column(name: 'lastname', type: 'string', length: 64, nullable: true)]
198
    protected ?string $lastname = null;
199
200
    #[Groups(['user:read', 'user:write'])]
201
    #[ORM\Column(name: 'website', type: 'string', length: 255, nullable: true)]
202
    protected ?string $website;
203
204
    #[Groups(['user:read', 'user:write'])]
205
    #[ORM\Column(name: 'biography', type: 'text', nullable: true)]
206
    protected ?string $biography;
207
208
    #[Groups(['user:read', 'user:write', 'user_json:read'])]
209
    #[ORM\Column(name: 'locale', type: 'string', length: 10)]
210
    protected string $locale;
211
212
    #[Groups(['user:write'])]
213
    protected ?string $plainPassword = null;
214
215
    #[ORM\Column(name: 'password', type: 'string', length: 255)]
216
    protected string $password;
217
218
    #[ORM\Column(name: 'username_canonical', type: 'string', length: 180)]
219
    protected string $usernameCanonical;
220
221
    #[Groups(['user:read', 'user:write', 'user_json:read'])]
222
    #[ORM\Column(name: 'timezone', type: 'string', length: 64)]
223
    protected string $timezone;
224
225
    #[ORM\Column(name: 'email_canonical', type: 'string', length: 100)]
226
    protected string $emailCanonical;
227
228
    #[Groups(['user:read', 'user:write', 'user_json:read'])]
229
    #[Assert\NotBlank]
230
    #[Assert\Email]
231
    #[ORM\Column(name: 'email', type: 'string', length: 100)]
232
    protected string $email;
233
234
    #[ORM\Column(name: 'locked', type: 'boolean')]
235
    protected bool $locked;
236
237
    #[Groups(['user:read', 'user:write'])]
238
    #[ORM\Column(name: 'expired', type: 'boolean')]
239
    protected bool $expired;
240
241
    #[ORM\Column(name: 'credentials_expired', type: 'boolean')]
242
    protected bool $credentialsExpired;
243
244
    #[ORM\Column(name: 'credentials_expire_at', type: 'datetime', nullable: true)]
245
    protected ?DateTime $credentialsExpireAt;
246
247
    #[ORM\Column(name: 'date_of_birth', type: 'datetime', nullable: true)]
248
    protected ?DateTime $dateOfBirth;
249
250
    #[Groups(['user:read', 'user:write'])]
251
    #[ORM\Column(name: 'expires_at', type: 'datetime', nullable: true)]
252
    protected ?DateTime $expiresAt;
253
254
    #[Groups(['user:read', 'user:write'])]
255
    #[ORM\Column(name: 'phone', type: 'string', length: 64, nullable: true)]
256
    protected ?string $phone = null;
257
258
    #[Groups(['user:read', 'user:write'])]
259
    #[ORM\Column(name: 'address', type: 'string', length: 250, nullable: true)]
260
    protected ?string $address = null;
261
262
    #[ORM\Column(type: 'string', length: 255)]
263
    protected string $salt;
264
265
    #[ORM\Column(name: 'gender', type: 'string', length: 1, nullable: true)]
266
    protected ?string $gender = null;
267
268
    #[Groups(['user:read'])]
269
    #[ORM\Column(name: 'last_login', type: 'datetime', nullable: true)]
270
    protected ?DateTime $lastLogin = null;
271
272
    /**
273
     * Random string sent to the user email address in order to verify it.
274
     */
275
    #[ORM\Column(name: 'confirmation_token', type: 'string', length: 255, nullable: true)]
276
    protected ?string $confirmationToken = null;
277
278
    #[ORM\Column(name: 'password_requested_at', type: 'datetime', nullable: true)]
279
    protected ?DateTime $passwordRequestedAt;
280
281
    /**
282
     * @var Collection<int, CourseRelUser>
283
     */
284
    #[ORM\OneToMany(mappedBy: 'user', targetEntity: CourseRelUser::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
285
    protected Collection $courses;
286
287
    /**
288
     * @var Collection<int, UsergroupRelUser>
289
     */
290
    #[ORM\OneToMany(mappedBy: 'user', targetEntity: UsergroupRelUser::class)]
291
    protected Collection $classes;
292
293
    /**
294
     * ORM\OneToMany(targetEntity="Chamilo\CourseBundle\Entity\CDropboxPost", mappedBy="user").
295
     */
296
    protected Collection $dropBoxReceivedFiles;
297
298
    /**
299
     * ORM\OneToMany(targetEntity="Chamilo\CourseBundle\Entity\CDropboxFile", mappedBy="userSent").
300
     */
301
    protected Collection $dropBoxSentFiles;
302
303
    /**
304
     * An array of roles. Example: ROLE_USER, ROLE_TEACHER, ROLE_ADMIN.
305
     */
306
    #[Groups(['user:read', 'user:write', 'user_json:read'])]
307
    #[ORM\Column(type: 'array')]
308
    protected array $roles = [];
309
310
    #[ORM\Column(name: 'profile_completed', type: 'boolean', nullable: true)]
311
    protected ?bool $profileCompleted = null;
312
313
    /**
314
     * ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\JuryMembers", mappedBy="user").
315
     */
316
    // protected $jurySubscriptions;
317
318
    /**
319
     * @var Collection<int, Group>
320
     */
321
    #[ORM\JoinTable(name: 'fos_user_user_group')]
322
    #[ORM\JoinColumn(name: 'user_id', referencedColumnName: 'id', onDelete: 'cascade')]
323
    #[ORM\InverseJoinColumn(name: 'group_id', referencedColumnName: 'id')]
324
    #[ORM\ManyToMany(targetEntity: Group::class, inversedBy: 'users')]
325
    protected Collection $groups;
326
327
    /**
328
     * ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\CurriculumItemRelUser", mappedBy="user").
329
     */
330
    protected Collection $curriculumItems;
331
332
    /**
333
     * @var Collection<int, AccessUrlRelUser>
334
     */
335
    #[ORM\OneToMany(
336
        mappedBy: 'user',
337
        targetEntity: AccessUrlRelUser::class,
338
        cascade: ['persist', 'remove'],
339
        orphanRemoval: true
340
    )]
341
    protected Collection $portals;
342
343
    /**
344
     * @var Collection<int, ResourceNode>
345
     */
346
    #[ORM\OneToMany(mappedBy: 'creator', targetEntity: ResourceNode::class, cascade: ['persist', 'remove'])]
347
    protected Collection $resourceNodes;
348
349
    /**
350
     * @var Collection<int, SessionRelCourseRelUser>
351
     */
352
    #[ORM\OneToMany(
353
        mappedBy: 'user',
354
        targetEntity: SessionRelCourseRelUser::class,
355
        cascade: ['persist'],
356
        orphanRemoval: true
357
    )]
358
    protected Collection $sessionRelCourseRelUsers;
359
360
    /**
361
     * @var Collection<int, SessionRelUser>
362
     */
363
    #[ORM\OneToMany(
364
        mappedBy: 'user',
365
        targetEntity: SessionRelUser::class,
366
        cascade: ['persist', 'remove'],
367
        orphanRemoval: true
368
    )]
369
    protected Collection $sessionsRelUser;
370
371
    /**
372
     * @var Collection<int, SkillRelUser>
373
     */
374
    #[ORM\OneToMany(
375
        mappedBy: 'user',
376
        targetEntity: SkillRelUser::class,
377
        cascade: ['persist', 'remove'],
378
        orphanRemoval: true
379
    )]
380
    protected Collection $achievedSkills;
381
382
    /**
383
     * @var Collection<int, SkillRelUserComment>
384
     */
385
    #[ORM\OneToMany(
386
        mappedBy: 'feedbackGiver',
387
        targetEntity: SkillRelUserComment::class,
388
        cascade: ['persist', 'remove'],
389
        orphanRemoval: true
390
    )]
391
    protected Collection $commentedUserSkills;
392
393
    /**
394
     * @var Collection<int, GradebookCategory>
395
     */
396
    #[ORM\OneToMany(mappedBy: 'user', targetEntity: GradebookCategory::class)]
397
    protected Collection $gradeBookCategories;
398
399
    /**
400
     * @var Collection<int, GradebookCertificate>
401
     */
402
    #[ORM\OneToMany(
403
        mappedBy: 'user',
404
        targetEntity: GradebookCertificate::class,
405
        cascade: ['persist', 'remove'],
406
        orphanRemoval: true
407
    )]
408
    protected Collection $gradeBookCertificates;
409
410
    /**
411
     * @var Collection<int, GradebookComment>
412
     */
413
    #[ORM\OneToMany(mappedBy: 'user', targetEntity: GradebookComment::class)]
414
    protected Collection $gradeBookComments;
415
416
    /**
417
     * @var Collection<int, GradebookResult>
418
     */
419
    #[ORM\OneToMany(
420
        mappedBy: 'user',
421
        targetEntity: GradebookResult::class,
422
        cascade: ['persist', 'remove'],
423
        orphanRemoval: true
424
    )]
425
    protected Collection $gradeBookResults;
426
427
    /**
428
     * @var Collection<int, GradebookResultLog>
429
     */
430
    #[ORM\OneToMany(
431
        mappedBy: 'user',
432
        targetEntity: GradebookResultLog::class,
433
        cascade: ['persist', 'remove'],
434
        orphanRemoval: true
435
    )]
436
    protected Collection $gradeBookResultLogs;
437
438
    /**
439
     * @var Collection<int, GradebookScoreLog>
440
     */
441
    #[ORM\OneToMany(
442
        mappedBy: 'user',
443
        targetEntity: GradebookScoreLog::class,
444
        cascade: ['persist', 'remove'],
445
        orphanRemoval: true
446
    )]
447
    protected Collection $gradeBookScoreLogs;
448
449
    /**
450
     * @var Collection<int, UserRelUser>
451
     */
452
    #[ORM\OneToMany(
453
        mappedBy: 'user',
454
        targetEntity: UserRelUser::class,
455
        cascade: ['persist', 'remove'],
456
        fetch: 'EXTRA_LAZY',
457
        orphanRemoval: true
458
    )]
459
    protected Collection $friends;
460
461
    /**
462
     * @var Collection<int, UserRelUser>
463
     */
464
    #[ORM\OneToMany(
465
        mappedBy: 'friend',
466
        targetEntity: UserRelUser::class,
467
        cascade: ['persist', 'remove'],
468
        fetch: 'EXTRA_LAZY',
469
        orphanRemoval: true
470
    )]
471
    protected Collection $friendsWithMe;
472
473
    /**
474
     * @var Collection<int, GradebookLinkevalLog>
475
     */
476
    #[ORM\OneToMany(
477
        mappedBy: 'user',
478
        targetEntity: GradebookLinkevalLog::class,
479
        cascade: ['persist', 'remove'],
480
        orphanRemoval: true
481
    )]
482
    protected Collection $gradeBookLinkEvalLogs;
483
484
    /**
485
     * @var Collection<int, SequenceValue>
486
     */
487
    #[ORM\OneToMany(
488
        mappedBy: 'user',
489
        targetEntity: SequenceValue::class,
490
        cascade: ['persist', 'remove'],
491
        orphanRemoval: true
492
    )]
493
    protected Collection $sequenceValues;
494
495
    /**
496
     * @var Collection<int, TrackEExerciseConfirmation>
497
     */
498
    #[ORM\OneToMany(
499
        mappedBy: 'user',
500
        targetEntity: TrackEExerciseConfirmation::class,
501
        cascade: ['persist', 'remove'],
502
        orphanRemoval: true
503
    )]
504
    protected Collection $trackEExerciseConfirmations;
505
506
    /**
507
     * @var Collection<int, TrackEAttempt>
508
     */
509
    #[ORM\OneToMany(
510
        mappedBy: 'user',
511
        targetEntity: TrackEAccessComplete::class,
512
        cascade: [
513
            'persist',
514
            'remove',
515
        ],
516
        orphanRemoval: true
517
    )]
518
    protected Collection $trackEAccessCompleteList;
519
520
    /**
521
     * @var Collection<int, Templates>
522
     */
523
    #[ORM\OneToMany(
524
        mappedBy: 'user',
525
        targetEntity: Templates::class,
526
        cascade: ['persist', 'remove'],
527
        fetch: 'EXTRA_LAZY',
528
        orphanRemoval: true
529
    )]
530
    protected Collection $templates;
531
532
    /**
533
     * @var Collection<int, TrackEAttempt>
534
     */
535
    #[ORM\OneToMany(
536
        mappedBy: 'user',
537
        targetEntity: TrackEAttempt::class,
538
        cascade: ['persist', 'remove'],
539
        orphanRemoval: true
540
    )]
541
    protected Collection $trackEAttempts;
542
543
    /**
544
     * @var Collection<int, TrackECourseAccess>
545
     */
546
    #[ORM\OneToMany(
547
        mappedBy: 'user',
548
        targetEntity: TrackECourseAccess::class,
549
        cascade: ['persist', 'remove'],
550
        orphanRemoval: true
551
    )]
552
    protected Collection $trackECourseAccess;
553
554
    /**
555
     * @var Collection<int, UserCourseCategory>
556
     */
557
    #[ORM\OneToMany(
558
        mappedBy: 'user',
559
        targetEntity: UserCourseCategory::class,
560
        cascade: ['persist', 'remove'],
561
        orphanRemoval: true
562
    )]
563
    protected Collection $userCourseCategories;
564
565
    /**
566
     * @var Collection<int, UserRelCourseVote>
567
     */
568
    #[ORM\OneToMany(
569
        mappedBy: 'user',
570
        targetEntity: UserRelCourseVote::class,
571
        cascade: ['persist', 'remove'],
572
        orphanRemoval: true
573
    )]
574
    protected Collection $userRelCourseVotes;
575
576
    /**
577
     * @var Collection<int, UserRelTag>
578
     */
579
    #[ORM\OneToMany(
580
        mappedBy: 'user',
581
        targetEntity: UserRelTag::class,
582
        cascade: ['persist', 'remove'],
583
        orphanRemoval: true
584
    )]
585
    protected Collection $userRelTags;
586
587
    /**
588
     * @var Collection<int, CGroupRelUser>
589
     */
590
    #[ORM\OneToMany(
591
        mappedBy: 'user',
592
        targetEntity: CGroupRelUser::class,
593
        cascade: ['persist', 'remove'],
594
        orphanRemoval: true
595
    )]
596
    protected Collection $courseGroupsAsMember;
597
598
    /**
599
     * @var Collection<int, CGroupRelTutor>
600
     */
601
    #[ORM\OneToMany(mappedBy: 'user', targetEntity: CGroupRelTutor::class, orphanRemoval: true)]
602
    protected Collection $courseGroupsAsTutor;
603
604
    #[ORM\Column(name: 'status', type: 'integer')]
605
    protected int $status;
606
607
    #[ORM\Column(name: 'official_code', type: 'string', length: 40, nullable: true)]
608
    protected ?string $officialCode = null;
609
610
    #[ORM\Column(name: 'picture_uri', type: 'string', length: 250, nullable: true)]
611
    protected ?string $pictureUri = null;
612
613
    #[ORM\Column(name: 'creator_id', type: 'integer', unique: false, nullable: true)]
614
    protected ?int $creatorId = null;
615
616
    #[ORM\Column(name: 'competences', type: 'text', unique: false, nullable: true)]
617
    protected ?string $competences = null;
618
619
    #[ORM\Column(name: 'diplomas', type: 'text', unique: false, nullable: true)]
620
    protected ?string $diplomas = null;
621
622
    #[ORM\Column(name: 'openarea', type: 'text', unique: false, nullable: true)]
623
    protected ?string $openarea = null;
624
625
    #[ORM\Column(name: 'teach', type: 'text', unique: false, nullable: true)]
626
    protected ?string $teach = null;
627
628
    #[ORM\Column(name: 'productions', type: 'string', length: 250, unique: false, nullable: true)]
629
    protected ?string $productions = null;
630
631
    #[ORM\Column(name: 'expiration_date', type: 'datetime', unique: false, nullable: true)]
632
    protected ?DateTime $expirationDate = null;
633
634
    #[Groups(['user:read', 'user_json:read'])]
635
    #[ORM\Column(name: 'active', type: 'integer')]
636
    protected int $active;
637
638
    #[ORM\Column(name: 'openid', type: 'string', length: 255, unique: false, nullable: true)]
639
    protected ?string $openid = null;
640
641
    #[ORM\Column(name: 'theme', type: 'string', length: 255, unique: false, nullable: true)]
642
    protected ?string $theme = null;
643
644
    #[ORM\Column(name: 'hr_dept_id', type: 'smallint', unique: false, nullable: true)]
645
    protected ?int $hrDeptId = null;
646
647
    #[Groups(['user:write'])]
648
    protected ?AccessUrl $currentUrl = null;
649
650
    /**
651
     * @var Collection<int, MessageTag>
652
     */
653
    #[ORM\OneToMany(
654
        mappedBy: 'user',
655
        targetEntity: MessageTag::class,
656
        cascade: ['persist', 'remove'],
657
        orphanRemoval: true
658
    )]
659
    protected Collection $messageTags;
660
661
    /**
662
     * @var Collection<int, Message>
663
     */
664
    #[ORM\OneToMany(
665
        mappedBy: 'sender',
666
        targetEntity: Message::class,
667
        cascade: ['persist']
668
    )]
669
    protected Collection $sentMessages;
670
671
    /**
672
     * @var Collection<int, MessageRelUser>
673
     */
674
    #[ORM\OneToMany(mappedBy: 'receiver', targetEntity: MessageRelUser::class, cascade: ['persist', 'remove'])]
675
    protected Collection $receivedMessages;
676
677
    /**
678
     * @var Collection<int, CSurveyInvitation>
679
     */
680
    #[ORM\OneToMany(mappedBy: 'user', targetEntity: CSurveyInvitation::class, cascade: ['persist', 'remove'])]
681
    protected Collection $surveyInvitations;
682
683
    /**
684
     * @var Collection<int, TrackELogin>
685
     */
686
    #[ORM\OneToMany(mappedBy: 'user', targetEntity: TrackELogin::class, cascade: ['persist', 'remove'])]
687
    protected Collection $logins;
688
689
    #[ORM\OneToOne(mappedBy: 'user', targetEntity: Admin::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
690
    protected ?Admin $admin = null;
691
692
    #[ORM\Column(type: 'uuid', unique: true)]
693
    protected Uuid $uuid;
694
695
    // Property used only during installation.
696
    protected bool $skipResourceNode = false;
697
698
    #[Groups([
699
        'user:read',
700
        'user_json:read',
701
        'social_post:read',
702
        'course:read',
703
        'course_rel_user:read',
704
        'message:read',
705
        'user_subscriptions:sessions',
706
        'student_publication_rel_user:read',
707
    ])]
708
    protected string $fullName;
709
710
    #[ORM\OneToMany(mappedBy: 'sender', targetEntity: SocialPost::class, orphanRemoval: true)]
711
    private Collection $sentSocialPosts;
712
713
    #[ORM\OneToMany(mappedBy: 'userReceiver', targetEntity: SocialPost::class)]
714
    private Collection $receivedSocialPosts;
715
716
    #[ORM\OneToMany(mappedBy: 'user', targetEntity: SocialPostFeedback::class, orphanRemoval: true)]
717
    private Collection $socialPostsFeedbacks;
718
719
    #[ORM\Column(name: 'mfa_enabled', type: 'boolean', options: ['default' => false])]
720
    protected bool $mfaEnabled = false;
721
722
    #[ORM\Column(name: 'mfa_service', type: 'string', length: 255, nullable: true)]
723
    protected ?string $mfaService = null;
724
725
    #[ORM\Column(name: 'mfa_secret', type: 'string', length: 255, nullable: true)]
726
    protected ?string $mfaSecret = null;
727
728
    #[ORM\Column(name: 'mfa_backup_codes', type: 'text', nullable: true)]
729
    protected ?string $mfaBackupCodes = null;
730
731
    #[ORM\Column(name: 'mfa_last_used', type: 'datetime', nullable: true)]
732
    protected ?DateTimeInterface $mfaLastUsed = null;
733
734
    /**
735
     * @var Collection<int, UserAuthSource>
736
     */
737
    #[ORM\OneToMany(mappedBy: 'user', targetEntity: UserAuthSource::class, cascade: ['persist'], orphanRemoval: true)]
738
    private Collection $authSources;
739
740
    #[Groups(['user:read', 'user:write'])]
741
    #[ORM\Column(name: 'password_update_at', type: 'datetime', nullable: true)]
742
    protected ?\DateTimeInterface $passwordUpdatedAt = null;
743
744
    public function __construct()
745
    {
746
        $this->skipResourceNode = false;
747
        $this->uuid = Uuid::v4();
748
        $this->apiToken = null;
749
        $this->biography = '';
750
        $this->website = '';
751
        $this->locale = 'en';
752
        $this->timezone = 'Europe/Paris';
753
        $this->status = CourseRelUser::STUDENT;
754
        $this->salt = sha1(uniqid('', true));
755
        $this->active = 1;
756
        $this->locked = false;
757
        $this->expired = false;
758
        $this->courses = new ArrayCollection();
759
        $this->classes = new ArrayCollection();
760
        $this->curriculumItems = new ArrayCollection();
761
        $this->portals = new ArrayCollection();
762
        $this->dropBoxSentFiles = new ArrayCollection();
763
        $this->dropBoxReceivedFiles = new ArrayCollection();
764
        $this->groups = new ArrayCollection();
765
        $this->gradeBookCertificates = new ArrayCollection();
766
        $this->courseGroupsAsMember = new ArrayCollection();
767
        $this->courseGroupsAsTutor = new ArrayCollection();
768
        $this->resourceNodes = new ArrayCollection();
769
        $this->sessionRelCourseRelUsers = new ArrayCollection();
770
        $this->achievedSkills = new ArrayCollection();
771
        $this->commentedUserSkills = new ArrayCollection();
772
        $this->gradeBookCategories = new ArrayCollection();
773
        $this->gradeBookComments = new ArrayCollection();
774
        $this->gradeBookResults = new ArrayCollection();
775
        $this->gradeBookResultLogs = new ArrayCollection();
776
        $this->gradeBookScoreLogs = new ArrayCollection();
777
        $this->friends = new ArrayCollection();
778
        $this->friendsWithMe = new ArrayCollection();
779
        $this->gradeBookLinkEvalLogs = new ArrayCollection();
780
        $this->messageTags = new ArrayCollection();
781
        $this->sequenceValues = new ArrayCollection();
782
        $this->trackEExerciseConfirmations = new ArrayCollection();
783
        $this->trackEAccessCompleteList = new ArrayCollection();
784
        $this->templates = new ArrayCollection();
785
        $this->trackEAttempts = new ArrayCollection();
786
        $this->trackECourseAccess = new ArrayCollection();
787
        $this->userCourseCategories = new ArrayCollection();
788
        $this->userRelCourseVotes = new ArrayCollection();
789
        $this->userRelTags = new ArrayCollection();
790
        $this->sessionsRelUser = new ArrayCollection();
791
        $this->sentMessages = new ArrayCollection();
792
        $this->receivedMessages = new ArrayCollection();
793
        $this->surveyInvitations = new ArrayCollection();
794
        $this->logins = new ArrayCollection();
795
        $this->createdAt = new DateTime();
796
        $this->updatedAt = new DateTime();
797
        $this->roles = [];
798
        $this->credentialsExpired = false;
799
        $this->credentialsExpireAt = new DateTime();
800
        $this->dateOfBirth = new DateTime();
801
        $this->expiresAt = new DateTime();
802
        $this->passwordRequestedAt = new DateTime();
803
        $this->sentSocialPosts = new ArrayCollection();
804
        $this->receivedSocialPosts = new ArrayCollection();
805
        $this->socialPostsFeedbacks = new ArrayCollection();
806
        $this->authSources = new ArrayCollection();
807
    }
808
809
    public function __toString(): string
810
    {
811
        return $this->username;
812
    }
813
814
    public static function getPasswordConstraints(): array
815
    {
816
        return [
817
            new Assert\Length(['min' => 5]),
818
            new Assert\Regex(['pattern' => '/^[a-z\-_0-9]+$/i', 'htmlPattern' => '/^[a-z\-_0-9]+$/i']),
819
            new Assert\Regex(['pattern' => '/[0-9]{2}/', 'htmlPattern' => '/[0-9]{2}/']),
820
        ];
821
    }
822
823
    public static function loadValidatorMetadata(ClassMetadata $metadata): void {}
824
825
    public function getUuid(): Uuid
826
    {
827
        return $this->uuid;
828
    }
829
830
    public function setUuid(Uuid $uuid): self
831
    {
832
        $this->uuid = $uuid;
833
834
        return $this;
835
    }
836
837
    public function getResourceNode(): ?ResourceNode
838
    {
839
        return $this->resourceNode;
840
    }
841
842
    public function setResourceNode(ResourceNode $resourceNode): self
843
    {
844
        $this->resourceNode = $resourceNode;
845
846
        return $this;
847
    }
848
849
    public function hasResourceNode(): bool
850
    {
851
        return $this->resourceNode instanceof ResourceNode;
852
    }
853
854
    public function getResourceNodes(): Collection
855
    {
856
        return $this->resourceNodes;
857
    }
858
859
    public function addResourceNode(ResourceNode $resourceNode): static
860
    {
861
        if (!$this->resourceNodes->contains($resourceNode)) {
862
            $this->resourceNodes->add($resourceNode);
863
            $resourceNode->setCreator($this);
864
        }
865
866
        return $this;
867
    }
868
869
    public function getDropBoxSentFiles(): Collection
870
    {
871
        return $this->dropBoxSentFiles;
872
    }
873
874
    public function setDropBoxSentFiles(Collection $value): self
875
    {
876
        $this->dropBoxSentFiles = $value;
877
878
        return $this;
879
    }
880
881
    public function getCourses(): Collection
882
    {
883
        return $this->courses;
884
    }
885
886
    /**
887
     * @param Collection<int, CourseRelUser> $courses
888
     */
889
    public function setCourses(Collection $courses): self
890
    {
891
        $this->courses = $courses;
892
893
        return $this;
894
    }
895
896
    public function setPortal(AccessUrlRelUser $portal): self
897
    {
898
        $this->portals->add($portal);
899
900
        return $this;
901
    }
902
903
    /**
904
     * Get a bool on whether the user is active or not. Active can be "-1" which means pre-deleted, and is returned as false (not active).
905
     *
906
     * @return bool True if active = 1, false in any other case (0 = inactive, -1 = predeleted)
907
     */
908
    public function getIsActive(): bool
909
    {
910
        return 1 === $this->active;
911
    }
912
913
    public function isEnabled(): bool
914
    {
915
        return $this->isActive();
916
    }
917
918
    /**
919
     * Returns the list of classes for the user.
920
     */
921
    public function getCompleteNameWithClasses(): string
922
    {
923
        $classSubscription = $this->getClasses();
924
        $classList = [];
925
926
        /** @var UsergroupRelUser $subscription */
927
        foreach ($classSubscription as $subscription) {
928
            $class = $subscription->getUsergroup();
929
            $classList[] = $class->getTitle();
930
        }
931
        $classString = empty($classList) ? null : ' ['.implode(', ', $classList).']';
932
933
        return UserManager::formatUserFullName($this).$classString;
934
    }
935
936
    public function getClasses(): Collection
937
    {
938
        return $this->classes;
939
    }
940
941
    /**
942
     * @param Collection<int, UsergroupRelUser> $classes
943
     */
944
    public function setClasses(Collection $classes): self
945
    {
946
        $this->classes = $classes;
947
948
        return $this;
949
    }
950
951
    public function getEmail(): string
952
    {
953
        return $this->email;
954
    }
955
956
    public function setEmail(string $email): self
957
    {
958
        $this->email = $email;
959
960
        return $this;
961
    }
962
963
    public function getOfficialCode(): ?string
964
    {
965
        return $this->officialCode;
966
    }
967
968
    public function setOfficialCode(?string $officialCode): self
969
    {
970
        $this->officialCode = $officialCode;
971
972
        return $this;
973
    }
974
975
    public function getPhone(): ?string
976
    {
977
        return $this->phone;
978
    }
979
980
    public function setPhone(?string $phone): self
981
    {
982
        $this->phone = $phone;
983
984
        return $this;
985
    }
986
987
    public function getAddress(): ?string
988
    {
989
        return $this->address;
990
    }
991
992
    public function setAddress(?string $address): self
993
    {
994
        $this->address = $address;
995
996
        return $this;
997
    }
998
999
    public function getCreatorId(): ?int
1000
    {
1001
        return $this->creatorId;
1002
    }
1003
1004
    public function setCreatorId(int $creatorId): self
1005
    {
1006
        $this->creatorId = $creatorId;
1007
1008
        return $this;
1009
    }
1010
1011
    public function getCompetences(): ?string
1012
    {
1013
        return $this->competences;
1014
    }
1015
1016
    public function setCompetences(?string $competences): self
1017
    {
1018
        $this->competences = $competences;
1019
1020
        return $this;
1021
    }
1022
1023
    public function getDiplomas(): ?string
1024
    {
1025
        return $this->diplomas;
1026
    }
1027
1028
    public function setDiplomas(?string $diplomas): self
1029
    {
1030
        $this->diplomas = $diplomas;
1031
1032
        return $this;
1033
    }
1034
1035
    public function getOpenarea(): ?string
1036
    {
1037
        return $this->openarea;
1038
    }
1039
1040
    public function setOpenarea(?string $openarea): self
1041
    {
1042
        $this->openarea = $openarea;
1043
1044
        return $this;
1045
    }
1046
1047
    public function getTeach(): ?string
1048
    {
1049
        return $this->teach;
1050
    }
1051
1052
    public function setTeach(?string $teach): self
1053
    {
1054
        $this->teach = $teach;
1055
1056
        return $this;
1057
    }
1058
1059
    public function getProductions(): ?string
1060
    {
1061
        return $this->productions;
1062
    }
1063
1064
    public function setProductions(?string $productions): self
1065
    {
1066
        $this->productions = $productions;
1067
1068
        return $this;
1069
    }
1070
1071
    public function getExpirationDate(): ?DateTime
1072
    {
1073
        return $this->expirationDate;
1074
    }
1075
1076
    public function setExpirationDate(?DateTime $expirationDate): self
1077
    {
1078
        $this->expirationDate = $expirationDate;
1079
1080
        return $this;
1081
    }
1082
1083
    public function getActive(): int
1084
    {
1085
        return $this->active;
1086
    }
1087
1088
    public function isActive(): bool
1089
    {
1090
        return $this->getIsActive();
1091
    }
1092
1093
    public function setActive(int $active): self
1094
    {
1095
        $this->active = $active;
1096
1097
        return $this;
1098
    }
1099
1100
    public function getOpenid(): ?string
1101
    {
1102
        return $this->openid;
1103
    }
1104
1105
    public function setOpenid(string $openid): self
1106
    {
1107
        $this->openid = $openid;
1108
1109
        return $this;
1110
    }
1111
1112
    public function getTheme(): ?string
1113
    {
1114
        return $this->theme;
1115
    }
1116
1117
    public function setTheme(string $theme): self
1118
    {
1119
        $this->theme = $theme;
1120
1121
        return $this;
1122
    }
1123
1124
    public function getHrDeptId(): ?int
1125
    {
1126
        return $this->hrDeptId;
1127
    }
1128
1129
    public function setHrDeptId(int $hrDeptId): self
1130
    {
1131
        $this->hrDeptId = $hrDeptId;
1132
1133
        return $this;
1134
    }
1135
1136
    public function isOnline(): bool
1137
    {
1138
        return false;
1139
    }
1140
1141
    public function getIdentifier(): int
1142
    {
1143
        return $this->getId();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getId() could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
1144
    }
1145
1146
    public function getId(): ?int
1147
    {
1148
        return $this->id;
1149
    }
1150
1151
    public function getIri(): ?string
1152
    {
1153
        if (null === $this->id) {
1154
            return null;
1155
        }
1156
1157
        return '/api/users/'.$this->getId();
1158
    }
1159
1160
    public function getSlug(): string
1161
    {
1162
        return $this->getUsername();
1163
    }
1164
1165
    public function getUsername(): string
1166
    {
1167
        return $this->username;
1168
    }
1169
1170
    public function setUsername(string $username): self
1171
    {
1172
        $this->username = $username;
1173
1174
        return $this;
1175
    }
1176
1177
    public function setSlug(string $slug): self
1178
    {
1179
        return $this->setUsername($slug);
1180
    }
1181
1182
    public function getLastLogin(): ?DateTime
1183
    {
1184
        return $this->lastLogin;
1185
    }
1186
1187
    public function setLastLogin(?DateTime $lastLogin = null): self
1188
    {
1189
        $this->lastLogin = $lastLogin;
1190
1191
        return $this;
1192
    }
1193
1194
    public function getConfirmationToken(): ?string
1195
    {
1196
        return $this->confirmationToken;
1197
    }
1198
1199
    public function setConfirmationToken(string $confirmationToken): self
1200
    {
1201
        $this->confirmationToken = $confirmationToken;
1202
1203
        return $this;
1204
    }
1205
1206
    public function isPasswordRequestNonExpired(int $ttl): bool
1207
    {
1208
        return $this->getPasswordRequestedAt() instanceof DateTime && $this->getPasswordRequestedAt()->getTimestamp(
1209
        ) + $ttl > time();
1210
    }
1211
1212
    public function getPasswordRequestedAt(): ?DateTime
1213
    {
1214
        return $this->passwordRequestedAt;
1215
    }
1216
1217
    public function setPasswordRequestedAt(?DateTime $date = null): self
1218
    {
1219
        $this->passwordRequestedAt = $date;
1220
1221
        return $this;
1222
    }
1223
1224
    public function getPlainPassword(): ?string
1225
    {
1226
        return $this->plainPassword;
1227
    }
1228
1229
    public function setPlainPassword(?string $password): self
1230
    {
1231
        $this->plainPassword = $password;
1232
        // forces the object to look "dirty" to Doctrine. Avoids
1233
        // Doctrine *not* saving this entity, if only plainPassword changes
1234
        $this->password = '';
1235
1236
        return $this;
1237
    }
1238
1239
    /**
1240
     * Returns the expiration date.
1241
     */
1242
    public function getExpiresAt(): ?DateTime
1243
    {
1244
        return $this->expiresAt;
1245
    }
1246
1247
    public function setExpiresAt(DateTime $date): self
1248
    {
1249
        $this->expiresAt = $date;
1250
1251
        return $this;
1252
    }
1253
1254
    /**
1255
     * Returns the credentials expiration date.
1256
     */
1257
    public function getCredentialsExpireAt(): ?DateTime
1258
    {
1259
        return $this->credentialsExpireAt;
1260
    }
1261
1262
    /**
1263
     * Sets the credentials expiration date.
1264
     */
1265
    public function setCredentialsExpireAt(?DateTime $date = null): self
1266
    {
1267
        $this->credentialsExpireAt = $date;
1268
1269
        return $this;
1270
    }
1271
1272
    #[Groups(['user:read', 'student_publication:read', 'student_publication_comment:read'])]
1273
    public function getFullname(): string
1274
    {
1275
        if (empty($this->fullName)) {
1276
            return \sprintf('%s %s', $this->getFirstname(), $this->getLastname());
1277
        }
1278
1279
        return $this->fullName;
1280
    }
1281
1282
    public function setFullName(string $fullName): self
1283
    {
1284
        $this->fullName = $fullName;
1285
1286
        return $this;
1287
    }
1288
1289
    public function getFirstname(): ?string
1290
    {
1291
        return $this->firstname;
1292
    }
1293
1294
    public function setFirstname(string $firstname): self
1295
    {
1296
        $this->firstname = $firstname;
1297
1298
        return $this;
1299
    }
1300
1301
    public function getLastname(): ?string
1302
    {
1303
        return $this->lastname;
1304
    }
1305
1306
    public function setLastname(string $lastname): self
1307
    {
1308
        $this->lastname = $lastname;
1309
1310
        return $this;
1311
    }
1312
1313
    public function hasGroup(string $name): bool
1314
    {
1315
        return \in_array($name, $this->getGroupNames(), true);
1316
    }
1317
1318
    public function getGroupNames(): array
1319
    {
1320
        $names = [];
1321
        foreach ($this->getGroups() as $group) {
1322
            $names[] = $group->getTitle();
1323
        }
1324
1325
        return $names;
1326
    }
1327
1328
    public function getGroups(): Collection
1329
    {
1330
        return $this->groups;
1331
    }
1332
1333
    /**
1334
     * Sets the user groups.
1335
     */
1336
    public function setGroups(Collection $groups): self
1337
    {
1338
        foreach ($groups as $group) {
1339
            $this->addGroup($group);
1340
        }
1341
1342
        return $this;
1343
    }
1344
1345
    public function addGroup(Group $group): self
1346
    {
1347
        if (!$this->getGroups()->contains($group)) {
1348
            $this->getGroups()->add($group);
1349
        }
1350
1351
        return $this;
1352
    }
1353
1354
    public function removeGroup(Group $group): self
1355
    {
1356
        if ($this->getGroups()->contains($group)) {
1357
            $this->getGroups()->removeElement($group);
1358
        }
1359
1360
        return $this;
1361
    }
1362
1363
    public function isAccountNonExpired(): bool
1364
    {
1365
        return true;
1366
    }
1367
1368
    public function isAccountNonLocked(): bool
1369
    {
1370
        return true;
1371
    }
1372
1373
    public function isCredentialsNonExpired(): bool
1374
    {
1375
        return true;
1376
    }
1377
1378
    public function getCredentialsExpired(): bool
1379
    {
1380
        return $this->credentialsExpired;
1381
    }
1382
1383
    public function setCredentialsExpired(bool $boolean): self
1384
    {
1385
        $this->credentialsExpired = $boolean;
1386
1387
        return $this;
1388
    }
1389
1390
    public function getExpired(): bool
1391
    {
1392
        return $this->expired;
1393
    }
1394
1395
    /**
1396
     * Sets this user to expired.
1397
     */
1398
    public function setExpired(bool $boolean): self
1399
    {
1400
        $this->expired = $boolean;
1401
1402
        return $this;
1403
    }
1404
1405
    public function getLocked(): bool
1406
    {
1407
        return $this->locked;
1408
    }
1409
1410
    public function setLocked(bool $boolean): self
1411
    {
1412
        $this->locked = $boolean;
1413
1414
        return $this;
1415
    }
1416
1417
    /**
1418
     * Check if the user has the skill.
1419
     *
1420
     * @param Skill $skill The skill
1421
     */
1422
    public function hasSkill(Skill $skill): bool
1423
    {
1424
        $achievedSkills = $this->getAchievedSkills();
1425
        foreach ($achievedSkills as $userSkill) {
1426
            if ($userSkill->getSkill()->getId() !== $skill->getId()) {
1427
                continue;
1428
            }
1429
1430
            return true;
1431
        }
1432
1433
        return false;
1434
    }
1435
1436
    /**
1437
     * @return Collection<int, SkillRelUser>
1438
     */
1439
    public function getAchievedSkills(): Collection
1440
    {
1441
        return $this->achievedSkills;
1442
    }
1443
1444
    /**
1445
     * @param Collection<int, SkillRelUser> $value
1446
     */
1447
    public function setAchievedSkills(Collection $value): self
1448
    {
1449
        $this->achievedSkills = $value;
1450
1451
        return $this;
1452
    }
1453
1454
    public function isProfileCompleted(): ?bool
1455
    {
1456
        return $this->profileCompleted;
1457
    }
1458
1459
    public function setProfileCompleted(?bool $profileCompleted): self
1460
    {
1461
        $this->profileCompleted = $profileCompleted;
1462
1463
        return $this;
1464
    }
1465
1466
    public function getCurrentUrl(): ?AccessUrl
1467
    {
1468
        return $this->currentUrl;
1469
    }
1470
1471
    public function setCurrentUrl(AccessUrl $url): self
1472
    {
1473
        $accessUrlRelUser = (new AccessUrlRelUser())->setUrl($url)->setUser($this);
1474
        $this->getPortals()->add($accessUrlRelUser);
1475
1476
        return $this;
1477
    }
1478
1479
    public function getPortals(): Collection
1480
    {
1481
        return $this->portals;
1482
    }
1483
1484
    /**
1485
     * @param Collection<int, AccessUrlRelUser> $value
1486
     */
1487
    public function setPortals(Collection $value): void
1488
    {
1489
        $this->portals = $value;
1490
    }
1491
1492
    public function getSessionsAsGeneralCoach(): array
1493
    {
1494
        return $this->getSessions(Session::GENERAL_COACH);
1495
    }
1496
1497
    /**
1498
     * Retrieves this user's related sessions.
1499
     */
1500
    public function getSessions(int $relationType): array
1501
    {
1502
        $sessions = [];
1503
        foreach ($this->getSessionsRelUser() as $sessionRelUser) {
1504
            if ($sessionRelUser->getRelationType() === $relationType) {
1505
                $sessions[] = $sessionRelUser->getSession();
1506
            }
1507
        }
1508
1509
        return $sessions;
1510
    }
1511
1512
    /**
1513
     * @return Collection<int, SessionRelUser>
1514
     */
1515
    public function getSessionsRelUser(): Collection
1516
    {
1517
        return $this->sessionsRelUser;
1518
    }
1519
1520
    public function getSessionsAsAdmin(): array
1521
    {
1522
        return $this->getSessions(Session::SESSION_ADMIN);
1523
    }
1524
1525
    public function getCommentedUserSkills(): Collection
1526
    {
1527
        return $this->commentedUserSkills;
1528
    }
1529
1530
    /**
1531
     * @param Collection<int, SkillRelUserComment> $commentedUserSkills
1532
     */
1533
    public function setCommentedUserSkills(Collection $commentedUserSkills): self
1534
    {
1535
        $this->commentedUserSkills = $commentedUserSkills;
1536
1537
        return $this;
1538
    }
1539
1540
    public function isEqualTo(UserInterface $user): bool
1541
    {
1542
        if ($this->password !== $user->getPassword()) {
1543
            return false;
1544
        }
1545
        if ($this->salt !== $user->getSalt()) {
1546
            return false;
1547
        }
1548
        if ($this->username !== $user->getUserIdentifier()) {
1549
            return false;
1550
        }
1551
1552
        return true;
1553
    }
1554
1555
    public function getPassword(): ?string
1556
    {
1557
        return $this->password;
1558
    }
1559
1560
    public function setPassword(string $password): self
1561
    {
1562
        $this->password = $password;
1563
1564
        return $this;
1565
    }
1566
1567
    public function getSalt(): ?string
1568
    {
1569
        return $this->salt;
1570
    }
1571
1572
    public function setSalt(string $salt): self
1573
    {
1574
        $this->salt = $salt;
1575
1576
        return $this;
1577
    }
1578
1579
    public function getUserIdentifier(): string
1580
    {
1581
        return $this->username;
1582
    }
1583
1584
    /**
1585
     * @return Collection<int, Message>
1586
     */
1587
    public function getSentMessages(): Collection
1588
    {
1589
        return $this->sentMessages;
1590
    }
1591
1592
    public function getReceivedMessages(): Collection
1593
    {
1594
        return $this->receivedMessages;
1595
    }
1596
1597
    public function getCourseGroupsAsMember(): Collection
1598
    {
1599
        return $this->courseGroupsAsMember;
1600
    }
1601
1602
    public function getCourseGroupsAsTutor(): Collection
1603
    {
1604
        return $this->courseGroupsAsTutor;
1605
    }
1606
1607
    public function getCourseGroupsAsMemberFromCourse(Course $course): Collection
1608
    {
1609
        $criteria = Criteria::create();
1610
        $criteria->where(Criteria::expr()->eq('cId', $course));
1611
1612
        return $this->courseGroupsAsMember->matching($criteria);
1613
    }
1614
1615
    public function eraseCredentials(): void
1616
    {
1617
        $this->plainPassword = null;
1618
    }
1619
1620
    /**
1621
     * Returns whether a user can be admin of all multi-URL portals in the case of a multi-URL install.
1622
     */
1623
    public function isSuperAdmin(): bool
1624
    {
1625
        return $this->hasRole('ROLE_SUPER_ADMIN');
1626
    }
1627
1628
    public function hasRole(string $role): bool
1629
    {
1630
        return \in_array(strtoupper($role), $this->getRoles(), true);
1631
    }
1632
1633
    /**
1634
     * Returns the user roles.
1635
     */
1636
    public function getRoles(): array
1637
    {
1638
        $roles = $this->roles;
1639
        foreach ($this->getGroups() as $group) {
1640
            $roles = array_merge($roles, $group->getRoles());
1641
        }
1642
        // we need to make sure to have at least one role
1643
        $roles[] = 'ROLE_USER';
1644
1645
        return array_unique($roles);
1646
    }
1647
1648
    public function setRoles(array $roles): self
1649
    {
1650
        $this->roles = [];
1651
        foreach ($roles as $role) {
1652
            $this->addRole($role);
1653
        }
1654
1655
        return $this;
1656
    }
1657
1658
    public function setRoleFromStatus(int $status): void
1659
    {
1660
        $role = self::getRoleFromStatus($status);
1661
        $this->addRole($role);
1662
    }
1663
1664
    public static function getRoleFromStatus(int $status): string
1665
    {
1666
        return match ($status) {
1667
            COURSEMANAGER => 'ROLE_TEACHER',
1668
            STUDENT => 'ROLE_STUDENT',
1669
            DRH => 'ROLE_HR',
1670
            SESSIONADMIN => 'ROLE_SESSION_MANAGER',
1671
            STUDENT_BOSS => 'ROLE_STUDENT_BOSS',
1672
            INVITEE => 'ROLE_INVITEE',
1673
            default => 'ROLE_USER',
1674
        };
1675
    }
1676
1677
    public function addRole(string $role): self
1678
    {
1679
        $role = strtoupper($role);
1680
        if ($role === static::ROLE_DEFAULT || empty($role)) {
1681
            return $this;
1682
        }
1683
        if (!\in_array($role, $this->roles, true)) {
1684
            $this->roles[] = $role;
1685
        }
1686
1687
        return $this;
1688
    }
1689
1690
    public function removeRole(string $role): self
1691
    {
1692
        if (false !== ($key = array_search(strtoupper($role), $this->roles, true))) {
1693
            unset($this->roles[$key]);
1694
            $this->roles = array_values($this->roles);
1695
        }
1696
1697
        return $this;
1698
    }
1699
1700
    public function getUsernameCanonical(): string
1701
    {
1702
        return $this->usernameCanonical;
1703
    }
1704
1705
    public function setUsernameCanonical(string $usernameCanonical): self
1706
    {
1707
        $this->usernameCanonical = $usernameCanonical;
1708
1709
        return $this;
1710
    }
1711
1712
    public function getEmailCanonical(): string
1713
    {
1714
        return $this->emailCanonical;
1715
    }
1716
1717
    public function setEmailCanonical(string $emailCanonical): self
1718
    {
1719
        $this->emailCanonical = $emailCanonical;
1720
1721
        return $this;
1722
    }
1723
1724
    public function getTimezone(): string
1725
    {
1726
        return $this->timezone;
1727
    }
1728
1729
    public function setTimezone(string $timezone): self
1730
    {
1731
        $this->timezone = $timezone;
1732
1733
        return $this;
1734
    }
1735
1736
    public function getLocale(): string
1737
    {
1738
        return $this->locale;
1739
    }
1740
1741
    public function setLocale(string $locale): self
1742
    {
1743
        $this->locale = $locale;
1744
1745
        return $this;
1746
    }
1747
1748
    public function getApiToken(): ?string
1749
    {
1750
        return $this->apiToken;
1751
    }
1752
1753
    public function setApiToken(string $apiToken): self
1754
    {
1755
        $this->apiToken = $apiToken;
1756
1757
        return $this;
1758
    }
1759
1760
    public function getWebsite(): ?string
1761
    {
1762
        return $this->website;
1763
    }
1764
1765
    public function setWebsite(string $website): self
1766
    {
1767
        $this->website = $website;
1768
1769
        return $this;
1770
    }
1771
1772
    public function getBiography(): ?string
1773
    {
1774
        return $this->biography;
1775
    }
1776
1777
    public function setBiography(string $biography): self
1778
    {
1779
        $this->biography = $biography;
1780
1781
        return $this;
1782
    }
1783
1784
    public function getDateOfBirth(): ?DateTime
1785
    {
1786
        return $this->dateOfBirth;
1787
    }
1788
1789
    public function setDateOfBirth(?DateTime $dateOfBirth = null): self
1790
    {
1791
        $this->dateOfBirth = $dateOfBirth;
1792
1793
        return $this;
1794
    }
1795
1796
    public function getProfileUrl(): string
1797
    {
1798
        return '/main/social/profile.php?u='.$this->id;
1799
    }
1800
1801
    public function getIconStatus(): string
1802
    {
1803
        $hasCertificates = $this->getGradeBookCertificates()->count() > 0;
1804
        $urlImg = '/img/';
1805
        if ($this->isStudent()) {
1806
            $iconStatus = $urlImg.'icons/svg/identifier_student.svg';
1807
            if ($hasCertificates) {
1808
                $iconStatus = $urlImg.'icons/svg/identifier_graduated.svg';
1809
            }
1810
1811
            return $iconStatus;
1812
        }
1813
        if ($this->isTeacher()) {
1814
            $iconStatus = $urlImg.'icons/svg/identifier_teacher.svg';
1815
            if ($this->isAdmin()) {
1816
                $iconStatus = $urlImg.'icons/svg/identifier_admin.svg';
1817
            }
1818
1819
            return $iconStatus;
1820
        }
1821
        if ($this->isStudentBoss()) {
1822
            return $urlImg.'icons/svg/identifier_teacher.svg';
1823
        }
1824
1825
        return '';
1826
    }
1827
1828
    public function getGradeBookCertificates(): Collection
1829
    {
1830
        return $this->gradeBookCertificates;
1831
    }
1832
1833
    /**
1834
     * @param Collection<int, GradebookCertificate> $gradeBookCertificates
1835
     */
1836
    public function setGradeBookCertificates(Collection $gradeBookCertificates): self
1837
    {
1838
        $this->gradeBookCertificates = $gradeBookCertificates;
1839
1840
        return $this;
1841
    }
1842
1843
    public function isStudent(): bool
1844
    {
1845
        return $this->hasRole('ROLE_STUDENT');
1846
    }
1847
1848
    public function isTeacher(): bool
1849
    {
1850
        return $this->hasRole('ROLE_TEACHER');
1851
    }
1852
1853
    public function isAdmin(): bool
1854
    {
1855
        return $this->hasRole('ROLE_ADMIN');
1856
    }
1857
1858
    public function isStudentBoss(): bool
1859
    {
1860
        return $this->hasRole('ROLE_STUDENT_BOSS');
1861
    }
1862
1863
    public function isSessionAdmin(): bool
1864
    {
1865
        return $this->hasRole('ROLE_SESSION_MANAGER');
1866
    }
1867
1868
    public function isInvitee(): bool
1869
    {
1870
        return $this->hasRole('ROLE_INVITEE');
1871
    }
1872
1873
    public function isHRM(): bool
1874
    {
1875
        return $this->hasRole('ROLE_HR');
1876
    }
1877
1878
    public function getStatus(): int
1879
    {
1880
        return $this->status;
1881
    }
1882
1883
    public function setStatus(int $status): self
1884
    {
1885
        $this->status = $status;
1886
1887
        return $this;
1888
    }
1889
1890
    public function getPictureUri(): ?string
1891
    {
1892
        return $this->pictureUri;
1893
    }
1894
1895
    /**
1896
     * @return Collection<int, GradebookCategory>
1897
     */
1898
    public function getGradeBookCategories(): Collection
1899
    {
1900
        return $this->gradeBookCategories;
1901
    }
1902
1903
    /**
1904
     * @return Collection<int, GradebookComment>
1905
     */
1906
    public function getGradeBookComments(): Collection
1907
    {
1908
        return $this->gradeBookComments;
1909
    }
1910
1911
    /**
1912
     * @return Collection<int, GradebookResult>
1913
     */
1914
    public function getGradeBookResults(): Collection
1915
    {
1916
        return $this->gradeBookResults;
1917
    }
1918
1919
    /**
1920
     * @return Collection<int, GradebookResultLog>
1921
     */
1922
    public function getGradeBookResultLogs(): Collection
1923
    {
1924
        return $this->gradeBookResultLogs;
1925
    }
1926
1927
    /**
1928
     * @return Collection<int, GradebookScoreLog>
1929
     */
1930
    public function getGradeBookScoreLogs(): Collection
1931
    {
1932
        return $this->gradeBookScoreLogs;
1933
    }
1934
1935
    /**
1936
     * @return Collection<int, GradebookLinkevalLog>
1937
     */
1938
    public function getGradeBookLinkEvalLogs(): Collection
1939
    {
1940
        return $this->gradeBookLinkEvalLogs;
1941
    }
1942
1943
    /**
1944
     * @return Collection<int, UserRelCourseVote>
1945
     */
1946
    public function getUserRelCourseVotes(): Collection
1947
    {
1948
        return $this->userRelCourseVotes;
1949
    }
1950
1951
    /**
1952
     * @return Collection<int, UserRelTag>
1953
     */
1954
    public function getUserRelTags(): Collection
1955
    {
1956
        return $this->userRelTags;
1957
    }
1958
1959
    public function getCurriculumItems(): Collection
1960
    {
1961
        return $this->curriculumItems;
1962
    }
1963
1964
    /**
1965
     * @return Collection<int, UserRelUser>
1966
     */
1967
    public function getFriends(): Collection
1968
    {
1969
        return $this->friends;
1970
    }
1971
1972
    /**
1973
     * @return Collection<int, UserRelUser>
1974
     */
1975
    public function getFriendsWithMe(): Collection
1976
    {
1977
        return $this->friendsWithMe;
1978
    }
1979
1980
    public function addFriend(self $friend): self
1981
    {
1982
        return $this->addUserRelUser($friend, UserRelUser::USER_RELATION_TYPE_FRIEND);
1983
    }
1984
1985
    public function addUserRelUser(self $friend, int $relationType): self
1986
    {
1987
        $userRelUser = (new UserRelUser())->setUser($this)->setFriend($friend)->setRelationType($relationType);
1988
        $this->friends->add($userRelUser);
1989
1990
        return $this;
1991
    }
1992
1993
    /**
1994
     * @return Collection<int, Templates>
1995
     */
1996
    public function getTemplates(): Collection
1997
    {
1998
        return $this->templates;
1999
    }
2000
2001
    public function getDropBoxReceivedFiles(): Collection
2002
    {
2003
        return $this->dropBoxReceivedFiles;
2004
    }
2005
2006
    /**
2007
     * @return Collection<int, SequenceValue>
2008
     */
2009
    public function getSequenceValues(): Collection
2010
    {
2011
        return $this->sequenceValues;
2012
    }
2013
2014
    /**
2015
     * @return Collection<int, TrackEExerciseConfirmation>
2016
     */
2017
    public function getTrackEExerciseConfirmations(): Collection
2018
    {
2019
        return $this->trackEExerciseConfirmations;
2020
    }
2021
2022
    /**
2023
     * @return Collection<int, TrackEAttempt>
2024
     */
2025
    public function getTrackEAccessCompleteList(): Collection
2026
    {
2027
        return $this->trackEAccessCompleteList;
2028
    }
2029
2030
    /**
2031
     * @return Collection<int, TrackEAttempt>
2032
     */
2033
    public function getTrackEAttempts(): Collection
2034
    {
2035
        return $this->trackEAttempts;
2036
    }
2037
2038
    /**
2039
     * @return Collection<int, TrackECourseAccess>
2040
     */
2041
    public function getTrackECourseAccess(): Collection
2042
    {
2043
        return $this->trackECourseAccess;
2044
    }
2045
2046
    /**
2047
     * @return Collection<int, UserCourseCategory>
2048
     */
2049
    public function getUserCourseCategories(): Collection
2050
    {
2051
        return $this->userCourseCategories;
2052
    }
2053
2054
    public function getCourseGroupsAsTutorFromCourse(Course $course): Collection
2055
    {
2056
        $criteria = Criteria::create();
2057
        $criteria->where(Criteria::expr()->eq('cId', $course->getId()));
2058
2059
        return $this->courseGroupsAsTutor->matching($criteria);
2060
    }
2061
2062
    /**
2063
     * Retrieves this user's related student sessions.
2064
     *
2065
     * @return Session[]
2066
     */
2067
    public function getSessionsAsStudent(): array
2068
    {
2069
        return $this->getSessions(Session::STUDENT);
2070
    }
2071
2072
    public function addSessionRelUser(SessionRelUser $sessionSubscription): static
2073
    {
2074
        $this->sessionsRelUser->add($sessionSubscription);
2075
2076
        return $this;
2077
    }
2078
2079
    public function isSkipResourceNode(): bool
2080
    {
2081
        return $this->skipResourceNode;
2082
    }
2083
2084
    public function setSkipResourceNode(bool $skipResourceNode): self
2085
    {
2086
        $this->skipResourceNode = $skipResourceNode;
2087
2088
        return $this;
2089
    }
2090
2091
    /**
2092
     * Retrieves this user's related DRH sessions.
2093
     *
2094
     * @return Session[]
2095
     */
2096
    public function getDRHSessions(): array
2097
    {
2098
        return $this->getSessions(Session::DRH);
2099
    }
2100
2101
    /**
2102
     * Get this user's related accessible sessions of a type, student by default.
2103
     *
2104
     * @return Session[]
2105
     */
2106
    public function getCurrentlyAccessibleSessions(int $relationType = Session::STUDENT): array
2107
    {
2108
        $sessions = [];
2109
        foreach ($this->getSessions($relationType) as $session) {
2110
            if ($session->isCurrentlyAccessible()) {
2111
                $sessions[] = $session;
2112
            }
2113
        }
2114
2115
        return $sessions;
2116
    }
2117
2118
    public function getResourceIdentifier(): int
2119
    {
2120
        return $this->id;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->id could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
2121
    }
2122
2123
    public function getResourceName(): string
2124
    {
2125
        return $this->getUsername();
2126
    }
2127
2128
    public function setResourceName(string $name): void
2129
    {
2130
        $this->setUsername($name);
2131
    }
2132
2133
    public function setParent(AbstractResource $parent): void {}
2134
2135
    public function getDefaultIllustration(int $size): string
2136
    {
2137
        $size = empty($size) ? 32 : $size;
2138
2139
        return \sprintf('/img/icons/%s/unknown.png', $size);
2140
    }
2141
2142
    public function getAdmin(): ?Admin
2143
    {
2144
        return $this->admin;
2145
    }
2146
2147
    public function setAdmin(?Admin $admin): self
2148
    {
2149
        $this->admin = $admin;
2150
2151
        return $this;
2152
    }
2153
2154
    public function addUserAsAdmin(): self
2155
    {
2156
        if (null === $this->admin) {
2157
            $admin = new Admin();
2158
            $admin->setUser($this);
2159
            $this->setAdmin($admin);
2160
            $this->addRole('ROLE_ADMIN');
2161
        }
2162
2163
        return $this;
2164
    }
2165
2166
    public function removeUserAsAdmin(): self
2167
    {
2168
        $this->admin->setUser(null);
0 ignored issues
show
Bug introduced by
The method setUser() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

2168
        $this->admin->/** @scrutinizer ignore-call */ 
2169
                      setUser(null);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
2169
        $this->admin = null;
2170
        $this->removeRole('ROLE_ADMIN');
2171
2172
        return $this;
2173
    }
2174
2175
    public function getSessionsByStatusInCourseSubscription(int $status): ReadableCollection
2176
    {
2177
        $criteria = Criteria::create()->where(Criteria::expr()->eq('status', $status));
2178
2179
        /** @var ArrayCollection $subscriptions */
2180
        $subscriptions = $this->getSessionRelCourseRelUsers();
2181
2182
        return $subscriptions->matching($criteria)->map(
2183
            fn (SessionRelCourseRelUser $sessionRelCourseRelUser) => $sessionRelCourseRelUser->getSession()
2184
        );
2185
    }
2186
2187
    /**
2188
     * @return Collection<int, SessionRelCourseRelUser>
2189
     */
2190
    public function getSessionRelCourseRelUsers(): Collection
2191
    {
2192
        return $this->sessionRelCourseRelUsers;
2193
    }
2194
2195
    /**
2196
     * @param Collection<int, SessionRelCourseRelUser> $sessionRelCourseRelUsers
2197
     */
2198
    public function setSessionRelCourseRelUsers(Collection $sessionRelCourseRelUsers): self
2199
    {
2200
        $this->sessionRelCourseRelUsers = $sessionRelCourseRelUsers;
2201
2202
        return $this;
2203
    }
2204
2205
    public function getGender(): ?string
2206
    {
2207
        return $this->gender;
2208
    }
2209
2210
    public function setGender(?string $gender): self
2211
    {
2212
        $this->gender = $gender;
2213
2214
        return $this;
2215
    }
2216
2217
    /**
2218
     * @return Collection<int, CSurveyInvitation>
2219
     */
2220
    public function getSurveyInvitations(): Collection
2221
    {
2222
        return $this->surveyInvitations;
2223
    }
2224
2225
    public function setSurveyInvitations(Collection $surveyInvitations): self
2226
    {
2227
        $this->surveyInvitations = $surveyInvitations;
2228
2229
        return $this;
2230
    }
2231
2232
    public function getLogin(): string
2233
    {
2234
        return $this->username;
2235
    }
2236
2237
    public function setLogin(string $login): self
2238
    {
2239
        $this->username = $login;
2240
2241
        return $this;
2242
    }
2243
2244
    /**
2245
     * @return Collection<int, TrackELogin>
2246
     */
2247
    public function getLogins(): Collection
2248
    {
2249
        return $this->logins;
2250
    }
2251
2252
    public function setLogins(Collection $logins): self
2253
    {
2254
        $this->logins = $logins;
2255
2256
        return $this;
2257
    }
2258
2259
    /**
2260
     * @return Collection<int, MessageTag>
2261
     */
2262
    public function getMessageTags(): Collection
2263
    {
2264
        return $this->messageTags;
2265
    }
2266
2267
    /**
2268
     * @param Collection<int, MessageTag> $messageTags
2269
     */
2270
    public function setMessageTags(Collection $messageTags): self
2271
    {
2272
        $this->messageTags = $messageTags;
2273
2274
        return $this;
2275
    }
2276
2277
    /**
2278
     * @param null|UserCourseCategory $userCourseCategory the user_course_category
2279
     *
2280
     * @todo move in a repo
2281
     * Find the largest sort value in a given UserCourseCategory
2282
     * This method is used when we are moving a course to a different category
2283
     * and also when a user subscribes to courses (the new course is added at the end of the main category).
2284
     *
2285
     * Used to be implemented in global function \api_max_sort_value.
2286
     * Reimplemented using the ORM cache.
2287
     */
2288
    public function getMaxSortValue(?UserCourseCategory $userCourseCategory = null): int
2289
    {
2290
        $categoryCourses = $this->courses->matching(
2291
            Criteria::create()->where(Criteria::expr()->neq('relationType', COURSE_RELATION_TYPE_RRHH))->andWhere(
2292
                Criteria::expr()->eq('userCourseCat', $userCourseCategory)
2293
            )
2294
        );
2295
2296
        return $categoryCourses->isEmpty() ? 0 : max(
2297
            $categoryCourses->map(fn ($courseRelUser) => $courseRelUser->getSort())->toArray()
2298
        );
2299
    }
2300
2301
    public function hasFriendWithRelationType(self $friend, int $relationType): bool
2302
    {
2303
        $friends = $this->getFriendsByRelationType($relationType);
2304
2305
        return $friends->exists(fn (int $index, UserRelUser $userRelUser) => $userRelUser->getFriend() === $friend);
2306
    }
2307
2308
    public function isFriendWithMeByRelationType(self $friend, int $relationType): bool
2309
    {
2310
        return $this
2311
            ->getFriendsWithMeByRelationType($relationType)
2312
            ->exists(fn (int $index, UserRelUser $userRelUser) => $userRelUser->getUser() === $friend)
2313
        ;
2314
    }
2315
2316
    /**
2317
     * @param int $relationType Example: UserRelUser::USER_RELATION_TYPE_BOSS
2318
     *
2319
     * @return Collection<int, UserRelUser>
2320
     */
2321
    public function getFriendsByRelationType(int $relationType): Collection
2322
    {
2323
        $criteria = Criteria::create();
2324
        $criteria->where(Criteria::expr()->eq('relationType', $relationType));
2325
2326
        return $this->friends->matching($criteria);
2327
    }
2328
2329
    public function getFriendsWithMeByRelationType(int $relationType): Collection
2330
    {
2331
        $criteria = Criteria::create();
2332
        $criteria->where(Criteria::expr()->eq('relationType', $relationType));
2333
2334
        return $this->friendsWithMe->matching($criteria);
2335
    }
2336
2337
    public function getFriendsOfFriends(): array
2338
    {
2339
        $friendsOfFriends = [];
2340
        foreach ($this->getFriends() as $friendRelation) {
2341
            foreach ($friendRelation->getFriend()->getFriends() as $friendOfFriendRelation) {
2342
                $friendsOfFriends[] = $friendOfFriendRelation->getFriend();
2343
            }
2344
        }
2345
2346
        return $friendsOfFriends;
2347
    }
2348
2349
    /**
2350
     * @return Collection<int, SocialPost>
2351
     */
2352
    public function getSentSocialPosts(): Collection
2353
    {
2354
        return $this->sentSocialPosts;
2355
    }
2356
2357
    public function addSentSocialPost(SocialPost $sentSocialPost): self
2358
    {
2359
        if (!$this->sentSocialPosts->contains($sentSocialPost)) {
2360
            $this->sentSocialPosts[] = $sentSocialPost;
2361
            $sentSocialPost->setSender($this);
2362
        }
2363
2364
        return $this;
2365
    }
2366
2367
    /**
2368
     * @return Collection<int, SocialPost>
2369
     */
2370
    public function getReceivedSocialPosts(): Collection
2371
    {
2372
        return $this->receivedSocialPosts;
2373
    }
2374
2375
    public function addReceivedSocialPost(SocialPost $receivedSocialPost): self
2376
    {
2377
        if (!$this->receivedSocialPosts->contains($receivedSocialPost)) {
2378
            $this->receivedSocialPosts[] = $receivedSocialPost;
2379
            $receivedSocialPost->setUserReceiver($this);
2380
        }
2381
2382
        return $this;
2383
    }
2384
2385
    public function getSocialPostFeedbackBySocialPost(SocialPost $post): ?SocialPostFeedback
2386
    {
2387
        $filtered = $this->getSocialPostsFeedbacks()->filter(
2388
            fn (SocialPostFeedback $postFeedback) => $postFeedback->getSocialPost() === $post
2389
        );
2390
        if ($filtered->count() > 0) {
2391
            return $filtered->first();
2392
        }
2393
2394
        return null;
2395
    }
2396
2397
    /**
2398
     * @return Collection<int, SocialPostFeedback>
2399
     */
2400
    public function getSocialPostsFeedbacks(): Collection
2401
    {
2402
        return $this->socialPostsFeedbacks;
2403
    }
2404
2405
    public function addSocialPostFeedback(SocialPostFeedback $socialPostFeedback): self
2406
    {
2407
        if (!$this->socialPostsFeedbacks->contains($socialPostFeedback)) {
2408
            $this->socialPostsFeedbacks[] = $socialPostFeedback;
2409
            $socialPostFeedback->setUser($this);
2410
        }
2411
2412
        return $this;
2413
    }
2414
2415
    public function getSubscriptionToSession(Session $session): ?SessionRelUser
2416
    {
2417
        $criteria = Criteria::create();
2418
        $criteria->where(
2419
            Criteria::expr()->eq('session', $session)
2420
        );
2421
2422
        $match = $this->sessionsRelUser->matching($criteria);
2423
2424
        if ($match->count() > 0) {
2425
            return $match->first();
2426
        }
2427
2428
        return null;
2429
    }
2430
2431
    public function getFirstAccessToSession(Session $session): ?TrackECourseAccess
2432
    {
2433
        $criteria = Criteria::create()
2434
            ->where(
2435
                Criteria::expr()->eq('sessionId', $session->getId())
2436
            )
2437
        ;
2438
2439
        $match = $this->trackECourseAccess->matching($criteria);
2440
2441
        return $match->count() > 0 ? $match->first() : null;
2442
    }
2443
2444
    public function isCourseTutor(?Course $course = null, ?Session $session = null): bool
2445
    {
2446
        return $session?->hasCoachInCourseList($this) || $course?->getSubscriptionByUser($this)?->isTutor();
2447
    }
2448
2449
    /**
2450
     * @return Collection<int, UserAuthSource>
2451
     */
2452
    public function getAuthSources(): Collection
2453
    {
2454
        return $this->authSources;
2455
    }
2456
2457
    public function getAuthSourcesByUrl(AccessUrl $url): Collection
2458
    {
2459
        $criteria = Criteria::create();
2460
        $criteria->where(
2461
            Criteria::expr()->eq('url', $url)
2462
        );
2463
2464
        return $this->authSources->matching($criteria);
2465
    }
2466
2467
    /**
2468
     * @return array<int, string>
2469
     */
2470
    public function getAuthSourcesAuthentications(?AccessUrl $url = null): array
2471
    {
2472
        $authSources = $url ? $this->getAuthSourcesByUrl($url) : $this->getAuthSources();
2473
2474
        return $authSources->map(fn (UserAuthSource $authSource) => $authSource->getAuthentication())->toArray();
2475
    }
2476
2477
    public function addAuthSource(UserAuthSource $authSource): static
2478
    {
2479
        if (!$this->authSources->contains($authSource)) {
2480
            $this->authSources->add($authSource);
2481
            $authSource->setUser($this);
2482
        }
2483
2484
        return $this;
2485
    }
2486
2487
    public function addAuthSourceByAuthentication(string $authentication, AccessUrl $url): static
2488
    {
2489
        $authSource = (new UserAuthSource())
2490
            ->setAuthentication($authentication)
2491
            ->setUrl($url)
2492
        ;
2493
2494
        $this->addAuthSource($authSource);
2495
2496
        return $this;
2497
    }
2498
2499
    public function hasAuthSourceByAuthentication(string $authentication): bool
2500
    {
2501
        return $this->authSources->exists(
2502
            fn ($key, $authSource) => $authSource instanceof UserAuthSource
2503
                && $authSource->getAuthentication() === $authentication
2504
        );
2505
    }
2506
2507
    public function getAuthSourceByAuthentication(string $authentication): UserAuthSource
2508
    {
2509
        return $this->authSources->findFirst(
2510
            fn (UserAuthSource $authSource) => $authSource->getAuthentication() === $authentication
2511
        );
2512
    }
2513
2514
    public function removeAuthSources(): static
2515
    {
2516
        foreach ($this->authSources as $authSource) {
2517
            $authSource->setUser(null);
2518
        }
2519
2520
        $this->authSources = new ArrayCollection();
2521
2522
        return $this;
2523
    }
2524
2525
    public function removeAuthSource(UserAuthSource $authSource): static
2526
    {
2527
        if ($this->authSources->removeElement($authSource)) {
2528
            // set the owning side to null (unless already changed)
2529
            if ($authSource->getUser() === $this) {
2530
                $authSource->setUser(null);
2531
            }
2532
        }
2533
2534
        return $this;
2535
    }
2536
2537
    public function getMfaEnabled(): bool
2538
    {
2539
        return $this->mfaEnabled;
2540
    }
2541
2542
    public function setMfaEnabled(bool $mfaEnabled): self
2543
    {
2544
        $this->mfaEnabled = $mfaEnabled;
2545
2546
        return $this;
2547
    }
2548
2549
    public function getMfaService(): ?string
2550
    {
2551
        return $this->mfaService;
2552
    }
2553
2554
    public function setMfaService(?string $mfaService): self
2555
    {
2556
        $this->mfaService = $mfaService;
2557
2558
        return $this;
2559
    }
2560
2561
    public function getMfaSecret(): ?string
2562
    {
2563
        return $this->mfaSecret;
2564
    }
2565
2566
    public function setMfaSecret(?string $mfaSecret): self
2567
    {
2568
        $this->mfaSecret = $mfaSecret;
2569
2570
        return $this;
2571
    }
2572
2573
    public function getMfaBackupCodes(): ?string
2574
    {
2575
        return $this->mfaBackupCodes;
2576
    }
2577
2578
    public function setMfaBackupCodes(?string $mfaBackupCodes): self
2579
    {
2580
        $this->mfaBackupCodes = $mfaBackupCodes;
2581
2582
        return $this;
2583
    }
2584
2585
    public function getMfaLastUsed(): ?DateTimeInterface
2586
    {
2587
        return $this->mfaLastUsed;
2588
    }
2589
2590
    public function setMfaLastUsed(?DateTimeInterface $mfaLastUsed): self
2591
    {
2592
        $this->mfaLastUsed = $mfaLastUsed;
2593
2594
        return $this;
2595
    }
2596
2597
    /**
2598
     * @return \DateTimeInterface|null
2599
     */
2600
    public function getPasswordUpdatedAt(): ?\DateTimeInterface
2601
    {
2602
        return $this->passwordUpdatedAt;
2603
    }
2604
2605
    /**
2606
     * @param \DateTimeInterface|null $date
2607
     *
2608
     * @return $this
2609
     */
2610
    public function setPasswordUpdatedAt(?\DateTimeInterface $date): self
2611
    {
2612
        $this->passwordUpdatedAt = $date;
2613
        return $this;
2614
    }
2615
}
2616