Passed
Push — master ( dc38fb...7b9cc4 )
by Angel Fernando Quiroz
09:43 queued 19s
created

Course   F

Complexity

Total Complexity 127

Size/Duplication

Total Lines 1149
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 432
dl 0
loc 1149
rs 2
c 4
b 0
f 0
wmc 127

112 Methods

Rating   Name   Duplication   Size   Complexity  
A getUsers() 0 3 1
A __toString() 0 3 1
A getDirectory() 0 3 1
A getId() 0 3 1
A getCode() 0 3 1
A getTrackCourseRanking() 0 3 1
A setTools() 0 7 2
A addSubscriptionForUser() 0 11 1
A removeSubscription() 0 5 3
A __construct() 0 34 1
A hasSubscriptionByUser() 0 13 2
A addTool() 0 6 1
A hasUsers() 0 20 2
A setTrackCourseRanking() 0 5 1
A getStatusList() 0 8 1
A hasUserAsStudent() 0 5 1
A addSubscription() 0 8 2
A setTitle() 0 9 2
A getStudentSubscriptions() 0 6 1
A getTitle() 0 3 1
A getTools() 0 3 1
A addUserAsStudent() 0 5 1
A getUrls() 0 3 1
A getCurrentSession() 0 3 1
A getRoom() 0 3 1
A getExpirationDate() 0 3 1
A setTutorName() 0 5 1
A getVisualCode() 0 3 1
A setRegistrationCode() 0 5 1
A setLastEdit() 0 5 1
A isHidden() 0 3 1
A getVisibility() 0 3 1
A setCourseLanguage() 0 5 1
A hasGroup() 0 2 1
A setLegal() 0 5 1
A getShowScore() 0 3 1
A getLastEdit() 0 3 1
A setCategories() 0 5 1
A setExpirationDate() 0 5 1
A setCurrentSession() 0 18 3
A getDescription() 0 3 1
A getTutorName() 0 3 1
A getSessions() 0 3 1
A setSubscribe() 0 5 1
A setCreationDate() 0 5 1
A getLastVisit() 0 3 1
A getDiskQuota() 0 3 1
A getRegistrationCode() 0 3 1
A getCurrentUrl() 0 3 1
A hasUserAsTeacher() 0 13 2
A setDepartmentUrl() 0 5 1
A setRoom() 0 5 1
A setVisibility() 0 5 1
A getActivateLegal() 0 3 1
A setCode() 0 6 1
A isPublic() 0 3 1
A addCategory() 0 5 1
A setCourseTypeId() 0 5 1
A addUserAsTeacher() 0 5 1
A setVisualCode() 0 5 1
A getDepartmentName() 0 3 1
A getTeachersSubscriptions() 0 13 3
A setDepartmentName() 0 5 1
A getCreationDate() 0 3 1
A setCurrentUrl() 0 14 3
A getCategories() 0 3 1
A getCourseTypeId() 0 3 1
A setShowScore() 0 5 1
A removeCategory() 0 3 1
A setDescription() 0 5 1
A getCourseLanguage() 0 3 1
A setDiskQuota() 0 5 1
A getLegal() 0 3 1
A getUnsubscribe() 0 3 1
A setLastVisit() 0 5 1
A getSubscribe() 0 3 1
A getTitleAndCode() 0 3 1
A setUnsubscribe() 0 5 1
A setActivateLegal() 0 5 1
A isActive() 0 5 1
A getDepartmentUrl() 0 3 1
A isAddTeachersToSessionsCourses() 0 3 1
A setAddTeachersToSessionsCourses() 0 5 1
A setGradebookLinks() 0 5 1
A setVideoUrl() 0 5 1
A getDefaultIllustration() 0 3 1
A getResourceName() 0 3 1
A getSkills() 0 3 1
A getGradebookEvaluations() 0 3 1
A getTrackEHotspots() 0 3 1
A setGradebookEvaluations() 0 5 1
A getGradebookCategories() 0 3 1
A getGradebookLinks() 0 3 1
A setSessionRelCourseRelUsers() 0 5 1
A getSessionRelCourseRelUsers() 0 3 1
A getVideoUrl() 0 3 1
A setSearchEngineRefs() 0 5 1
A setResourceName() 0 3 1
A setSticky() 0 5 1
A getSearchEngineRefs() 0 3 1
A setTrackEHotspots() 0 5 1
A getTemplates() 0 3 1
A setSkills() 0 5 1
A setTemplates() 0 5 1
A addAccessUrl() 0 6 1
A addUrls() 0 8 2
A isSticky() 0 3 1
A setIntroduction() 0 5 1
A getIssuedSkills() 0 3 1
A setGradebookCategories() 0 5 1
A getResourceIdentifier() 0 3 1
A getIntroduction() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like Course 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 Course, 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\Doctrine\Orm\Filter\OrderFilter;
10
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
11
use ApiPlatform\Metadata\ApiFilter;
12
use ApiPlatform\Metadata\ApiProperty;
13
use ApiPlatform\Metadata\ApiResource;
14
use ApiPlatform\Metadata\Get;
15
use ApiPlatform\Metadata\GetCollection;
16
use ApiPlatform\Metadata\Post;
17
use Chamilo\CoreBundle\Entity\Listener\CourseListener;
18
use Chamilo\CoreBundle\Entity\Listener\ResourceListener;
19
use Chamilo\CoreBundle\Repository\Node\CourseRepository;
20
use Chamilo\CourseBundle\Entity\CGroup;
21
use Chamilo\CourseBundle\Entity\CTool;
22
use DateTime;
23
use Doctrine\Common\Collections\ArrayCollection;
24
use Doctrine\Common\Collections\Collection;
25
use Doctrine\Common\Collections\Criteria;
26
use Doctrine\ORM\Mapping as ORM;
27
use Gedmo\Mapping\Annotation as Gedmo;
28
use Stringable;
29
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
30
use Symfony\Component\Serializer\Annotation\Groups;
31
use Symfony\Component\Serializer\Annotation\SerializedName;
32
use Symfony\Component\Validator\Constraints as Assert;
33
34
#[ApiResource(
35
    types: ['https://schema.org/Course'],
