Passed
Push — master ( c12494...619086 )
by Julito
15:29
created

Session   F

Complexity

Total Complexity 130

Size/Duplication

Total Lines 1088
Duplicated Lines 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
eloc 310
dl 0
loc 1088
rs 2
c 1
b 1
f 0
wmc 130

91 Methods

Rating   Name   Duplication   Size   Complexity  
A addUser() 0 6 2
A getUsers() 0 3 1
A setDuration() 0 5 1
A getDuration() 0 3 1
A getDisplayEndDate() 0 3 1
A getStatusList() 0 7 1
A isCurrentlyAccessible() 0 10 5
A isActiveForCoach() 0 6 1
A setVisibility() 0 5 1
A getCoachAccessEndDate() 0 3 1
A getCategory() 0 3 1
A setDisplayEndDate() 0 5 1
A setAccessStartDate() 0 5 1
A setCategory() 0 5 1
A getVisibility() 0 3 1
A getCurrentCourse() 0 3 1
A getCoachAccessStartDate() 0 3 1
A getPromotion() 0 3 1
A addUserInCourse() 0 12 2
A setCoachAccessEndDate() 0 5 1
A setPromotion() 0 5 1
A getDisplayStartDate() 0 3 1
A setCoachAccessStartDate() 0 5 1
A removeCourse() 0 11 2
A getNbrClasses() 0 3 1
A setAccessEndDate() 0 5 1
A addUserCourseSubscription() 0 5 2
A setUserCourseSubscriptions() 0 9 2
A addCourse() 0 5 1
A isActive() 0 5 1
A getGeneralCoach() 0 3 1
A hasUserCourseSubscription() 0 16 2
A getUserCourseSubscriptions() 0 3 1
A getAccessStartDate() 0 3 1
A setGeneralCoach() 0 5 1
A getCourseSubscription() 0 7 1
A isActiveForStudent() 0 6 1
A setDisplayStartDate() 0 5 1
A getAccessEndDate() 0 3 1
A removeCourses() 0 5 3
A getNbrUsers() 0 3 1
A addCourses() 0 4 1
A hasCourse() 0 12 2
A isRelatedToCourse() 0 5 1
A hasUserInCourse() 0 5 1
A setDescription() 0 5 1
A removeUserCourseSubscription() 0 15 5
A getCoursesByUser() 0 15 2
A hasStudentInCourse() 0 3 1
A getNbrCourses() 0 3 1
A setNbrCourses() 0 5 1
A setNbrClasses() 0 5 1
A setNbrUsers() 0 5 1
A hasUser() 0 17 2
A getUserInCourse() 0 16 2
A hasCoachInCourseWithStatus() 0 7 2
A getDescription() 0 3 1
A setName() 0 5 1
A setCourses() 0 6 2
A getCourses() 0 3 1
A getName() 0 3 1
A getUrls() 0 3 1
A setCurrentUrl() 0 12 3
A getCurrentUrl() 0 3 1
A getUserCourseSubscriptionsByStatus() 0 12 1
A getIssuedSkills() 0 3 1
A getSendSubscriptionNotification() 0 3 1
A setSendSubscriptionNotification() 0 5 1
A setCurrentCourse() 0 15 2
A getId() 0 3 1
A getSessionAdmin() 0 3 1
A setStatus() 0 5 1
A addAccessUrl() 0 9 1
A getStatus() 0 3 1
A setUrls() 0 9 2
A __toString() 0 3 1
A getPosition() 0 3 1
A addUrls() 0 6 1
A __construct() 0 28 1
A setUsers() 0 9 2
B compareDates() 0 13 8
A getSkills() 0 3 1
A hasStudentInCourseList() 0 9 3
A setPosition() 0 5 1
A getShowDescription() 0 3 1
A setShowDescription() 0 5 1
A addUserInSession() 0 10 1
A isUserGeneralCoach() 0 5 2
A hasCoachInCourseList() 0 9 3
A setSessionAdmin() 0 5 1
A getResourceLinks() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Session often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Session, and based on these observations, apply Extract Interface, too.

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