Passed
Pull Request — master (#6035)
by Yannick
08:39 queued 18s
created

ReplaceDocumentFileAction   A

Complexity

Total Complexity 13

Size/Duplication

Total Lines 78
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 39
c 1
b 0
f 0
dl 0
loc 78
rs 10
wmc 13

3 Methods

Rating   Name   Duplication   Size   Complexity  
A prepareDirectory() 0 12 5
A __construct() 0 3 1
B __invoke() 0 52 7
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\Repository\ResourceNodeRepository;
10
use Chamilo\CourseBundle\Entity\CDocument;
11
use Doctrine\ORM\EntityManagerInterface;
12
use Symfony\Component\HttpFoundation\Request;
13
use Symfony\Component\HttpFoundation\Response;
14
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
15
use Symfony\Component\HttpKernel\KernelInterface;
16
use Symfony\Component\HttpFoundation\File\Exception\FileException;
17
18
class ReplaceDocumentFileAction extends BaseResourceFileAction
19
{
20
    private string $uploadBasePath;
21
22
    public function __construct(KernelInterface $kernel)
23
    {
24
        $this->uploadBasePath = $kernel->getProjectDir() . '/var/upload/resource';
25
    }
26
27
    public function __invoke(
28
        CDocument $document,
29
        Request $request,
30
        ResourceNodeRepository $resourceNodeRepository,
31
        EntityManagerInterface $em
32
    ): Response {
33
        $uploadedFile = $request->files->get('file');
34
        if (!$uploadedFile) {
35
            throw new BadRequestHttpException('"file" is required.');
36
        }
37
38
        $resourceNode = $document->getResourceNode();
39
        if (!$resourceNode) {
40
            throw new BadRequestHttpException('ResourceNode not found.');
41
        }
42
43
        $resourceFile = $resourceNode->getFirstResourceFile();
44
        if (!$resourceFile) {
45
            throw new BadRequestHttpException('No file found in the resource node.');
46
        }
47
48
        $filePath = $this->uploadBasePath . $resourceNodeRepository->getFilename($resourceFile);
49
        if (!$filePath) {
50
            throw new BadRequestHttpException('File path could not be resolved.');
51
        }
52
53
        $this->prepareDirectory($filePath);
54
55
        try {
56
            $uploadedFile->move(dirname($filePath), basename($filePath));
57
        } catch (FileException $e) {
58
            throw new BadRequestHttpException(sprintf('Failed to move the file: %s', $e->getMessage()));
59
        }
60
61
        $movedFilePath = $filePath;
62
        if (!file_exists($movedFilePath)) {
63
            throw new \RuntimeException('The moved file does not exist at the expected location.');
64
        }
65
        $fileSize = filesize($movedFilePath);
66
        $resourceFile->setSize($fileSize);
67
68
        $newFileName = $uploadedFile->getClientOriginalName();
69
        $document->setTitle($newFileName);
70
        $resourceFile->setOriginalName($newFileName);
71
72
        $resourceNode->setUpdatedAt(new \DateTime());
73
74
        $em->persist($document);
75
        $em->persist($resourceFile);
76
        $em->flush();
77
78
        return new Response('Document replaced successfully.', Response::HTTP_OK);
79
    }
80
81
    /**
82
     * Prepares the directory to ensure it exists and is writable.
83
     */
84
    protected function prepareDirectory(string $filePath): void
85
    {
86
        $directory = dirname($filePath);
87
88
        if (!is_dir($directory)) {
89
            if (!mkdir($directory, 0775, true) && !is_dir($directory)) {
90
                throw new \RuntimeException(sprintf('Unable to create directory "%s".', $directory));
91
            }
92
        }
93
94
        if (!is_writable($directory)) {
95
            throw new \RuntimeException(sprintf('Directory "%s" is not writable.', $directory));
96
        }
97
    }
98
99
}
100