Passed
Push — master ( e1f86a...4e1a3a )
by Siad
05:23
created

File::lastModified()   A

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
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
4
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
5
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
7
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
8
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
9
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
10
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
11
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
12
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
13
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
14
 *
15
 * This software consists of voluntary contributions made by many individuals
16
 * and is licensed under the LGPL. For more information please see
17
 * <http://phing.info>.
18
 */
19
20
namespace Phing\Io;
21
22
use Exception;
23
use Phing\Exception\NullPointerException;
24
use Phing\Util\StringHelper;
25
26
/**
27
 * An abstract representation of file and directory pathnames.
28
 *
29
 * @package phing.system.io
30
 */
31
class File
32
{
33
    /**
34
     * This abstract pathname's normalized pathname string.  A normalized
35
     * pathname string uses the default name-separator character and does not
36
     * contain any duplicate or redundant separators.
37
     */
38
    private $path = null;
39
40
    /**
41
     * The length of this abstract pathname's prefix, or zero if it has no prefix.
42
     *
43
     * @var int
44
     */
45
    private $prefixLength = 0;
46
47
    /**
48
     * constructor
49
     *
50
     * @param mixed $arg1
51
     * @param mixed $arg2
52
     *
53
     * @throws IOException
54
     * @throws NullPointerException
55
     */
56 879
    public function __construct($arg1 = null, $arg2 = null)
57
    {
58
        /* simulate signature identified constructors */
59 879
        if ($arg1 instanceof File && is_string($arg2)) {
60 421
            $this->constructFileParentStringChild($arg1, $arg2);
61 879
        } elseif (is_string($arg1) && ($arg2 === null)) {
62 879
            $this->constructPathname($arg1);
63 144
        } elseif (is_string($arg1) && is_string($arg2)) {
64 28
            $this->constructStringParentStringChild($arg1, $arg2);
65
        } else {
66 133
            if ($arg1 === null) {
67
                throw new NullPointerException("Argument1 to function must not be null");
0 ignored issues
show
Deprecated Code introduced by
The class Phing\Exception\NullPointerException has been deprecated. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

67
                throw /** @scrutinizer ignore-deprecated */ new NullPointerException("Argument1 to function must not be null");
Loading history...
68
            }
69 133
            $this->path = (string) $arg1;
70 133
            $this->prefixLength = (int) $arg2;
71
        }
72 879
    }
73
74
    /**
75
     * Returns the length of this abstract pathname's prefix.
76
     *
77
     * @return int
78
     */
79 861
    public function getPrefixLength()
80
    {
81 861
        return (int) $this->prefixLength;
82
    }
83
84
    /* -- constructors not called by signature match, so we need some helpers --*/
85
86
    /**
87
     * @param string $pathname
88
     *
89
     * @throws IOException
90
     */
91 879
    protected function constructPathname(string $pathname): void
92
    {
93 879
        $fs = FileSystem::getFileSystem();
94
95 879
        $this->path = (string) $fs->normalize($pathname);
96 879
        $this->prefixLength = (int) $fs->prefixLength($this->path);
97 879
    }
98
99
    /**
100
     * @param string $parent
101
     * @param string $child
102
     * @throws IOException
103
     */
104 28
    protected function constructStringParentStringChild(string $parent, string $child): void
105
    {
106 28
        $fs = FileSystem::getFileSystem();
107
108 28
        if ($parent === "") {
109
            $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
110
        } else {
111 28
            $this->path = $fs->resolve($fs->normalize($parent), $fs->normalize($child));
112
        }
113
114 28
        $this->prefixLength = (int) $fs->prefixLength($this->path);
115 28
    }
116
117
    /**
118
     * @param File $parent
119
     * @param string $child
120
     * @throws IOException
121
     */
122 421
    protected function constructFileParentStringChild(File $parent, string $child): void
123
    {
124 421
        $fs = FileSystem::getFileSystem();
125
126 421
        if ($parent->path === "") {
127
            $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
128
        } else {
129 421
            $this->path = $fs->resolve($parent->path, $fs->normalize($child));
130
        }
131
132 421
        $this->prefixLength = $fs->prefixLength($this->path);
133 421
    }
134
135
    /* -- Path-component accessors -- */
136
137
    /**
138
     * Returns the name of the file or directory denoted by this abstract
139
     * pathname.  This is just the last name in the pathname's name
140
     * sequence.  If the pathname's name sequence is empty, then the empty
141
     * string is returned.
142
     *
143
     * @return string The name of the file or directory denoted by this abstract
144
     *                pathname, or the empty string if this pathname's name sequence
145
     *                is empty
146
     */
147 837
    public function getName()
148
    {
149
        // that's a lastIndexOf
150 837
        $index = ((($res = strrpos($this->path, FileUtils::getSeparator())) === false) ? -1 : $res);
151 837
        if ($index < $this->prefixLength) {
152 3
            return substr($this->path, $this->prefixLength);
153
        }
154
155 837
        return substr($this->path, $index + 1);
156
    }
157
158
    /**
159
     * Returns the pathname string of this abstract pathname's parent, or
160
     * null if this pathname does not name a parent directory.
161
     *
162
     * The parent of an abstract pathname consists of the pathname's prefix,
163
     * if any, and each name in the pathname's name sequence except for the last.
164
     * If the name sequence is empty then the pathname does not name a parent
165
     * directory.
166
     *
167
     * @return string $pathname string of the parent directory named by this
168
     *                          abstract pathname, or null if this pathname does not name a parent
169
     */
170 840
    public function getParent()
171
    {
172
        // that's a lastIndexOf
173 840
        $index = ((($res = strrpos($this->path, FileUtils::getSeparator())) === false) ? -1 : $res);
174 840
        if ($index < $this->prefixLength) {
175 9
            if (($this->prefixLength > 0) && (strlen($this->path) > $this->prefixLength)) {
176
                return substr($this->path, 0, $this->prefixLength);
177
            }
178
179 9
            return null;
180
        }
181
182 838
        return substr($this->path, 0, $index);
183
    }
184
185
    /**
186
     * Returns the abstract pathname of this abstract pathname's parent,
187
     * or null if this pathname does not name a parent directory.
188
     *
189
     * The parent of an abstract pathname consists of the pathname's prefix,
190
     * if any, and each name in the pathname's name sequence except for the
191
     * last.  If the name sequence is empty then the pathname does not name
192
     * a parent directory.
193
     *
194
     * @return File|null The abstract pathname of the parent directory named by this
195
     *             abstract pathname, or null if this pathname
196
     *             does not name a parent
197
     */
198 131
    public function getParentFile()
199
    {
200 131
        $p = $this->getParent();
201 131
        if ($p === null) {
0 ignored issues
show
introduced by
The condition $p === null is always false.
Loading history...
202
            return null;
203
        }
204
205 131
        return new File((string) $p, (int) $this->prefixLength);
206
    }
207
208
    /**
209
     * Converts this abstract pathname into a pathname string.  The resulting
210
     * string uses the default name-separator character to separate the names
211
     * in the name sequence.
212
     *
213
     * @return string The string form of this abstract pathname
214
     */
215 879
    public function getPath()
216
    {
217 879
        return (string) $this->path;
218
    }
219
220
    /**
221
     * Returns path without leading basedir.
222
     *
223
     * @param string $basedir Base directory to strip
224
     *
225
     * @return string Path without basedir
226
     *
227
     * @uses getPath()
228
     */
229 6
    public function getPathWithoutBase($basedir)
230
    {
231 6
        if (!StringHelper::endsWith(FileUtils::getSeparator(), $basedir)) {
232 6
            $basedir .= FileUtils::getSeparator();
233
        }
234 6
        $path = $this->getPath();
235 6
        if (substr($path, 0, strlen($basedir)) != $basedir) {
236
            //path does not begin with basedir, we don't modify it
237 1
            return $path;
238
        }
239
240 5
        return substr($path, strlen($basedir));
241
    }
242
243
    /**
244
     * Tests whether this abstract pathname is absolute.  The definition of
245
     * absolute pathname is system dependent.  On UNIX systems, a pathname is
246
     * absolute if its prefix is "/".  On Win32 systems, a pathname is absolute
247
     * if its prefix is a drive specifier followed by "\\", or if its prefix
248
     * is "\\".
249
     *
250
     * @return boolean true if this abstract pathname is absolute, false otherwise
251
     */
252 194
    public function isAbsolute()
253
    {
254 194
        return ($this->prefixLength !== 0);
255
    }
256
257
    /**
258
     * Returns the file extension for a given file. For example test.php would be returned as php.
259
     *
260
     * @return string The name of the extension.
261
     */
262 15
    public function getFileExtension()
263
    {
264 15
        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...
265
    }
266
267
    /**
268
     * Returns the absolute pathname string of this abstract pathname.
269
     *
270
     * If this abstract pathname is already absolute, then the pathname
271
     * string is simply returned as if by the getPath method.
272
     * If this abstract pathname is the empty abstract pathname then
273
     * the pathname string of the current user directory, which is named by the
274
     * system property user.dir, is returned.  Otherwise this
275
     * pathname is resolved in a system-dependent way.  On UNIX systems, a
276
     * relative pathname is made absolute by resolving it against the current
277
     * user directory.  On Win32 systems, a relative pathname is made absolute
278
     * by resolving it against the current directory of the drive named by the
279
     * pathname, if any; if not, it is resolved against the current user
280
     * directory.
281
     *
282
     * @return string The absolute pathname string denoting the same file or
283
     *                directory as this abstract pathname
284
     * @see    #isAbsolute()
285
     */
286 861
    public function getAbsolutePath()
287
    {
288 861
        $fs = FileSystem::getFileSystem();
289
290 861
        return $fs->resolveFile($this);
291
    }
292
293
    /**
294
     * Returns the absolute form of this abstract pathname.  Equivalent to
295
     * getAbsolutePath.
296
     *
297
     * @return File The absolute abstract pathname denoting the same file or
298
     *                directory as this abstract pathname
299
     */
300 4
    public function getAbsoluteFile()
301
    {
302 4
        return new File((string) $this->getAbsolutePath());
303
    }
304
305
306
    /**
307
     * Returns the canonical pathname string of this abstract pathname.
308
     *
309
     * A canonical pathname is both absolute and unique. The precise
310
     * definition of canonical form is system-dependent. This method first
311
     * converts this pathname to absolute form if necessary, as if by invoking the
312
     * getAbsolutePath() method, and then maps it to its unique form in a
313
     * system-dependent way.  This typically involves removing redundant names
314
     * such as "." and .. from the pathname, resolving symbolic links
315
     * (on UNIX platforms), and converting drive letters to a standard case
316
     * (on Win32 platforms).
317
     *
318
     * Every pathname that denotes an existing file or directory has a
319
     * unique canonical form.  Every pathname that denotes a nonexistent file
320
     * or directory also has a unique canonical form.  The canonical form of
321
     * the pathname of a nonexistent file or directory may be different from
322
     * the canonical form of the same pathname after the file or directory is
323
     * created.  Similarly, the canonical form of the pathname of an existing
324
     * file or directory may be different from the canonical form of the same
325
     * pathname after the file or directory is deleted.
326
     *
327
     * @return string The canonical pathname string denoting the same file or
328
     *                directory as this abstract pathname
329
     */
330 33
    public function getCanonicalPath()
331
    {
332 33
        $fs = FileSystem::getFileSystem();
333
334 33
        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...
335
    }
336
337
338
    /**
339
     * Returns the canonical form of this abstract pathname.  Equivalent to
340
     * getCanonicalPath(.
341
     *
342
     * @return File The canonical pathname string denoting the same file or
343
     *                   directory as this abstract pathname
344
     */
345 33
    public function getCanonicalFile()
346
    {
347 33
        return new File($this->getCanonicalPath());
348
    }
349
350
    /* -- Attribute accessors -- */
351
352
    /**
353
     * Tests whether the application can read the file denoted by this
354
     * abstract pathname.
355
     *
356
     * @return boolean true if and only if the file specified by this
357
     *                 abstract pathname exists and can be read by the
358
     *                 application; false otherwise
359
     */
360 843
    public function canRead()
361
    {
362 843
        $fs = FileSystem::getFileSystem();
363
364 843
        if ($fs->checkAccess($this)) {
365 843
            return (bool) @is_link($this->getAbsolutePath()) || @is_readable($this->getAbsolutePath());
366
        }
367
368
        return false;
369
    }
370
371
    /**
372
     * Tests whether the application can modify to the file denoted by this
373
     * abstract pathname.
374
     *
375
     * @return boolean true if and only if the file system actually
376
     *                 contains a file denoted by this abstract pathname and
377
     *                 the application is allowed to write to the file;
378
     *                 false otherwise.
379
     */
380 81
    public function canWrite()
381
    {
382 81
        $fs = FileSystem::getFileSystem();
383
384 81
        return $fs->checkAccess($this, true);
385
    }
386
387
    /**
388
     * Tests whether the file denoted by this abstract pathname exists.
389
     *
390
     * @return boolean true if and only if the file denoted by this
391
     *                 abstract pathname exists; false otherwise
392
     */
393 858
    public function exists()
394
    {
395 858
        clearstatcache();
396
397 858
        if (is_link($this->path)) {
398 4
            return true;
399
        }
400
401 858
        if ($this->isDirectory()) {
402 854
            return true;
403
        }
404
405 841
        return @file_exists($this->path) || is_link($this->path);
406
    }
407
408
    /**
409
     * Tests whether the file denoted by this abstract pathname is a
410
     * directory.
411
     *
412
     * @return boolean true if and only if the file denoted by this
413
     *                 abstract pathname exists and is a directory;
414
     *                 false otherwise
415
     * @throws IOException
416
     */
417 858
    public function isDirectory()
418
    {
419 858
        clearstatcache();
420 858
        $fs = FileSystem::getFileSystem();
421 858
        if ($fs->checkAccess($this) !== true) {
422
            throw new IOException("No read access to " . $this->path);
423
        }
424
425 858
        return @is_dir($this->path) && !@is_link($this->path);
426
    }
427
428
    /**
429
     * Tests whether the file denoted by this abstract pathname is a normal
430
     * file.  A file is normal if it is not a directory and, in
431
     * addition, satisfies other system-dependent criteria.  Any non-directory
432
     * file created by a Java application is guaranteed to be a normal file.
433
     *
434
     * @return boolean true if and only if the file denoted by this
435
     *                 abstract pathname exists and is a normal file;
436
     *                 false otherwise
437
     */
438 191
    public function isFile()
439
    {
440 191
        clearstatcache();
441
        //$fs = FileSystem::getFileSystem();
442 191
        return @is_file($this->path);
443
    }
444
445
    /**
446
     * Tests whether the file denoted by this abstract pathname is a symbolic link.
447
     *
448
     * @return boolean true if and only if the file denoted by this
449
     *                 abstract pathname exists and is a symbolic link;
450
     *                 false otherwise
451
     * @throws IOException
452
     */
453 140
    public function isLink()
454
    {
455 140
        clearstatcache();
456 140
        $fs = FileSystem::getFileSystem();
457 140
        if ($fs->checkAccess($this) !== true) {
458
            throw new IOException("No read access to " . $this->path);
459
        }
460
461 140
        return @is_link($this->path);
462
    }
463
464
    /**
465
     * Tests whether the file denoted by this abstract pathname is executable.
466
     *
467
     * @return boolean true if and only if the file denoted by this
468
     *                 abstract pathname exists and is a symbolic link;
469
     *                 false otherwise
470
     * @throws IOException
471
     */
472 2
    public function isExecutable()
473
    {
474 2
        clearstatcache();
475 2
        $fs = FileSystem::getFileSystem();
476 2
        if ($fs->checkAccess($this) !== true) {
477
            throw new IOException("No read access to " . $this->path);
478
        }
479
480 2
        return @is_executable($this->path);
481
    }
482
483
    /**
484
     * Returns the target of the symbolic link denoted by this abstract pathname
485
     *
486
     * @return string the target of the symbolic link denoted by this abstract pathname
487
     */
488 8
    public function getLinkTarget()
489
    {
490 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...
491
    }
492
493
    /**
494
     * Returns the time that the file denoted by this abstract pathname was
495
     * last modified.
496
     *
497
     * @return int An integer value representing the time the file was
498
     *             last modified, measured in seconds since the epoch
499
     *             (00:00:00 GMT, January 1, 1970), or 0 if the
500
     *             file does not exist or if an I/O error occurs
501
     * @throws IOException
502
     */
503 55
    public function lastModified()
504
    {
505 55
        $fs = FileSystem::getFileSystem();
506 55
        if ($fs->checkAccess($this) !== true) {
507
            throw new IOException("No read access to " . $this->path);
508
        }
509
510 55
        return $fs->getLastModifiedTime($this);
511
    }
512
513
    /**
514
     * Returns the length of the file denoted by this abstract pathname.
515
     * The return value is unspecified if this pathname denotes a directory.
516
     *
517
     * @return int The length, in bytes, of the file denoted by this abstract
518
     *             pathname, or 0 if the file does not exist
519
     * @throws IOException
520
     */
521 27
    public function length()
522
    {
523 27
        $fs = FileSystem::getFileSystem();
524 27
        if ($fs->checkAccess($this) !== true) {
525
            throw new IOException("No read access to " . $this->path . "\n");
526
        }
527
528 27
        return $fs->getLength($this);
529
    }
530
531
    /**
532
     * Convenience method for returning the contents of this file as a string.
533
     * This method uses file_get_contents() to read file in an optimized way.
534
     *
535
     * @return string
536
     * @throws Exception - if file cannot be read
537
     */
538 4
    public function contents()
539
    {
540 4
        if (!$this->canRead() || !$this->isFile()) {
541
            throw new IOException("Cannot read file contents!");
542
        }
543
544 4
        return file_get_contents($this->getAbsolutePath());
545
    }
546
547
    /* -- File operations -- */
548
549
    /**
550
     * Atomically creates a new, empty file named by this abstract pathname if
551
     * and only if a file with this name does not yet exist.  The check for the
552
     * existence of the file and the creation of the file if it does not exist
553
     * are a single operation that is atomic with respect to all other
554
     * filesystem activities that might affect the file.
555
     *
556
     * @param bool $parents
557
     * @return boolean     true if the named file does not exist and was
558
     *                     successfully created; <code>false</code> if the named file
559
     *                     already exists
560
     * @throws IOException
561
     */
562 80
    public function createNewFile($parents = true)
563
    {
564
        /**
565
         * @var File $parent
566
         */
567 80
        $parent = $this->getParentFile();
568 80
        if ($parents && $parent !== null && !$parent->exists()) {
569 5
            $parent->mkdirs();
570
        }
571
572 80
        $file = FileSystem::getFileSystem()->createNewFile($this->path);
573
574 79
        return $file;
575
    }
576
577
    /**
578
     * Deletes the file or directory denoted by this abstract pathname.  If
579
     * this pathname denotes a directory, then the directory must be empty in
580
     * order to be deleted.
581
     *
582
     * @param bool $recursive
583
     * @throws IOException
584
     */
585 206
    public function delete($recursive = false)
586
    {
587 206
        $fs = FileSystem::getFileSystem();
588 206
        if ($fs->canDelete($this) !== true) {
589
            throw new IOException("Cannot delete " . $this->path . "\n");
590
        }
591
592 206
        $fs->delete($this, $recursive);
593 206
    }
594
595
    /**
596
     * Requests that the file or directory denoted by this abstract pathname
597
     * be deleted when php terminates.  Deletion will be attempted only for
598
     * normal termination of php and if and if only Phing::shutdown() is
599
     * called.
600
     *
601
     * Once deletion has been requested, it is not possible to cancel the
602
     * request.  This method should therefore be used with care.
603
     */
604
    public function deleteOnExit()
605
    {
606
        $fs = FileSystem::getFileSystem();
607
        $fs->deleteOnExit($this);
608
    }
609
610
    /**
611
     * Returns an array of strings naming the files and directories in the
612
     * directory denoted by this abstract pathname.
613
     *
614
     * If this abstract pathname does not denote a directory, then this
615
     * method returns null  Otherwise an array of strings is
616
     * returned, one for each file or directory in the directory.  Names
617
     * denoting the directory itself and the directory's parent directory are
618
     * not included in the result.  Each string is a file name rather than a
619
     * complete path.
620
     *
621
     * There is no guarantee that the name strings in the resulting array
622
     * will appear in any specific order; they are not, in particular,
623
     * guaranteed to appear in alphabetical order.
624
     *
625
     * @return array|null An array of strings naming the files and directories in the
626
     *                    directory denoted by this abstract pathname.  The array will be
627
     *                    empty if the directory is empty.  Returns null if
628
     *                    this abstract pathname does not denote a directory, or if an
629
     *                    I/O error occurs.
630
     */
631 219
    public function listDir(): ?array
632
    {
633
        try {
634 219
            $elements = FileSystem::getFileSystem()->listContents($this);
635
        } catch (IOException $e) {
636
            $elements = null;
637
        }
638
639 219
        return $elements;
640
    }
641
642
    /**
643
     * Creates the directory named by this abstract pathname, including any
644
     * necessary but nonexistent parent directories.  Note that if this
645
     * operation fails it may have succeeded in creating some of the necessary
646
     * parent directories.
647
     *
648
     * @param int|null $mode
649
     * @return boolean     true if and only if the directory was created,
650
     *                     along with all necessary parent directories; false
651
     *                     otherwise
652
     * @throws IOException
653
     */
654 167
    public function mkdirs($mode = null)
655
    {
656 167
        if ($this->exists()) {
657
            return false;
658
        }
659
        try {
660 167
            if ($this->mkdir($mode)) {
661 167
                return true;
662
            }
663
        } catch (IOException $ioe) {
664
            // IOException from mkdir() means that directory propbably didn't exist.
665
        }
666 33
        $parentFile = $this->getParentFile();
667
668 33
        return (($parentFile !== null) && ($parentFile->mkdirs() && $this->mkdir($mode)));
669
    }
670
671
    /**
672
     * Creates the directory named by this abstract pathname.
673
     *
674
     * @param int|null $mode
675
     * @return boolean     true if and only if the directory was created; false otherwise
676
     * @throws IOException
677
     */
678 167
    public function mkdir($mode = null)
679
    {
680 167
        $fs = FileSystem::getFileSystem();
681
682 167
        if ($fs->checkAccess(new File($this->path), true) !== true) {
683
            throw new IOException("No write access to " . $this->getPath());
684
        }
685
686 167
        return $fs->createDirectory($this, $mode);
687
    }
688
689
    /**
690
     * Renames the file denoted by this abstract pathname.
691
     *
692
     * @param File $destFile The new abstract pathname for the named file
693
     * @throws IOException
694
     */
695 1
    public function renameTo(File $destFile)
696
    {
697 1
        $fs = FileSystem::getFileSystem();
698 1
        if ($fs->checkAccess($this) !== true) {
699
            throw new IOException("No write access to " . $this->getPath());
700
        }
701
702 1
        $fs->rename($this, $destFile);
703 1
    }
704
705
    /**
706
     * Simple-copies file denoted by this abstract pathname into another
707
     * PhingFile
708
     *
709
     * @param File $destFile The new abstract pathname for the named file
710
     * @throws IOException
711
     */
712 27
    public function copyTo(File $destFile)
713
    {
714 27
        $fs = FileSystem::getFileSystem();
715
716 27
        if ($fs->checkAccess($this) !== true) {
717
            throw new IOException("No read access to " . $this->getPath() . "\n");
718
        }
719
720 27
        if ($fs->checkAccess($destFile, true) !== true) {
721
            throw new IOException("File::copyTo() No write access to " . $destFile->getPath());
722
        }
723
724 27
        $fs->copy($this, $destFile);
725 27
    }
726
727
    /**
728
     * Sets the last-modified time of the file or directory named by this
729
     * abstract pathname.
730
     *
731
     * All platforms support file-modification times to the nearest second,
732
     * but some provide more precision.  The argument will be truncated to fit
733
     * the supported precision.  If the operation succeeds and no intervening
734
     * operations on the file take place, then the next invocation of the
735
     * lastModified method will return the (possibly truncated) time argument
736
     * that was passed to this method.
737
     *
738
     * @param int $time The new last-modified time, measured in milliseconds since
739
     *                       the epoch (00:00:00 GMT, January 1, 1970)
740
     * @throws Exception
741
     */
742 75
    public function setLastModified($time)
743
    {
744 75
        $time = (int) $time;
745 75
        if ($time < 0) {
746
            throw new Exception("IllegalArgumentException, Negative $time\n");
747
        }
748
749 75
        $fs = FileSystem::getFileSystem();
750
751 75
        $fs->setLastModifiedTime($this, $time);
752 75
    }
753
754
    /**
755
     * Sets the owner of the file.
756
     *
757
     * @param mixed $user User name or number.
758
     *
759
     * @throws IOException
760
     */
761
    public function setUser($user)
762
    {
763
        $fs = FileSystem::getFileSystem();
764
765
        $fs->chown($this->getPath(), $user);
766
    }
767
768
    /**
769
     * Sets the group of the file.
770
     *
771
     * @param string $group
772
     *
773
     * @throws IOException
774
     */
775
    public function setGroup($group)
776
    {
777
        $fs = FileSystem::getFileSystem();
778
779
        $fs->chgrp($this->getPath(), $group);
780
    }
781
782
    /**
783
     * Sets the mode of the file
784
     *
785
     * @param int $mode Octal mode.
786
     * @throws IOException
787
     */
788 60
    public function setMode($mode)
789
    {
790 60
        $fs = FileSystem::getFileSystem();
791
792 60
        $fs->chmod($this->getPath(), $mode);
793 60
    }
794
795
    /**
796
     * Retrieve the mode of this file.
797
     *
798
     * @return int
799
     */
800 49
    public function getMode()
801
    {
802 49
        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...
803
    }
804
805
    /* -- Basic infrastructure -- */
806
807
    /**
808
     * Compares two abstract pathnames lexicographically.  The ordering
809
     * defined by this method depends upon the underlying system.  On UNIX
810
     * systems, alphabetic case is significant in comparing pathnames; on Win32
811
     * systems it is not.
812
     *
813
     * @param File $file Th file whose pathname sould be compared to the pathname of this file.
814
     *
815
     * @return int Zero if the argument is equal to this abstract pathname, a
816
     *             value less than zero if this abstract pathname is
817
     *             lexicographically less than the argument, or a value greater
818
     *             than zero if this abstract pathname is lexicographically
819
     *             greater than the argument
820
     */
821 35
    public function compareTo(File $file)
822
    {
823 35
        $fs = FileSystem::getFileSystem();
824
825 35
        return $fs->compare($this, $file);
826
    }
827
828
    /**
829
     * Tests this abstract pathname for equality with the given object.
830
     * Returns <code>true</code> if and only if the argument is not
831
     * <code>null</code> and is an abstract pathname that denotes the same file
832
     * or directory as this abstract pathname.  Whether or not two abstract
833
     * pathnames are equal depends upon the underlying system.  On UNIX
834
     * systems, alphabetic case is significant in comparing pathnames; on Win32
835
     * systems it is not.
836
     *
837
     * @param File $obj
838
     *
839
     * @return boolean
840
     */
841 35
    public function equals($obj)
842
    {
843 35
        if (($obj !== null) && ($obj instanceof File)) {
844 35
            return ($this->compareTo($obj) === 0);
845
        }
846
847
        return false;
848
    }
849
850
    /**
851
     * Return string representation of the object
852
     *
853
     * @return string
854
     */
855 853
    public function __toString()
856
    {
857 853
        return $this->getPath();
858
    }
859
}
860