Passed
Pull Request — master (#7168)
by
unknown
09:56
created

Session::getDisplayEndDate()   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\Metadata\ApiResource;
10
use ApiPlatform\Metadata\Delete;
11
use ApiPlatform\Metadata\Get;
12
use ApiPlatform\Metadata\GetCollection;
13
use ApiPlatform\Metadata\Link;
14
use ApiPlatform\Metadata\Post;
15
use ApiPlatform\Metadata\Put;
16
use Chamilo\CoreBundle\Controller\Api\CreateSessionWithUsersAndCoursesAction;
17
use Chamilo\CoreBundle\Dto\CreateSessionWithUsersAndCoursesInput;
18
use Chamilo\CoreBundle\Entity\Listener\SessionListener;
19
use Chamilo\CoreBundle\Repository\SessionRepository;
20
use Chamilo\CoreBundle\State\UserSessionSubscriptionsStateProvider;
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 LogicException;
28
use Stringable;
29
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
30
use Symfony\Component\Serializer\Annotation\Groups;
31
use Symfony\Component\Validator\Constraints as Assert;
32
33
#[ApiResource(
34
    operations: [
35
        new Get(
36
            uriTemplate: '/sessions/{id}',
37
            normalizationContext: [
38
                'groups' => ['session:basic'],
39
            ],
40
            security: "is_granted('ROLE_ADMIN') or is_granted('VIEW', object)"
41
        ),
42
        new Put(security: "is_granted('ROLE_ADMIN')"),
43
        new GetCollection(
44
            security: "is_granted('ROLE_ADMIN')",
45
            filters: [
46
                'session.search_filter',
47
                'session.property_filter',
48
                'session.order_filter',
49
                'session.group_filter',
50
            ]
51
        ),
52
        new GetCollection(
53
            uriTemplate: '/users/{id}/session_subscriptions/past.{_format}',
54
            uriVariables: [
55
                'id' => new Link(
56
                    fromClass: User::class,
57
                    description: 'User identifier',
58
                ),
59
            ],
60
            paginationEnabled: false,
61
            normalizationContext: [
62
                'groups' => [
63
                    'user_subscriptions:sessions',
64
                ],
65
            ],
66
            security: "is_granted('ROLE_USER')",
67
            name: 'user_session_subscriptions_past',
68
            provider: UserSessionSubscriptionsStateProvider::class,
69
        ),
70
        new GetCollection(
71
            uriTemplate: '/users/{id}/session_subscriptions/current.{_format}',
72
            uriVariables: [
73
                'id' => new Link(
74
                    fromClass: User::class,
75
                    description: 'User identifier',
76
                ),
77
            ],
78
            normalizationContext: [
79
                'groups' => [
80
                    'user_subscriptions:sessions',
81
                ],
82
            ],
83
            security: "is_granted('ROLE_USER')",
84
            name: 'user_session_subscriptions_current',
85
            provider: UserSessionSubscriptionsStateProvider::class,
86
        ),
87
        new GetCollection(
88
            uriTemplate: '/users/{id}/session_subscriptions/upcoming.{_format}',
89
            uriVariables: [
90
                'id' => new Link(
91
                    fromClass: User::class,
92
                    description: 'User identifier',
93
                ),
94
            ],
95
            normalizationContext: [
96
                'groups' => [
97
                    'user_subscriptions:sessions',
98
                ],
99
            ],
100
            security: "is_granted('ROLE_USER')",
101
            name: 'user_session_subscriptions_upcoming',
102
            provider: UserSessionSubscriptionsStateProvider::class,
103
        ),
104
        new Post(security: "is_granted('ROLE_ADMIN')"),
105
        new Post(
106
            uriTemplate: '/advanced/create-session-with-courses-and-users',
107
            controller: CreateSessionWithUsersAndCoursesAction::class,
108
            denormalizationContext: ['groups' => ['write']],
109
            security: "is_granted('ROLE_ADMIN') or is_granted('ROLE_SESSION_MANAGER')",
110
            input: CreateSessionWithUsersAndCoursesInput::class,
111
            output: Session::class,
112
            deserialize: true,
113
            name: 'create_session_with_courses_and_assign_users'
114
        ),
115
        new Delete(security: "is_granted('DELETE', object)"),
116
    ],
117
    normalizationContext: ['groups' => ['session:basic']],
118
    denormalizationContext: ['groups' => ['session:write']],
119
    security: "is_granted('ROLE_ADMIN')"
120
)]
121
#[ORM\Table(name: 'session')]
122
#[ORM\UniqueConstraint(name: 'title', columns: ['title'])]
123
#[ORM\EntityListeners([SessionListener::class])]
124
#[ORM\Entity(repositoryClass: SessionRepository::class)]
125
#[UniqueEntity('title')]
126
class Session implements ResourceWithAccessUrlInterface, Stringable
127
{
128
    public const READ_ONLY = 1;
129
    public const VISIBLE = 2;
130
    public const INVISIBLE = 3;
131
    public const AVAILABLE = 4;
132
    public const LIST_ONLY = 5;
133
134
    public const STUDENT = 0;
135
    public const DRH = 1;
136
    public const COURSE_COACH = 2;
137
    public const GENERAL_COACH = 3;
138
    public const SESSION_ADMIN = 4;
139
140
    public const STATUS_PLANNED = 1;
141
    public const STATUS_PROGRESS = 2;
142
    public const STATUS_FINISHED = 3;
143
    public const STATUS_CANCELLED = 4;
144
    public const STATUS_UNKNOWN = 0;
145
146
    #[Groups([
147
        'session:basic',
148
        'session:read',
149
        'session_rel_user:read',
150
        'session_rel_course_rel_user:read',
151
        'course:read',
152
        'track_e_exercise:read',
153
        'user_subscriptions:sessions',
154
    ])]
155
    #[ORM\Column(name: 'id', type: 'integer')]
156
    #[ORM\Id]
157
    #[ORM\GeneratedValue]
158
    protected ?int $id = null;
159
160
    /**
161
     * @var Collection<int, SessionRelCourse>
162
     */
163
    #[Groups([
164
        'session:read',
165
        'session_rel_user:read',
166
        'session_rel_course_rel_user:read',
167
        'user_subscriptions:sessions',
168
    ])]
169
    #[ORM\OrderBy(['position' => 'ASC'])]
170
    #[ORM\OneToMany(
171
        mappedBy: 'session',
172
        targetEntity: SessionRelCourse::class,
173
        cascade: ['persist'],
174
        fetch: 'EXTRA_LAZY',
175
        orphanRemoval: true
176
    )]
177
    protected Collection $courses;
178
179
    /**
180
     * @var Collection<int, SessionRelUser>
181
     */
182
    #[Groups([
183
        'session:read',
184
    ])]
185
    #[ORM\OneToMany(
186
        mappedBy: 'session',
187
        targetEntity: SessionRelUser::class,
188
        cascade: ['persist', 'remove'],
