Passed
Push — master ( 13e36e...a9fdac )
by Yannick
06:45 queued 14s
created

BaseResourceFileAction   C

Complexity

Total Complexity 57

Size/Duplication

Total Lines 311
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 169
dl 0
loc 311
rs 5.04
c 0
b 0
f 0
wmc 57

4 Methods

Rating   Name   Duplication   Size   Complexity  
D setLinks() 0 98 19
B handleCreateRequest() 0 45 9
F handleCreateFileRequest() 0 89 18
B handleUpdateRequest() 0 62 11

How to fix   Complexity   

Complex Class

Complex classes like BaseResourceFileAction 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 BaseResourceFileAction, 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\Controller\Api;
8
9
use Chamilo\CoreBundle\Component\Utils\CreateUploadedFile;
10
use Chamilo\CoreBundle\Entity\AbstractResource;
11
use Chamilo\CoreBundle\Entity\Course;
12
use Chamilo\CoreBundle\Entity\ResourceLink;
13
use Chamilo\CoreBundle\Entity\ResourceRight;
14
use Chamilo\CoreBundle\Entity\Session;
15
use Chamilo\CoreBundle\Entity\User;
16
use Chamilo\CoreBundle\Repository\ResourceRepository;
17
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter;
18
use Chamilo\CourseBundle\Entity\CGroup;
19
use DateTime;
20
use Doctrine\ORM\EntityManager;
21
use Doctrine\ORM\EntityManagerInterface;
22
use Exception;
23
use InvalidArgumentException;
24
use Symfony\Component\HttpFoundation\File\UploadedFile;
25
use Symfony\Component\HttpFoundation\Request;
26
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
27
28
class BaseResourceFileAction
29
{
30
    public static function setLinks(AbstractResource $resource, EntityManagerInterface $em): void
31
    {
32
        $resourceNode = $resource->getResourceNode();
33
        $links = $resource->getResourceLinkArray();
34
        if ($links) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $links of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
35
            $groupRepo = $em->getRepository(CGroup::class);
36
            $courseRepo = $em->getRepository(Course::class);
37
            $sessionRepo = $em->getRepository(Session::class);
38
            $userRepo = $em->getRepository(User::class);
39
40
            foreach ($links as $link) {
41
                $resourceLink = new ResourceLink();
42
                $linkSet = false;
43
                if (isset($link['cid']) && !empty($link['cid'])) {
44
                    $course = $courseRepo->find($link['cid']);
45
                    if (null !== $course) {
46
                        $linkSet = true;
47
                        $resourceLink->setCourse($course);
48
                    } else {
49
                        throw new InvalidArgumentException(sprintf('Course #%s does not exists', $link['cid']));
50
                    }
51
                }
52
53
                if (isset($link['sid']) && !empty($link['sid'])) {
54
                    $session = $sessionRepo->find($link['sid']);
55
                    if (null !== $session) {
56
                        $linkSet = true;
57
                        $resourceLink->setSession($session);
58
                    } else {
59
                        throw new InvalidArgumentException(sprintf('Session #%s does not exists', $link['sid']));
60
                    }
61
                }
62
63
                if (isset($link['gid']) && !empty($link['gid'])) {
64
                    $group = $groupRepo->find($link['gid']);
65
                    if (null !== $group) {
66
                        $linkSet = true;
67
                        $resourceLink->setGroup($group);
68
                    } else {
69
                        throw new InvalidArgumentException(sprintf('Group #%s does not exists', $link['gid']));
70
                    }
71
                }
72
73
                if (isset($link['uid']) && !empty($link['uid'])) {
74
                    $user = $userRepo->find($link['uid']);
75
                    if (null !== $user) {
76
                        $linkSet = true;
77
                        $resourceLink->setUser($user);
78
                    } else {
79
                        throw new InvalidArgumentException(sprintf('User #%s does not exists', $link['uid']));
80
                    }
81
                }
82
83
                if (isset($link['visibility'])) {
84
                    $resourceLink->setVisibility((int) $link['visibility']);
85
                } else {
86
                    throw new InvalidArgumentException('Link needs a visibility key');
87
                }
88
89
                if ($linkSet) {
90
                    $em->persist($resourceLink);
91
                    $resourceNode->addResourceLink($resourceLink);
92
                    // $em->persist($resourceNode);
93
                    // $em->persist($resource->getResourceNode());
94
                }
95
            }
96
        }
97
98
        // Use by Chamilo not api platform.
99
        $links = $resource->getResourceLinkEntityList();
100
        if ($links) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $links of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
101
            // error_log('$resource->getResourceLinkEntityList()');
102
            foreach ($links as $link) {
103
                /*$rights = [];
104
                switch ($link->getVisibility()) {
105
                    case ResourceLink::VISIBILITY_PENDING:
106
                    case ResourceLink::VISIBILITY_DRAFT:
107
                        $editorMask = ResourceNodeVoter::getEditorMask();
108
                        $resourceRight = new ResourceRight();
109
                        $resourceRight
110
                            ->setMask($editorMask)
111
                            ->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER)
112
                        ;
113
                        $rights[] = $resourceRight;
114
115
                        break;
116
                }
117
118
                if (!empty($rights)) {
119
                    foreach ($rights as $right) {
120
                        $link->addResourceRight($right);
121
                    }
122
                }*/
123
                // error_log('link adding to node: '.$resource->getResourceNode()->getId());
124
                // error_log('link with user : '.$link->getUser()->getUsername());
125
                $resource->getResourceNode()->addResourceLink($link);
126
127
                $em->persist($link);
128
            }
129
        }
