Passed
Push — master ( 0e23f3...7cff38 )
by Julito
24:09
created

AbstractResource::addResourceToGroupList()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
cc 2
eloc 3
nc 2
nop 3
dl 0
loc 10
rs 10
c 1
b 0
f 1
1
<?php
2
3
declare(strict_types=1);
4
5
/* For licensing terms, see /license.txt */
6
7
namespace Chamilo\CoreBundle\Entity;
8
9
use ApiPlatform\Core\Annotation\ApiProperty;
10
use ApiPlatform\Core\Annotation\ApiSubresource;
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
/**
21
 * @ORM\MappedSuperclass
22
 * @ORM\HasLifecycleCallbacks
23
 * @ORM\EntityListeners({"Chamilo\CoreBundle\Entity\Listener\ResourceListener"})
24
 */
25
abstract class AbstractResource
26
{
27
    use UserCreatorTrait;
28
29
    /**
30
     * @ApiProperty(iri="http://schema.org/contentUrl")
31
     * @Groups({"resource_file:read", "resource_node:read", "document:read", "media_object_read"})
32
     */
33
    public ?string $contentUrl = null;
34
35
    /**
36
     * Download URL of the Resource File Property set by ResourceNormalizer.php.
37
     *
38
     * @ApiProperty(iri="http://schema.org/contentUrl")
39
     * @Groups({"resource_file:read", "resource_node:read", "document:read", "media_object_read"})
40
     */
41
    public ?string $downloadUrl = null;
42
43
    /**
44
     * Content from ResourceFile - Property set by ResourceNormalizer.php.
45
     *
46
     * @Groups({"resource_file:read", "resource_node:read", "document:read", "document:write", "media_object_read"})
47
     */
48
    public ?string $contentFile = null;
49
50
    /**
51
     * Resource illustration URL - Property set by ResourceNormalizer.php.
52
     *
53
     * @ApiProperty(iri="http://schema.org/contentUrl")
54
     * @Groups({
55
     *     "resource_node:read",
56
     *     "document:read",
57
     *     "media_object_read",
58
     *     "course:read",
59
     *     "session:read",
60
     *     "course_rel_user:read",
61
     *     "session_rel_course_rel_user:read"
62
     * })
63
     */
64
    public ?string $illustrationUrl = null;
65
66
    /**
67
     * @Assert\Valid()
68
     * @ApiSubresource()
69
     * @Groups({"resource_node:read", "resource_node:write", "personal_file:write", "document:write", "ctool:read", "course:read", "illustration:read"})
70
     * @ORM\OneToOne(
71
     *     targetEntity="Chamilo\CoreBundle\Entity\ResourceNode",
72
     *     cascade={"persist", "remove"},
73
     *     orphanRemoval=true
74
     * )
75
     * @ORM\JoinColumn(name="resource_node_id", referencedColumnName="id", onDelete="CASCADE")
76
     */
77
    public ?ResourceNode $resourceNode = null;
78
79
    /**
80
     * This property is used when using api platform.
81
     */
82
    #[Groups(['resource_node:read', 'resource_node:write', 'document:read', 'document:write'])]
83
    public ?int $parentResourceNode = 0;
84
85
    /**
86
     * @ApiProperty(iri="http://schema.org/image")
87
     */
88
    public ?UploadedFile $uploadFile = null;
89
90
    /**
91
     * @var AbstractResource|ResourceInterface
92
     */
93
    public $parentResource;
94
95
    /**
96
     * @Groups({"resource_node:read", "document:read"})
97
     */
98
    public ?array $resourceLinkListFromEntity = null;
99
100
    /**
101
     * Use when sending a request to Api platform.
102
     * Temporal array that saves the resource link list that will be filled by CreateDocumentFileAction.php.
103
     */
104
    public array $resourceLinkList = [];
105
106
    /**
107
     * Use when sending request to Chamilo.
108
     * Temporal array of objects locates the resource link list that will be filled by CreateDocumentFileAction.php.
109
     *
110
     * @var ResourceLink[]
111
     */
112
    public array $resourceLinkEntityList = [];
113
114
    abstract public function getResourceName(): string;
115
116
    abstract public function setResourceName(string $name);
117
118
    //abstract public function setResourceProperties(FormInterface $form, $course, $session, $fileType);
119
120
    /**
121
     * @return ResourceLink[]
122
     */
123
    public function getResourceLinkEntityList()
124
    {
125
        return $this->resourceLinkEntityList;
126
    }
127
128
    /**
129
     * $this->resourceLinkEntityList will be loaded in the ResourceListener in the setLinks() function.
130
     */
131
    public function addLink(ResourceLink $link)
132
    {
133
        $this->resourceLinkEntityList[] = $link;
134
135
        return $this;
136
    }
137
138
    public function addCourseLink(Course $course, Session $session = null, CGroup $group = null, int $visibility = ResourceLink::VISIBILITY_PUBLISHED)
139
    {
140
        if (null === $this->getParent()) {
141
            throw new Exception('$resource->addCourseLink requires to set the parent first.');
142
        }
143
144
        $resourceLink = (new ResourceLink())
145
            ->setVisibility($visibility)
146
            ->setCourse($course)
147
            ->setSession($session)
148
            ->setGroup($group)
149
        ;
150
151
        $rights = [];
152
        switch ($visibility) {
153
            case ResourceLink::VISIBILITY_PENDING:
154
            case ResourceLink::VISIBILITY_DRAFT:
155
                $editorMask = ResourceNodeVoter::getEditorMask();
156
                $resourceRight = new ResourceRight();
157
                $resourceRight
158
                    ->setMask($editorMask)
159
                    ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
160
                ;
161
                $rights[] = $resourceRight;
162
163
                break;
164
        }
165
166
        if (!empty($rights)) {
167
            foreach ($rights as $right) {
168
                $resourceLink->addResourceRight($right);
169
            }
170
        }
171
172
        if ($this->hasResourceNode()) {
173
            $resourceNode = $this->getResourceNode();
174
            $exists = $resourceNode->getResourceLinks()->exists(
175
                function ($key, $element) use ($course, $session, $group) {
176
                    return $course === $element->getCourse() &&
177
                        $session === $element->getSession() &&
178
                        $group === $element->getGroup();
179
                }
180
            );
181
182
            if ($exists) {
183
                return $this;
184
            }
185
            $resourceNode->addResourceLink($resourceLink);
186
        } else {
187
            $this->addLink($resourceLink);
188
        }
189
190
        return $this;
191
    }
192
193
    public function addGroupLink(Course $course, Session $session = null, CGroup $group = null)
194
    {
195
        $resourceLink = new ResourceLink();
196
        $resourceLink
197
            ->setCourse($course)
198
            ->setSession($session)
199
            ->setGroup($group)
200
            ->setVisibility(ResourceLink::VISIBILITY_PUBLISHED)
201
        ;
202
203
        if ($this->hasResourceNode()) {
204
            $resourceNode = $this->getResourceNode();
205
            $exists = $resourceNode->getResourceLinks()->exists(
206
                function ($key, $element) use ($group) {
207
                    if ($element->getGroup()) {
208
                        return $group->getIid() === $element->getGroup()->getIid();
0 ignored issues
show
Bug introduced by
The method getIid() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

208
                        return $group->/** @scrutinizer ignore-call */ getIid() === $element->getGroup()->getIid();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
209
                    }
210
                }
211
            );
212
213
            if ($exists) {
214
                return $this;
215
            }
216
            $resourceNode->addResourceLink($resourceLink);
217
        } else {
218
            $this->addLink($resourceLink);
219
        }
220
221
        return $this;
222
    }
223
224
    public function addUserLink(User $user, Course $course = null, Session $session = null, CGroup $group = null)
225
    {
226
        $resourceLink = new ResourceLink();
227
        $resourceLink
228
            ->setVisibility(ResourceLink::VISIBILITY_PUBLISHED)
229
            ->setUser($user)
230
            ->setCourse($course)
231
            ->setSession($session)
232
            ->setGroup($group)
233
        ;
234
235
        if ($this->hasResourceNode()) {
236
            $resourceNode = $this->getResourceNode();
237
            $exists = $resourceNode->getResourceLinks()->exists(
238
                function ($key, $element) use ($user) {
239
                    if ($element->hasUser()) {
240
                        return $user->getId() === $element->getUser()->getId();
241
                    }
242
                }
243
            );
244
245
            if ($exists) {
246
                error_log('Link already exist for user: '.$user->getUsername().', skipping');
247
248
                return $this;
249
            }
250
251
            error_log('New link can be added for user: '.$user->getUsername());
252
            $resourceNode->addResourceLink($resourceLink);
253
        } else {
254
            $this->addLink($resourceLink);
255
        }
256
257
        return $this;
258
    }
259
260
    public function setParent(ResourceInterface $parent)
261
    {
262
        $this->parentResource = $parent;
263
264
        return $this;
265
    }
266
267
    public function getParent()
268
    {
269
        return $this->parentResource;
270
    }
271
272
    /**
273
     * @param array $userList User id list
274
     */
275
    public function addResourceToUserList(
276
        array $userList,
277
        Course $course = null,
278
        Session $session = null,
279
        CGroup $group = null
280
    ) {
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 addResourceToGroupList(
291
        array $groupList,
292
        Course $course = null,
293
        Session $session = null,
294
    ) {
295
        foreach ($groupList as $group) {
296
            $this->addGroupLink($course, $session, $group);
297
        }
298
299
        return $this;
300
    }
301
302
    public function setResourceLinkArray(array $links)
303
    {
304
        $this->resourceLinkList = $links;
305
306
        return $this;
307
    }
308
309
    public function getResourceLinkArray()
310
    {
311
        return $this->resourceLinkList;
312
    }
313
314
    public function getResourceLinkListFromEntity()
315
    {
316
        return $this->resourceLinkListFromEntity;
317
    }
318
319
    public function setResourceLinkListFromEntity(): void
320
    {
321
        $resourceLinkList = [];
322
        if ($this->hasResourceNode()) {
323
            $resourceNode = $this->getResourceNode();
324
            $links = $resourceNode->getResourceLinks();
325
            foreach ($links as $link) {
326
                $resourceLinkList[] = [
327
                    'id' => $link->getId(),
328
                    'visibility' => $link->getVisibility(),
329
                    'visibilityName' => $link->getVisibilityName(),
330
                    'session' => $link->getSession(),
331
                    'course' => $link->getCourse(),
332
                    'group' => $link->getGroup(),
333
                    'userGroup' => $link->getUserGroup(),
334
                    'user' => $link->getUser(),
335
                ];
336
            }
337
        }
338
        $this->resourceLinkListFromEntity = $resourceLinkList;
339
    }
340
341
    public function hasParentResourceNode(): bool
342
    {
343
        return null !== $this->parentResourceNode && 0 !== $this->parentResourceNode;
344
    }
345
346
    public function setParentResourceNode(?int $resourceNode): self
347
    {
348
        $this->parentResourceNode = $resourceNode;
349
350
        return $this;
351
    }
352
353
    public function getParentResourceNode(): ?int
354
    {
355
        return $this->parentResourceNode;
356
    }
357
358
    public function hasUploadFile(): bool
359
    {
360
        return null !== $this->uploadFile;
361
    }
362
363
    public function getUploadFile(): ?UploadedFile
364
    {
365
        return $this->uploadFile;
366
    }
367
368
    public function setUploadFile(?UploadedFile $file): self
369
    {
370
        $this->uploadFile = $file;
371
372
        return $this;
373
    }
374
375
    public function setResourceNode(ResourceNode $resourceNode): self
376
    {
377
        $this->resourceNode = $resourceNode;
378
379
        return $this;
380
    }
381
382
    public function hasResourceNode(): bool
383
    {
384
        return $this->resourceNode instanceof ResourceNode;
385
    }
386
387
    public function getResourceNode(): ?ResourceNode
388
    {
389
        return $this->resourceNode;
390
    }
391
392
    public function getFirstResourceLink(): ?ResourceLink
393
    {
394
        $resourceNode = $this->getResourceNode();
395
396
        if ($resourceNode && $resourceNode->getResourceLinks()->count()) {
397
            $result = $resourceNode->getResourceLinks()->first();
398
            if ($result) {
399
                return $result;
400
            }
401
        }
402
403
        return null;
404
    }
405
406
    /**
407
     * See ResourceLink to see the visibility constants. Example: ResourceLink::VISIBILITY_DELETED.
408
     */
409
    /*public function getLinkVisibility(Course $course, Session $session = null): ?ResourceLink
410
    {
411
        return $this->getFirstResourceLinkFromCourseSession($course, $session)->getVisibility();
412
    }*/
413
414
    public function isVisible(Course $course, Session $session = null): bool
415
    {
416
        $link = $this->getFirstResourceLinkFromCourseSession($course, $session);
417
        if (null === $link) {
418
            return false;
419
        }
420
421
        return ResourceLink::VISIBILITY_PUBLISHED === $link->getVisibility();
422
    }
423
424
    public function getFirstResourceLinkFromCourseSession(Course $course, Session $session = null): ?ResourceLink
425
    {
426
        /*$criteria = Criteria::create();
427
        $criteria
428
            ->where(Criteria::expr()->eq('course', $course->getId()))
429
            ->andWhere(
430
                Criteria::expr()->eq('session', $session)
431
            )
432
            ->setFirstResult(0)
433
            ->setMaxResults(1)
434
        ;*/
435
        $resourceNode = $this->getResourceNode();
436
        $result = null;
437
        if ($resourceNode && $resourceNode->getResourceLinks()->count() > 0) {
438
            $links = $resourceNode->getResourceLinks();
439
            $found = false;
440
            $link = null;
441
            foreach ($links as $link) {
442
                if ($link->getCourse() === $course && $link->getSession() === $session) {
443
                    $found = true;
444
445
                    break;
446
                }
447
            }
448
            //$result = $links->matching($criteria)->count();
449
            //var_dump($result);
450
            if ($found) {
451
                return $link;
452
            }
453
        }
454
455
        return null;
456
    }
457
458
    public function isUserSubscribedToResource(User $user): bool
459
    {
460
        $links = $this->getResourceNode()->getResourceLinks();
461
462
        $result = false;
463
        foreach ($links as $link) {
464
            if ($link->hasUser()) {
465
                if ($link->getUser()->getId() === $user->getId()) {
466
                    $result = true;
467
468
                    break;
469
                }
470
            }
471
        }
472
473
        return $result;
474
    }
475
476
    public function getUsersAndGroupSubscribedToResource(): array
477
    {
478
        $users = [];
479
        $groups = [];
480
        $everyone = false;
481
        $links = $this->getResourceNode()->getResourceLinks();
482
        foreach ($links as $link) {
483
            if ($link->hasUser()) {
484
                $users[] = $link->getUser()->getId();
485
486
                continue;
487
            }
488
            if ($link->hasGroup()) {
489
                $groups[] = $link->getGroup()->getIid();
490
            }
491
        }
492
493
        if (empty($users) && empty($groups)) {
494
            $everyone = true;
495
        }
496
497
        return [
498
            'everyone' => $everyone,
499
            'users' => $users,
500
            'groups' => $groups,
501
        ];
502
    }
503
504
    /**
505
     * This function separates the users from the groups users have a value
506
     * USER:XXX (with XXX the groups id have a value
507
     * GROUP:YYY (with YYY the group id).
508
     *
509
     * @param array $to Array of strings that define the type and id of each destination
510
     *
511
     * @return array Array of groups and users (each an array of IDs)
512
     */
513
    public static function separateUsersGroups(array $to): array
514
    {
515
        $send_to = ['groups' => [], 'users' => []];
516
517
        foreach ($to as $to_item) {
518
            if (empty($to_item)) {
519
                continue;
520
            }
521
522
            $parts = explode(':', $to_item);
523
            $type = $parts[0] ?? '';
524
            $id = $parts[1] ?? '';
525
526
            switch ($type) {
527
                case 'GROUP':
528
                    $send_to['groups'][] = (int) $id;
529
530
                    break;
531
                case 'USER':
532
                    $send_to['users'][] = (int) $id;
533
534
                    break;
535
            }
536
        }
537
538
        return $send_to;
539
    }
540
}
541