189
        fetch: 'EXTRA_LAZY',
190
        orphanRemoval: true
191
    )]
192
    protected Collection $users;
193
194
    /**
195
     * @var Collection<int, SessionRelCourseRelUser>
196
     */
197
    #[Groups([
198
        'session:read',
199
        'session_rel_course_rel_user:read',
200
    ])]
201
    #[ORM\OneToMany(
202
        mappedBy: 'session',
203
        targetEntity: SessionRelCourseRelUser::class,
204
        cascade: ['persist'],
205
        orphanRemoval: true
206
    )]
207
    protected Collection $sessionRelCourseRelUsers;
208
209
    /**
210
     * @var Collection<int, SkillRelCourse>
211
     */
212
    #[ORM\OneToMany(
213
        mappedBy: 'session',
214
        targetEntity: SkillRelCourse::class,
215
        cascade: ['persist', 'remove']
216
    )]
217
    protected Collection $skills;
218
219
    /**
220
     * @var Collection<int, SkillRelUser>
221
     */
222
    #[ORM\OneToMany(mappedBy: 'session', targetEntity: SkillRelUser::class, cascade: ['persist'])]
223
    protected Collection $issuedSkills;
224
225
    /**
226
     * @var Collection<int, EntityAccessUrlInterface>
227
     */
228
    #[ORM\OneToMany(
229
        mappedBy: 'session',
230
        targetEntity: AccessUrlRelSession::class,
231
        cascade: ['persist'],
232
        orphanRemoval: true
233
    )]
234
    protected Collection $urls;
235
236
    /**
237
     * @var Collection<int, ResourceLink>
238
     */
239
    #[ORM\OneToMany(mappedBy: 'session', targetEntity: ResourceLink::class, cascade: ['remove'], orphanRemoval: true)]
240
    protected Collection $resourceLinks;
241
242
    protected AccessUrl $currentUrl;
243
244
    protected ?Course $currentCourse = null;
245
246
    #[Assert\NotBlank]
247
    #[Groups([
248
        'session:basic',
249
        'session:read',
250
        'session:write',
251
        'session_rel_course_rel_user:read',
252
        'document:read',
253
        'session_rel_user:read',
254
        'course:read',
255
        'track_e_exercise:read',
256
        'calendar_event:read',
257
        'user_subscriptions:sessions',
258
    ])]
259
    #[ORM\Column(name: 'title', type: 'string', length: 150)]
260
    protected string $title;
261
262
    #[Groups([
263
        'session:basic',
264
        'session:read',
265
        'session:write',
266
    ])]
267
    #[ORM\Column(name: 'description', type: 'text', unique: false, nullable: true)]
268
    protected ?string $description;
269
270
    #[Groups([
271
        'session:read',
272
        'session:write',
273
    ])]
274
    #[ORM\Column(name: 'show_description', type: 'boolean', nullable: true)]
275
    protected ?bool $showDescription = false;
276
277
    #[Groups(['session:read', 'session:write', 'user_subscriptions:sessions'])]
278
    #[ORM\Column(name: 'duration', type: 'integer', nullable: true)]
279
    protected ?int $duration = null;
280
281
    #[Groups(['session:basic', 'session:read', 'session:write'])]
282
    #[ORM\Column(name: 'nbr_courses', type: 'integer', unique: false, nullable: false)]
283
    protected int $nbrCourses;
284
285
    #[Groups(['session:basic', 'session:read', 'session:write'])]
286
    #[ORM\Column(name: 'nbr_users', type: 'integer', unique: false, nullable: false)]
287
    protected int $nbrUsers;
288
289
    #[Groups(['session:read'])]
290
    #[ORM\Column(name: 'nbr_classes', type: 'integer', unique: false, nullable: false)]
291
    protected int $nbrClasses;
292
293
    #[Groups([
294
        'session:basic',
295
        'session:read',
296
        'session:write',
297
    ])]
298
    #[ORM\Column(name: 'visibility', type: 'integer')]
299
    protected int $visibility;
300
301
    #[ORM\ManyToOne(targetEntity: Promotion::class, cascade: ['persist'], inversedBy: 'sessions')]
302
    #[ORM\JoinColumn(name: 'promotion_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
303
    protected ?Promotion $promotion = null;
304
305
    #[Groups([
306
        'session:read',
307
        'session:write',
308
        'session_rel_user:read',
309
        'session_rel_course_rel_user:read',
310
        'user_subscriptions:sessions',
311
    ])]
312
    #[ORM\Column(name: 'display_start_date', type: 'datetime', unique: false, nullable: true)]
313
    protected ?DateTime $displayStartDate = null;
314
315
    #[Groups([
316
        'session:read',
317
        'session:write',
318
        'session_rel_user:read',
319
        'session_rel_course_rel_user:read',
320
        'user_subscriptions:sessions',
321
    ])]
322
    #[ORM\Column(name: 'display_end_date', type: 'datetime', unique: false, nullable: true)]
323
    protected ?DateTime $displayEndDate = null;
324
325
    #[Groups([
326
        'session:read',
327
        'session:write',
328
        'session_rel_user:read',
329
        'session_rel_course_rel_user:read',
330
    ])]
331
    #[ORM\Column(name: 'access_start_date', type: 'datetime', unique: false, nullable: true)]
332
    protected ?DateTime $accessStartDate = null;
333
334
    #[Groups([
335
        'session:read',
336
        'session:write',
337
        'session_rel_user:read',
338
        'session_rel_course_rel_user:read',
339
    ])]
340
    #[ORM\Column(name: 'access_end_date', type: 'datetime', unique: false, nullable: true)]
341
    protected ?DateTime $accessEndDate = null;
342
343
    #[Groups([
344
        'session:read',
345
        'session:write',
346
        'session_rel_user:read',
347
        'session_rel_course_rel_user:read',
348
    ])]
349
    #[ORM\Column(name: 'coach_access_start_date', type: 'datetime', unique: false, nullable: true)]
350
    protected ?DateTime $coachAccessStartDate = null;
351
352
    #[Groups([
353
        'session:read',
354
        'session:write',
355
        'session_rel_user:read',
356
        'session_rel_course_rel_user:read',
357
    ])]
358
    #[ORM\Column(name: 'coach_access_end_date', type: 'datetime', unique: false, nullable: true)]
359
    protected ?DateTime $coachAccessEndDate = null;
360
361
    #[ORM\Column(name: 'position', type: 'integer', nullable: false, options: ['default' => 0])]
362
    protected int $position;
363
364
    #[Groups(['session:read'])]
365
    #[ORM\Column(name: 'status', type: 'integer', nullable: false)]
366
    protected int $status;
367
368
    #[Groups(['session:read', 'session:write', 'session_rel_user:read', 'user_subscriptions:sessions'])]
369
    #[ORM\ManyToOne(targetEntity: SessionCategory::class, inversedBy: 'sessions')]
370
    #[ORM\JoinColumn(name: 'session_category_id', referencedColumnName: 'id')]
