Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
98.98% covered (success)
98.98%
97 / 98
97.50% covered (success)
97.50%
39 / 40
CRAP
0.00% covered (danger)
0.00%
0 / 1
File
98.98% covered (success)
98.98%
97 / 98
97.50% covered (success)
97.50%
39 / 40
72
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 index
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 put
93.33% covered (success)
93.33%
14 / 15
0.00% covered (danger)
0.00%
0 / 1
15.07
 get
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
 count
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 set
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 append
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 prepend
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 exists
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 parent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 sanitize
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 size
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 owner
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 permission
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 pathInfo
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
1
 dirname
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 dirpath
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 copy
100.00% covered (success)
100.00%
9 / 9
100.00% covered (success)
100.00%
1 / 1
7
 move
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
 delete
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 getDirName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDirPath
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 createNode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isExisting
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 create
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
4
 getContent
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 setContent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 appendContent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 prependContent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getExtension
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 getParent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getDirectory
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 copyNode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 moveNode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 deleteNode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 putContent
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 name
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 basename
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 extension
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2/**
3 * Jingga
4 *
5 * PHP Version 8.1
6 *
7 * @package   phpOMS\System\File\Local
8 * @copyright Dennis Eichhorn
9 * @license   OMS License 2.0
10 * @version   1.0.0
11 * @link      https://jingga.app
12 */
13declare(strict_types=1);
14
15namespace phpOMS\System\File\Local;
16
17use phpOMS\System\File\ContainerInterface;
18use phpOMS\System\File\ContentPutMode;
19use phpOMS\System\File\FileInterface;
20use phpOMS\System\File\PathException;
21
22/**
23 * Filesystem class.
24 *
25 * Performing operations on the file system
26 *
27 * @package phpOMS\System\File\Local
28 * @license OMS License 2.0
29 * @link    https://jingga.app
30 * @since   1.0.0
31 */
32final class File extends FileAbstract implements FileInterface
33{
34    /**
35     * Constructor.
36     *
37     * @param string $path Path
38     *
39     * @since 1.0.0
40     */
41    public function __construct(string $path)
42    {
43        parent::__construct($path);
44        $this->count = 1;
45
46        if (\is_file($this->path)) {
47            $this->index();
48        }
49    }
50
51    /**
52     * {@inheritdoc}
53     */
54    public function index() : void
55    {
56        parent::index();
57
58        $this->size = (int) \filesize($this->path);
59    }
60
61    /**
62     * Save content to file.
63     *
64     * @param string $path    File path to save the content to
65     * @param string $content Content to save in file
66     * @param int    $mode    Mode (overwrite, append)
67     *
68     * @return bool
69     *
70     * @since 1.0.0
71     */
72    public static function put(string $path, string $content, int $mode = ContentPutMode::REPLACE | ContentPutMode::CREATE) : bool
73    {
74        $exists = \is_file($path);
75
76        try {
77            if (($exists && ContentPutMode::hasFlag($mode, ContentPutMode::APPEND))
78                || ($exists && ContentPutMode::hasFlag($mode, ContentPutMode::PREPEND))
79                || ($exists && ContentPutMode::hasFlag($mode, ContentPutMode::REPLACE))
80                || (!$exists && ContentPutMode::hasFlag($mode, ContentPutMode::CREATE))
81            ) {
82                if ($exists && ContentPutMode::hasFlag($mode, ContentPutMode::APPEND)) {
83                    \file_put_contents($path, \file_get_contents($path) . $content);
84                } elseif ($exists && ContentPutMode::hasFlag($mode, ContentPutMode::PREPEND)) {
85                    \file_put_contents($path, $content . \file_get_contents($path));
86                } else {
87                    if (!Directory::exists(\dirname($path))) {
88                        Directory::create(\dirname($path), 0755, true);
89                    }
90
91                    \file_put_contents($path, $content);
92                }
93
94                return true;
95            }
96        } catch (\Throwable $_) {
97            return false; // @codeCoverageIgnore
98        }
99
100        return false;
101    }
102
103    /**
104     * Get content from file.
105     *
106     * @param string $path File path of content
107     *
108     * @return string Content of file
109     *
110     * @throws PathException
111     *
112     * @since 1.0.0
113     */
114    public static function get(string $path) : string
115    {
116        if (!\is_file($path)) {
117            throw new PathException($path);
118        }
119
120        $contents = \file_get_contents($path);
121
122        return $contents === false ? '' : $contents;
123    }
124
125    /**
126     * {@inheritdoc}
127     */
128    public static function count(string $path, bool $recursive = true, array $ignore = []) : int
129    {
130        return 1;
131    }
132
133    /**
134     * Save content to file.
135     *
136     * Creates new file if it doesn't exist or overwrites existing file.
137     *
138     * @param string $path    File path to save the content to
139     * @param string $content Content to save in file
140     *
141     * @return bool
142     *
143     * @since 1.0.0
144     */
145    public static function set(string $path, string $content) : bool
146    {
147        return self::put($path, $content, ContentPutMode::REPLACE | ContentPutMode::CREATE);
148    }
149
150    /**
151     * Save content to file.
152     *
153     * Creates new file if it doesn't exist or appends existing file.
154     *
155     * @param string $path    File path to save the content to
156     * @param string $content Content to save in file
157     *
158     * @return bool
159     *
160     * @since 1.0.0
161     */
162    public static function append(string $path, string $content) : bool
163    {
164        return self::put($path, $content, ContentPutMode::APPEND | ContentPutMode::CREATE);
165    }
166
167    /**
168     * Save content to file.
169     *
170     * Creates new file if it doesn't exist or prepends existing file.
171     *
172     * @param string $path    File path to save the content to
173     * @param string $content Content to save in file
174     *
175     * @return bool
176     *
177     * @since 1.0.0
178     */
179    public static function prepend(string $path, string $content) : bool
180    {
181        return self::put($path, $content, ContentPutMode::PREPEND | ContentPutMode::CREATE);
182    }
183
184    /**
185     * {@inheritdoc}
186     */
187    public static function exists(string $path) : bool
188    {
189        return \is_file($path);
190    }
191
192    /**
193     * {@inheritdoc}
194     */
195    public static function parent(string $path) : string
196    {
197        return Directory::parent(\dirname($path));
198    }
199
200    /**
201     * {@inheritdoc}
202     */
203    public static function sanitize(string $path, string $replace = '', string $invalid = '/[^\w\s\d\.\-_~,;\/\[\]\(\]]/') : string
204    {
205        return \preg_replace($invalid, $replace, $path) ?? '';
206    }
207
208    /**
209     * {@inheritdoc}
210     */
211    public static function size(string $path, bool $recursive = true) : int
212    {
213        if (!\is_file($path)) {
214            return -1;
215        }
216
217        return (int) \filesize($path);
218    }
219
220    /**
221     * {@inheritdoc}
222     *
223     * @throws PathException
224     */
225    public static function owner(string $path) : int
226    {
227        if (!\is_file($path)) {
228            throw new PathException($path);
229        }
230
231        return (int) \fileowner($path);
232    }
233
234    /**
235     * {@inheritdoc}
236     */
237    public static function permission(string $path) : int
238    {
239        if (!\is_file($path)) {
240            return -1;
241        }
242
243        return (int) \fileperms($path);
244    }
245
246    /**
247     * Multi-byte path info
248     *
249     * @param string $path Path
250     *
251     * @return array
252     *
253     * @since 1.0.0
254     */
255    public static function pathInfo(string $path) : array
256    {
257        $temp = [];
258        \preg_match('#^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^.\\\\/]+?)|))[\\\\/.]*$#m', $path, $temp);
259
260        $info              = [];
261        $info['dirname']   = $temp[1] ?? '';
262        $info['basename']  = $temp[2] ?? '';
263        $info['filename']  = $temp[3] ?? '';
264        $info['extension'] = $temp[5] ?? '';
265
266        return $info;
267    }
268
269    /**
270     * Gets the directory name of a file.
271     *
272     * @param string $path path of the file to get the directory name for
273     *
274     * @return string returns the directory name of the file
275     *
276     * @since 1.0.0
277     */
278    public static function dirname(string $path) : string
279    {
280        return \basename(\dirname($path));
281    }
282
283    /**
284     * Gets the directory path of a file.
285     *
286     * @param string $path path of the file to get the directory name for
287     *
288     * @return string returns the directory name of the file
289     *
290     * @since 1.0.0
291     */
292    public static function dirpath(string $path) : string
293    {
294        return \dirname($path);
295    }
296
297    /**
298     * {@inheritdoc}
299     */
300    public static function copy(string $from, string $to, bool $overwrite = false) : bool
301    {
302        if (!\is_file($from)
303            || (!$overwrite && \is_file($to))
304        ) {
305            return false;
306        }
307
308        if (!Directory::exists(\dirname($to))) {
309            Directory::create(\dirname($to), 0755, true);
310        }
311
312        if ($overwrite && \is_file($to)) {
313            \unlink($to);
314        }
315
316        \copy($from, $to);
317
318        return true;
319    }
320
321    /**
322     * {@inheritdoc}
323     */
324    public static function move(string $from, string $to, bool $overwrite = false) : bool
325    {
326        $result = self::copy($from, $to, $overwrite);
327
328        if (!$result) {
329            return false;
330        }
331
332        self::delete($from);
333
334        return true;
335    }
336
337    /**
338     * {@inheritdoc}
339     */
340    public static function delete(string $path) : bool
341    {
342        if (!\is_file($path)) {
343            return false;
344        }
345
346        \unlink($path);
347
348        return true;
349    }
350
351    /**
352     * Gets the directory name of a file.
353     *
354     * @return string returns the directory name of the file
355     *
356     * @since 1.0.0
357     */
358    public function getDirName() : string
359    {
360        return \basename(\dirname($this->path));
361    }
362
363    /**
364     * Gets the directory path of a file.
365     *
366     * @return string returns the directory path of the file
367     *
368     * @since 1.0.0
369     */
370    public function getDirPath() : string
371    {
372        return \dirname($this->path);
373    }
374
375    /**
376     * {@inheritdoc}
377     */
378    public function createNode() : bool
379    {
380        return self::create($this->path);
381    }
382
383    /**
384     * Check if the file exists
385     *
386     * @return bool
387     *
388     * @since 1.0.0
389     */
390    public function isExisting() : bool
391    {
392        return \is_file($this->path);
393    }
394
395    /**
396     * {@inheritdoc}
397     */
398    public static function create(string $path) : bool
399    {
400        if (!\is_file($path)) {
401            if (!Directory::exists(\dirname($path))) {
402                Directory::create(\dirname($path), 0755, true);
403            }
404
405            if (!\is_writable(\dirname($path))) {
406                return false; // @codeCoverageIgnore
407            }
408
409            \touch($path);
410
411            return true;
412        }
413
414        return false;
415    }
416
417    /**
418     * {@inheritdoc}
419     */
420    public function getContent() : string
421    {
422        $contents = \file_get_contents($this->path);
423
424        return $contents === false ? '' : $contents;
425    }
426
427    /**
428     * {@inheritdoc}
429     */
430    public function setContent(string $content) : bool
431    {
432        return $this->putContent($content, ContentPutMode::REPLACE | ContentPutMode::CREATE);
433    }
434
435    /**
436     * {@inheritdoc}
437     */
438    public function appendContent(string $content) : bool
439    {
440        return $this->putContent($content, ContentPutMode::APPEND);
441    }
442
443    /**
444     * {@inheritdoc}
445     */
446    public function prependContent(string $content) : bool
447    {
448        return $this->putContent($content, ContentPutMode::PREPEND);
449    }
450
451    /**
452     * {@inheritdoc}
453     */
454    public function getName() : string
455    {
456        return \explode('.', $this->name)[0];
457    }
458
459    /**
460     * {@inheritdoc}
461     */
462    public function getExtension() : string
463    {
464        $extension = \explode('.', $this->name);
465
466        return $extension[1] ?? '';
467    }
468
469    /**
470     * {@inheritdoc}
471     */
472    public function getParent() : ContainerInterface
473    {
474        return new Directory(self::parent($this->path));
475    }
476
477    /**
478     * Get directory of the file
479     *
480     * @return ContainerInterface
481     *
482     * @since 1.0.0
483     */
484    public function getDirectory() : ContainerInterface
485    {
486        return new Directory(self::dirpath($this->path));
487    }
488
489    /**
490     * {@inheritdoc}
491     */
492    public function copyNode(string $to, bool $overwrite = false) : bool
493    {
494        return self::copy($this->path, $to, $overwrite);
495    }
496
497    /**
498     * {@inheritdoc}
499     */
500    public function moveNode(string $to, bool $overwrite = false) : bool
501    {
502        return self::move($this->path, $to, $overwrite);
503    }
504
505    /**
506     * {@inheritdoc}
507     */
508    public function deleteNode() : bool
509    {
510        return self::delete($this->path);
511    }
512
513    /**
514     * {@inheritdoc}
515     */
516    public function putContent(string $content, int $mode = ContentPutMode::APPEND | ContentPutMode::CREATE) : bool
517    {
518        return self::put($this->path, $content, $mode);
519    }
520
521    /**
522     * {@inheritdoc}
523     */
524    public static function name(string $path) : string
525    {
526        return \explode('.', \basename($path))[0];
527    }
528
529    /**
530     * {@inheritdoc}
531     */
532    public static function basename(string $path) : string
533    {
534        return \basename($path);
535    }
536
537    /**
538     * Get file extension.
539     *
540     * @param string $path File path
541     *
542     * @return string
543     *
544     * @since 1.0.0
545     */
546    public static function extension(string $path) : string
547    {
548        $extension = \explode('.', \basename($path));
549
550        return $extension[1] ?? '';
551    }
552}