PluginProbe ʕ •ᴥ•ʔ
Kirki – Freeform Page Builder, Website Builder & Customizer / 6.1.0
Kirki – Freeform Page Builder, Website Builder & Customizer v6.1.0
6.1.1 6.1.0 6.0.14 6.0.13 6.0.12 6.0.11 6.0.10 6.0.9 6.0.8 6.0.7 6.0.6 6.0.5 6.0.4 6.0.3 6.0.2 6.0.1 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9 4.0.19 4.0.20 4.0.21 4.0.22 4.0.23 4.0.24 4.1 4.2.0 5.0.0 5.1.0 5.1.1 5.2.0 5.2.1 5.2.2 5.2.3 6.0.0 trunk 3.0.40 3.0.41 3.0.42 3.0.43 3.0.44 3.0.45 3.1.0 3.1.1 3.1.2
kirki / libraries / framework / Filesystem / UploadedFile.php
kirki / libraries / framework / Filesystem Last commit date
File.php 3 weeks ago FileSystemServiceProvider.php 3 weeks ago Fileable.php 3 weeks ago Filesystem.php 3 weeks ago Path.php 3 weeks ago UploadedFile.php 3 weeks ago
UploadedFile.php
369 lines
1 <?php
2
3 /**
4 * Represents an HTTP uploaded file extending File with original name, mime, size, and error state.
5 * Supports moving to storage, JSON serialization, and WordPress media integration.
6 * Created by InteractsWithFiles from the global $_FILES array.
7 *
8 * @package Framework
9 * @subpackage Filesystem
10 * @since 1.0.0
11 */
12 namespace Kirki\Framework\Filesystem;
13
14 \defined('ABSPATH') || exit;
15 use Exception;
16 use Kirki\Framework\Container;
17 use Kirki\Framework\Exceptions\AuthorizationException;
18 use Kirki\Framework\Supports\Arr;
19 use JsonSerializable;
20 use function Kirki\Framework\Polyfill\str_starts_with;
21 use function Kirki\Framework\message;
22 class UploadedFile extends File implements JsonSerializable
23 {
24 /**
25 * The original name of the uploaded file.
26 *
27 * @var string
28 *
29 * @since 1.0.0
30 */
31 protected string $original_name;
32 /**
33 * The MIME type of the uploaded file.
34 *
35 * @var string
36 *
37 * @since 1.0.0
38 */
39 protected string $mime_type;
40 /**
41 * The error of the uploaded file.
42 *
43 * @var int
44 *
45 * @since 1.0.0
46 */
47 protected int $error;
48 /**
49 * The original path of the uploaded file.
50 *
51 * @var string
52 *
53 * @since 1.0.0
54 */
55 protected string $original_path;
56 /**
57 * The size of the uploaded file.
58 *
59 * @var int
60 *
61 * @since 1.0.0
62 */
63 protected int $size;
64 /**
65 * Create a new uploaded file instance.
66 *
67 * @param string $path The path.
68 * @param string $original_name The original name.
69 * @param ?string $mime_type The mime type.
70 * @param ?int $error The error.
71 * @param ?int $size The size.
72 *
73 * @return void
74 *
75 * @since 1.0.0
76 */
77 public function __construct(string $path, string $original_name, ?string $mime_type = null, ?int $error = null, ?int $size = null)
78 {
79 $this->original_name = $this->get_name($original_name);
80 $this->original_path = \strtr($original_name, '\\', '/');
81 $this->mime_type = $mime_type ?? 'application/octet-stream';
82 $this->error = $error ?: \UPLOAD_ERR_OK;
83 $this->size = $size ?: 0;
84 parent::__construct($path, $this->error === \UPLOAD_ERR_OK);
85 }
86 /**
87 * Create a new uploaded file instance from a base file.
88 *
89 * @param mixed $file The file.
90 *
91 * @return static
92 *
93 * @since 1.0.0
94 */
95 public static function create_from_base($file)
96 {
97 return $file instanceof static ? $file : new static($file['tmp_name'], $file['name'], $file['type'], $file['error'], $file['size']);
98 }
99 /**
100 * Get the original name of the uploaded file.
101 *
102 * @return string
103 *
104 * @since 1.0.0
105 */
106 public function get_client_original_name()
107 {
108 return $this->original_name;
109 }
110 /**
111 * Get the original extension of the uploaded file.
112 *
113 * @return string
114 *
115 * @since 1.0.0
116 */
117 public function get_client_original_extension()
118 {
119 return \pathinfo($this->original_name, \PATHINFO_EXTENSION);
120 }
121 /**
122 * Get the original MIME type of the uploaded file.
123 *
124 * @return string
125 *
126 * @since 1.0.0
127 */
128 public function get_client_mime_type()
129 {
130 return $this->mime_type;
131 }
132 /**
133 * Get the original path of the uploaded file.
134 *
135 * @return string
136 *
137 * @since 1.0.0
138 */
139 public function get_client_original_path()
140 {
141 return $this->original_path;
142 }
143 /**
144 * Get the error of the uploaded file.
145 *
146 * @return int
147 *
148 * @since 1.0.0
149 */
150 public function get_error()
151 {
152 return $this->error;
153 }
154 /**
155 * Get the size of the uploaded file.
156 *
157 * @return int
158 *
159 * @since 1.0.0
160 */
161 public function get_size()
162 {
163 return $this->size;
164 }
165 /**
166 * Store the uploaded file in a specified directory.
167 *
168 * @param string $path The path.
169 * @param array $options The options array.
170 *
171 * @return string
172 *
173 * @since 1.0.0
174 */
175 public function store(string $path, array $options = [])
176 {
177 return $this->store_as($path, $this->get_client_original_name(), $options);
178 }
179 /**
180 * Store the uploaded file in a specified directory with a specific name.
181 *
182 * @param string $path The path.
183 * @param mixed $name The name.
184 * @param array $options The options array.
185 *
186 * @return string
187 *
188 * @since 1.0.0
189 */
190 public function store_as(string $path, $name = null, array $options = [])
191 {
192 if (\is_null($name)) {
193 $name = $this->get_client_original_name();
194 }
195 return Container::get_instance()->make(Filesystem::class)->upload($path, $this, $name, $options);
196 }
197 /**
198 * Check if the uploaded file is valid.
199 *
200 * @return bool
201 *
202 * @since 1.0.0
203 */
204 public function is_valid()
205 {
206 $is_ok = \UPLOAD_ERR_OK === $this->error;
207 return $is_ok && \is_uploaded_file($this->getPathname());
208 }
209 /**
210 * Move the uploaded file to a new location.
211 *
212 * @param string $directory The directory.
213 * @param ?string $name The name.
214 *
215 * @return static
216 *
217 * @throws \Exception
218 *
219 * @since 1.0.0
220 */
221 public function move(string $directory, ?string $name = null)
222 {
223 if ($this->is_valid()) {
224 $target = $this->get_target_file($directory, $name);
225 \set_error_handler(static function ($type, $msg) use(&$error) {
226 $error = $msg;
227 });
228 try {
229 $moved = \move_uploaded_file($this->getPathname(), $target);
230 } finally {
231 \restore_error_handler();
232 }
233 if (!$moved) {
234 throw new Exception(message('upload.move_failed', $this->getPathname(), $target, \strip_tags($error ?? '')));
235 }
236 @\chmod($target, 0666 & ~\umask());
237 return $target;
238 }
239 throw new Exception($this->get_error_message());
240 }
241 /**
242 * Get the error message of the uploaded file.
243 *
244 * @return string
245 *
246 * @since 1.0.0
247 */
248 public function get_error_message()
249 {
250 return $this->error !== \UPLOAD_ERR_OK ? $this->get_exception_message() : '';
251 }
252 /**
253 * Get the exception message of the uploaded file.
254 *
255 * @return string
256 *
257 * @since 1.0.0
258 */
259 protected function get_exception_message()
260 {
261 $key = $this->get_message_key_for_error($this->error);
262 if ($this->error === \UPLOAD_ERR_INI_SIZE) {
263 return message($key, $this->get_client_original_name(), $this->get_max_file_size() / 1024);
264 }
265 if (\in_array($this->error, [\UPLOAD_ERR_NO_FILE, \UPLOAD_ERR_NO_TMP_DIR, \UPLOAD_ERR_EXTENSION], \true)) {
266 return message($key);
267 }
268 return message($key, $this->get_client_original_name());
269 }
270 /**
271 * Get the message key for an upload error code.
272 *
273 * @param int $error_code The upload error code.
274 *
275 * @return string
276 *
277 * @since 1.0.0
278 */
279 protected function get_message_key_for_error(int $error_code)
280 {
281 static $keys = [\UPLOAD_ERR_INI_SIZE => 'upload.ini_size_exceeded', \UPLOAD_ERR_FORM_SIZE => 'upload.form_size_exceeded', \UPLOAD_ERR_PARTIAL => 'upload.partial', \UPLOAD_ERR_NO_FILE => 'upload.no_file', \UPLOAD_ERR_CANT_WRITE => 'upload.cant_write', \UPLOAD_ERR_NO_TMP_DIR => 'upload.no_tmp_dir', \UPLOAD_ERR_EXTENSION => 'upload.stopped_by_extension'];
282 return $keys[$error_code] ?? 'upload.unknown_error';
283 }
284 /**
285 * Get the maximum file size of the uploaded file.
286 *
287 * @return int
288 *
289 * @since 1.0.0
290 */
291 protected function get_max_file_size()
292 {
293 $size_post_max = $this->parse_file_size(\ini_get('post_max_size'));
294 $size_upload_max = $this->parse_file_size(\ini_get('upload_max_filesize'));
295 return \min($size_post_max ?: \PHP_INT_MAX, $size_upload_max ?: \PHP_INT_MAX);
296 }
297 /**
298 * Parse the file size.
299 *
300 * @param string $size The size.
301 *
302 * @return int
303 *
304 * @since 1.0.0
305 */
306 protected function parse_file_size(string $size)
307 {
308 if ($size === '') {
309 return 0;
310 }
311 $size = \strtolower(\trim($size));
312 $max = \ltrim($size, '+');
313 if (str_starts_with($max, '0x')) {
314 $max = \intval($max, 16);
315 } elseif (str_starts_with($max, '0')) {
316 $max = \intval($max, 8);
317 } else {
318 $max = \intval($max);
319 }
320 switch (\substr($size, -1)) {
321 case 't':
322 $max *= 1024;
323 // no break
324 case 'g':
325 $max *= 1024;
326 // no break
327 case 'm':
328 $max *= 1024;
329 // no break
330 case 'k':
331 $max *= 1024;
332 }
333 return $max;
334 }
335 /**
336 * Convert the uploaded file to an array.
337 *
338 * @return array
339 *
340 * @since 1.0.0
341 */
342 public function to_array()
343 {
344 return ['path' => $this->getPathname(), 'name' => $this->get_client_original_name(), 'type' => $this->get_client_mime_type(), 'error' => $this->get_error(), 'size' => $this->get_size()];
345 }
346 /**
347 * Convert the uploaded file to a string.
348 *
349 * @return string
350 *
351 * @since 1.0.0
352 */
353 public function __toString()
354 {
355 return Arr::json_encode($this->to_array());
356 }
357 /**
358 * Convert the uploaded file to a JSON string.
359 *
360 * @return string
361 *
362 * @since 1.0.0
363 */
364 public function jsonSerialize() : string
365 {
366 return $this->__toString();
367 }
368 }
369