Passed
Push — master ( 2a0c4b...cf1b71 )
by Angel Fernando Quiroz
07:25 queued 23s
created

Session::getResourceLinks()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
declare(strict_types=1);
6
7
namespace Chamilo\CoreBundle\Entity;
8
9
use ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
10
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
11
use ApiPlatform\Metadata\ApiFilter;
12
use ApiPlatform\Metadata\ApiResource;
13
use ApiPlatform\Metadata\Delete;
14
use ApiPlatform\Metadata\Get;
15
use ApiPlatform\Metadata\GetCollection;
16
use ApiPlatform\Metadata\Post;
17
use ApiPlatform\Metadata\Put;
18
use ApiPlatform\Serializer\Filter\PropertyFilter;
19
use Chamilo\CoreBundle\Entity\Listener\SessionListener;
20
use Chamilo\CoreBundle\Repository\SessionRepository;
21
use DateTime;
22
use Doctrine\Common\Collections\ArrayCollection;
23
use Doctrine\Common\Collections\Collection;
24
use Doctrine\Common\Collections\Criteria;
25
use Doctrine\Common\Collections\ReadableCollection;
26
use Doctrine\ORM\Mapping as ORM;
27
use Stringable;
28
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
29
use Symfony\Component\Serializer\Annotation\Groups;
30
use Symfony\Component\Validator\Constraints as Assert;
31
32
#[ApiResource(
33
    operations: [
34
        new Get(
35
            normalizationContext: [
36
                'groups' => ['session:read', 'session:item:read'],
37
            ],
38
            security: "is_granted('ROLE_ADMIN') or is_granted('VIEW', object)"
39
        ),
40
        new Put(security: "is_granted('ROLE_ADMIN')"),
41
        new GetCollection(security: "is_granted('ROLE_ADMIN')"),
42
        new Post(security: "is_granted('ROLE_ADMIN')"),
43
        new Delete(security: "is_granted('DELETE', object)"),
44
    ],
45
    normalizationContext: ['groups' => ['session:read']],
46
    denormalizationContext: ['groups' => ['session:write']],
47
    security: "is_granted('ROLE_ADMIN')"
48
)]
49
#[ORM\Table(name: 'session')]
50
#[ORM\UniqueConstraint(name: 'title', columns: ['title'])]
51
#[ORM\EntityListeners([SessionListener::class])]
52
#[ORM\Entity(repositoryClass: SessionRepository::class)]
53
#[UniqueEntity('title')]
54
#[ApiFilter(filterClass: SearchFilter::class, properties: ['title' => 'partial'])]
55
#[ApiFilter(filterClass: PropertyFilter::class)]
56
#[ApiFilter(filterClass: OrderFilter::class, properties: ['id', 'title'])]
57
class Session implements ResourceWithAccessUrlInterface, Stringable
58
{
59
    public const VISIBLE = 1;
60
    public const READ_ONLY = 2;
61
    public const INVISIBLE = 3;
62
    public const AVAILABLE = 4;
63
    public const STUDENT = 0;
64
    public const DRH = 1;
65
    public const COURSE_COACH = 2;
66
    public const GENERAL_COACH = 3;
67
    public const SESSION_ADMIN = 4;
68
69
    #[Groups([
70
        'session:read',
71
        'session_rel_user:read',
72
        'session_rel_course_rel_user:read',
73
        'course:read',
74
        'track_e_exercise:read',
75
    ])]
76
    #[ORM\Column(name: 'id', type: 'integer')]
77
    #[ORM\Id]
78
    #[ORM\GeneratedValue]
79
    protected ?int $id = null;
80
81
    /**
82
     * @var Collection<int, SessionRelCourse>
83
     */
84
    #[Groups([
85
        'session:read',
86
        'session_rel_user:read',
87
        'session_rel_course_rel_user:read',
88
    ])]
89
    #[ORM\OrderBy(['position' => 'ASC'])]
90
    #[ORM\OneToMany(
91
        mappedBy: 'session',
92
        targetEntity: SessionRelCourse::class,
93
        cascade: ['persist'],
94
        orphanRemoval: true
95
    )]
96
    protected Collection $courses;
97
98
    /**
99
     * @var Collection<int, SessionRelUser>
100
     */
101
    #[Groups([
102
        'session:read',
103
    ])]
104
    #[ORM\OneToMany(
105
        mappedBy: 'session',
106
        targetEntity: SessionRelUser::class,
107
        cascade: ['persist', 'remove'],
108
        orphanRemoval: true
109
    )]
110
    protected Collection $users;
111
112
    /**
113
     * @var Collection<int, SessionRelCourseRelUser>
114
     */
115
    #[Groups([
116
        'session:read',
117
        'session_rel_course_rel_user:read',
