Elgg  Version 2.3
ElggFile.php
Go to the documentation of this file.
1 <?php
2 
6 
32 class ElggFile extends ElggObject {
33 
37  private $filestore;
38 
42  private $handle;
43 
49  protected function initializeAttributes() {
50  parent::initializeAttributes();
51 
52  $this->attributes['subtype'] = "file";
53  }
54 
58  public function getMetadata($name) {
59  if (0 === strpos($name, 'filestore::')) {
60  elgg_deprecated_notice("Do not access the ElggFile filestore metadata directly. Use setFilestore().", '2.0');
61  }
62  return parent::getMetadata($name);
63  }
64 
68  public function setMetadata($name, $value, $value_type = '', $multiple = false, $owner_guid = 0, $access_id = null) {
69  if (0 === strpos($name, 'filestore::')) {
70  elgg_deprecated_notice("Do not access the ElggFile filestore metadata directly. Use setFilestore().", '2.0');
71  }
72  return parent::setMetadata($name, $value, $value_type, $multiple, $owner_guid, $access_id);
73  }
74 
82  public function setFilename($name) {
83  $this->filename = $name;
84  }
85 
91  public function getFilename() {
92  return $this->filename;
93  }
94 
101  public function getFilenameOnFilestore() {
102  return $this->getFilestore()->getFilenameOnFilestore($this);
103  }
104 
113  public function getFilestoreSize($prefix = '', $container_guid = 0) {
114  if (!$container_guid) {
116  }
117  $fs = $this->getFilestore();
118  // @todo add getSize() to \ElggFilestore
119  return $fs->getSize($prefix, $container_guid);
120  }
121 
127  public function getMimeType() {
128  if ($this->mimetype) {
129  return $this->mimetype;
130  }
131  return $this->detectMimeType();
132  }
133 
140  public function setMimeType($mimetype) {
141  return $this->mimetype = $mimetype;
142  }
143 
156  public function detectMimeType($file = null, $default = null) {
157  $class = __CLASS__;
158  if (!$file && isset($this) && $this instanceof $class) {
159  $file = $this->getFilenameOnFilestore();
160  }
161 
162  if (!is_readable($file)) {
163  return false;
164  }
165 
166  $mime = $default;
167 
168  $detected = (new MimeTypeDetector())->tryStrategies($file);
169  if ($detected) {
170  $mime = $detected;
171  }
172 
173  $original_filename = isset($this) && $this instanceof $class ? $this->originalfilename : basename($file);
174  $params = array(
175  'filename' => $file,
176  'original_filename' => $original_filename, // @see file upload action
177  'default' => $default,
178  );
179  return _elgg_services()->hooks->trigger('mime_type', 'file', $params, $mime);
180  }
181 
189  public function getSimpleType() {
190  if (isset($this->simpletype)) {
191  return $this->simpletype;
192  }
193  $mime_type = $this->getMimeType();
194  return elgg_get_file_simple_type($mime_type);
195  }
196 
204  public function setDescription($description) {
205  $this->description = $description;
206  }
207 
218  public function open($mode) {
219  if (!$this->getFilename()) {
220  throw new IOException("You must specify a name before opening a file.");
221  }
222 
223  // See if file has already been saved
224  // seek on datastore, parameters and name?
225  // Sanity check
226  if (
227  ($mode != "read") &&
228  ($mode != "write") &&
229  ($mode != "append")
230  ) {
231  $msg = "Unrecognized file mode '" . $mode . "'";
232  throw new InvalidParameterException($msg);
233  }
234 
235  // Get the filestore
236  $fs = $this->getFilestore();
237 
238  // Ensure that we save the file details to object store
239  //$this->save();
240  // Open the file handle
241  $this->handle = $fs->open($this, $mode);
242 
243  return $this->handle;
244  }
245 
253  public function write($data) {
254  $fs = $this->getFilestore();
255 
256  return $fs->write($this->handle, $data);
257  }
258 
267  public function read($length, $offset = 0) {
268  $fs = $this->getFilestore();
269 
270  return $fs->read($this->handle, $length, $offset);
271  }
272 
278  public function grabFile() {
279  $fs = $this->getFilestore();
280  return $fs->grabFile($this);
281  }
282 
288  public function close() {
289  $fs = $this->getFilestore();
290 
291  if ($fs->close($this->handle)) {
292  $this->handle = null;
293 
294  return true;
295  }
296 
297  return false;
298  }
299 
306  public function delete($follow_symlinks = true) {
307  $fs = $this->getFilestore();
308 
309  $result = $fs->delete($this, $follow_symlinks);
310 
311  if ($this->getGUID() && $result) {
313  }
314 
315  return $result;
316  }
317 
325  public function seek($position) {
326  $fs = $this->getFilestore();
327 
328  return $fs->seek($this->handle, $position);
329  }
330 
336  public function tell() {
337  $fs = $this->getFilestore();
338 
339  return $fs->tell($this->handle);
340  }
341 
346  public function setModifiedTime() {
347  $filestorename = $this->getFilenameOnFilestore();
348  $modified = touch($filestorename);
349  if ($modified) {
350  clearstatcache(true, $filestorename);
351  } else {
352  elgg_log("Unable to update modified time for $filestorename", 'ERROR');
353  }
354  return $modified;
355  }
356 
361  public function getModifiedTime() {
362  return filemtime($this->getFilenameOnFilestore());
363  }
364 
371  public function getSize() {
372  return $this->getFilestore()->getFileSize($this);
373  }
374 
381  public function size() {
382  elgg_deprecated_notice("Use \ElggFile::getSize() instead of \ElggFile::size()", 1.9);
383  return $this->getSize();
384  }
385 
391  public function eof() {
392  $fs = $this->getFilestore();
393 
394  return $fs->eof($this->handle);
395  }
396 
402  public function exists() {
403  $fs = $this->getFilestore();
404 
405  return $fs->exists($this);
406  }
407 
416  public function setFilestore(ElggFilestore $filestore) {
417  elgg_deprecated_notice(__METHOD__ . ' is deprecated.', '2.1');
418  $this->filestore = $filestore;
419  }
420 
430  protected function getFilestore() {
431  if ($this->filestore) {
432  // already set
433  return $this->filestore;
434  }
435 
436  // such a common case we just assume for now
437  $this->filestore = $GLOBALS['DEFAULT_FILE_STORE'];
438 
439  if (!$this->guid) {
440  return $this->filestore;
441  }
442 
443  // Note we use parent::getMetadata() below to avoid showing the warnings added in #9193
444 
445  $class = parent::getMetadata('filestore::filestore');
446  if (!$class) {
447  return $this->filestore;
448  }
449 
450  // common case
451  if ($class === ElggDiskFilestore::class && parent::getMetadata('filestore::dir_root') === _elgg_services()->config->getDataPath()) {
452  return $this->filestore;
453  }
454 
455  if (!class_exists($class)) {
456  $this->filestore = null;
457  throw new ClassNotFoundException("Unable to load filestore class $class for file {$this->guid}");
458  }
459 
460  // need to get all filestore::* metadata because the rest are "parameters" that
461  // get passed to filestore::setParameters()
462  $mds = elgg_get_metadata([
463  'guid' => $this->guid,
464  'where' => array("n.string LIKE 'filestore::%'"),
465  ]);
466  $parameters = [];
467  foreach ($mds as $md) {
468  list(, $name) = explode("::", $md->name);
469  if ($name !== 'filestore') {
470  $parameters[$name] = $md->value;
471  }
472  }
473 
474  $this->filestore = new $class();
475  $this->filestore->setParameters($parameters);
476  return $this->filestore;
477  }
478 
489  public function save() {
490  if (!parent::save()) {
491  return false;
492  }
493 
494  $filestore = $this->getFilestore();
495 
496  // Note we use parent::getMetadata() below to avoid showing the warnings added in #9193
497  // Save datastore metadata
498  $params = $filestore->getParameters();
499  foreach ($params as $k => $v) {
500  parent::setMetadata("filestore::$k", $v);
501  }
502 
503  // Now make a note of the filestore class
504  parent::setMetadata("filestore::filestore", get_class($filestore));
505 
506  return true;
507  }
508 
520  public function transfer($owner_guid, $filename = null) {
521  if (!$owner_guid) {
522  return false;
523  }
524 
525  if (!$this->exists()) {
526  return false;
527  }
528 
529  if (!$filename) {
530  $filename = $this->getFilename();
531  }
532  $filestorename = $this->getFilenameOnFilestore();
533 
534  $this->owner_guid = $owner_guid;
535  $this->setFilename($filename);
536  $this->open('write');
537  $this->close();
538 
539  return rename($filestorename, $this->getFilenameOnFilestore());
540  }
541 
557  public function acceptUploadedFile(UploadedFile $upload) {
558  if (!$upload->isValid()) {
559  return false;
560  }
561 
562  $old_filestorename = '';
563  if ($this->exists()) {
564  $old_filestorename = $this->getFilenameOnFilestore();
565  }
566 
567  $originalfilename = $upload->getClientOriginalName();
568  $this->originalfilename = $originalfilename;
569  if (empty($this->title)) {
570  $this->title = htmlspecialchars($this->originalfilename, ENT_QUOTES, 'UTF-8');
571  }
572 
573  $this->upload_time = time();
574  $prefix = $this->filestore_prefix ? : 'file';
575  $prefix = trim($prefix, '/');
576  $filename = elgg_strtolower("$prefix/{$this->upload_time}{$this->originalfilename}");
577  $this->setFilename($filename);
578  $this->filestore_prefix = $prefix;
579 
580  $hook_params = [
581  'file' => $this,
582  'upload' => $upload,
583  ];
584 
585  $uploaded = _elgg_services()->hooks->trigger('upload', 'file', $hook_params);
586  if ($uploaded !== true && $uploaded !== false) {
587  $filestorename = $this->getFilenameOnFilestore();
588  try {
589  $uploaded = $upload->move(pathinfo($filestorename, PATHINFO_DIRNAME), pathinfo($filestorename, PATHINFO_BASENAME));
590  } catch (FileException $ex) {
591  _elgg_services()->logger->error($ex->getMessage());
592  $uploaded = false;
593  }
594  }
595 
596  if ($uploaded) {
597  if ($old_filestorename && $old_filestorename != $this->getFilenameOnFilestore()) {
598  // remove old file
599  unlink($old_filestorename);
600  }
601  $mime_type = $this->detectMimeType(null, $upload->getClientMimeType());
602  $this->setMimeType($mime_type);
603  $this->simpletype = elgg_get_file_simple_type($mime_type);
604  _elgg_services()->events->triggerAfter('upload', 'file', $this);
605  return true;
606  }
607 
608  return false;
609  }
610 
616  public function __sleep() {
617  return array_diff(array_keys(get_object_vars($this)), array(
618  // Don't persist filestore, which contains CONFIG
619  // https://github.com/Elgg/Elgg/issues/9081#issuecomment-152859856
620  'filestore',
621  // a resource
622  'handle',
623  ));
624  }
625 
626 }
setDescription($description)
Set the optional file description.
Definition: ElggFile.php:204
getSize()
Return the size of the file in bytes.
Definition: ElggFile.php:371
elgg module widget elgg state draggable elgg widget handle
Definition: admin.css.php:1269
if(!array_key_exists($filename, $text_files)) $file
$mode
Configure site maintenance mode.
setMetadata($name, $value, $value_type= '', $multiple=false, $owner_guid=0, $access_id=null)
{}
Definition: ElggFile.php:68
write($data)
Write data.
Definition: ElggFile.php:253
if($guid==elgg_get_logged_in_user_guid()) $name
Definition: delete.php:21
setModifiedTime()
Updates modification time of the file and clears stats cache for the file.
Definition: ElggFile.php:346
getFilestoreSize($prefix= '', $container_guid=0)
Return the size of the filestore associated with this file.
Definition: ElggFile.php:113
close()
Close the file and commit changes.
Definition: ElggFile.php:288
seek($position)
Seek a position in the file.
Definition: ElggFile.php:325
$data
Definition: opendd.php:13
$value
Definition: longtext.php:42
eof()
Return a boolean value whether the file handle is at the end of the file.
Definition: ElggFile.php:391
$class
Definition: field.php:20
exists()
Returns if the file exists.
Definition: ElggFile.php:402
if(!$count) $offset
Definition: pagination.php:26
getSimpleType()
Get the simple type of the file.
Definition: ElggFile.php:189
getGUID()
Returns the guid.
$default
Definition: checkbox.php:34
elgg button delete
Definition: admin.css.php:600
getMetadata($name)
{}
Definition: ElggFile.php:58
$length
Definition: excerpt.php:14
elgg_strtolower()
Wrapper function for mb_strtolower().
Definition: mb_wrapper.php:174
save()
Save the file.
Definition: ElggFile.php:489
getModifiedTime()
Returns file modification time.
Definition: ElggFile.php:361
$position
Definition: move.php:10
$params
Definition: login.php:72
getFilenameOnFilestore()
Return the filename of this file as it is/will be stored on the filestore, which may be different to ...
Definition: ElggFile.php:101
grabFile()
Gets the full contents of this file.
Definition: ElggFile.php:278
ui datepicker title
Definition: admin.css.php:662
initializeAttributes()
Set subtype to &#39;file&#39;.
Definition: ElggFile.php:49
$owner_guid
if(!$site) if(!($site instanceof ElggSite)) $site description
setMimeType($mimetype)
Set the mime type of the file.
Definition: ElggFile.php:140
if($categories) $description
Definition: full.php:176
getFilename()
Return the filename.
Definition: ElggFile.php:91
detectMimeType($file=null, $default=null)
Detects mime types based on filename or actual file.
Definition: ElggFile.php:156
read($length, $offset=0)
Read data.
Definition: ElggFile.php:267
tell()
Return the current position of the file.
Definition: ElggFile.php:336
acceptUploadedFile(UploadedFile $upload)
Writes contents of the uploaded file to an instance of ElggFile.
Definition: ElggFile.php:557
getMimeType()
Get the mime type of the file.
Definition: ElggFile.php:127
elgg river item elgg form comment save
elgg_deprecated_notice($msg, $dep_version, $backtrace_level=1)
Log a notice about deprecated use of a function, view, etc.
Definition: elgglib.php:1098
open($mode)
Open the file with the given mode.
Definition: ElggFile.php:218
setFilestore(ElggFilestore $filestore)
Set a filestore.
Definition: ElggFile.php:416
_elgg_services(\Elgg\Di\ServiceProvider $services=null)
Get the global service provider.
Definition: autoloader.php:17
elgg_log($message, $level= 'NOTICE')
Display or log a message.
Definition: elgglib.php:1028
elgg subtext time
getFilestore()
Return a filestore suitable for saving this file.
Definition: ElggFile.php:430
elgg_get_metadata(array $options=array())
Returns metadata.
Definition: metadata.php:164
Detect the MIME type of a file.
$filename
class
Definition: placeholder.php:21
setFilename($name)
Set the filename of this file.
Definition: ElggFile.php:82
size()
Return the size of the file in bytes.
Definition: ElggFile.php:381
$container_guid
http free of to any person obtaining a copy of this software and associated documentation to deal in the Software without including without limitation the rights to use
Definition: MIT-LICENSE.txt:5
transfer($owner_guid, $filename=null)
Transfer a file to a new owner and sets a new filename, copies file contents to a new location...
Definition: ElggFile.php:520
elgg_get_file_simple_type($mime_type)
Returns the category of a file from its MIME type.
Definition: filestore.php:352
__sleep()
Get property names to serialize.
Definition: ElggFile.php:616
$comment owner_guid
Definition: save.php:58