Passed
Push — master ( 727abb...ceefce )
by Yannick
07:55 queued 14s
created

Session::getSessionRelCourseRelUsersByStatus()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 6
nc 1
nop 2
dl 0
loc 12
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
50
#[ORM\Table(name: 'session')]
51
#[ORM\UniqueConstraint(name: 'title', columns: ['title'])]
52
#[ORM\EntityListeners([SessionListener::class])]
53
#[ORM\Entity(repositoryClass: SessionRepository::class)]
54
#[UniqueEntity('title')]
55
#[ApiFilter(filterClass: SearchFilter::class, properties: ['title' => 'partial'])]
56
#[ApiFilter(filterClass: PropertyFilter::class)]
57
#[ApiFilter(filterClass: OrderFilter::class, properties: ['id', 'title'])]
58
class Session implements ResourceWithAccessUrlInterface, \Stringable
59
{
60
    public const VISIBLE = 1;
61
    public const READ_ONLY = 2;
62
    public const INVISIBLE = 3;
63
    public const AVAILABLE = 4;
64
    public const STUDENT = 0;
65
    public const DRH = 1;
66
    public const COURSE_COACH = 2;
67
    public const GENERAL_COACH = 3;
68
    public const SESSION_ADMIN = 4;
69
70
    #[Groups([
71
        'session:read',
72
        'session_rel_user:read',
73
        'session_rel_course_rel_user:read',
74
        'course:read',
75
        'track_e_exercise:read',
76
    ])]
77
    #[ORM\Column(name: 'id', type: 'integer')]
78
    #[ORM\Id]
79
    #[ORM\GeneratedValue]
80
    protected ?int $id = null;
81
82
    /**
83
     * @var Collection<int, SessionRelCourse>
84
     */
85
    #[Groups([
86
        'session:read',
87
        'session_rel_user:read',
88
        'session_rel_course_rel_user:read',
89
    ])]
90
    #[ORM\OrderBy(['position' => 'ASC'])]
91
    #[ORM\OneToMany(
92
        mappedBy: 'session',
93
        targetEntity: SessionRelCourse::class,
94
        cascade: ['persist'],
95
        orphanRemoval: true
96
    )]
97
    protected Collection $courses;
98
99
    /**
100
     * @var Collection<int, SessionRelUser>
101
     */
102
    #[Groups([
103
        'session:read',
104
    ])]
105
    #[ORM\OneToMany(
106
        mappedBy: 'session',
107
        targetEntity: SessionRelUser::class,
108
        cascade: ['persist', 'remove'],
109
        orphanRemoval: true
110
    )]
111
    protected Collection $users;
112
113
    /**
114
     * @var Collection<int, SessionRelCourseRelUser>
115
     */
116
    #[Groups([
117
        'session:read',
118
        'session_rel_course_rel_user:read',
119
    ])]
120
    #[ORM\OneToMany(
121
        mappedBy: 'session',
122
        targetEntity: SessionRelCourseRelUser::class,
123
        cascade: ['persist'],
124
        orphanRemoval: true
125
    )]
126
    protected Collection $sessionRelCourseRelUsers;
127
128
    /**
129
     * @var Collection<int, SkillRelCourse>
130
     */
131
    #[ORM\OneToMany(
132
        mappedBy: 'session',
133
        targetEntity: SkillRelCourse::class,
134
        cascade: ['persist', 'remove']
135
    )]
136
    protected Collection $skills;
137
138
    /**
139
     * @var Collection<int, SkillRelUser>
140
     */
141
    #[ORM\OneToMany(mappedBy: 'session', targetEntity: SkillRelUser::class, cascade: ['persist'])]
142
    protected Collection $issuedSkills;
143
144
    /**
145
     * @var Collection<int, EntityAccessUrlInterface>
146
     */
147
    #[ORM\OneToMany(
148
        mappedBy: 'session',
149
        targetEntity: AccessUrlRelSession::class,
150
        cascade: ['persist'],
151
        orphanRemoval: true
152
    )]
153
    protected Collection $urls;
154
155
    /**
156
     * @var Collection<int, ResourceLink>
157
     */
