These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace IrishDan\ResponsiveImageBundle; |
||
4 | |||
5 | use Symfony\Component\HttpFoundation\File\Exception\FileException; |
||
6 | use Symfony\Component\HttpFoundation\File\UploadedFile; |
||
7 | |||
8 | /** |
||
9 | * Class Uploader |
||
10 | * |
||
11 | * @package ResponsiveImageBundle |
||
12 | */ |
||
13 | class Uploader |
||
14 | { |
||
15 | /** |
||
16 | * @var array |
||
17 | */ |
||
18 | public $allowedTypes = [ |
||
19 | 'jpg', |
||
20 | 'jpeg', |
||
21 | 'png', |
||
22 | ]; |
||
23 | /** |
||
24 | * @var FileManager |
||
25 | */ |
||
26 | private $fileSystem; |
||
27 | /** |
||
28 | * @var |
||
29 | */ |
||
30 | private $file; |
||
31 | /** |
||
32 | * @var |
||
33 | */ |
||
34 | private $uploadOk = false; |
||
35 | |||
36 | /** |
||
37 | * Uploader constructor. |
||
38 | * |
||
39 | * @param FileManager $system |
||
40 | */ |
||
41 | public function __construct(FileManager $system) |
||
42 | { |
||
43 | $this->fileSystem = $system; |
||
44 | } |
||
45 | |||
46 | /** |
||
47 | * Sets file. |
||
48 | * |
||
49 | * @param UploadedFile $file |
||
50 | */ |
||
51 | public function setFile(UploadedFile $file = null) |
||
52 | { |
||
53 | $this->file = $file; |
||
54 | } |
||
55 | |||
56 | /** |
||
57 | * Get file. |
||
58 | * |
||
59 | * @return UploadedFile |
||
60 | */ |
||
61 | public function getFile() |
||
62 | { |
||
63 | return $this->file; |
||
64 | } |
||
65 | |||
66 | /** |
||
67 | * Sanitizes and cleans up filename |
||
68 | * |
||
69 | * @param $str |
||
70 | * @return mixed |
||
71 | */ |
||
72 | private function createFilename($str) |
||
73 | { |
||
74 | // Sanitize and transliterate |
||
75 | $str = strtolower($str); |
||
76 | $str = strip_tags($str); |
||
77 | $safeName = preg_replace('/[^a-z0-9-_\.]/', '', $str); |
||
78 | |||
79 | // Create unique filename. |
||
80 | $i = 1; |
||
81 | while (!$this->isUniqueFilename($safeName)) { |
||
82 | $nameArray = explode('.', $safeName); |
||
83 | $safeName = $nameArray[0] . '-' . $i . '.' . $nameArray[1]; |
||
84 | $i++; |
||
85 | } |
||
86 | |||
87 | return $safeName; |
||
88 | } |
||
89 | |||
90 | /** |
||
91 | * Convert MB/K/G to bytesize |
||
92 | * |
||
93 | * @param $uploadMaxSize |
||
94 | * @return int |
||
95 | */ |
||
96 | public function mToBytes($uploadMaxSize) |
||
97 | { |
||
98 | $uploadMaxSize = trim($uploadMaxSize); |
||
99 | $last = strtolower($uploadMaxSize[strlen($uploadMaxSize) - 1]); |
||
100 | |||
101 | switch ($last) { |
||
102 | case 'g': |
||
103 | $uploadMaxSize *= 1024 * 1000 * 1000; |
||
104 | break; |
||
105 | |||
106 | case 'm': |
||
107 | $uploadMaxSize *= 1024 * 1000; |
||
108 | break; |
||
109 | |||
110 | case 'k': |
||
111 | $uploadMaxSize *= 1024; |
||
112 | break; |
||
113 | } |
||
114 | |||
115 | return $uploadMaxSize; |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * Checks to see if a file name is unique in the storage directory. |
||
120 | * |
||
121 | * @param $name |
||
122 | * @return bool |
||
123 | */ |
||
124 | private function isUniqueFilename($name) |
||
125 | { |
||
126 | $storageDirectory = $this->fileSystem->getStorageDirectory(); |
||
127 | $filePath = $storageDirectory . $name; |
||
128 | if ($this->fileSystem->directoryExists($filePath)) { |
||
129 | return false; |
||
130 | } else { |
||
131 | return true; |
||
132 | } |
||
133 | } |
||
134 | |||
135 | /** |
||
136 | * Tests if mime type is allowed. |
||
137 | * |
||
138 | * @return bool |
||
139 | */ |
||
140 | public function isAllowedType() |
||
141 | { |
||
142 | $extension = $this->getFile()->guessExtension(); |
||
143 | if (in_array($extension, $this->allowedTypes)) { |
||
144 | return true; |
||
145 | } else { |
||
146 | return false; |
||
147 | } |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * After uploading, this function checks if the image is valid and if so moves it to an appropriate storage |
||
152 | * location. |
||
153 | * |
||
154 | * @param ResponsiveImageInterface $image . |
||
155 | * @return ResponsiveImageInterface |
||
156 | */ |
||
157 | public function upload(ResponsiveImageInterface $image) |
||
158 | { |
||
159 | // The file property can be empty if the field is not required. |
||
160 | if (null === $image->getFile()) { |
||
161 | return false; |
||
0 ignored issues
–
show
|
|||
162 | } |
||
163 | |||
164 | $this->setFile($image->getFile()); |
||
165 | $messages = []; |
||
166 | $this->uploadOk = true; |
||
167 | |||
168 | // Get max file upload in bytes. |
||
169 | $uploadMaxSize = ini_get('upload_max_filesize'); |
||
170 | $uploadMaxSize = $this->mToBytes($uploadMaxSize); |
||
171 | |||
172 | if (!$this->file instanceof UploadedFile && !empty($image->getFile()->getError())) { |
||
173 | $messages[] = 'Uploaded file should be an instance of \'UploadedFile\''; |
||
174 | $this->uploadOk = false; |
||
175 | } elseif ($this->file->getSize() > $uploadMaxSize) { |
||
176 | $messages[] = sprintf('%s: File size cannot be larger than %s', $this->file->getSize(), $uploadMaxSize); |
||
177 | $this->uploadOk = false; |
||
178 | } elseif (!$this->isAllowedType()) { |
||
179 | $messages[] = 'File type is not allowed'; |
||
180 | $this->uploadOk = false; |
||
181 | } else { |
||
182 | // Sanitize it at least to avoid any security issues. |
||
183 | $fileName = $this->file->getClientOriginalName(); |
||
184 | $newFileName = $this->createFilename($fileName); |
||
185 | |||
186 | // Move takes the target directory and then the target filename to move to. |
||
187 | $storageDirectory = $this->fileSystem->getStorageDirectory('original'); |
||
188 | $this->file->move( |
||
189 | $storageDirectory, |
||
190 | $newFileName |
||
191 | ); |
||
192 | |||
193 | // Set the path property to the filename where you've saved the file. |
||
194 | $image->setPath($newFileName); |
||
195 | |||
196 | // Set the image dimensions. |
||
197 | $imageData = getimagesize($storageDirectory . $newFileName); |
||
198 | $image->setWidth($imageData[0]); |
||
199 | $image->setHeight($imageData[1]); |
||
200 | |||
201 | // Clean up the file property as you won't need it anymore. |
||
202 | $this->file = null; |
||
203 | $image->setFile(null); |
||
204 | } |
||
205 | |||
206 | if ($this->uploadOk) { |
||
207 | return $image; |
||
208 | } else { |
||
209 | throw new FileException($messages[0]); |
||
210 | } |
||
211 | } |
||
212 | } |
||
213 |
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_function
expects aPost
object, and outputs the author of the post. The base classPost
returns a simple string and outputting a simple string will work just fine. However, the child classBlogPost
which is a sub-type ofPost
instead decided to return anobject
, and is therefore violating the SOLID principles. If aBlogPost
were passed tomy_function
, PHP would not complain, but ultimately fail when executing thestrtoupper
call in its body.