Passed
Pull Request — master (#6835)
by Angel Fernando Quiroz
10:09
created

getFirstResourceLinkFromCourseSession()   B

Complexity

Conditions 9
Paths 15

Size

Total Lines 29
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 17
nc 15
nop 2
dl 0
loc 29
rs 8.0555
c 0
b 0
f 0
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\Metadata\ApiProperty;
10
use Chamilo\CoreBundle\Entity\Listener\ResourceListener;
11
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
12
use Chamilo\CoreBundle\Traits\UserCreatorTrait;
13
use Chamilo\CourseBundle\Entity\CGroup;
14
use Doctrine\ORM\Mapping as ORM;
15
use Exception;
16
use Symfony\Component\HttpFoundation\File\UploadedFile;
17
use Symfony\Component\Serializer\Annotation\Groups;
18
use Symfony\Component\Validator\Constraints as Assert;
19
20
#[ORM\MappedSuperclass]
21
#[ORM\HasLifecycleCallbacks]
22
#[ORM\EntityListeners([ResourceListener::class])]
23
abstract class AbstractResource
24
{
25
    use UserCreatorTrait;
26
27
    #[ApiProperty(types: ['https://schema.org/contentUrl'])]
28
    #[Groups(['resource_file:read', 'resource_node:read', 'document:read', 'media_object_read', 'message:read', 'student_publication:read', 'student_publication_comment:read'])]
29
    public ?string $contentUrl = null;
30
31
    /**
32
     * Download URL of the Resource File Property set by ResourceNormalizer.php.
33
     */
34
    #[ApiProperty(types: ['https://schema.org/contentUrl'])]
35
    #[Groups(['resource_file:read', 'resource_node:read', 'document:read', 'media_object_read', 'message:read', 'student_publication:read', 'student_publication_comment:read', 'student_publication_rel_document:read'])]
36
    public ?string $downloadUrl = null;
37
38
    /**
39
     * Content from ResourceFile - Property set by ResourceNormalizer.php.
40
     */
41
    #[Groups(['resource_file:read', 'resource_node:read', 'document:read', 'document:write', 'media_object_read', 'student_publication:read'])]
42
    public ?string $contentFile = null;
43
44
    /**
45
     * Resource illustration URL - Property set by ResourceNormalizer.php.
46
     */
47
    #[ApiProperty(types: ['https://schema.org/contentUrl'])]
48
    #[Groups([
49
        'resource_node:read',
50
        'document:read',
51
        'media_object_read',
52
        'course:read',
53
        'session:read',
54
        'course_rel_user:read',
55
        'session_rel_course:read',
56
        'session_rel_user:read',
57
        'session_rel_course_rel_user:read',
58
        'user_subscriptions:sessions',
59
    ])]
60
    public ?string $illustrationUrl = null;
61
62
    #[Assert\Valid]
63
    #[Groups([
64
        'resource_node:read',
65
        'resource_node:write',
66
        'personal_file:write',
67
        'document:write',
68
        'ctool:read',
69
        'course:read',
70
        'illustration:read',
71
        'message:read',
72
        'c_tool_intro:read',
73
        'attendance:read',
74
        'student_publication:read',
75
        'student_publication_comment:read',
76
    ])]
77
    #[ORM\OneToOne(targetEntity: ResourceNode::class, cascade: ['persist'])]
78
    #[ORM\JoinColumn(name: 'resource_node_id', referencedColumnName: 'id', onDelete: 'CASCADE')]
79
    public ?ResourceNode $resourceNode = null;
80
81
    /**
82
     * This property is used when using api platform.
83
     */
84
    #[Groups([
85
        'resource_node:read',
86
        'resource_node:write',
87
        'document:read',
88
        'document:write',
89
        'c_student_publication:write',
90
        'calendar_event:write',
91
    ])]
92
    public ?int $parentResourceNode = 0;
93
94
    #[ApiProperty(types: ['https://schema.org/image'])]
95
    public ?UploadedFile $uploadFile = null;
96
97
    /**
98
     * @var AbstractResource|ResourceInterface|null
99
     */
100
    public $parentResource;
101
102
    #[Groups(['resource_node:read', 'document:read', 'attendance:read', 'student_publication:read', 'student_publication_comment:read'])]
103
    public ?array $resourceLinkListFromEntity = null;