36
    operations: [
37
        new Get(security: "is_granted('VIEW', object)"),
38
        new Post(),
39
        new GetCollection(),
40
    ],
41
    normalizationContext: [
42
        'groups' => ['course:read'],
43
    ],
44
    denormalizationContext: [
45
        'groups' => ['course:write'],
46
    ],
47
    filters: [
48
        'course.sticky_boolean_filter',
49
    ],
50
    security: "is_granted('ROLE_USER')"
51
)]
52
#[ORM\Table(name: 'course')]
53
#[UniqueEntity('code')]
54
#[UniqueEntity('visualCode')]
55
#[ORM\Entity(repositoryClass: CourseRepository::class)]
56
#[ORM\EntityListeners([ResourceListener::class, CourseListener::class])]
57
#[ApiFilter(filterClass: SearchFilter::class, properties: ['title' => 'partial', 'code' => 'partial'])]
58
#[ApiFilter(filterClass: OrderFilter::class, properties: ['id', 'title'])]
59
class Course extends AbstractResource implements ResourceInterface, ResourceWithAccessUrlInterface, ResourceIllustrationInterface, ExtraFieldItemInterface, Stringable
60
{
61
    public const CLOSED = 0;
62
    public const REGISTERED = 1;
63
    // Only registered users in the course.
64
    public const OPEN_PLATFORM = 2;
65
    // All users registered in the platform (default).
66
    public const OPEN_WORLD = 3;
67
    public const HIDDEN = 4;
68
69
    #[Groups([
70
        'course:read',
71
        'course_rel_user:read',
72
        'session:read',
73
        'session_rel_course_rel_user:read',
74
        'session_rel_user:read',
75
        'session_rel_course:read',
76
        'track_e_exercise:read',
77
    ])]
78
    #[ORM\Column(name: 'id', type: 'integer')]
79
    #[ORM\Id]
80
    #[ORM\GeneratedValue(strategy: 'AUTO')]
81
    protected ?int $id = null;
82
83
    /**
84
     * The course title.
85
     */
86
    #[Groups([
87
        'course:read',
88
        'course:write',
89
        'course_rel_user:read',
90
        'session:read',
91
        'session_rel_course_rel_user:read',
92
        'session_rel_user:read',
93
        'session_rel_course:read',
94
        'track_e_exercise:read',
95
    ])]
96
    #[Assert\NotBlank(message: 'A Course requires a title')]
97
    #[ORM\Column(name: 'title', type: 'string', length: 250, unique: false, nullable: true)]
98
    protected ?string $title = null;
99
100
    /**
101
     * The course code.
102
     */
103
    #[ApiProperty(iris: ['http://schema.org/courseCode'])]
104
    #[Groups(['course:read', 'user:write', 'course_rel_user:read'])]
105
    #[Assert\NotBlank]
106
    #[Assert\Length(max: 40, maxMessage: 'Code cannot be longer than {{ limit }} characters')]
107
    #[Gedmo\Slug(fields: ['title'], updatable: false, style: 'upper', unique: true, separator: '')]
108
    #[ORM\Column(name: 'code', type: 'string', length: 40, unique: true, nullable: false)]
109
    protected string $code;
110
111
    #[Assert\Length(max: 40, maxMessage: 'Code cannot be longer than {{ limit }} characters')]
112
    #[ORM\Column(name: 'visual_code', type: 'string', length: 40, unique: false, nullable: true)]
113
    protected ?string $visualCode = null;
114
115
    /**
116
     * @var Collection<int, CourseRelUser>
117
     */
118
    #[Groups([
119
        'course:read',
120
        'user:read',
121
        'course_rel_user:read',
122
    ])]
123
    #[ORM\OneToMany(mappedBy: 'course', targetEntity: CourseRelUser::class, cascade: ['persist'], orphanRemoval: true)]
124
    protected Collection $users;
125
126
    /**
127
     * @var Collection<int, EntityAccessUrlInterface>
128
     */
129
    #[ORM\OneToMany(
130
        mappedBy: 'course',
131
        targetEntity: AccessUrlRelCourse::class,
132
        cascade: ['persist', 'remove'],
133
        orphanRemoval: true
134
    )]
135
    protected Collection $urls;
136
137
    /**
138
     * @var Collection<int, SessionRelCourse>
139
     */