158
    #[ORM\OneToMany(mappedBy: 'session', targetEntity: ResourceLink::class, cascade: ['remove'], orphanRemoval: true)]
159
    protected Collection $resourceLinks;
160
161
    protected AccessUrl $currentUrl;
162
163
    protected ?Course $currentCourse = null;
164
165
    #[Assert\NotBlank]
166
    #[Groups([
167
        'session:read',
168
        'session:write',
169
        'session_rel_course_rel_user:read',
170
        'document:read',
171
        'session_rel_user:read',
172
        'course:read',
173
        'track_e_exercise: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 getName(): string
350
    {
351
        return $this->name;
352
    }
353
354
    public function setName(string $name): self
355
    {
356
        $this->name = $name;
357
358
        return $this;
359
    }
360
361
    public function getDuration(): ?int
362
    {
363
        return $this->duration;
364
    }
365
366
    public function setDuration(int $duration): self
367
    {
368
        $this->duration = $duration;
369
370
        return $this;
371
    }
372
373
    public function getShowDescription(): bool
374
    {
375
        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...
376
    }
377
378
    public function setShowDescription(bool $showDescription): self
379
    {
380
        $this->showDescription = $showDescription;
381
382
        return $this;
383
    }
384
385
    /**
386
     * @return Collection<int, SessionRelUser>
387
     */
388
    public function getUsers(): Collection
389
    {
390
        return $this->users;
391
    }
392
393
    public function setUsers(Collection $users): self
394
    {
395
        $this->users = new ArrayCollection();
396
        foreach ($users as $user) {
397
            $this->addUserSubscription($user);
398
        }
399
400
        return $this;
401
    }
402
403
    public function addUserSubscription(SessionRelUser $subscription): void
404
    {
405
        $subscription->setSession($this);
406
        if (!$this->hasUser($subscription)) {
407
            $this->users->add($subscription);
408
            $this->nbrUsers++;
409
        }
410
    }
411
412
    public function hasUser(SessionRelUser $subscription): bool
413
    {
414
        if (0 !== $this->getUsers()->count()) {
415
            $criteria = Criteria::create()
416
                ->where(
417
                    Criteria::expr()->eq('user', $subscription->getUser())
418
                )
419
                ->andWhere(
420
                    Criteria::expr()->eq('session', $subscription->getSession())
421
                )
422
                ->andWhere(
423
                    Criteria::expr()->eq('relationType', $subscription->getRelationType())
424
                )
425
            ;
426
            $relation = $this->getUsers()->matching($criteria);
427
428
            return $relation->count() > 0;
429
        }
430
431
        return false;
432
    }
433
434
    public function hasCourse(Course $course): bool
435
    {
436
        if (0 !== $this->getCourses()->count()) {
437
            $criteria = Criteria::create()->where(Criteria::expr()->eq('course', $course));
438
            $relation = $this->getCourses()->matching($criteria);
439
440
            return $relation->count() > 0;
441
        }
442
443
        return false;
444
    }
445
446
    public function getCourses(): Collection
447
    {
448
        return $this->courses;
449
    }
450
451
    public function setCourses(ArrayCollection $courses): void
452
    {
453
        $this->courses = new ArrayCollection();
454
        foreach ($courses as $course) {
455
            $this->addCourses($course);
456
        }
457
    }
458
459
    public function addCourses(SessionRelCourse $course): void
460
    {
461
        $course->setSession($this);
462
        $this->courses->add($course);
463
    }
464
465
    public function removeCourses(SessionRelCourse $course): void
466
    {
467
        foreach ($this->courses as $key => $value) {
468
            if ($value->getId() === $course->getId()) {
469
                unset($this->courses[$key]);
470
            }
471
        }
472
    }
473
474
    public function getId(): ?int
475
    {
476
        return $this->id;
477
    }
478
479
    /**
480
     * Remove course subscription for a user.
481
     * If user status in session is student, then decrease number of course users.
482
     */
483
    public function removeUserCourseSubscription(User $user, Course $course): void