104
105
    /**
106
     * Use when sending a request to Api platform.
107
     * Temporal array that saves the resource link list that will be filled by CreateDocumentFileAction.php.
108
     *
109
     * @var array<int, array<string, int>>
110
     */
111
    #[Groups(['c_tool_intro:write', 'resource_node:write', 'c_student_publication:write', 'calendar_event:write', 'attendance:write'])]
112
    public array $resourceLinkList = [];
113
114
    /**
115
     * @var array<ResourceLink>
116
     */
117
    public array $resourceLinkEntityList = [];
118
119
    /**
120
     * This function separates the users from the groups users have a value
121
     * USER:XXX (with XXX the groups id have a value
122
     * GROUP:YYY (with YYY the group id).
123
     *
124
     * @param array $to Array of strings that define the type and id of each destination
125
     *
126
     * @return array Array of groups and users (each an array of IDs)
127
     */
128
    public static function separateUsersGroups(array $to): array
129
    {
130
        $sendTo = ['groups' => [], 'users' => []];
131
132
        foreach ($to as $toItem) {
133
            if (empty($toItem)) {
134
                continue;
135
            }
136
137
            $parts = explode(':', $toItem);
138
            $type = $parts[0] ?? '';
139
            $id = $parts[1] ?? '';
140
141
            switch ($type) {
142
                case 'GROUP':
143
                    $sendTo['groups'][] = (int) $id;
144
145
                    break;
146
147
                case 'USER':
148
                    $sendTo['users'][] = (int) $id;
149
150
                    break;
151
            }
152
        }
153
154
        return $sendTo;
155
    }
156
157
    abstract public function getResourceName(): string;
158
159
    abstract public function setResourceName(string $name);
160
161
    public function getResourceLinkEntityList(): array
162
    {
163
        return $this->resourceLinkEntityList;
164
    }
165
166
    /**
167
     * @throws Exception
168
     */
169
    public function addCourseLink(
170
        Course $course,
171
        ?Session $session = null,
172
        ?CGroup $group = null,
173
        int $visibility = ResourceLink::VISIBILITY_PUBLISHED,
174
        ?\DateTime $createdAt = null,
175
        ?\DateTime $updatedAt = null,
176
    ): self {
177
        if (null === $this->getParent()) {
178
            throw new Exception('$resource->addCourseLink requires to set the parent first.');
179
        }
180
181
        $resourceLink = (new ResourceLink())
182
            ->setVisibility($visibility)
183
            ->setCourse($course)
184
            ->setSession($session)
185
            ->setGroup($group)
186
        ;
187
188
        if ($createdAt) {
189
            $resourceLink->setCreatedAt($createdAt);
190
        }
191
192
        if ($updatedAt) {
193
            $resourceLink->setUpdatedAt($updatedAt);
194
        }
195
196
        $rights = [];
197
198
        switch ($visibility) {
199
            case ResourceLink::VISIBILITY_PENDING:
200
            case ResourceLink::VISIBILITY_DRAFT:
201
                $editorMask = ResourceNodeVoter::getEditorMask();
202
                $resourceRight = (new ResourceRight())
203
                    ->setMask($editorMask)
204
                    ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
205
                ;
206
                $rights[] = $resourceRight;
207
208
                break;
209
        }
210
211
        if (!empty($rights)) {
212
            foreach ($rights as $right) {
213
                $resourceLink->addResourceRight($right);
214
            }
215
        }
216
217
        if ($this->hasResourceNode()) {
218
            $resourceNode = $this->getResourceNode();
219
            $exists = $resourceNode->getResourceLinks()->exists(
220
                fn ($key, $element) => $course === $element->getCourse()
221
                    && $session === $element->getSession()
222
                    && $group === $element->getGroup()
223
            );
224
225
            if ($exists) {
226
                return $this;
227
            }
228
            $resourceNode->addResourceLink($resourceLink);
229
        } else {
230
            $this->addLink($resourceLink);
231
        }
232
233
        return $this;
234
    }
235
236
    public function getParent()
237
    {
238
        return $this->parentResource;
239
    }
240
241
    public function hasResourceNode(): bool
242
    {
243
        return $this->resourceNode instanceof ResourceNode;
244
    }
245
246
    public function getResourceNode(): ?ResourceNode
247
    {
248
        return $this->resourceNode;
249
    }
250
251
    public function setResourceNode(?ResourceNode $resourceNode): self