140
    #[ORM\OneToMany(mappedBy: 'course', targetEntity: SessionRelCourse::class, cascade: ['persist', 'remove'])]
141
    protected Collection $sessions;
142
143
    /**
144
     * @var Collection<int, SessionRelCourseRelUser>
145
     */
146
    #[ORM\OneToMany(mappedBy: 'course', targetEntity: SessionRelCourseRelUser::class, cascade: [
147
        'persist',
148
        'remove',
149
    ])]
150
    protected Collection $sessionRelCourseRelUsers;
151
152
    /**
153
     * @var Collection<int, CTool>
154
     */
155
    #[ORM\OneToMany(
156
        mappedBy: 'course',
157
        targetEntity: CTool::class,
158
        cascade: [
159
            'persist',
160
            'remove',
161
        ],
162
        orphanRemoval: true
163
    )]
164
    protected Collection $tools;
165
166
    #[Groups(['course:read'])]
167
    #[ORM\OneToOne(
168
        mappedBy: 'course',
169
        targetEntity: TrackCourseRanking::class,
170
        cascade: [
171
            'persist',
172
            'remove',
173
        ],
174
        orphanRemoval: true
175
    )]
176
    protected ?TrackCourseRanking $trackCourseRanking = null;
177
178
    protected Session $currentSession;
179
180
    protected AccessUrl $currentUrl;
181
182
    /**
183
     * @var Collection<int, SkillRelCourse>
184
     */
185
    #[ORM\OneToMany(mappedBy: 'course', targetEntity: SkillRelCourse::class, cascade: ['persist', 'remove'])]
186
    protected Collection $skills;
187
188
    /**
189
     * @var Collection<int, SkillRelUser>
190
     */
191
    #[ORM\OneToMany(mappedBy: 'course', targetEntity: SkillRelUser::class, cascade: ['persist', 'remove'])]
192
    protected Collection $issuedSkills;
193
194
    /**
195
     * @var Collection<int, GradebookCategory>
196
     */
197
    #[ORM\OneToMany(mappedBy: 'course', targetEntity: GradebookCategory::class, cascade: ['persist', 'remove'])]
198
    protected Collection $gradebookCategories;
199
200
    /**
201
     * @var Collection<int, GradebookEvaluation>
202
     */
203
    #[ORM\OneToMany(mappedBy: 'course', targetEntity: GradebookEvaluation::class, cascade: ['persist', 'remove'])]
204
    protected Collection $gradebookEvaluations;
205
206
    /**
207
     * @var Collection<int, GradebookLink>
208
     */
209
    #[ORM\OneToMany(mappedBy: 'course', targetEntity: GradebookLink::class, cascade: ['persist', 'remove'])]
210
    protected Collection $gradebookLinks;
211
212
    /**
213
     * @var Collection<int, TrackEHotspot>
214
     */
215
    #[ORM\OneToMany(mappedBy: 'course', targetEntity: TrackEHotspot::class, cascade: ['persist', 'remove'])]
216
    protected Collection $trackEHotspots;
217
218
    /**
219
     * @var Collection<int, SearchEngineRef>
220
     */
221
    #[ORM\OneToMany(mappedBy: 'course', targetEntity: SearchEngineRef::class, cascade: ['persist', 'remove'])]
222
    protected Collection $searchEngineRefs;
223
224
    /**
225
     * @var Collection<int, Templates>
226
     */
227
    #[ORM\OneToMany(mappedBy: 'course', targetEntity: Templates::class, cascade: ['persist', 'remove'])]
228
    protected Collection $templates;
229
230
    /**
231
     * ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\SpecificFieldValues", mappedBy="course").
232
     */
233
    // protected $specificFieldValues;
234
235
    /**
236
     * ORM\OneToMany(targetEntity="Chamilo\CoreBundle\Entity\SharedSurvey", mappedBy="course").
237
     */
238
    // protected $sharedSurveys;
239
240
    #[ORM\Column(name: 'directory', type: 'string', length: 40, unique: false, nullable: true)]
241
    protected ?string $directory = null;
242
243
    #[Groups(['course:read', 'session:read'])]
244
    #[Assert\NotBlank]
245
    #[ORM\Column(name: 'course_language', type: 'string', length: 20, unique: false, nullable: false)]
246
    protected string $courseLanguage;
247
248
    #[Groups(['course:read', 'course_rel_user:read'])]
249
    #[ORM\Column(name: 'description', type: 'text', unique: false, nullable: true)]
250
    protected ?string $description;
251
252
    #[Groups(['course:read', 'course_rel_user:read'])]
253
    #[ORM\Column(name: 'introduction', type: 'text', nullable: true)]
254
    protected ?string $introduction;
255
256
    /**
257
     * @var Collection<int, CourseCategory>
258
     */
259
    #[Groups(['course:read', 'course:write', 'course_rel_user:read', 'session:read'])]
260
    #[ORM\JoinTable(name: 'course_rel_category')]
261
    #[ORM\JoinColumn(name: 'course_id', referencedColumnName: 'id')]
262
    #[ORM\InverseJoinColumn(name: 'course_category_id', referencedColumnName: 'id')]
263
    #[ORM\ManyToMany(targetEntity: CourseCategory::class, inversedBy: 'courses')]