484
    {
485
        foreach ($this->sessionRelCourseRelUsers as $i => $sessionRelUser) {
486
            if ($sessionRelUser->getCourse()->getId() === $course->getId()
487
                && $sessionRelUser->getUser()->getId() === $user->getId()
488
            ) {
489
                if (self::STUDENT === $this->sessionRelCourseRelUsers[$i]->getStatus()) {
490
                    $sessionCourse = $this->getCourseSubscription($course);
491
                    $sessionCourse->setNbrUsers($sessionCourse->getNbrUsers() - 1);
492
                }
493
494
                unset($this->sessionRelCourseRelUsers[$i]);
495
            }
496
        }
497
    }
498
499
    public function getStatus(): int
500
    {
501
        return $this->status;
502
    }
503
504
    public function setStatus(int $status): self
505
    {
506
        $this->status = $status;
507
508
        return $this;
509
    }
510
511
    public function setTitle(string $title): self
512
    {
513
        $this->title = $title;
514
515
        return $this;
516
    }
517
518
    public function getCourseSubscription(Course $course): ?SessionRelCourse
519
    {
520
        $criteria = Criteria::create()->where(Criteria::expr()->eq('course', $course));
521
522
        return $this->courses->matching($criteria)->current();
523
    }
524
525
    public function getTitle(): string
526
    {
527
        return $this->title;
528
    }
529
530
    public function getNbrUsers(): int
531
    {
532
        return $this->nbrUsers;
533
    }
534
535
    public function setNbrUsers(int $nbrUsers): self
536
    {
537
        $this->nbrUsers = $nbrUsers;
538
539
        return $this;
540
    }
541
542
    public function getAllUsersFromCourse(int $status): Collection
543
    {
544
        $criteria = Criteria::create()->where(Criteria::expr()->eq('status', $status));
545
546
        return $this->getSessionRelCourseRelUsers()->matching($criteria);
547
    }
548
549
    public function getSessionRelCourseRelUsers(): Collection
550
    {
551
        return $this->sessionRelCourseRelUsers;
552
    }
553
554
    public function setSessionRelCourseRelUsers(Collection $sessionRelCourseRelUsers): self
555
    {
556
        $this->sessionRelCourseRelUsers = new ArrayCollection();
557
        foreach ($sessionRelCourseRelUsers as $item) {
558
            $this->addSessionRelCourseRelUser($item);
559
        }
560
561
        return $this;
562
    }
563
564
    public function addSessionRelCourseRelUser(SessionRelCourseRelUser $sessionRelCourseRelUser): void
565
    {
566
        $sessionRelCourseRelUser->setSession($this);
567
        if (!$this->hasUserCourseSubscription($sessionRelCourseRelUser)) {
568
            $this->sessionRelCourseRelUsers->add($sessionRelCourseRelUser);
569
        }
570
    }
571
572
    public function hasUserCourseSubscription(SessionRelCourseRelUser $subscription): bool
573
    {
574
        if (0 !== $this->getSessionRelCourseRelUsers()->count()) {
575
            $criteria = Criteria::create()
576
                ->where(
577
                    Criteria::expr()->eq('user', $subscription->getUser())
578
                )
579
                ->andWhere(
580
                    Criteria::expr()->eq('course', $subscription->getCourse())
581
                )
582
                ->andWhere(
583
                    Criteria::expr()->eq('session', $subscription->getSession())
584
                )
585
            ;
586
            $relation = $this->getSessionRelCourseRelUsers()->matching($criteria);
587
588
            return $relation->count() > 0;
589
        }
590
591
        return false;
592
    }
593
594
    public function getSessionRelCourseByUser(User $user, int $status = null): Collection
595
    {
596
        $criteria = Criteria::create()->where(Criteria::expr()->eq('user', $user));
597
        if (null !== $status) {
598
            $criteria->andWhere(Criteria::expr()->eq('status', $status));
599
        }
600
601
        return $this->sessionRelCourseRelUsers->matching($criteria);
602
    }
603
604
    public function getDescription(): ?string
605
    {
606
        return $this->description;
607
    }
608
609
    public function setDescription(string $description): self
610
    {
611
        $this->description = $description;
612
613
        return $this;
614
    }
