Completed
Push — master ( 89abc8...a320a7 )
by Siad
16:11
created

PhingFile   F

Complexity

Total Complexity 91

Size/Duplication

Total Lines 828
Duplicated Lines 0 %

Test Coverage

Coverage 82.76%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 156
dl 0
loc 828
ccs 168
cts 203
cp 0.8276
rs 2
c 1
b 0
f 0
wmc 91

43 Methods

Rating   Name   Duplication   Size   Complexity  
A constructStringParentStringChild() 0 11 2
A isLink() 0 9 2
A getAbsoluteFile() 0 3 1
A isDirectory() 0 9 3
A listDir() 0 9 2
A getPath() 0 3 1
A getCanonicalPath() 0 5 1
A createNewFile() 0 13 4
A getAbsolutePath() 0 5 1
A contents() 0 7 3
A setLastModified() 0 10 2
A isExecutable() 0 9 2
A getParentFile() 0 8 2
A setMode() 0 5 1
A deleteOnExit() 0 4 1
A equals() 0 7 3
A renameTo() 0 8 2
B __construct() 0 15 8
A getPathWithoutBase() 0 12 3
A getFileExtension() 0 3 1
A __toString() 0 3 1
A exists() 0 13 4
A isFile() 0 5 1
A canWrite() 0 5 1
A getParent() 0 13 5
A canRead() 0 9 3
A getLinkTarget() 0 3 1
A constructPathname() 0 6 1
A compareTo() 0 5 1
A mkdir() 0 9 2
A setGroup() 0 5 1
A length() 0 8 2
A delete() 0 8 2
A constructFileParentStringChild() 0 11 2
A getMode() 0 3 1
A getCanonicalFile() 0 3 1
A copyTo() 0 13 3
A setUser() 0 5 1
A getPrefixLength() 0 3 1
A mkdirs() 0 15 6
A getName() 0 9 3
A isAbsolute() 0 3 1
A lastModified() 0 8 2

How to fix   Complexity   

Complex Class

Complex classes like PhingFile often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use PhingFile, and based on these observations, apply Extract Interface, too.

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
/**
21
 * An abstract representation of file and directory pathnames.
22
 *
23
 * @package phing.system.io
24
 */