264
    protected Collection $categories;
265
266
    #[Assert\NotBlank]
267
    #[Groups(['course:read', 'course:write'])]
268
    #[ORM\Column(name: 'visibility', type: 'integer', unique: false, nullable: false)]
269
    protected int $visibility;
270
271
    #[ORM\Column(name: 'show_score', type: 'integer', unique: false, nullable: true)]
272
    protected ?int $showScore = null;
273
274
    #[ORM\Column(name: 'tutor_name', type: 'string', length: 200, unique: false, nullable: true)]
275
    protected ?string $tutorName;
276
277
    #[Groups(['course:read'])]
278
    #[ORM\Column(name: 'department_name', type: 'string', length: 30, unique: false, nullable: true)]
279
    protected ?string $departmentName = null;
280
281
    #[Assert\Url]
282
    #[Groups(['course:read', 'course:write'])]
283
    #[ORM\Column(name: 'department_url', type: 'string', length: 180, unique: false, nullable: true)]
284
    protected ?string $departmentUrl = null;
285
286
    #[Assert\Url]
287
    #[Groups(['course:read', 'course:write'])]
288
    #[ORM\Column(name: 'video_url', type: 'string', length: 255)]
289
    protected string $videoUrl;
290
291
    #[Groups(['course:read', 'course:write'])]
292
    #[ORM\Column(name: 'sticky', type: 'boolean')]
293
    protected bool $sticky;
294
295
    #[ORM\Column(name: 'disk_quota', type: 'integer', unique: false, nullable: true)]
296
    protected ?int $diskQuota = null;
297
298
    #[ORM\Column(name: 'last_visit', type: 'datetime', unique: false, nullable: true)]
299
    protected ?DateTime $lastVisit;
300
301
    #[ORM\Column(name: 'last_edit', type: 'datetime', unique: false, nullable: true)]
302
    protected ?DateTime $lastEdit;
303
304
    #[ORM\Column(name: 'creation_date', type: 'datetime', unique: false, nullable: false)]
305
    protected DateTime $creationDate;
306
307
    #[Groups(['course:read'])]
308
    #[ORM\Column(name: 'expiration_date', type: 'datetime', unique: false, nullable: true)]
309
    protected ?DateTime $expirationDate = null;
310
311
    #[Assert\NotNull]
312
    #[ORM\Column(name: 'subscribe', type: 'boolean', unique: false, nullable: false)]
313
    protected bool $subscribe;
314
315
    #[Assert\NotNull]
316
    #[ORM\Column(name: 'unsubscribe', type: 'boolean', unique: false, nullable: false)]
317
    protected bool $unsubscribe;
318
319
    #[ORM\Column(name: 'registration_code', type: 'string', length: 255, unique: false, nullable: true)]
320
    protected ?string $registrationCode;
321
322
    #[ORM\Column(name: 'legal', type: 'text', unique: false, nullable: true)]
323
    protected ?string $legal;
324
325
    #[ORM\Column(name: 'activate_legal', type: 'integer', unique: false, nullable: true)]
326
    protected ?int $activateLegal;
327
328
    #[ORM\Column(name: 'add_teachers_to_sessions_courses', type: 'boolean', nullable: true)]
329
    protected ?bool $addTeachersToSessionsCourses;
330
331
    #[ORM\Column(name: 'course_type_id', type: 'integer', unique: false, nullable: true)]
332
    protected ?int $courseTypeId;
333
334
    /**
335
     * ORM\OneToMany(targetEntity="CurriculumCategory", mappedBy="course").
336
     */
337
    // protected $curriculumCategories;
338
339
    #[ORM\ManyToOne(targetEntity: Room::class)]
340
    #[ORM\JoinColumn(name: 'room_id', referencedColumnName: 'id')]
341
    protected ?Room $room;
342
343
    public function __construct()
344
    {
345
        $this->visibility = self::OPEN_PLATFORM;
346
        $this->sessions = new ArrayCollection();
347
        $this->sessionRelCourseRelUsers = new ArrayCollection();
348
        $this->skills = new ArrayCollection();
349
        $this->issuedSkills = new ArrayCollection();
350
        $this->creationDate = new DateTime();
351
        $this->lastVisit = new DateTime();
352
        $this->lastEdit = new DateTime();
353
        $this->description = '';
354
        $this->introduction = '';
355
        $this->tutorName = '';
356
        $this->legal = '';
357
        $this->videoUrl = '';
358
        $this->registrationCode = null;
359
        $this->users = new ArrayCollection();
360
        $this->urls = new ArrayCollection();
361
        $this->tools = new ArrayCollection();
362
        $this->categories = new ArrayCollection();
363
        $this->gradebookCategories = new ArrayCollection();
364
        $this->gradebookEvaluations = new ArrayCollection();
365
        $this->gradebookLinks = new ArrayCollection();
366
        $this->trackEHotspots = new ArrayCollection();
367
        $this->searchEngineRefs = new ArrayCollection();
368
        $this->templates = new ArrayCollection();
369
        $this->activateLegal = 0;
370
        $this->addTeachersToSessionsCourses = false;
371
        $this->courseTypeId = null;
372
        $this->room = null;
373
        $this->courseLanguage = 'en';
374
        $this->subscribe = true;
375
        $this->unsubscribe = false;
376
        $this->sticky = false;
377
        // $this->specificFieldValues = new ArrayCollection();
378
        // $this->sharedSurveys = new ArrayCollection();
379
    }