252
    {
253
        $this->resourceNode = $resourceNode;
254
255
        return $this;
256
    }
257
258
    /**
259
     * $this->resourceLinkEntityList will be loaded in the ResourceListener in the setLinks() function.
260
     */
261
    public function addLink(ResourceLink $link): static
262
    {
263
        $this->resourceLinkEntityList[] = $link;
264
265
        return $this;
266
    }
267
268
    public function setParent(ResourceInterface $parent): static
269
    {
270
        $this->parentResource = $parent;
271
272
        return $this;
273
    }
274
275
    public function addResourceToUserList(
276
        array $userList,
277
        ?Course $course = null,
278
        ?Session $session = null,
279
        ?CGroup $group = null
280
    ): static {
281
        if (!empty($userList)) {
282
            foreach ($userList as $user) {
283
                $this->addUserLink($user, $course, $session, $group);
284
            }
285
        }
286
287
        return $this;
288
    }
289
290
    public function addUserLink(
291
        User $user,
292
        ?Course $course = null,
293
        ?Session $session = null,
294
        ?CGroup $group = null,
295
        ?\DateTime $createdAt = null,
296
        ?\DateTime $updatedAt = null,
297
    ): static {
298
        $resourceLink = (new ResourceLink())
299
            ->setVisibility(ResourceLink::VISIBILITY_PUBLISHED)
300
            ->setUser($user)
301
            ->setCourse($course)
302
            ->setSession($session)
303
            ->setGroup($group)
304
        ;
305
306
        if ($createdAt) {
307
            $resourceLink->setCreatedAt($createdAt);
308
        }
309
310
        if ($updatedAt) {
311
            $resourceLink->setUpdatedAt($updatedAt);
312
        }
313
314
        if ($this->hasResourceNode()) {
315
            $resourceNode = $this->getResourceNode();
316
            $exists = $resourceNode->getResourceLinks()->exists(
317
                function ($key, $element) use ($user) {
318
                    if ($element->hasUser()) {
319
                        return $user->getId() === $element->getUser()->getId();
320
                    }
321
322
                    return false;
323
                }
324
            );
325
326
            if ($exists) {
327
                return $this;
328
            }
329
330
            $resourceNode->addResourceLink($resourceLink);
331
        } else {
332
            $this->addLink($resourceLink);
333
        }
334
335
        return $this;
336
    }
337
338
    public function addResourceToGroupList(
339
        array $groupList,
340
        ?Course $course = null,
341
        ?Session $session = null,
342
    ): static {
343
        foreach ($groupList as $group) {
344
            $this->addGroupLink($course, $group, $session);
345
        }
346
347
        return $this;
348
    }
349
350
    public function addGroupLink(Course $course, CGroup $group, ?Session $session = null): static
351
    {
352
        $resourceLink = (new ResourceLink())
353
            ->setCourse($course)
354
            ->setSession($session)
355
            ->setGroup($group)
356
            ->setVisibility(ResourceLink::VISIBILITY_PUBLISHED)
357
        ;
358
359
        if ($this->hasResourceNode()) {
360
            $resourceNode = $this->getResourceNode();
361
            $exists = $resourceNode->getResourceLinks()->exists(
362
                function ($key, $element) use ($group) {
363
                    if ($element->getGroup()) {
364
                        return $group->getIid() === $element->getGroup()->getIid();
365
                    }
366
                }
367
            );
368
369
            if ($exists) {
370
                return $this;
371
            }
372
            $resourceNode->addResourceLink($resourceLink);
373
        } else {
374
            $this->addLink($resourceLink);
375
        }
376
377
        return $this;
378
    }
379
380
    public function getResourceLinkArray(): array
381
    {
382
        return $this->resourceLinkList;
383
    }
384
385
    public function setResourceLinkArray(array $links): static
386
    {
387
        $this->resourceLinkList = $links;
388
389
        return $this;
390
    }
391
392
    public function getResourceLinkListFromEntity(): ?array
393
    {
394
        return $this->resourceLinkListFromEntity;
395
    }
396
397
    public function setResourceLinkListFromEntity(): void