615
616
    public function getNbrCourses(): int
617
    {
618
        return $this->nbrCourses;
619
    }
620
621
    public function setNbrCourses(int $nbrCourses): self
622
    {
623
        $this->nbrCourses = $nbrCourses;
624
625
        return $this;
626
    }
627
628
    public function getNbrClasses(): int
629
    {
630
        return $this->nbrClasses;
631
    }
632
633
    public function setNbrClasses(int $nbrClasses): self
634
    {
635
        $this->nbrClasses = $nbrClasses;
636
637
        return $this;
638
    }
639
640
    public function getVisibility(): int
641
    {
642
        return $this->visibility;
643
    }
644
645
    public function setVisibility(int $visibility): self
646
    {
647
        $this->visibility = $visibility;
648
649
        return $this;
650
    }
651
652
    public function getPromotion(): ?Promotion
653
    {
654
        return $this->promotion;
655
    }
656
657
    public function setPromotion(?Promotion $promotion): self
658
    {
659
        $this->promotion = $promotion;
660
661
        return $this;
662
    }
663
664
    public function getDisplayStartDate(): ?DateTime
665
    {
666
        return $this->displayStartDate;
667
    }
668
669
    public function setDisplayStartDate(?DateTime $displayStartDate): self
670
    {
671
        $this->displayStartDate = $displayStartDate;
672
673
        return $this;
674
    }
675
676
    public function getDisplayEndDate(): ?DateTime
677
    {
678
        return $this->displayEndDate;
679
    }
680
681
    public function setDisplayEndDate(?DateTime $displayEndDate): self
682
    {
683
        $this->displayEndDate = $displayEndDate;
684
685
        return $this;
686
    }
687
688
    public function getGeneralCoaches(): ReadableCollection
689
    {
690
        return $this->getGeneralCoachesSubscriptions()
691
            ->map(fn (SessionRelUser $subscription) => $subscription->getUser())
692
        ;
693
    }
694
695
    public function getGeneralCoachesSubscriptions(): Collection
696
    {
697
        $criteria = Criteria::create()->where(Criteria::expr()->eq('relationType', self::GENERAL_COACH));
698
699
        return $this->users->matching($criteria);
700
    }
701
702
    public function hasUserAsGeneralCoach(User $user): bool
703
    {
704
        $criteria = Criteria::create()
705
            ->where(
706
                Criteria::expr()->eq('relationType', self::GENERAL_COACH)
707
            )
708
            ->andWhere(
709
                Criteria::expr()->eq('user', $user)
710
            )
711
        ;
712
713
        return $this->users->matching($criteria)->count() > 0;
714
    }
715
716
    public function addGeneralCoach(User $coach): self
717
    {
718
        return $this->addUserInSession(self::GENERAL_COACH, $coach);
719
    }
720
721
    public function addUserInSession(int $relationType, User $user): self
722
    {
723
        $sessionRelUser = (new SessionRelUser())->setUser($user)->setRelationType($relationType);
724
        $this->addUserSubscription($sessionRelUser);
725
726
        return $this;
727
    }
728
729
    public function removeGeneralCoach(User $user): self
730
    {
731
        $this->removeUserInSession(self::GENERAL_COACH, $user);
732
733
        return $this;
734
    }
735
736
    public function removeUserInSession(int $relationType, User $user): self
737
    {
738
        $criteria = Criteria::create()
739
            ->where(
740
                Criteria::expr()->eq('relationType', $relationType)
741
            )
742
            ->andWhere(
743
                Criteria::expr()->eq('user', $user)
744
            )
745
        ;
746
        $subscriptions = $this->users->matching($criteria);
747
748
        foreach ($subscriptions as $subscription) {
749
            $this->removeUserSubscription($subscription);
750
        }
751
752
        return $this;
753
    }
754
755
    public function removeUserSubscription(SessionRelUser $subscription): self
756
    {
757
        if ($this->hasUser($subscription)) {
758
            $subscription->setSession(null);
759
            $this->users->removeElement($subscription);
760
            $this->nbrUsers--;
761
        }
762
763
        return $this;
764
    }
