Created
February 27, 2013 07:46
-
-
Save finwe/5046030 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* File operations wrapper class | |
* | |
* @author Finwe | |
*/ | |
class File | |
{ | |
const READ = 1; | |
const WRITE = 2; | |
const START = 4; | |
const END = 8; | |
const CREATE = 16; | |
const FAIL_IF_EXISTS = 32; | |
const TRUNCATE = 64; | |
const MODE_R = 'r'; | |
const MODE_RPLUS = 'r+'; | |
const MODE_W = 'w'; | |
const MODE_WPLUS = 'w+'; | |
const MODE_A = 'a'; | |
const MODE_APLUS = 'a+'; | |
const MODE_X = 'x'; | |
const MODE_XPLUS = 'x+'; | |
const MODE_C = 'c' ; | |
const MODE_CPLUS = 'c+'; | |
private $legacyModes = array( | |
self::MODE_R, | |
self::MODE_RPLUS, | |
self::MODE_W, | |
self::MODE_WPLUS, | |
self::MODE_A, | |
self::MODE_APLUS, | |
self::MODE_X, | |
self::MODE_XPLUS, | |
self::MODE_C, | |
self::MODE_CPLUS | |
); | |
private $handler; | |
/** | |
* Constructor. Opens a file of given path | |
* | |
* @param type $path Path to file | |
* @param type $mode Mode to open file. Defaults to self::READ | self::WRITE | self::END | self::CREATE | |
* @param type $useIncludePath | |
* @param type $context | |
* @throws InvalidStateException $path does not exist | |
* @throws InvalidStateException Unable to open file for other reasons | |
*/ | |
public function __construct($path, $mode = 27, $useIncludePath = false, $context = NULL) | |
{ | |
if (!self::exists($path)) { | |
throw new InvalidArgumentException("File $path does not exist"); | |
} | |
$this->handler = @fopen($path, $this->getMode($mode), $useIncludePath, $context); | |
if (false === $this->handler) { | |
$error = error_get_last(); | |
$message = isset($error['message']) ? ': ' . $error['message'] : NULL; | |
throw new InvalidStateException("Unable to open file $path $message"); | |
} | |
} | |
/** | |
* Static file opening method | |
* | |
* @param type $path | |
* @param type $mode | |
* @param type $useIncludePath | |
* @param type $context | |
* @return \self | |
*/ | |
public static function open($path, $mode = 27, $useIncludePath = false, $context = NULL) | |
{ | |
$file = new self; | |
if ($path) { | |
$file->open($path, $mode, $useIncludePath, $context); | |
} | |
return $file; | |
} | |
public function __destruct() | |
{ | |
$this->close(); | |
} | |
public function write($data, $length = NULL) | |
{ | |
return fwrite($this->handler, $data, $length); | |
} | |
public function close() | |
{ | |
if (!$this->handler) { | |
throw new InvalidStateException('File already closed.'); | |
} | |
fclose($this->handler); | |
$this->handler = NULL; | |
} | |
/** | |
* Returns php internal file open mode. | |
* | |
* @link http://php.net/manual/en/function.fopen.php | |
* | |
* @param mixed $mode | |
* @return string | |
* | |
* @throws InvalidArgumentException on invalid mode or flag combination | |
*/ | |
private function getMode($mode) | |
{ | |
$returnMode = NULL; | |
if (is_int($mode)) { | |
$read = (0 === $mode | self::READ); | |
$write = (0 === $mode | self::WRITE); | |
$start = (0 === $mode | self::START); | |
$end = (0 === $mode | self::END); | |
$truncate = (0 === $mode | self::TRUNCATE); | |
$fail = (0 === $mode | self::FAIL_IF_EXISTS); | |
$create = (0 === $mode | self::CREATE); | |
if ($read && $write) { | |
if ($start) { | |
if ($truncate && $fail && $create) { | |
// 'x+' Create and open for reading and writing; otherwise it has the same behavior as 'x'. | |
return self::MODE_XPLUS; | |
} | |
if ($truncate && $create) { | |
// 'w+' Open for reading and writing; place the file pointer at the beginning of the file and truncate the file to zero length. | |
// If the file does not exist, attempt to create it. | |
return self::MODE_WPLUS; | |
} | |
if ($create) { | |
// 'c+' Open the file for reading and writing; otherwise it has the same behavior as 'c'. | |
return self::MODE_CPLUS; | |
} | |
// 'r+' Open for reading and writing; place the file pointer at the beginning of the file. | |
return self::MODE_RPLUS; | |
} elseif ($end) { | |
if ($create) { | |
// 'a+' Open for reading and writing; place the file pointer at the end of the file. If the file does not exist, attempt to create it. | |
return self::MODE_APLUS; | |
} | |
} else { | |
throw new InvalidArgumentException('No pointer position specified when opening file'); | |
} | |
} elseif ($read) { | |
if ($start) { | |
// 'r' Open for reading only; place the file pointer at the beginning of the file. | |
return self::MODE_R; | |
} else { | |
throw new InvalidArgumentException('Unable to place pointer to end of file when opening for reading only'); | |
} | |
} elseif ($write) { | |
if ($start) { | |
if ($truncate && $create) { | |
// 'w' Open for writing only; place the file pointer at the beginning of the file and truncate the file to zero length. | |
// If the file does not exist, attempt to create it. | |
return self::MODE_W; | |
} | |
if ($fail && $create) { | |
// 'x' Create and open for writing only; place the file pointer at the beginning of the file. | |
// If the file already exists, the fopen() call will fail by returning FALSE and generating an error of level E_WARNING. | |
// If the file does not exist, attempt to create it. | |
// This is equivalent to specifying O_EXCL|O_CREAT flags for the underlying open(2) system call. | |
return self::MODE_X; | |
} | |
if ($create) { | |
// 'c' Open the file for writing only. If the file does not exist, it is created. | |
// If it exists, it is neither truncated (as opposed to 'w'), nor the call to this function fails (as is the case with 'x'). | |
// The file pointer is positioned on the beginning of the file. | |
// This may be useful if it's desired to get an advisory lock (see flock()) before attempting to modify the file, | |
// as using 'w' could truncate the file before the lock was obtained (if truncation is desired, ftruncate() can be used after the lock is requested). | |
return self::MODE_C; | |
} | |
} elseif ($end) { | |
if ($create) { | |
// 'a' Open for writing only; place the file pointer at the end of the file. If the file does not exist, attempt to create it. | |
return self::MODE_A; | |
} | |
} else { | |
throw new InvalidArgumentException('No pointer position specified when opening file'); | |
} | |
} else { | |
throw new InvalidArgumentException('No read/write option specified to opened file'); | |
} | |
throw new InvalidArgumentException('Invalid mode flag combination specified when opening file'); | |
} elseif (in_array($mode, $this->legacyModes)) { | |
return $mode; | |
} else { | |
throw new InvalidArgumentException('Invalid mode given'); | |
} | |
} | |
public static function exists($path) | |
{ | |
return file_exists($path); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment