<?php /** * @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; } }