Passed
Push — main ( f3cfb1...17781b )
by Emil
04:34
created

UploadManager::saveUploadedFile()   A

Complexity

Conditions 5
Paths 4

Size

Total Lines 27
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 5

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 5
eloc 14
nc 4
nop 2
dl 0
loc 27
rs 9.4888
c 1
b 1
f 0
ccs 14
cts 14
cp 1
crap 5
1
<?php
2
3
namespace App;
4
5
use Symfony\Component\HttpFoundation\File\UploadedFile;
6
7
class UploadManager
8
{
9
    private string $projectDir;
10
    private string $targetDirectory;
11
    private string $targetDirectoryPath;
12
13
    /**
14
     * __construct.
15
     *
16
     * @return void
17
     */
18 7
    public function __construct(string $projectDir, string $targetDirectory = '/uploads')
19
    {
20 7
        $this->projectDir = $projectDir;
21 7
        $this->targetDirectory = ltrim($targetDirectory, '/');
22 7
        $this->targetDirectoryPath = rtrim($this->projectDir.'/public/'.$this->targetDirectory, '/');
23
24
        // Make sure the directory exists
25 7
        if (!is_dir($this->targetDirectoryPath)) {
26 6
            mkdir($this->targetDirectoryPath, 0777, true);
27
        }
28
        // Check write permissions
29 7
        if (!is_writable($this->targetDirectoryPath)) {
30 1
            throw new \RuntimeException($this->targetDirectory.' directory is not writable.');
31
        }
32
    }
33
34
    /**
35
     * saveUploadedFile.
36
     *
37
     * Saves the uploaded file to the /public/uploads folder and returns the path
38
     *
39
     * @param array<string> $fileTypesSupported
40
     *
41
     * @return string|null string containing filePath if successful null if failed
42
     */
43 4
    public function saveUploadedFile(?UploadedFile $file, array $fileTypesSupported): ?string
44
    {
45 4
        $filePath = null;
46
47 4
        if ($file instanceof UploadedFile && $file->isValid()) {
48
            // Check if file is of allowed type
49 3
            $fileType = $file->getMimeType();
50 3
            if (!in_array($fileType, $fileTypesSupported)) {
51 1
                throw new \RuntimeException('Invalid file type. Filetype of '.$fileType.' is not allowed.');
52
            }
53
54
            /** @var string $originalFilename */
55 2
            $originalFilename = pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME);
56 2
            $safeFilename = transliterator_transliterate('Any-Latin; Latin-ASCII; [^A-Za-z0-9_] remove; Lower()', $originalFilename);
57 2
            $newFilename = $safeFilename.'-'.uniqid().'.'.$file->guessExtension();
58
59
            // Move the file to the directory
60
            try {
61 2
                $file->move($this->targetDirectoryPath, $newFilename);
62
                // Save $newFilename and path to database
63 1
                $filePath = '/'.$this->targetDirectory.'/'.$newFilename;
64 1
            } catch (\Exception $e) {
65 1
                throw new \RuntimeException('Error uploading file: '.$e->getMessage());
66
            }
67
        }
68
69 2
        return $filePath;
70
    }
71
72
    /**
73
     * deleteUploadedFile.
74
     *
75
     * Deletes the file at the given path within the target directory.
76
     *
77
     * @param string $filePath The relative path to the image, e.g., '/uploads/filename.jpg'
78
     *
79
     * @return bool True if deletion was successful, false otherwise
80
     */
81 1
    public function deleteUploadedFile(string $filePath): bool
82
    {
83
        // Full path to the file
84 1
        $fullPath = $this->projectDir.'/public'.$filePath;
85
86
        // Check if file exists
87 1
        if (!file_exists($fullPath)) {
88
            // File does not exist
89 1
            return false;
90
        }
91
92
        // Attempt to delete the file
93 1
        return unlink($fullPath);
94
    }
95
}
96