118
    ])]
119
    #[ORM\OneToMany(
120
        mappedBy: 'session',
121
        targetEntity: SessionRelCourseRelUser::class,
122
        cascade: ['persist'],
123
        orphanRemoval: true
124
    )]
125
    protected Collection $sessionRelCourseRelUsers;
126
127
    /**
128
     * @var Collection<int, SkillRelCourse>
129
     */
130
    #[ORM\OneToMany(
131
        mappedBy: 'session',
132
        targetEntity: SkillRelCourse::class,
133
        cascade: ['persist', 'remove']
134
    )]
135
    protected Collection $skills;
136
137
    /**
138
     * @var Collection<int, SkillRelUser>
139
     */
140
    #[ORM\OneToMany(mappedBy: 'session', targetEntity: SkillRelUser::class, cascade: ['persist'])]
141
    protected Collection $issuedSkills;
142
143
    /**
144
     * @var Collection<int, EntityAccessUrlInterface>
145
     */
146
    #[ORM\OneToMany(
147
        mappedBy: 'session',
148
        targetEntity: AccessUrlRelSession::class,
149
        cascade: ['persist'],
150
        orphanRemoval: true
151
    )]
152
    protected Collection $urls;
153
154
    /**
155
     * @var Collection<int, ResourceLink>
156
     */
157
    #[ORM\OneToMany(mappedBy: 'session', targetEntity: ResourceLink::class, cascade: ['remove'], orphanRemoval: true)]
158
    protected Collection $resourceLinks;
159
160
    protected AccessUrl $currentUrl;
161
162
    protected ?Course $currentCourse = null;
163
164
    #[Assert\NotBlank]
165
    #[Groups([
166
        'session:read',
167
        'session:write',
168
        'session_rel_course_rel_user:read',
169
        'document:read',
170
        'session_rel_user:read',
171
        'course:read',
172
        'track_e_exercise:read',
173
        'calendar_event:read',
174
    ])]
175
    #[ORM\Column(name: 'title', type: 'string', length: 150)]
176
    protected string $title;
177
178
    #[Groups([
179
        'session:read',
180
        'session:write',
181
    ])]
182
    #[ORM\Column(name: 'description', type: 'text', unique: false, nullable: true)]
183
    protected ?string $description;
184
185
    #[Groups([
186
        'session:read',
187
        'session:write',
188
    ])]
189
    #[ORM\Column(name: 'show_description', type: 'boolean', nullable: true)]
190
    protected ?bool $showDescription;
191
192
    #[Groups(['session:read', 'session:write'])]
193
    #[ORM\Column(name: 'duration', type: 'integer', nullable: true)]
194
    protected ?int $duration = null;
195
196
    #[Groups(['session:read'])]
197
    #[ORM\Column(name: 'nbr_courses', type: 'integer', unique: false, nullable: false)]
198
    protected int $nbrCourses;
199
200
    #[Groups(['session:read'])]
201
    #[ORM\Column(name: 'nbr_users', type: 'integer', unique: false, nullable: false)]
202
    protected int $nbrUsers;
203
204
    #[Groups(['session:read'])]
205
    #[ORM\Column(name: 'nbr_classes', type: 'integer', unique: false, nullable: false)]
206
    protected int $nbrClasses;
207
208
    #[Groups([
209
        'session:read',
210
        'session:write',
211
    ])]
212
    #[ORM\Column(name: 'visibility', type: 'integer')]
213
    protected int $visibility;
214
215
    #[ORM\ManyToOne(targetEntity: Promotion::class, cascade: ['persist'], inversedBy: 'sessions')]
216
    #[ORM\JoinColumn(name: 'promotion_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
217
    protected ?Promotion $promotion = null;
218
219
    #[Groups([
220
        'session:read',
221
        'session:write',
222
        'session_rel_user:read',
223
        'session_rel_course_rel_user:read',
224
    ])]
225
    #[ORM\Column(name: 'display_start_date', type: 'datetime', unique: false, nullable: true)]
226
    protected ?DateTime $displayStartDate;
227
228
    #[Groups([
229
        'session:read',
230
        'session:write',
231
        'session_rel_user:read',
232
        'session_rel_course_rel_user:read',
233
    ])]
234
    #[ORM\Column(name: 'display_end_date', type: 'datetime', unique: false, nullable: true)]
235
    protected ?DateTime $displayEndDate;
236
237
    #[Groups([
238
        'session:read',
239
        'session:write',
240
        'session_rel_user:read',
241
        'session_rel_course_rel_user:read',
242
    ])]
243
    #[ORM\Column(name: 'access_start_date', type: 'datetime', unique: false, nullable: true)]
244
    protected ?DateTime $accessStartDate;
245
246
    #[Groups([
247
        'session:read',