130
    }
131
132
    /**
133
     * @todo use this function inside handleCreateFileRequest
134
     */
135
    protected function handleCreateRequest(AbstractResource $resource, ResourceRepository $resourceRepository, Request $request): array
136
    {
137
        $contentData = $request->getContent();
138
139
        if (!empty($contentData)) {
140
            $contentData = json_decode($contentData, true);
141
            $title = $contentData['title'] ?? '';
142
            $parentResourceNodeId = (int) ($contentData['parentResourceNodeId'] ?? 0);
143
            $resourceLinkList = $contentData['resourceLinkList'] ?? [];
144
            if (empty($resourceLinkList)) {
145
                $resourceLinkList = $contentData['resourceLinkListFromEntity'] ?? [];
146
            }
147
        } else {
148
            $contentData = $request->request->all();
149
            $title = $request->get('title');
150
            $parentResourceNodeId = (int) $request->get('parentResourceNodeId');
151
            $resourceLinkList = $request->get('resourceLinkList', []);
152
            if (!empty($resourceLinkList)) {
153
                $resourceLinkList = !str_contains($resourceLinkList, '[') ? json_decode('['.$resourceLinkList.']', true) : json_decode($resourceLinkList, true);
154
                if (empty($resourceLinkList)) {
155
                    $message = 'resourceLinkList is not a valid json. Use for example: [{"cid":1, "visibility":1}]';
156
157
                    throw new InvalidArgumentException($message);
158
                }
159
            }
160
        }
161
162
        if (0 === $parentResourceNodeId) {
163
            throw new Exception('Parameter parentResourceNodeId int value is needed');
164
        }
165
166
        $resource->setParentResourceNode($parentResourceNodeId);
167
168
        if (empty($title)) {
169
            throw new InvalidArgumentException('title is required');
170
        }
171
172
        $resource->setResourceName($title);
173
174
        // Set resource link list if exists.
175
        if (!empty($resourceLinkList)) {
176
            $resource->setResourceLinkArray($resourceLinkList);
177
        }
178
179
        return $contentData;
180
    }
181
182
    /**
183
     * Function loaded when creating a resource using the api, then the ResourceListener is executed.
184
     */
185
    protected function handleCreateFileRequest(AbstractResource $resource, ResourceRepository $resourceRepository, Request $request): array
