Passed
Push — master ( db53d7...84ebef )
by Julito
09:47
created

AbstractResource   D

Complexity

Total Complexity 58

Size/Duplication

Total Lines 415
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 165
dl 0
loc 415
rs 4.5599
c 1
b 0
f 1
wmc 58

27 Methods

Rating   Name   Duplication   Size   Complexity  
A getResourceLinkEntityList() 0 3 1
A addLink() 0 5 1
A getParentResourceNode() 0 3 1
A addGroupLink() 0 29 4
A getResourceNode() 0 3 1
A setResourceNode() 0 5 1
A setResourceLinkListFromEntity() 0 18 2
A setParent() 0 5 1
A addUserLink() 0 34 4
A setResourceLinkArray() 0 5 1
A getResourceLinkArray() 0 3 1
A hasResourceNode() 0 3 1
A hasParentResourceNode() 0 3 1
A isVisible() 0 8 2
A getLinkVisibility() 0 3 1
B addCourseLink() 0 54 10
A getCourseSessionResourceLink() 0 3 1
A addResourceToUserList() 0 13 3
A getUploadFile() 0 3 1
A getParent() 0 3 1
A hasUploadFile() 0 3 1
A setUploadFile() 0 5 1
A getFirstResourceLinkFromCourseSession() 0 24 5
A getFirstResourceLink() 0 12 4
A getUsersAndGroupSubscribedToResource() 0 23 6
A getResourceLinkListFromEntity() 0 3 1
A setParentResourceNode() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like AbstractResource 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 AbstractResource, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/* For licensing terms, see /license.txt */
4
5
namespace Chamilo\CoreBundle\Entity;
6
7
use ApiPlatform\Core\Annotation\ApiProperty;
8
use ApiPlatform\Core\Annotation\ApiSubresource;
9
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
10
use Chamilo\CourseBundle\Entity\CGroup;
11
use Doctrine\Common\Collections\Criteria;
12
use Doctrine\ORM\Mapping as ORM;
13
use Symfony\Component\Serializer\Annotation\Groups;
14
use Symfony\Component\Validator\Constraints as Assert;
15
16
/**
17
 * @ORM\MappedSuperclass
18
 * @ORM\HasLifecycleCallbacks
19
 * @ORM\EntityListeners({"Chamilo\CoreBundle\Entity\Listener\ResourceListener"})
20
 */
