Passed
Push — master ( bd8ed8...9d8dba )
by Angel Fernando Quiroz
09:46 queued 18s
created

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