765
766
    public function getCategory(): ?SessionCategory
767
    {
768
        return $this->category;
769
    }
770
771
    public function setCategory(?SessionCategory $category): self
772
    {
773
        $this->category = $category;
774
775
        return $this;
776
    }
777
778
    /**
779
     * Check if session is visible.
780
     */
781
    public function isActive(): bool
782
    {
783
        $now = new Datetime('now');
784
785
        return $now > $this->getAccessStartDate();
786
    }
787
788
    public function getAccessStartDate(): ?DateTime
789
    {
790
        return $this->accessStartDate;
791
    }
792
793
    public function setAccessStartDate(?DateTime $accessStartDate): self
794
    {
795
        $this->accessStartDate = $accessStartDate;
796
797
        return $this;
798
    }
799
800
    public function isActiveForStudent(): bool
801
    {
802
        $start = $this->getAccessStartDate();
803
        $end = $this->getAccessEndDate();
804
805
        return $this->compareDates($start, $end);
806
    }
807
808
    public function getAccessEndDate(): ?DateTime
809
    {
810
        return $this->accessEndDate;
811
    }
812
813
    public function setAccessEndDate(?DateTime $accessEndDate): self
814
    {
815
        $this->accessEndDate = $accessEndDate;
816
817
        return $this;
818
    }
819
820
    public function isActiveForCoach(): bool
821
    {
822
        $start = $this->getCoachAccessStartDate();
823
        $end = $this->getCoachAccessEndDate();
824
825
        return $this->compareDates($start, $end);
826
    }
827
828
    public function getCoachAccessStartDate(): ?DateTime
829
    {
830
        return $this->coachAccessStartDate;
831
    }
832
833
    public function setCoachAccessStartDate(?DateTime $coachAccessStartDate): self
834
    {
835
        $this->coachAccessStartDate = $coachAccessStartDate;
836
837
        return $this;
838
    }
839
840
    public function getCoachAccessEndDate(): ?DateTime
841
    {
842
        return $this->coachAccessEndDate;
843
    }
844
845
    public function setCoachAccessEndDate(?DateTime $coachAccessEndDate): self
846
    {
847
        $this->coachAccessEndDate = $coachAccessEndDate;
848
849
        return $this;
850
    }
851
852
    /**
853
     * Compare the current date with start and end access dates.
854
     * Either missing date is interpreted as no limit.
855
     *
856
     * @return bool whether now is between the session access start and end dates
857
     */
858
    public function isCurrentlyAccessible(): bool
859
    {
860
        $now = new Datetime();
861
862
        return (null === $this->accessStartDate || $this->accessStartDate < $now)
863
            && (null === $this->accessEndDate || $now < $this->accessEndDate);
864
    }
865
866
    public function addCourse(Course $course): self
867
    {
868
        $sessionRelCourse = (new SessionRelCourse())->setCourse($course);
869
        $this->addCourses($sessionRelCourse);
870
871
        return $this;
872
    }
873
874
    /**
875
     * Removes a course from this session.
876
     *
877
     * @param Course $course the course to remove from this session
878
     *
879
     * @return bool whether the course was actually found in this session and removed from it
880
     */
881
    public function removeCourse(Course $course): bool
882
    {
883
        $relCourse = $this->getCourseSubscription($course);
884
        if (null !== $relCourse) {
885
            $this->courses->removeElement($relCourse);
886
            $this->setNbrCourses(\count($this->courses));
887
888
            return true;
889
        }
890
891
        return false;
892
    }
893
894
    /**
895
     * Add a user course subscription.
896
     * If user status in session is student, then increase number of course users.
897
     * Status example: Session::STUDENT.
898
     */
899
    public function addUserInCourse(int $status, User $user, Course $course): SessionRelCourseRelUser
900
    {
901
        $userRelCourseRelSession = (new SessionRelCourseRelUser())
902
            ->setCourse($course)
903
            ->setUser($user)
904
            ->setSession($this)
905
            ->setStatus($status)
906
        ;
907
908
        $this->addSessionRelCourseRelUser($userRelCourseRelSession);
909
910
        if (self::STUDENT === $status) {
911
            $sessionCourse = $this->getCourseSubscription($course);
912
            $sessionCourse->setNbrUsers($sessionCourse->getNbrUsers() + 1);
913
        }
914
915
        return $userRelCourseRelSession;
916
    }
