aboutsummaryrefslogtreecommitdiff
path: root/engine/classes/ElggFile.php
diff options
context:
space:
mode:
Diffstat (limited to 'engine/classes/ElggFile.php')
-rw-r--r--engine/classes/ElggFile.php228
1 files changed, 175 insertions, 53 deletions
diff --git a/engine/classes/ElggFile.php b/engine/classes/ElggFile.php
index 68ed2f2f2..23080834b 100644
--- a/engine/classes/ElggFile.php
+++ b/engine/classes/ElggFile.php
@@ -1,21 +1,24 @@
<?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.
+ * 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.
+ * 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).
+ * 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
+ * @package Elgg.Core
+ * @subpackage DataModel.File
*/
class ElggFile extends ElggObject {
/** Filestore */
@@ -24,12 +27,22 @@ class ElggFile extends ElggObject {
/** File handle used to identify this file in a filestore. Created by open. */
private $handle;
- protected function initialise_attributes() {
- parent::initialise_attributes();
+ /**
+ * Set subtype to 'file'.
+ *
+ * @return void
+ */
+ protected function initializeAttributes() {
+ parent::initializeAttributes();
$this->attributes['subtype'] = "file";
}
+ /**
+ * Loads an ElggFile entity.
+ *
+ * @param int $guid GUID of the ElggFile object
+ */
public function __construct($guid = null) {
parent::__construct($guid);
@@ -41,6 +54,8 @@ class ElggFile extends ElggObject {
* Set the filename of this file.
*
* @param string $name The filename.
+ *
+ * @return void
*/
public function setFilename($name) {
$this->filename = $name;
@@ -48,33 +63,44 @@ class ElggFile extends ElggObject {
/**
* Return the filename.
+ *
+ * @return string
*/
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.
+ * Return the filename of this file as it is/will be stored on the
+ * filestore, which may be different to the filename.
+ *
+ * @return string
*/
public function getFilenameOnFilestore() {
return $this->filestore->getFilenameOnFilestore($this);
}
- /*
+ /**
* Return the size of the filestore associated with this file
*
+ * @param string $prefix Storage prefix
+ * @param int $container_guid The container GUID of the checked filestore
+ *
+ * @return int
*/
- public function getFilestoreSize($prefix='',$container_guid=0) {
+ public function getFilestoreSize($prefix = '', $container_guid = 0) {
if (!$container_guid) {
$container_guid = $this->container_guid;
}
$fs = $this->getFilestore();
- return $fs->getSize($prefix,$container_guid);
+ // @todo add getSize() to ElggFilestore
+ return $fs->getSize($prefix, $container_guid);
}
/**
* Get the mime type of the file.
+ *
+ * @return string
*/
public function getMimeType() {
if ($this->mimetype) {
@@ -87,16 +113,63 @@ class ElggFile extends ElggObject {
/**
* Set the mime type of the file.
*
- * @param $mimetype The mimetype
+ * @param string $mimetype The mimetype
+ *
+ * @return bool
*/
public function setMimeType($mimetype) {
return $this->mimetype = $mimetype;
}
/**
+ * Detects mime types based on filename or actual file.
+ *
+ * @param mixed $file The full path of the file to check. For uploaded files, use tmp_name.
+ * @param mixed $default A default. Useful to pass what the browser thinks it is.
+ * @since 1.7.12
+ *
+ * @note If $file is provided, this may be called statically
+ *
+ * @return mixed Detected type on success, false on failure.
+ */
+ public function detectMimeType($file = null, $default = null) {
+ if (!$file) {
+ if (isset($this) && $this->filename) {
+ $file = $this->filename;
+ } else {
+ return false;
+ }
+ }
+
+ $mime = false;
+
+ // for PHP5 folks.
+ if (function_exists('finfo_file') && defined('FILEINFO_MIME_TYPE')) {
+ $resource = finfo_open(FILEINFO_MIME_TYPE);
+ if ($resource) {
+ $mime = finfo_file($resource, $file);
+ }
+ }
+
+ // for everyone else.
+ if (!$mime && function_exists('mime_content_type')) {
+ $mime = mime_content_type($file);
+ }
+
+ // default
+ if (!$mime) {
+ return $default;
+ }
+
+ return $mime;
+ }
+
+ /**
* Set the optional file description.
*
* @param string $description The description.
+ *
+ * @return bool
*/
public function setDescription($description) {
$this->description = $description;
@@ -106,6 +179,10 @@ class ElggFile extends ElggObject {
* Open the file with the given mode
*
* @param string $mode Either read/write/append
+ *
+ * @return resource File handler
+ *
+ * @throws IOException|InvalidParameterException
*/
public function open($mode) {
if (!$this->getFilename()) {
@@ -117,11 +194,12 @@ class ElggFile extends ElggObject {
// Sanity check
if (
- ($mode!="read") &&
- ($mode!="write") &&
- ($mode!="append")
+ ($mode != "read") &&
+ ($mode != "write") &&
+ ($mode != "append")
) {
- throw new InvalidParameterException(sprintf(elgg_echo('InvalidParameterException:UnrecognisedFileMode'), $mode));
+ $msg = elgg_echo('InvalidParameterException:UnrecognisedFileMode', array($mode));
+ throw new InvalidParameterException($msg);
}
// Get the filestore
@@ -137,9 +215,11 @@ class ElggFile extends ElggObject {
}
/**
- * Write some data.
+ * Write data.
*
* @param string $data The data
+ *
+ * @return bool
*/
public function write($data) {
$fs = $this->getFilestore();
@@ -148,10 +228,12 @@ class ElggFile extends ElggObject {
}
/**
- * Read some data.
+ * Read data.
*
* @param int $length Amount to read.
* @param int $offset The offset to start from.
+ *
+ * @return mixed Data or false
*/
public function read($length, $offset = 0) {
$fs = $this->getFilestore();
@@ -171,6 +253,8 @@ class ElggFile extends ElggObject {
/**
* Close the file and commit changes
+ *
+ * @return bool
*/
public function close() {
$fs = $this->getFilestore();
@@ -186,22 +270,32 @@ class ElggFile extends ElggObject {
/**
* Delete this file.
+ *
+ * @return bool
*/
public function delete() {
$fs = $this->getFilestore();
- if ($fs->delete($this)) {
- return parent::delete();
+
+ $result = $fs->delete($this);
+
+ if ($this->getGUID() && $result) {
+ $result = parent::delete();
}
+
+ return $result;
}
/**
* Seek a position in the file.
*
- * @param int $position
+ * @param int $position Position in bytes
+ *
+ * @return bool
*/
public function seek($position) {
$fs = $this->getFilestore();
+ // @todo add seek() to ElggFilestore
return $fs->seek($this->handle, $position);
}
@@ -218,6 +312,8 @@ class ElggFile extends ElggObject {
/**
* Return the size of the file in bytes.
+ *
+ * @return int
*/
public function size() {
return $this->filestore->getFileSize($this);
@@ -225,6 +321,8 @@ class ElggFile extends ElggObject {
/**
* Return a boolean value whether the file handle is at the end of the file
+ *
+ * @return bool
*/
public function eof() {
$fs = $this->getFilestore();
@@ -232,6 +330,11 @@ class ElggFile extends ElggObject {
return $fs->eof($this->handle);
}
+ /**
+ * Returns if the file exists
+ *
+ * @return bool
+ */
public function exists() {
$fs = $this->getFilestore();
@@ -242,6 +345,8 @@ class ElggFile extends ElggObject {
* Set a filestore.
*
* @param ElggFilestore $filestore The file store.
+ *
+ * @return void
*/
public function setFilestore(ElggFilestore $filestore) {
$this->filestore = $filestore;
@@ -249,8 +354,12 @@ class ElggFile extends ElggObject {
/**
* 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.
+ * This filestore is either a pre-registered filestore,
+ * a filestore as recorded in metadata or the system default.
+ *
+ * @return ElggFilestore
+ *
+ * @throws ClassNotFoundException
*/
protected function getFilestore() {
// Short circuit if already set.
@@ -258,40 +367,43 @@ class ElggFile extends ElggObject {
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;
+ // ask for entity specific filestore
+ // saved as filestore::className in metadata.
+ // need to get all filestore::* metadata because the rest are "parameters" that
+ // get passed to filestore::setParameters()
+ if ($this->guid) {
+ $options = array(
+ 'guid' => $this->guid,
+ 'where' => array("n.string LIKE 'filestore::%'"),
+ );
+
+ $mds = elgg_get_metadata($options);
+
+ $parameters = array();
+ foreach ($mds as $md) {
+ list($foo, $name) = explode("::", $md->name);
+ if ($name == 'filestore') {
+ $filestore = $md->value;
}
+ $parameters[$name] = $md->value;
}
}
- if (isset($parameters['filestore'])) {
- if (!class_exists($parameters['filestore'])) {
- $msg = sprintf(elgg_echo('ClassNotFoundException:NotFoundNotSavedWithFile'),
- $parameters['filestore'],
- $this->guid);
+ // need to check if filestore is set because this entity is loaded in save()
+ // before the filestore metadata is saved.
+ if (isset($filestore)) {
+ if (!class_exists($filestore)) {
+ $msg = elgg_echo('ClassNotFoundException:NotFoundNotSavedWithFile',
+ array($filestore, $this->guid));
throw new ClassNotFoundException($msg);
}
- // Create new filestore object
- $this->filestore = new $parameters['filestore']();
-
+ $this->filestore = new $filestore();
$this->filestore->setParameters($parameters);
- } else {
- // @todo - should we log error if filestore not set
+ // @todo explain why $parameters will always be set here (PhpStorm complains)
}
-
- // if still nothing then set filestore to default
+ // this means the entity hasn't been saved so fallback to default
if (!$this->filestore) {
$this->filestore = get_default_filestore();
}
@@ -299,6 +411,16 @@ class ElggFile extends ElggObject {
return $this->filestore;
}
+ /**
+ * Save the file
+ *
+ * Write the file's data to the filestore and save
+ * the corresponding entity.
+ *
+ * @see ElggObject::save()
+ *
+ * @return bool
+ */
public function save() {
if (!parent::save()) {
return false;