File::length()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2.032

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 0
dl 0
loc 8
ccs 4
cts 5
cp 0.8
crap 2.032
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
5
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
7
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
8
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
9
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
10
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
11
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
12
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
13
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
14
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
15
 *
16
 * This software consists of voluntary contributions made by many individuals
17
 * and is licensed under the LGPL. For more information please see
18
 * <http://phing.info>.
19
 */
20
21
namespace Phing\Io;
22
23
use Exception;
24
use Phing\Util\StringHelper;
25
26
/**
27
 * An abstract representation of file and directory pathnames.
28
 */
29
class File
30
{
31
    /**
32
     * This abstract pathname's normalized pathname string.  A normalized
33
     * pathname string uses the default name-separator character and does not
34
     * contain any duplicate or redundant separators.
35
     */
36
    private $path = '';
37
38
    /**
39
     * The length of this abstract pathname's prefix, or zero if it has no prefix.
40
     *
41
     * @var int
42
     */
43
    private $prefixLength = 0;
44
45
    /**
46
     * constructor.
47
     *
48
     * @param null|mixed $arg1
49
     * @param null|mixed $arg2
50
     *
51
     * @throws IOException
52
     * @throws \InvalidArgumentException
53
     */
54 952
    public function __construct($arg1 = null, $arg2 = null)
55
    {
56
        // simulate signature identified constructors
57 952
        if ($arg1 instanceof File && is_string($arg2)) {
58 455
            $this->constructFileParentStringChild($arg1, $arg2);
59 952
        } elseif (is_string($arg1) && (null === $arg2)) {
60 952
            $this->constructPathname($arg1);
61 153
        } elseif (is_string($arg1) && is_string($arg2)) {
62 29
            $this->constructStringParentStringChild($arg1, $arg2);
63
        } else {
64 141
            if (null === $arg1) {
65
                throw new \InvalidArgumentException('Argument1 to function must not be null');
66
            }
67 141
            $this->path = (string) $arg1;
68 141
            $this->prefixLength = (int) $arg2;
69
        }
70
    }
71
72
    /**
73
     * Return string representation of the object.
74
     *
75
     * @return string
76
     */
77 923
    public function __toString()
78
    {
79 923
        return $this->getPath();
80
    }
81
82
    /**
83
     * Returns the length of this abstract pathname's prefix.
84
     *
85
     * @return int
86
     */
87 934
    public function getPrefixLength()
88
    {
89 934
        return (int) $this->prefixLength;
90
    }
91
92
    // -- Path-component accessors --
93
94
    /**
95
     * Returns the name of the file or directory denoted by this abstract
96
     * pathname.  This is just the last name in the pathname's name
97
     * sequence.  If the pathname's name sequence is empty, then the empty
98
     * string is returned.
99
     *
100
     * @return string The name of the file or directory denoted by this abstract
101
     *                pathname, or the empty string if this pathname's name sequence
102
     *                is empty
103
     */
104 905
    public function getName()
105
    {
106
        // that's a lastIndexOf
107 905
        $index = ((($res = strrpos($this->path, FileUtils::getSeparator())) === false) ? -1 : $res);
108 905
        if ($index < $this->prefixLength) {
109 3
            return substr($this->path, $this->prefixLength);
110
        }
111
112 905
        return substr($this->path, $index + 1);
113
    }
114
115
    /**
116
     * Returns the pathname string of this abstract pathname's parent, or
117
     * null if this pathname does not name a parent directory.
118
     *
119
     * The parent of an abstract pathname consists of the pathname's prefix,
120
     * if any, and each name in the pathname's name sequence except for the last.
121
     * If the name sequence is empty then the pathname does not name a parent
122
     * directory.
123
     *
124
     * @return string $pathname string of the parent directory named by this
125
     *                abstract pathname, or null if this pathname does not name a parent
126
     */
127 910
    public function getParent()
128
    {
129
        // that's a lastIndexOf
130 910
        $index = ((($res = strrpos($this->path, FileUtils::getSeparator())) === false) ? -1 : $res);
131 910
        if ($index < $this->prefixLength) {
132 10
            if (($this->prefixLength > 0) && (strlen($this->path) > $this->prefixLength)) {
133
                return substr($this->path, 0, $this->prefixLength);
134
            }
135
136 10
            return null;
137
        }
138
139 908
        return substr($this->path, 0, $index);
140
    }
141
142
    /**
143
     * Returns the abstract pathname of this abstract pathname's parent,
144
     * or null if this pathname does not name a parent directory.
145
     *
146
     * The parent of an abstract pathname consists of the pathname's prefix,
147
     * if any, and each name in the pathname's name sequence except for the
148
     * last.  If the name sequence is empty then the pathname does not name
149
     * a parent directory.
150
     *
151
     * @return null|File The abstract pathname of the parent directory named by this
152
     *                   abstract pathname, or null if this pathname
153
     *                   does not name a parent
154
     */
155 139
    public function getParentFile()
156
    {
157 139
        $p = $this->getParent();
158 139
        if (null === $p) {
0 ignored issues
show
introduced by
The condition null === $p is always false.
Loading history...
159
            return null;
160
        }
161
162 139
        return new File((string) $p, (int) $this->prefixLength);
163
    }
164
165
    /**
166
     * Converts this abstract pathname into a pathname string.  The resulting
167
     * string uses the default name-separator character to separate the names
168
     * in the name sequence.
169
     *
170
     * @return string The string form of this abstract pathname
171
     */
172 952
    public function getPath()
173
    {
174 952
        return (string) $this->path;
175
    }
176
177
    /**
178
     * Returns path without leading basedir.
179
     *
180
     * @param string $basedir Base directory to strip
181
     *
182
     * @return string Path without basedir
183
     *
184
     * @uses getPath()
185
     */
186 7
    public function getPathWithoutBase($basedir)
187
    {
188 7
        if (!StringHelper::endsWith(FileUtils::getSeparator(), $basedir)) {
189 7
            $basedir .= FileUtils::getSeparator();
190
        }
191 7
        $path = $this->getPath();
192 7
        if (substr($path, 0, strlen($basedir)) != $basedir) {
193
            //path does not begin with basedir, we don't modify it
194 1
            return $path;
195
        }
196
197 6
        return substr($path, strlen($basedir));
198
    }
199
200
    /**
201
     * Tests whether this abstract pathname is absolute.  The definition of
202
     * absolute pathname is system dependent.  On UNIX systems, a pathname is
203
     * absolute if its prefix is "/".  On Win32 systems, a pathname is absolute
204
     * if its prefix is a drive specifier followed by "\\", or if its prefix
205
     * is "\\".
206
     *
207
     * @return bool true if this abstract pathname is absolute, false otherwise
208
     */
209 206
    public function isAbsolute()
210
    {
211 206
        return 0 !== $this->prefixLength;
212
    }
213
214
    /**
215
     * Returns the file extension for a given file. For example test.php would be returned as php.
216
     *
217
     * @return string the name of the extension
218
     */
219 17
    public function getFileExtension()
220
    {
221 17
        return pathinfo((string) $this->getAbsolutePath(), PATHINFO_EXTENSION);
0 ignored issues
show
Bug Best Practice introduced by
The expression return pathinfo((string)...\Io\PATHINFO_EXTENSION) also could return the type array which is incompatible with the documented return type string.
Loading history...
222
    }
223
224
    /**
225
     * Returns the absolute pathname string of this abstract pathname.
226
     *
227
     * If this abstract pathname is already absolute, then the pathname
228
     * string is simply returned as if by the getPath method.
229
     * If this abstract pathname is the empty abstract pathname then
230
     * the pathname string of the current user directory, which is named by the
231
     * system property user.dir, is returned.  Otherwise this
232
     * pathname is resolved in a system-dependent way.  On UNIX systems, a
233
     * relative pathname is made absolute by resolving it against the current
234
     * user directory.  On Win32 systems, a relative pathname is made absolute
235
     * by resolving it against the current directory of the drive named by the
236
     * pathname, if any; if not, it is resolved against the current user
237
     * directory.
238
     *
239
     * @return string The absolute pathname string denoting the same file or
240
     *                directory as this abstract pathname
241
     *
242
     * @see    #isAbsolute()
243
     */
244 934
    public function getAbsolutePath()
245
    {
246 934
        $fs = FileSystem::getFileSystem();
247
248 934
        return $fs->resolveFile($this);
249
    }
250
251
    /**
252
     * Returns the absolute form of this abstract pathname.  Equivalent to
253
     * getAbsolutePath.
254
     *
255
     * @return File The absolute abstract pathname denoting the same file or
256
     *              directory as this abstract pathname
257
     */
258 1
    public function getAbsoluteFile()
259
    {
260 1
        return new File((string) $this->getAbsolutePath());
261
    }
262
263
    /**
264
     * Returns the canonical pathname string of this abstract pathname.
265
     *
266
     * A canonical pathname is both absolute and unique. The precise
267
     * definition of canonical form is system-dependent. This method first
268
     * converts this pathname to absolute form if necessary, as if by invoking the
269
     * getAbsolutePath() method, and then maps it to its unique form in a
270
     * system-dependent way.  This typically involves removing redundant names
271
     * such as "." and .. from the pathname, resolving symbolic links
272
     * (on UNIX platforms), and converting drive letters to a standard case
273
     * (on Win32 platforms).
274
     *
275
     * Every pathname that denotes an existing file or directory has a
276
     * unique canonical form.  Every pathname that denotes a nonexistent file
277
     * or directory also has a unique canonical form.  The canonical form of
278
     * the pathname of a nonexistent file or directory may be different from
279
     * the canonical form of the same pathname after the file or directory is
280
     * created.  Similarly, the canonical form of the pathname of an existing
281
     * file or directory may be different from the canonical form of the same
282
     * pathname after the file or directory is deleted.
283
     *
284
     * @return string The canonical pathname string denoting the same file or
285
     *                directory as this abstract pathname
286
     */
287 38
    public function getCanonicalPath()
288
    {
289 38
        $fs = FileSystem::getFileSystem();
290
291 38
        return $fs->canonicalize($this->path);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $fs->canonicalize($this->path) could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
292
    }
293
294
    /**
295
     * Returns the canonical form of this abstract pathname.  Equivalent to
296
     * getCanonicalPath(.
297
     *
298
     * @return File The canonical pathname string denoting the same file or
299
     *              directory as this abstract pathname
300
     */
301 37
    public function getCanonicalFile()
302
    {
303 37
        return new File($this->getCanonicalPath());
304
    }
305
306
    // -- Attribute accessors --
307
308
    /**
309
     * Tests whether the application can read the file denoted by this
310
     * abstract pathname.
311
     *
312
     * @return bool true if and only if the file specified by this
313
     *              abstract pathname exists and can be read by the
314
     *              application; false otherwise
315
     */
316 911
    public function canRead()
317
    {
318 911
        $fs = FileSystem::getFileSystem();
319
320 911
        if ($fs->checkAccess($this)) {
321 911
            return (bool) @is_link($this->getAbsolutePath()) || @is_readable($this->getAbsolutePath());
322
        }
323
324
        return false;
325
    }
326
327
    /**
328
     * Tests whether the application can modify to the file denoted by this
329
     * abstract pathname.
330
     *
331
     * @return bool true if and only if the file system actually
332
     *              contains a file denoted by this abstract pathname and
333
     *              the application is allowed to write to the file;
334
     *              false otherwise
335
     */
336 89
    public function canWrite()
337
    {
338 89
        $fs = FileSystem::getFileSystem();
339
340 89
        return $fs->checkAccess($this, true);
341
    }
342
343
    /**
344
     * Tests whether the file denoted by this abstract pathname exists.
345
     *
346
     * @return bool true if and only if the file denoted by this
347
     *              abstract pathname exists; false otherwise
348
     */
349 929
    public function exists()
350
    {
351 929
        clearstatcache();
352
353 929
        if (is_link($this->path)) {
354 3
            return true;
355
        }
356
357 929
        if ($this->isDirectory()) {
358 926
            return true;
359
        }
360
361 910
        return @file_exists($this->path) || is_link($this->path);
362
    }
363
364
    /**
365
     * Tests whether the file denoted by this abstract pathname is a
366
     * directory.
367
     *
368
     * @throws IOException
369
     *
370
     * @return bool true if and only if the file denoted by this
371
     *              abstract pathname exists and is a directory;
372
     *              false otherwise
373
     */
374 929
    public function isDirectory()
375
    {
376 929
        clearstatcache();
377 929
        $fs = FileSystem::getFileSystem();
378 929
        if (true !== $fs->checkAccess($this)) {
379
            throw new IOException('No read access to ' . $this->path);
380
        }
381
382 929
        return @is_dir($this->path) && !@is_link($this->path);
383
    }
384
385
    /**
386
     * Tests whether the file denoted by this abstract pathname is a normal
387
     * file.  A file is normal if it is not a directory and, in
388
     * addition, satisfies other system-dependent criteria.  Any non-directory
389
     * file created by a Java application is guaranteed to be a normal file.
390
     *
391
     * @return bool true if and only if the file denoted by this
392
     *              abstract pathname exists and is a normal file;
393
     *              false otherwise
394
     */
395 209
    public function isFile()
396
    {
397 209
        clearstatcache();
398
        //$fs = FileSystem::getFileSystem();
399 209
        return @is_file($this->path);
400
    }
401
402
    /**
403
     * Tests whether the file denoted by this abstract pathname is a symbolic link.
404
     *
405
     * @throws IOException
406
     *
407
     * @return bool true if and only if the file denoted by this
408
     *              abstract pathname exists and is a symbolic link;
409
     *              false otherwise
410
     */
411 145
    public function isLink()
412
    {
413 145
        clearstatcache();
414 145
        $fs = FileSystem::getFileSystem();
415 145
        if (true !== $fs->checkAccess($this)) {
416
            throw new IOException('No read access to ' . $this->path);
417
        }
418
419 145
        return @is_link($this->path);
420
    }
421
422
    /**
423
     * Tests whether the file denoted by this abstract pathname is executable.
424
     *
425
     * @throws IOException
426
     *
427
     * @return bool true if and only if the file denoted by this
428
     *              abstract pathname exists and is a symbolic link;
429
     *              false otherwise
430
     */
431 2
    public function isExecutable()
432
    {
433 2
        clearstatcache();
434 2
        $fs = FileSystem::getFileSystem();
435 2
        if (true !== $fs->checkAccess($this)) {
436
            throw new IOException('No read access to ' . $this->path);
437
        }
438
439 2
        return @is_executable($this->path);
440
    }
441
442
    /**
443
     * Returns the target of the symbolic link denoted by this abstract pathname.
444
     *
445
     * @return string the target of the symbolic link denoted by this abstract pathname
446
     */
447 8
    public function getLinkTarget()
448
    {
449 8
        return @readlink($this->path);
0 ignored issues
show
Bug Best Practice introduced by
The expression return @readlink($this->path) could also return false which is incompatible with the documented return type string. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
450
    }
451
452
    /**
453
     * Returns the time that the file denoted by this abstract pathname was
454
     * last modified.
455
     *
456
     * @throws IOException
457
     *
458
     * @return int An int value representing the time the file was
459
     *             last modified, measured in seconds since the epoch
460
     *             (00:00:00 GMT, January 1, 1970), or 0 if the
461
     *             file does not exist or if an I/O error occurs
462
     */
463 60
    public function lastModified()
464
    {
465 60
        $fs = FileSystem::getFileSystem();
466 60
        if (true !== $fs->checkAccess($this)) {
467
            throw new IOException('No read access to ' . $this->path);
468
        }
469
470 60
        return $fs->getLastModifiedTime($this);
471
    }
472
473
    /**
474
     * Returns the length of the file denoted by this abstract pathname.
475
     * The return value is unspecified if this pathname denotes a directory.
476
     *
477
     * @throws IOException
478
     *
479
     * @return int The length, in bytes, of the file denoted by this abstract
480
     *             pathname, or 0 if the file does not exist
481
     */
482 27
    public function length()
483
    {
484 27
        $fs = FileSystem::getFileSystem();
485 27
        if (true !== $fs->checkAccess($this)) {
486
            throw new IOException('No read access to ' . $this->path . "\n");
487
        }
488
489 27
        return $fs->getLength($this);
490
    }
491
492
    /**
493
     * Convenience method for returning the contents of this file as a string.
494
     * This method uses file_get_contents() to read file in an optimized way.
495
     *
496
     * @throws Exception - if file cannot be read
497
     *
498
     * @return string
499
     */
500 4
    public function contents()
501
    {
502 4
        if (!$this->canRead() || !$this->isFile()) {
503
            throw new IOException('Cannot read file contents!');
504
        }
505
506 4
        return file_get_contents($this->getAbsolutePath());
507
    }
508
509
    // -- File operations --
510
511
    /**
512
     * Atomically creates a new, empty file named by this abstract pathname if
513
     * and only if a file with this name does not yet exist.  The check for the
514
     * existence of the file and the creation of the file if it does not exist
515
     * are a single operation that is atomic with respect to all other
516
     * filesystem activities that might affect the file.
517
     *
518
     * @param bool $parents
519
     *
520
     * @throws IOException
521
     *
522
     * @return bool true if the named file does not exist and was
523
     *              successfully created; <code>false</code> if the named file
524
     *              already exists
525
     */
526 85
    public function createNewFile($parents = true)
527
    {
528
        /**
529
         * @var File $parent
530
         */
531 85
        $parent = $this->getParentFile();
532 85
        if ($parents && null !== $parent && !$parent->exists()) {
533 6
            $parent->mkdirs();
534
        }
535
536 85
        return FileSystem::getFileSystem()->createNewFile($this->path);
537
    }
538
539
    /**
540
     * Deletes the file or directory denoted by this abstract pathname.  If
541
     * this pathname denotes a directory, then the directory must be empty in
542
     * order to be deleted.
543
     *
544
     * @param bool $recursive
545
     *
546
     * @throws IOException
547
     */
548 233
    public function delete($recursive = false)
549
    {
550 233
        $fs = FileSystem::getFileSystem();
551 233
        if (true !== $fs->canDelete($this)) {
552
            throw new IOException('Cannot delete ' . $this->path . "\n");
553
        }
554
555 233
        $fs->delete($this, $recursive);
556
    }
557
558
    /**
559
     * Requests that the file or directory denoted by this abstract pathname
560
     * be deleted when php terminates.  Deletion will be attempted only for
561
     * normal termination of php and if and if only Phing::shutdown() is
562
     * called.
563
     *
564
     * Once deletion has been requested, it is not possible to cancel the
565
     * request.  This method should therefore be used with care.
566
     */
567
    public function deleteOnExit()
568
    {
569
        $fs = FileSystem::getFileSystem();
570
        $fs->deleteOnExit($this);
571
    }
572
573
    /**
574
     * Returns an array of strings naming the files and directories in the
575
     * directory denoted by this abstract pathname.
576
     *
577
     * If this abstract pathname does not denote a directory, then this
578
     * method returns null  Otherwise an array of strings is
579
     * returned, one for each file or directory in the directory.  Names
580
     * denoting the directory itself and the directory's parent directory are
581
     * not included in the result.  Each string is a file name rather than a
582
     * complete path.
583
     *
584
     * There is no guarantee that the name strings in the resulting array
585
     * will appear in any specific order; they are not, in particular,
586
     * guaranteed to appear in alphabetical order.
587
     *
588
     * @return null|array An array of strings naming the files and directories in the
589
     *                    directory denoted by this abstract pathname.  The array will be
590
     *                    empty if the directory is empty.  Returns null if
591
     *                    this abstract pathname does not denote a directory, or if an
592
     *                    I/O error occurs.
593
     */
594 235
    public function listDir(): ?array
595
    {
596
        try {
597 235
            $elements = FileSystem::getFileSystem()->listContents($this);
598
        } catch (IOException $e) {
599
            $elements = null;
600
        }
601
602 235
        return $elements;
603
    }
604
605
    /**
606
     * Creates the directory named by this abstract pathname, including any
607
     * necessary but nonexistent parent directories.  Note that if this
608
     * operation fails it may have succeeded in creating some of the necessary
609
     * parent directories.
610
     *
611
     * @param null|int $mode
612
     *
613
     * @throws IOException
614
     *
615
     * @return bool true if and only if the directory was created,
616
     *              along with all necessary parent directories; false
617
     *              otherwise
618
     */
619 187
    public function mkdirs($mode = null)
620
    {
621 187
        if ($this->exists()) {
622
            return false;
623
        }
624
625
        try {
626 187
            if ($this->mkdir($mode)) {
627 187
                return true;
628
            }
629
        } catch (IOException $ioe) {
630
            // IOException from mkdir() means that directory propbably didn't exist.
631
        }
632 36
        $parentFile = $this->getParentFile();
633
634 36
        return (null !== $parentFile) && ($parentFile->mkdirs() && $this->mkdir($mode));
635
    }
636
637
    /**
638
     * Creates the directory named by this abstract pathname.
639
     *
640
     * @param null|int $mode
641
     *
642
     * @throws IOException
643
     *
644
     * @return bool true if and only if the directory was created; false otherwise
645
     */
646 187
    public function mkdir($mode = null)
647
    {
648 187
        $fs = FileSystem::getFileSystem();
649
650 187
        if (true !== $fs->checkAccess(new File($this->path), true)) {
651
            throw new IOException('No write access to ' . $this->getPath());
652
        }
653
654 187
        return $fs->createDirectory($this, $mode);
655
    }
656
657
    /**
658
     * Renames the file denoted by this abstract pathname.
659
     *
660
     * @param File $destFile The new abstract pathname for the named file
661
     *
662
     * @throws IOException
663
     */
664 1
    public function renameTo(File $destFile)
665
    {
666 1
        $fs = FileSystem::getFileSystem();
667 1
        if (true !== $fs->checkAccess($this)) {
668
            throw new IOException('No write access to ' . $this->getPath());
669
        }
670
671 1
        $fs->rename($this, $destFile);
672
    }
673
674
    /**
675
     * Simple-copies file denoted by this abstract pathname into another
676
     * PhingFile.
677
     *
678
     * @param File $destFile The new abstract pathname for the named file
679
     *
680
     * @throws IOException
681
     */
682 29
    public function copyTo(File $destFile)
683
    {
684 29
        $fs = FileSystem::getFileSystem();
685
686 29
        if (true !== $fs->checkAccess($this)) {
687
            throw new IOException('No read access to ' . $this->getPath() . "\n");
688
        }
689
690 29
        if (true !== $fs->checkAccess($destFile, true)) {
691
            throw new IOException('File::copyTo() No write access to ' . $destFile->getPath());
692
        }
693
694 29
        $fs->copy($this, $destFile);
695
    }
696
697
    /**
698
     * Sets the last-modified time of the file or directory named by this
699
     * abstract pathname.
700
     *
701
     * All platforms support file-modification times to the nearest second,
702
     * but some provide more precision.  The argument will be truncated to fit
703
     * the supported precision.  If the operation succeeds and no intervening
704
     * operations on the file take place, then the next invocation of the
705
     * lastModified method will return the (possibly truncated) time argument
706
     * that was passed to this method.
707
     *
708
     * @param int $time The new last-modified time, measured in milliseconds since
709
     *                  the epoch (00:00:00 GMT, January 1, 1970)
710
     *
711
     * @throws Exception
712
     */
713 83
    public function setLastModified($time)
714
    {
715 83
        $time = (int) $time;
716 83
        if ($time < 0) {
717
            throw new Exception("IllegalArgumentException, Negative {$time}\n");
718
        }
719
720 83
        $fs = FileSystem::getFileSystem();
721
722 83
        $fs->setLastModifiedTime($this, $time);
723
    }
724
725
    /**
726
     * Sets the owner of the file.
727
     *
728
     * @param mixed $user user name or number
729
     *
730
     * @throws IOException
731
     */
732 1
    public function setUser($user)
733
    {
734 1
        $fs = FileSystem::getFileSystem();
735
736 1
        $fs->chown($this->getPath(), $user);
737
    }
738
739
    /**
740
     * Sets the group of the file.
741
     *
742
     * @param string $group
743
     *
744
     * @throws IOException
745
     */
746 1
    public function setGroup($group)
747
    {
748 1
        $fs = FileSystem::getFileSystem();
749
750 1
        $fs->chgrp($this->getPath(), $group);
751
    }
752
753
    /**
754
     * Sets the mode of the file.
755
     *
756
     * @param int $mode octal mode
757
     *
758
     * @throws IOException
759
     */
760 67
    public function setMode($mode)
761
    {
762 67
        $fs = FileSystem::getFileSystem();
763
764 67
        $fs->chmod($this->getPath(), $mode);
765
    }
766
767
    /**
768
     * Retrieve the mode of this file.
769
     *
770
     * @return int
771
     */
772 53
    public function getMode()
773
    {
774 53
        return @fileperms($this->getPath());
0 ignored issues
show
Bug Best Practice introduced by
The expression return @fileperms($this->getPath()) could also return false which is incompatible with the documented return type integer. Did you maybe forget to handle an error condition?

If the returned type also contains false, it is an indicator that maybe an error condition leading to the specific return statement remains unhandled.

Loading history...
775
    }
776
777
    // -- Basic infrastructure --
778
779
    /**
780
     * Compares two abstract pathnames lexicographically.  The ordering
781
     * defined by this method depends upon the underlying system.  On UNIX
782
     * systems, alphabetic case is significant in comparing pathnames; on Win32
783
     * systems it is not.
784
     *
785
     * @param File $file th file whose pathname sould be compared to the pathname of this file
786
     *
787
     * @return int Zero if the argument is equal to this abstract pathname, a
788
     *             value less than zero if this abstract pathname is
789
     *             lexicographically less than the argument, or a value greater
790
     *             than zero if this abstract pathname is lexicographically
791
     *             greater than the argument
792
     */
793 38
    public function compareTo(File $file)
794
    {
795 38
        $fs = FileSystem::getFileSystem();
796
797 38
        return $fs->compare($this, $file);
798
    }
799
800
    /**
801
     * Tests this abstract pathname for equality with the given object.
802
     * Returns <code>true</code> if and only if the argument is not
803
     * <code>null</code> and is an abstract pathname that denotes the same file
804
     * or directory as this abstract pathname.  Whether or not two abstract
805
     * pathnames are equal depends upon the underlying system.  On UNIX
806
     * systems, alphabetic case is significant in comparing pathnames; on Win32
807
     * systems it is not.
808
     *
809
     * @param File $obj
810
     *
811
     * @return bool
812
     */
813 38
    public function equals($obj)
814
    {
815 38
        if ((null !== $obj) && ($obj instanceof File)) {
816 38
            return 0 === $this->compareTo($obj);
817
        }
818
819
        return false;
820
    }
821
822
    // -- constructors not called by signature match, so we need some helpers --
823
824
    /**
825
     * @throws IOException
826
     */
827 952
    protected function constructPathname(string $pathname): void
828
    {
829 952
        $fs = FileSystem::getFileSystem();
830
831 952
        $this->path = (string) $fs->normalize($pathname);
832 952
        $this->prefixLength = (int) $fs->prefixLength($this->path);
833
    }
834
835
    /**
836
     * @throws IOException
837
     */
838 29
    protected function constructStringParentStringChild(string $parent, string $child): void
839
    {
840 29
        $fs = FileSystem::getFileSystem();
841
842 29
        if ('' === $parent) {
843
            $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
844
        } else {
845 29
            $this->path = $fs->resolve($fs->normalize($parent), $fs->normalize($child));
846
        }
847
848 29
        $this->prefixLength = (int) $fs->prefixLength($this->path);
849
    }
850
851
    /**
852
     * @throws IOException
853
     */
854 455
    protected function constructFileParentStringChild(File $parent, string $child): void
855
    {
856 455
        $fs = FileSystem::getFileSystem();
857
858 455
        if ('' === $parent->path) {
859
            $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
860
        } else {
861 455
            $this->path = $fs->resolve($parent->path, $fs->normalize($child));
862
        }
863
864 455
        $this->prefixLength = $fs->prefixLength($this->path);
865
    }
866
}
867