371
    protected ?SessionCategory $category = null;
372
373
    #[ORM\Column(
374
        name: 'send_subscription_notification',
375
        type: 'boolean',
376
        nullable: false,
377
        options: ['default' => false]
378
    )]
379
    protected bool $sendSubscriptionNotification;
380
381
    /**
382
     * Image illustrating the session (was extra field 'image' in 1.11).
383
     */
384
    #[Groups(['user_subscriptions:sessions'])]
385
    #[ORM\ManyToOne(targetEntity: Asset::class, cascade: ['persist', 'remove'])]
386
    #[ORM\JoinColumn(name: 'image_id', referencedColumnName: 'id', onDelete: 'SET NULL')]
387
    protected ?Asset $image = null;
388
389
    #[Groups(['session:basic'])]
390
    private ?string $imageUrl = null;
391
392
    #[Groups(['user_subscriptions:sessions', 'session:read', 'session:item:read'])]
393
    private int $accessVisibility = 0;
394
395
    #[ORM\Column(name: 'parent_id', type: 'integer', nullable: true)]
396
    protected ?int $parentId = null;
397
398
    #[ORM\Column(name: 'days_to_reinscription', type: 'integer', nullable: true)]
399
    protected ?int $daysToReinscription = null;
400
401
    #[ORM\Column(name: 'last_repetition', type: 'boolean', nullable: false, options: ['default' => false])]
402
    protected bool $lastRepetition = false;
403
404
    #[ORM\Column(name: 'days_to_new_repetition', type: 'integer', nullable: true)]
405
    protected ?int $daysToNewRepetition = null;
406
407
    #[ORM\Column(name: 'notify_boss', type: 'boolean', options: ['default' => false])]
408
    protected bool $notifyBoss = false;
409
410
    #[Groups(['session:basic', 'session:read', 'session:write'])]
411
    #[ORM\Column(name: 'validity_in_days', type: 'integer', nullable: true)]
412
    protected ?int $validityInDays = null;
413
414
    #[Groups(['user_subscriptions:sessions'])]
415
    private ?int $daysLeft = null;
416
417
    public function __construct()
418
    {
419
        $this->skills = new ArrayCollection();
420
        $this->issuedSkills = new ArrayCollection();
421
        $this->resourceLinks = new ArrayCollection();
422
        $this->courses = new ArrayCollection();
423
        $this->users = new ArrayCollection();
424
        $this->sessionRelCourseRelUsers = new ArrayCollection();
425
        $this->urls = new ArrayCollection();
426
        $this->duration = 0;
427
        $this->description = '';
428
        $this->nbrClasses = 0;
429
        $this->nbrUsers = 0;
430
        $this->nbrCourses = 0;
431
        $this->sendSubscriptionNotification = false;
432
        $now = new DateTime();
433
        $this->displayStartDate = $now;
434
        $this->displayEndDate = $now;
435
        $this->accessStartDate = $now;
436
        $this->accessEndDate = $now;
437
        $this->coachAccessStartDate = $now;
438
        $this->coachAccessEndDate = $now;
439
        $this->visibility = 1;
440
        $this->showDescription = false;
441
        $this->category = null;
442
        $this->status = 0;
443
        $this->position = 0;
444
    }
445
446
    public function __toString(): string
447
    {
448
        return $this->getTitle();
449
    }
450
451
    public static function getRelationTypeList(): array
452
    {
453
        return [self::STUDENT, self::DRH, self::COURSE_COACH, self::GENERAL_COACH, self::SESSION_ADMIN];
454
    }
455
456
    public static function getStatusList(): array
457
    {
458
        return [
459
            self::READ_ONLY => 'status_read_only',
460
            self::VISIBLE => 'status_visible',
461
            self::INVISIBLE => 'status_invisible',
462
            self::AVAILABLE => 'status_available',
463
        ];
464
    }
465
466
    public function getDuration(): ?int
467
    {
468
        return $this->duration;
469
    }
470
471
    public function setDuration(int $duration): self
472
    {
473
        $this->duration = $duration;
474
475
        return $this;
476
    }
477
478
    public function getShowDescription(): bool
479
    {
480
        return $this->showDescription ?? false;
481
    }
482
483
    public function setShowDescription(bool $showDescription): self
484
    {
485
        $this->showDescription = $showDescription;
486
487
        return $this;
488
    }
489
490
    /**
491
     * @return Collection<int, SessionRelUser>
492
     */
493
    public function getUsers(): Collection
494
    {
495
        return $this->users;
496
    }
497
498
    public function setUsers(Collection $users): self
499
    {
500
        $this->users = new ArrayCollection();
501
        foreach ($users as $user) {
502
            $this->addUserSubscription($user);
503
        }
504
505
        return $this;
506
    }
507
508
    public function addUserSubscription(SessionRelUser $subscription): void
509
    {
510
        $subscription->setSession($this);
511
        if (!$this->hasUser($subscription)) {
512
            $this->users->add($subscription);
513
            $this->nbrUsers++;
514
        }
515
    }
516
517
    public function hasUser(SessionRelUser $subscription): bool
518
    {
519
        if (0 !== $this->getUsers()->count()) {
520
            $criteria = Criteria::create()
521
                ->where(
522
                    Criteria::expr()->eq('user', $subscription->getUser())
523
                )
524
                ->andWhere(
525
                    Criteria::expr()->eq('session', $subscription->getSession())
526
                )
527
                ->andWhere(
528
                    Criteria::expr()->eq('relationType', $subscription->getRelationType())
529
                )
530
            ;
531
            $relation = $this->getUsers()->matching($criteria);
532
533
            return $relation->count() > 0;
534
        }
535
536
        return false;
537
    }
538
539
    public function hasCourse(Course $course): bool
540
    {
541
        if (0 !== $this->getCourses()->count()) {
542
            $criteria = Criteria::create()->where(Criteria::expr()->eq('course', $course));
543
            $relation = $this->getCourses()->matching($criteria);
544
545
            return $relation->count() > 0;
546
        }
547
548
        return false;
549
    }
550
551
    /**
552
     * @return Collection<int, SessionRelCourse>
553
     */
554
    public function getCourses(): Collection
555
    {
556
        return $this->courses;
557
    }
558
559
    public function setCourses(ArrayCollection $courses): void
560
    {
561
        $this->courses = new ArrayCollection();
562
        foreach ($courses as $course) {
563
            $this->addCourses($course);
564
        }
565
    }
566
567
    public function addCourses(SessionRelCourse $course): void
568
    {
569
        $course->setSession($this);
570
        $this->courses->add($course);
571
    }
572
573
    public function removeCourses(SessionRelCourse $course): void
574
    {
575
        foreach ($this->courses as $key => $value) {
576
            if ($value->getId() === $course->getId()) {
577
                unset($this->courses[$key]);
578
            }
579
        }
580
    }
581
582
    public function getId(): ?int
583
    {
584
        return $this->id;
585
    }
