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\Entity\AbstractResource; |
10
|
|
|
use Chamilo\CoreBundle\Entity\Course; |
11
|
|
|
use Chamilo\CoreBundle\Entity\ResourceLink; |
12
|
|
|
use Chamilo\CoreBundle\Entity\ResourceRight; |
13
|
|
|
use Chamilo\CoreBundle\Entity\Session; |
14
|
|
|
use Chamilo\CoreBundle\Entity\User; |
15
|
|
|
use Chamilo\CoreBundle\Repository\ResourceRepository; |
16
|
|
|
use Chamilo\CoreBundle\Security\Authorization\Voter\ResourceNodeVoter; |
17
|
|
|
use Chamilo\CourseBundle\Entity\CGroup; |
18
|
|
|
use DateTime; |
19
|
|
|
use Doctrine\ORM\EntityManager; |
20
|
|
|
use Exception; |
21
|
|
|
use InvalidArgumentException; |
22
|
|
|
use Symfony\Component\HttpFoundation\File\UploadedFile; |
23
|
|
|
use Symfony\Component\HttpFoundation\Request; |
24
|
|
|
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; |
25
|
|
|
|
26
|
|
|
class BaseResourceFileAction |
27
|
|
|
{ |
28
|
|
|
public static function setLinks(AbstractResource $resource, EntityManager $em): void |
29
|
|
|
{ |
30
|
|
|
$resourceNode = $resource->getResourceNode(); |
31
|
|
|
$links = $resource->getResourceLinkArray(); |
32
|
|
|
if ($links) { |
|
|
|
|
33
|
|
|
$groupRepo = $em->getRepository(CGroup::class); |
34
|
|
|
$courseRepo = $em->getRepository(Course::class); |
35
|
|
|
$sessionRepo = $em->getRepository(Session::class); |
36
|
|
|
$userRepo = $em->getRepository(User::class); |
37
|
|
|
|
38
|
|
|
foreach ($links as $link) { |
39
|
|
|
$resourceLink = new ResourceLink(); |
40
|
|
|
$linkSet = false; |
41
|
|
|
if (isset($link['cid']) && !empty($link['cid'])) { |
42
|
|
|
$course = $courseRepo->find($link['cid']); |
43
|
|
|
if (null !== $course) { |
44
|
|
|
$linkSet = true; |
45
|
|
|
$resourceLink->setCourse($course); |
46
|
|
|
} else { |
47
|
|
|
throw new InvalidArgumentException(sprintf('Course #%s does not exists', $link['cid'])); |
48
|
|
|
} |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
if (isset($link['sid']) && !empty($link['sid'])) { |
52
|
|
|
$session = $sessionRepo->find($link['sid']); |
53
|
|
|
if (null !== $session) { |
54
|
|
|
$linkSet = true; |
55
|
|
|
$resourceLink->setSession($session); |
56
|
|
|
} else { |
57
|
|
|
throw new InvalidArgumentException(sprintf('Session #%s does not exists', $link['sid'])); |
58
|
|
|
} |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
if (isset($link['gid']) && !empty($link['gid'])) { |
62
|
|
|
$group = $groupRepo->find($link['gid']); |
63
|
|
|
if (null !== $group) { |
64
|
|
|
$linkSet = true; |
65
|
|
|
$resourceLink->setGroup($group); |
66
|
|
|
} else { |
67
|
|
|
throw new InvalidArgumentException(sprintf('Group #%s does not exists', $link['gid'])); |
68
|
|
|
} |
69
|
|
|
} |
70
|
|
|
|
71
|
|
|
if (isset($link['uid']) && !empty($link['uid'])) { |
72
|
|
|
$user = $userRepo->find($link['uid']); |
73
|
|
|
if (null !== $user) { |
74
|
|
|
$linkSet = true; |
75
|
|
|
$resourceLink->setUser($user); |
76
|
|
|
} else { |
77
|
|
|
throw new InvalidArgumentException(sprintf('User #%s does not exists', $link['uid'])); |
78
|
|
|
} |
79
|
|
|
} |
80
|
|
|
|
81
|
|
|
if (isset($link['visibility'])) { |
82
|
|
|
$resourceLink->setVisibility((int) $link['visibility']); |
83
|
|
|
} else { |
84
|
|
|
throw new InvalidArgumentException('Link needs a visibility key'); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
if ($linkSet) { |
88
|
|
|
$em->persist($resourceLink); |
89
|
|
|
$resourceNode->addResourceLink($resourceLink); |
90
|
|
|
//$em->persist($resourceNode); |
91
|
|
|
//$em->persist($resource->getResourceNode()); |
92
|
|
|
} |
93
|
|
|
} |
94
|
|
|
} |
95
|
|
|
|
96
|
|
|
// Use by Chamilo not api platform. |
97
|
|
|
$links = $resource->getResourceLinkEntityList(); |
98
|
|
|
if ($links) { |
|
|
|
|
99
|
|
|
//error_log('$resource->getResourceLinkEntityList()'); |
100
|
|
|
foreach ($links as $link) { |
101
|
|
|
/*$rights = []; |
102
|
|
|
switch ($link->getVisibility()) { |
103
|
|
|
case ResourceLink::VISIBILITY_PENDING: |
104
|
|
|
case ResourceLink::VISIBILITY_DRAFT: |
105
|
|
|
$editorMask = ResourceNodeVoter::getEditorMask(); |
106
|
|
|
$resourceRight = new ResourceRight(); |
107
|
|
|
$resourceRight |
108
|
|
|
->setMask($editorMask) |
109
|
|
|
->setRole(ResourceNodeVoter::ROLE_CURRENT_COURSE_TEACHER) |
110
|
|
|
; |
111
|
|
|
$rights[] = $resourceRight; |
112
|
|
|
|
113
|
|
|
break; |
114
|
|
|
} |
115
|
|
|
|
116
|
|
|
if (!empty($rights)) { |
117
|
|
|
foreach ($rights as $right) { |
118
|
|
|
$link->addResourceRight($right); |
119
|
|
|
} |
120
|
|
|
}*/ |
121
|
|
|
//error_log('link adding to node: '.$resource->getResourceNode()->getId()); |
122
|
|
|
//error_log('link with user : '.$link->getUser()->getUsername()); |
123
|
|
|
$resource->getResourceNode()->addResourceLink($link); |
124
|
|
|
|
125
|
|
|
$em->persist($link); |
126
|
|
|
} |
127
|
|
|
} |
128
|
|
|
} |
129
|
|
|
|
130
|
|
|
/** |
131
|
|
|
* @todo use this function inside handleCreateFileRequest |
132
|
|
|
*/ |
133
|
|
|
protected function handleCreateRequest(AbstractResource $resource, ResourceRepository $resourceRepository, Request $request): array |
134
|
|
|
{ |
135
|
|
|
$contentData = $request->getContent(); |
136
|
|
|
|
137
|
|
|
if (!empty($contentData)) { |
138
|
|
|
$contentData = json_decode($contentData, true); |
139
|
|
|
$title = $contentData['title'] ?? ''; |
140
|
|
|
$parentResourceNodeId = (int) ($contentData['parentResourceNodeId'] ?? 0); |
141
|
|
|
$resourceLinkList = $contentData['resourceLinkList'] ?? []; |
142
|
|
|
if (empty($resourceLinkList)) { |
143
|
|
|
$resourceLinkList = $contentData['resourceLinkListFromEntity'] ?? []; |
144
|
|
|
} |
145
|
|
|
} else { |
146
|
|
|
$contentData = $request->request->all(); |
147
|
|
|
$title = $request->get('title'); |
148
|
|
|
$parentResourceNodeId = (int) $request->get('parentResourceNodeId'); |
149
|
|
|
$resourceLinkList = $request->get('resourceLinkList', []); |
150
|
|
|
if (!empty($resourceLinkList)) { |
151
|
|
|
$resourceLinkList = false === strpos($resourceLinkList, '[') ? json_decode('['.$resourceLinkList.']', true) : json_decode($resourceLinkList, true); |
152
|
|
|
if (empty($resourceLinkList)) { |
153
|
|
|
$message = 'resourceLinkList is not a valid json. Use for example: [{"cid":1, "visibility":1}]'; |
154
|
|
|
|
155
|
|
|
throw new InvalidArgumentException($message); |
156
|
|
|
} |
157
|
|
|
} |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
if (0 === $parentResourceNodeId) { |
161
|
|
|
throw new Exception('Parameter parentResourceNodeId int value is needed'); |
162
|
|
|
} |
163
|
|
|
|
164
|
|
|
$resource->setParentResourceNode($parentResourceNodeId); |
165
|
|
|
|
166
|
|
|
if (empty($title)) { |
167
|
|
|
throw new InvalidArgumentException('title is required'); |
168
|
|
|
} |
169
|
|
|
|
170
|
|
|
$resource->setResourceName($title); |
171
|
|
|
|
172
|
|
|
// Set resource link list if exists. |
173
|
|
|
if (!empty($resourceLinkList)) { |
174
|
|
|
$resource->setResourceLinkArray($resourceLinkList); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
return $contentData; |
178
|
|
|
} |
179
|
|
|
|
180
|
|
|
/** |
181
|
|
|
* Function loaded when creating a resource using the api, then the ResourceListener is executed. |
182
|
|
|
*/ |
183
|
|
|
protected function handleCreateFileRequest(AbstractResource $resource, ResourceRepository $resourceRepository, Request $request): array |
184
|
|
|
{ |
185
|
|
|
$contentData = $request->getContent(); |
186
|
|
|
|
187
|
|
|
if (!empty($contentData)) { |
188
|
|
|
$contentData = json_decode($contentData, true); |
189
|
|
|
$title = $contentData['title'] ?? ''; |
190
|
|
|
$comment = $contentData['comment'] ?? ''; |
191
|
|
|
$parentResourceNodeId = (int) ($contentData['parentResourceNodeId'] ?? 0); |
192
|
|
|
$fileType = $contentData['filetype'] ?? ''; |
193
|
|
|
$resourceLinkList = $contentData['resourceLinkList'] ?? []; |
194
|
|
|
} else { |
195
|
|
|
$title = $request->get('title'); |
196
|
|
|
$comment = $request->get('comment'); |
197
|
|
|
$parentResourceNodeId = (int) $request->get('parentResourceNodeId'); |
198
|
|
|
$fileType = $request->get('filetype'); |
199
|
|
|
$resourceLinkList = $request->get('resourceLinkList', []); |
200
|
|
|
if (!empty($resourceLinkList)) { |
201
|
|
|
$resourceLinkList = false === strpos($resourceLinkList, '[') ? json_decode('['.$resourceLinkList.']', true) : json_decode($resourceLinkList, true); |
202
|
|
|
if (empty($resourceLinkList)) { |
203
|
|
|
$message = 'resourceLinkList is not a valid json. Use for example: [{"cid":1, "visibility":1}]'; |
204
|
|
|
|
205
|
|
|
throw new InvalidArgumentException($message); |
206
|
|
|
} |
207
|
|
|
} |
208
|
|
|
} |
209
|
|
|
|
210
|
|
|
if (empty($fileType)) { |
211
|
|
|
throw new Exception('filetype needed: folder or file'); |
212
|
|
|
} |
213
|
|
|
|
214
|
|
|
if (0 === $parentResourceNodeId) { |
215
|
|
|
throw new Exception('parentResourceNodeId int value needed'); |
216
|
|
|
} |
217
|
|
|
|
218
|
|
|
$resource->setParentResourceNode($parentResourceNodeId); |
219
|
|
|
|
220
|
|
|
switch ($fileType) { |
221
|
|
|
case 'file': |
222
|
|
|
$content = ''; |
223
|
|
|
if ($request->request->has('contentFile')) { |
224
|
|
|
$content = $request->request->get('contentFile'); |
225
|
|
|
} |
226
|
|
|
$fileParsed = false; |
227
|
|
|
// File upload. |
228
|
|
|
if ($request->files->count() > 0) { |
229
|
|
|
if (!$request->files->has('uploadFile')) { |
230
|
|
|
throw new BadRequestHttpException('"uploadFile" is required'); |
231
|
|
|
} |
232
|
|
|
|
233
|
|
|
/** @var UploadedFile $uploadedFile */ |
234
|
|
|
$uploadedFile = $request->files->get('uploadFile'); |
235
|
|
|
$title = $uploadedFile->getClientOriginalName(); |
236
|
|
|
$resource->setUploadFile($uploadedFile); |
237
|
|
|
$fileParsed = true; |
238
|
|
|
} |
239
|
|
|
|
240
|
|
|
// Get data in content and create a HTML file. |
241
|
|
|
if (!$fileParsed && $content) { |
242
|
|
|
$uploadedFile = $resourceRepository->createTempUploadedFile($title.'.html', 'text/html', $content); |
243
|
|
|
$resource->setUploadFile($uploadedFile); |
244
|
|
|
$fileParsed = true; |
245
|
|
|
} |
246
|
|
|
|
247
|
|
|
if (!$fileParsed) { |
248
|
|
|
throw new InvalidArgumentException('filetype was set to "file" but not upload file found'); |
249
|
|
|
} |
250
|
|
|
|
251
|
|
|
break; |
252
|
|
|
case 'folder': |
253
|
|
|
break; |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
if (empty($title)) { |
257
|
|
|
throw new InvalidArgumentException('title is required'); |
258
|
|
|
} |
259
|
|
|
|
260
|
|
|
$resource->setResourceName($title); |
261
|
|
|
|
262
|
|
|
// Set resource link list if exists. |
263
|
|
|
if (!empty($resourceLinkList)) { |
264
|
|
|
$resource->setResourceLinkArray($resourceLinkList); |
265
|
|
|
} |
266
|
|
|
|
267
|
|
|
return [ |
268
|
|
|
'filetype' => $fileType, |
269
|
|
|
'comment' => $comment, |
270
|
|
|
]; |
271
|
|
|
} |
272
|
|
|
|
273
|
|
|
protected function handleUpdateRequest(AbstractResource $resource, ResourceRepository $repo, Request $request, EntityManager $em): AbstractResource |
274
|
|
|
{ |
275
|
|
|
$contentData = $request->getContent(); |
276
|
|
|
$resourceLinkList = []; |
277
|
|
|
if (!empty($contentData)) { |
278
|
|
|
$contentData = json_decode($contentData, true); |
279
|
|
|
$title = $contentData['title'] ?? ''; |
280
|
|
|
$content = $contentData['contentFile'] ?? ''; |
281
|
|
|
$resourceLinkList = $contentData['resourceLinkListFromEntity'] ?? []; |
282
|
|
|
} else { |
283
|
|
|
$title = $request->get('title'); |
284
|
|
|
$content = $request->request->get('contentFile'); |
285
|
|
|
//$comment = $request->request->get('comment'); |
286
|
|
|
} |
287
|
|
|
|
288
|
|
|
$repo->setResourceName($resource, $title); |
289
|
|
|
|
290
|
|
|
$hasFile = $resource->getResourceNode()->hasResourceFile(); |
291
|
|
|
|
292
|
|
|
$resourceNode = $resource->getResourceNode(); |
293
|
|
|
|
294
|
|
|
if ($hasFile && !empty($content)) { |
295
|
|
|
if ($resourceNode->hasResourceFile()) { |
296
|
|
|
// The content is updated by the ResourceNodeListener.php |
297
|
|
|
$resourceNode->setContent($content); |
298
|
|
|
$resourceNode->getResourceFile()->setSize(\strlen($content)); |
299
|
|
|
} |
300
|
|
|
$resourceNode->getResourceFile()->setUpdatedAt(new DateTime()); |
301
|
|
|
$resource->setResourceNode($resourceNode); |
302
|
|
|
} |
303
|
|
|
|
304
|
|
|
$link = null; |
305
|
|
|
if (!empty($resourceLinkList)) { |
306
|
|
|
foreach ($resourceLinkList as $key => &$linkArray) { |
307
|
|
|
// Find the exact link. |
308
|
|
|
$linkId = $linkArray['id'] ?? 0; |
309
|
|
|
if (!empty($linkId)) { |
310
|
|
|
/** @var ResourceLink $link */ |
311
|
|
|
$link = $resourceNode->getResourceLinks()->filter(fn ($link) => $link->getId() === $linkId)->first(); |
312
|
|
|
|
313
|
|
|
if (null !== $link) { |
314
|
|
|
$link->setVisibility((int) $linkArray['visibility']); |
315
|
|
|
unset($resourceLinkList[$key]); |
316
|
|
|
|
317
|
|
|
$em->persist($link); |
318
|
|
|
} |
319
|
|
|
} |
320
|
|
|
} |
321
|
|
|
|
322
|
|
|
$resource->setResourceLinkArray($resourceLinkList); |
323
|
|
|
self::setLinks($resource, $em); |
324
|
|
|
} |
325
|
|
|
|
326
|
|
|
$isRecursive = !$hasFile; |
327
|
|
|
// If it's a folder then change the visibility to the children (That have the same link). |
328
|
|
|
if ($isRecursive && null !== $link) { |
329
|
|
|
$repo->copyVisibilityToChildren($resource->getResourceNode(), $link); |
330
|
|
|
} |
331
|
|
|
|
332
|
|
|
$resourceNode->setUpdatedAt(new DateTime()); |
333
|
|
|
|
334
|
|
|
return $resource; |
335
|
|
|
} |
336
|
|
|
} |
337
|
|
|
|
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.