21
abstract class AbstractResource
22
{
23
    /**
24
     * @var string|null
25
     *
26
     * @ApiProperty(iri="http://schema.org/contentUrl")
27
     * @Groups({"resource_file:read", "resource_node:read", "document:read", "media_object_read"})
28
     */
29
    public $contentUrl;
30
31
    /**
32
     * @var string|null
33
     *
34
     * @ApiProperty(iri="http://schema.org/contentUrl")
35
     * @Groups({"resource_file:read", "resource_node:read", "document:read", "media_object_read"})
36
     */
37
    public $downloadUrl;
38
39
    /**
40
     * @var string|null
41
     *
42
     * @Groups({"resource_file:read", "resource_node:read", "document:read", "document:write", "media_object_read"})
43
     */
44
    public $contentFile;
45
46
    /**
47
     * @Assert\Valid()
48
     * @ApiSubresource()
49
     * @Groups({"resource_node:read", "resource_node:write", "document:write" })
50
     * @ORM\OneToOne(
51
     *     targetEntity="Chamilo\CoreBundle\Entity\ResourceNode",
52
     *     cascade={"persist", "remove"},
53
     *     orphanRemoval=true
54
     * )
55
     * @ORM\JoinColumn(name="resource_node_id", referencedColumnName="id", onDelete="CASCADE")
56
     */
57
    public $resourceNode;
58
59
    /**
60
     * @Groups({"resource_node:read", "resource_node:write", "document:read", "document:write"})
61
     */
62
    public $parentResourceNode;
63
64
    /**
65
     * @ApiProperty(iri="http://schema.org/image")
66
     */
67
    public $uploadFile;
68
69
    /** @var AbstractResource */
70
    public $parentResource;
71
72
    /**
73
     * @Groups({"resource_node:read", "document:read"})
74
     */
75
    public $resourceLinkListFromEntity;
76
77
    /**
78
     * Use when sending a request to Api platform.
79
     * Temporal array that saves the resource link list that will be filled by CreateResourceNodeFileAction.php.
80
     *
81
     * @var array
82
     */
83
    public $resourceLinkList;
84
85
    /**
86
     * Use when sending request to Chamilo.
87
     * Temporal array of objects locates the resource link list that will be filled by CreateResourceNodeFileAction.php.
88
     *
89
     * @var ResourceLink[]
90
     */
91
    public $resourceLinkEntityList;
92
93
    abstract public function getResourceName(): string;
94
95
    abstract public function setResourceName(string $name);
96
97
    public function getResourceLinkEntityList()
98
    {
99
        return $this->resourceLinkEntityList;
100
    }
101
102
    public function addLink(ResourceLink $link)
103
    {
104
        $this->resourceLinkEntityList[] = $link;
105
106
        return $this;
107
    }
108
109
    public function addCourseLink(Course $course, Session $session = null, CGroup $group = null, int $visibility = ResourceLink::VISIBILITY_PUBLISHED)
110
    {
111
        if (null === $this->getParent()) {
112
            throw new \Exception('addCourseLink requires to set the parent.');
113
        }
114
115
        $resourceLink = new ResourceLink();
116
        $resourceLink
117
            ->setVisibility($visibility)
118
            ->setCourse($course)
119
            ->setSession($session)
120
            ->setGroup($group)
121
        ;
122
        $rights = [];
123
        switch ($visibility) {
124
            case ResourceLink::VISIBILITY_PENDING:
125
            case ResourceLink::VISIBILITY_DRAFT:
126
                $editorMask = ResourceNodeVoter::getEditorMask();
127
                $resourceRight = new ResourceRight();
128
                $resourceRight
129
                    ->setMask($editorMask)
130
                    ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
131
                ;
132
                $rights[] = $resourceRight;
133
134
                break;
135
        }
136
137
        if (!empty($rights)) {
138
            foreach ($rights as $right) {
139
                $resourceLink->addResourceRight($right);
140
            }
141
        }
142
143
        if ($this->hasResourceNode()) {
144
            $resourceNode = $this->getResourceNode();
145
            $exists = $resourceNode->getResourceLinks()->exists(
146
                function ($key, $element) use ($course, $session, $group) {
147
                    return
148
                        $course === $element->getCourse() &&
149
                        $session === $element->getSession() &&
150
                        $group === $element->getGroup();
151
                }
152
            );
153
154
            if ($exists) {
155
                return $this;
156
            }
157
            $resourceNode->addResourceLink($resourceLink);
158
        } else {
159
            $this->addLink($resourceLink);
160
        }
161
162
        return $this;
163
    }
164
165
    public function addGroupLink(Course $course, Session $session = null, CGroup $group = null)
166
    {
167
        $resourceLink = new ResourceLink();
168
        $resourceLink
169
            ->setCourse($course)
170
            ->setSession($session)
171
            ->setGroup($group)
172
            ->setVisibility(ResourceLink::VISIBILITY_PUBLISHED)
173
        ;
174
175
        if ($this->hasResourceNode()) {
176
            $resourceNode = $this->getResourceNode();
177
            $exists = $resourceNode->getResourceLinks()->exists(
178
                function ($key, $element) use ($group) {
179
                    if ($element->getGroup()) {
180
                        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

180
                        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...
181
                    }
182
                }
183
            );
184
185
            if ($exists) {
186
                return $this;
187
            }
188
            $resourceNode->addResourceLink($resourceLink);
189
        } else {
190
            $this->addLink($resourceLink);
191
        }
192
193
        return $this;
194
    }
195
196
    public function addUserLink(User $user, Course $course = null, Session $session = null, CGroup $group = null)
197
    {
198
        $resourceLink = new ResourceLink();
199
        $resourceLink
200
            ->setVisibility(ResourceLink::VISIBILITY_PUBLISHED)
201
            ->setUser($user)
202
            ->setCourse($course)
203
            ->setSession($session)
204
            ->setGroup($group)
205
        ;
206
207
        if ($this->hasResourceNode()) {
208
            $resourceNode = $this->getResourceNode();
209
            $exists = $resourceNode->getResourceLinks()->exists(
210
                function ($key, $element) use ($user) {
211
                    if ($element->hasUser()) {
212
                        return $user->getId() === $element->getUser()->getId();
213
                    }
214
                }
215
            );
216
217
            if ($exists) {
218
                error_log('Link already exist for user: '.$user->getUsername().', skipping');
219
220
                return $this;
221
            }
222
223
            error_log('New link can be added for user: '.$user->getUsername());
224
            $resourceNode->addResourceLink($resourceLink);
225
        } else {
226
            $this->addLink($resourceLink);
227
        }
228
229
        return $this;
230
    }
231
232
    public function setParent(AbstractResource $parent)
233
    {
234
        $this->parentResource = $parent;
235
236
        return $this;
237
    }
238
239
    public function getParent()
240
    {
241
        return $this->parentResource;
242
    }
243
244
    /**
245
     * @param array $userList User id list
246
     */
247
    public function addResourceToUserList(
248
        array $userList,
249
        Course $course = null,
250
        Session $session = null,
251
        CGroup $group = null
252
    ) {
253
        if (!empty($userList)) {
254
            foreach ($userList as $user) {
255
                $this->addUserLink($user, $course, $session, $group);
256
            }
257
        }
258
259
        return $this;
260
    }
261
262
    public function setResourceLinkArray(array $links)
263
    {
264
        $this->resourceLinkList = $links;
265
266
        return $this;
267
    }
268
269
    public function getResourceLinkArray()
270
    {
271
        return $this->resourceLinkList;
272
    }
273
274
    public function getResourceLinkListFromEntity()
275
    {
276
        return $this->resourceLinkListFromEntity;
277
    }
278
279
    public function setResourceLinkListFromEntity()
280
    {
281
        $resourceNode = $this->getResourceNode();
282
        $links = $resourceNode->getResourceLinks();
283
        $resourceLinkList = [];
284
285
        foreach ($links as $link) {
286
            $resourceLinkList[] = [
287
                'id' => $link->getId(),
288
                'session' => $link->getSession(),
289
                'course' => $link->getCourse(),
290
                'visibility' => $link->getVisibility(),
291
                'visibilityName' => $link->getVisibilityName(),
292
                'group' => $link->getGroup(),
293
                'userGroup' => $link->getUserGroup(),
294
            ];
295
        }
296
        $this->resourceLinkListFromEntity = $resourceLinkList;
297
    }
298
299
    public function hasParentResourceNode(): bool
300
    {
301
        return null !== $this->parentResourceNode;
302
    }
303
304
    public function setParentResourceNode($resourceNode): self
305
    {
306
        $this->parentResourceNode = $resourceNode;
307
308
        return $this;
309
    }
310
311
    public function getParentResourceNode()
312
    {
313
        return $this->parentResourceNode;
314
    }
315
316
    public function hasUploadFile(): bool
317
    {
318
        return null !== $this->uploadFile;
319
    }
320
321
    public function getUploadFile()
322
    {
323
        return $this->uploadFile;
324
    }
325
326
    public function setUploadFile($file): self
327
    {
328
        $this->uploadFile = $file;
329
330
        return $this;
331
    }
332
333
    public function setResourceNode(ResourceNode $resourceNode): self
334
    {
335
        $this->resourceNode = $resourceNode;
336
337
        return $this;
338
    }
339
340
    public function hasResourceNode(): bool
341
    {
342
        return $this->resourceNode instanceof ResourceNode;
343
    }
344
345
    public function getResourceNode(): ResourceNode
346
    {
347
        return $this->resourceNode;
348
    }
349
350
    public function getCourseSessionResourceLink(Course $course, Session $session = null): ?ResourceLink
351
    {
352
        return $this->getFirstResourceLinkFromCourseSession($course, $session);
353
    }
354
355
    public function getFirstResourceLink(): ?ResourceLink
356
    {
357
        $resourceNode = $this->getResourceNode();
358
359
        if ($resourceNode && $resourceNode->getResourceLinks()->count()) {
360
            $result = $resourceNode->getResourceLinks()->first();
361
            if ($result) {
362
                return $result;
363
            }
364
        }
365
366
        return null;
367
    }
368
369
    /**
370
     * See ResourceLink to see the visibility constants. Example: ResourceLink::VISIBILITY_DELETED.
371
     */
372
    public function getLinkVisibility(Course $course, Session $session = null): ?ResourceLink
373
    {
374
        return $this->getCourseSessionResourceLink($course, $session)->getVisibility();
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->getCourseS...ssion)->getVisibility() returns the type integer which is incompatible with the type-hinted return Chamilo\CoreBundle\Entity\ResourceLink|null.
Loading history...
375
    }