586
587
    /**
588
     * Remove course subscription for a user.
589
     * If user status in session is student, then decrease number of course users.
590
     */
591
    public function removeUserCourseSubscription(User $user, Course $course): void
592
    {
593
        foreach ($this->sessionRelCourseRelUsers as $i => $sessionRelUser) {
594
            if ($sessionRelUser->getCourse()->getId() === $course->getId()
595
                && $sessionRelUser->getUser()->getId() === $user->getId()
596
            ) {
597
                if (self::STUDENT === $this->sessionRelCourseRelUsers[$i]->getStatus()) {
598
                    $sessionCourse = $this->getCourseSubscription($course);
599
                    $sessionCourse->setNbrUsers($sessionCourse->getNbrUsers() - 1);
600
                }
601
602
                unset($this->sessionRelCourseRelUsers[$i]);
603
            }
604
        }
605
    }
606
607
    public function getStatus(): int
608
    {
609
        return $this->status;
610
    }
611
612
    public function setStatus(int $status): self
613
    {
614
        $this->status = $status;
615
616
        return $this;
617
    }
618
619
    public function setTitle(string $title): self
620
    {
621
        $this->title = $title;
622
623
        return $this;
624
    }
625
626
    public function getCourseSubscription(Course $course): ?SessionRelCourse
627
    {
628
        $criteria = Criteria::create()->where(Criteria::expr()->eq('course', $course));
629
630
        return $this->courses->matching($criteria)->current();
631
    }
632
633
    public function getTitle(): string
634
    {
635
        return $this->title;
636
    }
637
638
    public function getNbrUsers(): int
639
    {
640
        return $this->nbrUsers;
641
    }
642
643
    public function setNbrUsers(int $nbrUsers): self
644
    {
645
        $this->nbrUsers = $nbrUsers;
646
647
        return $this;
648
    }
649
650
    /**
651
     * @return Collection<int, SessionRelCourseRelUser>
652
     */
653
    public function getAllUsersFromCourse(int $status): Collection
654
    {
655
        $criteria = Criteria::create()->where(Criteria::expr()->eq('status', $status));
656
657
        return $this->getSessionRelCourseRelUsers()->matching($criteria);
658
    }
659
660
    public function getSessionRelCourseRelUsers(): Collection
661
    {
662
        return $this->sessionRelCourseRelUsers;
663
    }
664
665
    public function setSessionRelCourseRelUsers(Collection $sessionRelCourseRelUsers): self
666
    {
667
        $this->sessionRelCourseRelUsers = new ArrayCollection();
668
        foreach ($sessionRelCourseRelUsers as $item) {
669
            $this->addSessionRelCourseRelUser($item);
670
        }
671
672
        return $this;
673
    }
674
675
    public function addSessionRelCourseRelUser(SessionRelCourseRelUser $sessionRelCourseRelUser): void
676
    {
677
        $sessionRelCourseRelUser->setSession($this);
678
        if (!$this->hasUserCourseSubscription($sessionRelCourseRelUser)) {
679
            $this->sessionRelCourseRelUsers->add($sessionRelCourseRelUser);
680
        }
681
    }
682
683
    public function hasUserCourseSubscription(SessionRelCourseRelUser $subscription): bool
684
    {
685
        if (0 !== $this->getSessionRelCourseRelUsers()->count()) {
686
            $criteria = Criteria::create()
687
                ->where(
688
                    Criteria::expr()->eq('user', $subscription->getUser())
689
                )
690
                ->andWhere(
691
                    Criteria::expr()->eq('course', $subscription->getCourse())
692
                )
693
                ->andWhere(
694
                    Criteria::expr()->eq('session', $subscription->getSession())
695
                )
696
            ;
697
            $relation = $this->getSessionRelCourseRelUsers()->matching($criteria);
698
699
            return $relation->count() > 0;
700
        }
701
702
        return false;
703
    }
704
705
    /**
706
     * @return Collection<int, SessionRelCourseRelUser>
707
     */
708
    public function getSessionRelCourseByUser(User $user, ?int $status = null): Collection
709
    {
710
        $criteria = Criteria::create()->where(Criteria::expr()->eq('user', $user));
711
        if (null !== $status) {
712
            $criteria->andWhere(Criteria::expr()->eq('status', $status));
713
        }
714
715
        return $this->sessionRelCourseRelUsers->matching($criteria);
716
    }
717
718
    public function getDescription(): ?string
719
    {
720
        return $this->description;
721
    }
722
723
    public function setDescription(string $description): self
724
    {
725
        $this->description = $description;
726
727
        return $this;
728
    }
729
730
    public function getNbrCourses(): int
731
    {
732
        return $this->nbrCourses;
733
    }
734
735
    public function setNbrCourses(int $nbrCourses): self
736
    {
737
        $this->nbrCourses = $nbrCourses;
738
739
        return $this;
740
    }
741
742
    public function getNbrClasses(): int
743
    {
744
        return $this->nbrClasses;
745
    }
746
747
    public function setNbrClasses(int $nbrClasses): self
748
    {
749
        $this->nbrClasses = $nbrClasses;
750
751
        return $this;
752
    }
753
754
    public function getVisibility(): int
755
    {
756
        return $this->visibility;
757
    }
758
759
    public function setVisibility(int $visibility): self
760
    {
761
        $this->visibility = $visibility;
762
763
        return $this;
764
    }
765
766
    public function getPromotion(): ?Promotion
767
    {
768
        return $this->promotion;
769
    }
770
771
    public function setPromotion(?Promotion $promotion): self
772
    {
773
        $this->promotion = $promotion;
774
775
        return $this;
776
    }
777
778
    public function getDisplayStartDate(): ?DateTime
779
    {
780
        return $this->displayStartDate;
781
    }
782
783
    public function setDisplayStartDate(?DateTime $displayStartDate): self
784
    {
785
        $this->displayStartDate = $displayStartDate;
786
787
        return $this;
788
    }
789
790
    public function getDisplayEndDate(): ?DateTime
791
    {
792
        return $this->displayEndDate;
793
    }
794
795
    public function setDisplayEndDate(?DateTime $displayEndDate): self
796
    {
797
        $this->displayEndDate = $displayEndDate;
798
799
        return $this;
800
    }
801
802
    /**
803
     * @return Collection<int, User>
804
     */
805
    public function getGeneralCoaches(): Collection
806
    {
807
        return $this->getGeneralCoachesSubscriptions()
808
            ->map(fn (SessionRelUser $subscription) => $subscription->getUser())
809
        ;
810
    }
811
812
    /**
813
     * @return Collection<int, SessionRelUser>
814
     */
815
    public function getCoachesSubscriptions(bool $includeSessionAdmin = false): Collection
816
    {
817
        $relationTypes = [
818
            self::COURSE_COACH,
819
            self::GENERAL_COACH,
820
        ];
821
822
        if ($includeSessionAdmin) {
823
            $relationTypes[] = self::SESSION_ADMIN;
824
        }
825
826
        $criteria = Criteria::create()->where(Criteria::expr()->in('relationType', $relationTypes));
827
828
        return $this->users->matching($criteria);
829
    }
