PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 1.7.1
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v1.7.1
2.5.0 2.4.0 2.3.0 2.2.5 2.2.0 2.1.2 2.1.1 trunk 1.10.0 1.10.01 1.10.02 1.5.0 1.5.01 1.5.02 1.5.1 1.5.10 1.5.20 1.5.21 1.5.22 1.5.23 1.5.24 1.5.25 1.6.0 1.7.0 1.7.1 All 34 releases
fluent-booking / vendor / wpfluent / framework / src / WPFluent / Http / Request / File.php

File.php in Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution 1.7.1, at vendor/wpfluent/framework/src/WPFluent/Http/Request/File.php

463 lines 11.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentBooking\Framework\Http\Request;
4
5 use SplFileInfo;
6 use JsonSerializable;
7 use RuntimeException;
8 use FluentBooking\Framework\Support\Util;
9 use FluentBooking\Framework\Foundation\App;
10 use FluentBooking\Framework\Validator\Contracts\File as Contract;
11
12 class File extends SplFileInfo implements Contract, JsonSerializable
13 {
14 /**
15 * Original file name.
16 *
17 * @var string $originalName
18 */
19 private $originalName;
20
21 /**
22 * Mime type of the file.
23 *
24 * @var string $mimeType
25 */
26 private $mimeType;
27
28 /**
29 * File size in bytes.
30 *
31 * @var int|null $size
32 */
33 private $size;
34
35 /**
36 * File upload error.
37 *
38 * @var int $error
39 */
40 private $error;
41
42 /**
43 * HTTP File instantiator.
44 *
45 * @param $path
46 * @param $originalName
47 * @param null $mimeType
48 * @param null $size
49 * @param null $error
50 */
51 public function __construct(
52 $path,
53 $originalName,
54 $mimeType = null,
55 $size = null,
56 $error = null
57 ) {
58 $this->init($path, $size, $error);
59 $this->originalName = $this->getName($originalName);
60 $this->mimeType = $this->getFileMimeType($mimeType);
61 }
62
63 /**
64 * Init the file object with size and error.
65 *
66 * @param string $path
67 * @param int|null $size
68 * @param string|nill $error
69 * @return void
70 */
71 protected function init($path, $size, $error)
72 {
73 $this->size = $size ?: @filesize($path);
74 $this->error = $error ?: UPLOAD_ERR_OK;
75 parent::__construct($path);
76 }
77
78 /**
79 * @taken from \Symfony\Component\HttpFoundation\File\File
80 *
81 * Returns locale independent base name of the given path.
82 *
83 * @param string $name The new file name
84 *
85 * @return string containing
86 */
87 public function getName($name)
88 {
89 $originalName = str_replace('\\', '/', $name);
90
91 $pos = strrpos($originalName, '/');
92
93 $originalName = false === $pos ? $originalName : substr(
94 $originalName, $pos + 1
95 );
96
97 return sanitize_file_name($originalName);
98 }
99
100 public function getFileMimeType($mimeType)
101 {
102 $mimeType = $mimeType ?: $this->getMimeType();
103
104 if (!$mimeType) {
105 $path = $this->getPathname() ?: $this->getRealPath();
106 if ($handle = @fopen($path, 'rb')) {
107 $data = fread($handle, 8192);
108 $finfo = new \finfo(FILEINFO_MIME_TYPE);
109 $mimeType = $finfo->buffer($data);
110 fclose($handle);
111 }
112 }
113
114 return $mimeType ?: 'application/octet-stream';
115 }
116
117 /**
118 * Get the file upload error.
119 *
120 * @return int
121 */
122 public function getError()
123 {
124 return $this->error;
125 }
126
127 /**
128 * Returns whether the file was uploaded successfully.
129 *
130 * @return bool True if the file has been uploaded with HTTP and no error occurred
131 */
132 public function isValid()
133 {
134 $isOk = UPLOAD_ERR_OK === $this->getError();
135
136 return $isOk && is_uploaded_file($this->getPathname());
137 }
138
139 /**
140 * Returns the original file name.
141 *
142 * @return string The Name Of the file
143 */
144 public function getClientOriginalName()
145 {
146 return $this->originalName;
147 }
148
149 /**
150 * Returns the original file extension.
151 *
152 * It is extracted from the original file name that was uploaded.
153 * Then it should not be considered as a safe value.
154 *
155 * @return string The extension
156 */
157 public function getClientOriginalExtension()
158 {
159 return pathinfo($this->originalName, PATHINFO_EXTENSION);
160 }
161
162 /**
163 * Take an educated guess of the file's extension.
164 *
165 * @return mixed|null
166 */
167 public function guessExtension()
168 {
169 return $this->getMimeTypeAndExtension()['ext'];
170 }
171
172 /**
173 * Take an educated guess of the file's mime type.
174 *
175 * @return string
176 */
177 public function getMimeType()
178 {
179 return $this->getMimeTypeAndExtension()['type'];
180 }
181
182 /**
183 * Take an educated guess of the file's mime type and ext
184 * based on the WordsPress' get_allowed_mime_types.
185 *
186 * @return array
187 * @see https://developer.wordpress.org/reference/functions/get_allowed_mime_types
188 * @see https://developer.wordpress.org/reference/functions/wp_get_mime_types
189 */
190 public function getMimeTypeAndExtension()
191 {
192 $path = $this->getPathname();
193
194 if(!function_exists('wp_check_filetype_and_ext')) {
195 require_once ABSPATH .'wp-admin/includes/file.php';
196 }
197
198 return wp_check_filetype_and_ext($path, $this->originalName);
199 }
200
201 /**
202 * Get the file name.
203 *
204 * @return string
205 */
206 public function getSavedFileName()
207 {
208 if ($name = $this->originalName) {
209 return $name;
210 }
211
212 return basename($this->getPathname());
213 }
214
215 /**
216 * Get the url from path.
217 *
218 * @return string
219 */
220 public function getUrl()
221 {
222 return $this->url($this->getPathname());
223 }
224
225 /**
226 * Returns the contents of the file.
227 *
228 * @return string the contents of the file
229 *
230 * @throws RuntimeException
231 */
232 public function getContents()
233 {
234 $level = error_reporting(0);
235 $content = file_get_contents($this->getPathname());
236 error_reporting($level);
237 if (false === $content) {
238 $error = error_get_last();
239 throw new RuntimeException($error['message']);
240 }
241
242 return $content;
243 }
244
245 /**
246 * Move the file to a new location.
247 *
248 * @param string $directory Target Path
249 * @param string $name Target file name (optional)
250 * @return self
251 * @throws RuntimeException
252 */
253 public function move($directory, $name = null)
254 {
255 $err = '';
256
257 $target = $this->getTargetFile($directory, $name);
258
259 set_error_handler(function ($_, $msg) use (&$err) { $err = $msg; });
260
261 try {
262 $renamed = rename($this->getPathname(), $target);
263 } finally {
264 restore_error_handler();
265 }
266
267 if (!$renamed) {
268 throw new RuntimeException(
269 sprintf(
270 'Could not move the file "%s" to "%s" (%s).',
271 $this->getPathname(), $target, strip_tags($err)
272 )
273 );
274 }
275
276 @chmod($target, 0666 & ~umask());
277
278 return $target;
279 }
280
281 /**
282 * Save the uploaded file.
283 *
284 * @param string $path
285 * @return self (File Object)
286 * @throws RuntimeException
287 */
288 public function save($path = null)
289 {
290 $path = $this->resolveTargetPath($path);
291
292 return $this->move($path);
293 }
294
295 /**
296 * Save the uploaded file with a given name.
297 *
298 * @param string $name
299 * @param string $path
300 * @return self (File Object)
301 * @throws RuntimeException
302 */
303 public function saveAs($name, $path = null)
304 {
305 $path = $this->resolveTargetPath($path);
306
307 return $this->move($path, $name);
308 }
309
310 /**
311 * Check that the given path exists.
312 *
313 * @param string $path
314 * @return string
315 * @throws RuntimeException
316 */
317 protected function resolveTargetPath($path)
318 {
319 if ($this->isAbsolutePath($path)) {
320
321 $pieces = array_values(
322 array_filter(
323 explode(DIRECTORY_SEPARATOR, $path)
324 )
325 );
326
327 // Sometimes developers can pass a relative directory like an
328 // absolute directory so in that case, If the root is not a
329 // real directory then make it relative and resolve it:
330 // i.e: 'a/relative/path/looks/like/an/absolute/path'
331
332 if (!is_dir(DIRECTORY_SEPARATOR.$pieces[0])) {
333 return $this->resolveTargetPath(trim($path, DIRECTORY_SEPARATOR));
334 }
335
336 $path = dirname($this->getTargetFile($path));
337
338 if (!is_dir($path)) {
339 throw new RuntimeException("Invalid file upload path: {$path}");
340 }
341
342 return $path;
343 }
344
345 $config = App::make('config');
346
347 $default = $config->get(
348 'app.file_upload_path', function() use ($config) {
349 $slug = $config->get('app.slug');
350 $uploadDir = wp_upload_dir()['basedir'];
351 $uploadDir .= DIRECTORY_SEPARATOR . $slug;
352 return $uploadDir;
353 }
354 );
355
356 $path = rtrim(
357 ($default . DIRECTORY_SEPARATOR . $path), DIRECTORY_SEPARATOR
358 );
359
360 if (is_file($path)) {
361 throw new RuntimeException("Invalid file upload path: {$path}");
362 }
363
364 if (!is_dir($path = dirname($this->getTargetFile($path)))) {
365 throw new RuntimeException("Invalid file upload path: {$path}");
366 }
367
368 return $path;
369 }
370
371 /**
372 * Check if given path is absolute.
373 *
374 * @param string $path
375 * @return boolean
376 */
377 function isAbsolutePath($path)
378 {
379 if (!$path) return false;
380
381 // For Unix-like systems
382 if (DIRECTORY_SEPARATOR === '/') {
383 return $path[0] === '/';
384 }
385
386 // For Windows
387 if (DIRECTORY_SEPARATOR === '\\') {
388 return preg_match(
389 '/^[a-zA-Z]:\\\\/', $path
390 ) || substr($path, 0, 2) === '\\\\';
391 }
392
393 return false;
394 }
395
396 /**
397 * Get the URL from the file path.
398 *
399 * @param string $path
400 * @return string
401 */
402 public function url($path = '')
403 {
404 return Util::pathToUrl($path ?: $this->getPathname());
405 }
406
407 /**
408 * Get the target file name to move (full path).
409 *
410 * @param string $directory Target Path
411 * @param string $name Target file name (optional)
412 * @return self
413 * @throws RuntimeException
414 */
415 protected function getTargetFile($directory, $name = null)
416 {
417 if (!is_dir($directory)) {
418 if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) {
419 throw new RuntimeException(
420 sprintf('Unable to create the "%s" directory.', $directory)
421 );
422 }
423 } elseif (!is_writable($directory)) {
424 throw new RuntimeException(
425 sprintf('Unable to write in the "%s" directory.', $directory)
426 );
427 }
428
429 $target = rtrim($directory, "/\\") . DIRECTORY_SEPARATOR . (
430 null === $name ? $this->originalName : $this->getName($name)
431 );
432
433 return new self($target, false);
434 }
435
436 /**
437 * Get original HTTP file array
438 *
439 * @return array
440 */
441 public function toArray()
442 {
443 return [
444 'type' => $this->mimeType,
445 'size_in_bytes' => $this->size,
446 'size' => size_format($this->size),
447 'name' => $this->getSavedFileName(),
448 'path' => $this->getPathname(),
449 'url' => $this->getUrl(),
450 ];
451 }
452
453 /**
454 * JsonSerialize implementation
455 * @return array
456 */
457 #[\ReturnTypeWillChange]
458 public function jsonSerialize()
459 {
460 return $this->toArray();
461 }
462 }
463