380
381
    public function __toString(): string
382
    {
383
        return $this->getTitle();
384
    }
385
386
    public static function getStatusList(): array
387
    {
388
        return [
389
            self::CLOSED => 'Closed',
390
            self::REGISTERED => 'Registered',
391
            self::OPEN_PLATFORM => 'Open platform',
392
            self::OPEN_WORLD => 'Open world',
393
            self::HIDDEN => 'Hidden',
394
        ];
395
    }
396
397
    public function getTitle(): string
398
    {
399
        return $this->title;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->title could return the type null which is incompatible with the type-hinted return string. Consider adding an additional type-check to rule them out.
Loading history...
400
    }
401
402
    public function setTitle(string $title): self
403
    {
404
        $this->title = $title;
405
        // Set the code based in the title if it doesnt exists.
406
        if (empty($this->code)) {
407
            $this->setCode($title);
408
        }
409
410
        return $this;
411
    }
412
413
    /**
414
     * @return Collection<int, CTool>
415
     */
416
    public function getTools(): Collection
417
    {
418
        return $this->tools;
419
    }
420
421
    public function setTools(array $tools): self
422
    {
423
        foreach ($tools as $tool) {
424
            $this->addTool($tool);
425
        }
426
427
        return $this;
428
    }
429
430
    public function addTool(CTool $tool): self
431
    {
432
        $tool->setCourse($this);
433
        $this->tools->add($tool);
434
435
        return $this;
436
    }
437
438
    public function getTrackCourseRanking(): ?TrackCourseRanking
439
    {
440
        return $this->trackCourseRanking;
441
    }
442
443
    public function setTrackCourseRanking(?TrackCourseRanking $trackCourseRanking): self
444
    {
445
        $this->trackCourseRanking = $trackCourseRanking;
446
447
        return $this;
448
    }
449
450
    public function hasSubscriptionByUser(User $user): bool
451
    {
452
        $users = $this->getUsers();
453
454
        if (0 === $users->count()) {
455
            return false;
456
        }
457
458
        $matching = $users->filter(
459
            fn (CourseRelUser $subscription) => $subscription->getUser()->getId() === $user->getId()
460
        );
461
462
        return $matching->count() > 0;
463
    }
464
465
    /**
466
     * @return Collection<int, CourseRelUser>
467
     */
468
    public function getUsers(): Collection
469
    {
470
        return $this->users;
471
    }
472
473
    public function addSubscription(CourseRelUser $courseRelUser): self
474
    {
475
        $courseRelUser->setCourse($this);
476
        if (!$this->hasUsers($courseRelUser)) {
477
            $this->users->add($courseRelUser);
478
        }
479
480
        return $this;
481
    }
482
483
    public function removeSubscription(CourseRelUser $user): void
484
    {
485
        foreach ($this->users as $key => $value) {
486
            if ($value->getId() === $user->getId()) {
487
                unset($this->users[$key]);
488
            }
489
        }
490
    }
491
492
    public function hasUsers(CourseRelUser $subscription): bool
493
    {
494
        if (0 !== $this->users->count()) {
495
            $criteria = Criteria::create()
496
                ->where(
497
                    Criteria::expr()->eq('user', $subscription->getUser())
498
                )
499
                ->andWhere(
500
                    Criteria::expr()->eq('status', $subscription->getStatus())
501
                )
502
                ->andWhere(
503
                    Criteria::expr()->eq('relationType', $subscription->getRelationType())
504
                )
505
            ;
506
            $relation = $this->users->matching($criteria);
507
508
            return $relation->count() > 0;
509
        }
510
511
        return false;
512
    }
513
514
    public function addSubscriptionForUser(User $user, int $relationType, ?string $role, int $status): self
515
    {
516
        $courseRelUser = (new CourseRelUser())
517
            ->setCourse($this)
518
            ->setUser($user)
519
            ->setRelationType($relationType)
520
            ->setStatus($status)
521
        ;
522
        $this->addSubscription($courseRelUser);
523
524
        return $this;
525
    }
526
527
    public function hasUserAsStudent(User $user): bool
528
    {
529
        $criteria = Criteria::create()->where(Criteria::expr()->eq('user', $user));
530
531
        return $this->getStudentSubscriptions()->matching($criteria)->count() > 0;
532
    }
533
534
    public function getStudentSubscriptions(): Collection
535
    {
536
        $criteria = Criteria::create();
537
        $criteria->where(Criteria::expr()->eq('status', CourseRelUser::STUDENT));
538
539
        return $this->users->matching($criteria);
540
    }
541
542
    public function addUserAsStudent(User $user): self
543
    {
544
        $this->addSubscriptionForUser($user, 0, '', CourseRelUser::STUDENT);
545
546
        return $this;
547
    }
548
549
    public function hasUserAsTeacher(User $user): bool
