ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilObjFile.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
8 
9 require_once("Services/Object/classes/class.ilObject2.php");
10 require_once('Modules/File/classes/class.ilFSStorageFile.php');
11 
21 class ilObjFile extends ilObject2
22 {
24  const MODE_FILELIST = "filelist";
25  const MODE_OBJECT = "object";
33  protected $filename = '';
37  protected $filetype = '';
41  protected $filemaxsize = "20000000"; // not used yet
45  protected $filesize;
53  public $mode = self::MODE_OBJECT;
57  protected $page_count = 0;
61  protected $rating = false;
65  private $file_storage = null;
69  protected $log = null;
73  protected $version = 1;
77  protected $max_version = 1;
81  protected $action = null;
85  protected $rollback_version = null;
89  protected $rollback_user_id = null;
90 
91 
98  public function __construct($a_id = 0, $a_call_by_reference = true)
99  {
100  $this->version = 0;
101  $this->max_version = 0;
102  $this->raise_upload_error = true;
103 
104  $this->log = ilLoggerFactory::getLogger('file');
105 
106  parent::__construct($a_id, $a_call_by_reference);
107 
108  if ($this->getId()) {
109  $this->initFileStorage();
110  }
111  }
112 
113 
114  public function initType()
115  {
116  $this->type = "file";
117  }
118 
119 
125  protected function doCreate($a_upload = false)
126  {
127  $this->createProperties($a_upload);
128  }
129 
130 
138  public function createProperties($a_upload = false)
139  {
140  global $DIC;
141 
142  // Create file directory
143  $this->initFileStorage();
144  $this->file_storage->create();
145 
146  if ($a_upload) {
147  return true;
148  }
149 
150  // not upload mode
151  ilHistory::_createEntry($this->getId(), "create", $this->getFileName() . ",1" . ",1");
152  $this->addNewsNotification("file_created");
153 
154  // New Item
155  $default_visibility = ilNewsItem::_getDefaultVisibilityForRefId($_GET['ref_id']);
156  if ($default_visibility == "public") {
157  ilBlockSetting::_write("news", "public_notifications", 1, 0, $this->getId());
158  }
159 
160  // log creation
161  $this->log->debug("ilObjFile::createProperties, ID: " . $this->getId() . ", Name: "
162  . $this->getFileName() . ", Type: " . $this->getFileType() . ", Size: "
163  . $this->getFileSize() . ", Mode: " . $this->getMode() . ", Name(Bytes): "
164  . implode(":", ilStr::getBytesForString($this->getFileName())));
165  $this->log->logStack(ilLogLevel::DEBUG);
166 
167  $DIC->database()->insert('file_data', $this->getArrayForDatabase());
168 
169  //add metadata to database
170  $metadata = [
171  'meta_lifecycle_id' => ['integer', $DIC->database()->nextId('il_meta_lifecycle')],
172  'rbac_id' => ['integer', $this->getId()],
173  'obj_id' => ['integer', $this->getId()],
174  'obj_type' => ['text', "file"],
175  'meta_version' => ['integer', (int) $this->getVersion()],
176  ];
177  $DIC->database()->insert('il_meta_lifecycle', $metadata);
178 
179  // no meta data handling for file list files
180  if ($this->getMode() != self::MODE_FILELIST) {
181  $this->createMetaData();
182  }
183  }
184 
185 
189  public function setNoMetaDataCreation($a_status)
190  {
191  $this->no_meta_data_creation = (bool) $a_status;
192  }
193 
194 
195  protected function beforeCreateMetaData()
196  {
197  return !(bool) $this->no_meta_data_creation;
198  }
199 
200 
201  protected function beforeUpdateMetaData()
202  {
203  return !(bool) $this->no_meta_data_creation;
204  }
205 
206 
210  protected function doCreateMetaData()
211  {
212  // add technical section with file size and format
213  $md_obj = new ilMD($this->getId(), 0, $this->getType());
214  $technical = $md_obj->addTechnical();
215  $technical->setSize($this->getFileSize());
216  $technical->save();
217  $format = $technical->addFormat();
218  $format->setFormat($this->getFileType());
219  $format->save();
220  $technical->update();
221  }
222 
223 
224  protected function beforeMDUpdateListener($a_element)
225  {
226  // Check file extension
227  // Removing the file extension is not allowed
228  include_once 'Services/MetaData/classes/class.ilMD.php';
229  $md = new ilMD($this->getId(), 0, $this->getType());
230  if (!is_object($md_gen = $md->getGeneral())) {
231  return false;
232  }
233  $title = $this->checkFileExtension($this->getFileName(), $md_gen->getTitle());
234  $md_gen->setTitle($title);
235  $md_gen->update();
236 
237  return true;
238  }
239 
240 
241  protected function doMDUpdateListener($a_element)
242  {
243  // handling for technical section
244  include_once 'Services/MetaData/classes/class.ilMD.php';
245 
246  switch ($a_element) {
247  case 'Technical':
248 
249  // Update Format (size is not stored in db)
250  $md = new ilMD($this->getId(), 0, $this->getType());
251  if (!is_object($md_technical = $md->getTechnical())) {
252  return false;
253  }
254 
255  foreach ($md_technical->getFormatIds() as $id) {
256  $md_format = $md_technical->getFormat($id);
257  ilObjFile::_writeFileType($this->getId(), $md_format->getFormat());
258  $this->setFileType($md_format->getFormat());
259  break;
260  }
261 
262  break;
263  }
264 
265  return true;
266  }
267 
268 
274  public function getDirectory($a_version = 0)
275  {
276  $version_subdir = "";
277 
278  if ($a_version) {
279  // BEGIN WebDAV Avoid double slash before version subdirectory
280  $version_subdir = sprintf("%03d", $a_version);
281  // END WebDAV Avoid double slash before version subdirectory
282  }
283 
284  if (!is_object($this->file_storage)) {
285  $this->initFileStorage();
286  }
287 
288  $str = $this->file_storage->getAbsolutePath() . '/' . $version_subdir;
289 
290  return $str;
291  }
292 
293 
294  public function createDirectory()
295  {
297  }
298 
299 
300  public function raiseUploadError($a_raise = true)
301  {
302  $this->raise_upload_error = $a_raise;
303  }
304 
305 
315  public function getUploadFile($a_upload_file, $a_filename, $a_prevent_preview = false)
316  {
317  global $DIC;
318 
319  $upload = $DIC->upload();
320  $result = null;
321 
322  if ($upload->hasUploads()) {
323  if (!$upload->hasBeenProcessed()) {
324  $upload->process();
325  }
329  $result = $upload->getResults()[$a_upload_file];
330  if ($result->getStatus()->getCode() === \ILIAS\FileUpload\DTO\ProcessingStatus::OK) {
331  $metadata = $result->getMetaData();
332  if ($metadata->has(ilCountPDFPagesPreProcessors::PAGE_COUNT)) {
334  $this->doUpdate();
335  }
336  $a_name = $result->getName();
337  $this->setFileName($this->secure($a_name));
338 
339  $this->setVersion($this->getMaxVersion() + 1);
340  $this->setMaxVersion($this->getMaxVersion() + 1);
341 
342  if (!is_dir($this->getDirectory($this->getVersion()))) {
344  }
345 
346  $target_directory = $this->getDirectory($this->getVersion()) . "/";
347  $relative_path_to_file = LegacyPathHelper::createRelativePath($target_directory);
348 
349  $upload->moveOneFileTo($result, $relative_path_to_file, Location::STORAGE);
350 
351  $this->handleQuotaUpdate($this);
352 
353  // create preview?
354  if (!$a_prevent_preview) {
355  $this->createPreview(false);
356  }
357  } else {
358  $this->delete();
359  throw new ilFileException($result->getStatus()->getMessage());
360  }
361  }
362 
363  return $result;
364  }
365 
366 
375  public function replaceFile($a_upload_file, $a_filename)
376  {
377  if ($result = $this->getUploadFile($a_upload_file, $a_filename, true)) {
378  ilHistory::_createEntry($this->getId(), "replace", $a_filename . "," . $this->getVersion() . "," . $this->getMaxVersion());
379  $this->addNewsNotification("file_updated");
380 
381  // create preview
382  $this->createPreview(true);
383  }
384 
385  return $result;
386  }
387 
388 
397  public function addFileVersion($a_upload_file, $a_filename)
398  {
399  if ($result = $this->getUploadFile($a_upload_file, $a_filename, true)) {
400  ilHistory::_createEntry($this->getId(), "new_version", $result->getName() . "," . $this->getVersion() . "," . $this->getMaxVersion());
401  $this->addNewsNotification("file_updated");
402 
403  // create preview
404  $this->createPreview($this->getVersion() > 1);
405  }
406 
407  return $result;
408  }
409 
410 
414  public function copy($a_source, $a_destination)
415  {
416  return copy($a_source, $this->getDirectory() . "/" . $a_destination);
417  }
418 
419 
423  public function clearDataDirectory()
424  {
425  ilUtil::delDir($this->getDirectory());
426  $this->createDirectory();
427  }
428 
429 
435  public function deleteVersions($a_hist_entry_ids = null)
436  {
437  if ($a_hist_entry_ids == null || count($a_hist_entry_ids) < 1) {
438  $this->clearDataDirectory();
439 
441 
442  self::handleQuotaUpdate($this);
443  } else {
444  $actualVersionDeleted = false;
445 
446  // get all versions
447  $versions = $this->getVersions();
448 
449  // delete each version
450  foreach ($a_hist_entry_ids as $hist_id) {
451  $entry = null;
452 
453  // get version
454  foreach ($versions as $index => $version) {
455  if ($version["hist_entry_id"] == $hist_id) {
456  // remove each history entry
458 
459  // delete directory
460  $version_dir = $this->getDirectory($version["version"]);
461  ilUtil::delDir($version_dir);
462 
463  // is actual version?
464  if ($version["version"] == $this->getVersion()) {
465  $actualVersionDeleted = true;
466  }
467 
468  // remove from array
469  unset($versions[$index]);
470  break;
471  }
472  }
473  }
474 
475  // update actual version if it was deleted before
476  if ($actualVersionDeleted) {
477  // get newest version (already sorted by getVersions)
478  $version = reset($versions);
479  $version['max_version'] = $this->getMaxVersion();
480  $this->updateWithVersion($version);
481  } else {
482  // updateWithVersion() will trigger quota, too
483  self::handleQuotaUpdate($this);
484  }
485  }
486  }
487 
488 
489  protected function doRead()
490  {
491  global $DIC;
492 
493  $q = "SELECT * FROM file_data WHERE file_id = %s";
494  $r = $DIC->database()->queryF($q, ['integer'], [$this->getId()]);
495  $row = $r->fetchObject();
496 
497  $this->setFileName($this->secure($row->file_name));
498  $this->setFileType($row->file_type);
499  $this->setFileSize($row->file_size);
500  $this->setVersion($row->version ? $row->version : 1);
501  $this->setMaxVersion($row->max_version ? $row->max_version : 1);
502  $this->setMode($row->f_mode);
503  $this->setRating($row->rating);
504  $this->setPageCount($row->page_count);
505 
506  $this->initFileStorage();
507  }
508 
509 
510  protected function beforeUpdate()
511  {
512  // no meta data handling for file list files
513  if ($this->getMode() != self::MODE_FILELIST) {
514  $this->updateMetaData();
515  }
516 
517  return true;
518  }
519 
520 
521  protected function doUpdate()
522  {
523  global $DIC;
524 
525  $a_columns = $this->getArrayForDatabase();
526  $DIC->database()->update('file_data', $a_columns, [
527  'file_id' => [
528  'integer',
529  $this->getId(),
530  ],
531  ]);
532 
533  // update metadata with the current file version
534  $meta_version_column = ['meta_version' => ['integer', (int) $this->getVersion()]];
535  $DIC->database()->update('il_meta_lifecycle', $meta_version_column, [
536  'rbac_id' => [
537  'integer',
538  $this->getId(),
539  ],
540  ]);
541 
542  self::handleQuotaUpdate($this);
543 
544  return true;
545  }
546 
547 
551  protected function doUpdateMetaData()
552  {
553  // add technical section with file size and format
554  $md_obj = new ilMD($this->getId(), 0, $this->getType());
555  if (!is_object($technical = $md_obj->getTechnical())) {
556  $technical = $md_obj->addTechnical();
557  $technical->save();
558  }
559  $technical->setSize($this->getFileSize());
560 
561  $format_ids = $technical->getFormatIds();
562  if (count($format_ids) > 0) {
563  $format = $technical->getFormat($format_ids[0]);
564  $format->setFormat($this->getFileType());
565  $format->update();
566  } else {
567  $format = $technical->addFormat();
568  $format->setFormat($this->getFileType());
569  $format->save();
570  }
571  $technical->update();
572  }
573 
574 
578  public function setFileName($a_name)
579  {
580  $this->filename = $a_name;
581  }
582 
583 
587  public function getFileName()
588  {
589  return $this->filename;
590  }
591 
592 
596  public function setFileType($a_type)
597  {
598  $this->filetype = $a_type;
599  }
600 
601 
605  public function getFileType()
606  {
607  return $this->filetype;
608  }
609 
610 
614  public function setFileSize($a_size)
615  {
616  $this->filesize = $a_size;
617  }
618 
619 
620  public function getFileSize()
621  {
622  return $this->filesize;
623  }
624 
625 
626  public function setAction($a_action)
627  {
628  $this->action = $a_action;
629  }
630 
631 
632  public function getAction()
633  {
634  return $this->action;
635  }
636 
637 
638  public function setRollbackVersion($a_rollback_version)
639  {
640  $this->rollback_version = $a_rollback_version;
641  }
642 
643 
644  public function getRollbackVersion()
645  {
647  }
648 
649 
650  public function setRollbackUserId($a_rollback_user_id)
651  {
652  $this->rollback_user_id = $a_rollback_user_id;
653  }
654 
655 
656  public function getRollbackUserId()
657  {
659  }
660 
661 
668  public function getDiskUsage()
669  {
670  require_once("./Modules/File/classes/class.ilObjFileAccess.php");
671 
672  return ilObjFileAccess::_lookupDiskUsage($this->id);
673  }
674 
675 
676  // END PATCH WebDAV Encapsulate file access in ilObjFile class.
677  public function getFile($a_hist_entry_id = null)
678  {
679  if (is_null($a_hist_entry_id)) {
680  $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName();
681  } else {
682  require_once("./Services/History/classes/class.ilHistory.php");
683  $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
684 
685  if ($entry === false) {
686  return false;
687  }
688 
689  $data = $this->parseInfoParams($entry);
690  $file = $this->getDirectory($data["version"]) . "/" . $data["filename"];
691  }
692 
693  return $file;
694  }
695 
696 
697  // END PATCH WebDAV Encapsulate file access in ilObjFile class.
698 
699  public function setVersion($a_version)
700  {
701  $this->version = $a_version;
702  }
703 
704 
705  public function getVersion()
706  {
707  return $this->version;
708  }
709 
710 
711  public function setMaxVersion($a_max_version)
712  {
713  $this->max_version = $a_max_version;
714  }
715 
716 
717  public function getMaxVersion()
718  {
719  return $this->max_version;
720  }
721 
722 
728  public function setMode($a_mode)
729  {
730  $this->mode = $a_mode;
731  }
732 
733 
739  public function getMode()
740  {
741  return $this->mode;
742  }
743 
744 
745  public static function _writeFileType($a_id, $a_format)
746  {
747  global $DIC;
748  $ilDB = $DIC['ilDB'];
749 
750  $q = "UPDATE file_data SET " . " file_type = " . $ilDB->quote($a_format, 'text')
751  . " WHERE file_id = " . $ilDB->quote($a_id, 'integer');
752  $res = $ilDB->manipulate($q);
753  }
754 
755 
762  public static function _lookupFileName($a_id)
763  {
764  global $DIC;
765  $ilDB = $DIC['ilDB'];
766 
767  $q = "SELECT * FROM file_data WHERE file_id = " . $ilDB->quote($a_id, 'integer');
768  $r = $ilDB->query($q);
769  $row = $r->fetchRow(ilDBConstants::FETCHMODE_OBJECT);
770 
771  $strip_slashes = ilUtil::stripSlashes($row->file_name);
772 
773  return $strip_slashes;
774  }
775 
776 
778  public static function _lookupFileSize($a_id)
779  {
780  require_once("./Modules/File/classes/class.ilObjFileAccess.php");
781 
782  return ilObjFileAccess::_lookupFileSize($a_id);
783  }
784 
785 
789  public static function _lookupVersion($a_id)
790  {
791  require_once("./Modules/File/classes/class.ilObjFileAccess.php");
792 
793  return ilObjFileAccess::_lookupVersion($a_id);
794  }
795 
796 
800  public function determineFileSize($a_hist_entry_id = null)
801  {
802  if (is_null($a_hist_entry_id)) {
803  $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName();
804  } else {
805  require_once("./Services/History/classes/class.ilHistory.php");
806  $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
807 
808  if ($entry === false) {
809  return false;
810  }
811 
812  $data = $this->parseInfoParams($entry);
813  $file = $this->getDirectory($data["version"]) . "/" . $data["filename"];
814  }
815  if (is_file($file)) {
816  $this->setFileSize(filesize($file));
817  }
818  }
819 
820 
826  public function sendFile($a_hist_entry_id = null)
827  {
828  $s = new FilePathSanitizer($this);
829  $s->sanitizeIfNeeded();
830 
831  if (is_null($a_hist_entry_id)) {
832  $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName();
833  $file = ilFileUtils::getValidFilename($file);
834  } else {
835  $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
836  $data = $this->parseInfoParams($entry);
837  $file = $this->getDirectory($data["version"]) . "/" . $data["filename"];
838  }
839 
840  if ($this->file_storage->fileExists($file)) {
841  global $DIC;
842  $ilClientIniFile = $DIC['ilClientIniFile'];
847  $ilFileDelivery = new ilFileDelivery($file);
848  $ilFileDelivery->setDisposition($this->isInline() ? ilFileDelivery::DISP_INLINE : ilFileDelivery::DISP_ATTACHMENT);
849  $ilFileDelivery->setMimeType($this->guessFileType($file));
850  $ilFileDelivery->setConvertFileNameToAsci((bool) !$ilClientIniFile->readVariable('file_access', 'disable_ascii'));
851 
852  // also returning the 'real' filename if a history file is delivered
853  if ($ilClientIniFile->readVariable('file_access', 'download_with_uploaded_filename')
854  != '1'
855  && is_null($a_hist_entry_id)
856  ) {
857  $ilFileDelivery->setDownloadFileName(ilFileUtils::getValidFilename($this->getTitle()));
858  } else {
859  // $download_file_name = basename($file);
860  /* FSX Info: basename has a Bug with Japanese and other characters, see:
861  * http://stackoverflow.com/questions/32115609/basename-fail-when-file-name-start-by-an-accent
862  * Therefore we can no longer use basename();
863  */
864  $parts = explode(DIRECTORY_SEPARATOR, $file);
865  $download_file_name = end($parts);
866  $download_file_name = ilFileUtils::getValidFilename($download_file_name);
867  $ilFileDelivery->setDownloadFileName($download_file_name);
868  }
869  $ilFileDelivery->deliver();
870 
871  return true;
872  }
873 
874  throw new FileNotFoundException($this->lng->txt('file_not_found_sec'));
875  }
876 
877 
882  public function getFileExtension()
883  {
884  require_once 'Modules/File/classes/class.ilObjFileAccess.php';
885 
887  }
888 
889 
895  public function isInline()
896  {
897  require_once 'Modules/File/classes/class.ilObjFileAccess.php';
898 
899  return ilObjFileAccess::_isFileInline($this->getTitle());
900  }
901 
902 
906  public function isHidden()
907  {
908  require_once 'Modules/File/classes/class.ilObjFileAccess.php';
909 
910  return ilObjFileAccess::_isFileHidden($this->getTitle());
911  }
912  // END WebDAV: Get file extension, determine if file is inline, guess file type.
913 
914 
921  public function guessFileType($a_file = "")
922  {
923  $path = pathinfo($a_file);
924  if ($path["extension"] != "") {
925  $filename = $path["basename"];
926  } else {
927  $filename = "dummy." . $this->getFileExtension();
928  }
929  include_once("./Services/Utilities/classes/class.ilMimeTypeUtil.php");
930  $mime = ilMimeTypeUtil::getMimeType($a_file, $filename, $this->getFileType());
931 
932  return $mime;
933  }
934 
935 
946  protected function doCloneObject($a_new_obj, $a_target_id, $a_copy_id = 0)
947  {
948  global $DIC;
949  $ilDB = $DIC['ilDB'];
950 
951  $a_new_obj->createDirectory();
952  $this->cloneMetaData($a_new_obj);
953 
954  // Copy all file versions
955  ilUtil::rCopy($this->getDirectory(), $a_new_obj->getDirectory());
956 
957  // object created now copy other settings
958  $query = "INSERT INTO file_data (file_id,file_name,file_type,file_size,version,rating,f_mode) VALUES ("
959  . $ilDB->quote($a_new_obj->getId(), 'integer') . ","
960  . $ilDB->quote($this->getFileName(), 'text') . ","
961  . $ilDB->quote($this->getFileType(), 'text') . ","
962  . $ilDB->quote((int) $this->getFileSize(), 'integer') . ", "
963  . $ilDB->quote($this->getVersion(), 'integer') . ", "
964  . $ilDB->quote($this->hasRating(), 'integer') . ", "
965  . $ilDB->quote($this->getMode(), 'text') . ")";
966  $res = $ilDB->manipulate($query);
967 
968  // copy all previews
969  require_once("./Services/Preview/classes/class.ilPreview.php");
970  ilPreview::copyPreviews($this->getId(), $a_new_obj->getId());
971 
972  // copy history entries
973  require_once("./Services/History/classes/class.ilHistory.php");
974  ilHistory::_copyEntriesForObject($this->getId(), $a_new_obj->getId());
975 
976  // Copy learning progress settings
977  include_once('Services/Tracking/classes/class.ilLPObjSettings.php');
978  $obj_settings = new ilLPObjSettings($this->getId());
979  $obj_settings->cloneSettings($a_new_obj->getId());
980  unset($obj_settings);
981 
982  // add news notification
983  $a_new_obj->addNewsNotification("file_created");
984 
985  return $a_new_obj;
986  }
987 
988 
989  protected function beforeDelete()
990  {
991  global $DIC;
992  $ilDB = $DIC['ilDB'];
993 
994  // check, if file is used somewhere
995  $usages = $this->getUsages();
996  if (count($usages) == 0) {
997  return true;
998  }
999 
1000  return false;
1001  }
1002 
1003 
1004  protected function doDelete()
1005  {
1006  global $DIC;
1007  $ilDB = $DIC['ilDB'];
1008 
1009  // delete file data entry
1010  $q = "DELETE FROM file_data WHERE file_id = " . $ilDB->quote($this->getId(), 'integer');
1011  $this->ilias->db->query($q);
1012 
1013  // delete history entries
1014  require_once("./Services/History/classes/class.ilHistory.php");
1016 
1017  self::handleQuotaUpdate($this);
1018 
1019  // delete entire directory and its content
1020  if (@is_dir($this->getDirectory())) {
1021  ilUtil::delDir($this->getDirectory());
1022  }
1023 
1024  // delete meta data
1025  if ($this->getMode() != self::MODE_FILELIST) {
1026  $this->deleteMetaData();
1027  }
1028 
1029  // delete preview
1030  $this->deletePreview();
1031  }
1032 
1033 
1041  public function export($a_target_dir)
1042  {
1043  $subdir = "il_" . IL_INST_ID . "_file_" . $this->getId();
1044  ilUtil::makeDir($a_target_dir . "/objects/" . $subdir);
1045 
1046  $filedir = $this->getDirectory($this->getVersion());
1047 
1048  if (@!is_dir($filedir)) {
1049  $filedir = $this->getDirectory();
1050  }
1051 
1052  ilUtil::rCopy($filedir, $a_target_dir . "/objects/" . $subdir);
1053  }
1054 
1055 
1059  public static function _deleteAllUsages($a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
1060  {
1061  global $DIC;
1062  $ilDB = $DIC['ilDB'];
1063 
1064  $and_hist = ($a_usage_hist_nr !== false) ? " AND usage_hist_nr = "
1065  . $ilDB->quote($a_usage_hist_nr, "integer") : "";
1066 
1067  $file_ids = array();
1068  $set = $ilDB->query("SELECT id FROM file_usage" . " WHERE usage_type = "
1069  . $ilDB->quote($a_type, "text") . " AND usage_id= "
1070  . $ilDB->quote($a_id, "integer") . " AND usage_lang= "
1071  . $ilDB->quote($a_usage_lang, "text") . $and_hist);
1072  while ($row = $ilDB->fetchAssoc($set)) {
1073  $file_ids[] = $row["id"];
1074  }
1075 
1076  $ilDB->manipulate("DELETE FROM file_usage WHERE usage_type = "
1077  . $ilDB->quote($a_type, "text") . " AND usage_id = "
1078  . $ilDB->quote((int) $a_id, "integer") . " AND usage_lang= "
1079  . $ilDB->quote($a_usage_lang, "text") . " AND usage_hist_nr = "
1080  . $ilDB->quote((int) $a_usage_hist_nr, "integer"));
1081 
1082  foreach ($file_ids as $file_id) {
1083  self::handleQuotaUpdate(new self($file_id, false));
1084  }
1085  }
1086 
1087 
1091  public static function _saveUsage($a_file_id, $a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
1092  {
1093  global $DIC;
1094  $ilDB = $DIC['ilDB'];
1095 
1096  // check if file really exists
1097  if (ilObject::_lookupType($a_file_id) != "file") {
1098  return;
1099  }
1100  // #15143
1101  $ilDB->replace("file_usage", array(
1102  "id" => array("integer", (int) $a_file_id),
1103  "usage_type" => array("text", (string) $a_type),
1104  "usage_id" => array("integer", (int) $a_id),
1105  "usage_hist_nr" => array("integer", (int) $a_usage_hist_nr),
1106  "usage_lang" => array("text", $a_usage_lang),
1107  ), array());
1108 
1109  self::handleQuotaUpdate(new self($a_file_id, false));
1110  }
1111 
1112 
1116  public function getUsages()
1117  {
1118  global $DIC;
1119  $ilDB = $DIC['ilDB'];
1120 
1121  // get usages in learning modules
1122  $q = "SELECT * FROM file_usage WHERE id = " . $ilDB->quote($this->getId(), "integer");
1123  $us_set = $ilDB->query($q);
1124  $ret = array();
1125  while ($us_rec = $ilDB->fetchAssoc($us_set)) {
1126  $ret[] = array(
1127  "type" => $us_rec["usage_type"],
1128  "id" => $us_rec["usage_id"],
1129  "lang" => $us_rec["usage_lang"],
1130  "hist_nr" => $us_rec["usage_hist_nr"],
1131  );
1132  }
1133 
1134  return $ret;
1135  }
1136 
1137 
1146  public static function _getFilesOfObject($a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
1147  {
1148  global $DIC;
1149  $ilDB = $DIC['ilDB'];
1150 
1151  $lstr = "";
1152  if ($a_usage_lang != "") {
1153  $lstr = "usage_lang = " . $ilDB->quote((string) $a_usage_lang, "text") . " AND ";
1154  }
1155 
1156  // get usages in learning modules
1157  $q = "SELECT * FROM file_usage WHERE " . "usage_id = " . $ilDB->quote((int) $a_id, "integer")
1158  . " AND " . "usage_type = " . $ilDB->quote((string) $a_type, "text") . " AND " . $lstr
1159  . "usage_hist_nr = " . $ilDB->quote((int) $a_usage_hist_nr, "integer");
1160  $file_set = $ilDB->query($q);
1161  $ret = array();
1162  while ($file_rec = $ilDB->fetchAssoc($file_set)) {
1163  $ret[$file_rec["id"]] = $file_rec["id"];
1164  }
1165 
1166  return $ret;
1167  }
1168 
1169 
1170  // TODO: What is this function good for??
1171  public function getXMLZip()
1172  {
1173  global $DIC;
1174  $ilias = $DIC['ilias'];
1175 
1176  $zip = PATH_TO_ZIP;
1177 
1178  exec($zip . ' ' . ilUtil::escapeShellArg($this->getDirectory() . '/' . $this->getFileName())
1179  . " " . ilUtil::escapeShellArg($this->getDirectory() . '/' . '1.zip'));
1180 
1181  return $this->getDirectory() . '/1.zip';
1182  }
1183 
1184 
1185  public function addNewsNotification($a_lang_var)
1186  {
1187  // BEGIN WebDAV Suppress news notification for hidden files
1188  if ($this->isHidden()) {
1189  return;
1190  }
1191  // END WebDAV Suppress news notification for hidden files
1192 
1193  global $DIC;
1194  $ilUser = $DIC['ilUser'];
1195 
1196  // Add Notification to news
1197  include_once("./Services/News/classes/class.ilNewsItem.php");
1198  include_once("./Modules/File/classes/class.ilObjFileAccess.php");
1199  $news_item = new ilNewsItem();
1200  $news_item->setContext($this->getId(), $this->getType());
1201  $news_item->setPriority(NEWS_NOTICE);
1202  $news_item->setTitle($a_lang_var);
1203  $news_item->setContentIsLangVar(true);
1204  if ($this->getDescription() != "") {
1205  $news_item->setContent("<p>" . $this->getDescription() . "</p>");
1206  }
1207  $news_item->setUserId($ilUser->getId());
1208  $news_item->setVisibility(NEWS_USERS);
1209  $news_item->create();
1210  }
1211 
1212 
1219  public function initFileStorage()
1220  {
1221  $this->file_storage = new ilFSStorageFile($this->getId());
1222 
1223  return true;
1224  }
1225 
1226 
1236  public function storeUnzipedFile($a_upload_file, $a_filename)
1237  {
1238  $this->setVersion($this->getVersion() + 1);
1239 
1240  if (@!is_dir($this->getDirectory($this->getVersion()))) {
1241  ilUtil::makeDir($this->getDirectory($this->getVersion()));
1242  }
1243 
1244  $file = $this->getDirectory($this->getVersion()) . "/" . $a_filename;
1245 
1246  $file = ilFileUtils::getValidFilename($file);
1247 
1248  ilFileUtils::rename($a_upload_file, $file);
1249 
1250  // create preview
1251  $this->createPreview();
1252  }
1253 
1254 
1262  public static function _lookupAbsolutePath($obj_id, $a_version = null)
1263  {
1264  $file_object = new self($obj_id, false);
1265  $s = new FilePathSanitizer($file_object);
1266  $s->sanitizeIfNeeded();
1267 
1268  return $file_object->getFile($a_version);
1269  }
1270 
1271 
1277  public function checkFileExtension($new_filename, $new_title)
1278  {
1279  include_once './Modules/File/classes/class.ilObjFileAccess.php';
1280  $fileExtension = ilObjFileAccess::_getFileExtension($new_filename);
1281  $titleExtension = ilObjFileAccess::_getFileExtension($new_title);
1282  if ($titleExtension != $fileExtension && strlen($fileExtension) > 0) {
1283  // remove old extension
1284  $pi = pathinfo($this->getFileName());
1285  $suffix = $pi["extension"];
1286  if ($suffix != "") {
1287  if (substr($new_title, strlen($new_title) - strlen($suffix) - 1) == "." . $suffix) {
1288  $new_title = substr($new_title, 0, strlen($new_title) - strlen($suffix) - 1);
1289  }
1290  }
1291  $new_title .= '.' . $fileExtension;
1292  }
1293 
1294  return $new_title;
1295  }
1296 
1297 
1318  public function getVersions($version_ids = null) : array
1319  {
1320  $versions = (array) ilHistory::_getEntriesForObject($this->getId(), $this->getType());
1321 
1322  if ($version_ids != null && count($version_ids) > 0) {
1323  foreach ($versions as $index => $version) {
1324  if (!in_array($version["hist_entry_id"], $version_ids, true)) {
1325  unset($versions[$index]);
1326  }
1327  }
1328  }
1329 
1330  // add custom entries
1331  foreach ($versions as $index => $version) {
1332  $params = $this->parseInfoParams($version);
1333  $versions[$index] = array_merge($version, $params);
1334  }
1335 
1336  // sort by version number (hist_entry_id will do for that)
1337  usort($versions, array($this, "compareVersions"));
1338 
1339  return $versions;
1340  }
1341 
1342 
1350  public function getSpecificVersion($version_id)
1351  {
1352  include_once("./Services/History/classes/class.ilHistory.php");
1354  if ($version === false) {
1355  return false;
1356  }
1357 
1358  // ilHistory returns different keys in _getEntryByHistoryID and _getEntriesForObject
1359  // so this makes it the same
1360  $version["hist_entry_id"] = $version["id"];
1361  $version["user_id"] = $version["usr_id"];
1362  $version["date"] = $version["hdate"];
1363  unset($version["id"], $version["usr_id"], $version["hdate"]);
1364 
1365  // parse params
1366  $params = $this->parseInfoParams($version);
1367 
1368  return array_merge($version, $params);
1369  }
1370 
1371 
1379  public function rollback($version_id)
1380  {
1381  global $DIC;
1382  $ilDB = $DIC['ilDB'];
1383  $ilUser = $DIC['ilUser'];
1384 
1385  $source = $this->getSpecificVersion($version_id);
1386  if ($source === false) {
1387  $this->ilErr->raiseError($this->lng->txt("obj_not_found"), $this->ilErr->MESSAGE);
1388  }
1389 
1390  // get the new version number
1391  $new_version_nr = $this->getMaxVersion() + 1;
1392  $this->setMaxVersion($new_version_nr);
1393 
1394  // copy file
1395  $source_path = $this->getDirectory($source["version"]) . "/" . $source["filename"];
1396  $dest_dir = $this->getDirectory($new_version_nr);
1397  if (@!is_dir($dest_dir)) {
1398  ilUtil::makeDir($dest_dir);
1399  }
1400 
1401  copy($source_path, $dest_dir . "/" . $source["filename"]);
1402 
1403  // create new history entry based on the old one
1404  include_once("./Services/History/classes/class.ilHistory.php");
1405  ilHistory::_createEntry($this->getId(), "rollback", $source["filename"] . ","
1406  . $new_version_nr . ","
1407  . $this->getMaxVersion() . "|"
1408  . $source["version"] . "|"
1409  . $ilUser->getId());
1410 
1411  // get id of newest entry
1412  $entries = ilHistory::_getEntriesForObject($this->getId());
1413  $newest_entry_id = 0;
1414  foreach ($entries as $entry) {
1415  if ($entry["action"] == "rollback") {
1416  $newest_entry_id = $entry["hist_entry_id"];
1417  }
1418  }
1419  $new_version = $this->getSpecificVersion($newest_entry_id);
1420  $new_version['version'] = $new_version_nr;
1421  $new_version['max_version'] = $new_version_nr;
1422 
1423  // change user back to the original uploader
1424  ilHistory::_changeUserId($new_version["hist_entry_id"], $source["user_id"]);
1425 
1426  // update this file with the new version
1427  $this->updateWithVersion($new_version);
1428 
1429  $this->addNewsNotification("file_updated");
1430 
1431  return $new_version;
1432  }
1433 
1434 
1440  protected function updateWithVersion($version)
1441  {
1442  // update title (checkFileExtension must be called before setFileName!)
1443  $this->setTitle($this->checkFileExtension($version["filename"], $this->getTitle()));
1444 
1445  $this->setVersion($version["version"]);
1446  $this->setMaxVersion($version["max_version"]);
1447  $this->setFileName($version["filename"]);
1448 
1449  // evaluate mime type (reset file type before)
1450  $this->setFileType("");
1451  $this->setFileType($this->guessFileType($version["filename"]));
1452 
1453  // set filesize
1454  $this->determineFileSize();
1455 
1456  $this->update();
1457 
1458  // refresh preview
1459  $this->createPreview(true);
1460  }
1461 
1462 
1473  public function compareVersions($v1, $v2)
1474  {
1475  // v2 - v1 because version should be descending
1476  return (int) $v2["version"] - (int) $v1["version"];
1477  }
1478 
1479 
1488  private function parseInfoParams($entry)
1489  {
1490  $data = explode(",", $entry["info_params"]);
1491 
1492  // bugfix: first created file had no version number
1493  // this is a workaround for all files created before the bug was fixed
1494  if (empty($data[1])) {
1495  $data[1] = "1";
1496  }
1497 
1498  if (empty($data[2])) {
1499  $data[2] = "1";
1500  }
1501 
1502  $result = array(
1503  "filename" => $data[0],
1504  "version" => $data[1],
1505  "max_version" => $data[2],
1506  "rollback_version" => "",
1507  "rollback_user_id" => "",
1508  );
1509 
1510  // if rollback, the version contains the rollback version as well
1511  if ($entry["action"] == "rollback") {
1512  $tokens = explode("|", $result["max_version"]);
1513  if (count($tokens) > 1) {
1514  $result["max_version"] = $tokens[0];
1515  $result["rollback_version"] = $tokens[1];
1516 
1517  if (count($tokens) > 2) {
1518  $result["rollback_user_id"] = $tokens[2];
1519  }
1520  }
1521  }
1522 
1523  return $result;
1524  }
1525 
1526 
1527  protected static function handleQuotaUpdate(ilObjFile $a_file)
1528  {
1529  include_once "Services/MediaObjects/classes/class.ilObjMediaObject.php";
1530  $mob = new ilObjMediaObject();
1531 
1532  // file itself could be workspace item
1533  $parent_obj_ids = array($a_file->getId());
1534 
1535  foreach ($a_file->getUsages() as $item) {
1536  $parent_obj_id = $mob->getParentObjectIdForUsage($item);
1537  if ($parent_obj_id
1538  && !in_array($parent_obj_id, $parent_obj_ids)
1539  ) {
1540  $parent_obj_ids[] = $parent_obj_id;
1541  }
1542  }
1543 
1544  include_once "Services/DiskQuota/classes/class.ilDiskQuotaHandler.php";
1545  ilDiskQuotaHandler::handleUpdatedSourceObject($a_file->getType(), $a_file->getId(), $a_file->getDiskUsage(), $parent_obj_ids);
1546  }
1547 
1548 
1555  protected function createPreview($force = false)
1556  {
1557  // only normal files are supported
1558  if ($this->getMode() != self::MODE_OBJECT) {
1559  return;
1560  }
1561 
1562  require_once("./Services/Preview/classes/class.ilPreview.php");
1563  ilPreview::createPreview($this, $force);
1564  }
1565 
1566 
1570  protected function deletePreview()
1571  {
1572  // only normal files are supported
1573  if ($this->getMode() != self::MODE_OBJECT) {
1574  return;
1575  }
1576 
1577  require_once("./Services/Preview/classes/class.ilPreview.php");
1578  ilPreview::deletePreview($this->getId());
1579  }
1580 
1581 
1585  public function setRating($a_value)
1586  {
1587  $this->rating = (bool) $a_value;
1588  }
1589 
1590 
1594  public function hasRating()
1595  {
1596  return $this->rating;
1597  }
1598 
1599 
1603  public function getPageCount()
1604  {
1605  return $this->page_count;
1606  }
1607 
1608 
1612  public function setPageCount($page_count)
1613  {
1614  $this->page_count = $page_count;
1615  }
1616 
1617 
1621  private function getArrayForDatabase()
1622  {
1623  return [
1624  'file_id' => ['integer', $this->getId()],
1625  'file_name' => ['text', $this->getFileName()],
1626  'file_type' => ['text', $this->getFileType()],
1627  'file_size' => ['integer', (int) $this->getFileSize()],
1628  'version' => ['integer', (int) $this->getVersion()],
1629  'max_version' => ['integer', (int) $this->getMaxVersion()],
1630  'f_mode' => ['text', $this->getMode()],
1631  'page_count' => ['text', $this->getPageCount()],
1632  'rating' => ['integer', $this->hasRating()],
1633  ];
1634  }
1635 }
static makeDirParents($a_dir)
Create a new directory and all parent directories.
static _writeFileType($a_id, $a_format)
setFileType($a_type)
createProperties($a_upload=false)
The basic properties of a file object are stored in table object_data.
static _lookupDiskUsage($a_id)
Returns the number of bytes used on the harddisk by the file object with the specified object id...
setRollbackVersion($a_rollback_version)
static _removeEntryByHistoryID($a_hist_entry_id)
Removes a single entry from the history.
static _isFileInline($a_file_name)
Returns true, if the specified file shall be displayed inline in the browser.
parseInfoParams($entry)
Parses the info parameters ("info_params") of the specified history entry.
static _write($a_type, $a_setting, $a_value, $a_user=0, $a_block_id=0)
Write setting to database.
$data
Definition: storeScorm.php:23
setFileName($a_name)
static _changeUserId($a_hist_entry_id, $new_user_id)
Changes the user id of the specified history entry.
$result
setMode($a_mode)
mode is object or filelist
static rCopy($a_sdir, $a_tdir, $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
$_GET["client_id"]
copy($a_source, $a_destination)
copy file
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.
clearDataDirectory()
clear data directory
compareVersions($v1, $v2)
Compares two file versions.
getFile($a_hist_entry_id=null)
getMode()
mode is object or filelist
storeUnzipedFile($a_upload_file, $a_filename)
storeUnzipedFile
static _deleteAllUsages($a_type, $a_id, $a_usage_hist_nr=0, $a_usage_lang="-")
static delete all usages of
setVersion($a_version)
doCreateMetaData()
create file object meta data
getDirectory($a_version=0)
setFileSize($a_size)
setNoMetaDataCreation($a_status)
doCreate($a_upload=false)
create object
static _createEntry( $a_obj_id, $a_action, $a_info_params="", $a_obj_type="", $a_user_comment="", $a_update_last=false)
Creates a new history entry for an object.
static _getEntryByHistoryID($a_hist_entry_id)
returns a single history entry
$index
Definition: metadata.php:128
beforeMDUpdateListener($a_element)
checkFileExtension($new_filename, $new_title)
Check if the file extension does still exist after an update of the title.
static _lookupFileSize($a_id)
Quickly looks up the file size from the database and returns the number of bytes. ...
doUpdateMetaData()
update meta data
static rename($a_source, $a_target)
Rename a file.
replaceFile($a_upload_file, $a_filename)
static getMimeType($a_file='', $a_filename='', $a_mime='')
$a_type
Definition: workflow.php:92
setRollbackUserId($a_rollback_user_id)
static _copyEntriesForObject($a_src_id, $a_dst_id)
copy all history entries for an object
foreach($_POST as $key=> $value) $res
getId()
get object id public
static _lookupFileName($a_id)
static getBytesForString($a_str)
Return string as byte array Note: Use this for debugging purposes only.
addFileVersion($a_upload_file, $a_filename)
const NEWS_NOTICE
setAction($a_action)
const MODE_FILELIST
static createPreview($a_obj, $a_force=false)
Creates the preview for the object with the specified id.
deletePreview()
Deletes the preview of the file object.
$format
Definition: metadata.php:218
$ilUser
Definition: imgupload.php:18
isHidden()
Returns true, if this file should be hidden in the repository view.
Class to report exception.
redirection script todo: (a better solution should control the processing via a xml file) ...
Class ilObjMediaObject.
$query
setTitle($a_title)
static _saveUsage($a_file_id, $a_type, $a_id, $a_usage_hist_nr=0, $a_usage_lang="-")
save usage
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
isInline()
Returns true, if this file should be displayed inline in a browser window.
createPreview($force=false)
Creates a preview for the file object.
getSpecificVersion($version_id)
Gets a specific file version.
static _getFilesOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_usage_lang="-")
get all files of an object
static _getEntriesForObject($a_obj_id, $a_obj_type="")
get all history entries for an object
addNewsNotification($a_lang_var)
static _lookupType($a_id, $a_reference=false)
lookup object type
getUsages()
get all usages of file object
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
doCloneObject($a_new_obj, $a_target_id, $a_copy_id=0)
Clone.
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)
Deletes the specified history entries or all entries if no ids are specified.
static _lookupFileSize($a_id)
Lookups the file size of the file in bytes.
getFileExtension()
Returns the extension of the file name converted to lower-case.
static handleQuotaUpdate(ilObjFile $a_file)
rollback($version_id)
Makes the specified version the current one and returns theSummary of rollbackVersion.
export($a_target_dir)
export files of object to target directory note: target directory must be the export target directory...
static _lookupVersion($a_id)
lookup version
static escapeShellArg($a_arg)
initFileStorage()
init file storage object
__construct(Container $dic, ilPlugin $plugin)
static handleUpdatedSourceObject($a_src_obj_type, $a_src_obj_id, $a_src_filesize, $a_owner_obj_ids=null, $a_is_prtf=false)
Find and update/create all related entries for source object.
Class ilFileDelivery.
setPageCount($page_count)
static deletePreview($a_obj_id)
Deletes the preview for the object with the specified id.
global $ilDB
static _lookupAbsolutePath($obj_id, $a_version=null)
$ret
Definition: parser.php:6
static _getDefaultVisibilityForRefId($a_ref_id)
Get default visibility for reference id.
$DIC
Definition: xapitoken.php:46
static _removeEntriesForObject($a_obj_id)
remove all history entries for an object
static getLogger($a_component_id)
Get component logger.
raiseUploadError($a_raise=true)
Class ilFSStorageFile.
const NEWS_USERS
doMDUpdateListener($a_element)
static _lookupVersion($a_id)
lookup version
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
determineFileSize($a_hist_entry_id=null)
Determine File Size.
$source
Definition: metadata.php:76
__construct($a_id=0, $a_call_by_reference=true)
ilObjFile constructor.
getVersions($version_ids=null)
Gets the file versions for this object.
setRating($a_value)
static getValidFilename($a_filename)
Get valid filename.
guessFileType($a_file="")
Guesses the file type based on the current values returned by getFileType() and getFileExtension().
updateWithVersion($version)
Updates the file object with the specified file version.
cloneMetaData($target_obj)
getDiskUsage()
Gets the disk usage of the object in bytes.