248
        'session:write',
249
        'session_rel_user:read',
250
        'session_rel_course_rel_user:read',
251
    ])]
252
    #[ORM\Column(name: 'access_end_date', type: 'datetime', unique: false, nullable: true)]
253
    protected ?DateTime $accessEndDate;
254
255
    #[Groups([
256
        'session:read',
257
        'session:write',
258
        'session_rel_user:read',
259
        'session_rel_course_rel_user:read',
260
    ])]
261
    #[ORM\Column(name: 'coach_access_start_date', type: 'datetime', unique: false, nullable: true)]
262
    protected ?DateTime $coachAccessStartDate;
263
264
    #[Groups([
265
        'session:read',
266
        'session:write',
267
        'session_rel_user:read',
268
        'session_rel_course_rel_user:read',
269
    ])]
270
    #[ORM\Column(name: 'coach_access_end_date', type: 'datetime', unique: false, nullable: true)]
271
    protected ?DateTime $coachAccessEndDate;
272
273
    #[ORM\Column(name: 'position', type: 'integer', nullable: false, options: ['default' => 0])]
274
    protected int $position;
275
276
    #[Groups(['session:read'])]
277
    #[ORM\Column(name: 'status', type: 'integer', nullable: false)]
278
    protected int $status;
279
280
    #[Groups(['session:read', 'session:write', 'session_rel_user:read'])]
281
    #[ORM\ManyToOne(targetEntity: SessionCategory::class, inversedBy: 'sessions')]
282
    #[ORM\JoinColumn(name: 'session_category_id', referencedColumnName: 'id')]
283
    protected ?SessionCategory $category = null;
284
285
    #[ORM\Column(
286
        name: 'send_subscription_notification',
287
        type: 'boolean',
288
        nullable: false,
289
        options: ['default' => false]
290
    )]
291
    protected bool $sendSubscriptionNotification;
292
293
    /**
294
     * Image illustrating the session (was extra field 'image' in 1.11).
295
     */
296
    #[ORM\ManyToOne(targetEntity: Asset::class, cascade: ['remove'])]
297
    #[ORM\JoinColumn(name: 'image_id', referencedColumnName: 'id', onDelete: 'SET NULL')]
298
    protected ?Asset $image = null;
299
300
    public function __construct()
301
    {
302
        $this->skills = new ArrayCollection();
303
        $this->issuedSkills = new ArrayCollection();
304
        $this->resourceLinks = new ArrayCollection();
305
        $this->courses = new ArrayCollection();
306
        $this->users = new ArrayCollection();
307
        $this->sessionRelCourseRelUsers = new ArrayCollection();
308
        $this->urls = new ArrayCollection();
309
        $this->duration = 0;
310
        $this->description = '';
311
        $this->nbrClasses = 0;
312
        $this->nbrUsers = 0;
313
        $this->nbrCourses = 0;
314
        $this->sendSubscriptionNotification = false;
315
        $now = new DateTime();
316
        $this->displayStartDate = $now;
317
        $this->displayEndDate = $now;
318
        $this->accessStartDate = $now;
319
        $this->accessEndDate = $now;
320
        $this->coachAccessStartDate = $now;
321
        $this->coachAccessEndDate = $now;
322
        $this->visibility = 1;
323
        $this->showDescription = false;
324
        $this->category = null;
325
        $this->status = 0;
326
        $this->position = 0;
327
    }
328
329
    public function __toString(): string
330
    {
331
        return $this->getTitle();
332
    }
333
334
    public static function getRelationTypeList(): array
335
    {
336
        return [self::STUDENT, self::DRH, self::COURSE_COACH, self::GENERAL_COACH, self::SESSION_ADMIN];
337
    }
338
339
    public static function getStatusList(): array
340
    {
341
        return [
342
            self::VISIBLE => 'status_visible',
343
            self::READ_ONLY => 'status_read_only',
344
            self::INVISIBLE => 'status_invisible',
345
            self::AVAILABLE => 'status_available',
346
        ];
347
    }
348
349
    public function getDuration(): ?int
350
    {
351
        return $this->duration;
352
    }
353
354
    public function setDuration(int $duration): self
355
    {
356
        $this->duration = $duration;
357
358
        return $this;
359
    }
360
361
    public function getShowDescription(): bool
362
    {
363
        return $this->showDescription;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->showDescription could return the type null which is incompatible with the type-hinted return boolean. Consider adding an additional type-check to rule them out.
Loading history...
364
    }
365
366
    public function setShowDescription(bool $showDescription): self
367
    {
368
        $this->showDescription = $showDescription;
369
370
        return $this;
371
    }
372
373
    /**
374
     * @return Collection<int, SessionRelUser>
375
     */
376
    public function getUsers(): Collection