550
    {
551
        $users = $this->getTeachersSubscriptions();
552
553
        if (0 === $users->count()) {
554
            return false;
555
        }
556
557
        $matching = $users->filter(
558
            fn (CourseRelUser $subscription) => $subscription->getUser()->getId() === $user->getId()
559
        );
560
561
        return $matching->count() > 0;
562
    }
563
564
    #[SerializedName('teachers')]
565
    #[Groups(['course:read'])]
566
    public function getTeachersSubscriptions(): Collection
567
    {
568
        $teacherSubscriptions = new ArrayCollection();
569
570
        foreach ($this->users as $subscription) {
571
            if (CourseRelUser::TEACHER === $subscription->getStatus()) {
572
                $teacherSubscriptions->add($subscription);
573
            }
574
        }
575
576
        return $teacherSubscriptions;
577
    }
578
579
    public function addUserAsTeacher(User $user): self
580
    {
581
        $this->addSubscriptionForUser($user, 0, 'Trainer', CourseRelUser::TEACHER);
582
583
        return $this;
584
    }
585
586
    public function hasGroup(CGroup $group): void
587
    {
588
        /*$criteria = Criteria::create()->where(
589
              Criteria::expr()->eq('groups', $group)
590
          );*/
591
        // return $this->getGroups()->contains($group);
592
    }
593
594
    public function getId(): ?int
595
    {
596
        return $this->id;
597
    }
598
599
    /**
600
     * Get directory, needed in migrations.
601
     */
602
    public function getDirectory(): ?string
603
    {
604
        return $this->directory;
605
    }
606
607
    public function getCourseLanguage(): string
608
    {
609
        return $this->courseLanguage;
610
    }
611
612
    public function setCourseLanguage(string $courseLanguage): self
613
    {
614
        $this->courseLanguage = $courseLanguage;
615
616
        return $this;
617
    }
618
619
    public function getTitleAndCode(): string
620
    {
621
        return $this->getTitle().' ('.$this->getCode().')';
622
    }
623
624
    public function getCode(): string
625
    {
626
        return $this->code;
627
    }
628
629
    public function setCode(string $code): self
630
    {
631
        $this->code = $code;
632
        $this->visualCode = $code;
633
634
        return $this;
635
    }
636
637
    public function getDescription(): ?string
638
    {
639
        return $this->description;
640
    }
641
642
    public function setDescription(string $description): self
643
    {
644
        $this->description = $description;
645
646
        return $this;
647
    }
648
649
    /**
650
     * @return Collection<int, CourseCategory>
651
     */
652
    public function getCategories(): Collection
653
    {
654
        return $this->categories;
655
    }
656
657
    public function setCategories(Collection $categories): self
658
    {
659
        $this->categories = $categories;
660
661
        return $this;
662
    }
663
664
    public function addCategory(CourseCategory $category): self
665
    {
666
        $this->categories[] = $category;
667
668
        return $this;
669
    }
670
671
    public function removeCategory(CourseCategory $category): void
672
    {
673
        $this->categories->removeElement($category);
674
    }
675
676
    public function getVisibility(): int
677
    {
678
        return $this->visibility;
679
    }
680
681
    public function setVisibility(int $visibility): self
682
    {
683
        $this->visibility = $visibility;
684
685
        return $this;
686
    }
687
688
    public function getShowScore(): ?int
689
    {
690
        return $this->showScore;
691
    }
692
693
    public function setShowScore(int $showScore): self
694
    {
695
        $this->showScore = $showScore;
696
697
        return $this;
698
    }
699
700
    public function getTutorName(): ?string
701
    {
702
        return $this->tutorName;
703
    }
704
705
    public function setTutorName(?string $tutorName): self
706
    {
707
        $this->tutorName = $tutorName;
708
709
        return $this;
710
    }
711
712
    public function getVisualCode(): ?string
713
    {
714
        return $this->visualCode;
715
    }
716
717
    public function setVisualCode(string $visualCode): self
718
    {
719
        $this->visualCode = $visualCode;
720
721
        return $this;
722
    }
723
724
    public function getDepartmentName(): ?string
725
    {
726
        return $this->departmentName;
727
    }
728
729
    public function setDepartmentName(string $departmentName): self
730
    {
731
        $this->departmentName = $departmentName;
732
733
        return $this;
734
    }
735
736
    public function getDepartmentUrl(): ?string
737
    {
738
        return $this->departmentUrl;
739
    }
740
741
    public function setDepartmentUrl(string $departmentUrl): self
742
    {
743
        $this->departmentUrl = $departmentUrl;
744
745
        return $this;
746
    }
747
748
    public function getDiskQuota(): ?int
749
    {
750
        return $this->diskQuota;
751
    }
752
753
    public function setDiskQuota(int $diskQuota): self
754
    {
755
        $this->diskQuota = $diskQuota;
756
757
        return $this;
758
    }
759
760
    public function getLastVisit(): ?DateTime
761
    {
762
        return $this->lastVisit;
763
    }
764
765
    public function setLastVisit(DateTime $lastVisit): self
766
    {
767
        $this->lastVisit = $lastVisit;
768
769
        return $this;
770
    }
771
772
    public function getLastEdit(): ?DateTime
773
    {
774
        return $this->lastEdit;
775
    }
776
777
    public function setLastEdit(DateTime $lastEdit): self