25
class PhingFile
26
{
27
    /**
28
     * This abstract pathname's normalized pathname string.  A normalized
29
     * pathname string uses the default name-separator character and does not
30
     * contain any duplicate or redundant separators.
31
     */
32
    private $path = null;
33
34
    /**
35
     * The length of this abstract pathname's prefix, or zero if it has no prefix.
36
     *
37
     * @var int
38
     */
39
    private $prefixLength = 0;
40
41
    /**
42
     * constructor
43
     *
44
     * @param mixed $arg1
45
     * @param mixed $arg2
46
     *
47
     * @throws IOException
48
     * @throws NullPointerException
49
     */
50 790
    public function __construct($arg1 = null, $arg2 = null)
51
    {
52
        /* simulate signature identified constructors */
53 790
        if ($arg1 instanceof PhingFile && is_string($arg2)) {
54 337
            $this->constructFileParentStringChild($arg1, $arg2);
55 790
        } elseif (is_string($arg1) && ($arg2 === null)) {
56 790
            $this->constructPathname($arg1);
57 100
        } elseif (is_string($arg1) && is_string($arg2)) {
58 6
            $this->constructStringParentStringChild($arg1, $arg2);
59
        } else {
60 97
            if ($arg1 === null) {
61
                throw new NullPointerException("Argument1 to function must not be null");
62
            }
63 97
            $this->path = (string) $arg1;
64 97
            $this->prefixLength = (int) $arg2;
65
        }
66 790
    }
67
68
    /**
69
     * Returns the length of this abstract pathname's prefix.
70
     *
71
     * @return int
72
     */
73 784
    public function getPrefixLength()
74
    {
75 784
        return (int) $this->prefixLength;
76
    }
77
78
    /* -- constructors not called by signature match, so we need some helpers --*/
79
80
    /**
81
     * @param string $pathname
82
     *
83
     * @throws IOException
84
     */
85 790
    protected function constructPathname(string $pathname): void
86
    {
87 790
        $fs = FileSystem::getFileSystem();
88
89 790
        $this->path = (string) $fs->normalize($pathname);
90 790
        $this->prefixLength = (int) $fs->prefixLength($this->path);
91 790
    }
92
93
    /**
94
     * @param string $parent
95
     * @param string $child
96
     * @throws IOException
97
     */
98 6
    protected function constructStringParentStringChild(string $parent, string $child): void
99
    {
100 6
        $fs = FileSystem::getFileSystem();
101
102 6
        if ($parent === "") {
103
            $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
104
        } else {
105 6
            $this->path = $fs->resolve($fs->normalize($parent), $fs->normalize($child));
106
        }
107
108 6
        $this->prefixLength = (int) $fs->prefixLength($this->path);
109 6
    }
110
111
    /**
112
     * @param PhingFile $parent
113
     * @param string $child
114
     * @throws IOException
115
     */
116 337
    protected function constructFileParentStringChild(PhingFile $parent, string $child): void
117
    {
118 337
        $fs = FileSystem::getFileSystem();
119
120 337
        if ($parent->path === "") {
121
            $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
122
        } else {
123 337
            $this->path = $fs->resolve($parent->path, $fs->normalize($child));
124
        }
125
126 337
        $this->prefixLength = $fs->prefixLength($this->path);
127 337
    }
128
129
    /* -- Path-component accessors -- */
130
131
    /**
132
     * Returns the name of the file or directory denoted by this abstract
133
     * pathname.  This is just the last name in the pathname's name
134
     * sequence.  If the pathname's name sequence is empty, then the empty
135
     * string is returned.
136
     *
137
     * @return string The name of the file or directory denoted by this abstract
138
     *                pathname, or the empty string if this pathname's name sequence
139
     *                is empty
140
     */
141 763
    public function getName()
142
    {
143
        // that's a lastIndexOf
144 763
        $index = ((($res = strrpos($this->path, FileUtils::$separator)) === false) ? -1 : $res);
145 763
        if ($index < $this->prefixLength) {
146 1
            return substr($this->path, $this->prefixLength);
147
        }
148
149 763
        return substr($this->path, $index + 1);
150
    }
151
152
    /**
153
     * Returns the pathname string of this abstract pathname's parent, or
154
     * null if this pathname does not name a parent directory.
155
     *
156
     * The parent of an abstract pathname consists of the pathname's prefix,
157
     * if any, and each name in the pathname's name sequence except for the last.
158
     * If the name sequence is empty then the pathname does not name a parent
159
     * directory.
160
     *
161
     * @return string $pathname string of the parent directory named by this
162
     *                          abstract pathname, or null if this pathname does not name a parent
163
     */
164 765
    public function getParent()
165
    {
166
        // that's a lastIndexOf
167 765
        $index = ((($res = strrpos($this->path, FileUtils::$separator)) === false) ? -1 : $res);
168 765
        if ($index < $this->prefixLength) {
169 7
            if (($this->prefixLength > 0) && (strlen($this->path) > $this->prefixLength)) {
170
                return substr($this->path, 0, $this->prefixLength);
171
            }
172
173 7
            return null;
174
        }
175
176 763
        return substr($this->path, 0, $index);
177
    }
178
179
    /**
180
     * Returns the abstract pathname of this abstract pathname's parent,
181
     * or null if this pathname does not name a parent directory.
182
     *
183
     * The parent of an abstract pathname consists of the pathname's prefix,
184
     * if any, and each name in the pathname's name sequence except for the
185
     * last.  If the name sequence is empty then the pathname does not name
186
     * a parent directory.
187
     *
188
     * @return PhingFile|null The abstract pathname of the parent directory named by this
189
     *             abstract pathname, or null if this pathname
190
     *             does not name a parent
191
     */
192 95
    public function getParentFile()
193
    {
194 95
        $p = $this->getParent();
195 95
        if ($p === null) {
0 ignored issues
show
introduced by
The condition $p === null is always false.
Loading history...
196
            return null;
197
        }
198
199 95
        return new PhingFile((string) $p, (int) $this->prefixLength);
200
    }
201
202
    /**
203
     * Converts this abstract pathname into a pathname string.  The resulting
204
     * string uses the default name-separator character to separate the names
205
     * in the name sequence.
206
     *
207
     * @return string The string form of this abstract pathname
208
     */
209 790
    public function getPath()
210
    {
211 790
        return (string) $this->path;
212
    }
213
214
    /**
215
     * Returns path without leading basedir.
216
     *
217
     * @param string $basedir Base directory to strip
218
     *
219
     * @return string Path without basedir
220
     *
221
     * @uses getPath()
222
     */
223 5
    public function getPathWithoutBase($basedir)
224
    {
225 5
        if (!StringHelper::endsWith(FileUtils::$separator, $basedir)) {
226 5
            $basedir .= FileUtils::$separator;
227
        }
228 5
        $path = $this->getPath();
229 5
        if (substr($path, 0, strlen($basedir)) != $basedir) {
230
            //path does not begin with basedir, we don't modify it
231 1
            return $path;
232
        }
233
234 4
        return substr($path, strlen($basedir));
235
    }
236
237
    /**
238
     * Tests whether this abstract pathname is absolute.  The definition of
239
     * absolute pathname is system dependent.  On UNIX systems, a pathname is
240
     * absolute if its prefix is "/".  On Win32 systems, a pathname is absolute
241
     * if its prefix is a drive specifier followed by "\\", or if its prefix
242
     * is "\\".
243
     *
244
     * @return boolean true if this abstract pathname is absolute, false otherwise
245
     */
246 170
    public function isAbsolute()
247
    {
248 170
        return ($this->prefixLength !== 0);
249
    }
250
251
    /**
252
     * Returns the file extension for a given file. For example test.php would be returned as php.
253
     *
254
     * @return string The name of the extension.
255
     */
256 13
    public function getFileExtension()
257
    {
258 13
        return pathinfo((string) $this->getAbsolutePath(), PATHINFO_EXTENSION);
259
    }
260
261
    /**
262
     * Returns the absolute pathname string of this abstract pathname.
263
     *
264
     * If this abstract pathname is already absolute, then the pathname
265
     * string is simply returned as if by the getPath method.
266
     * If this abstract pathname is the empty abstract pathname then
267
     * the pathname string of the current user directory, which is named by the
268
     * system property user.dir, is returned.  Otherwise this
269
     * pathname is resolved in a system-dependent way.  On UNIX systems, a
270
     * relative pathname is made absolute by resolving it against the current
271
     * user directory.  On Win32 systems, a relative pathname is made absolute
272
     * by resolving it against the current directory of the drive named by the
273
     * pathname, if any; if not, it is resolved against the current user
274
     * directory.
275
     *
276
     * @return string The absolute pathname string denoting the same file or
277
     *                directory as this abstract pathname
278
     * @see    #isAbsolute()
279
     */
280 784
    public function getAbsolutePath()
281
    {
282 784
        $fs = FileSystem::getFileSystem();
283
284 784
        return $fs->resolveFile($this);
285
    }
286
287
    /**
288
     * Returns the absolute form of this abstract pathname.  Equivalent to
289
     * getAbsolutePath.
290
     *
291
     * @return PhingFile The absolute abstract pathname denoting the same file or
292
     *                directory as this abstract pathname
293
     */
294 4
    public function getAbsoluteFile()
295
    {
296 4
        return new PhingFile((string) $this->getAbsolutePath());
297
    }
298
299
300
    /**
301
     * Returns the canonical pathname string of this abstract pathname.
302
     *
303
     * A canonical pathname is both absolute and unique. The precise
304
     * definition of canonical form is system-dependent. This method first
305
     * converts this pathname to absolute form if necessary, as if by invoking the
306
     * getAbsolutePath() method, and then maps it to its unique form in a
307
     * system-dependent way.  This typically involves removing redundant names
308
     * such as "." and .. from the pathname, resolving symbolic links
309
     * (on UNIX platforms), and converting drive letters to a standard case
310
     * (on Win32 platforms).
311
     *
312
     * Every pathname that denotes an existing file or directory has a
313
     * unique canonical form.  Every pathname that denotes a nonexistent file
314
     * or directory also has a unique canonical form.  The canonical form of
315
     * the pathname of a nonexistent file or directory may be different from
316
     * the canonical form of the same pathname after the file or directory is
317
     * created.  Similarly, the canonical form of the pathname of an existing
318
     * file or directory may be different from the canonical form of the same
319
     * pathname after the file or directory is deleted.
320
     *
321
     * @return string The canonical pathname string denoting the same file or
322
     *                directory as this abstract pathname
323
     */
324 31
    public function getCanonicalPath()
325
    {
326 31
        $fs = FileSystem::getFileSystem();
327
328 31
        return $fs->canonicalize($this->path);
329
    }
330
331
332
    /**
333
     * Returns the canonical form of this abstract pathname.  Equivalent to
334
     * getCanonicalPath(.
335
     *
336
     * @return PhingFile The canonical pathname string denoting the same file or
337
     *                   directory as this abstract pathname
338
     */
339 31
    public function getCanonicalFile()
340
    {
341 31
        return new PhingFile($this->getCanonicalPath());
342
    }
343
344
    /* -- Attribute accessors -- */
345
346
    /**
347
     * Tests whether the application can read the file denoted by this
348
     * abstract pathname.
349
     *
350
     * @return boolean true if and only if the file specified by this
351
     *                 abstract pathname exists and can be read by the
352
     *                 application; false otherwise
353
     */
354 766
    public function canRead()
355
    {
356 766
        $fs = FileSystem::getFileSystem();
357
358 766
        if ($fs->checkAccess($this)) {
359 766
            return (bool) @is_link($this->getAbsolutePath()) || @is_readable($this->getAbsolutePath());
360
        }
361
362
        return false;
363
    }
364
365
    /**
366
     * Tests whether the application can modify to the file denoted by this
367
     * abstract pathname.
368
     *
369
     * @return boolean true if and only if the file system actually
370
     *                 contains a file denoted by this abstract pathname and
371
     *                 the application is allowed to write to the file;
372
     *                 false otherwise.
373
     */
374 72
    public function canWrite()
375
    {
376 72
        $fs = FileSystem::getFileSystem();
377
378 72
        return $fs->checkAccess($this, true);
379
    }
380
381
    /**
382
     * Tests whether the file denoted by this abstract pathname exists.
383
     *
384
     * @return boolean true if and only if the file denoted by this
385
     *                 abstract pathname exists; false otherwise
386
     */
387 784
    public function exists()
388
    {
389 784
        clearstatcache();
390
391 784
        if (is_link($this->path)) {
392 4
            return true;
393
        }
394
395 784
        if ($this->isDirectory()) {
396 780
            return true;
397
        }
398
399 767
        return @file_exists($this->path) || is_link($this->path);
400
    }
401
402
    /**
403
     * Tests whether the file denoted by this abstract pathname is a
404
     * directory.
405
     *
406
     * @throws IOException
407
     * @return boolean true if and only if the file denoted by this
408
     *                 abstract pathname exists and is a directory;
409
     *                 false otherwise
410
     */
411 784
    public function isDirectory()
412
    {
413 784
        clearstatcache();
414 784
        $fs = FileSystem::getFileSystem();
415 784
        if ($fs->checkAccess($this) !== true) {
416
            throw new IOException("No read access to " . $this->path);
417
        }
418
419 784
        return @is_dir($this->path) && !@is_link($this->path);
420
    }
421
422
    /**
423
     * Tests whether the file denoted by this abstract pathname is a normal
424
     * file.  A file is normal if it is not a directory and, in
425
     * addition, satisfies other system-dependent criteria.  Any non-directory
426
     * file created by a Java application is guaranteed to be a normal file.
427
     *
428
     * @return boolean true if and only if the file denoted by this
429
     *                 abstract pathname exists and is a normal file;
430
     *                 false otherwise
431
     */
432 127
    public function isFile()
433
    {
434 127
        clearstatcache();
435
        //$fs = FileSystem::getFileSystem();
436 127
        return @is_file($this->path);
437
    }
438
439
    /**
440
     * Tests whether the file denoted by this abstract pathname is a symbolic link.
441
     *
442
     * @throws IOException
443
     * @return boolean true if and only if the file denoted by this
444
     *                 abstract pathname exists and is a symbolic link;
445
     *                 false otherwise
446
     */
447 112
    public function isLink()
448
    {
449 112
        clearstatcache();
450 112
        $fs = FileSystem::getFileSystem();
451 112
        if ($fs->checkAccess($this) !== true) {
452
            throw new IOException("No read access to " . $this->path);
453
        }
454
455 112
        return @is_link($this->path);
456
    }
457
458
    /**
459
     * Tests whether the file denoted by this abstract pathname is executable.
460
     *
461
     * @throws IOException
462
     * @return boolean true if and only if the file denoted by this
463
     *                 abstract pathname exists and is a symbolic link;
464
     *                 false otherwise
465
     */
466 2
    public function isExecutable()
467
    {
468 2
        clearstatcache();
469 2
        $fs = FileSystem::getFileSystem();
470 2
        if ($fs->checkAccess($this) !== true) {
471
            throw new IOException("No read access to " . $this->path);
472
        }
473
474 2
        return @is_executable($this->path);
475
    }
476
477
    /**
478
     * Returns the target of the symbolic link denoted by this abstract pathname
479
     *
480
     * @return string the target of the symbolic link denoted by this abstract pathname
481
     */
482 8
    public function getLinkTarget()
483
    {
484 8
        return @readlink($this->path);
485
    }
486
487
    /**
488
     * Returns the time that the file denoted by this abstract pathname was
489
     * last modified.
490
     *
491
     * @throws IOException
492
     * @return int An integer value representing the time the file was
493
     *             last modified, measured in seconds since the epoch
494
     *             (00:00:00 GMT, January 1, 1970), or 0 if the
495
     *             file does not exist or if an I/O error occurs
496
     */
497 41
    public function lastModified()
498
    {
499 41
        $fs = FileSystem::getFileSystem();
500 41
        if ($fs->checkAccess($this) !== true) {
501
            throw new IOException("No read access to " . $this->path);
502
        }
503
504 41
        return $fs->getLastModifiedTime($this);
505
    }
506
507
    /**
508
     * Returns the length of the file denoted by this abstract pathname.
509
     * The return value is unspecified if this pathname denotes a directory.
510
     *
511
     * @throws IOException
512
     * @return int The length, in bytes, of the file denoted by this abstract
513
     *             pathname, or 0 if the file does not exist
514
     */
515 14
    public function length()
516
    {
517 14
        $fs = FileSystem::getFileSystem();
518 14
        if ($fs->checkAccess($this) !== true) {
519
            throw new IOException("No read access to " . $this->path . "\n");
520
        }
521
522 14
        return $fs->getLength($this);
523
    }
524
525
    /**
526
     * Convenience method for returning the contents of this file as a string.
527
     * This method uses file_get_contents() to read file in an optimized way.
528
     *
529
     * @return string
530
     * @throws Exception - if file cannot be read
531
     */
532 4
    public function contents()
533
    {
534 4
        if (!$this->canRead() || !$this->isFile()) {
535
            throw new IOException("Cannot read file contents!");
536
        }
537
538 4
        return file_get_contents($this->getAbsolutePath());
539
    }
540
541
    /* -- File operations -- */
542
543
    /**
544
     * Atomically creates a new, empty file named by this abstract pathname if
545
     * and only if a file with this name does not yet exist.  The check for the
546
     * existence of the file and the creation of the file if it does not exist
547
     * are a single operation that is atomic with respect to all other
548
     * filesystem activities that might affect the file.
549
     *
550
     * @param  bool $parents
551
     * @param  int $mode
552
     * @throws IOException
553
     * @return boolean     true if the named file does not exist and was
554
     *                     successfully created; <code>false</code> if the named file
555
     *                     already exists
556
     */
557 61
    public function createNewFile($parents = true, $mode = 0777)
0 ignored issues
show
Unused Code introduced by
The parameter $mode is not used and could be removed. ( Ignorable by Annotation )

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

557
    public function createNewFile($parents = true, /** @scrutinizer ignore-unused */ $mode = 0777)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

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