Passed
Push — master ( e8ff21...737e91 )
by Julito
12:00
created

User::setAdmin()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

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