778
    {
779
        $this->lastEdit = $lastEdit;
780
781
        return $this;
782
    }
783
784
    public function getCreationDate(): DateTime
785
    {
786
        return $this->creationDate;
787
    }
788
789
    public function setCreationDate(DateTime $creationDate): self
790
    {
791
        $this->creationDate = $creationDate;
792
793
        return $this;
794
    }
795
796
    public function getExpirationDate(): ?DateTime
797
    {
798
        return $this->expirationDate;
799
    }
800
801
    public function setExpirationDate(DateTime $expirationDate): self
802
    {
803
        $this->expirationDate = $expirationDate;
804
805
        return $this;
806
    }
807
808
    public function getSubscribe(): bool
809
    {
810
        return $this->subscribe;
811
    }
812
813
    public function setSubscribe(bool $subscribe): self
814
    {
815
        $this->subscribe = $subscribe;
816
817
        return $this;
818
    }
819
820
    public function getUnsubscribe(): bool
821
    {
822
        return $this->unsubscribe;
823
    }
824
825
    public function setUnsubscribe(bool $unsubscribe): self
826
    {
827
        $this->unsubscribe = $unsubscribe;
828
829
        return $this;
830
    }
831
832
    public function getRegistrationCode(): ?string
833
    {
834
        return $this->registrationCode;
835
    }
836
837
    public function setRegistrationCode(string $registrationCode): self
838
    {
839
        $this->registrationCode = $registrationCode;
840
841
        return $this;
842
    }
843
844
    public function getLegal(): ?string
845
    {
846
        return $this->legal;
847
    }
848
849
    public function setLegal(string $legal): self
850
    {
851
        $this->legal = $legal;
852
853
        return $this;
854
    }
855
856
    public function getActivateLegal(): ?int
857
    {
858
        return $this->activateLegal;
859
    }
860
861
    public function setActivateLegal(int $activateLegal): self
862
    {
863
        $this->activateLegal = $activateLegal;
864
865
        return $this;
866
    }
867
868
    public function isAddTeachersToSessionsCourses(): ?bool
869
    {
870
        return $this->addTeachersToSessionsCourses;
871
    }
872
873
    public function setAddTeachersToSessionsCourses(bool $addTeachersToSessionsCourses): self
874
    {
875
        $this->addTeachersToSessionsCourses = $addTeachersToSessionsCourses;
876
877
        return $this;
878
    }
879
880
    public function getCourseTypeId(): ?int
881
    {
882
        return $this->courseTypeId;
883
    }
884
885
    public function setCourseTypeId(int $courseTypeId): self
886
    {
887
        $this->courseTypeId = $courseTypeId;
888
889
        return $this;
890
    }
891
892
    public function getRoom(): ?Room
893
    {
894
        return $this->room;
895
    }
896
897
    public function setRoom(Room $room): self
898
    {
899
        $this->room = $room;
900
901
        return $this;
902
    }
903
904
    public function isActive(): bool
905
    {
906
        $activeVisibilityList = [self::REGISTERED, self::OPEN_PLATFORM, self::OPEN_WORLD];
907
908
        return \in_array($this->visibility, $activeVisibilityList, true);
909
    }
910
911
    /**
912
     * Anybody can see this course.
913
     */
914
    public function isPublic(): bool
915
    {
916
        return self::OPEN_WORLD === $this->visibility;
917
    }
918
919
    public function isHidden(): bool
920
    {
921
        return self::HIDDEN === $this->visibility;
922
    }
923
924
    public function getCurrentSession(): Session
925
    {
926
        return $this->currentSession;
927
    }
928
929
    public function setCurrentSession(Session $session): self
930
    {
931
        // If the session is registered in the course session list.
932
        /*if ($this->getSessions()->contains($session->getId())) {
933
              $this->currentSession = $session;
934
          }*/
935
        $list = $this->getSessions();
936
937
        /** @var SessionRelCourse $item */
938
        foreach ($list as $item) {
939
            if ($item->getSession()->getId() === $session->getId()) {
940
                $this->currentSession = $session;
941
942
                break;
943
            }
944
        }
945
946
        return $this;
947
    }
948
949
    /**
950
     * @return Collection<int, SessionRelCourse>
951
     */
952
    public function getSessions(): Collection
953
    {
954
        return $this->sessions;
955
    }
956
957
    public function getCurrentUrl(): AccessUrl
958
    {
959
        return $this->currentUrl;
960
    }
961
962
    public function setCurrentUrl(AccessUrl $url): self
963
    {
964
        $urlList = $this->getUrls();
965
966
        /** @var AccessUrlRelCourse $item */
967
        foreach ($urlList as $item) {
968
            if ($item->getUrl()->getId() === $url->getId()) {
969
                $this->currentUrl = $url;
970
971
                break;
972
            }
973
        }
974
975
        return $this;
976
    }
977
978
    public function getUrls(): Collection
979
    {
980
        return $this->urls;
981
    }
982
983
    public function addUrls(AccessUrlRelCourse $urlRelCourse): static
984
    {
985
        if (!$this->urls->contains($urlRelCourse)) {
986
            $this->urls->add($urlRelCourse);
987
            $urlRelCourse->setCourse($this);
988
        }
989
990
        return $this;
991
    }
