ImageUpload   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 163
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 63
dl 0
loc 163
rs 10
c 0
b 0
f 0
wmc 17

8 Methods

Rating   Name   Duplication   Size   Complexity  
A fileInputPostUpload() 0 7 1
A fileInputUpload() 0 16 3
A getFilename() 0 25 4
A isImageValid() 0 13 3
A fileInputConfigUpload() 0 8 1
A fileInputUserUpload() 0 7 1
A __construct() 0 6 1
A tinymceUpload() 0 23 3
1
<?php
2
3
namespace App\Controllers\Ajax;
4
5
use Cocur\Slugify\Slugify;
6
use Core\AjaxController;
7
use Core\Container;
8
9
class ImageUpload extends AjaxController
10
{
11
    /**
12
     * @var string the image upload folder, must be writable
13
     */
14
    private $imageFolder;
15
    private $configFolder;
16
    private $userFolder;
17
18
    public function __construct(Container $container)
19
    {
20
        parent::__construct($container);
21
        $this->imageFolder = \Core\Config::UPLOADED_IMAGES;
22
        $this->configFolder = \Core\Config::CONFIG_IMAGES;
23
        $this->userFolder = \Core\Config::USER_IMAGES;
24
    }
25
26
    /**
27
     * check if the image name is valid
28
     * @param $image string filename to check
29
     * @return bool if image name is valid
30
     *
31
     */
32
    private function isImageValid($image): bool
33
    {
34
        // Sanitize input
35
        if (preg_match("/([^\w\s\d\-_~,;:\[\]\(\).])|([\.]{2,})/", $image)) {
36
            return false;
37
        }
38
39
        // Verify extension
40
        if (!in_array(strtolower(pathinfo($image, PATHINFO_EXTENSION)), array("gif", "jpg", "png"))) {
41
            return false;
42
        }
43
44
        return true;
45
    }
46
47
    /**
48
     * Check if file exists and add a number to avoid overwrite
49
     * @param string $folder destination folder
50
     * @param string $file destination filename
51
     * @return string the unique file name
52
     */
53
    private function getFilename(string $folder, string $file): string
54
    {
55
        //slugify the file name to avoid security errors or bugs with special characters.
56
        $fileName = pathinfo($file, PATHINFO_FILENAME );
57
        $fileExtension = pathinfo($file, PATHINFO_EXTENSION );
58
        $slugify = new Slugify();
59
        $fileName = $slugify->slugify($fileName);
60
        //if the filename has only special chars, the slugify will be empty, create a unique ID
61
        if($fileName ==="")
62
        {
63
            $fileName = uniqid();
64
        }
65
        $file = $fileName.".".$fileExtension;
66
        $fileUrl = $folder . $file;
67
        $docRoot = $this->request->getDocumentRoot();
68
        $filePath = $docRoot . "/public/" . $fileUrl;
69
        if (file_exists($filePath) !== 1) {
70
            $fileNum = 0;
71
            while (file_exists($filePath)) {
72
                $fileUrl = $folder . $fileNum . "_" . $file;
73
                $filePath = $docRoot . "/public/" . $fileUrl;
74
                $fileNum += 1;
75
            }
76
        }
77
        return $fileUrl;
78
    }
79
80
    /**
81
     * @param $tempFile array
82
     * @param $folder string
83
     */
84
    private function fileInputUpload(array $tempFile, string $folder)
85
    {
86
        if (is_uploaded_file($tempFile['tmp_name'])) {
87
            if (!$this->isImageValid($tempFile['name'])) {
88
                echo json_encode(array('error' => 'Invalid name or file extension'));
89
                return;
90
            }
91
92
            $filetowrite = $this->getFilename($folder, basename($tempFile['name']));
93
            move_uploaded_file($tempFile['tmp_name'], $filetowrite);
94
95
            // Respond to the successful upload with JSON.
96
            echo json_encode(array('location' => $filetowrite));
97
        } else {
98
            // Notify editor that the upload failed
99
            echo json_encode(array('error' => 'Upload failed, file might be too big'));
100
101
        }
102
103
    }
104
105
    /**
106
     * Upload images from TinyMCE
107
     * grabbed from https://www.codexworld.com/tinymce-upload-image-to-server-using-php/
108
     */
109
    public function tinymceUpload()
110
    {
111
        //security checks, only admins can upload images to posts
112
        $this->onlyAdmin();
113
        $this->onlyPost();
114
115
        $tempFile = $this->request->getUploadedFiles();
116
117
        //need to clean up
118
        if (is_uploaded_file($tempFile['tmp_name'])) {
119
            if (!$this->isImageValid($tempFile['name'])) {
120
                header("HTTP/1.1 400 Invalid file name or file extension.");
121
                return;
122
            }
123
124
            $filetowrite = $this->getFilename($this->imageFolder, basename($tempFile['name']));
125
            move_uploaded_file($tempFile['tmp_name'], $filetowrite);
126
127
            // Respond to the successful upload with JSON.
128
            echo json_encode(array('location' => $filetowrite));
129
        } else {
130
            // Notify editor that the upload failed
131
            header("HTTP/1.1 500 Server Error");
132
        }
133
    }
134
135
136
    /**
137
     * Upload for the file input in the configuration
138
     */
139
    public function fileInputConfigUpload()
140
    {
141
        //security checks, only admins can upload images to config
142
        $this->onlyAdmin();
143
        $this->onlyPost();
144
        $tempFile = $this->request->getUploadedFiles();
145
146
        $this->fileInputUpload($tempFile, $this->configFolder);
147
148
    }
149
150
    /**
151
     * Upload for the file input in the configuration
152
     */
153
    public function fileInputPostUpload()
154
    {
155
        //security checks, only admins can upload images to config
156
        $this->onlyAdmin();
157
        $this->onlyPost();
158
        $tempFile = $this->request->getUploadedFiles();
159
        $this->fileInputUpload($tempFile, $this->imageFolder);
160
    }
161
162
    /**
163
     * Upload for the file input in the configuration
164
     */
165
    public function fileInputUserUpload()
166
    {
167
        //security checks, only admins can upload images to config
168
        $this->onlyUser();
169
        $this->onlyPost();
170
        $tempFile = $this->request->getUploadedFiles();
171
        $this->fileInputUpload($tempFile, $this->userFolder);
172
    }
173
174
}