830
831
    /**
832
     * @return Collection<int, SessionRelUser>
833
     */
834
    public function getStudentSubscriptions(): Collection
835
    {
836
        $criteria = Criteria::create()->where(Criteria::expr()->eq('relationType', self::STUDENT));
837
838
        return $this->users->matching($criteria);
839
    }
840
841
    /**
842
     * @return Collection<int, SessionRelUser>
843
     */
844
    #[Groups(['session:basic', 'user_subscriptions:sessions'])]
845
    public function getGeneralCoachesSubscriptions(): Collection
846
    {
847
        $criteria = Criteria::create()->where(Criteria::expr()->eq('relationType', self::GENERAL_COACH));
848
849
        return $this->users->matching($criteria);
850
    }
851
852
    public function hasUserAsGeneralCoach(User $user): bool
853
    {
854
        $criteria = Criteria::create()
855
            ->where(
856
                Criteria::expr()->eq('relationType', self::GENERAL_COACH)
857
            )
858
            ->andWhere(
859
                Criteria::expr()->eq('user', $user)
860
            )
861
        ;
862
863
        return $this->users->matching($criteria)->count() > 0;
864
    }
865
866
    public function hasUserInSession(User $user, int $relationType): bool
867
    {
868
        $criteria = Criteria::create()
869
            ->where(Criteria::expr()->eq('user', $user))
870
            ->andWhere(Criteria::expr()->eq('relationType', $relationType))
871
        ;
872
873
        return $this->users->matching($criteria)->count() > 0;
874
    }
875
876
    public function addGeneralCoach(User $coach): self
877
    {
878
        return $this->addUserInSession(self::GENERAL_COACH, $coach);
879
    }
880
881
    public function addUserInSession(int $relationType, User $user): self
882
    {
883
        foreach ($this->getUsers() as $existingSubscription) {
884
            if (
885
                $existingSubscription->getUser()->getId() === $user->getId()
886
                && $existingSubscription->getRelationType() === $relationType
887
            ) {
888
                return $this;
889
            }
890
        }
891
892
        $sessionRelUser = (new SessionRelUser())
893
            ->setUser($user)
894
            ->setRelationType($relationType)
895
        ;
896
897
        $this->addUserSubscription($sessionRelUser);
898
899
        if ($this->duration <= 0) {
900
            $isCoach = \in_array($relationType, [self::COURSE_COACH, self::GENERAL_COACH, self::SESSION_ADMIN]);
901
902
            $sessionRelUser
903
                ->setAccessStartDate(
904
                    $isCoach && $this->coachAccessStartDate ? $this->coachAccessStartDate : $this->accessStartDate
905
                )
906
                ->setAccessEndDate(
907
                    $isCoach && $this->coachAccessEndDate ? $this->coachAccessEndDate : $this->accessEndDate
908
                )
909
            ;
910
        }
911
912
        return $this;
913
    }
914
915
    public function removeGeneralCoach(User $user): self
916
    {
917
        $this->removeUserInSession(self::GENERAL_COACH, $user);
918
919
        return $this;
920
    }
921
922
    public function removeUserInSession(int $relationType, User $user): self
923
    {
924
        $criteria = Criteria::create()
925
            ->where(
926
                Criteria::expr()->eq('relationType', $relationType)
927
            )
928
            ->andWhere(
929
                Criteria::expr()->eq('user', $user)
930
            )
931
        ;
932
        $subscriptions = $this->users->matching($criteria);
933
934
        foreach ($subscriptions as $subscription) {
935
            $this->removeUserSubscription($subscription);
936
        }
937
938
        return $this;
939
    }
940
941
    public function removeUserSubscription(SessionRelUser $subscription): self
942
    {
943
        if ($this->hasUser($subscription)) {
944
            $subscription->setSession(null);
945
            $this->users->removeElement($subscription);
946
            $this->nbrUsers--;
947
        }
948
949
        return $this;
950
    }
951
952
    public function getCategory(): ?SessionCategory
953
    {
954
        return $this->category;
955
    }
956
957
    public function setCategory(?SessionCategory $category): self
958
    {
959
        $this->category = $category;
960
961
        return $this;
962
    }
963
964
    /**
965
     * Check if session is visible.
966
     */
967
    public function isActive(): bool
968
    {
969
        $now = new DateTime('now');
970
971
        return $now > $this->getAccessStartDate();
972
    }
973
974
    public function getAccessStartDate(): ?DateTime
975
    {
976
        return $this->accessStartDate;
977
    }
978
979
    public function setAccessStartDate(?DateTime $accessStartDate, bool $updateCoachesDates = false): self
980
    {
981
        $this->accessStartDate = $accessStartDate;
982
983
        if ($updateCoachesDates) {
984
            foreach ($this->getStudentSubscriptions() as $studentSubscription) {
985
                $studentSubscription->setAccessStartDate($this->accessStartDate);
986
            }
987
        }
988
989
        return $this;
990
    }
991
992
    public function isActiveForStudent(): bool
993
    {
994
        $start = $this->getAccessStartDate();
995
        $end = $this->getAccessEndDate();
996
997
        return $this->compareDates($start, $end);
998
    }
999
1000
    public function getAccessEndDate(): ?DateTime
1001
    {
1002
        return $this->accessEndDate;
1003
    }
1004
1005
    public function setAccessEndDate(?DateTime $accessEndDate, bool $updateCoachesDates = false): self
1006
    {
1007
        $this->accessEndDate = $accessEndDate;
1008
1009
        if ($updateCoachesDates) {
1010
            foreach ($this->getStudentSubscriptions() as $studentSubscription) {
1011
                $studentSubscription->setAccessEndDate($this->accessEndDate);
1012
            }
1013
        }
1014
1015
        return $this;
1016
    }
1017
1018
    public function isActiveForCoach(): bool
1019
    {
1020
        $start = $this->getCoachAccessStartDate();
1021
        $end = $this->getCoachAccessEndDate();
1022
1023
        return $this->compareDates($start, $end);
1024
    }
1025
1026
    public function getCoachAccessStartDate(): ?DateTime
1027
    {
1028
        return $this->coachAccessStartDate;
1029
    }
1030
1031
    public function setCoachAccessStartDate(
1032
        ?DateTime $coachAccessStartDate,
1033
        bool $updateCoachesDates = false,
1034
        bool $updateAdminDates = false,
1035
    ): self {
1036
        $this->coachAccessStartDate = $coachAccessStartDate;
1037
1038
        if ($updateCoachesDates) {
1039
            foreach ($this->getCoachesSubscriptions($updateAdminDates) as $coachSubscription) {
1040
                $coachSubscription->setAccessStartDate($this->coachAccessStartDate ?: $this->accessStartDate);
1041
            }
1042
        }
1043
1044
        return $this;
1045
    }