186
    {
187
        $contentData = $request->getContent();
188
189
        if (!empty($contentData)) {
190
            $contentData = json_decode($contentData, true);
191
            $title = $contentData['title'] ?? '';
192
            $comment = $contentData['comment'] ?? '';
193
            $parentResourceNodeId = (int) ($contentData['parentResourceNodeId'] ?? 0);
194
            $fileType = $contentData['filetype'] ?? '';
195
            $resourceLinkList = $contentData['resourceLinkList'] ?? [];
196
        } else {
197
            $title = $request->get('title');
198
            $comment = $request->get('comment');
199
            $parentResourceNodeId = (int) $request->get('parentResourceNodeId');
200
            $fileType = $request->get('filetype');
201
            $resourceLinkList = $request->get('resourceLinkList', []);
202
            if (!empty($resourceLinkList)) {
203
                $resourceLinkList = !str_contains($resourceLinkList, '[') ? json_decode('['.$resourceLinkList.']', true) : json_decode($resourceLinkList, true);
204
                if (empty($resourceLinkList)) {
205
                    $message = 'resourceLinkList is not a valid json. Use for example: [{"cid":1, "visibility":1}]';
206
207
                    throw new InvalidArgumentException($message);
208
                }
209
            }
210
        }
211
212
        if (empty($fileType)) {
213
            throw new Exception('filetype needed: folder or file');
214
        }
215
216
        if (0 === $parentResourceNodeId) {
217
            throw new Exception('parentResourceNodeId int value needed');
218
        }
219
220
        $resource->setParentResourceNode($parentResourceNodeId);
221
222
        switch ($fileType) {
223
            case 'certificate':
224
            case 'file':
225
                $content = '';
226
                if ($request->request->has('contentFile')) {
227
                    $content = $request->request->get('contentFile');
228
                }
229
                $fileParsed = false;
230
                // File upload.
231
                if ($request->files->count() > 0) {
232
                    if (!$request->files->has('uploadFile')) {
233
                        throw new BadRequestHttpException('"uploadFile" is required');
234
                    }
235
236
                    /** @var UploadedFile $uploadedFile */
237
                    $uploadedFile = $request->files->get('uploadFile');
238
                    $title = $uploadedFile->getClientOriginalName();
239
                    $resource->setUploadFile($uploadedFile);
240
                    $fileParsed = true;
241
                }
242
243
                // Get data in content and create a HTML file.
244
                if (!$fileParsed && $content) {
245
                    $uploadedFile = CreateUploadedFile::fromString($title.'.html', 'text/html', $content);
246
                    $resource->setUploadFile($uploadedFile);
247
                    $fileParsed = true;
248
                }
249
250
                if (!$fileParsed) {
251
                    throw new InvalidArgumentException('filetype was set to "file" but not upload file found');
252
                }
253
254
                break;
255
256
            case 'folder':
257
                break;
258
        }
259
260
        if (empty($title)) {
261
            throw new InvalidArgumentException('title is required');
262
        }
263
264
        $resource->setResourceName($title);
265
266
        // Set resource link list if exists.
267
        if (!empty($resourceLinkList)) {
268
            $resource->setResourceLinkArray($resourceLinkList);
269
        }
270
271
        return [
272
            'filetype' => $fileType,
273
            'comment' => $comment,
274
        ];
275
    }
276
277
    protected function handleUpdateRequest(AbstractResource $resource, ResourceRepository $repo, Request $request, EntityManager $em): AbstractResource
278
    {
279
        $contentData = $request->getContent();
280
        $resourceLinkList = [];
281
        if (!empty($contentData)) {
282
            $contentData = json_decode($contentData, true);
283
            $title = $contentData['title'] ?? '';
284
            $content = $contentData['contentFile'] ?? '';
285
            $resourceLinkList = $contentData['resourceLinkListFromEntity'] ?? [];
286
        } else {
287
            $title = $request->get('title');
288
            $content = $request->request->get('contentFile');
289
            // $comment = $request->request->get('comment');
290
        }
291
292
        $repo->setResourceName($resource, $title);
293
294
        $hasFile = $resource->getResourceNode()->hasResourceFile();
295
296
        $resourceNode = $resource->getResourceNode();
297
298
        if ($hasFile && !empty($content)) {
299
            if ($resourceNode->hasResourceFile()) {
300
                // The content is updated by the ResourceNodeListener.php
301
                $resourceNode->setContent($content);
302
                $resourceNode->getResourceFile()->setSize(\strlen($content));
303
            }
304
            $resourceNode->getResourceFile()->setUpdatedAt(new DateTime());
305
            $resource->setResourceNode($resourceNode);
306
        }
307
308
        $link = null;
309
        if (!empty($resourceLinkList)) {
310
            foreach ($resourceLinkList as $key => &$linkArray) {
311
                // Find the exact link.
312
                $linkId = $linkArray['id'] ?? 0;
313
                if (!empty($linkId)) {
314
                    /** @var ResourceLink $link */
315
                    $link = $resourceNode->getResourceLinks()->filter(fn ($link) => $link->getId() === $linkId)->first();
316
317
                    if (null !== $link) {
318
                        $link->setVisibility((int) $linkArray['visibility']);
319
                        unset($resourceLinkList[$key]);
320
321
                        $em->persist($link);
322
                    }
323
                }
324
            }
325
326
            $resource->setResourceLinkArray($resourceLinkList);
327
            self::setLinks($resource, $em);
328
        }
329
330
        $isRecursive = !$hasFile;
331
        // If it's a folder then change the visibility to the children (That have the same link).
332
        if ($isRecursive && null !== $link) {
333
            $repo->copyVisibilityToChildren($resource->getResourceNode(), $link);
334
        }
335
336
        $resourceNode->setUpdatedAt(new DateTime());
337
338
        return $resource;
339
    }
340
}
341