376
377
    public function isVisible(Course $course, Session $session = null): bool
378
    {
379
        $link = $this->getCourseSessionResourceLink($course, $session);
380
        if (null === $link) {
381
            return false;
382
        }
383
384
        return ResourceLink::VISIBILITY_PUBLISHED === $link->getVisibility();
385
    }
386
387
    public function getFirstResourceLinkFromCourseSession(Course $course, Session $session = null): ?ResourceLink
388
    {
389
        $criteria = Criteria::create();
390
        $criteria
391
            ->where(Criteria::expr()->eq('course', $course))
392
            ->andWhere(
393
                Criteria::expr()->eq('session', $session)
394
            );
395
        $resourceNode = $this->getResourceNode();
396
397
        $result = null;
398
        if ($resourceNode && $resourceNode->getResourceLinks()->count() > 0) {
399
            //var_dump($resourceNode->getResourceLinks()->count());
400
            foreach ($resourceNode->getResourceLinks() as $link) {
401
                //var_dump(get_class($link));
402
            }
403
            $result = $resourceNode->getResourceLinks()->matching($criteria)->first();
404
            //var_dump($result);
405
            if ($result) {
406
                return $result;
407
            }
408
        }
409
410
        return null;
411
    }
412
413
    public function getUsersAndGroupSubscribedToResource(): array
414
    {
415
        $users = [];
416
        $groups = [];
417
        $everyone = false;
418
        $links = $this->getResourceNode()->getResourceLinks();
419
        foreach ($links as $link) {
420
            if ($link->getUser()) {
421
                $users[] = $link->getUser()->getId();
422
            }
423
            if ($link->getGroup()) {
424
                $groups[] = $link->getGroup()->getIid();
425
            }
426
        }
427
428
        if (empty($users) && empty($groups)) {
429
            $everyone = true;
430
        }
431
432
        return [
433
            'everyone' => $everyone,
434
            'users' => $users,
435
            'groups' => $groups,
436
        ];
437
    }
438
}
439