1046
1047
    public function getCoachAccessEndDate(): ?DateTime
1048
    {
1049
        return $this->coachAccessEndDate;
1050
    }
1051
1052
    public function setCoachAccessEndDate(
1053
        ?DateTime $coachAccessEndDate,
1054
        bool $updateCoachesDates = false,
1055
        bool $updateAdminDates = false,
1056
    ): self {
1057
        $this->coachAccessEndDate = $coachAccessEndDate;
1058
1059
        if ($updateCoachesDates) {
1060
            foreach ($this->getCoachesSubscriptions($updateAdminDates) as $coachSubscription) {
1061
                $coachSubscription->setAccessEndDate($this->coachAccessEndDate ?: $this->accessEndDate);
1062
            }
1063
        }
1064
1065
        return $this;
1066
    }
1067
1068
    /**
1069
     * Compare the current date with start and end access dates.
1070
     * Either missing date is interpreted as no limit.
1071
     *
1072
     * @return bool whether now is between the session access start and end dates
1073
     */
1074
    public function isCurrentlyAccessible(): bool
1075
    {
1076
        $now = new DateTime();
1077
1078
        return (!$this->accessStartDate || $now >= $this->accessStartDate) && (!$this->accessEndDate || $now <= $this->accessEndDate);
1079
    }
1080
1081
    public function addCourse(Course $course): self
1082
    {
1083
        $sessionRelCourse = (new SessionRelCourse())->setCourse($course);
1084
        $this->addCourses($sessionRelCourse);
1085
1086
        return $this;
1087
    }
1088
1089
    /**
1090
     * Removes a course from this session.
1091
     *
1092
     * @param Course $course the course to remove from this session
1093
     *
1094
     * @return bool whether the course was actually found in this session and removed from it
1095
     */
1096
    public function removeCourse(Course $course): bool
1097
    {
1098
        $relCourse = $this->getCourseSubscription($course);
1099
        if (null !== $relCourse) {
1100
            $this->courses->removeElement($relCourse);
1101
            $this->setNbrCourses(\count($this->courses));
1102
1103
            return true;
1104
        }
1105
1106
        return false;
1107
    }
1108
1109
    /**
1110
     * Add a user course subscription.
1111
     * If user status in session is student, then increase number of course users.
1112
     * Status example: Session::STUDENT.
1113
     */
1114
    public function addUserInCourse(int $status, User $user, Course $course): ?SessionRelCourseRelUser
1115
    {
1116
        if ($this->hasUserInCourse($user, $course, $status)) {
1117
            return null;
1118
        }
1119
1120
        $userRelCourseRelSession = (new SessionRelCourseRelUser())
1121
            ->setCourse($course)
1122
            ->setUser($user)
1123
            ->setSession($this)
1124
            ->setStatus($status)
1125
        ;
1126
1127
        $this->addSessionRelCourseRelUser($userRelCourseRelSession);
1128
1129
        if (self::STUDENT === $status) {
1130
            $sessionCourse = $this->getCourseSubscription($course);
1131
            if ($sessionCourse) {
1132
                $sessionCourse->setNbrUsers($sessionCourse->getNbrUsers() + 1);
1133
            }
1134
        }
1135
1136
        return $userRelCourseRelSession;
1137
    }
1138
1139
    /**
1140
     * currentCourse is set in CidReqListener.
1141
     */
1142
    public function getCurrentCourse(): ?Course
1143
    {
1144
        return $this->currentCourse;
1145
    }
1146
1147
    /**
1148
     * currentCourse is set in CidReqListener.
1149
     */
1150
    public function setCurrentCourse(Course $course): self
1151
    {
1152
        // If the session is registered in the course session list.
1153
        $exists = $this->getCourses()
1154
            ->exists(
1155
                fn ($key, $element) => $course->getId() === $element->getCourse()->getId()
1156
            )
1157
        ;
1158
1159
        if ($exists) {
1160
            $this->currentCourse = $course;
1161
        }
1162
1163
        return $this;
1164
    }
1165
1166
    public function getSendSubscriptionNotification(): bool
1167
    {
1168
        return $this->sendSubscriptionNotification;
1169
    }
1170
1171
    public function setSendSubscriptionNotification(bool $sendNotification): self
1172
    {
1173
        $this->sendSubscriptionNotification = $sendNotification;
1174
1175
        return $this;
1176
    }
1177
1178
    /**
1179
     * Get user from course by status.
1180
     *
1181
     * @return Collection<int, SessionRelCourseRelUser>
1182
     */
1183
    public function getSessionRelCourseRelUsersByStatus(Course $course, int $status): Collection
1184
    {
1185
        $criteria = Criteria::create()
1186
            ->where(
1187
                Criteria::expr()->eq('course', $course)
1188
            )
1189
            ->andWhere(
1190
                Criteria::expr()->eq('status', $status)
1191
            )
1192
        ;
1193
1194
        return $this->sessionRelCourseRelUsers->matching($criteria);
1195
    }
1196
1197
    public function getSessionRelCourseRelUserInCourse(Course $course): Collection
1198
    {
1199
        $criteria = Criteria::create()
1200
            ->where(
1201
                Criteria::expr()->eq('course', $course)
1202
            )
1203
        ;
1204
1205
        return $this->sessionRelCourseRelUsers->matching($criteria);
1206
    }
1207
1208
    public function getIssuedSkills(): Collection
1209
    {
1210
        return $this->issuedSkills;
1211
    }
1212
1213
    public function getCurrentUrl(): AccessUrl
1214
    {
1215
        return $this->currentUrl;
1216
    }
1217
1218
    public function setCurrentUrl(AccessUrl $url): self
1219
    {
1220
        $urlList = $this->getUrls();
1221
        foreach ($urlList as $item) {
1222
            if ($item->getUrl()->getId() === $url->getId()) {
1223
                $this->currentUrl = $url;
1224
1225
                break;
1226
            }
1227
        }
1228
1229
        return $this;
1230
    }
1231
1232
    /**
1233
     * @return Collection<int, EntityAccessUrlInterface>
1234
     */
1235
    public function getUrls(): Collection
1236
    {
1237
        return $this->urls;
1238
    }
1239
1240
    public function setUrls(Collection $urls): self
1241
    {
1242
        $this->urls = new ArrayCollection();
1243
        foreach ($urls as $url) {
1244
            $this->addUrls($url);
1245
        }
1246
1247
        return $this;
1248
    }
1249
1250
    public function addUrls(AccessUrlRelSession $url): self
1251
    {
1252
        $url->setSession($this);
1253
        $this->urls->add($url);
1254
1255
        return $this;
1256
    }
1257
1258
    public function addAccessUrl(?AccessUrl $url): self
1259
    {
1260
        $accessUrlRelSession = new AccessUrlRelSession();
1261
        $accessUrlRelSession->setUrl($url);
1262
        $accessUrlRelSession->setSession($this);
1263
        $this->addUrls($accessUrlRelSession);
1264
1265
        return $this;
1266
    }