992
993
    public function addAccessUrl(?AccessUrl $url): self
994
    {
995
        $urlRelCourse = (new AccessUrlRelCourse())->setUrl($url);
996
        $this->addUrls($urlRelCourse);
997
998
        return $this;
999
    }
1000
1001
    /**
1002
     * @return Collection<int, SkillRelUser>
1003
     */
1004
    public function getIssuedSkills(): Collection
1005
    {
1006
        return $this->issuedSkills;
1007
    }
1008
1009
    /**
1010
     * @return Collection<int, SessionRelCourseRelUser>
1011
     */
1012
    public function getSessionRelCourseRelUsers(): Collection
1013
    {
1014
        return $this->sessionRelCourseRelUsers;
1015
    }
1016
1017
    public function setSessionRelCourseRelUsers(Collection $sessionUserSubscriptions): self
1018
    {
1019
        $this->sessionRelCourseRelUsers = $sessionUserSubscriptions;
1020
1021
        return $this;
1022
    }
1023
1024
    /**
1025
     * @return Collection<int, SkillRelCourse>
1026
     */
1027
    public function getSkills(): Collection
1028
    {
1029
        return $this->skills;
1030
    }
1031
1032
    public function setSkills(Collection $skills): self
1033
    {
1034
        $this->skills = $skills;
1035
1036
        return $this;
1037
    }
1038
1039
    /**
1040
     * @return Collection<int, GradebookCategory>
1041
     */
1042
    public function getGradebookCategories(): Collection
1043
    {
1044
        return $this->gradebookCategories;
1045
    }
1046
1047
    public function setGradebookCategories(Collection $gradebookCategories): self
1048
    {
1049
        $this->gradebookCategories = $gradebookCategories;
1050
1051
        return $this;
1052
    }
1053
1054
    /**
1055
     * @return Collection<int, GradebookEvaluation>
1056
     */
1057
    public function getGradebookEvaluations(): Collection
1058
    {
1059
        return $this->gradebookEvaluations;
1060
    }
1061
1062
    public function setGradebookEvaluations(Collection $gradebookEvaluations): self
1063
    {
1064
        $this->gradebookEvaluations = $gradebookEvaluations;
1065
1066
        return $this;
1067
    }
1068
1069
    /**
1070
     * @return Collection<int, GradebookLink>
1071
     */
1072
    public function getGradebookLinks(): Collection
1073
    {
1074
        return $this->gradebookLinks;
1075
    }
1076
1077
    public function setGradebookLinks(Collection $gradebookLinks): self
1078
    {
1079
        $this->gradebookLinks = $gradebookLinks;
1080
1081
        return $this;
1082
    }
1083
1084
    /**
1085
     * @return Collection<int, TrackEHotspot>
1086
     */
1087
    public function getTrackEHotspots(): Collection
1088
    {
1089
        return $this->trackEHotspots;
1090
    }
1091
1092
    public function setTrackEHotspots(Collection $trackEHotspots): self
1093
    {
1094
        $this->trackEHotspots = $trackEHotspots;
1095
1096
        return $this;
1097
    }
1098
1099
    /**
1100
     * @return Collection<int, SearchEngineRef>
1101
     */
1102
    public function getSearchEngineRefs(): Collection
1103
    {
1104
        return $this->searchEngineRefs;
1105
    }
1106
1107
    public function setSearchEngineRefs(Collection $searchEngineRefs): self
1108
    {
1109
        $this->searchEngineRefs = $searchEngineRefs;
1110
1111
        return $this;
1112
    }
1113
1114
    public function getIntroduction(): ?string
1115
    {
1116
        return $this->introduction;
1117
    }
1118
1119
    public function setIntroduction(?string $introduction): self
1120
    {
1121
        $this->introduction = $introduction;
1122
1123
        return $this;
1124
    }
1125
1126
    /**
1127
     * @return Collection<int, Templates>
1128
     */
1129
    public function getTemplates(): Collection
1130
    {
1131
        return $this->templates;
1132
    }
1133
1134
    public function setTemplates(Collection $templates): self
1135
    {
1136
        $this->templates = $templates;
1137
1138
        return $this;
1139
    }
1140
1141
    public function getVideoUrl(): string
1142
    {
1143
        return $this->videoUrl;
1144
    }
1145
1146
    public function setVideoUrl(string $videoUrl): self
1147
    {
1148
        $this->videoUrl = $videoUrl;
1149
1150
        return $this;
1151
    }
1152
1153
    public function isSticky(): bool
1154
    {
1155
        return $this->sticky;
1156
    }
1157
1158
    public function setSticky(bool $sticky): self
1159
    {
1160
        $this->sticky = $sticky;
1161
1162
        return $this;
1163
    }
1164
1165
    public function getDefaultIllustration(int $size): string
1166
    {
1167
        return '/img/session_default.svg';
1168
    }
1169
1170
    public function getResourceIdentifier(): int
1171
    {
1172
        return $this->getId();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getId() 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...
1173
    }
1174
1175
    public function getResourceName(): string
1176
    {
1177
        return $this->getCode();
1178
    }
1179
1180
    public function setResourceName(string $name): self
1181
    {
1182
        return $this->setCode($name);
1183
    }
1184
}
1185