Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/*
3
 *  $Id: PhingFile.php 362 2008-03-08 10:07:53Z mrook $
4
 *
5
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
7
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
8
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
9
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
10
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
11
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
12
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
13
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
14
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
15
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
16
 *
17
 * This software consists of voluntary contributions made by many individuals
18
 * and is licensed under the LGPL. For more information please see
19
 * <http://phing.info>.
20
 */
21
 
22
include_once 'phing/system/io/FileSystem.php';
23
include_once 'phing/system/lang/NullPointerException.php';
24
 
25
/**
26
 * An abstract representation of file and directory pathnames.
27
 *
28
 * @version   $Revision: 1.1 $
29
 * @package   phing.system.io
30
 */
31
class PhingFile {
32
 
33
    /** separator string, static, obtained from FileSystem */
34
    public static $separator;
35
 
36
    /** path separator string, static, obtained from FileSystem (; or :)*/
37
    public static $pathSeparator;
38
 
39
    /**
40
     * This abstract pathname's normalized pathname string.  A normalized
41
     * pathname string uses the default name-separator character and does not
42
     * contain any duplicate or redundant separators.
43
     */
44
    private $path = null;
45
 
46
    /** The length of this abstract pathname's prefix, or zero if it has no prefix. */
47
    private $prefixLength = 0;
48
 
49
    /** constructor */
50
    function __construct($arg1 = null, $arg2 = null) {
51
 
52
        if (self::$separator === null || self::$pathSeparator === null) {
53
            $fs = FileSystem::getFileSystem();
54
            self::$separator = $fs->getSeparator();
55
            self::$pathSeparator = $fs->getPathSeparator();
56
        }
57
 
58
        /* simulate signature identified constructors */
59
        if ($arg1 instanceof PhingFile && is_string($arg2)) {
60
            $this->_constructFileParentStringChild($arg1, $arg2);
61
        } elseif (is_string($arg1) && ($arg2 === null)) {
62
            $this->_constructPathname($arg1);
63
        } elseif(is_string($arg1) && is_string($arg2)) {
64
            $this->_constructStringParentStringChild($arg1, $arg2);
65
        } else {
66
            if ($arg1 === null) {
67
                throw new NullPointerException("Argument1 to function must not be null");
68
            }
69
            $this->path = (string) $arg1;
70
            $this->prefixLength = (int) $arg2;
71
        }
72
    }
73
 
74
    /** Returns the length of this abstract pathname's prefix. */
75
    function getPrefixLength() {
76
        return (int) $this->prefixLength;
77
    }
78
 
79
    /* -- constructors not called by signature match, so we need some helpers --*/
80
 
81
    function _constructPathname($pathname) {
82
        // obtain ref to the filesystem layer
83
        $fs = FileSystem::getFileSystem();
84
 
85
        if ($pathname === null) {
86
            throw new NullPointerException("Argument to function must not be null");
87
        }
88
 
89
        $this->path = (string) $fs->normalize($pathname);
90
        $this->prefixLength = (int) $fs->prefixLength($this->path);
91
    }
92
 
93
    function _constructStringParentStringChild($parent, $child = null) {
94
        // obtain ref to the filesystem layer
95
        $fs = FileSystem::getFileSystem();
96
 
97
        if ($child === null) {
98
            throw new NullPointerException("Argument to function must not be null");
99
        }
100
        if ($parent !== null) {
101
            if ($parent === "") {
102
                $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
103
            } else {
104
                $this->path = $fs->resolve($fs->normalize($parent), $fs->normalize($child));
105
            }
106
        } else {
107
            $this->path = (string) $fs->normalize($child);
108
        }
109
        $this->prefixLength = (int) $fs->prefixLength($this->path);
110
    }
111
 
112
    function _constructFileParentStringChild($parent, $child = null) {
113
        // obtain ref to the filesystem layer
114
        $fs = FileSystem::getFileSystem();
115
 
116
        if ($child === null) {
117
            throw new NullPointerException("Argument to function must not be null");
118
        }
119
 
120
        if ($parent !== null) {
121
            if ($parent->path === "") {
122
                $this->path = $fs->resolve($fs->getDefaultParent(), $fs->normalize($child));
123
            } else {
124
                $this->path = $fs->resolve($parent->path, $fs->normalize($child));
125
            }
126
        } else {
127
            $this->path = $fs->normalize($child);
128
        }
129
        $this->prefixLength = $fs->prefixLength($this->path);
130
    }
131
 
132
    /* -- Path-component accessors -- */
133
 
134
    /**
135
     * Returns the name of the file or directory denoted by this abstract
136
     * pathname.  This is just the last name in the pathname's name
137
     * sequence.  If the pathname's name sequence is empty, then the empty
138
     * string is returned.
139
     *
140
     * @return  The name of the file or directory denoted by this abstract
141
     *          pathname, or the empty string if this pathname's name sequence
142
     *          is empty
143
     */
144
    function getName() {
145
        // that's a lastIndexOf
146
        $index = ((($res = strrpos($this->path, self::$separator)) === false) ? -1 : $res);
147
        if ($index < $this->prefixLength) {
148
            return substr($this->path, $this->prefixLength);
149
        }
150
        return substr($this->path, $index + 1);
151
    }
152
 
153
    /**
154
     * Returns the pathname string of this abstract pathname's parent, or
155
     * null if this pathname does not name a parent directory.
156
     *
157
     * The parent of an abstract pathname consists of the pathname's prefix,
158
     * if any, and each name in the pathname's name sequence except for the last.
159
     * If the name sequence is empty then the pathname does not name a parent
160
     * directory.
161
     *
162
     * @return  The pathname string of the parent directory named by this
163
     *          abstract pathname, or null if this pathname does not name a parent
164
     */
165
    function getParent() {
166
        // that's a lastIndexOf
167
        $index = ((($res = strrpos($this->path, self::$separator)) === false) ? -1 : $res);
168
        if ($index < $this->prefixLength) {
169
            if (($this->prefixLength > 0) && (strlen($this->path > $this->prefixLength))) {
170
                return substr($this->path, 0, $this->prefixLength);
171
            }
172
            return null;
173
        }
174
        return substr($this->path, 0, $index);
175
    }
176
 
177
    /**
178
     * Returns the abstract pathname of this abstract pathname's parent,
179
     * or null if this pathname does not name a parent directory.
180
     *
181
     * The parent of an abstract pathname consists of the pathname's prefix,
182
     * if any, and each name in the pathname's name sequence except for the
183
     * last.  If the name sequence is empty then the pathname does not name
184
     * a parent directory.
185
     *
186
     * @return  The abstract pathname of the parent directory named by this
187
     *          abstract pathname, or null if this pathname
188
     *          does not name a parent
189
     */
190
    function getParentFile() {
191
        $p = $this->getParent();
192
        if ($p === null) {
193
            return null;
194
        }
195
        return new PhingFile((string) $p, (int) $this->prefixLength);
196
    }
197
 
198
    /**
199
     * Converts this abstract pathname into a pathname string.  The resulting
200
     * string uses the default name-separator character to separate the names
201
     * in the name sequence.
202
     *
203
     * @return  The string form of this abstract pathname
204
     */
205
    function getPath() {
206
        return (string) $this->path;
207
    }
208
 
209
    /**
210
     * Tests whether this abstract pathname is absolute.  The definition of
211
     * absolute pathname is system dependent.  On UNIX systems, a pathname is
212
     * absolute if its prefix is "/".  On Win32 systems, a pathname is absolute
213
     * if its prefix is a drive specifier followed by "\\", or if its prefix
214
     * is "\\".
215
     *
216
     * @return  true if this abstract pathname is absolute, false otherwise
217
     */
218
    function isAbsolute() {
219
        return ($this->prefixLength !== 0);
220
    }
221
 
222
 
223
    /**
224
     * Returns the absolute pathname string of this abstract pathname.
225
     *
226
     * If this abstract pathname is already absolute, then the pathname
227
     * string is simply returned as if by the getPath method.
228
     * If this abstract pathname is the empty abstract pathname then
229
     * the pathname string of the current user directory, which is named by the
230
     * system property user.dir, is returned.  Otherwise this
231
     * pathname is resolved in a system-dependent way.  On UNIX systems, a
232
     * relative pathname is made absolute by resolving it against the current
233
     * user directory.  On Win32 systems, a relative pathname is made absolute
234
     * by resolving it against the current directory of the drive named by the
235
     * pathname, if any; if not, it is resolved against the current user
236
     * directory.
237
     *
238
     * @return  The absolute pathname string denoting the same file or
239
     *          directory as this abstract pathname
240
     * @see     #isAbsolute()
241
     */
242
    function getAbsolutePath() {
243
        $fs = FileSystem::getFileSystem();
244
        return $fs->resolveFile($this);
245
    }
246
 
247
    /**
248
     * Returns the absolute form of this abstract pathname.  Equivalent to
249
     * getAbsolutePath.
250
     *
251
     * @return  The absolute abstract pathname denoting the same file or
252
     *          directory as this abstract pathname
253
     */
254
    function getAbsoluteFile() {
255
        return new PhingFile((string) $this->getAbsolutePath());
256
    }
257
 
258
 
259
    /**
260
     * Returns the canonical pathname string of this abstract pathname.
261
     *
262
     * A canonical pathname is both absolute and unique. The precise
263
     * definition of canonical form is system-dependent. This method first
264
     * converts this pathname to absolute form if necessary, as if by invoking the
265
     * getAbsolutePath() method, and then maps it to its unique form in a
266
     * system-dependent way.  This typically involves removing redundant names
267
     * such as "." and .. from the pathname, resolving symbolic links
268
     * (on UNIX platforms), and converting drive letters to a standard case
269
     * (on Win32 platforms).
270
     *
271
     * Every pathname that denotes an existing file or directory has a
272
     * unique canonical form.  Every pathname that denotes a nonexistent file
273
     * or directory also has a unique canonical form.  The canonical form of
274
     * the pathname of a nonexistent file or directory may be different from
275
     * the canonical form of the same pathname after the file or directory is
276
     * created.  Similarly, the canonical form of the pathname of an existing
277
     * file or directory may be different from the canonical form of the same
278
     * pathname after the file or directory is deleted.
279
     *
280
     * @return  The canonical pathname string denoting the same file or
281
     *          directory as this abstract pathname
282
     */
283
    function getCanonicalPath() {
284
        $fs = FileSystem::getFileSystem();
285
        return $fs->canonicalize($this->path);
286
    }
287
 
288
 
289
    /**
290
     * Returns the canonical form of this abstract pathname.  Equivalent to
291
     * getCanonicalPath(.
292
     *
293
     * @return  PhingFile The canonical pathname string denoting the same file or
294
     *          directory as this abstract pathname
295
     */
296
    function getCanonicalFile() {
297
        return new PhingFile($this->getCanonicalPath());
298
    }
299
 
300
    /**
301
     * Converts this abstract pathname into a file: URL.  The
302
     * exact form of the URL is system-dependent.  If it can be determined that
303
     * the file denoted by this abstract pathname is a directory, then the
304
     * resulting URL will end with a slash.
305
     *
306
     * Usage note: This method does not automatically escape
307
     * characters that are illegal in URLs.  It is recommended that new code
308
     * convert an abstract pathname into a URL by first converting it into a
309
     * URI, via the toURI() method, and then converting the URI
310
     * into a URL via the URI::toURL()
311
     *
312
     * @return  A URL object representing the equivalent file URL
313
     *
314
     *
315
     */
316
    function toURL() {
317
        /*
318
        // URL class not implemented yet
319
        return new URL("file", "", $this->_slashify($this->getAbsolutePath(), $this->isDirectory()));
320
        */
321
    }
322
 
323
    /**
324
     * Constructs a file: URI that represents this abstract pathname.
325
     * Not implemented yet
326
     */
327
    function toURI() {
328
        /*
329
        $f = $this->getAbsoluteFile();
330
           $sp = (string) $this->slashify($f->getPath(), $f->isDirectory());
331
           if (StringHelper::startsWith('//', $sp))
332
        $sp = '//' + sp;
333
           return new URI('file', null, $sp, null);
334
        */
335
    }
336
 
337
    function _slashify($path, $isDirectory) {
338
        $p = (string) $path;
339
 
340
        if (self::$separator !== '/') {
341
            $p = str_replace(self::$separator, '/', $p);
342
        }
343
 
344
        if (!StringHelper::startsWith('/', $p)) {
345
            $p = '/'.$p;
346
        }
347
 
348
        if (!StringHelper::endsWith('/', $p) && $isDirectory) {
349
            $p = $p.'/';
350
        }
351
 
352
        return $p;
353
    }
354
 
355
    /* -- Attribute accessors -- */
356
 
357
    /**
358
     * Tests whether the application can read the file denoted by this
359
     * abstract pathname.
360
     *
361
     * @return  true if and only if the file specified by this
362
     *          abstract pathname exists and can be read by the
363
     *          application; false otherwise
364
     */
365
    function canRead() {
366
        $fs = FileSystem::getFileSystem();
367
 
368
        if ($fs->checkAccess($this)) {
369
            return (boolean) @is_readable($this->getAbsolutePath());
370
        }
371
        return false;
372
    }
373
 
374
    /**
375
     * Tests whether the application can modify to the file denoted by this
376
     * abstract pathname.
377
     *
378
     * @return  true if and only if the file system actually
379
     *          contains a file denoted by this abstract pathname and
380
     *          the application is allowed to write to the file;
381
     *          false otherwise.
382
     *
383
     */
384
    function canWrite() {
385
        $fs = FileSystem::getFileSystem();
386
        return $fs->checkAccess($this, true);
387
    }
388
 
389
    /**
390
     * Tests whether the file denoted by this abstract pathname exists.
391
     *
392
     * @return  true if and only if the file denoted by this
393
     *          abstract pathname exists; false otherwise
394
     *
395
     */
396
    function exists() {
397
		clearstatcache();
398
        if ($this->isFile()) {
399
            return @file_exists($this->path);
400
        } else {
401
            return @is_dir($this->path);
402
        }
403
    }
404
 
405
    /**
406
     * Tests whether the file denoted by this abstract pathname is a
407
     * directory.
408
     *
409
     * @return true if and only if the file denoted by this
410
     *         abstract pathname exists and is a directory;
411
     *         false otherwise
412
     *
413
     */
414
    function isDirectory() {
415
		clearstatcache();
416
        $fs = FileSystem::getFileSystem();
417
        if ($fs->checkAccess($this) !== true) {
418
            throw new IOException("No read access to ".$this->path);
419
        }
420
        return @is_dir($this->path);
421
    }
422
 
423
    /**
424
     * Tests whether the file denoted by this abstract pathname is a normal
425
     * file.  A file is normal if it is not a directory and, in
426
     * addition, satisfies other system-dependent criteria.  Any non-directory
427
     * file created by a Java application is guaranteed to be a normal file.
428
     *
429
     * @return  true if and only if the file denoted by this
430
     *          abstract pathname exists and is a normal file;
431
     *          false otherwise
432
     */
433
    function isFile() {
434
		clearstatcache();
435
        //$fs = FileSystem::getFileSystem();
436
        return @is_file($this->path);
437
    }
438
 
439
    /**
440
     * Tests whether the file named by this abstract pathname is a hidden
441
     * file.  The exact definition of hidden is system-dependent.  On
442
     * UNIX systems, a file is considered to be hidden if its name begins with
443
     * a period character ('.').  On Win32 systems, a file is considered to be
444
     * hidden if it has been marked as such in the filesystem. Currently there
445
     * seems to be no way to dermine isHidden on Win file systems via PHP
446
     *
447
     * @return  true if and only if the file denoted by this
448
     *          abstract pathname is hidden according to the conventions of the
449
     *          underlying platform
450
     */
451
    function isHidden() {
452
        $fs = FileSystem::getFileSystem();
453
        if ($fs->checkAccess($this) !== true) {
454
            throw new IOException("No read access to ".$this->path);
455
        }
456
        return (($fs->getBooleanAttributes($this) & $fs->BA_HIDDEN) !== 0);
457
    }
458
 
459
    /**
460
     * Returns the time that the file denoted by this abstract pathname was
461
     * last modified.
462
     *
463
     * @return  A integer value representing the time the file was
464
     *          last modified, measured in milliseconds since the epoch
465
     *          (00:00:00 GMT, January 1, 1970), or 0 if the
466
     *          file does not exist or if an I/O error occurs
467
     */
468
    function lastModified() {
469
        $fs = FileSystem::getFileSystem();
470
        if ($fs->checkAccess($this) !== true) {
471
            throw new IOException("No read access to " . $this->path);
472
        }
473
        return $fs->getLastModifiedTime($this);
474
    }
475
 
476
    /**
477
     * Returns the length of the file denoted by this abstract pathname.
478
     * The return value is unspecified if this pathname denotes a directory.
479
     *
480
     * @return  The length, in bytes, of the file denoted by this abstract
481
     *          pathname, or 0 if the file does not exist
482
     */
483
    function length() {
484
        $fs = FileSystem::getFileSystem();
485
        if ($fs->checkAccess($this) !== true) {
486
            throw new IOException("No read access to ".$this->path."\n");
487
        }
488
        return $fs->getLength($this);
489
    }
490
 
491
    /**
492
     * Convenience method for returning the contents of this file as a string.
493
     * This method uses file_get_contents() to read file in an optimized way.
494
     * @return string
495
     * @throws Exception - if file cannot be read
496
     */
497
    function contents() {
498
        if (!$this->canRead() || !$this->isFile()) {
499
            throw new IOException("Cannot read file contents!");
500
        }
501
        return file_get_contents($this->getAbsolutePath());
502
    }
503
 
504
    /* -- File operations -- */
505
 
506
    /**
507
     * Atomically creates a new, empty file named by this abstract pathname if
508
     * and only if a file with this name does not yet exist.  The check for the
509
     * existence of the file and the creation of the file if it does not exist
510
     * are a single operation that is atomic with respect to all other
511
     * filesystem activities that might affect the file.
512
     *
513
     * @return  true if the named file does not exist and was
514
     *          successfully created; <code>false</code> if the named file
515
     *          already exists
516
     * @throws IOException if file can't be created
517
     */
518
    function createNewFile($parents=true, $mode=0777) {
519
        $file = FileSystem::getFileSystem()->createNewFile($this->path);
520
        return $file;
521
    }
522
 
523
    /**
524
     * Deletes the file or directory denoted by this abstract pathname.  If
525
     * this pathname denotes a directory, then the directory must be empty in
526
     * order to be deleted.
527
     *
528
     * @return  true if and only if the file or directory is
529
     *          successfully deleted; false otherwise
530
     */
531
    function delete() {
532
        $fs = FileSystem::getFileSystem();
533
        if ($fs->canDelete($this) !== true) {
534
            throw new IOException("Cannot delete " . $this->path . "\n");
535
        }
536
        return $fs->delete($this);
537
    }
538
 
539
    /**
540
     * Requests that the file or directory denoted by this abstract pathname
541
     * be deleted when php terminates.  Deletion will be attempted only for
542
     * normal termination of php and if and if only Phing::shutdown() is
543
     * called.
544
     *
545
     * Once deletion has been requested, it is not possible to cancel the
546
     * request.  This method should therefore be used with care.
547
     *
548
     */
549
    function deleteOnExit() {
550
        $fs = FileSystem::getFileSystem();
551
        $fs->deleteOnExit($this);
552
    }
553
 
554
    /**
555
     * Returns an array of strings naming the files and directories in the
556
     * directory denoted by this abstract pathname.
557
     *
558
     * If this abstract pathname does not denote a directory, then this
559
     * method returns null  Otherwise an array of strings is
560
     * returned, one for each file or directory in the directory.  Names
561
     * denoting the directory itself and the directory's parent directory are
562
     * not included in the result.  Each string is a file name rather than a
563
     * complete path.
564
     *
565
     * There is no guarantee that the name strings in the resulting array
566
     * will appear in any specific order; they are not, in particular,
567
     * guaranteed to appear in alphabetical order.
568
     *
569
     * @return  An array of strings naming the files and directories in the
570
     *          directory denoted by this abstract pathname.  The array will be
571
     *          empty if the directory is empty.  Returns null if
572
     *          this abstract pathname does not denote a directory, or if an
573
     *          I/O error occurs.
574
     *
575
     */
576
    function listDir($filter = null) {
577
        $fs = FileSystem::getFileSystem();
578
        return $fs->lister($this, $filter);
579
    }
580
 
581
    function listFiles($filter = null) {
582
        $ss = $this->listDir($filter);
583
        if ($ss === null) {
584
            return null;
585
        }
586
        $n = count($ss);
587
        $fs = array();
588
        for ($i = 0; $i < $n; $i++) {
589
            $fs[$i] = new PhingFile((string)$this->path, (string)$ss[$i]);
590
        }
591
        return $fs;
592
    }
593
 
594
    /**
595
     * Creates the directory named by this abstract pathname, including any
596
     * necessary but nonexistent parent directories.  Note that if this
597
     * operation fails it may have succeeded in creating some of the necessary
598
     * parent directories.
599
     *
600
     * @return  true if and only if the directory was created,
601
     *          along with all necessary parent directories; false
602
     *          otherwise
603
     * @throws  IOException
604
     */
605
    function mkdirs() {
606
        if ($this->exists()) {
607
            return false;
608
        }
609
		try {
610
			if ($this->mkdir()) {
611
	            return true;
612
	        }
613
		} catch (IOException $ioe) {
614
			// IOException from mkdir() means that directory propbably didn't exist.
615
		}
616
        $parentFile = $this->getParentFile();
617
        return (($parentFile !== null) && ($parentFile->mkdirs() && $this->mkdir()));
618
    }
619
 
620
    /**
621
     * Creates the directory named by this abstract pathname.
622
     *
623
     * @return  true if and only if the directory was created; false otherwise
624
     * @throws  IOException
625
     */
626
    function mkdir() {
627
        $fs = FileSystem::getFileSystem();
628
 
629
        if ($fs->checkAccess(new PhingFile($this->path), true) !== true) {
630
            throw new IOException("No write access to " . $this->getPath());
631
        }
632
        return $fs->createDirectory($this);
633
    }
634
 
635
    /**
636
     * Renames the file denoted by this abstract pathname.
637
     *
638
     * @param   destFile  The new abstract pathname for the named file
639
     * @return  true if and only if the renaming succeeded; false otherwise
640
     */
641
    function renameTo(PhingFile $destFile) {
642
        $fs = FileSystem::getFileSystem();
643
        if ($fs->checkAccess($this) !== true) {
644
            throw new IOException("No write access to ".$this->getPath());
645
        }
646
        return $fs->rename($this, $destFile);
647
    }
648
 
649
    /**
650
     * Simple-copies file denoted by this abstract pathname into another
651
     * PhingFile
652
     *
653
     * @param PhingFile $destFile  The new abstract pathname for the named file
654
     * @return true if and only if the renaming succeeded; false otherwise
655
     */
656
    function copyTo(PhingFile $destFile) {
657
        $fs = FileSystem::getFileSystem();
658
 
659
        if ($fs->checkAccess($this) !== true) {
660
            throw new IOException("No read access to ".$this->getPath()."\n");
661
        }
662
 
663
        if ($fs->checkAccess($destFile, true) !== true) {
664
            throw new IOException("File::copyTo() No write access to ".$destFile->getPath());
665
        }
666
        return $fs->copy($this, $destFile);
667
    }
668
 
669
    /**
670
     * Sets the last-modified time of the file or directory named by this
671
     * abstract pathname.
672
     *
673
     * All platforms support file-modification times to the nearest second,
674
     * but some provide more precision.  The argument will be truncated to fit
675
     * the supported precision.  If the operation succeeds and no intervening
676
     * operations on the file take place, then the next invocation of the
677
     * lastModified method will return the (possibly truncated) time argument
678
     * that was passed to this method.
679
     *
680
     * @param  time  The new last-modified time, measured in milliseconds since
681
     *               the epoch (00:00:00 GMT, January 1, 1970)
682
     * @return true if and only if the operation succeeded; false otherwise
683
     */
684
    function setLastModified($time) {
685
        $time = (int) $time;
686
        if ($time < 0) {
687
            throw new Exception("IllegalArgumentException, Negative $time\n");
688
        }
689
 
690
        $fs = FileSystem::getFileSystem();
691
        return $fs->setLastModifiedTime($this, $time);
692
    }
693
 
694
    /**
695
     * Marks the file or directory named by this abstract pathname so that
696
     * only read operations are allowed.  After invoking this method the file
697
     * or directory is guaranteed not to change until it is either deleted or
698
     * marked to allow write access.  Whether or not a read-only file or
699
     * directory may be deleted depends upon the underlying system.
700
     *
701
     * @return true if and only if the operation succeeded; false otherwise
702
     */
703
    function setReadOnly() {
704
        $fs = FileSystem::getFileSystem();
705
        if ($fs->checkAccess($this, true) !== true) {
706
            // Error, no write access
707
            throw new IOException("No write access to " . $this->getPath());
708
        }
709
        return $fs->setReadOnly($this);
710
    }
711
 
712
	/**
713
	 * Sets the owner of the file.
714
	 * @param mixed $user User name or number.
715
	 */
716
	public function setUser($user) {
717
		$fs = FileSystem::getFileSystem();
718
		return $fs->chown($this->getPath(), $user);
719
    }
720
 
721
	/**
722
     * Retrieve the owner of this file.
723
     * @return int User ID of the owner of this file.
724
     */
725
    function getUser() {
726
        return @fileowner($this->getPath());
727
    }
728
 
729
    /**
730
     * Sets the mode of the file
731
     * @param int $mode Ocatal mode.
732
     */
733
    function setMode($mode) {
734
        $fs = FileSystem::getFileSystem();
735
        return $fs->chmod($this->getPath(), $mode);
736
    }
737
 
738
    /**
739
     * Retrieve the mode of this file.
740
     * @return int
741
     */
742
    function getMode() {
743
        return @fileperms($this->getPath());
744
    }
745
 
746
    /* -- Filesystem interface -- */
747
 
748
    /**
749
     * List the available filesystem roots.
750
     *
751
     * A particular platform may support zero or more hierarchically-organized
752
     * file systems.  Each file system has a root  directory from which all
753
     * other files in that file system can be reached.
754
     * Windows platforms, for example, have a root directory for each active
755
     * drive; UNIX platforms have a single root directory, namely "/".
756
     * The set of available filesystem roots is affected by various system-level
757
     * operations such the insertion or ejection of removable media and the
758
     * disconnecting or unmounting of physical or virtual disk drives.
759
     *
760
     * This method returns an array of PhingFile objects that
761
     * denote the root directories of the available filesystem roots.  It is
762
     * guaranteed that the canonical pathname of any file physically present on
763
     * the local machine will begin with one of the roots returned by this
764
     * method.
765
     *
766
     * The canonical pathname of a file that resides on some other machine
767
     * and is accessed via a remote-filesystem protocol such as SMB or NFS may
768
     * or may not begin with one of the roots returned by this method.  If the
769
     * pathname of a remote file is syntactically indistinguishable from the
770
     * pathname of a local file then it will begin with one of the roots
771
     * returned by this method.  Thus, for example, PhingFile objects
772
     * denoting the root directories of the mapped network drives of a Windows
773
     * platform will be returned by this method, while PhingFile
774
     * objects containing UNC pathnames will not be returned by this method.
775
     *
776
     * @return  An array of PhingFile objects denoting the available
777
     *          filesystem roots, or null if the set of roots
778
     *          could not be determined.  The array will be empty if there are
779
     *          no filesystem roots.
780
     */
781
    function listRoots() {
782
        $fs = FileSystem::getFileSystem();
783
        return (array) $fs->listRoots();
784
    }
785
 
786
    /* -- Tempfile management -- */
787
 
788
    /**
789
     * Returns the path to the temp directory.
790
     */
791
    function getTempDir() {
792
        return Phing::getProperty('php.tmpdir');
793
    }
794
 
795
    /**
796
     * Static method that creates a unique filename whose name begins with
797
     * $prefix and ends with $suffix in the directory $directory. $directory
798
     * is a reference to a PhingFile Object.
799
     * Then, the file is locked for exclusive reading/writing.
800
     *
801
     * @author      manuel holtgrewe, grin@gmx.net
802
     * @throws      IOException
803
     * @access      public
804
     */
805
    function createTempFile($prefix, $suffix, PhingFile $directory) {
806
 
807
        // quick but efficient hack to create a unique filename ;-)
808
        $result = null;
809
        do {
810
            $result = new PhingFile($directory, $prefix . substr(md5(time()), 0, 8) . $suffix);
811
        } while (file_exists($result->getPath()));
812
 
813
        $fs = FileSystem::getFileSystem();
814
        $fs->createNewFile($result->getPath());
815
        $fs->lock($result);
816
 
817
        return $result;
818
    }
819
 
820
    /**
821
     * If necessary, $File the lock on $File is removed and then the file is
822
     * deleted
823
     *
824
     * @access      public
825
     */
826
    function removeTempFile() {
827
        $fs = FileSystem::getFileSystem();
828
        // catch IO Exception
829
        $fs->unlock($this);
830
        $this->delete();
831
    }
832
 
833
 
834
    /* -- Basic infrastructure -- */
835
 
836
    /**
837
     * Compares two abstract pathnames lexicographically.  The ordering
838
     * defined by this method depends upon the underlying system.  On UNIX
839
     * systems, alphabetic case is significant in comparing pathnames; on Win32
840
     * systems it is not.
841
     *
842
     * @param PhingFile $file Th file whose pathname sould be compared to the pathname of this file.
843
     *
844
     * @return int Zero if the argument is equal to this abstract pathname, a
845
     *        value less than zero if this abstract pathname is
846
     *        lexicographically less than the argument, or a value greater
847
     *        than zero if this abstract pathname is lexicographically
848
     *        greater than the argument
849
     */
850
    function compareTo(PhingFile $file) {
851
        $fs = FileSystem::getFileSystem();
852
        return $fs->compare($this, $file);
853
    }
854
 
855
    /**
856
     * Tests this abstract pathname for equality with the given object.
857
     * Returns <code>true</code> if and only if the argument is not
858
     * <code>null</code> and is an abstract pathname that denotes the same file
859
     * or directory as this abstract pathname.  Whether or not two abstract
860
     * pathnames are equal depends upon the underlying system.  On UNIX
861
     * systems, alphabetic case is significant in comparing pathnames; on Win32
862
     * systems it is not.
863
     * @return boolean
864
     */
865
    function equals($obj) {
866
        if (($obj !== null) && ($obj instanceof PhingFile)) {
867
            return ($this->compareTo($obj) === 0);
868
        }
869
        return false;
870
    }
871
 
872
    /** Backwards compatibility -- use PHP5's native __tostring method. */
873
    function toString() {
874
        return $this->getPath();
875
    }
876
 
877
    /** PHP5's native method. */
878
    function __toString() {
879
        return $this->getPath();
880
    }
881
}
882