1267
1268
    public function getPosition(): int
1269
    {
1270
        return $this->position;
1271
    }
1272
1273
    public function setPosition(int $position): self
1274
    {
1275
        $this->position = $position;
1276
1277
        return $this;
1278
    }
1279
1280
    public function getSessionAdmins(): ReadableCollection
1281
    {
1282
        return $this->getGeneralAdminsSubscriptions()
1283
            ->map(fn (SessionRelUser $subscription) => $subscription->getUser())
1284
        ;
1285
    }
1286
1287
    public function getGeneralAdminsSubscriptions(): Collection
1288
    {
1289
        $criteria = Criteria::create()->where(Criteria::expr()->eq('relationType', self::SESSION_ADMIN));
1290
1291
        return $this->users->matching($criteria);
1292
    }
1293
1294
    public function hasUserAsSessionAdmin(User $user): bool
1295
    {
1296
        $criteria = Criteria::create()
1297
            ->where(
1298
                Criteria::expr()->eq('relationType', self::SESSION_ADMIN)
1299
            )
1300
            ->andWhere(
1301
                Criteria::expr()->eq('user', $user)
1302
            )
1303
        ;
1304
1305
        return $this->users->matching($criteria)->count() > 0;
1306
    }
1307
1308
    public function addSessionAdmin(User $sessionAdmin): self
1309
    {
1310
        return $this->addUserInSession(self::SESSION_ADMIN, $sessionAdmin);
1311
    }
1312
1313
    public function getSkills(): Collection
1314
    {
1315
        return $this->skills;
1316
    }
1317
1318
    public function getResourceLinks(): Collection
1319
    {
1320
        return $this->resourceLinks;
1321
    }
1322
1323
    public function getImage(): ?Asset
1324
    {
1325
        return $this->image;
1326
    }
1327
1328
    public function setImage(?Asset $asset): self
1329
    {
1330
        $this->image = $asset;
1331
1332
        return $this;
1333
    }
1334
1335
    public function hasImage(): bool
1336
    {
1337
        return null !== $this->image;
1338
    }
1339
1340
    public function setImageUrl(?string $imageUrl): self
1341
    {
1342
        $this->imageUrl = $imageUrl;
1343
1344
        return $this;
1345
    }
1346
1347
    public function getImageUrl(): ?string
1348
    {
1349
        $image = $this->getImage();
1350
1351
        if ($image instanceof Asset) {
1352
            $category = $image->getCategory();
1353
            $filename = $image->getTitle();
1354
1355
            return \sprintf('/assets/%s/%s/%s', $category, $filename, $filename);
1356
        }
1357
1358
        return null;
1359
    }
1360
1361
    /**
1362
     * Check if $user is course coach in any course.
1363
     */
1364
    public function hasCoachInCourseList(User $user): bool
1365
    {
1366
        foreach ($this->courses as $sessionCourse) {
1367
            if ($this->hasCourseCoachInCourse($user, $sessionCourse->getCourse())) {
1368
                return true;
1369
            }
1370
        }
1371
1372
        return false;
1373
    }
1374
1375
    public function hasCourseCoachInCourse(User $user, ?Course $course = null): bool
1376
    {
1377
        if (null === $course) {
1378
            return false;
1379
        }
1380
1381
        return $this->hasUserInCourse($user, $course, self::COURSE_COACH);
1382
    }
1383
1384
    /**
1385
     * @param int $status if not set it will check if the user is registered
1386
     *                    with any status
1387
     */
1388
    public function hasUserInCourse(User $user, Course $course, ?int $status = null): bool
1389
    {
1390
        $relation = $this->getUserInCourse($user, $course, $status);
1391
1392
        return $relation->count() > 0;
1393
    }
1394
1395
    public function getUserInCourse(User $user, Course $course, ?int $status = null): Collection
1396
    {
1397
        $criteria = Criteria::create()
1398
            ->where(
1399
                Criteria::expr()->eq('course', $course)
1400
            )
1401
            ->andWhere(
1402
                Criteria::expr()->eq('user', $user)
1403
            )
1404
        ;
1405
1406
        if (null !== $status) {
1407
            $criteria->andWhere(Criteria::expr()->eq('status', $status));
1408
        }
1409
1410
        return $this->getSessionRelCourseRelUsers()->matching($criteria);
1411
    }
1412
1413
    /**
1414
     * Check if $user is student in any course.
1415
     */
1416
    public function hasStudentInCourseList(User $user): bool
1417
    {
1418
        foreach ($this->courses as $sessionCourse) {
1419
            if ($this->hasStudentInCourse($user, $sessionCourse->getCourse())) {
1420
                return true;
1421
            }
1422
        }
1423
1424
        return false;
1425
    }
1426
1427
    public function hasStudentInCourse(User $user, Course $course): bool
1428
    {
1429
        return $this->hasUserInCourse($user, $course, self::STUDENT);
1430
    }
1431
1432
    protected function compareDates(?DateTime $start, ?DateTime $end = null): bool
1433
    {
1434
        $now = new DateTime('now');
1435
1436
        if (!empty($start) && !empty($end)) {
1437
            return $now >= $start && $now <= $end;
1438
        }
1439
1440
        if (!empty($start)) {
1441
            return $now >= $start;
1442
        }
1443
1444
        return !empty($end) && $now <= $end;
1445
    }
1446
1447
    /**
1448
     * @return Collection<int, User>
1449
     */
1450
    public function getCourseCoaches(): Collection
1451
    {
1452
        return $this->getCourseCoachesSubscriptions()
1453
            ->map(fn (SessionRelCourseRelUser $subscription) => $subscription->getUser())
1454
        ;
1455
    }
1456
1457
    /**
1458
     * @return Collection<int, SessionRelCourseRelUser>
1459
     */
1460
    #[Groups(['session:basic', 'user_subscriptions:sessions'])]
1461
    public function getCourseCoachesSubscriptions(): Collection
1462
    {
1463
        return $this->getAllUsersFromCourse(self::COURSE_COACH);
1464
    }
1465
1466
    public function isAvailableByDurationForUser(User $user): bool
1467
    {
1468
        $duration = $this->duration * 24 * 60 * 60;
1469
1470
        if (0 === $user->getTrackECourseAccess()->count()) {
1471
            return true;
1472
        }
1473
1474
        $trackECourseAccess = $user->getFirstAccessToSession($this);
1475
1476
        $firstAccess = $trackECourseAccess
1477
            ? $trackECourseAccess->getLoginCourseDate()->getTimestamp()
1478
            : 0;
1479
1480
        $userDurationData = $user->getSubscriptionToSession($this);
1481
1482
        $userDuration = $userDurationData
1483
            ? ($userDurationData->getDuration() * 24 * 60 * 60)
1484
            : 0;
1485
1486
        $totalDuration = $firstAccess + $duration + $userDuration;
1487
        $currentTime = time();
1488
1489
        return $totalDuration > $currentTime;
1490
    }