377
    {
378
        return $this->users;
379
    }
380
381
    public function setUsers(Collection $users): self
382
    {
383
        $this->users = new ArrayCollection();
384
        foreach ($users as $user) {
385
            $this->addUserSubscription($user);
386
        }
387
388
        return $this;
389
    }
390
391
    public function addUserSubscription(SessionRelUser $subscription): void
392
    {
393
        $subscription->setSession($this);
394
        if (!$this->hasUser($subscription)) {
395
            $this->users->add($subscription);
396
            $this->nbrUsers++;
397
        }
398
    }
399
400
    public function hasUser(SessionRelUser $subscription): bool
401
    {
402
        if (0 !== $this->getUsers()->count()) {
403
            $criteria = Criteria::create()
404
                ->where(
405
                    Criteria::expr()->eq('user', $subscription->getUser())
406
                )
407
                ->andWhere(
408
                    Criteria::expr()->eq('session', $subscription->getSession())
409
                )
410
                ->andWhere(
411
                    Criteria::expr()->eq('relationType', $subscription->getRelationType())
412
                )
413
            ;
414
            $relation = $this->getUsers()->matching($criteria);
415
416
            return $relation->count() > 0;
417
        }
418
419
        return false;
420
    }
421
422
    public function hasCourse(Course $course): bool
423
    {
424
        if (0 !== $this->getCourses()->count()) {
425
            $criteria = Criteria::create()->where(Criteria::expr()->eq('course', $course));
426
            $relation = $this->getCourses()->matching($criteria);
427
428
            return $relation->count() > 0;
429
        }
430
431
        return false;
432
    }
433
434
    /**
435
     * @return Collection<int, SessionRelCourse>
436
     */
437
    public function getCourses(): Collection
438
    {
439
        return $this->courses;
440
    }
441
442
    public function setCourses(ArrayCollection $courses): void
443
    {
444
        $this->courses = new ArrayCollection();
445
        foreach ($courses as $course) {
446
            $this->addCourses($course);
447
        }
448
    }
449
450
    public function addCourses(SessionRelCourse $course): void
451
    {
452
        $course->setSession($this);
453
        $this->courses->add($course);
454
    }
455
456
    public function removeCourses(SessionRelCourse $course): void
457
    {
458
        foreach ($this->courses as $key => $value) {
459
            if ($value->getId() === $course->getId()) {
460
                unset($this->courses[$key]);
461
            }
462
        }
463
    }
464
465
    public function getId(): ?int
466
    {
467
        return $this->id;
468
    }
469
470
    /**
471
     * Remove course subscription for a user.
472
     * If user status in session is student, then decrease number of course users.
473
     */
474
    public function removeUserCourseSubscription(User $user, Course $course): void
475
    {
476
        foreach ($this->sessionRelCourseRelUsers as $i => $sessionRelUser) {
477
            if ($sessionRelUser->getCourse()->getId() === $course->getId()
478
                && $sessionRelUser->getUser()->getId() === $user->getId()
479
            ) {
480
                if (self::STUDENT === $this->sessionRelCourseRelUsers[$i]->getStatus()) {
481
                    $sessionCourse = $this->getCourseSubscription($course);
482
                    $sessionCourse->setNbrUsers($sessionCourse->getNbrUsers() - 1);
483
                }
484
485
                unset($this->sessionRelCourseRelUsers[$i]);
486
            }
487
        }
488
    }
489
490
    public function getStatus(): int
491
    {
492
        return $this->status;
493
    }
494
495
    public function setStatus(int $status): self
496
    {
497
        $this->status = $status;
498
499
        return $this;
500
    }
501
502
    public function setTitle(string $title): self
503
    {
504
        $this->title = $title;
505
506
        return $this;
507
    }
508
509
    public function getCourseSubscription(Course $course): ?SessionRelCourse
510
    {
511
        $criteria = Criteria::create()->where(Criteria::expr()->eq('course', $course));
512
513
        return $this->courses->matching($criteria)->current();
514
    }
515
516
    public function getTitle(): string
517
    {
518
        return $this->title;
519
    }
520
521
    public function getNbrUsers(): int
522
    {
523
        return $this->nbrUsers;
524
    }
525
526
    public function setNbrUsers(int $nbrUsers): self
527
    {
528
        $this->nbrUsers = $nbrUsers;
529
530
        return $this;
531
    }
532
533
    public function getAllUsersFromCourse(int $status): Collection
534
    {
535
        $criteria = Criteria::create()->where(Criteria::expr()->eq('status', $status));
536
537
        return $this->getSessionRelCourseRelUsers()->matching($criteria);
538
    }
539
540
    public function getSessionRelCourseRelUsers(): Collection
541
    {
542
        return $this->sessionRelCourseRelUsers;
543
    }
