Elgg  Version master
ElggFile.php
Go to the documentation of this file.
1 <?php
2 
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 
240  public function delete(bool $follow_symlinks = true): bool {
241  $result = $this->getFilestore()->delete($this, $follow_symlinks);
242 
243  if ($this->getGUID() && $result) {
244  $result = parent::delete();
245  }
246 
247  return $result;
248  }
249 
257  public function seek(int $position): void {
258  $this->getFilestore()->seek($this->handle, $position);
259  }
260 
266  public function tell(): int {
267  return $this->getFilestore()->tell($this->handle);
268  }
269 
275  public function setModifiedTime(): bool {
276  $filestorename = $this->getFilenameOnFilestore();
277 
278  $modified = touch($filestorename);
279  if ($modified) {
280  clearstatcache(true, $filestorename);
281  } else {
282  elgg_log("Unable to update modified time for {$filestorename}", 'ERROR');
283  }
284 
285  return $modified;
286  }
287 
293  public function getModifiedTime(): int {
294  return filemtime($this->getFilenameOnFilestore());
295  }
296 
303  public function getSize(): int {
304  return $this->getFilestore()->getFileSize($this);
305  }
306 
312  public function eof(): bool {
313  return $this->getFilestore()->eof($this->handle);
314  }
315 
321  public function exists(): bool {
322  return $this->getFilestore()->exists($this);
323  }
324 
330  protected function getFilestore(): \Elgg\Filesystem\Filestore\DiskFilestore {
331  return _elgg_services()->filestore;
332  }
333 
346  public function transfer(int $owner_guid, string $filename = null): bool {
347  if ($owner_guid < 1) {
348  return false;
349  }
350 
351  if (!$this->exists()) {
352  return false;
353  }
354 
355  if (empty($filename)) {
356  $filename = $this->getFilename();
357  }
358 
359  $filestorename = $this->getFilenameOnFilestore();
360 
361  $this->owner_guid = $owner_guid;
362  $this->setFilename($filename);
363  $this->open('write');
364  $this->close();
365 
366  return rename($filestorename, $this->getFilenameOnFilestore());
367  }
368 
385  public function acceptUploadedFile(UploadedFile $upload): bool {
386  if (!$upload->isValid()) {
387  return false;
388  }
389 
390  $old_filestorename = '';
391  if ($this->exists()) {
392  $old_filestorename = $this->getFilenameOnFilestore();
393  }
394 
395  $originalfilename = $upload->getClientOriginalName();
396  $this->originalfilename = $originalfilename;
397  if (empty($this->title)) {
398  $this->title = htmlspecialchars($this->originalfilename, ENT_QUOTES, 'UTF-8');
399  }
400 
401  $this->upload_time = time();
402  $prefix = $this->filestore_prefix ?: 'file';
403  $prefix = trim($prefix, '/');
404  $filename = elgg_strtolower("{$prefix}/{$this->upload_time}{$this->originalfilename}");
405  $this->setFilename($filename);
406  $this->filestore_prefix = $prefix;
407 
408  $params = [
409  'file' => $this,
410  'upload' => $upload,
411  ];
412 
413  $uploaded = _elgg_services()->events->triggerResults('upload', 'file', $params);
414  if ($uploaded !== true && $uploaded !== false) {
415  $filestorename = $this->getFilenameOnFilestore();
416  try {
417  $uploaded = $upload->move(pathinfo($filestorename, PATHINFO_DIRNAME), pathinfo($filestorename, PATHINFO_BASENAME));
418  } catch (FileException $ex) {
419  _elgg_services()->logger->error($ex->getMessage());
420  $uploaded = false;
421  }
422  }
423 
424  if ($uploaded) {
425  if ($old_filestorename && $old_filestorename != $this->getFilenameOnFilestore()) {
426  // remove old file
427  unlink($old_filestorename);
428  }
429 
430  try {
431  // try to detect mimetype
432  $mime_type = _elgg_services()->mimetype->getMimeType($this->getFilenameOnFilestore());
433  $this->setMimeType($mime_type);
434  $this->simpletype = _elgg_services()->mimetype->getSimpleType($mime_type);
435  } catch (ElggInvalidArgumentException $e) {
436  // this can fail if the upload events returns true, but the file is not present on the filestore
437  // this happens in a unittest
438  }
439 
440  _elgg_services()->events->triggerAfter('upload', 'file', $this);
441  return true;
442  }
443 
444  return false;
445  }
446 
452  public function __sleep() {
453  return array_diff(array_keys(get_object_vars($this)), [
454  // a resource
455  'handle',
456  ]);
457  }
458 
467  public function canDownload(int $user_guid = 0, bool $default = true): bool {
468  return _elgg_services()->userCapabilities->canDownload($this, $user_guid, $default);
469  }
470 
481  public function getDownloadURL(bool $use_cookie = true, string $expires = '+2 hours'): ?string {
482  $file_svc = new \Elgg\FileService\File();
483  $file_svc->setFile($this);
484  if (!empty($expires)) {
485  $file_svc->setExpires($expires);
486  }
487 
488  $file_svc->setDisposition('attachment');
489  $file_svc->bindSession($use_cookie);
490 
491  $params = [
492  'entity' => $this,
493  'use_cookie' => $use_cookie,
494  'expires' => $expires,
495  ];
496  return _elgg_services()->events->triggerResults('download:url', 'file', $params, $file_svc->getURL());
497  }
498 
510  public function getInlineURL(bool $use_cookie = false, string $expires = ''): ?string {
511  $file_svc = new \Elgg\FileService\File();
512  $file_svc->setFile($this);
513  if (!empty($expires)) {
514  $file_svc->setExpires($expires);
515  }
516 
517  $file_svc->setDisposition('inline');
518  $file_svc->bindSession($use_cookie);
519 
520  $params = [
521  'entity' => $this,
522  'use_cookie' => $use_cookie,
523  'expires' => $expires,
524  ];
525  return _elgg_services()->events->triggerResults('inline:url', 'file', $params, $file_svc->getURL());
526  }
527 }
$default
Definition: checkbox.php:30
getSize()
Return the size of the file in bytes.
Definition: ElggFile.php:303
$user_guid
Definition: login_as.php:10
$params
Saves global plugin settings.
Definition: save.php:13
$mode
Configure site maintenance mode.
$position
Definition: add.php:11
__set($name, $value)
Definition: ElggFile.php:54
An IO Exception, throw when an IO Exception occurs.
Definition: IOException.php:12
if(!$user||!$user->canDelete()) $name
Definition: delete.php:22
if(!$item instanceof\ElggEntity) $length
Definition: excerpt.php:16
setModifiedTime()
Updates modification time of the file and clears stats cache for the file.
Definition: ElggFile.php:275
close()
Close the file and commit changes.
Definition: ElggFile.php:223
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition plus the scripts used to control compilation and installation of the executable as a special the source code distributed need not include anything that is normally and so on of the operating system on which the executable unless that component itself accompanies the executable If distribution of executable or object code is made by offering access to copy from a designated then offering equivalent access to copy the source code from the same place counts as distribution of the source even though third parties are not compelled to copy the source along with the object code You may not or distribute the Program except as expressly provided under this License Any attempt otherwise to sublicense or distribute the Program is void
Definition: LICENSE.txt:215
if(empty($count)) $offset
Definition: pagination.php:26
eof()
Return a boolean value whether the file handle is at the end of the file.
Definition: ElggFile.php:312
exists()
Returns if the file exists.
Definition: ElggFile.php:321
getSimpleType()
Get the simple type of the file.
Definition: ElggFile.php:153
getGUID()
Returns the guid.
seek(int $position)
Seek a position in the file.
Definition: ElggFile.php:257
getInlineURL(bool $use_cookie=false, string $expires= '')
Returns file&#39;s URL for inline display Suitable for displaying cacheable resources, such as user avatars.
Definition: ElggFile.php:510
elgg_strtolower()
Wrapper function for mb_strtolower().
Definition: mb_wrapper.php:161
getModifiedTime()
Returns file modification time.
Definition: ElggFile.php:293
__get($name)
Definition: ElggFile.php:68
$value
Definition: generic.php:51
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
setFilename(string $filename)
Set the filename of this file.
Definition: ElggFile.php:85
grabFile()
Gets the full contents of this file.
Definition: ElggFile.php:214
getFilestore()
Return the system filestore based on dataroot.
Definition: ElggFile.php:330
if(!$entity instanceof\ElggUser) $data
Definition: attributes.php:13
canDownload(int $user_guid=0, bool $default=true)
Checks the download permissions for the file.
Definition: ElggFile.php:467
initializeAttributes()
Set subtype to &#39;file&#39;.
Definition: ElggFile.php:45
$owner_guid
getFilename()
Return the filename.
Definition: ElggFile.php:96
elgg_log($message, $level=\Psr\Log\LogLevel::NOTICE)
Log a message.
Definition: elgglib.php:86
read(int $length, int $offset=0)
Read data.
Definition: ElggFile.php:205
tell()
Return the current position of the file.
Definition: ElggFile.php:266
acceptUploadedFile(UploadedFile $upload)
Writes contents of the uploaded file to an instance of ElggFile.
Definition: ElggFile.php:385
getMimeType()
Get the mime type of the file.
Definition: ElggFile.php:121
write(string $data)
Write data.
Definition: ElggFile.php:193
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:346
$expires
getDownloadURL(bool $use_cookie=true, string $expires= '+2 hours')
Returns file&#39;s download URL.
Definition: ElggFile.php:481
setMimeType(string $mimetype)
Set the mime type of the file.
Definition: ElggFile.php:143
_elgg_services()
Get the global service provider.
Definition: elgglib.php:346
open(string $mode)
Open the file with the given mode.
Definition: ElggFile.php:171
__sleep()
Get property names to serialize.
Definition: ElggFile.php:452