917
918
    /**
919
     * currentCourse is set in CourseListener.
920
     */
921
    public function getCurrentCourse(): ?Course
922
    {
923
        return $this->currentCourse;
924
    }
925
926
    /**
927
     * currentCourse is set in CourseListener.
928
     */
929
    public function setCurrentCourse(Course $course): self
930
    {
931
        // If the session is registered in the course session list.
932
        $exists = $this->getCourses()
933
            ->exists(
934
                fn ($key, $element) => $course->getId() === $element->getCourse()->getId()
935
            )
936
        ;
937
938
        if ($exists) {
939
            $this->currentCourse = $course;
940
        }
941
942
        return $this;
943
    }
944
945
    public function getSendSubscriptionNotification(): bool
946
    {
947
        return $this->sendSubscriptionNotification;
948
    }
949
950
    public function setSendSubscriptionNotification(bool $sendNotification): self
951
    {
952
        $this->sendSubscriptionNotification = $sendNotification;
953
954
        return $this;
955
    }
956
957
    /**
958
     * Get user from course by status.
959
     */
960
    public function getSessionRelCourseRelUsersByStatus(Course $course, int $status): Collection
961
    {
962
        $criteria = Criteria::create()
963
            ->where(
964
                Criteria::expr()->eq('course', $course)
965
            )
966
            ->andWhere(
967
                Criteria::expr()->eq('status', $status)
968
            )
969
        ;
970
971
        return $this->sessionRelCourseRelUsers->matching($criteria);
972
    }
973
974
    public function getIssuedSkills(): Collection
975
    {
976
        return $this->issuedSkills;
977
    }
978
979
    public function getCurrentUrl(): AccessUrl
980
    {
981
        return $this->currentUrl;
982
    }
983
984
    public function setCurrentUrl(AccessUrl $url): self
985
    {
986
        $urlList = $this->getUrls();
987
        foreach ($urlList as $item) {
988
            if ($item->getUrl()->getId() === $url->getId()) {
989
                $this->currentUrl = $url;
990
991
                break;
992
            }
993
        }
994
995
        return $this;
996
    }
997
998
    /**
999
     * @return Collection<int, EntityAccessUrlInterface>
1000
     */
1001
    public function getUrls(): Collection
1002
    {
1003
        return $this->urls;
1004
    }
1005
1006
    public function setUrls(Collection $urls): self
1007
    {
1008
        $this->urls = new ArrayCollection();
1009
        foreach ($urls as $url) {
1010
            $this->addUrls($url);
1011
        }
1012
1013
        return $this;
1014
    }
1015
1016
    public function addUrls(AccessUrlRelSession $url): self
1017
    {
1018
        $url->setSession($this);
1019
        $this->urls->add($url);
1020
1021
        return $this;
1022
    }
1023
1024
    public function addAccessUrl(?AccessUrl $url): self
1025
    {
1026
        $accessUrlRelSession = new AccessUrlRelSession();
1027
        $accessUrlRelSession->setUrl($url);
1028
        $accessUrlRelSession->setSession($this);
1029
        $this->addUrls($accessUrlRelSession);
1030
1031
        return $this;
1032
    }
1033
1034
    public function getPosition(): int
1035
    {
1036
        return $this->position;
1037
    }
1038
1039
    public function setPosition(int $position): self
1040
    {
1041
        $this->position = $position;
1042
1043
        return $this;
1044
    }
1045
1046
    public function getSessionAdmins(): ReadableCollection
1047
    {
1048
        return $this->getGeneralAdminsSubscriptions()
1049
            ->map(fn (SessionRelUser $subscription) => $subscription->getUser())
1050
        ;
1051
    }
1052
1053
    public function getGeneralAdminsSubscriptions(): Collection