544
545
    public function setSessionRelCourseRelUsers(Collection $sessionRelCourseRelUsers): self
546
    {
547
        $this->sessionRelCourseRelUsers = new ArrayCollection();
548
        foreach ($sessionRelCourseRelUsers as $item) {
549
            $this->addSessionRelCourseRelUser($item);
550
        }
551
552
        return $this;
553
    }
554
555
    public function addSessionRelCourseRelUser(SessionRelCourseRelUser $sessionRelCourseRelUser): void
556
    {
557
        $sessionRelCourseRelUser->setSession($this);
558
        if (!$this->hasUserCourseSubscription($sessionRelCourseRelUser)) {
559
            $this->sessionRelCourseRelUsers->add($sessionRelCourseRelUser);
560
        }
561
    }
562
563
    public function hasUserCourseSubscription(SessionRelCourseRelUser $subscription): bool
564
    {
565
        if (0 !== $this->getSessionRelCourseRelUsers()->count()) {
566
            $criteria = Criteria::create()
567
                ->where(
568
                    Criteria::expr()->eq('user', $subscription->getUser())
569
                )
570
                ->andWhere(
571
                    Criteria::expr()->eq('course', $subscription->getCourse())
572
                )
573
                ->andWhere(
574
                    Criteria::expr()->eq('session', $subscription->getSession())
575
                )
576
            ;
577
            $relation = $this->getSessionRelCourseRelUsers()->matching($criteria);
578
579
            return $relation->count() > 0;
580
        }
581
582
        return false;
583
    }
584
585
    /**
586
     * @return Collection<int, SessionRelCourseRelUser>
587
     */
588
    public function getSessionRelCourseByUser(User $user, ?int $status = null): Collection
589
    {
590
        $criteria = Criteria::create()->where(Criteria::expr()->eq('user', $user));
591
        if (null !== $status) {
592
            $criteria->andWhere(Criteria::expr()->eq('status', $status));
593
        }
594
595
        return $this->sessionRelCourseRelUsers->matching($criteria);
596
    }
597
598
    public function getDescription(): ?string
599
    {
600
        return $this->description;
601
    }
602
603
    public function setDescription(string $description): self
604
    {
605
        $this->description = $description;
606
607
        return $this;
608
    }
609
610
    public function getNbrCourses(): int
611
    {
612
        return $this->nbrCourses;
613
    }
614
615
    public function setNbrCourses(int $nbrCourses): self
616
    {
617
        $this->nbrCourses = $nbrCourses;
618
619
        return $this;
620
    }
621
622
    public function getNbrClasses(): int
623
    {
624
        return $this->nbrClasses;
625
    }
626
627
    public function setNbrClasses(int $nbrClasses): self
628
    {
629
        $this->nbrClasses = $nbrClasses;
630
631
        return $this;
632
    }
633
634
    public function getVisibility(): int
635
    {
636
        return $this->visibility;
637
    }
638
639
    public function setVisibility(int $visibility): self
640
    {
641
        $this->visibility = $visibility;
642
643
        return $this;
644
    }
645
646
    public function getPromotion(): ?Promotion
647
    {
648
        return $this->promotion;
649
    }
650
651
    public function setPromotion(?Promotion $promotion): self
652
    {
653
        $this->promotion = $promotion;
654
655
        return $this;
656
    }
657
658
    public function getDisplayStartDate(): ?DateTime
659
    {
660
        return $this->displayStartDate;
661
    }
662
663
    public function setDisplayStartDate(?DateTime $displayStartDate): self
664
    {
665
        $this->displayStartDate = $displayStartDate;
666
667
        return $this;
668
    }
669
670
    public function getDisplayEndDate(): ?DateTime
671
    {
672
        return $this->displayEndDate;
673
    }
674
675
    public function setDisplayEndDate(?DateTime $displayEndDate): self
676
    {
677
        $this->displayEndDate = $displayEndDate;
678
679
        return $this;
680
    }
681
682
    public function getGeneralCoaches(): ReadableCollection
683
    {
684
        return $this->getGeneralCoachesSubscriptions()
685
            ->map(fn (SessionRelUser $subscription) => $subscription->getUser())
686
        ;
687
    }
688
689
    public function getGeneralCoachesSubscriptions(): Collection
690
    {
691
        $criteria = Criteria::create()->where(Criteria::expr()->eq('relationType', self::GENERAL_COACH));
692
693
        return $this->users->matching($criteria);
694
    }
695
696
    public function hasUserAsGeneralCoach(User $user): bool
697
    {
698
        $criteria = Criteria::create()
699
            ->where(
700
                Criteria::expr()->eq('relationType', self::GENERAL_COACH)
701
            )
702
            ->andWhere(
703
                Criteria::expr()->eq('user', $user)
704
            )
705
        ;
706
707
        return $this->users->matching($criteria)->count() > 0;
708
    }