1491
1492
    public function getDaysLeftByUser(User $user): int
1493
    {
1494
        $userSessionSubscription = $user->getSubscriptionToSession($this);
1495
1496
        $duration = $this->duration;
1497
1498
        if ($userSessionSubscription) {
1499
            $duration += $userSessionSubscription->getDuration();
1500
        }
1501
1502
        $courseAccess = $user->getFirstAccessToSession($this);
1503
1504
        if (!$courseAccess) {
1505
            return $duration;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $duration could return the type null which is incompatible with the type-hinted return integer. Consider adding an additional type-check to rule them out.
Loading history...
1506
        }
1507
1508
        $endDateInSeconds = $courseAccess->getLoginCourseDate()->getTimestamp() + $duration * 24 * 60 * 60;
1509
        $currentTime = time();
1510
1511
        return (int) round(($endDateInSeconds - $currentTime) / 60 / 60 / 24);
1512
    }
1513
1514
    private function getAccessVisibilityByDuration(User $user): int
1515
    {
1516
        // Session duration per student.
1517
        if ($this->getDuration() > 0) {
1518
            if ($this->hasCoach($user)) {
1519
                return self::AVAILABLE;
1520
            }
1521
1522
            $duration = $this->getDuration() * 24 * 60 * 60;
1523
            $courseAccess = $user->getFirstAccessToSession($this);
1524
1525
            // If there is a session duration but there is no previous
1526
            // access by the user, then the session is still available
1527
            if (!$courseAccess) {
1528
                return self::AVAILABLE;
1529
            }
1530
1531
            $currentTime = time();
1532
            $firstAccess = $courseAccess->getLoginCourseDate()->getTimestamp();
1533
            $userSessionSubscription = $user->getSubscriptionToSession($this);
1534
            $userDuration = $userSessionSubscription
1535
                ? $userSessionSubscription->getDuration() * 24 * 60 * 60
1536
                : 0;
1537
1538
            $totalDuration = $firstAccess + $duration + $userDuration;
1539
1540
            return $totalDuration > $currentTime ? self::AVAILABLE : $this->visibility;
1541
        }
1542
1543
        return self::AVAILABLE;
1544
    }
1545
1546
    /**
1547
     * Checks whether the user is a course or session coach.
1548
     */
1549
    public function hasCoach(User $user): bool
1550
    {
1551
        return $this->hasUserAsGeneralCoach($user) || $this->hasCoachInCourseList($user);
1552
    }
1553
1554
    private function getAcessVisibilityByDates(User $user): int
1555
    {
1556
        $now = new DateTime();
1557
1558
        $userIsCoach = $this->hasCoach($user);
1559
1560
        $sessionEndDate = $userIsCoach && $this->coachAccessEndDate
1561
            ? $this->coachAccessEndDate
1562
            : $this->accessEndDate;
1563
1564
        if (!$userIsCoach && $this->accessStartDate && $now < $this->accessStartDate) {
1565
            return self::LIST_ONLY;
1566
        }
1567
1568
        if ($sessionEndDate) {
1569
            return $now <= $sessionEndDate ? self::AVAILABLE : $this->visibility;
1570
        }
1571
1572
        return self::AVAILABLE;
1573
    }
1574
1575
    public function setAccessVisibilityByUser(User $user, bool $ignoreVisibilityForAdmins = true): int
1576
    {
1577
        if (($user->isAdmin() || $user->isSuperAdmin()) && $ignoreVisibilityForAdmins) {
1578
            $this->accessVisibility = self::AVAILABLE;
1579
        } elseif (!$this->getAccessStartDate() && !$this->getAccessEndDate()) {
1580
            // I don't care the session visibility.
1581
            $this->accessVisibility = $this->getAccessVisibilityByDuration($user);
1582
        } else {
1583
            $this->accessVisibility = $this->getAcessVisibilityByDates($user);
1584
        }
1585
1586
        return $this->accessVisibility;
1587
    }
1588
1589
    public function getAccessVisibility(): int
1590
    {
1591
        if (0 === $this->accessVisibility) {
1592
            throw new LogicException('Access visibility by user is not set');
1593
        }
1594
1595
        return $this->accessVisibility;
1596
    }
1597
1598
    public function getClosedOrHiddenCourses(): Collection
1599
    {
1600
        $closedVisibilities = [
1601
            Course::CLOSED,
1602
            Course::HIDDEN,
1603
        ];
1604
1605
        return $this->courses->filter(fn (SessionRelCourse $sessionRelCourse) => \in_array(
1606
            $sessionRelCourse->getCourse()->getVisibility(),
1607
            $closedVisibilities
1608
        ));
1609
    }
1610
1611
    public function getParentId(): ?int
1612
    {
1613
        return $this->parentId;
1614
    }
1615
1616
    public function setParentId(?int $parentId): self
1617
    {
1618
        $this->parentId = $parentId;
1619
1620
        return $this;
1621
    }
1622
1623
    public function getDaysToReinscription(): ?int
1624
    {
1625
        return $this->daysToReinscription;
1626
    }
1627
1628
    public function setDaysToReinscription(?int $daysToReinscription): self
1629
    {
1630
        $this->daysToReinscription = $daysToReinscription ?: null;
1631
1632
        return $this;
1633
    }
1634
1635
    public function getLastRepetition(): bool
1636
    {
1637
        return $this->lastRepetition;
1638
    }
1639
1640
    public function setLastRepetition(bool $lastRepetition): self
1641
    {
1642
        $this->lastRepetition = $lastRepetition;
1643
1644
        return $this;
1645
    }
1646
1647
    public function getDaysToNewRepetition(): ?int
1648
    {
1649
        return $this->daysToNewRepetition;
1650
    }
1651
1652
    public function setDaysToNewRepetition(?int $daysToNewRepetition): self
1653
    {
1654
        $this->daysToNewRepetition = $daysToNewRepetition ?: null;
1655
1656
        return $this;
1657
    }
1658
1659
    public function getNotifyBoss(): bool
1660
    {
1661
        return $this->notifyBoss;
1662
    }
1663
1664
    public function setNotifyBoss(bool $notifyBoss): self
1665
    {
1666
        $this->notifyBoss = $notifyBoss;
1667
1668
        return $this;
1669
    }
1670
1671
    public function getValidityInDays(): ?int
1672
    {
1673
        return $this->validityInDays;
1674
    }
1675
1676
    public function setValidityInDays(?int $validityInDays): self
1677
    {
1678
        $this->validityInDays = $validityInDays ?: null;
1679
1680
        return $this;
1681
    }
1682
1683
    public function getDaysLeft(): ?int
1684
    {
1685
        return $this->daysLeft;
1686
    }
1687
1688
    public function setDaysLeft(?int $daysLeft): self
1689
    {
1690
        $this->daysLeft = $daysLeft;
1691
1692
        return $this;
1693
    }
1694
}
1695