PluginProbe
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution / 2.1.1
Fluent Booking – The Ultimate Appointments Scheduling, Events Booking, Events Calendar Solution v2.1.1
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 1.7.2 All 33 releases
fluent-booking / vendor / wpfluent / framework / src / WPFluent / Support / File.php

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

595 lines 15.0 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\Support;
4
5 use FluentBooking\Framework\Support\Str;
6
7 /**
8 * Class File
9 *
10 * A wrapper for the WordPress Filesystem API.
11 */
12 class File
13 {
14 /**
15 * Instance of the WordPress Filesystem API.
16 *
17 * @var \WP_Filesystem_Base|false
18 */
19 protected static $filesystem;
20
21 /**
22 * Initialize or return the WordPress Filesystem API instance.
23 *
24 * @return \WP_Filesystem_Base
25 */
26 public static function init()
27 {
28 return static::fileSystem();
29 }
30
31 /**
32 * Initialize or return the WordPress Filesystem API instance.
33 *
34 * @return \WP_Filesystem_Base
35 */
36 public static function fileSystem()
37 {
38 global $wp_filesystem;
39
40 if (isset($wp_filesystem)) {
41 return $wp_filesystem;
42 }
43
44 if (!function_exists('WP_Filesystem')) {
45 require_once ABSPATH . 'wp-admin/includes/file.php';
46 }
47
48 if (!WP_Filesystem()) {
49 throw new \Exception(
50 'Could not initialize the WordPress filesystem.'
51 );
52 }
53
54 if (
55 $wp_filesystem === null ||
56 !($wp_filesystem instanceof \WP_Filesystem_Base)
57 ) {
58 throw new \Exception(
59 'The WordPress filesystem object is not set or is invalid.'
60 );
61 }
62
63 return $wp_filesystem;
64 }
65
66 /**
67 * Check if a file or directory exists.
68 *
69 * @param string $path
70 * @return bool
71 */
72 public static function exists($path)
73 {
74 return static::fileSystem()->exists($path);
75 }
76
77 /**
78 * Read the contents of a file.
79 *
80 * @param string $path
81 * @return string
82 */
83 public static function get($path)
84 {
85 return static::fileSystem()->get_contents($path);
86 }
87
88 /**
89 * Read the contents of a file.
90 *
91 * @param string $path
92 * @return string
93 */
94 public static function read($path)
95 {
96 return static::get($path);
97 }
98
99 /**
100 * Read the contents of a file.
101 *
102 * @param string $path
103 * @return string
104 */
105 public static function getJson($path, $asArray = true)
106 {
107 $content = static::get($path);
108
109 $data = json_decode($content, $asArray);
110
111 if (json_last_error() !== JSON_ERROR_NONE) {
112 throw new \RuntimeException(
113 'Invalid JSON: ' . json_last_error_msg()
114 );
115 }
116
117 return $data;
118 }
119
120 /**
121 * Read the contents of a file as lines of array.
122 *
123 * @param string $path
124 * @return string
125 */
126 public static function getArray($path)
127 {
128 return static::fileSystem()->get_contents_array($path);
129 }
130
131 /**
132 * Read the contents of a file as lines of array.
133 *
134 * @param string $path
135 * @return string
136 */
137 public static function readAsArray($path)
138 {
139 return static::getArray($path);
140 }
141
142 /**
143 * Write contents to a file.
144 *
145 * @param string $path
146 * @param string $contents
147 * @param int|false $mode The file permissions as octal number.
148 * @return bool
149 */
150 public static function put($path, $contents, $mode = false)
151 {
152 return static::fileSystem()->put_contents(
153 $path, $contents, $mode
154 );
155 }
156
157 /**
158 * Write contents to a file.
159 *
160 * @param string $path
161 * @param string $contents
162 * @param int|false $mode The file permissions as octal number.
163 * @return bool
164 */
165 public static function write($path, $contents, $mode = false)
166 {
167 return static::put($path, $contents, $mode);
168 }
169
170 /**
171 * Append contents to a file.
172 *
173 * @param string $path
174 * @param string $contents
175 * @return bool
176 */
177 public static function append($path, $contents)
178 {
179 $existingContents = static::exists($path) ? static::get($path) : '';
180
181 $newContents = $existingContents . $contents;
182
183 return static::put($path, $newContents);
184 }
185
186 /**
187 * Prepend contents to a file.
188 *
189 * @param string $path
190 * @param string $contents
191 * @return bool
192 */
193 public static function prepend($path, $contents)
194 {
195 $existingContents = static::exists($path) ? static::get($path) : '';
196
197 $newContents = $contents . $existingContents;
198
199 return static::put($path, $newContents);
200 }
201
202
203 /**
204 * Delete a file or directory.
205 *
206 * @param string $path
207 * @param bool $recursive
208 * @return bool
209 */
210 public static function delete($path, $recursive = true)
211 {
212 return static::fileSystem()->delete($path, $recursive);
213 }
214
215 /**
216 * Delete a file or directory.
217 *
218 * @param string $path
219 * @param bool $recursive
220 * @return bool
221 */
222 public static function deleteDirectory($path, $recursive = true)
223 {
224 return static::fileSystem()->delete($path, $recursive, 'd');
225 }
226
227 /**
228 * Delete a file or directory.
229 *
230 * @param string $path
231 * @param bool $recursive
232 * @return bool
233 */
234 public static function rmdir($path, $recursive = true)
235 {
236 return static::fileSystem()->delete($path, $recursive, 'd');
237 }
238
239 /**
240 * Create a directory.
241 *
242 * @param string $path
243 * @param int $chmod
244 * @param string|int|false $chown Optional. A user name or number.
245 * @param string|int|false $chgrp Optional. A group name or number.
246 * @return bool
247 */
248 public static function mkdir(
249 $path, $chmod = FS_CHMOD_DIR, $chown = false, $chgrp = false
250 )
251 {
252 return static::fileSystem()->mkdir($path, $chmod, $chown, $chgrp);
253 }
254
255 /**
256 * Create a directory.
257 *
258 * @param string $path
259 * @param int $chmod
260 * @param string|int|false $chown Optional. A user name or number.
261 * @param string|int|false $chgrp Optional. A group name or number.
262 * @return bool
263 */
264 public static function makeDirectory(
265 $path, $chmod = FS_CHMOD_DIR, $chown = false, $chgrp = false
266 )
267 {
268 return static::mkdir($path, $chmod, $chown, $chgrp);
269 }
270
271 /**
272 * List files and directories in a path.
273 *
274 * @param string $path
275 * @param bool $withHidden
276 * @param bool $recurse
277 * @return array An associative array with details.
278 */
279 public static function list($path, $withHidden = true, $recurse = false)
280 {
281 return static::fileSystem()->dirlist($path, $withHidden, $recurse);
282 }
283
284 /**
285 * Get the list of files and directories as plain array.
286 *
287 * @param string $path
288 * @param bool $withHidden
289 * @return array
290 */
291 public static function getList($path, $withHidden = true)
292 {
293 return array_values(array_map(function ($item) {
294 return $item['name'];
295 }, static::list($path, $withHidden)));
296 }
297
298 /**
299 * List files in a path.
300 *
301 * @param string $path
302 * @param bool $withHidden
303 * @param bool $recurse
304 * @return array An associative array with details.
305 */
306 public static function files($path, $withHidden = true, $recurse = false)
307 {
308 $list = static::list($path, $withHidden, $recurse);
309
310 return array_filter($list, function ($item) {
311 return $item['type'] === 'f';
312 });
313 }
314
315 /**
316 * Get the list of files as plain array.
317 *
318 * @param string $path
319 * @param bool $withHidden
320 * @return array
321 */
322 public static function getFiles($path, $withHidden = true)
323 {
324 return array_values(array_map(function($item) {
325 return $item['name'];
326 }, static::files($path, $withHidden)));
327 }
328
329 /**
330 * List directories in a path.
331 *
332 * @param string $path
333 * @param bool $withHidden
334 * @param bool $recurse
335 * @return array An associative array with details.
336 */
337 public static function directories($path, $withHidden = true, $recurse = true)
338 {
339 $list = static::list($path, $withHidden, $recurse);
340
341 return array_filter($list, function ($item) {
342 return $item['type'] === 'd';
343 });
344 }
345
346 /**
347 * Get the list of directories as plain array.
348 *
349 * @param string $path
350 * @param bool $withHidden
351 * @return array
352 */
353 public static function getDirectories($path, $withHidden = true)
354 {
355 return array_values(array_map(function($item) {
356 return $item['name'];
357 }, static::directories($path, $withHidden)));
358 }
359
360 /**
361 * Copy a file.
362 *
363 * @param string $source
364 * @param string $dest
365 * @param bool $overwrite
366 * @return bool
367 */
368 public static function copy($source, $dest, $overwrite = true)
369 {
370 return static::fileSystem()->copy($source, $dest, $overwrite);
371 }
372
373 /**
374 * Move a file.
375 *
376 * @param string $source
377 * @param string $destination
378 * @param bool $overwrite
379 * @return bool
380 */
381 public static function move($source, $destination, $overwrite = false)
382 {
383 return static::copy(
384 $source, $destination, $overwrite
385 ) && static::delete($source);
386 }
387
388 /**
389 * Get file metadata.
390 *
391 * @param string $path
392 * @return array|false
393 */
394 public static function getInfo($path)
395 {
396 if (!static::exists($path)) {
397 return false;
398 }
399
400 $fs = static::fileSystem();
401
402 $metadata = [
403 'path' => $path,
404 'size' => $fs->size($path),
405 'atime' => $fs->atime($path),
406 'mtime' => $fs->mtime($path),
407 'mode' => $fs->getchmod($path),
408 'is_dir' => $fs->is_dir($path),
409 'is_file' => $fs->is_file($path)
410 ];
411
412 if ($metadata['is_file']) {
413 $metadata['is_image'] = static::isImage($path);
414 if ($metadata['is_image']) {
415 $metadata['image_meta'] = static::getImageMetadata($path);
416 }
417 }
418
419 return $metadata;
420 }
421
422 /**
423 * Get file/dir metadata using stat.
424 *
425 * @param string $path
426 * @return array|false
427 */
428 public static function getStats($path)
429 {
430 if (!static::exists($path)) {
431 return false;
432 }
433
434 clearstatcache();
435
436 $stat = stat($path);
437
438 // Convert permissions to a readable format (e.g., "rw-r--r--")
439 // Get the last 3 characters (user, group, others)
440 $permissions = substr(sprintf('%o', $stat['mode']), -3);
441
442 $permissionsString = '';
443 $permissionsString .= ($stat['mode'] & 0x0100) ? 'r' : '-'; // Owner read
444 $permissionsString .= ($stat['mode'] & 0x0080) ? 'w' : '-'; // Owner write
445 $permissionsString .= ($stat['mode'] & 0x0040) ? 'x' : '-'; // Owner execute
446 $permissionsString .= ($stat['mode'] & 0x0020) ? 'r' : '-'; // Group read
447 $permissionsString .= ($stat['mode'] & 0x0010) ? 'w' : '-'; // Group write
448 $permissionsString .= ($stat['mode'] & 0x0008) ? 'x' : '-'; // Group execute
449 $permissionsString .= ($stat['mode'] & 0x0004) ? 'r' : '-'; // Others read
450 $permissionsString .= ($stat['mode'] & 0x0002) ? 'w' : '-'; // Others write
451 $permissionsString .= ($stat['mode'] & 0x0001) ? 'x' : '-'; // Others execute
452
453 $permissionsNumeric = (int) substr(sprintf('%o', $stat['mode']), -3);
454
455 $metadata = [
456 'path' => $path,
457 'size' => $stat['size'],
458 'size_string' => size_format($stat['size']),
459 'last_modified_timestamp' => $stat['mtime'],
460 'last_modified_at' => date('Y-m-d H:i:s', $stat['mtime']),
461 'last_access_timestamp' => $stat['atime'],
462 'last_accessed_at' => date('Y-m-d H:i:s', $stat['atime']),
463 'last_change_timestamp' => $stat['ctime'],
464 'last_changed_at' => date('Y-m-d H:i:s', $stat['ctime']),
465 'permission' => $permissionsNumeric,
466 'permission_string' => $permissionsString,
467 'is_dir' => ($stat['mode'] & 0040000) === 0040000,
468 'is_file' => ($stat['mode'] & 0100000) === 0100000
469 ];
470
471 if ($metadata['is_file']) {
472 $metadata['is_image'] = static::isImage($path);
473 if ($metadata['is_image']) {
474 $metadata['image_meta'] = static::getImageMetadata($path);
475 }
476 }
477
478 return $metadata;
479 }
480
481
482 /**
483 * Searches for metadata in the first 8 KB of a file.
484 *
485 * @param string $file
486 * @param array $keys
487 * @return array
488 */
489 public static function getMetaData($file, $keys = [])
490 {
491 $data = [];
492
493 if (!file_exists($file)) {
494 return $data;
495 }
496
497 $content = file_get_contents($file, false, null, 0, 8 * 1024);
498
499 if ($content === false) {
500 return $data;
501 }
502
503 $content = str_replace("\r", "\n", $content);
504
505 $pattern = '/^(?:[ \t]*<\?php)?[ \t\/*#@]*(.*?):(.*)$/mi';
506
507 if (preg_match_all($pattern, $content, $matches)) {
508 foreach ($matches[1] as $key => $value) {
509 $name = str_replace(' ', '_', strtolower(trim($value)));
510 $data[$name] = trim($matches[2][$key]);
511 }
512 }
513
514 $normalizedKeys = array_map(function ($key) {
515 return strtolower(str_replace(' ', '_', $key));
516 }, $keys);
517
518 return $keys ? array_intersect_key(
519 $data, array_flip($normalizedKeys)
520 ) : $data;
521 }
522
523 /**
524 * Check if a file is an image based on its MIME type.
525 *
526 * @param string $path
527 * @return bool
528 */
529 public static function isImage($path)
530 {
531 return file_is_valid_image($path);
532 }
533
534 /**
535 * Get image metadata using EXIF.
536 *
537 * @param string $path
538 * @return array|false
539 */
540 public static function getImageMetadata($path)
541 {
542 if (!static::exists($path)) {
543 return false;
544 }
545
546 $image_info = getimagesize($path);
547
548 if ($image_info === false) {
549 return false;
550 }
551
552 $metadata = wp_read_image_metadata($path);
553
554 return array_merge([
555 'width' => $image_info[0],
556 'height' => $image_info[1],
557 'type' => $image_info['mime'],
558 ], $metadata ?: []);
559 }
560
561 /**
562 * Dynamically handle calls to the filesystem API.
563 *
564 * @param string $method
565 * @param array $args
566 * @return mixed
567 */
568 public function __call($method, $args)
569 {
570 $fs = static::fileSystem();
571
572 if (!method_exists($fs, $method)) {
573 $method = strtolower(
574 preg_replace([
575 '/([a-z\d])([A-Z])/', '/([^_])([A-Z][a-z])/'
576 ], '$1_$2', $method)
577 );
578 }
579
580 return $fs->{$method}(...$args);
581 }
582
583 /**
584 * Dynamically handle static calls to the filesystem API.
585 *
586 * @param string $method
587 * @param array $args
588 * @return mixed
589 */
590 public static function __callStatic($method, $args)
591 {
592 return (new static)->{$method}(...$args);
593 }
594 }
595