709
710
    public function addGeneralCoach(User $coach): self
711
    {
712
        return $this->addUserInSession(self::GENERAL_COACH, $coach);
713
    }
714
715
    public function addUserInSession(int $relationType, User $user): self
716
    {
717
        $sessionRelUser = (new SessionRelUser())->setUser($user)->setRelationType($relationType);
718
        $this->addUserSubscription($sessionRelUser);
719
720
        return $this;
721
    }
722
723
    public function removeGeneralCoach(User $user): self
724
    {
725
        $this->removeUserInSession(self::GENERAL_COACH, $user);
726
727
        return $this;
728
    }
729
730
    public function removeUserInSession(int $relationType, User $user): self
731
    {
732
        $criteria = Criteria::create()
733
            ->where(
734
                Criteria::expr()->eq('relationType', $relationType)
735
            )
736
            ->andWhere(
737
                Criteria::expr()->eq('user', $user)
738
            )
739
        ;
740
        $subscriptions = $this->users->matching($criteria);
741
742
        foreach ($subscriptions as $subscription) {
743
            $this->removeUserSubscription($subscription);
744
        }
745
746
        return $this;
747
    }
748
749
    public function removeUserSubscription(SessionRelUser $subscription): self
750
    {
751
        if ($this->hasUser($subscription)) {
752
            $subscription->setSession(null);
753
            $this->users->removeElement($subscription);
754
            $this->nbrUsers--;
755
        }
756
757
        return $this;
758
    }
759
760
    public function getCategory(): ?SessionCategory
761
    {
762
        return $this->category;
763
    }
764
765
    public function setCategory(?SessionCategory $category): self
766
    {
767
        $this->category = $category;
768
769
        return $this;
770
    }
771
772
    /**
773
     * Check if session is visible.
774
     */
775
    public function isActive(): bool
776
    {
777
        $now = new DateTime('now');
778
779
        return $now > $this->getAccessStartDate();
780
    }
781
782
    public function getAccessStartDate(): ?DateTime
783
    {
784
        return $this->accessStartDate;
785
    }
786
787
    public function setAccessStartDate(?DateTime $accessStartDate): self
788
    {
789
        $this->accessStartDate = $accessStartDate;
790
791
        return $this;
792
    }
793
794
    public function isActiveForStudent(): bool
795
    {
796
        $start = $this->getAccessStartDate();
797
        $end = $this->getAccessEndDate();
798
799
        return $this->compareDates($start, $end);
800
    }
801
802
    public function getAccessEndDate(): ?DateTime
803
    {
804
        return $this->accessEndDate;
805
    }
806
807
    public function setAccessEndDate(?DateTime $accessEndDate): self
808
    {
809
        $this->accessEndDate = $accessEndDate;
810
811
        return $this;
812
    }
813
814
    public function isActiveForCoach(): bool
815
    {
816
        $start = $this->getCoachAccessStartDate();
817
        $end = $this->getCoachAccessEndDate();
818
819
        return $this->compareDates($start, $end);
820
    }
821
822
    public function getCoachAccessStartDate(): ?DateTime
823
    {
824
        return $this->coachAccessStartDate;
825
    }
826
827
    public function setCoachAccessStartDate(?DateTime $coachAccessStartDate): self
828
    {
829
        $this->coachAccessStartDate = $coachAccessStartDate;
830
831
        return $this;
832
    }
833
834
    public function getCoachAccessEndDate(): ?DateTime
835
    {
836
        return $this->coachAccessEndDate;
837
    }
838
839
    public function setCoachAccessEndDate(?DateTime $coachAccessEndDate): self
840
    {
841
        $this->coachAccessEndDate = $coachAccessEndDate;
842
843
        return $this;
844
    }
845
846
    /**
847
     * Compare the current date with start and end access dates.
848
     * Either missing date is interpreted as no limit.
849
     *
850
     * @return bool whether now is between the session access start and end dates
851
     */
852
    public function isCurrentlyAccessible(): bool
853
    {
854
        $now = new DateTime();
855
856
        return (null === $this->accessStartDate || $this->accessStartDate < $now)
857
            && (null === $this->accessEndDate || $now < $this->accessEndDate);
858
    }
859
860
    public function addCourse(Course $course): self
861
    {
862
        $sessionRelCourse = (new SessionRelCourse())->setCourse($course);
863
        $this->addCourses($sessionRelCourse);
864
865
        return $this;
866
    }
867
868
    /**
869
     * Removes a course from this session.
870
     *
871
     * @param Course $course the course to remove from this session
872
     *
873
     * @return bool whether the course was actually found in this session and removed from it
874
     */