398
    {
399
        $resourceLinkList = [];
400
        if ($this->hasResourceNode()) {
401
            $resourceNode = $this->getResourceNode();
402
            $links = $resourceNode->getResourceLinks();
403
            foreach ($links as $link) {
404
                $resourceLinkList[] = [
405
                    'id' => $link->getId(),
406
                    'visibility' => $link->getVisibility(),
407
                    'visibilityName' => $link->getVisibilityName(),
408
                    'session' => $link->getSession(),
409
                    'course' => $link->getCourse(),
410
                    'group' => $link->getGroup(),
411
                    'userGroup' => $link->getUserGroup(),
412
                    'user' => $link->getUser(),
413
                ];
414
            }
415
        }
416
        $this->resourceLinkListFromEntity = $resourceLinkList;
417
    }
418
419
    public function hasParentResourceNode(): bool
420
    {
421
        return null !== $this->parentResourceNode && 0 !== $this->parentResourceNode;
422
    }
423
424
    public function getParentResourceNode(): ?int
425
    {
426
        return $this->parentResourceNode;
427
    }
428
429
    public function setParentResourceNode(?int $resourceNode): self
430
    {
431
        $this->parentResourceNode = $resourceNode;
432
433
        return $this;
434
    }
435
436
    public function hasUploadFile(): bool
437
    {
438
        return null !== $this->uploadFile;
439
    }
440
441
    public function getUploadFile(): ?UploadedFile
442
    {
443
        return $this->uploadFile;
444
    }
445
446
    public function setUploadFile(?UploadedFile $file): self
447
    {
448
        $this->uploadFile = $file;
449
450
        return $this;
451
    }
452
453
    #[Groups([
454
        'student_publication:read',
455
        'student_publication_comment:read',
456
    ])]
457
    public function getFirstResourceLink(): ?ResourceLink
458
    {
459
        $resourceNode = $this->getResourceNode();
460
461
        if ($resourceNode && $resourceNode->getResourceLinks()->count()) {
462
            $result = $resourceNode->getResourceLinks()->first();
463
            if ($result) {
464
                return $result;
465
            }
466
        }
467
468
        return null;
469
    }
470
471
    public function isVisible(Course $course, ?Session $session = null): bool
472
    {
473
        $link = $this->getFirstResourceLinkFromCourseSession($course, $session);
474
475
        if (null === $link && $this instanceof ResourceShowCourseResourcesInSessionInterface) {
476
            $link = $this->getFirstResourceLinkFromCourseSession($course);
477
        }
478
479
        if (null === $link) {
480
            return false;
481
        }
482
483
        return ResourceLink::VISIBILITY_PUBLISHED === $link->getVisibility();
484
    }
485
486
    public function getFirstResourceLinkFromCourseSession(Course $course, ?Session $session = null): ?ResourceLink
487
    {
488
        $resourceNode = $this->getResourceNode();
489
        if ($resourceNode && $resourceNode->getResourceLinks()->count() > 0) {
490
            $links = $resourceNode->getResourceLinks();
491
            $found = false;
492
            $link = null;
493
            foreach ($links as $link) {
494
                if ($session) {
495
                    if ($link->getCourse() === $course && $link->getSession() === $session) {
496
                        $found = true;
497
498
                        break;
499
                    }
500
                } else {
501
                    if ($link->getCourse() === $course) {
502
                        $found = true;
503
504
                        break;
505
                    }
506
                }
507
            }
508
509
            if ($found) {
510
                return $link;
511
            }
512
        }
513
514
        return null;
515
    }
516
517
    public function isUserSubscribedToResource(User $user): bool
518
    {
519
        $links = $this->getResourceNode()->getResourceLinks();
520
521
        $result = false;
522
        foreach ($links as $link) {
523
            if ($link->hasUser() && $link->getUser()->getId() === $user->getId()) {
524
                $result = true;
525
526
                break;
527
            }
528
        }
529
530
        return $result;
531
    }
532
533
    public function getUsersAndGroupSubscribedToResource(): array
534
    {
535
        $users = [];
536
        $groups = [];
537
        $everyone = false;
538
        $links = $this->getResourceNode()->getResourceLinks();
539
        foreach ($links as $link) {
540
            if ($link->hasUser()) {
541
                $users[] = $link->getUser()->getId();
542
543
                continue;
544
            }
545
            if ($link->hasGroup()) {
546
                $groups[] = $link->getGroup()->getIid();
547
            }
548
        }
549
550
        if (empty($users) && empty($groups)) {
551
            $everyone = true;
552
        }
553
554
        return [
555
            'everyone' => $everyone,
556
            'users' => $users,
557
            'groups' => $groups,
558
        ];
559
    }
560
}
561