Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
78 / 78
100.00% covered (success)
100.00%
31 / 31
CRAP
100.00% covered (success)
100.00%
1 / 1
File
100.00% covered (success)
100.00%
78 / 78
100.00% covered (success)
100.00%
31 / 31
52
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
6
 getMimeTypes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getFileMimeType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 formatFileSize
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
1
 setBasename
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getBasename
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasBasename
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setFilename
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getFilename
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasFilename
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setExtension
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 getExtension
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasExtension
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setPath
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getPath
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasPath
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setSize
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getSize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasSize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 formatSize
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
1 / 1
13
 setMimeType
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getMimeType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 hasMimeType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setDefaultMimeType
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getDefaultMimeType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isDefaultMimeType
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getAllMimeTypes
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 exists
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 getContents
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 toArray
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2/**
3 * Pop PHP Framework (http://www.popphp.org/)
4 *
5 * @link       https://github.com/popphp/popphp-framework
6 * @author     Nick Sagona, III <dev@nolainteractive.com>
7 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
8 * @license    http://www.popphp.org/license     New BSD License
9 */
10
11/**
12 * @namespace
13 */
14namespace Pop\Utils;
15
16/**
17 * Pop utils file helper class
18 *
19 * @category   Pop
20 * @package    Pop\Utils
21 * @author     Nick Sagona, III <dev@nolainteractive.com>
22 * @copyright  Copyright (c) 2009-2024 NOLA Interactive, LLC. (http://www.nolainteractive.com)
23 * @license    http://www.popphp.org/license     New BSD License
24 * @version    2.1.0
25 */
26class File
27{
28
29    /**
30     * Basename (filename.ext)
31     * @var ?string
32     */
33    protected ?string $basename = null;
34
35    /**
36     * Filename (filename)
37     * @var ?string
38     */
39    protected ?string $filename = null;
40
41    /**
42     * Extension (.ext)
43     * @var ?string
44     */
45    protected ?string $extension = null;
46
47    /**
48     * Path (/some/path)
49     * @var ?string
50     */
51    protected ?string $path = null;
52
53    /**
54     * Size
55     * @var int
56     */
57    protected int $size = 0;
58
59    /**
60     * Mime type
61     * @var ?string
62     */
63    protected ?string $mimeType = null;
64
65    /**
66     * Mime types
67     * @var array
68     */
69    protected static array $mimeTypes = [
70        'avi'   => 'video/x-msvideo',
71        'bin'   => 'application/octet-stream',
72        'bmp'   => 'image/bmp',
73        'bz'    => 'application/x-bzip',
74        'bz2'   => 'application/x-bzip2',
75        'css'   => 'text/css',
76        'csv'   => 'text/csv',
77        'doc'   => 'application/msword',
78        'docx'  => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
79        'gz'    => 'application/gzip',
80        'gif'   => 'image/gif',
81        'htm'   => 'text/html',
82        'html'  => 'text/html',
83        'ico'   => 'image/vnd.microsoft.icon',
84        'ics'   => 'text/calendar',
85        'jar'   => 'application/java-archive',
86        'jpe'   => 'image/jpeg',
87        'jpg'   => 'image/jpeg',
88        'jpeg'  => 'image/jpeg',
89        'js'    => 'text/javascript',
90        'json'  => 'application/json',
91        'jwt'   => 'application/jwt',
92        'log'   => 'text/plain',
93        'mid'   => 'audio/midi',
94        'midi'  => 'audio/midi',
95        'mp3'   => 'audio/mpeg',
96        'mp4'   => 'video/mp4',
97        'mpeg'  => 'video/mpeg',
98        'odp'   => 'application/vnd.oasis.opendocument.presentation',
99        'ods'   => 'application/vnd.oasis.opendocument.spreadsheet',
100        'odt'   => 'application/vnd.oasis.opendocument.text',
101        'oga'   => 'audio/ogg',
102        'ogv'   => 'video/ogg',
103        'ogx'   => 'application/ogg',
104        'otf'   => 'font/otf',
105        'png'   => 'image/png',
106        'pdf'   => 'application/pdf',
107        'php'   => 'application/x-httpd-php',
108        'ppt'   => 'application/vnd.ms-powerpoint',
109        'pptx'  => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
110        'psd'   => 'image/vnd.adobe.photoshop',
111        'rar'   => 'application/vnd.rar',
112        'rtf'   => 'application/rtf',
113        'sgml'  => 'application/sgml',
114        'sql'   => 'application/sql',
115        'svg'   => 'image/svg+xml',
116        'tar'   => 'application/x-tar',
117        'tif'   => 'image/tiff',
118        'tiff'  => 'image/tiff',
119        'ttf'   => 'font/ttf',
120        'tsv'   => 'text/tsv',
121        'txt'   => 'text/plain',
122        'wav'   => 'audio/wav',
123        'xhtml' => 'application/xhtml+xml',
124        'xls'   => 'application/vnd.ms-excel',
125        'xlsx'  => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
126        'xml'   => 'application/xml',
127        'yaml'  => 'application/yaml',
128        'zip'   => 'application/zip',
129    ];
130
131    /**
132     * Default mime types
133     * @var string
134     */
135    protected static string $defaultMimeType = 'application/octet-stream';
136
137    /**
138     * Constructor
139     *
140     * Instantiate the file object
141     *
142     * @param  ?string $filename
143     */
144    public function __construct(?string $filename = null)
145    {
146        $info = [];
147
148        if (!empty($filename)) {
149            $info = pathinfo($filename);
150            $this->setSize(filesize($filename));
151        }
152
153        if (!empty($info['basename'])) {
154            $this->setBasename($info['basename']);
155        }
156        if (!empty($info['filename'])) {
157            $this->setFilename($info['filename']);
158        }
159        if (!empty($info['dirname'])) {
160            $this->setPath($info['dirname']);
161        }
162        if (!empty($info['extension'])) {
163            $this->setExtension($info['extension']);
164        }
165    }
166
167    /**
168     * Get common mime types
169     *
170     * @return array
171     */
172    public static function getMimeTypes(): array
173    {
174        return (new self())->getAllMimeTypes();
175    }
176
177    /**
178     * Get file's mime type
179     *
180     * @param  string $filename
181     * @return ?string
182     */
183    public static function getFileMimeType(string $filename): ?string
184    {
185        return (new self($filename))->getMimeType();
186    }
187
188    /**
189     * Format file size
190     *
191     * @param  int    $filesize
192     * @param  int    $round
193     * @param  ?bool  $case null = UPPER (MB); true = Title (Mb); false = lower (mb)
194     * @param  string $space
195     * @return string
196     */
197    public static function formatFileSize(int $filesize, int $round = 2, ?bool $case = null, string $space = ' '): string
198    {
199        $file = new self();
200        $file->setSize($filesize);
201        return $file->formatSize();
202    }
203
204    /**
205     * Set the basename
206     *
207     * @param  string $basename
208     * @return File
209     */
210    public function setBasename(string $basename): File
211    {
212        $this->basename = $basename;
213        return $this;
214    }
215
216    /**
217     * Get the basename
218     *
219     * @return ?string
220     */
221    public function getBasename(): ?string
222    {
223        return $this->basename;
224    }
225
226    /**
227     * Has the basename
228     *
229     * @return bool
230     */
231    public function hasBasename(): bool
232    {
233        return ($this->basename !== null);
234    }
235
236    /**
237     * Set the filename
238     *
239     * @param  string $filename
240     * @return File
241     */
242    public function setFilename(string $filename): File
243    {
244        $this->filename = $filename;
245        return $this;
246    }
247
248    /**
249     * Get the filename
250     *
251     * @return ?string
252     */
253    public function getFilename(): ?string
254    {
255        return $this->filename;
256    }
257
258    /**
259     * Has the filename
260     *
261     * @return bool
262     */
263    public function hasFilename(): bool
264    {
265        return ($this->filename !== null);
266    }
267
268    /**
269     * Set the extension
270     *
271     * @param  string $extension
272     * @return File
273     */
274    public function setExtension(string $extension): File
275    {
276        $this->extension = $extension;
277        if (array_key_exists(strtolower($extension), self::$mimeTypes)) {
278            $this->setMimeType(self::$mimeTypes[strtolower($extension)]);
279        } else {
280            $this->setDefaultMimeType();
281        }
282        return $this;
283    }
284
285    /**
286     * Get the extension
287     *
288     * @return ?string
289     */
290    public function getExtension(): ?string
291    {
292        return $this->extension;
293    }
294
295    /**
296     * Has the extension
297     *
298     * @return bool
299     */
300    public function hasExtension(): bool
301    {
302        return ($this->extension !== null);
303    }
304
305    /**
306     * Set the path
307     *
308     * @param  string $path
309     * @return File
310     */
311    public function setPath(string $path): File
312    {
313        $this->path = $path;
314        return $this;
315    }
316
317    /**
318     * Get the path
319     *
320     * @return ?string
321     */
322    public function getPath(): ?string
323    {
324        return $this->path;
325    }
326
327    /**
328     * Has the path
329     *
330     * @return bool
331     */
332    public function hasPath(): bool
333    {
334        return ($this->path !== null);
335    }
336
337    /**
338     * Set the size
339     *
340     * @param  int $size
341     * @return File
342     */
343    public function setSize(int $size): File
344    {
345        $this->size = $size;
346        return $this;
347    }
348
349    /**
350     * Get the size
351     *
352     * @return int
353     */
354    public function getSize(): int
355    {
356        return $this->size;
357    }
358
359    /**
360     * Has the size
361     *
362     * @return bool
363     */
364    public function hasSize(): bool
365    {
366        return ($this->size > 0);
367    }
368
369    /**
370     * Format size into human-readable string
371     *
372     * @param  int    $round
373     * @param  ?bool  $case null = UPPER (MB); true = Title (Mb); false = lower (mb)
374     * @param  string $space
375     * @return string
376     */
377    public function formatSize(int $round = 2, ?bool $case = null, string $space = ' '): string
378    {
379        $prefix = '';
380        $byte   = ($case !== null) ? 'b' : 'B';
381
382        if ($this->size >= 1000000000000) {
383            $prefix    = ($case !== false) ? 'T' : 't';
384            $formatted = round($this->size / 1000000000000, $round);
385        } else if (($this->size < 1000000000000) && ($this->size >= 1000000000)) {
386            $prefix    = ($case !== false) ? 'G' : 'g';
387            $formatted = round($this->size / 1000000000, $round);
388        } else if (($this->size < 1000000000) && ($this->size >= 1000000)) {
389            $prefix    = ($case !== false) ? 'M' : 'm';
390            $formatted = round($this->size / 1000000, $round);
391        } else if (($this->size < 1000000) && ($this->size >= 1000)) {
392            $prefix    = ($case !== false) ? 'K' : 'k';
393            $formatted = round($this->size / 1000, $round);
394        } else {
395            $formatted = $this->size;
396        }
397
398        return $formatted . $space . $prefix . $byte;
399    }
400
401    /**
402     * Set the mime type
403     *
404     * @param  string $mimeType
405     * @return File
406     */
407    public function setMimeType(string $mimeType): File
408    {
409        $this->mimeType = $mimeType;
410        return $this;
411    }
412
413    /**
414     * Get the mime type
415     *
416     * @return ?string
417     */
418    public function getMimeType(): ?string
419    {
420        return $this->mimeType;
421    }
422
423    /**
424     * Has the mime type
425     *
426     * @return bool
427     */
428    public function hasMimeType(): bool
429    {
430        return ($this->mimeType !== null);
431    }
432
433    /**
434     * Set the mime type to default mime type
435     *
436     * @return File
437     */
438    public function setDefaultMimeType(): File
439    {
440        $this->mimeType = self::$defaultMimeType;
441        return $this;
442    }
443
444    /**
445     * Get the default mime type
446     *
447     * @return string
448     */
449    public function getDefaultMimeType(): string
450    {
451        return self::$defaultMimeType;
452    }
453
454    /**
455     * Set the default mime type
456     *
457     * @return bool
458     */
459    public function isDefaultMimeType(): bool
460    {
461        return ($this->mimeType == self::$defaultMimeType);
462    }
463
464    /**
465     * Get the all common mime types
466     *
467     * @return array
468     */
469    public function getAllMimeTypes(): array
470    {
471        return self::$mimeTypes;
472    }
473
474    /**
475     * Does the file exist
476     *
477     * @return bool
478     */
479    public function exists(): bool
480    {
481        $fullPath = ($this->hasPath()) ? $this->path . DIRECTORY_SEPARATOR . $this->basename : $this->basename;
482        return file_exists($fullPath);
483    }
484
485    /**
486     * Get the file contents
487     *
488     * @return mixed
489     */
490    public function getContents(): mixed
491    {
492        $fullPath = ($this->hasPath()) ? $this->path . DIRECTORY_SEPARATOR . $this->basename : $this->basename;
493        return file_get_contents($fullPath);
494    }
495
496    /**
497     * Convert file to an array
498     *
499     * @return array
500     */
501    public function toArray(): array
502    {
503        return [
504            'basename'  => $this->basename,
505            'filename'  => $this->filename,
506            'extension' => $this->extension,
507            'path'      => $this->path,
508            'size'      => $this->size,
509            'mime_type' => $this->mimeType,
510        ];
511    }
512
513    /**
514     * To string
515     *
516     * @return string
517     */
518    public function __toString(): string
519    {
520        return ($this->hasPath()) ? $this->path . DIRECTORY_SEPARATOR . $this->basename : $this->basename;
521    }
522
523}