Passed
Push — master ( 972120...1c77fc )
by Michiel
08:19
created

File::setMode()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 5
ccs 3
cts 3
cp 1
crap 1
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
        return FileSystem::getFileSystem()->createNewFile($this->path);
573
    }
574
575
    /**
576
     * Deletes the file or directory denoted by this abstract pathname.  If
577
     * this pathname denotes a directory, then the directory must be empty in
578
     * order to be deleted.
579
     *
580
     * @param bool $recursive
581
     * @throws IOException
582
     */
583 206
    public function delete($recursive = false)
584
    {
585 206
        $fs = FileSystem::getFileSystem();
586 206
        if ($fs->canDelete($this) !== true) {
587
            throw new IOException("Cannot delete " . $this->path . "\n");
588
        }
589
590 206
        $fs->delete($this, $recursive);
591 206
    }
592
593
    /**
594
     * Requests that the file or directory denoted by this abstract pathname
595
     * be deleted when php terminates.  Deletion will be attempted only for
596
     * normal termination of php and if and if only Phing::shutdown() is
597
     * called.
598
     *
599
     * Once deletion has been requested, it is not possible to cancel the
600
     * request.  This method should therefore be used with care.
601
     */
602
    public function deleteOnExit()
603
    {
604
        $fs = FileSystem::getFileSystem();
605
        $fs->deleteOnExit($this);
606
    }
607
608
    /**
609
     * Returns an array of strings naming the files and directories in the
610
     * directory denoted by this abstract pathname.
611
     *
612
     * If this abstract pathname does not denote a directory, then this
613
     * method returns null  Otherwise an array of strings is
614
     * returned, one for each file or directory in the directory.  Names
615
     * denoting the directory itself and the directory's parent directory are
616
     * not included in the result.  Each string is a file name rather than a
617
     * complete path.
618
     *
619
     * There is no guarantee that the name strings in the resulting array
620
     * will appear in any specific order; they are not, in particular,
621
     * guaranteed to appear in alphabetical order.
622
     *
623
     * @return array|null An array of strings naming the files and directories in the
624
     *                    directory denoted by this abstract pathname.  The array will be
625
     *                    empty if the directory is empty.  Returns null if
626
     *                    this abstract pathname does not denote a directory, or if an
627
     *                    I/O error occurs.
628
     */
629 219
    public function listDir(): ?array
630
    {
631
        try {
632 219
            $elements = FileSystem::getFileSystem()->listContents($this);
633
        } catch (IOException $e) {
634
            $elements = null;
635
        }
636
637 219
        return $elements;
638
    }
639
640
    /**
641
     * Creates the directory named by this abstract pathname, including any
642
     * necessary but nonexistent parent directories.  Note that if this
643
     * operation fails it may have succeeded in creating some of the necessary
644
     * parent directories.
645
     *
646
     * @param int|null $mode
647
     * @return boolean     true if and only if the directory was created,
648
     *                     along with all necessary parent directories; false
649
     *                     otherwise
650
     * @throws IOException
651
     */
652 167
    public function mkdirs($mode = null)
653
    {
654 167
        if ($this->exists()) {
655
            return false;
656
        }
657
        try {
658 167
            if ($this->mkdir($mode)) {
659 167
                return true;
660
            }
661
        } catch (IOException $ioe) {
662
            // IOException from mkdir() means that directory propbably didn't exist.
663
        }
664 33
        $parentFile = $this->getParentFile();
665
666 33
        return (($parentFile !== null) && ($parentFile->mkdirs() && $this->mkdir($mode)));
667
    }
668
669
    /**
670
     * Creates the directory named by this abstract pathname.
671
     *
672
     * @param int|null $mode
673
     * @return boolean     true if and only if the directory was created; false otherwise
674
     * @throws IOException
675
     */
676 167
    public function mkdir($mode = null)
677
    {
678 167
        $fs = FileSystem::getFileSystem();
679
680 167
        if ($fs->checkAccess(new File($this->path), true) !== true) {
681
            throw new IOException("No write access to " . $this->getPath());
682
        }
683
684 167
        return $fs->createDirectory($this, $mode);
685
    }
686
687
    /**
688
     * Renames the file denoted by this abstract pathname.
689
     *
690
     * @param File $destFile The new abstract pathname for the named file
691
     * @throws IOException
692
     */
693 1
    public function renameTo(File $destFile)
694
    {
695 1
        $fs = FileSystem::getFileSystem();
696 1
        if ($fs->checkAccess($this) !== true) {
697
            throw new IOException("No write access to " . $this->getPath());
698
        }
699
700 1
        $fs->rename($this, $destFile);
701 1
    }
