source: Dev/branches/cakephp/cake/libs/file.php @ 126

Last change on this file since 126 was 126, checked in by fpvanagthoven, 14 years ago

Cakephp branch.

File size: 11.4 KB
Line 
1<?php
2/**
3 * Convenience class for reading, writing and appending to files.
4 *
5 * PHP versions 4 and 5
6 *
7 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
8 * Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
9 *
10 * Licensed under The MIT License
11 * Redistributions of files must retain the above copyright notice.
12 *
13 * @copyright     Copyright 2005-2011, Cake Software Foundation, Inc. (http://cakefoundation.org)
14 * @link          http://cakephp.org CakePHP(tm) Project
15 * @package       cake
16 * @subpackage    cake.cake.libs
17 * @since         CakePHP(tm) v 0.2.9
18 * @license       MIT License (http://www.opensource.org/licenses/mit-license.php)
19 */
20
21/**
22 * Included libraries.
23 *
24 */
25if (!class_exists('Object')) {
26        require LIBS . 'object.php';
27}
28if (!class_exists('Folder')) {
29        require LIBS . 'folder.php';
30}
31
32/**
33 * Convenience class for reading, writing and appending to files.
34 *
35 * @package       cake
36 * @subpackage    cake.cake.libs
37 */
38class File extends Object {
39
40/**
41 * Folder object of the File
42 *
43 * @var Folder
44 * @access public
45 */
46        var $Folder = null;
47
48/**
49 * Filename
50 *
51 * @var string
52 * @access public
53 */
54        var $name = null;
55
56/**
57 * file info
58 *
59 * @var string
60 * @access public
61 */
62        var $info = array();
63
64/**
65 * Holds the file handler resource if the file is opened
66 *
67 * @var resource
68 * @access public
69 */
70        var $handle = null;
71
72/**
73 * enable locking for file reading and writing
74 *
75 * @var boolean
76 * @access public
77 */
78        var $lock = null;
79
80/**
81 * path property
82 *
83 * Current file's absolute path
84 *
85 * @var mixed null
86 * @access public
87 */
88        var $path = null;
89
90/**
91 * Constructor
92 *
93 * @param string $path Path to file
94 * @param boolean $create Create file if it does not exist (if true)
95 * @param integer $mode Mode to apply to the folder holding the file
96 */
97        function __construct($path, $create = false, $mode = 0755) {
98                parent::__construct();
99                $this->Folder =& new Folder(dirname($path), $create, $mode);
100                if (!is_dir($path)) {
101                        $this->name = basename($path);
102                }
103                $this->pwd();
104                $create && !$this->exists() && $this->safe($path) && $this->create();
105        }
106
107/**
108 * Closes the current file if it is opened
109 *
110 */
111        function __destruct() {
112                $this->close();
113        }
114
115/**
116 * Creates the File.
117 *
118 * @return boolean Success
119 * @access public
120 */
121        function create() {
122                $dir = $this->Folder->pwd();
123                if (is_dir($dir) && is_writable($dir) && !$this->exists()) {
124                        $old = umask(0);
125                        if (touch($this->path)) {
126                                umask($old);
127                                return true;
128                        }
129                }
130                return false;
131        }
132
133/**
134 * Opens the current file with a given $mode
135 *
136 * @param string $mode A valid 'fopen' mode string (r|w|a ...)
137 * @param boolean $force If true then the file will be re-opened even if its already opened, otherwise it won't
138 * @return boolean True on success, false on failure
139 * @access public
140 */
141        function open($mode = 'r', $force = false) {
142                if (!$force && is_resource($this->handle)) {
143                        return true;
144                }
145                clearstatcache();
146                if ($this->exists() === false) {
147                        if ($this->create() === false) {
148                                return false;
149                        }
150                }
151
152                $this->handle = fopen($this->path, $mode);
153                if (is_resource($this->handle)) {
154                        return true;
155                }
156                return false;
157        }
158
159/**
160 * Return the contents of this File as a string.
161 *
162 * @param string $bytes where to start
163 * @param string $mode A `fread` compatible mode.
164 * @param boolean $force If true then the file will be re-opened even if its already opened, otherwise it won't
165 * @return mixed string on success, false on failure
166 * @access public
167 */
168        function read($bytes = false, $mode = 'rb', $force = false) {
169                if ($bytes === false && $this->lock === null) {
170                        return file_get_contents($this->path);
171                }
172                if ($this->open($mode, $force) === false) {
173                        return false;
174                }
175                if ($this->lock !== null && flock($this->handle, LOCK_SH) === false) {
176                        return false;
177                }
178                if (is_int($bytes)) {
179                        return fread($this->handle, $bytes);
180                }
181
182                $data = '';
183                while (!feof($this->handle)) {
184                        $data .= fgets($this->handle, 4096);
185                }
186
187                if ($this->lock !== null) {
188                        flock($this->handle, LOCK_UN);
189                }
190                if ($bytes === false) {
191                        $this->close();
192                }
193                return trim($data);
194        }
195
196/**
197 * Sets or gets the offset for the currently opened file.
198 *
199 * @param mixed $offset The $offset in bytes to seek. If set to false then the current offset is returned.
200 * @param integer $seek PHP Constant SEEK_SET | SEEK_CUR | SEEK_END determining what the $offset is relative to
201 * @return mixed True on success, false on failure (set mode), false on failure or integer offset on success (get mode)
202 * @access public
203 */
204        function offset($offset = false, $seek = SEEK_SET) {
205                if ($offset === false) {
206                        if (is_resource($this->handle)) {
207                                return ftell($this->handle);
208                        }
209                } elseif ($this->open() === true) {
210                        return fseek($this->handle, $offset, $seek) === 0;
211                }
212                return false;
213        }
214
215/**
216 * Prepares a ascii string for writing.  Converts line endings to the
217 * correct terminator for the current platform.  If windows "\r\n" will be used
218 * all other platforms will use "\n"
219 *
220 * @param string $data Data to prepare for writing.
221 * @return string The with converted line endings.
222 * @access public
223 */
224        function prepare($data, $forceWindows = false) {
225                $lineBreak = "\n";
226                if (DIRECTORY_SEPARATOR == '\\' || $forceWindows === true) {
227                        $lineBreak = "\r\n";
228                }
229                return strtr($data, array("\r\n" => $lineBreak, "\n" => $lineBreak, "\r" => $lineBreak));
230        }
231
232/**
233 * Write given data to this File.
234 *
235 * @param string $data Data to write to this File.
236 * @param string $mode Mode of writing. {@link http://php.net/fwrite See fwrite()}.
237 * @param string $force force the file to open
238 * @return boolean Success
239 * @access public
240 */
241        function write($data, $mode = 'w', $force = false) {
242                $success = false;
243                if ($this->open($mode, $force) === true) {
244                        if ($this->lock !== null) {
245                                if (flock($this->handle, LOCK_EX) === false) {
246                                        return false;
247                                }
248                        }
249
250                        if (fwrite($this->handle, $data) !== false) {
251                                $success = true;
252                        }
253                        if ($this->lock !== null) {
254                                flock($this->handle, LOCK_UN);
255                        }
256                }
257                return $success;
258        }
259
260/**
261 * Append given data string to this File.
262 *
263 * @param string $data Data to write
264 * @param string $force force the file to open
265 * @return boolean Success
266 * @access public
267 */
268        function append($data, $force = false) {
269                return $this->write($data, 'a', $force);
270        }
271
272/**
273 * Closes the current file if it is opened.
274 *
275 * @return boolean True if closing was successful or file was already closed, otherwise false
276 * @access public
277 */
278        function close() {
279                if (!is_resource($this->handle)) {
280                        return true;
281                }
282                return fclose($this->handle);
283        }
284
285/**
286 * Deletes the File.
287 *
288 * @return boolean Success
289 * @access public
290 */
291        function delete() {
292                clearstatcache();
293                if (is_resource($this->handle)) {
294                        fclose($this->handle);
295                        $this->handle = null;
296                }
297                if ($this->exists()) {
298                        return unlink($this->path);
299                }
300                return false;
301        }
302
303/**
304 * Returns the File info.
305 *
306 * @return string The File extension
307 * @access public
308 */
309        function info() {
310                if ($this->info == null) {
311                        $this->info = pathinfo($this->path);
312                }
313                if (!isset($this->info['filename'])) {
314                        $this->info['filename'] = $this->name();
315                }
316                return $this->info;
317        }
318
319/**
320 * Returns the File extension.
321 *
322 * @return string The File extension
323 * @access public
324 */
325        function ext() {
326                if ($this->info == null) {
327                        $this->info();
328                }
329                if (isset($this->info['extension'])) {
330                        return $this->info['extension'];
331                }
332                return false;
333        }
334
335/**
336 * Returns the File name without extension.
337 *
338 * @return string The File name without extension.
339 * @access public
340 */
341        function name() {
342                if ($this->info == null) {
343                        $this->info();
344                }
345                if (isset($this->info['extension'])) {
346                        return basename($this->name, '.'.$this->info['extension']);
347                } elseif ($this->name) {
348                        return $this->name;
349                }
350                return false;
351        }
352
353/**
354 * makes filename safe for saving
355 *
356 * @param string $name The name of the file to make safe if different from $this->name
357 * @param strin $ext The name of the extension to make safe if different from $this->ext
358 * @return string $ext the extension of the file
359 * @access public
360 */
361        function safe($name = null, $ext = null) {
362                if (!$name) {
363                        $name = $this->name;
364                }
365                if (!$ext) {
366                        $ext = $this->ext();
367                }
368                return preg_replace( "/(?:[^\w\.-]+)/", "_", basename($name, $ext));
369        }
370
371/**
372 * Get md5 Checksum of file with previous check of Filesize
373 *
374 * @param mixed $maxsize in MB or true to force
375 * @return string md5 Checksum {@link http://php.net/md5_file See md5_file()}
376 * @access public
377 */
378        function md5($maxsize = 5) {
379                if ($maxsize === true) {
380                        return md5_file($this->path);
381                }
382
383                $size = $this->size();
384                if ($size && $size < ($maxsize * 1024) * 1024) {
385                        return md5_file($this->path);
386                }
387
388                return false;
389        }
390
391/**
392 * Returns the full path of the File.
393 *
394 * @return string Full path to file
395 * @access public
396 */
397        function pwd() {
398                if (is_null($this->path)) {
399                        $this->path = $this->Folder->slashTerm($this->Folder->pwd()) . $this->name;
400                }
401                return $this->path;
402        }
403
404/**
405 * Returns true if the File exists.
406 *
407 * @return boolean true if it exists, false otherwise
408 * @access public
409 */
410        function exists() {
411                return (file_exists($this->path) && is_file($this->path));
412        }
413
414/**
415 * Returns the "chmod" (permissions) of the File.
416 *
417 * @return string Permissions for the file
418 * @access public
419 */
420        function perms() {
421                if ($this->exists()) {
422                        return substr(sprintf('%o', fileperms($this->path)), -4);
423                }
424                return false;
425        }
426
427/**
428 * Returns the Filesize
429 *
430 * @return integer size of the file in bytes, or false in case of an error
431 * @access public
432 */
433        function size() {
434                if ($this->exists()) {
435                        return filesize($this->path);
436                }
437                return false;
438        }
439
440/**
441 * Returns true if the File is writable.
442 *
443 * @return boolean true if its writable, false otherwise
444 * @access public
445 */
446        function writable() {
447                return is_writable($this->path);
448        }
449
450/**
451 * Returns true if the File is executable.
452 *
453 * @return boolean true if its executable, false otherwise
454 * @access public
455 */
456        function executable() {
457                return is_executable($this->path);
458        }
459
460/**
461 * Returns true if the File is readable.
462 *
463 * @return boolean true if file is readable, false otherwise
464 * @access public
465 */
466        function readable() {
467                return is_readable($this->path);
468        }
469
470/**
471 * Returns the File's owner.
472 *
473 * @return integer the Fileowner
474 * @access public
475 */
476        function owner() {
477                if ($this->exists()) {
478                        return fileowner($this->path);
479                }
480                return false;
481        }
482
483/**
484 * Returns the File's group.
485 *
486 * @return integer the Filegroup
487 * @access public
488 */
489        function group() {
490                if ($this->exists()) {
491                        return filegroup($this->path);
492                }
493                return false;
494        }
495
496/**
497 * Returns last access time.
498 *
499 * @return integer timestamp Timestamp of last access time
500 * @access public
501 */
502        function lastAccess() {
503                if ($this->exists()) {
504                        return fileatime($this->path);
505                }
506                return false;
507        }
508
509/**
510 * Returns last modified time.
511 *
512 * @return integer timestamp Timestamp of last modification
513 * @access public
514 */
515        function lastChange() {
516                if ($this->exists()) {
517                        return filemtime($this->path);
518                }
519                return false;
520        }
521
522/**
523 * Returns the current folder.
524 *
525 * @return Folder Current folder
526 * @access public
527 */
528        function &Folder() {
529                return $this->Folder;
530        }
531
532/**
533 * Copy the File to $dest
534 *
535 * @param string $dest destination for the copy
536 * @param boolean $overwrite Overwrite $dest if exists
537 * @return boolean Succes
538 * @access public
539 */
540        function copy($dest, $overwrite = true) {
541                if (!$this->exists() || is_file($dest) && !$overwrite) {
542                        return false;
543                }
544                return copy($this->path, $dest);
545        }
546}
Note: See TracBrowser for help on using the repository browser.