Elgg  Version 6.2
ElggFile.php
Go to the documentation of this file.
1 <?php
2 
4 use Elgg\Exceptions\DomainException as ElggDomainException;
5 use Elgg\Exceptions\InvalidArgumentException as ElggInvalidArgumentException;
7 use Symfony\Component\HttpFoundation\File\Exception\FileException;
8 use Symfony\Component\HttpFoundation\File\UploadedFile;
9 
32 class ElggFile extends ElggObject {
33 
38  private $handle;
39 
45  protected function initializeAttributes() {
46  parent::initializeAttributes();
47 
48  $this->attributes['subtype'] = 'file';
49  }
50 
54  public function __set($name, $value) {
55  switch ($name) {
56  case 'filename':
57  // ensure sanitization
58  $this->setFilename($value);
59  return;
60  }
61 
62  parent::__set($name, $value);
63  }
64 
68  public function __get($name) {
69  switch ($name) {
70  case 'filename':
71  // ensure sanitization
72  return $this->getFilename();
73  }
74 
75  return parent::__get($name);
76  }
77 
85  public function setFilename(string $filename): void {
86  $filename = ltrim(Paths::sanitize($filename, false), '/');
87 
88  parent::__set('filename', $filename);
89  }
90 
96  public function getFilename(): string {
97  $filename = parent::__get('filename');
98  if (empty($filename)) {
99  return '';
100  }
101 
102  return ltrim(Paths::sanitize($filename, false), '/');
103  }
104 
111  public function getFilenameOnFilestore(): string {
112  return $this->getFilestore()->getFilenameOnFilestore($this);
113  }
114 
121  public function getMimeType(): string|false {
122  if ($this->mimetype) {
123  return $this->mimetype;
124  }
125 
126  try {
127  return _elgg_services()->mimetype->getMimeType($this->getFilenameOnFilestore());
128  } catch (ElggInvalidArgumentException $e) {
129  // the file has no file on the filesystem
130  // can happen in tests etc.
131  }
132 
133  return false;
134  }
135 
143  public function setMimeType(string $mimetype): void {
144  $this->mimetype = $mimetype;
145  }
146 
153  public function getSimpleType(): string {
154  if (isset($this->simpletype)) {
155  return $this->simpletype;
156  }
157 
158  return _elgg_services()->mimetype->getSimpleType($this->getMimeType() ?: '');
159  }
160 
171  public function open(string $mode) {
172  if (!$this->getFilename()) {
173  throw new IOException('You must specify a name before opening a file.');
174  }
175 
176  if (!in_array($mode, ['read', 'write', 'append'])) {
177  throw new ElggDomainException("Unrecognized file mode '{$mode}'");
178  }
179 
180  // Open the file handle
181  $this->handle = $this->getFilestore()->open($this, $mode);
182 
183  return $this->handle;
184  }
185 
193  public function write(string $data): int|false {
194  return $this->getFilestore()->write($this->handle, $data);
195  }
196 
205  public function read(int $length, int $offset = 0) {
206  return $this->getFilestore()->read($this->handle, $length, $offset);
207  }
208 
214  public function grabFile(): string|false {
215  return $this->getFilestore()->grabFile($this);
216  }
217 
223  public function close(): bool {
224  if (is_resource($this->handle) && $this->getFilestore()->close($this->handle)) {
225  $this->handle = null;
226 
227  return true;
228  }
229 
230  return false;
231  }
232 
236  public function delete(bool $recursive = true, bool $persistent = null): bool {
237  if (!$this->guid) {
238  return $this->persistentDelete($recursive);
239  }
240 
241  return parent::delete($recursive, $persistent);
242  }
243 
247  protected function persistentDelete(bool $recursive = true): bool {
248  if ($this->guid) {
249  $result = parent::persistentDelete($recursive);
250  if ($result) {
251  $this->getFilestore()->delete($this);
252  }
253 
254  return $result;
255  }
256 
257  return $this->getFilestore()->delete($this);
258  }
259 
267  public function seek(int $position): void {
268  $this->getFilestore()->seek($this->handle, $position);
269  }
270 
276  public function tell(): int {
277  return $this->getFilestore()->tell($this->handle);
278  }
279 
285  public function setModifiedTime(): bool {
286  $filestorename = $this->getFilenameOnFilestore();
287 
288  $modified = touch($filestorename);
289  if ($modified) {
290  clearstatcache(true, $filestorename);
291  } else {
292  elgg_log("Unable to update modified time for {$filestorename}", \Psr\Log\LogLevel::ERROR);
293  }
294 
295  return $modified;
296  }
297 
303  public function getModifiedTime(): int {
304  return filemtime($this->getFilenameOnFilestore());
305  }
306 
313  public function getSize(): int {
314  return $this->getFilestore()->getFileSize($this);
315  }
316 
322  public function eof(): bool {
323  return $this->getFilestore()->eof($this->handle);
324  }
325 
331  public function exists(): bool {
332  return $this->getFilestore()->exists($this);
333  }
334 
340  protected function getFilestore(): \Elgg\Filesystem\Filestore\DiskFilestore {
341  return _elgg_services()->filestore;
342  }
343 
356  public function transfer(int $owner_guid, ?string $filename = null): bool {
357  if ($owner_guid < 1) {
358  return false;
359  }
360 
361  if (!$this->exists()) {
362  return false;
363  }
364 
365  if (empty($filename)) {
366  $filename = $this->getFilename();
367  }
368 
369  $filestorename = $this->getFilenameOnFilestore();
370 
371  $this->owner_guid = $owner_guid;
372  $this->setFilename($filename);
373  $this->open('write');
374  $this->close();
375 
376  return rename($filestorename, $this->getFilenameOnFilestore());
377  }
378 
395  public function acceptUploadedFile(UploadedFile $upload): bool {
396  if (!$upload->isValid()) {
397  return false;
398  }
399 
400  $old_filestorename = '';
401  if ($this->exists()) {
402  $old_filestorename = $this->getFilenameOnFilestore();
403  }
404 
405  $originalfilename = $upload->getClientOriginalName();
406  $this->originalfilename = $originalfilename;
407  if (empty($this->title)) {
408  $this->title = htmlspecialchars($this->originalfilename, ENT_QUOTES, 'UTF-8');
409  }
410 
411  $this->upload_time = time();
412  $prefix = $this->filestore_prefix ?: 'file';
413  $prefix = trim($prefix, '/');
414  $filename = elgg_strtolower("{$prefix}/{$this->upload_time}{$this->originalfilename}");
415  $this->setFilename($filename);
416  $this->filestore_prefix = $prefix;
417 
418  $params = [
419  'file' => $this,
420  'upload' => $upload,
421  ];
422 
423  $uploaded = _elgg_services()->events->triggerResults('upload', 'file', $params);
424  if ($uploaded !== true && $uploaded !== false) {
425  $filestorename = $this->getFilenameOnFilestore();
426  try {
427  $uploaded = $upload->move(pathinfo($filestorename, PATHINFO_DIRNAME), pathinfo($filestorename, PATHINFO_BASENAME));
428  } catch (FileException $ex) {
429  _elgg_services()->logger->error($ex->getMessage());
430  $uploaded = false;
431  }
432  }
433 
434  if ($uploaded) {
435  if ($old_filestorename && $old_filestorename != $this->getFilenameOnFilestore()) {
436  // remove old file
437  unlink($old_filestorename);
438  }
439 
440  try {
441  // try to detect mimetype
442  $mime_type = _elgg_services()->mimetype->getMimeType($this->getFilenameOnFilestore());
443  $this->setMimeType($mime_type);
444  $this->simpletype = _elgg_services()->mimetype->getSimpleType($mime_type);
445  } catch (ElggInvalidArgumentException $e) {
446  // this can fail if the upload events returns true, but the file is not present on the filestore
447  // this happens in a unittest
448  }
449 
450  _elgg_services()->events->triggerAfter('upload', 'file', $this);
451  return true;
452  }
453 
454  return false;
455  }
456 
462  public function __sleep() {
463  return array_diff(array_keys(get_object_vars($this)), [
464  // a resource
465  'handle',
466  ]);
467  }
468 
477  public function canDownload(int $user_guid = 0, bool $default = true): bool {
478  return _elgg_services()->userCapabilities->canDownload($this, $user_guid, $default);
479  }
480 
491  public function getDownloadURL(bool $use_cookie = true, string $expires = '+2 hours'): ?string {
492  $file_svc = new \Elgg\FileService\File();
493  $file_svc->setFile($this);
494  if (!empty($expires)) {
495  $file_svc->setExpires($expires);
496  }
497 
498  $file_svc->setDisposition('attachment');
499  $file_svc->bindSession($use_cookie);
500 
501  $params = [
502  'entity' => $this,
503  'use_cookie' => $use_cookie,
504  'expires' => $expires,
505  ];
506  return _elgg_services()->events->triggerResults('download:url', 'file', $params, $file_svc->getURL());
507  }
508 
520  public function getInlineURL(bool $use_cookie = false, string $expires = ''): ?string {
521  $file_svc = new \Elgg\FileService\File();
522  $file_svc->setFile($this);
523  if (!empty($expires)) {
524  $file_svc->setExpires($expires);
525  }
526 
527  $file_svc->setDisposition('inline');
528  $file_svc->bindSession($use_cookie);
529 
530  $params = [
531  'entity' => $this,
532  'use_cookie' => $use_cookie,
533  'expires' => $expires,
534  ];
535  return _elgg_services()->events->triggerResults('inline:url', 'file', $params, $file_svc->getURL());
536  }
537 }
$mode
Configure site maintenance mode.
if(! $user||! $user->canDelete()) $name
Definition: delete.php:22
$params
Saves global plugin settings.
Definition: save.php:13
$position
Definition: add.php:11
return[ 'admin/delete_admin_notices'=>['access'=> 'admin'], 'admin/menu/save'=>['access'=> 'admin'], 'admin/plugins/activate'=>['access'=> 'admin'], 'admin/plugins/activate_all'=>['access'=> 'admin'], 'admin/plugins/deactivate'=>['access'=> 'admin'], 'admin/plugins/deactivate_all'=>['access'=> 'admin'], 'admin/plugins/set_priority'=>['access'=> 'admin'], 'admin/security/security_txt'=>['access'=> 'admin'], 'admin/security/settings'=>['access'=> 'admin'], 'admin/security/regenerate_site_secret'=>['access'=> 'admin'], 'admin/site/cache/invalidate'=>['access'=> 'admin'], 'admin/site/flush_cache'=>['access'=> 'admin'], 'admin/site/icons'=>['access'=> 'admin'], 'admin/site/set_maintenance_mode'=>['access'=> 'admin'], 'admin/site/set_robots'=>['access'=> 'admin'], 'admin/site/theme'=>['access'=> 'admin'], 'admin/site/unlock_upgrade'=>['access'=> 'admin'], 'admin/site/settings'=>['access'=> 'admin'], 'admin/upgrade'=>['access'=> 'admin'], 'admin/upgrade/reset'=>['access'=> 'admin'], 'admin/user/ban'=>['access'=> 'admin'], 'admin/user/bulk/ban'=>['access'=> 'admin'], 'admin/user/bulk/delete'=>['access'=> 'admin'], 'admin/user/bulk/unban'=>['access'=> 'admin'], 'admin/user/bulk/validate'=>['access'=> 'admin'], 'admin/user/change_email'=>['access'=> 'admin'], 'admin/user/delete'=>['access'=> 'admin'], 'admin/user/login_as'=>['access'=> 'admin'], 'admin/user/logout_as'=>[], 'admin/user/makeadmin'=>['access'=> 'admin'], 'admin/user/resetpassword'=>['access'=> 'admin'], 'admin/user/removeadmin'=>['access'=> 'admin'], 'admin/user/unban'=>['access'=> 'admin'], 'admin/user/validate'=>['access'=> 'admin'], 'annotation/delete'=>[], 'avatar/upload'=>[], 'comment/save'=>[], 'diagnostics/download'=>['access'=> 'admin'], 'entity/chooserestoredestination'=>[], 'entity/delete'=>[], 'entity/mute'=>[], 'entity/restore'=>[], 'entity/subscribe'=>[], 'entity/trash'=>[], 'entity/unmute'=>[], 'entity/unsubscribe'=>[], 'login'=>['access'=> 'logged_out'], 'logout'=>[], 'notifications/mute'=>['access'=> 'public'], 'plugins/settings/remove'=>['access'=> 'admin'], 'plugins/settings/save'=>['access'=> 'admin'], 'plugins/usersettings/save'=>[], 'register'=>['access'=> 'logged_out', 'middleware'=>[\Elgg\Router\Middleware\RegistrationAllowedGatekeeper::class,],], 'river/delete'=>[], 'settings/notifications'=>[], 'settings/notifications/subscriptions'=>[], 'user/changepassword'=>['access'=> 'public'], 'user/requestnewpassword'=>['access'=> 'public'], 'useradd'=>['access'=> 'admin'], 'usersettings/save'=>[], 'widgets/add'=>[], 'widgets/delete'=>[], 'widgets/move'=>[], 'widgets/save'=>[],]
Definition: actions.php:73
if(! $entity instanceof \ElggUser) $data
Definition: attributes.php:13
initializeAttributes()
Set subtype to 'file'.
Definition: ElggFile.php:45
getSize()
Return the size of the file in bytes.
Definition: ElggFile.php:313
acceptUploadedFile(UploadedFile $upload)
Writes contents of the uploaded file to an instance of ElggFile.
Definition: ElggFile.php:395
open(string $mode)
Open the file with the given mode.
Definition: ElggFile.php:171
grabFile()
Gets the full contents of this file.
Definition: ElggFile.php:214
setFilename(string $filename)
Set the filename of this file.
Definition: ElggFile.php:85
persistentDelete(bool $recursive=true)
{Permanently delete the entity from the database.If true (default) then all entities which are owned ...
Definition: ElggFile.php:247
getFilenameOnFilestore()
Return the filename of this file as it is/will be stored on the filestore, which may be different to ...
Definition: ElggFile.php:111
getModifiedTime()
Returns file modification time.
Definition: ElggFile.php:303
__sleep()
Get property names to serialize.
Definition: ElggFile.php:462
write(string $data)
Write data.
Definition: ElggFile.php:193
getSimpleType()
Get the simple type of the file.
Definition: ElggFile.php:153
exists()
Returns if the file exists.
Definition: ElggFile.php:331
getMimeType()
Get the mime type of the file.
Definition: ElggFile.php:121
__get($name)
Get an attribute or metadata value.If the name matches an attribute, the attribute is returned....
Definition: ElggFile.php:68
__set($name, $value)
Set an attribute or metadata value for this entity.Anything that is not an attribute is saved as meta...
Definition: ElggFile.php:54
setMimeType(string $mimetype)
Set the mime type of the file.
Definition: ElggFile.php:143
getInlineURL(bool $use_cookie=false, string $expires='')
Returns file's URL for inline display Suitable for displaying cacheable resources,...
Definition: ElggFile.php:520
read(int $length, int $offset=0)
Read data.
Definition: ElggFile.php:205
getFilestore()
Return the system filestore based on dataroot.
Definition: ElggFile.php:340
getFilename()
Return the filename.
Definition: ElggFile.php:96
setModifiedTime()
Updates modification time of the file and clears stats cache for the file.
Definition: ElggFile.php:285
transfer(int $owner_guid, ?string $filename=null)
Transfer a file to a new owner and sets a new filename, copies file contents to a new location.
Definition: ElggFile.php:356
canDownload(int $user_guid=0, bool $default=true)
Checks the download permissions for the file.
Definition: ElggFile.php:477
seek(int $position)
Seek a position in the file.
Definition: ElggFile.php:267
eof()
Return a boolean value whether the file handle is at the end of the file.
Definition: ElggFile.php:322
getDownloadURL(bool $use_cookie=true, string $expires='+2 hours')
Returns file's download URL.
Definition: ElggFile.php:491
close()
Close the file and commit changes.
Definition: ElggFile.php:223
tell()
Return the current position of the file.
Definition: ElggFile.php:276
Exception thrown if a value does not adhere to a defined valid data domain.
An IO Exception, throw when an IO Exception occurs.
Definition: IOException.php:12
Exception thrown if an argument is not of the expected type.
Find Elgg and project paths.
Definition: Paths.php:8
$owner_guid
elgg_log($message, $level=\Psr\Log\LogLevel::NOTICE)
Log a message.
Definition: elgglib.php:88
_elgg_services()
Get the global service provider.
Definition: elgglib.php:353
$value
Definition: generic.php:51
$default
Definition: checkbox.php:30
$user_guid
Definition: login_as.php:10
$persistent
Definition: login_as.php:21
elgg_strtolower()
Wrapper function for mb_strtolower().
Definition: mb_wrapper.php:125
if(! $item instanceof \ElggEntity) $length
Definition: excerpt.php:16
if(empty($count)) $offset
Definition: pagination.php:26
if(parse_url(elgg_get_site_url(), PHP_URL_PATH) !=='/') if(file_exists(elgg_get_root_path() . 'robots.txt'))
Set robots.txt.
Definition: robots.php:10
$expires