1054
    {
1055
        $criteria = Criteria::create()->where(Criteria::expr()->eq('relationType', self::SESSION_ADMIN));
1056
1057
        return $this->users->matching($criteria);
1058
    }
1059
1060
    public function hasUserAsSessionAdmin(User $user): bool
1061
    {
1062
        $criteria = Criteria::create()
1063
            ->where(
1064
                Criteria::expr()->eq('relationType', self::SESSION_ADMIN)
1065
            )
1066
            ->andWhere(
1067
                Criteria::expr()->eq('user', $user)
1068
            )
1069
        ;
1070
1071
        return $this->users->matching($criteria)->count() > 0;
1072
    }
1073
1074
    public function addSessionAdmin(User $sessionAdmin): self
1075
    {
1076
        return $this->addUserInSession(self::SESSION_ADMIN, $sessionAdmin);
1077
    }
1078
1079
    public function getSkills(): Collection
1080
    {
1081
        return $this->skills;
1082
    }
1083
1084
    public function getResourceLinks(): Collection
1085
    {
1086
        return $this->resourceLinks;
1087
    }
1088
1089
    public function getImage(): ?Asset
1090
    {
1091
        return $this->image;
1092
    }
1093
1094
    public function setImage(?Asset $asset): self
1095
    {
1096
        $this->image = $asset;
1097
1098
        return $this;
1099
    }
1100
1101
    public function hasImage(): bool
1102
    {
1103
        return null !== $this->image;
1104
    }
1105
1106
    /**
1107
     * Check if $user is course coach in any course.
1108
     */
1109
    public function hasCoachInCourseList(User $user): bool
1110
    {
1111
        foreach ($this->courses as $sessionCourse) {
1112
            if ($this->hasCourseCoachInCourse($user, $sessionCourse->getCourse())) {
1113
                return true;
1114
            }
1115
        }
1116
1117
        return false;
1118
    }
1119
1120
    public function hasCourseCoachInCourse(User $user, Course $course = null): bool
1121
    {
1122
        if (null === $course) {
1123
            return false;
1124
        }
1125
1126
        return $this->hasUserInCourse($user, $course, self::COURSE_COACH);
1127
    }
1128
1129
    /**
1130
     * @param int $status if not set it will check if the user is registered
1131
     *                    with any status
1132
     */
1133
    public function hasUserInCourse(User $user, Course $course, int $status = null): bool
1134
    {
1135
        $relation = $this->getUserInCourse($user, $course, $status);
1136
1137
        return $relation->count() > 0;
1138
    }
1139
1140
    public function getUserInCourse(User $user, Course $course, int $status = null): Collection
1141
    {
1142
        $criteria = Criteria::create()
1143
            ->where(
1144
                Criteria::expr()->eq('course', $course)
1145
            )
1146
            ->andWhere(
1147
                Criteria::expr()->eq('user', $user)
1148
            )
1149
        ;
1150
1151
        if (null !== $status) {
1152
            $criteria->andWhere(Criteria::expr()->eq('status', $status));
1153
        }
1154
1155
        return $this->getSessionRelCourseRelUsers()->matching($criteria);
1156
    }
1157
1158
    /**
1159
     * Check if $user is student in any course.
1160
     */
1161
    public function hasStudentInCourseList(User $user): bool
1162
    {
1163
        foreach ($this->courses as $sessionCourse) {
1164
            if ($this->hasStudentInCourse($user, $sessionCourse->getCourse())) {
1165
                return true;
1166
            }
1167
        }
1168
1169
        return false;
1170
    }
1171
1172
    public function hasStudentInCourse(User $user, Course $course): bool
1173
    {
1174
        return $this->hasUserInCourse($user, $course, self::STUDENT);
1175
    }
1176
1177
    protected function compareDates(?DateTime $start, DateTime $end = null): bool
1178
    {
1179
        $now = new Datetime('now');
1180
1181
        if (!empty($start) && !empty($end) && ($now >= $start && $now <= $end)) {
1182
            return true;
1183
        }
1184
1185
        if (!empty($start) && $now >= $start) {
1186
            return true;
1187
        }
1188
1189
        return !empty($end) && $now <= $end;
1190
    }
1191
}
1192