UploadHelper   A
last analyzed

Complexity

Total Complexity 20

Size/Duplication

Total Lines 100
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 46
dl 0
loc 100
rs 10
c 0
b 0
f 0
wmc 20

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 8 1
D handleUpload() 0 78 19
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Zikula package.
7
 *
8
 * Copyright Zikula - https://ziku.la/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Zikula\UsersBundle\Helper;
15
16
use Imagine\Gd\Imagine;
17
use Imagine\Image\Box;
18
use Symfony\Component\DependencyInjection\Attribute\Autowire;
19
use Symfony\Component\HttpFoundation\File\UploadedFile;
20
21
class UploadHelper
22
{
23
    /**
24
     * List of allowed file extensions
25
     */
26
    private array $imageExtensions;
27
28
    private string $avatarPath;
29
30
    public function __construct(
31
        private readonly array $uploadConfig,
32
        #[Autowire(param: 'kernel.project_dir')]
33
        string $projectDir,
34
        string $imagePath
35
    ) {
36
        $this->imageExtensions = ['gif', 'jpeg', 'jpg', 'png'];
37
        $this->avatarPath = $projectDir . '/' . $imagePath;
38
    }
39
40
    /**
41
     * Process a given upload file.
42
     */
43
    public function handleUpload(UploadedFile $file, int $userId = 0): string
44
    {
45
        $allowUploads = $this->uploadConfig['enabled'];
46
        if (!$allowUploads) {
47
            return '';
48
        }
49
        if (!file_exists($this->avatarPath) || !is_readable($this->avatarPath) || !is_writable($this->avatarPath)) {
50
            return '';
51
        }
52
53
        if (UPLOAD_ERR_OK !== $file->getError()) {
54
            return '';
55
        }
56
        if (!is_numeric($userId) || $userId < 1) {
0 ignored issues
show
introduced by
The condition is_numeric($userId) is always true.
Loading history...
57
            return '';
58
        }
59
60
        $shrinkImages = $this->uploadConfig['shrink_large_images'];
61
        $filePath = $file->getRealPath();
62
63
        // check for file size limit
64
        if (!$shrinkImages && filesize($filePath) > $this->uploadConfig['max_size']) {
65
            unlink($filePath);
66
67
            return '';
68
        }
69
70
        // Get image information
71
        $imageInfo = getimagesize($filePath);
72
        if (!$imageInfo) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $imageInfo 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...
73
            // file is not an image
74
            unlink($filePath);
75
76
            return '';
77
        }
78
79
        $extension = image_type_to_extension($imageInfo[2], false);
80
        // check for image type
81
        if (!in_array($extension, $this->imageExtensions, true)) {
82
            unlink($filePath);
83
84
            return '';
85
        }
86
87
        // check for image dimensions limit
88
        $isTooLarge = $imageInfo[0] > $this->uploadConfig['max_width'] || $imageInfo[1] > $this->uploadConfig['max_height'];
89
90
        if ($isTooLarge && !$shrinkImages) {
91
            unlink($filePath);
92
93
            return '';
94
        }
95
96
        // everything's OK, so move the file
97
        $avatarFileNameWithoutExtension = 'pers_' . $userId;
98
        $avatarFileName = $avatarFileNameWithoutExtension . '.' . $extension;
99
        $avatarFilePath = $this->avatarPath . '/' . $avatarFileName;
100
101
        // delete old user avatar
102
        foreach ($this->imageExtensions as $ext) {
103
            $oldFilePath = $this->avatarPath . '/' . $avatarFileNameWithoutExtension . '.' . $ext;
104
            if (file_exists($oldFilePath)) {
105
                unlink($oldFilePath);
106
            }
107
        }
108
109
        $file->move($this->avatarPath, $avatarFileName);
110
111
        if ($isTooLarge && $shrinkImages) {
112
            $imagine = new Imagine();
113
            $image = $imagine->open($avatarFilePath);
114
            $image->resize(new Box($this->uploadConfig['max_width'], $this->uploadConfig['max_height']))
115
                  ->save($avatarFilePath);
116
        }
117
118
        chmod($avatarFilePath, 0644);
119
120
        return $avatarFileName;
121
    }
122
}
123