702
703
    /**
704
     * Simple-copies file denoted by this abstract pathname into another
705
     * PhingFile
706
     *
707
     * @param File $destFile The new abstract pathname for the named file
708
     * @throws IOException
709
     */
710 27
    public function copyTo(File $destFile)
711
    {
712 27
        $fs = FileSystem::getFileSystem();
713
714 27
        if ($fs->checkAccess($this) !== true) {
715
            throw new IOException("No read access to " . $this->getPath() . "\n");
716
        }
717
718 27
        if ($fs->checkAccess($destFile, true) !== true) {
719
            throw new IOException("File::copyTo() No write access to " . $destFile->getPath());
720
        }
721
722 27
        $fs->copy($this, $destFile);
723 27
    }
724
725
    /**
726
     * Sets the last-modified time of the file or directory named by this
727
     * abstract pathname.
728
     *
729
     * All platforms support file-modification times to the nearest second,
730
     * but some provide more precision.  The argument will be truncated to fit
731
     * the supported precision.  If the operation succeeds and no intervening
732
     * operations on the file take place, then the next invocation of the
733
     * lastModified method will return the (possibly truncated) time argument
734
     * that was passed to this method.
735
     *
736
     * @param int $time The new last-modified time, measured in milliseconds since
737
     *                       the epoch (00:00:00 GMT, January 1, 1970)
738
     * @throws Exception
739
     */
740 75
    public function setLastModified($time)
741
    {
742 75
        $time = (int) $time;
743 75
        if ($time < 0) {
744
            throw new Exception("IllegalArgumentException, Negative $time\n");
745
        }
746
747 75
        $fs = FileSystem::getFileSystem();
748
749 75
        $fs->setLastModifiedTime($this, $time);
750 75
    }
751
752
    /**
753
     * Sets the owner of the file.
754
     *
755
     * @param mixed $user User name or number.
756
     *
757
     * @throws IOException
758
     */
759
    public function setUser($user)
760
    {
761
        $fs = FileSystem::getFileSystem();
762
763
        $fs->chown($this->getPath(), $user);
764
    }
765
766
    /**
767
     * Sets the group of the file.
768
     *
769
     * @param string $group
770
     *
771
     * @throws IOException
772
     */
773
    public function setGroup($group)
774
    {
775
        $fs = FileSystem::getFileSystem();
776
777
        $fs->chgrp($this->getPath(), $group);
778
    }
779
780
    /**
781
     * Sets the mode of the file
782
     *
783
     * @param int $mode Octal mode.
784
     * @throws IOException
785
     */
786 60
    public function setMode($mode)
787
    {
788 60
        $fs = FileSystem::getFileSystem();
789
790 60
        $fs->chmod($this->getPath(), $mode);
791 60
    }
792
793
    /**
794
     * Retrieve the mode of this file.
795
     *
796
     * @return int
797
     */
798 49
    public function getMode()
799
    {
800 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...
801
    }
802
803
    /* -- Basic infrastructure -- */
804
805
    /**
806
     * Compares two abstract pathnames lexicographically.  The ordering
807
     * defined by this method depends upon the underlying system.  On UNIX
808
     * systems, alphabetic case is significant in comparing pathnames; on Win32
809
     * systems it is not.
810
     *
811
     * @param File $file Th file whose pathname sould be compared to the pathname of this file.
812
     *
813
     * @return int Zero if the argument is equal to this abstract pathname, a
814
     *             value less than zero if this abstract pathname is
815
     *             lexicographically less than the argument, or a value greater
816
     *             than zero if this abstract pathname is lexicographically
817
     *             greater than the argument
818
     */
819 35
    public function compareTo(File $file)
820
    {
821 35
        $fs = FileSystem::getFileSystem();
822
823 35
        return $fs->compare($this, $file);
824
    }
825
826
    /**
827
     * Tests this abstract pathname for equality with the given object.
828
     * Returns <code>true</code> if and only if the argument is not
829
     * <code>null</code> and is an abstract pathname that denotes the same file
830
     * or directory as this abstract pathname.  Whether or not two abstract
831
     * pathnames are equal depends upon the underlying system.  On UNIX
832
     * systems, alphabetic case is significant in comparing pathnames; on Win32
833
     * systems it is not.
834
     *
835
     * @param File $obj
836
     *
837
     * @return boolean
838
     */
839 35
    public function equals($obj)
840
    {
841 35
        if (($obj !== null) && ($obj instanceof File)) {
842 35
            return ($this->compareTo($obj) === 0);
843
        }
844
845
        return false;
846
    }
847
848
    /**
849
     * Return string representation of the object
850
     *
851
     * @return string
852
     */
853 853
    public function __toString()
854
    {
855 853
        return $this->getPath();
856
    }
857
}
858