3 * Convenience class for reading, writing and appending to files.
7 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
8 * Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
10 * Licensed under The MIT License
11 * Redistributions of files must retain the above copyright notice.
13 * @copyright Copyright 2005-2010, Cake Software Foundation, Inc. (http://cakefoundation.org)
14 * @link http://cakephp.org CakePHP(tm) Project
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)
25 if (!class_exists('Object')) {
26 require LIBS
. 'object.php';
28 if (!class_exists('Folder')) {
29 require LIBS
. 'folder.php';
33 * Convenience class for reading, writing and appending to files.
36 * @subpackage cake.cake.libs
38 class File
extends Object {
41 * Folder object of the File
65 * Holds the file handler resource if the file is opened
73 * enable locking for file reading and writing
83 * Current file's absolute path
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
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);
104 $create && !$this->exists() && $this->safe($path) && $this->create();
108 * Closes the current file if it is opened
111 function __destruct() {
118 * @return boolean Success
122 $dir = $this->Folder
->pwd();
123 if (is_dir($dir) && is_writable($dir) && !$this->exists()) {
125 if (touch($this->path
)) {
134 * Opens the current file with a given $mode
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
141 function open($mode = 'r', $force = false) {
142 if (!$force && is_resource($this->handle
)) {
146 if ($this->exists() === false) {
147 if ($this->create() === false) {
152 $this->handle
= fopen($this->path
, $mode);
153 if (is_resource($this->handle
)) {
160 * Return the contents of this File as a string.
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
168 function read($bytes = false, $mode = 'rb', $force = false) {
169 if ($bytes === false && $this->lock
=== null) {
170 return file_get_contents($this->path
);
172 if ($this->open($mode, $force) === false) {
175 if ($this->lock
!== null && flock($this->handle
, LOCK_SH
) === false) {
178 if (is_int($bytes)) {
179 return fread($this->handle
, $bytes);
183 while (!feof($this->handle
)) {
184 $data .= fgets($this->handle
, 4096);
187 if ($this->lock
!== null) {
188 flock($this->handle
, LOCK_UN
);
190 if ($bytes === false) {
197 * Sets or gets the offset for the currently opened file.
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)
204 function offset($offset = false, $seek = SEEK_SET
) {
205 if ($offset === false) {
206 if (is_resource($this->handle
)) {
207 return ftell($this->handle
);
209 } elseif ($this->open() === true) {
210 return fseek($this->handle
, $offset, $seek) === 0;
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"
220 * @param string $data Data to prepare for writing.
221 * @return string The with converted line endings.
224 function prepare($data, $forceWindows = false) {
226 if (DIRECTORY_SEPARATOR
== '\\' ||
$forceWindows === true) {
229 return strtr($data, array("\r\n" => $lineBreak, "\n" => $lineBreak, "\r" => $lineBreak));
233 * Write given data to this File.
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
241 function write($data, $mode = 'w', $force = false) {
243 if ($this->open($mode, $force) === true) {
244 if ($this->lock
!== null) {
245 if (flock($this->handle
, LOCK_EX
) === false) {
250 if (fwrite($this->handle
, $data) !== false) {
253 if ($this->lock
!== null) {
254 flock($this->handle
, LOCK_UN
);
261 * Append given data string to this File.
263 * @param string $data Data to write
264 * @param string $force force the file to open
265 * @return boolean Success
268 function append($data, $force = false) {
269 return $this->write($data, 'a', $force);
273 * Closes the current file if it is opened.
275 * @return boolean True if closing was successful or file was already closed, otherwise false
279 if (!is_resource($this->handle
)) {
282 return fclose($this->handle
);
288 * @return boolean Success
293 if ($this->exists()) {
294 return unlink($this->path
);
300 * Returns the File info.
302 * @return string The File extension
306 if ($this->info
== null) {
307 $this->info
= pathinfo($this->path
);
309 if (!isset($this->info
['filename'])) {
310 $this->info
['filename'] = $this->name();
316 * Returns the File extension.
318 * @return string The File extension
322 if ($this->info
== null) {
325 if (isset($this->info
['extension'])) {
326 return $this->info
['extension'];
332 * Returns the File name without extension.
334 * @return string The File name without extension.
338 if ($this->info
== null) {
341 if (isset($this->info
['extension'])) {
342 return basename($this->name
, '.'.$this->info
['extension']);
343 } elseif ($this->name
) {
350 * makes filename safe for saving
352 * @param string $name The name of the file to make safe if different from $this->name
353 * @param strin $ext The name of the extension to make safe if different from $this->ext
354 * @return string $ext the extension of the file
357 function safe($name = null, $ext = null) {
364 return preg_replace( "/(?:[^\w\.-]+)/", "_", basename($name, $ext));
368 * Get md5 Checksum of file with previous check of Filesize
370 * @param mixed $maxsize in MB or true to force
371 * @return string md5 Checksum {@link http://php.net/md5_file See md5_file()}
374 function md5($maxsize = 5) {
375 if ($maxsize === true) {
376 return md5_file($this->path
);
379 $size = $this->size();
380 if ($size && $size < ($maxsize * 1024) * 1024) {
381 return md5_file($this->path
);
388 * Returns the full path of the File.
390 * @return string Full path to file
394 if (is_null($this->path
)) {
395 $this->path
= $this->Folder
->slashTerm($this->Folder
->pwd()) . $this->name
;
401 * Returns true if the File exists.
403 * @return boolean true if it exists, false otherwise
407 return (file_exists($this->path
) && is_file($this->path
));
411 * Returns the "chmod" (permissions) of the File.
413 * @return string Permissions for the file
417 if ($this->exists()) {
418 return substr(sprintf('%o', fileperms($this->path
)), -4);
424 * Returns the Filesize
426 * @return integer size of the file in bytes, or false in case of an error
430 if ($this->exists()) {
431 return filesize($this->path
);
437 * Returns true if the File is writable.
439 * @return boolean true if its writable, false otherwise
442 function writable() {
443 return is_writable($this->path
);
447 * Returns true if the File is executable.
449 * @return boolean true if its executable, false otherwise
452 function executable() {
453 return is_executable($this->path
);
457 * Returns true if the File is readable.
459 * @return boolean true if file is readable, false otherwise
462 function readable() {
463 return is_readable($this->path
);
467 * Returns the File's owner.
469 * @return integer the Fileowner
473 if ($this->exists()) {
474 return fileowner($this->path
);
480 * Returns the File's group.
482 * @return integer the Filegroup
486 if ($this->exists()) {
487 return filegroup($this->path
);
493 * Returns last access time.
495 * @return integer timestamp Timestamp of last access time
498 function lastAccess() {
499 if ($this->exists()) {
500 return fileatime($this->path
);
506 * Returns last modified time.
508 * @return integer timestamp Timestamp of last modification
511 function lastChange() {
512 if ($this->exists()) {
513 return filemtime($this->path
);
519 * Returns the current folder.
521 * @return Folder Current folder
525 return $this->Folder
;
529 * Copy the File to $dest
531 * @param string $dest destination for the copy
532 * @param boolean $overwrite Overwrite $dest if exists
533 * @return boolean Succes
536 function copy($dest, $overwrite = true) {
537 if (!$this->exists() ||
is_file($dest) && !$overwrite) {
540 return copy($this->path
, $dest);