875
    public function removeCourse(Course $course): bool
876
    {
877
        $relCourse = $this->getCourseSubscription($course);
878
        if (null !== $relCourse) {
879
            $this->courses->removeElement($relCourse);
880
            $this->setNbrCourses(\count($this->courses));
881
882
            return true;
883
        }
884
885
        return false;
886
    }
887
888
    /**
889
     * Add a user course subscription.
890
     * If user status in session is student, then increase number of course users.
891
     * Status example: Session::STUDENT.
892
     */
893
    public function addUserInCourse(int $status, User $user, Course $course): SessionRelCourseRelUser
894
    {
895
        $userRelCourseRelSession = (new SessionRelCourseRelUser())
896
            ->setCourse($course)
897
            ->setUser($user)
898
            ->setSession($this)
899
            ->setStatus($status)
900
        ;
901
902
        $this->addSessionRelCourseRelUser($userRelCourseRelSession);
903
904
        if (self::STUDENT === $status) {
905
            $sessionCourse = $this->getCourseSubscription($course);
906
            $sessionCourse->setNbrUsers($sessionCourse->getNbrUsers() + 1);
907
        }
908
909
        return $userRelCourseRelSession;
910
    }
911
912
    /**
913
     * currentCourse is set in CidReqListener.
914
     */
915
    public function getCurrentCourse(): ?Course
916
    {
917
        return $this->currentCourse;
918
    }
919
920
    /**
921
     * currentCourse is set in CidReqListener.
922
     */
923
    public function setCurrentCourse(Course $course): self
924
    {
925
        // If the session is registered in the course session list.
926
        $exists = $this->getCourses()
927
            ->exists(
928
                fn ($key, $element) => $course->getId() === $element->getCourse()->getId()
929
            )
930
        ;
931
932
        if ($exists) {
933
            $this->currentCourse = $course;
934
        }
935
936
        return $this;
937
    }
938
939
    public function getSendSubscriptionNotification(): bool
940
    {
941
        return $this->sendSubscriptionNotification;
942
    }
943
944
    public function setSendSubscriptionNotification(bool $sendNotification): self
945
    {
946
        $this->sendSubscriptionNotification = $sendNotification;
947
948
        return $this;
949
    }
950
951
    /**
952
     * Get user from course by status.
953
     */
954
    public function getSessionRelCourseRelUsersByStatus(Course $course, int $status): Collection
955
    {
956
        $criteria = Criteria::create()
957
            ->where(
958
                Criteria::expr()->eq('course', $course)
959
            )
960
            ->andWhere(
961
                Criteria::expr()->eq('status', $status)
962
            )
963
        ;
964
965
        return $this->sessionRelCourseRelUsers->matching($criteria);
966
    }
967
968
    public function getSessionRelCourseRelUserInCourse(Course $course): Collection
969
    {
970
        $criteria = Criteria::create()
971
            ->where(
972
                Criteria::expr()->eq('course', $course)
973
            )
974
        ;
975
976
        return $this->sessionRelCourseRelUsers->matching($criteria);
977
    }
978
979
    public function getIssuedSkills(): Collection
980
    {
981
        return $this->issuedSkills;
982
    }
983
984
    public function getCurrentUrl(): AccessUrl
985
    {
986
        return $this->currentUrl;
987
    }
988
989
    public function setCurrentUrl(AccessUrl $url): self
990
    {
991
        $urlList = $this->getUrls();
992
        foreach ($urlList as $item) {
993
            if ($item->getUrl()->getId() === $url->getId()) {
994
                $this->currentUrl = $url;
995
996
                break;
997
            }
998
        }
999
1000
        return $this;
1001
    }
1002
1003
    /**
1004
     * @return Collection<int, EntityAccessUrlInterface>
1005
     */
1006
    public function getUrls(): Collection
1007
    {
1008
        return $this->urls;
1009
    }
1010
1011
    public function setUrls(Collection $urls): self
1012
    {
1013
        $this->urls = new ArrayCollection();
1014
        foreach ($urls as $url) {
1015
            $this->addUrls($url);
1016
        }
1017
1018
        return $this;
1019
    }
1020
1021
    public function addUrls(AccessUrlRelSession $url): self
1022
    {
1023
        $url->setSession($this);
1024
        $this->urls->add($url);
1025
1026
        return $this;
1027
    }
1028
1029
    public function addAccessUrl(?AccessUrl $url): self
1030
    {
1031
        $accessUrlRelSession = new AccessUrlRelSession();
1032
        $accessUrlRelSession->setUrl($url);
1033
        $accessUrlRelSession->setSession($this);
1034
        $this->addUrls($accessUrlRelSession);
1035
1036
        return $this;
1037
    }
1038
1039
    public function getPosition(): int
