diff options
author | ewinslow <ewinslow@36083f99-b078-4883-b0ff-0f9b5a30f544> | 2010-09-06 02:42:09 +0000 |
---|---|---|
committer | ewinslow <ewinslow@36083f99-b078-4883-b0ff-0f9b5a30f544> | 2010-09-06 02:42:09 +0000 |
commit | 76dac45ebaf104b312a8527a05424601ca9d520a (patch) | |
tree | 7440558a893ebf1d3816829ecbb96c3b0df9b4f0 /engine/lib/filestore.php | |
parent | 9e8baf614938dfd1687ddce39b409c3c0e5c5753 (diff) | |
download | elgg-76dac45ebaf104b312a8527a05424601ca9d520a.tar.gz elgg-76dac45ebaf104b312a8527a05424601ca9d520a.tar.bz2 |
Refs #2220: Pulled most classes / interfaces out of lib files (except query.php and exception.php) into "classes" folder. Replaced inline classes with "require_once" statements for now. Ran unit tests to verify functionality before committing.
git-svn-id: http://code.elgg.org/elgg/trunk@6908 36083f99-b078-4883-b0ff-0f9b5a30f544
Diffstat (limited to 'engine/lib/filestore.php')
-rw-r--r-- | engine/lib/filestore.php | 697 |
1 files changed, 3 insertions, 694 deletions
diff --git a/engine/lib/filestore.php b/engine/lib/filestore.php index 31fc9ab0d..74a8b0315 100644 --- a/engine/lib/filestore.php +++ b/engine/lib/filestore.php @@ -12,700 +12,9 @@ include_once("objects.php"); -/** - * @class ElggFilestore - * This class defines the interface for all elgg data repositories. - * @author Curverider Ltd - */ -abstract class ElggFilestore { - /** - * Attempt to open the file $file for storage or writing. - * - * @param ElggFile $file - * @param string $mode "read", "write", "append" - * @return mixed A handle to the opened file or false on error. - */ - abstract public function open(ElggFile $file, $mode); - - /** - * Write data to a given file handle. - * - * @param mixed $f The file handle - exactly what this is depends on the file system - * @param string $data The binary string of data to write - * @return int Number of bytes written. - */ - abstract public function write($f, $data); - - /** - * Read data from a filestore. - * - * @param mixed $f The file handle - * @param int $length Length in bytes to read. - * @param int $offset The optional offset. - * @return mixed String of data or false on error. - */ - abstract public function read($f, $length, $offset = 0); - - /** - * Seek a given position within a file handle. - * - * @param mixed $f The file handle. - * @param int $position The position. - */ - abstract public function seek($f, $position); - - /** - * Return a whether the end of a file has been reached. - * - * @param mixed $f The file handle. - * @return boolean - */ - abstract public function eof($f); - - /** - * Return the current position in an open file. - * - * @param mixed $f The file handle. - * @return int - */ - abstract public function tell($f); - - /** - * Close a given file handle. - * - * @param mixed $f - */ - abstract public function close($f); - - /** - * Delete the file associated with a given file handle. - * - * @param ElggFile $file - */ - abstract public function delete(ElggFile $file); - - /** - * Return the size in bytes for a given file. - * - * @param ElggFile $file - */ - abstract public function getFileSize(ElggFile $file); - - /** - * Return the filename of a given file as stored on the filestore. - * - * @param ElggFile $file - */ - abstract public function getFilenameOnFilestore(ElggFile $file); - - /** - * Get the filestore's creation parameters as an associative array. - * Used for serialisation and for storing the creation details along side a file object. - * - * @return array - */ - abstract public function getParameters(); - - /** - * Set the parameters from the associative array produced by $this->getParameters(). - */ - abstract public function setParameters(array $parameters); - - /** - * Get the contents of the whole file. - * - * @param mixed $file The file handle. - * @return mixed The file contents. - */ - abstract public function grabFile(ElggFile $file); - - /** - * Return whether a file physically exists or not. - * - * @param ElggFile $file - */ - abstract public function exists(ElggFile $file); -} - -/** - * @class ElggDiskFilestore - * This class uses disk storage to save data. - * @author Curverider Ltd - */ -class ElggDiskFilestore extends ElggFilestore { - /** - * Directory root. - */ - private $dir_root; - - /** - * Default depth of file directory matrix - */ - private $matrix_depth = 5; - - /** - * Construct a disk filestore using the given directory root. - * - * @param string $directory_root Root directory, must end in "/" - */ - public function __construct($directory_root = "") { - global $CONFIG; - - if ($directory_root) { - $this->dir_root = $directory_root; - } else { - $this->dir_root = $CONFIG->dataroot; - } - } - - public function open(ElggFile $file, $mode) { - $fullname = $this->getFilenameOnFilestore($file); - - // Split into path and name - $ls = strrpos($fullname,"/"); - if ($ls===false) { - $ls = 0; - } - - $path = substr($fullname, 0, $ls); - $name = substr($fullname, $ls); - - // Try and create the directory - try { - $this->make_directory_root($path); - } catch (Exception $e) { - - } - - if (($mode!='write') && (!file_exists($fullname))) { - return false; - } - - switch ($mode) { - case "read" : - $mode = "rb"; - break; - case "write" : - $mode = "w+b"; - break; - case "append" : - $mode = "a+b"; - break; - default: - throw new InvalidParameterException(sprintf(elgg_echo('InvalidParameterException:UnrecognisedFileMode'), $mode)); - } - - return fopen($fullname, $mode); - - } - - public function write($f, $data) { - return fwrite($f, $data); - } - - public function read($f, $length, $offset = 0) { - if ($offset) { - $this->seek($f, $offset); - } - - return fread($f, $length); - } - - public function close($f) { - return fclose($f); - } - - public function delete(ElggFile $file) { - $filename = $this->getFilenameOnFilestore($file); - if (file_exists($filename)) { - return unlink($filename); - } else { - return true; - } - } - - public function seek($f, $position) { - return fseek($f, $position); - } - - public function tell($f) { - return ftell($f); - } - - public function eof($f) { - return feof($f); - } - - public function getFileSize(ElggFile $file) { - return filesize($this->getFilenameOnFilestore($file)); - } - - public function getFilenameOnFilestore(ElggFile $file) { - $owner = $file->getOwnerEntity(); - if (!$owner) { - $owner = get_loggedin_user(); - } - - if ((!$owner) || (!$owner->username)) { - throw new InvalidParameterException(sprintf(elgg_echo('InvalidParameterException:MissingOwner'), $file->getFilename(), $file->guid)); - } - - return $this->dir_root . $this->make_file_matrix($owner->guid) . $file->getFilename(); - } - - public function grabFile(ElggFile $file) { - return file_get_contents($file->getFilenameOnFilestore()); - } - - public function exists(ElggFile $file) { - return file_exists($this->getFilenameOnFilestore($file)); - } - - public function getSize($prefix,$container_guid) { - if ($container_guid) { - return get_dir_size($this->dir_root.$this->make_file_matrix($container_guid).$prefix); - } else { - return false; - } - } - - /** - * Make the directory root. - * - * @param string $dirroot - */ - protected function make_directory_root($dirroot) { - if (!file_exists($dirroot)) { - if (!@mkdir($dirroot, 0700, true)) { - throw new IOException(sprintf(elgg_echo('IOException:CouldNotMake'), $dirroot)); - } - } - - return true; - } - - /** - * Multibyte string tokeniser. - * - * Splits a string into an array. Will fail safely if mbstring is not installed (although this may still - * not handle . - * - * @param string $string String - * @param string $charset The charset, defaults to UTF8 - * @return array - */ - private function mb_str_split($string, $charset = 'UTF8') { - if (is_callable('mb_substr')) { - $length = mb_strlen($string); - $array = array(); - - while ($length) { - $array[] = mb_substr($string, 0, 1, $charset); - $string = mb_substr($string, 1, $length, $charset); - - $length = mb_strlen($string); - } - - return $array; - } else { - return str_split($string); - } - - return false; - } - - /** - * Construct the filename matrix. - * - * @param int | string $identifier - * @return str - */ - protected function make_file_matrix($identifier) { - if (is_numeric($identifier)) { - return $this->user_file_matrix($identifier); - } - - return $this->deprecated_file_matrix($identifier); - } - - /** - * Construct the filename matrix with user info - * - * This method will generate a matrix using the entity's creation time and - * unique guid. This is intended only to determine a user's data directory. - * - * @param int $guid - * @return str - */ - protected function user_file_matrix($guid) { - // lookup the entity - $user = get_entity($guid); - if ($user->type != 'user') - { - // only to be used for user directories - return FALSE; - } - - if (!$user->time_created) { - // fall back to deprecated method - return $this->deprecated_file_matrix($user->username); - } - - $time_created = date('Y/m/d', $user->time_created); - return "$time_created/$user->guid/"; - } - - /** - * Construct the filename matrix using a string - * - * Particularly, this is used with a username to generate the file storage - * location. - * - * @deprecated for user directories: use user_file_matrix() instead. - * - * @param str $filename - * @return str - */ - protected function deprecated_file_matrix($filename) { - // throw a warning for using deprecated method - $error = 'Deprecated use of ElggDiskFilestore::make_file_matrix. '; - $error .= 'Username passed instead of guid.'; - elgg_log($error, WARNING); - - $user = new ElggUser($filename); - return $this->user_file_matrix($user->guid); - } - - public function getParameters() { - return array("dir_root" => $this->dir_root); - } - - public function setParameters(array $parameters) { - if (isset($parameters['dir_root'])) { - $this->dir_root = $parameters['dir_root']; - return true; - } - - return false; - } -} - -/** - * @class ElggFile - * This class represents a physical file. - * - * Usage: - * Create a new ElggFile object and specify a filename, and optionally a FileStore (if one isn't specified - * then the default is assumed. - * - * Open the file using the appropriate mode, and you will be able to read and write to the file. - * - * Optionally, you can also call the file's save() method, this will turn the file into an entity in the - * system and permit you to do things like attach tags to the file etc. This is not done automatically since - * there are many occasions where you may want access to file data on datastores using the ElggFile interface - * but do not want to create an Entity reference to it in the system (temporary files for example). - * - * @author Curverider Ltd - */ -class ElggFile extends ElggObject { - /** Filestore */ - private $filestore; - - /** File handle used to identify this file in a filestore. Created by open. */ - private $handle; - - protected function initialise_attributes() { - parent::initialise_attributes(); - - $this->attributes['subtype'] = "file"; - } - - public function __construct($guid = null) { - parent::__construct($guid); - - // Set default filestore - $this->filestore = $this->getFilestore(); - } - - /** - * Set the filename of this file. - * - * @param string $name The filename. - */ - public function setFilename($name) { - $this->filename = $name; - } - - /** - * Return the filename. - */ - public function getFilename() { - return $this->filename; - } - - /** - * Return the filename of this file as it is/will be stored on the filestore, which may be different - * to the filename. - */ - public function getFilenameOnFilestore() { - return $this->filestore->getFilenameOnFilestore($this); - } - - /* - * Return the size of the filestore associated with this file - * - */ - public function getFilestoreSize($prefix='',$container_guid=0) { - if (!$container_guid) { - $container_guid = $this->container_guid; - } - $fs = $this->getFilestore(); - return $fs->getSize($prefix,$container_guid); - } - - /** - * Get the mime type of the file. - */ - public function getMimeType() { - if ($this->mimetype) { - return $this->mimetype; - } - - // @todo Guess mimetype if not here - } - - /** - * Set the mime type of the file. - * - * @param $mimetype The mimetype - */ - public function setMimeType($mimetype) { - return $this->mimetype = $mimetype; - } - - /** - * Set the optional file description. - * - * @param string $description The description. - */ - public function setDescription($description) { - $this->description = $description; - } - - /** - * Open the file with the given mode - * - * @param string $mode Either read/write/append - */ - public function open($mode) { - if (!$this->getFilename()) { - throw new IOException(elgg_echo('IOException:MissingFileName')); - } - - // See if file has already been saved - // seek on datastore, parameters and name? - - // Sanity check - if ( - ($mode!="read") && - ($mode!="write") && - ($mode!="append") - ) { - throw new InvalidParameterException(sprintf(elgg_echo('InvalidParameterException:UnrecognisedFileMode'), $mode)); - } - - // Get the filestore - $fs = $this->getFilestore(); - - // Ensure that we save the file details to object store - //$this->save(); - - // Open the file handle - $this->handle = $fs->open($this, $mode); - - return $this->handle; - } - - /** - * Write some data. - * - * @param string $data The data - */ - public function write($data) { - $fs = $this->getFilestore(); - - return $fs->write($this->handle, $data); - } - - /** - * Read some data. - * - * @param int $length Amount to read. - * @param int $offset The offset to start from. - */ - public function read($length, $offset = 0) { - $fs = $this->getFilestore(); - - return $fs->read($this->handle, $length, $offset); - } - - /** - * Gets the full contents of this file. - * - * @return mixed The file contents. - */ - public function grabFile() { - $fs = $this->getFilestore(); - return $fs->grabFile($this); - } - - /** - * Close the file and commit changes - */ - public function close() { - $fs = $this->getFilestore(); - - if ($fs->close($this->handle)) { - $this->handle = NULL; - - return true; - } - - return false; - } - - /** - * Delete this file. - */ - public function delete() { - $fs = $this->getFilestore(); - if ($fs->delete($this)) { - return parent::delete(); - } - } - - /** - * Seek a position in the file. - * - * @param int $position - */ - public function seek($position) { - $fs = $this->getFilestore(); - - return $fs->seek($this->handle, $position); - } - - /** - * Return the current position of the file. - * - * @return int The file position - */ - public function tell() { - $fs = $this->getFilestore(); - - return $fs->tell($this->handle); - } - - /** - * Return the size of the file in bytes. - */ - public function size() { - return $this->filestore->getFileSize($this); - } - - /** - * Return a boolean value whether the file handle is at the end of the file - */ - public function eof() { - $fs = $this->getFilestore(); - - return $fs->eof($this->handle); - } - - public function exists() { - $fs = $this->getFilestore(); - - return $fs->exists($this); - } - - /** - * Set a filestore. - * - * @param ElggFilestore $filestore The file store. - */ - public function setFilestore(ElggFilestore $filestore) { - $this->filestore = $filestore; - } - - /** - * Return a filestore suitable for saving this file. - * This filestore is either a pre-registered filestore, a filestore loaded from metatags saved - * along side this file, or the system default. - */ - protected function getFilestore() { - // Short circuit if already set. - if ($this->filestore) { - return $this->filestore; - } - - // If filestore meta set then retrieve filestore - // @todo Better way of doing this? - $metas = get_metadata_for_entity($this->guid); - $parameters = array(); - if (is_array($metas)) { - foreach ($metas as $meta) { - if (strpos($meta->name, "filestore::")!==false) { - // Filestore parameter tag - $comp = explode("::", $meta->name); - $name = $comp[1]; - - $parameters[$name] = $meta->value; - } - } - } - - if (isset($parameters['filestore'])) { - if (!class_exists($parameters['filestore'])) { - $msg = sprintf(elgg_echo('ClassNotFoundException:NotFoundNotSavedWithFile'), - $parameters['filestore'], - $this->guid); - throw new ClassNotFoundException($msg); - } - - // Create new filestore object - $this->filestore = new $parameters['filestore'](); - - $this->filestore->setParameters($parameters); - } else { - // @todo - should we log error if filestore not set - } - - - // if still nothing then set filestore to default - if (!$this->filestore) { - $this->filestore = get_default_filestore(); - } - - return $this->filestore; - } - - public function save() { - if (!parent::save()) { - return false; - } - - // Save datastore metadata - $params = $this->filestore->getParameters(); - foreach ($params as $k => $v) { - $this->setMetaData("filestore::$k", $v); - } - - // Now make a note of the filestore class - $this->setMetaData("filestore::filestore", get_class($this->filestore)); - - return true; - } -} +require_once dirname(dirname(__FILE__)).'/classes/ElggFilestore.php'; +require_once dirname(dirname(__FILE__)).'/classes/ElggDiskFilestore.php'; +require_once dirname(dirname(__FILE__)).'/classes/ElggFile.php'; /** * Get the size of the specified directory. |