file.php

Go to the documentation of this file.
00001 <?php
00002 /* SVN FILE: $Id: file_8php-source.html 580 2008-07-01 14:45:49Z gwoo $ */
00003 /**
00004  * Convenience class for reading, writing and appending to files.
00005  *
00006  * PHP versions 4 and 5
00007  *
00008  * CakePHP(tm) :  Rapid Development Framework <http://www.cakephp.org/>
00009  * Copyright 2005-2008, Cake Software Foundation, Inc.
00010  *                              1785 E. Sahara Avenue, Suite 490-204
00011  *                              Las Vegas, Nevada 89104
00012  *
00013  * Licensed under The MIT License
00014  * Redistributions of files must retain the above copyright notice.
00015  *
00016  * @filesource
00017  * @copyright       Copyright 2005-2008, Cake Software Foundation, Inc.
00018  * @link                http://www.cakefoundation.org/projects/info/cakephp CakePHP(tm) Project
00019  * @package         cake
00020  * @subpackage      cake.cake.libs
00021  * @since           CakePHP(tm) v 0.2.9
00022  * @version         $Revision: 580 $
00023  * @modifiedby      $LastChangedBy: gwoo $
00024  * @lastmodified    $Date: 2008-07-01 09:45:49 -0500 (Tue, 01 Jul 2008) $
00025  * @license         http://www.opensource.org/licenses/mit-license.php The MIT License
00026  */
00027 /**
00028  * Included libraries.
00029  *
00030  */
00031 if (!class_exists('Object')) {
00032     uses ('object');
00033 }
00034 
00035 if (!class_exists('Folder')) {
00036     uses('folder');
00037 }
00038 /**
00039  * Convenience class for reading, writing and appending to files.
00040  *
00041  * @package     cake
00042  * @subpackage  cake.cake.libs
00043  */
00044 class File extends Object {
00045 /**
00046  * Folder object of the File
00047  *
00048  * @var object
00049  * @access public
00050  */
00051     var $Folder = null;
00052 /**
00053  * Filename
00054  *
00055  * @var string
00056  * @access public
00057  */
00058     var $name = null;
00059 /**
00060  * file info
00061  *
00062  * @var string
00063  * @access public
00064  */
00065     var $info = array();
00066 /**
00067  * Holds the file handler resource if the file is opened
00068  *
00069  * @var resource
00070  * @access public
00071  */
00072     var $handle = null;
00073 /**
00074  * enable locking for file reading and writing
00075  *
00076  * @var boolean
00077  * @access public
00078  */
00079     var $lock = null;
00080 /**
00081  * Constructor
00082  *
00083  * @param string $path Path to file
00084  * @param boolean $create Create file if it does not exist (if true)
00085  * @param integer $mode Mode to apply to the folder holding the file
00086  * @access private
00087  */
00088     function __construct($path, $create = false, $mode = 0755) {
00089         parent::__construct();
00090         $this->Folder =& new Folder(dirname($path), $create, $mode);
00091         if (!is_dir($path)) {
00092             $this->name = basename($path);
00093         }
00094 
00095         if (!$this->exists()) {
00096             if ($create === true) {
00097                 if ($this->safe($path) && $this->create() === false) {
00098                     return false;
00099                 }
00100             } else {
00101                 return false;
00102             }
00103         }
00104     }
00105 /**
00106  * Closes the current file if it is opened
00107  *
00108  * @access private
00109  */
00110     function __destruct() {
00111         $this->close();
00112     }
00113 /**
00114  * Creates the File.
00115  *
00116  * @return boolean Success
00117  * @access public
00118  */
00119     function create() {
00120         $dir = $this->Folder->pwd();
00121         if (is_dir($dir) && is_writable($dir) && !$this->exists()) {
00122             if (touch($this->pwd())) {
00123                 return true;
00124             }
00125         }
00126         return false;
00127     }
00128 /**
00129  * Opens the current file with a given $mode
00130  *
00131  * @param string $mode A valid 'fopen' mode string (r|w|a ...)
00132  * @param boolean $force If true then the file will be re-opened even if its already opened, otherwise it won't
00133  * @return boolean True on success, false on failure
00134  * @access public
00135  */
00136     function open($mode = 'r', $force = false) {
00137         if (!$force && is_resource($this->handle)) {
00138             return true;
00139         }
00140         if ($this->exists() === false) {
00141             if ($this->create() === false) {
00142                 return false;
00143             }
00144         }
00145 
00146         $this->handle = fopen($this->pwd(), $mode);
00147         if (is_resource($this->handle)) {
00148             return true;
00149         }
00150         return false;
00151     }
00152 /**
00153  * Return the contents of this File as a string.
00154  *
00155  * @param string $bytes where to start
00156  * @param string $mode
00157  * @param boolean $force If true then the file will be re-opened even if its already opened, otherwise it won't
00158  * @return mixed string on success, false on failure
00159  * @access public
00160  */
00161     function read($bytes = false, $mode = 'rb', $force = false) {
00162         $success = false;
00163         if ($this->lock !== null) {
00164             if (flock($this->handle, LOCK_SH) === false) {
00165                 return false;
00166             }
00167         }
00168         if ($bytes === false) {
00169             $success = file_get_contents($this->pwd());
00170         } elseif ($this->open($mode, $force) === true) {
00171             if (is_int($bytes)) {
00172                 $success = fread($this->handle, $bytes);
00173             } else {
00174                 $data = '';
00175                 while (!feof($this->handle)) {
00176                     $data .= fgets($this->handle, 4096);
00177                 }
00178                 $success = trim($data);
00179             }
00180         }
00181         if ($this->lock !== null) {
00182             flock($this->handle, LOCK_UN);
00183         }
00184         return $success;
00185     }
00186 /**
00187  * Sets or gets the offset for the currently opened file.
00188  *
00189  * @param mixed $offset The $offset in bytes to seek. If set to false then the current offset is returned.
00190  * @param integer $seek PHP Constant SEEK_SET | SEEK_CUR | SEEK_END determining what the $offset is relative to
00191  * @return mixed True on success, false on failure (set mode), false on failure or integer offset on success (get mode)
00192  * @access public
00193  */
00194     function offset($offset = false, $seek = SEEK_SET) {
00195         if ($offset === false) {
00196             if (is_resource($this->handle)) {
00197                 return ftell($this->handle);
00198             }
00199         } elseif ($this->open() === true) {
00200             return fseek($this->handle, $offset, $seek) === 0;
00201         }
00202         return false;
00203     }
00204 /**
00205  * Prepares a ascii string for writing
00206  * fixes line endings
00207  *
00208  * @param string $data Data to prepare for writing.
00209  * @return string
00210  * @access public
00211  */
00212     function prepare($data, $forceWindows = false) {
00213         $lineBreak = "\n";
00214         if (substr(PHP_OS,0,3) == "WIN" || $forceWindows === true) {
00215             $lineBreak = "\r\n";
00216         }
00217         return strtr($data, array("\r\n" => $lineBreak, "\n" => $lineBreak, "\r" => $lineBreak));
00218     }
00219 
00220 /**
00221  * Write given data to this File.
00222  *
00223  * @param string $data  Data to write to this File.
00224  * @param string $mode  Mode of writing. {@link http://php.net/fwrite See fwrite()}.
00225  * @param string $force force the file to open
00226  * @return boolean Success
00227  * @access public
00228  */
00229     function write($data, $mode = 'w', $force = false) {
00230         $success = false;
00231         if ($this->open($mode, $force) === true) {
00232             if($this->lock !== null) {
00233                 if(flock($this->handle, LOCK_EX) === false) {
00234                     return false;
00235                 }
00236             }
00237 
00238             if (fwrite($this->handle, $data) !== false) {
00239                 $success = true;
00240             }
00241             if ($this->lock !== null) {
00242                 flock($this->handle, LOCK_UN);
00243             }
00244         }
00245         return $success;
00246     }
00247 /**
00248  * Append given data string to this File.
00249  *
00250  * @param string $data Data to write
00251  * @param string $force force the file to open
00252  * @return boolean Success
00253  * @access public
00254  */
00255     function append($data, $force = false) {
00256         return $this->write($data, 'a', $force);
00257     }
00258 /**
00259  * Closes the current file if it is opened.
00260  *
00261  * @return boolean True if closing was successful or file was already closed, otherwise false
00262  * @access public
00263  */
00264     function close() {
00265         if (!is_resource($this->handle)) {
00266             return true;
00267         }
00268         return fclose($this->handle);
00269     }
00270 /**
00271  * Deletes the File.
00272  *
00273  * @return boolean Success
00274  * @access public
00275  */
00276     function delete() {
00277         if ($this->exists()) {
00278             return unlink($this->pwd());
00279         }
00280         return false;
00281     }
00282 /**
00283  * Returns the File extension.
00284  *
00285  * @return string The File extension
00286  * @access public
00287  */
00288     function info() {
00289         if ($this->info == null) {
00290             $this->info = pathinfo($this->pwd());
00291         }
00292         if (!isset($this->info['filename'])) {
00293             $this->info['filename'] = $this->name();
00294         }
00295         return $this->info;
00296     }
00297 /**
00298  * Returns the File extension.
00299  *
00300  * @return string The File extension
00301  * @access public
00302  */
00303     function ext() {
00304         if ($this->info == null) {
00305             $this->info();
00306         }
00307         if (isset($this->info['extension'])) {
00308             return $this->info['extension'];
00309         }
00310         return false;
00311     }
00312 /**
00313  * Returns the File name without extension.
00314  *
00315  * @return string The File name without extension.
00316  * @access public
00317  */
00318     function name() {
00319         if ($this->info == null) {
00320             $this->info();
00321         }
00322         if (isset($this->info['extension'])) {
00323             return basename($this->name, '.'.$this->info['extension']);
00324         } elseif ($this->name) {
00325             return $this->name;
00326         }
00327         return false;
00328     }
00329 /**
00330  * makes filename safe for saving
00331  *
00332  * @param string $name the name of the file to make safe if different from $this->name
00333  * @return string $ext the extension of the file
00334  * @access public
00335  */
00336     function safe($name = null, $ext = null) {
00337         if (!$name) {
00338             $name = $this->name;
00339         }
00340         if (!$ext) {
00341             $ext = $this->ext();
00342         }
00343         return preg_replace( "/[^\w\.-]+/", "_", basename($name, $ext));
00344     }
00345 /**
00346  * Get md5 Checksum of file with previous check of Filesize
00347  *
00348  * @param mixed $maxsize in MB or true to force
00349  * @return string md5 Checksum {@link http://php.net/md5_file See md5_file()}
00350  * @access public
00351  */
00352     function md5($maxsize = 5) {
00353         if ($maxsize === true) {
00354             return md5_file($this->pwd());
00355         } else {
00356             $size = $this->size();
00357             if ($size && $size < ($maxsize * 1024) * 1024) {
00358                 return md5_file($this->pwd());
00359             }
00360         }
00361         return false;
00362     }
00363 /**
00364 * Returns the full path of the File.
00365 *
00366 * @return string Full path to file
00367 * @access public
00368 */
00369     function pwd() {
00370         return $this->Folder->slashTerm($this->Folder->pwd()) . $this->name;
00371     }
00372 /**
00373  * Returns true if the File exists.
00374  *
00375  * @return boolean true if it exists, false otherwise
00376  * @access public
00377  */
00378     function exists() {
00379         $exists = (file_exists($this->pwd()) && is_file($this->pwd()));
00380         return $exists;
00381     }
00382 /**
00383  * Returns the "chmod" (permissions) of the File.
00384  *
00385  * @return string Permissions for the file
00386  * @access public
00387  */
00388     function perms() {
00389         if ($this->exists()) {
00390             return substr(sprintf('%o', fileperms($this->pwd())), -4);
00391         }
00392         return false;
00393     }
00394 /**
00395  * Returns the Filesize, either in bytes or in human-readable format.
00396  *
00397  * @param boolean $humanReadeble    Data to write to this File.
00398  * @return string|int filesize as int or as a human-readable string
00399  * @access public
00400  */
00401     function size() {
00402         if ($this->exists()) {
00403             return filesize($this->pwd());
00404         }
00405         return false;
00406     }
00407 /**
00408  * Returns true if the File is writable.
00409  *
00410  * @return boolean true if its writable, false otherwise
00411  * @access public
00412  */
00413     function writable() {
00414         return is_writable($this->pwd());
00415     }
00416 /**
00417  * Returns true if the File is executable.
00418  *
00419  * @return boolean true if its executable, false otherwise
00420  * @access public
00421  */
00422     function executable() {
00423         return is_executable($this->pwd());
00424     }
00425 /**
00426  * Returns true if the File is readable.
00427  *
00428  * @return boolean true if file is readable, false otherwise
00429  * @access public
00430  */
00431     function readable() {
00432         return is_readable($this->pwd());
00433     }
00434 /**
00435  * Returns the File's owner.
00436  *
00437  * @return integer the Fileowner
00438  */
00439     function owner() {
00440         if ($this->exists()) {
00441             return fileowner($this->pwd());
00442         }
00443         return false;
00444     }
00445 /**
00446  * Returns the File group.
00447  *
00448  * @return integer the Filegroup
00449  * @access public
00450  */
00451     function group() {
00452         if ($this->exists()) {
00453             return filegroup($this->pwd());
00454         }
00455         return false;
00456     }
00457 /**
00458  * Returns last access time.
00459  *
00460  * @return integer timestamp Timestamp of last access time
00461  * @access public
00462  */
00463     function lastAccess() {
00464         if ($this->exists()) {
00465             return fileatime($this->pwd());
00466         }
00467         return false;
00468     }
00469 /**
00470  * Returns last modified time.
00471  *
00472  * @return integer timestamp Timestamp of last modification
00473  * @access public
00474  */
00475     function lastChange() {
00476         if ($this->exists()) {
00477             return filemtime($this->pwd());
00478         }
00479         return false;
00480     }
00481 /**
00482  * Returns the current folder.
00483  *
00484  * @return Folder Current folder
00485  * @access public
00486  */
00487     function &Folder() {
00488         return $this->Folder;
00489     }
00490 }
00491 ?>