Passed
Push — master ( 41fa80...398a1a )
by Angel Fernando Quiroz
07:48
created

Session   F

Complexity

Total Complexity 140

Size/Duplication

Total Lines 1232
Duplicated Lines 0 %

Importance

Changes 5
Bugs 1 Features 0
Metric Value
eloc 533
c 5
b 1
f 0
dl 0
loc 1232
rs 2
wmc 140

103 Methods

Rating   Name   Duplication   Size   Complexity  
A setNbrClasses() 0 5 1
A getAccessStartDate() 0 3 1
A getNbrCourses() 0 3 1
A getDisplayStartDate() 0 3 1
A setNbrUsers() 0 5 1
A addUrls() 0 6 1
A getSendSubscriptionNotification() 0 3 1
A hasCoachInCourseList() 0 9 3
A getId() 0 3 1
A getDisplayEndDate() 0 3 1
A removeCourses() 0 5 3
A getStatusList() 0 7 1
A removeUserSubscription() 0 9 2
A setStatus() 0 5 1
A setVisibility() 0 5 1
A getStatus() 0 3 1
A getDuration() 0 3 1
A setSessionRelCourseRelUsers() 0 8 2
A getNbrUsers() 0 3 1
A addCourses() 0 4 1
A getCategory() 0 3 1
A setDisplayEndDate() 0 5 1
A addGeneralCoach() 0 3 1
A getAllUsersFromCourse() 0 5 1
A hasCourse() 0 10 2
A __toString() 0 3 1
A hasUserAsGeneralCoach() 0 12 1
A setAccessStartDate() 0 5 1
A __construct() 0 27 1
A getRelationTypeList() 0 3 1
A setCategory() 0 5 1
A setUsers() 0 8 2
A getSessionRelCourseByUser() 0 8 2
A getSessionRelCourseRelUsers() 0 3 1
A getVisibility() 0 3 1
A getGeneralCoachesSubscriptions() 0 6 1
A getTitle() 0 3 1
A setDescription() 0 5 1
A removeUserCourseSubscription() 0 12 5
A getPromotion() 0 3 1
A setPromotion() 0 5 1
A addSessionRelCourseRelUser() 0 5 2
A removeGeneralCoach() 0 5 1
A setNbrCourses() 0 5 1
A getNbrClasses() 0 3 1
A setShowDescription() 0 5 1
A getShowDescription() 0 3 1
A getGeneralCoaches() 0 4 1
A addUserInSession() 0 6 1
A isActive() 0 5 1
A removeUserInSession() 0 17 2
A hasUserCourseSubscription() 0 20 2
A hasUser() 0 20 2
A setDuration() 0 5 1
A getDescription() 0 3 1
A setTitle() 0 5 1
A getCourseSubscription() 0 5 1
A setDisplayStartDate() 0 5 1
A setCourses() 0 5 2
A addUserSubscription() 0 6 2
A getCourses() 0 3 1
A getUsers() 0 3 1
A getCourseCoachesSubscriptions() 0 4 1
A setImage() 0 5 1
A getUrls() 0 3 1
A isCurrentlyAccessible() 0 6 4
A addAccessUrl() 0 8 1
A isActiveForCoach() 0 7 1
A getCoachAccessEndDate() 0 3 1
A setUrls() 0 8 2
A hasUserInCourse() 0 5 1
A getPosition() 0 3 1
A getSessionAdmins() 0 4 1
A hasImage() 0 3 1
A hasUserAsSessionAdmin() 0 12 1
A setCurrentUrl() 0 12 3
A getCurrentCourse() 0 3 1
A getCurrentUrl() 0 3 1
A getIssuedSkills() 0 3 1
A getCoachAccessStartDate() 0 3 1
A hasCourseCoachInCourse() 0 7 2
A addUserInCourse() 0 17 2
A setCoachAccessEndDate() 0 5 1
A getSkills() 0 3 1
A hasStudentInCourse() 0 3 1
A hasStudentInCourseList() 0 9 3
A setPosition() 0 5 1
A setSendSubscriptionNotification() 0 5 1
A setCoachAccessStartDate() 0 5 1
A removeCourse() 0 11 2
A setAccessEndDate() 0 5 1
A getSessionRelCourseRelUsersByStatus() 0 12 1
A addCourse() 0 6 1
A addSessionAdmin() 0 3 1
A getGeneralAdminsSubscriptions() 0 5 1
A getUserInCourse() 0 16 2
A setCurrentCourse() 0 14 2
A getImage() 0 3 1
A isActiveForStudent() 0 7 1
A getResourceLinks() 0 3 1
A getSessionRelCourseRelUserInCourse() 0 9 1
A getAccessEndDate() 0 3 1
A compareDates() 0 13 6

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