Total Complexity | 105 |
Total Lines | 644 |
Duplicated Lines | 0 % |
Changes | 0 |
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 |
||
34 | class BaseResourceFileAction |
||
35 | { |
||
36 | public static function setLinks(AbstractResource $resource, EntityManagerInterface $em): void |
||
132 | } |
||
133 | } |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * @todo use this function inside handleCreateFileRequest |
||
138 | */ |
||
139 | protected function handleCreateRequest(AbstractResource $resource, ResourceRepository $resourceRepository, Request $request): array |
||
184 | } |
||
185 | |||
186 | /** |
||
187 | * Handles the creation logic for a student publication comment resource. |
||
188 | */ |
||
189 | public function handleCreateCommentRequest( |
||
190 | AbstractResource $resource, |
||
191 | ResourceRepository $resourceRepository, |
||
192 | Request $request, |
||
193 | EntityManager $em, |
||
194 | string $fileExistsOption = '', |
||
195 | ?TranslatorInterface $translator = null |
||
196 | ): array { |
||
197 | $title = $request->get('comment', ''); |
||
198 | $parentResourceNodeId = (int) $request->get('parentResourceNodeId'); |
||
199 | $fileType = $request->get('filetype'); |
||
200 | $uploadedFile = null; |
||
201 | |||
202 | if (empty($fileType)) { |
||
203 | throw new Exception('filetype needed: folder or file'); |
||
204 | } |
||
205 | |||
206 | if (0 === $parentResourceNodeId) { |
||
207 | throw new Exception('parentResourceNodeId int value needed'); |
||
208 | } |
||
209 | |||
210 | $resource->setParentResourceNode($parentResourceNodeId); |
||
211 | |||
212 | if ($request->files->count() > 0 && $request->files->has('uploadFile')) { |
||
213 | /** @var UploadedFile $uploadedFile */ |
||
214 | $uploadedFile = $request->files->get('uploadFile'); |
||
215 | $resource->setUploadFile($uploadedFile); |
||
216 | } |
||
217 | |||
218 | return [ |
||
219 | 'title' => $title, |
||
220 | 'filename' => $uploadedFile?->getClientOriginalName(), |
||
221 | 'filetype' => $fileType, |
||
222 | ]; |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * Function loaded when creating a resource using the api, then the ResourceListener is executed. |
||
227 | */ |
||
228 | public function handleCreateFileRequest( |
||
229 | AbstractResource $resource, |
||
230 | ResourceRepository $resourceRepository, |
||
231 | Request $request, |
||
232 | EntityManager $em, |
||
233 | string $fileExistsOption = '', |
||
234 | ?TranslatorInterface $translator = null |
||
235 | ): array { |
||
236 | $contentData = $request->getContent(); |
||
237 | |||
238 | if (!empty($contentData)) { |
||
239 | $contentData = json_decode($contentData, true); |
||
240 | $title = $contentData['title'] ?? ''; |
||
241 | $comment = $contentData['comment'] ?? ''; |
||
242 | $parentResourceNodeId = (int) ($contentData['parentResourceNodeId'] ?? 0); |
||
243 | $fileType = $contentData['filetype'] ?? ''; |
||
244 | $resourceLinkList = $contentData['resourceLinkList'] ?? []; |
||
245 | } else { |
||
246 | $title = $request->get('title'); |
||
247 | $comment = $request->get('comment'); |
||
248 | $parentResourceNodeId = (int) $request->get('parentResourceNodeId'); |
||
249 | $fileType = $request->get('filetype'); |
||
250 | $resourceLinkList = $request->get('resourceLinkList', []); |
||
251 | if (!empty($resourceLinkList)) { |
||
252 | $resourceLinkList = !str_contains($resourceLinkList, '[') ? json_decode('['.$resourceLinkList.']', true) : json_decode($resourceLinkList, true); |
||
253 | if (empty($resourceLinkList)) { |
||
254 | $message = 'resourceLinkList is not a valid json. Use for example: [{"cid":1, "visibility":1}]'; |
||
255 | |||
256 | throw new InvalidArgumentException($message); |
||
257 | } |
||
258 | } |
||
259 | } |
||
260 | |||
261 | if (empty($fileType)) { |
||
262 | throw new Exception('filetype needed: folder or file'); |
||
263 | } |
||
264 | |||
265 | if (0 === $parentResourceNodeId) { |
||
266 | throw new Exception('parentResourceNodeId int value needed'); |
||
267 | } |
||
268 | |||
269 | $resource->setParentResourceNode($parentResourceNodeId); |
||
270 | |||
271 | switch ($fileType) { |
||
272 | case 'certificate': |
||
273 | case 'file': |
||
274 | $content = ''; |
||
275 | if ($request->request->has('contentFile')) { |
||
276 | $content = $request->request->get('contentFile'); |
||
277 | } |
||
278 | $fileParsed = false; |
||
279 | // File upload. |
||
280 | if ($request->files->count() > 0) { |
||
281 | if (!$request->files->has('uploadFile')) { |
||
282 | throw new BadRequestHttpException('"uploadFile" is required'); |
||
283 | } |
||
284 | |||
285 | /** @var UploadedFile $uploadedFile */ |
||
286 | $uploadedFile = $request->files->get('uploadFile'); |
||
287 | $title = $uploadedFile->getClientOriginalName(); |
||
288 | |||
289 | if (empty($title)) { |
||
290 | throw new InvalidArgumentException('title is required'); |
||
291 | } |
||
292 | |||
293 | // Handle the appropriate action based on the fileExistsOption |
||
294 | if (!empty($fileExistsOption)) { |
||
295 | // Check if a document with the same title and parent resource node already exists |
||
296 | $existingDocument = $resourceRepository->findByTitleAndParentResourceNode($title, $parentResourceNodeId); |
||
297 | if ($existingDocument) { |
||
298 | if ('overwrite' === $fileExistsOption) { |
||
299 | $existingDocument->setTitle($title); |
||
300 | $existingDocument->setComment($comment); |
||
301 | |||
302 | $resourceNode = $existingDocument->getResourceNode(); |
||
303 | |||
304 | $resourceFile = $resourceNode->getFirstResourceFile(); |
||
305 | if ($resourceFile instanceof ResourceFile) { |
||
306 | $resourceFile->setFile($uploadedFile); |
||
307 | $em->persist($resourceFile); |
||
308 | } else { |
||
309 | $existingDocument->setUploadFile($uploadedFile); |
||
310 | } |
||
311 | |||
312 | $resourceNode->setUpdatedAt(new DateTime()); |
||
313 | $existingDocument->setResourceNode($resourceNode); |
||
314 | |||
315 | $em->persist($existingDocument); |
||
316 | $em->flush(); |
||
317 | |||
318 | // Return any data you need for further processing |
||
319 | return [ |
||
320 | 'title' => $title, |
||
321 | 'filetype' => 'file', |
||
322 | 'comment' => $comment, |
||
323 | ]; |
||
324 | } |
||
325 | |||
326 | if ('rename' == $fileExistsOption) { |
||
327 | // Perform actions when file exists and 'rename' option is selected |
||
328 | $newTitle = $this->generateUniqueTitle($title); // Generate a unique title |
||
329 | $resource->setResourceName($newTitle); |
||
330 | $resource->setUploadFile($uploadedFile); |
||
331 | if (!empty($resourceLinkList)) { |
||
332 | $resource->setResourceLinkArray($resourceLinkList); |
||
333 | } |
||
334 | $em->persist($resource); |
||
335 | $em->flush(); |
||
336 | |||
337 | // Return any data you need for further processing |
||
338 | return [ |
||
339 | 'title' => $newTitle, |
||
340 | 'filetype' => 'file', |
||
341 | 'comment' => $comment, |
||
342 | ]; |
||
343 | } |
||
344 | |||
345 | if ('nothing' == $fileExistsOption) { |
||
346 | // Perform actions when file exists and 'nothing' option is selected |
||
347 | // Display a message indicating that the file already exists |
||
348 | // or perform any other desired actions based on your application's requirements |
||
349 | $resource->setResourceName($title); |
||
350 | $flashBag = $request->getSession()->getFlashBag(); |
||
351 | $message = $translator ? $translator->trans('upload.already_exists') : 'Upload Already Exists'; |
||
352 | $flashBag->add('warning', $message); |
||
353 | |||
354 | throw new BadRequestHttpException($translator ? $translator->trans('file.already_exists') : 'The file already exists and was not uploaded.'); |
||
355 | } |
||
356 | |||
357 | throw new InvalidArgumentException('Invalid fileExistsOption'); |
||
358 | } else { |
||
359 | $resource->setResourceName($title); |
||
360 | $resource->setUploadFile($uploadedFile); |
||
361 | $fileParsed = true; |
||
362 | } |
||
363 | } |
||
364 | } |
||
365 | |||
366 | // Get data in content and create a HTML file. |
||
367 | if (!$fileParsed && $content) { |
||
368 | $uploadedFile = CreateUploadedFile::fromString($title.'.html', 'text/html', $content); |
||
369 | $resource->setUploadFile($uploadedFile); |
||
370 | $fileParsed = true; |
||
371 | } |
||
372 | |||
373 | if (!$fileParsed) { |
||
374 | throw new InvalidArgumentException('filetype was set to "file" but no upload file found'); |
||
375 | } |
||
376 | |||
377 | break; |
||
378 | |||
379 | case 'folder': |
||
380 | break; |
||
381 | } |
||
382 | |||
383 | // Set resource link list if exists. |
||
384 | if (!empty($resourceLinkList)) { |
||
385 | $resource->setResourceLinkArray($resourceLinkList); |
||
386 | } |
||
387 | |||
388 | return [ |
||
389 | 'title' => $title, |
||
390 | 'filetype' => $fileType, |
||
391 | 'comment' => $comment, |
||
392 | ]; |
||
393 | } |
||
394 | |||
395 | protected function handleCreateFileRequestUncompress(AbstractResource $resource, Request $request, EntityManager $em, KernelInterface $kernel): array |
||
396 | { |
||
397 | // Get the parameters from the request |
||
398 | $parentResourceNodeId = (int) $request->get('parentResourceNodeId'); |
||
399 | $fileType = $request->get('filetype'); |
||
400 | $resourceLinkList = $request->get('resourceLinkList', []); |
||
401 | if (!empty($resourceLinkList)) { |
||
402 | $resourceLinkList = !str_contains($resourceLinkList, '[') ? json_decode('['.$resourceLinkList.']', true) : json_decode($resourceLinkList, true); |
||
403 | if (empty($resourceLinkList)) { |
||
404 | $message = 'resourceLinkList is not a valid json. Use for example: [{"cid":1, "visibility":1}]'; |
||
405 | |||
406 | throw new InvalidArgumentException($message); |
||
407 | } |
||
408 | } |
||
409 | |||
410 | if (empty($fileType)) { |
||
411 | throw new Exception('filetype needed: folder or file'); |
||
412 | } |
||
413 | |||
414 | if (0 === $parentResourceNodeId) { |
||
415 | throw new Exception('parentResourceNodeId int value needed'); |
||
416 | } |
||
417 | |||
418 | if ('file' == $fileType && $request->files->count() > 0) { |
||
419 | if (!$request->files->has('uploadFile')) { |
||
420 | throw new BadRequestHttpException('"uploadFile" is required'); |
||
421 | } |
||
422 | |||
423 | $uploadedFile = $request->files->get('uploadFile'); |
||
424 | $resourceTitle = $uploadedFile->getClientOriginalName(); |
||
425 | $resource->setResourceName($resourceTitle); |
||
426 | $resource->setUploadFile($uploadedFile); |
||
427 | |||
428 | if ('zip' === $uploadedFile->getClientOriginalExtension()) { |
||
429 | // Extract the files and subdirectories |
||
430 | $extractedData = $this->extractZipFile($uploadedFile, $kernel); |
||
431 | $folderStructure = $extractedData['folderStructure']; |
||
432 | $extractPath = $extractedData['extractPath']; |
||
433 | $documents = $this->saveZipContentsAsDocuments($folderStructure, $em, $resourceLinkList, $parentResourceNodeId, '', $extractPath, $processedItems); |
||
434 | } |
||
435 | } |
||
436 | |||
437 | $resource->setParentResourceNode($parentResourceNodeId); |
||
438 | |||
439 | return [ |
||
440 | 'filetype' => $fileType, |
||
441 | 'comment' => 'Uncompressed', |
||
442 | ]; |
||
443 | } |
||
444 | |||
445 | protected function handleUpdateRequest(AbstractResource $resource, ResourceRepository $repo, Request $request, EntityManager $em): AbstractResource |
||
446 | { |
||
447 | $contentData = $request->getContent(); |
||
448 | $resourceLinkList = []; |
||
449 | if (!empty($contentData)) { |
||
450 | $contentData = json_decode($contentData, true); |
||
451 | if (isset($contentData['parentResourceNodeId']) && 1 === \count($contentData)) { |
||
452 | $parentResourceNodeId = (int) $contentData['parentResourceNodeId']; |
||
453 | } |
||
454 | $title = $contentData['title'] ?? ''; |
||
455 | $content = $contentData['contentFile'] ?? ''; |
||
456 | $resourceLinkList = $contentData['resourceLinkListFromEntity'] ?? []; |
||
457 | } else { |
||
458 | $title = $request->get('title'); |
||
459 | $content = $request->request->get('contentFile'); |
||
460 | } |
||
461 | |||
462 | $repo->setResourceName($resource, $title); |
||
463 | |||
464 | $resourceNode = $resource->getResourceNode(); |
||
465 | $hasFile = $resourceNode->hasResourceFile(); |
||
466 | |||
467 | if ($hasFile && !empty($content)) { |
||
468 | // The content is updated by the ResourceNodeListener.php |
||
469 | $resourceNode->setContent($content); |
||
470 | foreach ($resourceNode->getResourceFiles() as $resourceFile) { |
||
471 | $resourceFile->setSize(\strlen($content)); |
||
472 | } |
||
473 | $resource->setResourceNode($resourceNode); |
||
474 | } |
||
475 | |||
476 | $link = null; |
||
477 | if (!empty($resourceLinkList)) { |
||
478 | foreach ($resourceLinkList as $key => &$linkArray) { |
||
479 | // Find the exact link. |
||
480 | $linkId = $linkArray['id'] ?? 0; |
||
481 | if (!empty($linkId)) { |
||
482 | /** @var ResourceLink $link */ |
||
483 | $link = $resourceNode->getResourceLinks()->filter(fn ($link) => $link->getId() === $linkId)->first(); |
||
484 | |||
485 | if (null !== $link) { |
||
486 | $link->setVisibility((int) $linkArray['visibility']); |
||
487 | unset($resourceLinkList[$key]); |
||
488 | |||
489 | $em->persist($link); |
||
490 | } |
||
491 | } |
||
492 | } |
||
493 | |||
494 | $resource->setResourceLinkArray($resourceLinkList); |
||
495 | self::setLinks($resource, $em); |
||
496 | } |
||
497 | |||
498 | $isRecursive = !$hasFile; |
||
499 | // If it's a folder then change the visibility to the children (That have the same link). |
||
500 | if ($isRecursive && null !== $link) { |
||
501 | $repo->copyVisibilityToChildren($resource->getResourceNode(), $link); |
||
502 | } |
||
503 | |||
504 | if (!empty($parentResourceNodeId)) { |
||
505 | $parentResourceNode = $em->getRepository(ResourceNode::class)->find($parentResourceNodeId); |
||
506 | if ($parentResourceNode) { |
||
507 | $resourceNode->setParent($parentResourceNode); |
||
508 | } |
||
509 | } |
||
510 | |||
511 | $resourceNode->setUpdatedAt(new DateTime()); |
||
512 | |||
513 | return $resource; |
||
514 | } |
||
515 | |||
516 | private function saveZipContentsAsDocuments(array $folderStructure, EntityManager $em, $resourceLinkList = [], $parentResourceId = null, $currentPath = '', $extractPath = '', &$processedItems = []): array |
||
517 | { |
||
518 | $documents = []; |
||
519 | |||
520 | foreach ($folderStructure as $key => $item) { |
||
521 | if (\is_array($item)) { |
||
522 | $folderName = $key; |
||
523 | $subFolderStructure = $item; |
||
524 | |||
525 | $document = new CDocument(); |
||
526 | $document->setTitle($folderName); |
||
527 | $document->setFiletype('folder'); |
||
528 | |||
529 | if (null !== $parentResourceId) { |
||
530 | $document->setParentResourceNode($parentResourceId); |
||
531 | } |
||
532 | |||
533 | if (!empty($resourceLinkList)) { |
||
534 | $document->setResourceLinkArray($resourceLinkList); |
||
535 | } |
||
536 | |||
537 | $em->persist($document); |
||
538 | $em->flush(); |
||
539 | |||
540 | $documentId = $document->getResourceNode()->getId(); |
||
541 | $documents[$documentId] = [ |
||
542 | 'name' => $document->getTitle(), |
||
543 | 'files' => [], |
||
544 | ]; |
||
545 | |||
546 | $subDocuments = $this->saveZipContentsAsDocuments($subFolderStructure, $em, $resourceLinkList, $documentId, $currentPath.$folderName.'/', $extractPath, $processedItems); |
||
547 | $documents[$documentId]['files'] = $subDocuments; |
||
548 | } else { |
||
549 | $fileName = $item; |
||
550 | |||
551 | $document = new CDocument(); |
||
552 | $document->setTitle($fileName); |
||
553 | $document->setFiletype('file'); |
||
554 | |||
555 | if (null !== $parentResourceId) { |
||
556 | $document->setParentResourceNode($parentResourceId); |
||
557 | } |
||
558 | |||
559 | if (!empty($resourceLinkList)) { |
||
560 | $document->setResourceLinkArray($resourceLinkList); |
||
561 | } |
||
562 | |||
563 | $filePath = $extractPath.'/'.$currentPath.$fileName; |
||
564 | |||
565 | if (file_exists($filePath)) { |
||
566 | $uploadedFile = new UploadedFile( |
||
567 | $filePath, |
||
568 | $fileName |
||
569 | ); |
||
570 | |||
571 | $document->setUploadFile($uploadedFile); |
||
572 | $em->persist($document); |
||
573 | $em->flush(); |
||
574 | |||
575 | $documentId = $document->getResourceNode()->getId(); |
||
576 | $documents[$documentId] = [ |
||
577 | 'name' => $document->getTitle(), |
||
578 | 'files' => [], |
||
579 | ]; |
||
580 | } else { |
||
581 | error_log('File does not exist: '.$filePath); |
||
582 | |||
583 | continue; |
||
584 | } |
||
585 | } |
||
586 | } |
||
587 | |||
588 | return $documents; |
||
589 | } |
||
590 | |||
591 | private function extractZipFile(UploadedFile $file, KernelInterface $kernel): array |
||
626 | ]; |
||
627 | } |
||
628 | |||
629 | private function buildFolderStructure(array $paths, string $extractPath): array |
||
649 | } |
||
650 | |||
651 | private function formatFolderStructure(array $folderStructure): array |
||
652 | { |
||
666 | } |
||
667 | |||
668 | /** |
||
669 | * Generates a unique filename by appending a random suffix. |
||
670 | */ |
||
671 | private function generateUniqueTitle(string $title): string |
||
680 |
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.