ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilObjFile.php
Go to the documentation of this file.
1 <?php
25 
34 {
36  use ilObjFileUsages;
38  use ilObjFileNews;
40 
41  public const MODE_FILELIST = "filelist";
42  public const MODE_OBJECT = "object";
43 
47  protected $implementation;
48 
52  protected $page_count = 0;
56  protected $rating = false;
60  protected $log;
61 
62  // ABSTRACT
66  protected $filename = '';
70  protected $filetype = '';
74  protected $filesize;
78  protected $version = 1;
82  protected $max_version = 1;
86  protected $action;
87  // ABSTRACT
88 
92  protected $resource_id;
93 
97  public $mode = self::MODE_OBJECT;
101  protected $manager;
105  protected $upload;
109  protected $stakeholder;
110 
116  public function __construct(int $a_id = 0, bool $a_call_by_reference = true)
117  {
118  global $DIC;
122  $this->manager = $DIC->resourceStorage()->manage();
123  $this->stakeholder = new ilObjFileStakeholder($DIC->user()->getId());
124  $this->upload = $DIC->upload();
125  $this->version = 0;
126  $this->max_version = 0;
127  $this->log = ilLoggerFactory::getLogger('file');
128 
129  parent::__construct($a_id, $a_call_by_reference);
130  }
131 
132  protected function initImplementation() : void
133  {
134  if ($this->resource_id && ($id = $this->manager->find($this->resource_id)) !== null) {
135  $resource = $this->manager->getResource($id);
136  $this->implementation = new ilObjFileImplementationStorage(
137  $resource,
138  (int) $this->getId()
139  );
140  $this->setMaxVersion($resource->getMaxRevision());
141  $this->setVersion($resource->getMaxRevision());
142  } else {
143  $this->implementation = new ilObjFileImplementationLegacy(
144  (int) $this->getId(),
145  (int) $this->getVersion(),
146  (string) $this->getFileName()
147  );
148  $s = new FilePathSanitizer($this);
149  $s->sanitizeIfNeeded();
150  }
151  }
152 
153  private function updateObjectFromRevision(Revision $r, bool $create_previews = true) : void
154  {
155  $this->setTitle($r->getTitle());
156  $this->setFileName($r->getInformation()->getTitle());
157  $this->setVersion($r->getVersionNumber());
158  $this->setMaxVersion($r->getVersionNumber());
159  $this->setFileSize($r->getInformation()->getSize());
160  $this->setFileType($r->getInformation()->getMimeType());
161  $this->update();
162  if ($create_previews) {
163  $this->createPreview(true);
164  }
165  }
166 
167  private function appendSuffixToTitle(string $title, string $filename) : string
168  {
169  // bugfix mantis 0026160 && 0030391 and 0032340
170  $title_info = new SplFileInfo($title);
171  $filename_info = new SplFileInfo($filename);
172 
173  $filename = str_replace('.' . $title_info->getExtension(), '', $title_info->getPathname());
174  $extension = $filename_info->getExtension();
175 
176  return $this->secure($filename . '.' . $extension);
177  }
178 
182  public function appendStream(FileStream $stream, string $title) : int
183  {
184  if ($this->getResourceId() && $i = $this->manager->find($this->getResourceId())) {
185  $revision = $this->manager->appendNewRevisionFromStream($i, $stream, $this->stakeholder, $title);
186  } else {
187  $i = $this->manager->stream($stream, $this->stakeholder, $title);
188  $revision = $this->manager->getCurrentRevision($i);
189  $this->setResourceId($i->serialize());
190  $this->initImplementation();
191  }
192  $this->updateObjectFromRevision($revision);
193 
194  return $revision->getVersionNumber();
195  }
196 
200  public function appendUpload(UploadResult $result, string $title) : int
201  {
202  $title = $this->appendSuffixToTitle($title, $result->getName());
203  if ($this->getResourceId() && $i = $this->manager->find($this->getResourceId())) {
204  $revision = $this->manager->appendNewRevision($i, $result, $this->stakeholder, $title);
205  } else {
206  $i = $this->manager->upload($result, $this->stakeholder, $title);
207  $revision = $this->manager->getCurrentRevision($i);
208  $this->setResourceId($i->serialize());
209  $this->initImplementation();
210  }
213  }
214  $this->updateObjectFromRevision($revision);
215 
216  return $revision->getVersionNumber();
217  }
218 
222  public function replaceWithStream(FileStream $stream, string $title) : int
223  {
224  if ($this->getResourceId() && $i = $this->manager->find($this->getResourceId())) {
225  $revision = $this->manager->replaceWithStream($i, $stream, $this->stakeholder, $title);
226  } else {
227  throw new LogicException('only files with existing resource and revision can be replaced');
228  }
229  $this->updateObjectFromRevision($revision);
230 
231  return $revision->getVersionNumber();
232  }
233 
237  public function replaceWithUpload(UploadResult $result, string $title) : int
238  {
239  $title = $this->appendSuffixToTitle($title, $result->getName());
240  if ($this->getResourceId() && $i = $this->manager->find($this->getResourceId())) {
241  $revision = $this->manager->replaceWithUpload($i, $result, $this->stakeholder, $title);
242  } else {
243  throw new LogicException('only files with existing resource and revision can be replaced');
244  }
247  }
248  $this->updateObjectFromRevision($revision);
249 
250  return $revision->getVersionNumber();
251  }
252 
258  public function getFile($a_hist_entry_id = null)
259  {
260  return $this->implementation->getFile($a_hist_entry_id);
261  }
262 
263  public function getDirectory($a_version = 0)
264  {
265  return $this->implementation->getDirectory($a_version);
266  }
267 
268  public function getVersion()
269  {
270  return $this->version;
271  }
272 
273  public function setVersion($a_version)
274  {
275  $this->version = $a_version;
276  }
277 
281  public function getFileName()
282  {
283  return $this->filename;
284  }
285 
289  public function setFileName($a_name)
290  {
291  $this->filename = $a_name;
292  }
293 
297  public function setRating($a_value)
298  {
299  $this->rating = (bool) $a_value;
300  }
301 
306  public function setResourceId(?string $resource_id) : ilObjFile
307  {
308  $this->resource_id = $resource_id;
309  return $this;
310  }
311 
312  public function getResourceId() : ?string
313  {
314  return $this->resource_id ?? '-';
315  }
316 
317  public function getStorageID() : ?string
318  {
319  return $this->implementation->getStorageID();
320  }
321 
325  public function getMode()
326  {
327  return $this->mode;
328  }
329 
333  public function setMode($a_mode)
334  {
335  $this->mode = $a_mode;
336  }
337 
338  public function getFileSize()
339  {
340  return $this->filesize;
341  }
342 
346  public function setFileSize($a_size)
347  {
348  $this->filesize = $a_size;
349  }
350 
354  public function getFileType()
355  {
356  return $this->filetype;
357  }
358 
362  public function setFileType($a_type)
363  {
364  $this->filetype = $a_type;
365  }
366 
370  public function hasRating()
371  {
372  return $this->rating;
373  }
374 
375  public function getMaxVersion()
376  {
377  return $this->max_version;
378  }
379 
380  public function setMaxVersion($a_max_version)
381  {
382  $this->max_version = $a_max_version;
383  }
384 
388  public function getPageCount()
389  {
390  return $this->page_count;
391  }
392 
396  public function setPageCount($page_count)
397  {
398  $this->page_count = $page_count;
399  }
400 
405  public function getAction()
406  {
407  return $this->action;
408  }
409 
414  public function setAction($a_action)
415  {
416  $this->action = $a_action;
417  }
418 
419  public function handleChangedObjectTitle(string $new_title)
420  {
421  $this->setTitle($new_title);
422  $this->implementation->handleChangedObjectTitle($new_title);
423  }
424 
425 
426  // CRUD
427 
431  protected function doCreate($a_upload = false)
432  {
433  $this->createProperties($a_upload);
434  $this->notifyCreation($this->getId(), $this->getDescription());
435  }
436 
437  protected function doRead()
438  {
439  global $DIC;
444  $q = "SELECT * FROM file_data WHERE file_id = %s";
445  $r = $DIC->database()->queryF($q, ['integer'], [$this->getId()]);
446  $row = $r->fetchObject();
447 
448  $this->setFileName($this->secure($row->file_name ?? ''));
449  $this->setFileType($row->file_type);
450  $this->setFileSize($row->file_size);
451  $this->setVersion($row->version ? $row->version : 1);
452  $this->setMaxVersion($row->max_version ? $row->max_version : 1);
453  $this->setMode($row->f_mode);
454  $this->setRating($row->rating);
455  $this->setPageCount($row->page_count);
456  $this->setPageCount($row->page_count);
457  $this->setResourceId($row->rid);
458 
459  $this->initImplementation();
460  }
461 
462  protected function doCloneObject($new_object, $a_target_id, $a_copy_id = 0)
463  {
467  $this->cloneMetaData($new_object);
468 
469  // object created now copy other settings
470  $this->db->manipulateF(
471  "INSERT INTO file_data (file_id, file_name, file_type, file_size, version, rating, f_mode) VALUES (%s, %s, %s, %s, %s, %s, %s)",
472  [
473  'integer', // file_id
474  'text', // file_name
475  'text', // file_type
476  'integer', // file_size
477  'integer', // version
478  'integer', // rating
479  'integer' // f_mode
480  ],
481  [
482  (int) $new_object->getId(),
483  $this->getFileName(),
484  $this->getFileType(),
485  (int) $this->getFileSize(),
486  (int) $this->getVersion(),
487  (int) $this->hasRating(),
488  (int) $this->getMode()
489  ]
490  );
491 
492  // Copy Resource
493  if ($this->resource_id
494  && ($identification = $this->manager->find($this->resource_id)) instanceof ResourceIdentification) {
495  $new_resource_identification = $this->manager->clone($identification);
496  $new_current_revision = $this->manager->getCurrentRevision($new_resource_identification);
497  $new_object->setResourceId($new_resource_identification->serialize());
498  $new_object->initImplementation();
499  $new_object->updateObjectFromRevision($new_current_revision, false); // Previews are already copied in 453
500  $new_object->setTitle($this->getTitle()); // see https://mantis.ilias.de/view.php?id=31375
501  $new_object->update();
502  } else {
503  // migrate
504  global $DIC;
505  $migration = new ilFileObjectToStorageMigrationRunner(
506  $DIC->fileSystem()->storage(),
507  $DIC->database(),
508  rtrim(CLIENT_DATA_DIR, "/") . '/ilFile/migration_log.csv'
509  );
510  $migration->setMigrateToNewObjectId((int) $new_object->getId());
511  $migration->migrate(new ilFileObjectToStorageDirectory($this->getId(), $this->getDirectory()));
512  }
513 
514  // copy all previews
515  ilPreview::copyPreviews($this->getId(), $new_object->getId());
516 
517  // Copy learning progress settings
518  $obj_settings = new ilLPObjSettings($this->getId());
519  $obj_settings->cloneSettings($new_object->getId());
520  unset($obj_settings);
521 
522  return $new_object;
523  }
524 
525  protected function doUpdate()
526  {
527  global $DIC;
528 
529  $a_columns = $this->getArrayForDatabase();
530  $DIC->database()->update('file_data', $a_columns, [
531  'file_id' => [
532  'integer',
533  $this->getId(),
534  ],
535  ]);
536 
537  // update metadata with the current file version
538  $meta_version_column = ['meta_version' => ['integer', (int) $this->getVersion()]];
539  $DIC->database()->update('il_meta_lifecycle', $meta_version_column, [
540  'rbac_id' => [
541  'integer',
542  $this->getId(),
543  ],
544  ]);
545 
546  $this->notifyUpdate($this->getId(), $this->getDescription());
547 
548  return true;
549  }
550 
551  protected function beforeUpdate()
552  {
553  // no meta data handling for file list files
554  if ($this->getMode() != self::MODE_FILELIST) {
555  $this->updateMetaData();
556  }
557 
558  return true;
559  }
560 
561  protected function beforeDelete()
562  {
563  // check, if file is used somewhere
564  $usages = $this->getUsages();
565  if (count($usages) == 0) {
566  return true;
567  }
568 
569  return false;
570  }
571 
572  protected function doDelete()
573  {
574  global $DIC;
575 
576  // delete file data entry
577  $DIC->database()->manipulateF("DELETE FROM file_data WHERE file_id = %s", ['integer'], [$this->getId()]);
578 
579  // delete history entries
581 
582  // delete meta data
583  if ($this->getMode() != self::MODE_FILELIST) {
584  $this->deleteMetaData();
585  }
586 
587  // delete preview
588  $this->deletePreview();
589 
590  // delete resource
591  $identification = $this->getResourceId();
592  if ($identification && $identification != '-') {
593  $resource = $this->manager->find($identification);
594  if ($resource !== null) {
595  $this->manager->remove($resource, $this->stakeholder);
596  }
597  }
598  }
599 
603  private function getArrayForDatabase() : array
604  {
605  return [
606  'file_id' => ['integer', $this->getId()],
607  'file_name' => ['text', $this->getFileName()],
608  'file_type' => ['text', $this->getFileType()],
609  'file_size' => ['integer', (int) $this->getFileSize()],
610  'version' => ['integer', (int) $this->getVersion()],
611  'max_version' => ['integer', (int) $this->getMaxVersion()],
612  'f_mode' => ['text', $this->getMode()],
613  'page_count' => ['text', $this->getPageCount()],
614  'rating' => ['integer', $this->hasRating()],
615  'rid' => ['text', $this->resource_id ?? ''],
616  ];
617  }
618 
619  public function initType()
620  {
621  $this->type = "file";
622  }
623 
624  public function createDirectory()
625  {
626  // we no longer create directories
627  }
628 
629  public function raiseUploadError($raise = false)
630  {
631  // we no longer support that
632  }
633 
634  // Upload Handling
635  public function replaceFile($a_upload_file, $a_filename)
636  {
637  return null;
638  }
639 
640  private function prepareUpload() : void
641  {
642  if (true !== $this->upload->hasBeenProcessed()) {
643  if (defined('PATH_TO_GHOSTSCRIPT') && PATH_TO_GHOSTSCRIPT !== "") {
644  $this->upload->register(new ilCountPDFPagesPreProcessors());
645  }
646 
647  $this->upload->process();
648  }
649  }
650 
656  public function getUploadFile($a_upload_file, string $title, bool $a_prevent_preview = false) : bool
657  {
658  $this->prepareUpload();
659 
660  $results = $this->upload->getResults();
661  $upload = $results[$a_upload_file];
662 
663  $this->appendUpload($upload, $title);
664 
665  return true;
666  }
667 
672  public function isHidden()
673  {
674  return ilObjFileAccess::_isFileHidden($this->getTitle());
675  }
676 
681  public function clearDataDirectory()
682  {
683  $this->implementation->clearDataDirectory();
684  }
685 
690  public function deleteVersions($a_hist_entry_ids = null)
691  {
692  $this->implementation->deleteVersions($a_hist_entry_ids);
693  }
694 
699  public function sendFile($a_hist_entry_id = null) : void
700  {
701  $this->implementation->sendFile($a_hist_entry_id);
702  }
703 
708  public function isInline()
709  {
710  return ilObjFileAccess::_isFileInline($this->getTitle());
711  }
712 
717  public function export(string $target_dir) : void
718  {
719  $this->implementation->export($target_dir);
720  }
721 
730  public function storeUnzipedFile($a_upload_file, $a_filename)
731  {
732  $this->setVersion($this->getVersion() + 1);
733 
734  if (@!is_dir($this->getDirectory($this->getVersion()))) {
735  ilUtil::makeDir($this->getDirectory($this->getVersion()));
736  }
737 
738  $file = $this->getDirectory($this->getVersion()) . "/" . $a_filename;
739 
740  $file = ilFileUtils::getValidFilename($file);
741 
742  ilFileUtils::rename($a_upload_file, $file);
743 
744  // create preview
745  $this->createPreview();
746  }
747 
752  public function getVersions($version_ids = null) : array
753  {
754  return $this->implementation->getVersions($version_ids);
755  }
756 
761  public function rollback(int $version_id) : void
762  {
763  if ($this->getResourceId() && $i = $this->manager->find($this->getResourceId())) {
764  $this->manager->rollbackRevision($i, $version_id);
765  $latest_revision = $this->manager->getCurrentRevision($i);
766  $this->updateObjectFromRevision($latest_revision);
767  } else {
768  throw new LogicException('only files with existing resource and revision can be replaced');
769  }
770  }
771 
778  public function checkFileExtension($new_filename, $new_title)
779  {
780  $fileExtension = ilObjFileAccess::_getFileExtension($new_filename);
781  $titleExtension = ilObjFileAccess::_getFileExtension($new_title);
782  if ($titleExtension != $fileExtension && strlen($fileExtension) > 0) {
783  // remove old extension
784  $pi = pathinfo($this->getFileName());
785  $suffix = $pi["extension"];
786  if ($suffix != "") {
787  if (substr($new_title, strlen($new_title) - strlen($suffix) - 1) == "." . $suffix) {
788  $new_title = substr($new_title, 0, strlen($new_title) - strlen($suffix) - 1);
789  }
790  }
791  $new_title .= '.' . $fileExtension;
792  }
793 
794  return $new_title;
795  }
796 
801  public function getFileExtension()
802  {
803  return $this->implementation->getFileExtension();
804  }
805 }
setFileType($a_type)
Class ilObjFileStakeholder.
Class ilFileObjectToStorageDirectory.
static _isFileInline($a_file_name)
Returns true, if the specified file shall be displayed inline in the browser.
Class ilObjFileImplementationLegacy.
Class ilObjFileImplementationStorage.
setFileName($a_name)
$result
setMode($a_mode)
Interface ilObjFileImplementationInterface.
replaceWithUpload(UploadResult $result, string $title)
raiseUploadError($raise=false)
static _isFileHidden($a_file_name)
Returns true, if a file with the specified name, is usually hidden from the user. ...
static _getFileExtension($a_file_name)
Gets the file extension of the specified file name.
trait ilObjFileMetadata
Trait ilObjFileMetadata.
getFile($a_hist_entry_id=null)
appendSuffixToTitle(string $title, string $filename)
storeUnzipedFile($a_upload_file, $a_filename)
storeUnzipedFile Stores Files unzipped from uploaded archive in filesystem
rollback(int $version_id)
Makes the specified version the current one.
setVersion($a_version)
getDirectory($a_version=0)
updateObjectFromRevision(Revision $r, bool $create_previews=true)
setFileSize($a_size)
doCreate($a_upload=false)
appendUpload(UploadResult $result, string $title)
checkFileExtension($new_filename, $new_title)
static rename($a_source, $a_target)
Rename a file.
replaceFile($a_upload_file, $a_filename)
const CLIENT_DATA_DIR
Definition: constants.php:44
doCloneObject($new_obj, $a_target_id, $a_copy_id=null)
appendStream(FileStream $stream, string $title)
getUploadFile($a_upload_file, string $title, bool $a_prevent_preview=false)
This Method is used to append a fileupload by it&#39;s POST-name to the current ilObjFile ...
getId()
get object id public
__construct($a_id=0, $a_reference=true)
Constructor public.
setAction($a_action)
global $DIC
Definition: goto.php:24
const MODE_FILELIST
sendFile($a_hist_entry_id=null)
export(string $target_dir)
setTitle($a_title)
$results
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
setMaxVersion($a_max_version)
static copyPreviews($a_src_id, $a_dest_id)
Copies the preview images from one preview to a new preview object.
const MODE_OBJECT
deleteVersions($a_hist_entry_ids=null)
trait ilObjFileSecureString
Trait ilObjFileSecureString.
notifyUpdate(int $obj_id, string $additional_message=null)
replaceWithStream(FileStream $stream, string $title)
__construct(Container $dic, ilPlugin $plugin)
notifyCreation(int $obj_id, string $additional_message=null)
setPageCount($page_count)
static _removeEntriesForObject($a_obj_id)
remove all history entries for an object
Class ilCountPDFPagesPreProcessors.
static getLogger($a_component_id)
Get component logger.
createProperties($a_upload=false)
The basic properties of a file object are stored in table object_data.
setResourceId(?string $resource_id)
handleChangedObjectTitle(string $new_title)
Interface FileStream The base interface for all filesystem streams.
Definition: FileStream.php:17
getVersions($version_ids=null)
setRating($a_value)
static getValidFilename($a_filename)
Get valid filename.
$i
Definition: metadata.php:24
trait ilObjFileNews
Trait ilObjFileNews.
cloneMetaData($target_obj)