1040
    {
1041
        return $this->position;
1042
    }
1043
1044
    public function setPosition(int $position): self
1045
    {
1046
        $this->position = $position;
1047
1048
        return $this;
1049
    }
1050
1051
    public function getSessionAdmins(): ReadableCollection
1052
    {
1053
        return $this->getGeneralAdminsSubscriptions()
1054
            ->map(fn (SessionRelUser $subscription) => $subscription->getUser())
1055
        ;
1056
    }
1057
1058
    public function getGeneralAdminsSubscriptions(): Collection
1059
    {
1060
        $criteria = Criteria::create()->where(Criteria::expr()->eq('relationType', self::SESSION_ADMIN));
1061
1062
        return $this->users->matching($criteria);
1063
    }
1064
1065
    public function hasUserAsSessionAdmin(User $user): bool
1066
    {
1067
        $criteria = Criteria::create()
1068
            ->where(
1069
                Criteria::expr()->eq('relationType', self::SESSION_ADMIN)
1070
            )
1071
            ->andWhere(
1072
                Criteria::expr()->eq('user', $user)
1073
            )
1074
        ;
1075
1076
        return $this->users->matching($criteria)->count() > 0;
1077
    }
1078
1079
    public function addSessionAdmin(User $sessionAdmin): self
1080
    {
1081
        return $this->addUserInSession(self::SESSION_ADMIN, $sessionAdmin);
1082
    }
1083
1084
    public function getSkills(): Collection
1085
    {
1086
        return $this->skills;
1087
    }
1088
1089
    public function getResourceLinks(): Collection
1090
    {
1091
        return $this->resourceLinks;
1092
    }
1093
1094
    public function getImage(): ?Asset
1095
    {
1096
        return $this->image;
1097
    }
1098
1099
    public function setImage(?Asset $asset): self
1100
    {
1101
        $this->image = $asset;
1102
1103
        return $this;
1104
    }
1105
1106
    public function hasImage(): bool
1107
    {
1108
        return null !== $this->image;
1109
    }
1110
1111
    /**
1112
     * Check if $user is course coach in any course.
1113
     */
1114
    public function hasCoachInCourseList(User $user): bool
1115
    {
1116
        foreach ($this->courses as $sessionCourse) {
1117
            if ($this->hasCourseCoachInCourse($user, $sessionCourse->getCourse())) {
1118
                return true;
1119
            }
1120
        }
1121
1122
        return false;
1123
    }
1124
1125
    public function hasCourseCoachInCourse(User $user, ?Course $course = null): bool
1126
    {
1127
        if (null === $course) {
1128
            return false;
1129
        }
1130
1131
        return $this->hasUserInCourse($user, $course, self::COURSE_COACH);
1132
    }
1133
1134
    /**
1135
     * @param int $status if not set it will check if the user is registered
1136
     *                    with any status
1137
     */
1138
    public function hasUserInCourse(User $user, Course $course, ?int $status = null): bool
1139
    {
1140
        $relation = $this->getUserInCourse($user, $course, $status);
1141
1142
        return $relation->count() > 0;
1143
    }
1144
1145
    public function getUserInCourse(User $user, Course $course, ?int $status = null): Collection
1146
    {
1147
        $criteria = Criteria::create()
1148
            ->where(
1149
                Criteria::expr()->eq('course', $course)
1150
            )
1151
            ->andWhere(
1152
                Criteria::expr()->eq('user', $user)
1153
            )
1154
        ;
1155
1156
        if (null !== $status) {
1157
            $criteria->andWhere(Criteria::expr()->eq('status', $status));
1158
        }
1159
1160
        return $this->getSessionRelCourseRelUsers()->matching($criteria);
1161
    }
1162
1163
    /**
1164
     * Check if $user is student in any course.
1165
     */
1166
    public function hasStudentInCourseList(User $user): bool
1167
    {
1168
        foreach ($this->courses as $sessionCourse) {
1169
            if ($this->hasStudentInCourse($user, $sessionCourse->getCourse())) {
1170
                return true;
1171
            }
1172
        }
1173
1174
        return false;
1175
    }
1176
1177
    public function hasStudentInCourse(User $user, Course $course): bool
1178
    {
1179
        return $this->hasUserInCourse($user, $course, self::STUDENT);
1180
    }
1181
1182
    protected function compareDates(?DateTime $start, ?DateTime $end = null): bool
1183
    {
1184
        $now = new DateTime('now');
1185
1186
        if (!empty($start) && !empty($end) && ($now >= $start && $now <= $end)) {
1187
            return true;
1188
        }
1189
1190
        if (!empty($start) && $now >= $start) {
1191
            return true;
1192
        }
1193
1194
        return !empty($end) && $now <= $end;
1195
    }
1196
}
1197