ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
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
9require_once("Services/Object/classes/class.ilObject2.php");
10require_once('Modules/File/classes/class.ilFSStorageFile.php');
11
21class ilObjFile extends ilObject2
22{
23 const MODE_FILELIST = "filelist";
24 const MODE_OBJECT = "object";
32 protected $filename = '';
36 protected $filetype = '';
40 protected $filemaxsize = "20000000"; // not used yet
44 protected $filesize;
56 protected $page_count = 0;
60 protected $rating = false;
64 private $file_storage = null;
68 protected $log = null;
72 protected $version = 1;
76 protected $max_version = 1;
80 protected $action = null;
84 protected $rollback_version = null;
88 protected $rollback_user_id = null;
89
90
97 public function __construct($a_id = 0, $a_call_by_reference = true)
98 {
99 $this->version = 0;
100 $this->max_version = 0;
101 $this->raise_upload_error = true;
102
103 $this->log = ilLoggerFactory::getLogger('file');
104
105 parent::__construct($a_id, $a_call_by_reference);
106
107 if ($this->getId()) {
108 $this->initFileStorage();
109 }
110 }
111
112
113 public function initType()
114 {
115 $this->type = "file";
116 }
117
118
124 protected function doCreate($a_upload = false)
125 {
126 $this->createProperties($a_upload);
127 }
128
129
137 public function createProperties($a_upload = false)
138 {
139 global $DIC;
140
141 // Create file directory
142 $this->initFileStorage();
143 $this->file_storage->create();
144
145 if ($a_upload) {
146 return true;
147 }
148
149 // not upload mode
150 ilHistory::_createEntry($this->getId(), "create", $this->getFileName() . ",1" . ",1");
151 $this->addNewsNotification("file_created");
152
153 // New Item
154 $default_visibility = ilNewsItem::_getDefaultVisibilityForRefId($_GET['ref_id']);
155 if ($default_visibility == "public") {
156 ilBlockSetting::_write("news", "public_notifications", 1, 0, $this->getId());
157 }
158
159 // log creation
160 $this->log->debug("ilObjFile::createProperties, ID: " . $this->getId() . ", Name: "
161 . $this->getFileName() . ", Type: " . $this->getFileType() . ", Size: "
162 . $this->getFileSize() . ", Mode: " . $this->getMode() . ", Name(Bytes): "
163 . implode(":", ilStr::getBytesForString($this->getFileName())));
164 $this->log->logStack(ilLogLevel::DEBUG);
165
166 $DIC->database()->insert('file_data', $this->getArrayForDatabase());
167
168 //add metadata to database
169 $metadata = [
170 'meta_lifecycle_id' => ['integer', $DIC->database()->nextId('il_meta_lifecycle')],
171 'rbac_id' => ['integer', $this->getId()],
172 'obj_id' => ['integer', $this->getId()],
173 'obj_type' => ['text', "file"],
174 'meta_version' => ['integer', (int) $this->getVersion()],
175 ];
176 $DIC->database()->insert('il_meta_lifecycle', $metadata);
177
178 // no meta data handling for file list files
179 if ($this->getMode() != self::MODE_FILELIST) {
180 $this->createMetaData();
181 }
182 }
183
184
188 public function setNoMetaDataCreation($a_status)
189 {
190 $this->no_meta_data_creation = (bool) $a_status;
191 }
192
193
194 protected function beforeCreateMetaData()
195 {
196 return !(bool) $this->no_meta_data_creation;
197 }
198
199
200 protected function beforeUpdateMetaData()
201 {
202 return !(bool) $this->no_meta_data_creation;
203 }
204
205
209 protected function doCreateMetaData()
210 {
211 // add technical section with file size and format
212 $md_obj = new ilMD($this->getId(), 0, $this->getType());
213 $technical = $md_obj->addTechnical();
214 $technical->setSize($this->getFileSize());
215 $technical->save();
216 $format = $technical->addFormat();
217 $format->setFormat($this->getFileType());
218 $format->save();
219 $technical->update();
220 }
221
222
223 protected function beforeMDUpdateListener($a_element)
224 {
225 // Check file extension
226 // Removing the file extension is not allowed
227 include_once 'Services/MetaData/classes/class.ilMD.php';
228 $md = new ilMD($this->getId(), 0, $this->getType());
229 if (!is_object($md_gen = $md->getGeneral())) {
230 return false;
231 }
232 $title = $this->checkFileExtension($this->getFileName(), $md_gen->getTitle());
233 $md_gen->setTitle($title);
234 $md_gen->update();
235
236 return true;
237 }
238
239
240 protected function doMDUpdateListener($a_element)
241 {
242 // handling for technical section
243 include_once 'Services/MetaData/classes/class.ilMD.php';
244
245 switch ($a_element) {
246 case 'Technical':
247
248 // Update Format (size is not stored in db)
249 $md = new ilMD($this->getId(), 0, $this->getType());
250 if (!is_object($md_technical = $md->getTechnical())) {
251 return false;
252 }
253
254 foreach ($md_technical->getFormatIds() as $id) {
255 $md_format = $md_technical->getFormat($id);
256 ilObjFile::_writeFileType($this->getId(), $md_format->getFormat());
257 $this->setFileType($md_format->getFormat());
258 break;
259 }
260
261 break;
262 }
263
264 return true;
265 }
266
267
273 public function getDirectory($a_version = 0)
274 {
275 $version_subdir = "";
276
277 if ($a_version) {
278 // BEGIN WebDAV Avoid double slash before version subdirectory
279 $version_subdir = sprintf("%03d", $a_version);
280 // END WebDAV Avoid double slash before version subdirectory
281 }
282
283 if (!is_object($this->file_storage)) {
284 $this->initFileStorage();
285 }
286
287 $str = $this->file_storage->getAbsolutePath() . '/' . $version_subdir;
288
289 return $str;
290 }
291
292
293 public function createDirectory()
294 {
296 }
297
298
299 public function raiseUploadError($a_raise = true)
300 {
301 $this->raise_upload_error = $a_raise;
302 }
303
304
314 public function getUploadFile($a_upload_file, $a_filename, $a_prevent_preview = false)
315 {
316 global $DIC;
317
318 $upload = $DIC->upload();
319 $result = null;
320
321 if ($upload->hasUploads()) {
322 if (!$upload->hasBeenProcessed()) {
323 $upload->process();
324 }
328 $result = $upload->getResults()[$a_upload_file];
329 if ($result->getStatus()->getCode() === \ILIAS\FileUpload\DTO\ProcessingStatus::OK) {
330 $metadata = $result->getMetaData();
333 $this->doUpdate();
334 }
335 $a_name = $result->getName();
336 $this->setFileName($a_name);
337
338 // bugfix mantis 26236:
339 // ensure that version and max_version are correct to prevent the upload file from being versioned incorrectly
340 if ($this->getVersion() > 0) {
341 $file_hist_entries = (array) ilHistory::_getEntriesForObject($this->getId(), $this->getType());
342 $highest_version = 0;
343 foreach ($file_hist_entries as $file_hist_entry) {
344 $version = $this->parseInfoParams($file_hist_entry)['version'];
345 if ($version > $highest_version) {
346 $highest_version = $version;
347 }
348 }
349 if ($this->getVersion() < $highest_version) {
350 $this->setVersion($highest_version);
351 }
352 if ($this->getVersion() > $this->getMaxVersion()) {
353 $this->setMaxVersion($this->getVersion());
354 }
355 }
356
357 $this->setVersion($this->getMaxVersion() + 1);
358 $this->setMaxVersion($this->getMaxVersion() + 1);
359
360 if (!is_dir($this->getDirectory($this->getVersion()))) {
362 }
363
364 $target_directory = $this->getDirectory($this->getVersion()) . "/";
365 $relative_path_to_file = LegacyPathHelper::createRelativePath($target_directory);
366
367 $upload->moveOneFileTo($result, $relative_path_to_file, Location::STORAGE);
368
369 $this->handleQuotaUpdate($this);
370
371 // create preview?
372 if (!$a_prevent_preview) {
373 $this->createPreview(false);
374 }
375 } else {
376 throw new ilFileException('not supported File');
377 }
378 }
379
380 return $result;
381 }
382
383
392 public function replaceFile($a_upload_file, $a_filename)
393 {
394 if ($result = $this->getUploadFile($a_upload_file, $a_filename, true)) {
395 ilHistory::_createEntry($this->getId(), "replace", $a_filename . "," . $this->getVersion() . "," . $this->getMaxVersion());
396 $this->addNewsNotification("file_updated");
397
398 // create preview
399 $this->createPreview(true);
400 }
401
402 return $result;
403 }
404
405
414 public function addFileVersion($a_upload_file, $a_filename)
415 {
416 if ($result = $this->getUploadFile($a_upload_file, $a_filename, true)) {
417 ilHistory::_createEntry($this->getId(), "new_version", $result->getName() . "," . $this->getVersion() . "," . $this->getMaxVersion());
418 $this->addNewsNotification("file_updated");
419
420 // create preview
421 $this->createPreview($this->getVersion() > 1);
422 }
423
424 return $result;
425 }
426
427
431 public function copy($a_source, $a_destination)
432 {
433 return copy($a_source, $this->getDirectory() . "/" . $a_destination);
434 }
435
436
440 public function clearDataDirectory()
441 {
443 $this->createDirectory();
444 }
445
446
452 public function deleteVersions($a_hist_entry_ids = null)
453 {
454 if ($a_hist_entry_ids == null || count($a_hist_entry_ids) < 1) {
455 $this->clearDataDirectory();
456
458
460 } else {
461 $actualVersionDeleted = false;
462
463 // get all versions
464 $versions = $this->getVersions();
465
466 // delete each version
467 foreach ($a_hist_entry_ids as $hist_id) {
468 $entry = null;
469
470 // get version
471 foreach ($versions as $index => $version) {
472 if ($version["hist_entry_id"] == $hist_id) {
473 // remove each history entry
475
476 // delete directory
477 $version_dir = $this->getDirectory($version["version"]);
478 ilUtil::delDir($version_dir);
479
480 // is actual version?
481 if ($version["version"] == $this->getVersion()) {
482 $actualVersionDeleted = true;
483 }
484
485 // remove from array
486 unset($versions[$index]);
487 break;
488 }
489 }
490 }
491
492 // update actual version if it was deleted before
493 if ($actualVersionDeleted) {
494 // get newest version (already sorted by getVersions)
495 $version = reset($versions);
496 $version['max_version'] = $this->getMaxVersion();
498 } else {
499 // updateWithVersion() will trigger quota, too
501 }
502 }
503 }
504
505
506 protected function doRead()
507 {
508 global $DIC;
509
510 $q = "SELECT * FROM file_data WHERE file_id = %s";
511 $r = $DIC->database()->queryF($q, ['integer'], [$this->getId()]);
512 $row = $r->fetchObject();
513
514 $this->setFileName($row->file_name);
515 $this->setFileType($row->file_type);
516 $this->setFileSize($row->file_size);
517 $this->setVersion($row->version ? $row->version : 1);
518 $this->setMaxVersion($row->max_version ? $row->max_version : 1);
519 $this->setMode($row->f_mode);
520 $this->setRating($row->rating);
521 $this->setPageCount($row->page_count);
522
523 $this->initFileStorage();
524 }
525
526
527 protected function beforeUpdate()
528 {
529 // no meta data handling for file list files
530 if ($this->getMode() != self::MODE_FILELIST) {
531 $this->updateMetaData();
532 }
533
534 return true;
535 }
536
537
538 protected function doUpdate()
539 {
540 global $DIC;
541
542 $a_columns = $this->getArrayForDatabase();
543 $DIC->database()->update('file_data', $a_columns, [
544 'file_id' => [
545 'integer',
546 $this->getId(),
547 ],
548 ]);
549
550 // update metadata with the current file version
551 $meta_version_column = ['meta_version' => ['integer', (int) $this->getVersion()]];
552 $DIC->database()->update('il_meta_lifecycle', $meta_version_column, [
553 'obj_id' => [
554 'integer',
555 $this->getId(),
556 ],
557 ]);
558
560
561 return true;
562 }
563
564
568 protected function doUpdateMetaData()
569 {
570 // add technical section with file size and format
571 $md_obj = new ilMD($this->getId(), 0, $this->getType());
572 if (!is_object($technical = $md_obj->getTechnical())) {
573 $technical = $md_obj->addTechnical();
574 $technical->save();
575 }
576 $technical->setSize($this->getFileSize());
577
578 $format_ids = $technical->getFormatIds();
579 if (count($format_ids) > 0) {
580 $format = $technical->getFormat($format_ids[0]);
581 $format->setFormat($this->getFileType());
582 $format->update();
583 } else {
584 $format = $technical->addFormat();
585 $format->setFormat($this->getFileType());
586 $format->save();
587 }
588 $technical->update();
589 }
590
591
595 public function setFileName($a_name)
596 {
597 $this->filename = $a_name;
598 }
599
600
604 public function getFileName()
605 {
606 return $this->filename;
607 }
608
609
613 public function setFileType($a_type)
614 {
615 $this->filetype = $a_type;
616 }
617
618
622 public function getFileType()
623 {
624 return $this->filetype;
625 }
626
627
631 public function setFileSize($a_size)
632 {
633 $this->filesize = $a_size;
634 }
635
636
637 public function getFileSize()
638 {
639 return $this->filesize;
640 }
641
642
643 public function setAction($a_action)
644 {
645 $this->action = $a_action;
646 }
647
648
649 public function getAction()
650 {
651 return $this->action;
652 }
653
654
655 public function setRollbackVersion($a_rollback_version)
656 {
657 $this->rollback_version = $a_rollback_version;
658 }
659
660
661 public function getRollbackVersion()
662 {
664 }
665
666
667 public function setRollbackUserId($a_rollback_user_id)
668 {
669 $this->rollback_user_id = $a_rollback_user_id;
670 }
671
672
673 public function getRollbackUserId()
674 {
676 }
677
678
685 public function getDiskUsage()
686 {
687 require_once("./Modules/File/classes/class.ilObjFileAccess.php");
688
689 return ilObjFileAccess::_lookupDiskUsage($this->id);
690 }
691
692
693 // END PATCH WebDAV Encapsulate file access in ilObjFile class.
694 public function getFile($a_hist_entry_id = null)
695 {
696 if (is_null($a_hist_entry_id)) {
697 $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName();
698 } else {
699 require_once("./Services/History/classes/class.ilHistory.php");
700 $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
701
702 if ($entry === false) {
703 return false;
704 }
705
706 $data = $this->parseInfoParams($entry);
707 $file = $this->getDirectory($data["version"]) . "/" . $data["filename"];
708 }
709
710 return $file;
711 }
712
713
714 // END PATCH WebDAV Encapsulate file access in ilObjFile class.
715
716 public function setVersion($a_version)
717 {
718 $this->version = $a_version;
719 }
720
721
722 public function getVersion()
723 {
724 return $this->version;
725 }
726
727
728 public function setMaxVersion($a_max_version)
729 {
730 $this->max_version = $a_max_version;
731 }
732
733
734 public function getMaxVersion()
735 {
736 return $this->max_version;
737 }
738
739
745 public function setMode($a_mode)
746 {
747 $this->mode = $a_mode;
748 }
749
750
756 public function getMode()
757 {
758 return $this->mode;
759 }
760
761
762 public static function _writeFileType($a_id, $a_format)
763 {
764 global $DIC;
765 $ilDB = $DIC['ilDB'];
766
767 $q = "UPDATE file_data SET " . " file_type = " . $ilDB->quote($a_format, 'text')
768 . " WHERE file_id = " . $ilDB->quote($a_id, 'integer');
769 $res = $ilDB->manipulate($q);
770 }
771
772
779 public static function _lookupFileName($a_id)
780 {
781 global $DIC;
782 $ilDB = $DIC['ilDB'];
783
784 $q = "SELECT * FROM file_data WHERE file_id = " . $ilDB->quote($a_id, 'integer');
785 $r = $ilDB->query($q);
787
788 $strip_slashes = ilUtil::stripSlashes($row->file_name);
789
790 return $strip_slashes;
791 }
792
793
795 public static function _lookupFileSize($a_id)
796 {
797 require_once("./Modules/File/classes/class.ilObjFileAccess.php");
798
800 }
801
802
806 public static function _lookupVersion($a_id)
807 {
808 require_once("./Modules/File/classes/class.ilObjFileAccess.php");
809
811 }
812
813
817 public function determineFileSize($a_hist_entry_id = null)
818 {
819 if (is_null($a_hist_entry_id)) {
820 $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName();
821 } else {
822 require_once("./Services/History/classes/class.ilHistory.php");
823 $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
824
825 if ($entry === false) {
826 return false;
827 }
828
829 $data = $this->parseInfoParams($entry);
830 $file = $this->getDirectory($data["version"]) . "/" . $data["filename"];
831 }
832 if (is_file($file)) {
833 $this->setFileSize(filesize($file));
834 }
835 }
836
837
843 public function sendFile($a_hist_entry_id = null)
844 {
845 $s = new FilePathSanitizer($this);
846 $s->sanitizeIfNeeded();
847
848 if (is_null($a_hist_entry_id)) {
849 $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName();
850 $file = ilFileUtils::getValidFilename($file);
851 } else {
852 $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
853 $data = $this->parseInfoParams($entry);
854 $file = $this->getDirectory($data["version"]) . "/" . $data["filename"];
855 }
856
857
858 if ($this->file_storage->fileExists($file)) {
859 global $DIC;
860 $ilClientIniFile = $DIC['ilClientIniFile'];
865 $ilFileDelivery = new ilFileDelivery($file);
866 $ilFileDelivery->setDisposition($this->isInline() ? ilFileDelivery::DISP_INLINE : ilFileDelivery::DISP_ATTACHMENT);
867 $ilFileDelivery->setMimeType($this->guessFileType($file));
868 $ilFileDelivery->setConvertFileNameToAsci((bool) !$ilClientIniFile->readVariable('file_access', 'disable_ascii'));
869
870 // also returning the 'real' filename if a history file is delivered
871 if ($ilClientIniFile->readVariable('file_access', 'download_with_uploaded_filename')
872 != '1'
873 && is_null($a_hist_entry_id)
874 ) {
875 $ilFileDelivery->setDownloadFileName(ilFileUtils::getValidFilename($this->getTitle()));
876 } else {
877 // $download_file_name = basename($file);
878 /* FSX Info: basename has a Bug with Japanese and other characters, see:
879 * http://stackoverflow.com/questions/32115609/basename-fail-when-file-name-start-by-an-accent
880 * Therefore we can no longer use basename();
881 */
882 $parts = explode(DIRECTORY_SEPARATOR, $file);
883 $download_file_name = end($parts);
884 $download_file_name = ilFileUtils::getValidFilename($download_file_name);
885 $ilFileDelivery->setDownloadFileName($download_file_name);
886 }
887 $ilFileDelivery->deliver();
888
889 return true;
890 }
891
892 throw new FileNotFoundException($this->lng->txt('file_not_found_sec'));
893 }
894
895
900 public function getFileExtension()
901 {
902 require_once 'Modules/File/classes/class.ilObjFileAccess.php';
903
905 }
906
907
913 public function isInline()
914 {
915 require_once 'Modules/File/classes/class.ilObjFileAccess.php';
916
918 }
919
920
924 public function isHidden()
925 {
926 require_once 'Modules/File/classes/class.ilObjFileAccess.php';
927
929 }
930 // END WebDAV: Get file extension, determine if file is inline, guess file type.
931
932
939 public function guessFileType($a_file = "")
940 {
941 $path = pathinfo($a_file);
942 if ($path["extension"] != "") {
943 $filename = $path["basename"];
944 } else {
945 $filename = "dummy." . $this->getFileExtension();
946 }
947 include_once("./Services/Utilities/classes/class.ilMimeTypeUtil.php");
948 $mime = ilMimeTypeUtil::getMimeType($a_file, $filename, $this->getFileType());
949
950 return $mime;
951 }
952
953
964 protected function doCloneObject($a_new_obj, $a_target_id, $a_copy_id = 0)
965 {
966 global $DIC;
967 $ilDB = $DIC['ilDB'];
968
969 $a_new_obj->createDirectory();
970 $this->cloneMetaData($a_new_obj);
971
972 // Copy all file versions
973 ilUtil::rCopy($this->getDirectory(), $a_new_obj->getDirectory());
974
975 // object created now copy other settings
976 // bugfix mantis 26131
977 $DIC->database()->insert('file_data', $this->getArrayForDatabase($a_new_obj->getId()));
978
979 // copy all previews
980 require_once("./Services/Preview/classes/class.ilPreview.php");
981 ilPreview::copyPreviews($this->getId(), $a_new_obj->getId());
982
983 // copy history entries
984 require_once("./Services/History/classes/class.ilHistory.php");
985 ilHistory::_copyEntriesForObject($this->getId(), $a_new_obj->getId());
986
987 // Copy learning progress settings
988 include_once('Services/Tracking/classes/class.ilLPObjSettings.php');
989 $obj_settings = new ilLPObjSettings($this->getId());
990 $obj_settings->cloneSettings($a_new_obj->getId());
991 unset($obj_settings);
992
993 // add news notification
994 $a_new_obj->addNewsNotification("file_created");
995
996 return $a_new_obj;
997 }
998
999
1000 protected function beforeDelete()
1001 {
1002 global $DIC;
1003 $ilDB = $DIC['ilDB'];
1004
1005 // check, if file is used somewhere
1006 $usages = $this->getUsages();
1007 if (count($usages) == 0) {
1008 return true;
1009 }
1010
1011 return false;
1012 }
1013
1014
1015 protected function doDelete()
1016 {
1017 global $DIC;
1018 $ilDB = $DIC['ilDB'];
1019
1020 // delete file data entry
1021 $q = "DELETE FROM file_data WHERE file_id = " . $ilDB->quote($this->getId(), 'integer');
1022 $this->ilias->db->query($q);
1023
1024 // delete history entries
1025 require_once("./Services/History/classes/class.ilHistory.php");
1027
1029
1030 // delete entire directory and its content
1031 if (@is_dir($this->getDirectory())) {
1032 ilUtil::delDir($this->getDirectory());
1033 }
1034
1035 // delete meta data
1036 if ($this->getMode() != self::MODE_FILELIST) {
1037 $this->deleteMetaData();
1038 }
1039
1040 // delete preview
1041 $this->deletePreview();
1042 }
1043
1044
1052 public function export($a_target_dir)
1053 {
1054 $subdir = "il_" . IL_INST_ID . "_file_" . $this->getId();
1055 ilUtil::makeDir($a_target_dir . "/objects/" . $subdir);
1056
1057 $filedir = $this->getDirectory($this->getVersion());
1058
1059 if (@!is_dir($filedir)) {
1060 $filedir = $this->getDirectory();
1061 }
1062
1063 ilUtil::rCopy($filedir, $a_target_dir . "/objects/" . $subdir);
1064 }
1065
1066
1070 public static function _deleteAllUsages($a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
1071 {
1072 global $DIC;
1073 $ilDB = $DIC['ilDB'];
1074
1075 $and_hist = ($a_usage_hist_nr !== false) ? " AND usage_hist_nr = "
1076 . $ilDB->quote($a_usage_hist_nr, "integer") : "";
1077
1078 $file_ids = array();
1079 $set = $ilDB->query("SELECT id FROM file_usage" . " WHERE usage_type = "
1080 . $ilDB->quote($a_type, "text") . " AND usage_id= "
1081 . $ilDB->quote($a_id, "integer") . " AND usage_lang= "
1082 . $ilDB->quote($a_usage_lang, "text") . $and_hist);
1083 while ($row = $ilDB->fetchAssoc($set)) {
1084 $file_ids[] = $row["id"];
1085 }
1086
1087 $ilDB->manipulate("DELETE FROM file_usage WHERE usage_type = "
1088 . $ilDB->quote($a_type, "text") . " AND usage_id = "
1089 . $ilDB->quote((int) $a_id, "integer") . " AND usage_lang= "
1090 . $ilDB->quote($a_usage_lang, "text") . " AND usage_hist_nr = "
1091 . $ilDB->quote((int) $a_usage_hist_nr, "integer"));
1092
1093 foreach ($file_ids as $file_id) {
1094 self::handleQuotaUpdate(new self($file_id, false));
1095 }
1096 }
1097
1098
1102 public static function _saveUsage($a_file_id, $a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
1103 {
1104 global $DIC;
1105 $ilDB = $DIC['ilDB'];
1106
1107 // check if file really exists
1108 if (ilObject::_lookupType($a_file_id) != "file") {
1109 return;
1110 }
1111 // #15143
1112 $ilDB->replace("file_usage", array(
1113 "id" => array("integer", (int) $a_file_id),
1114 "usage_type" => array("text", (string) $a_type),
1115 "usage_id" => array("integer", (int) $a_id),
1116 "usage_hist_nr" => array("integer", (int) $a_usage_hist_nr),
1117 "usage_lang" => array("text", $a_usage_lang),
1118 ), array());
1119
1120 self::handleQuotaUpdate(new self($a_file_id, false));
1121 }
1122
1123
1127 public function getUsages()
1128 {
1129 global $DIC;
1130 $ilDB = $DIC['ilDB'];
1131
1132 // get usages in learning modules
1133 $q = "SELECT * FROM file_usage WHERE id = " . $ilDB->quote($this->getId(), "integer");
1134 $us_set = $ilDB->query($q);
1135 $ret = array();
1136 while ($us_rec = $ilDB->fetchAssoc($us_set)) {
1137 $ret[] = array(
1138 "type" => $us_rec["usage_type"],
1139 "id" => $us_rec["usage_id"],
1140 "lang" => $us_rec["usage_lang"],
1141 "hist_nr" => $us_rec["usage_hist_nr"],
1142 );
1143 }
1144
1145 return $ret;
1146 }
1147
1148
1157 public static function _getFilesOfObject($a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
1158 {
1159 global $DIC;
1160 $ilDB = $DIC['ilDB'];
1161
1162 $lstr = "";
1163 if ($a_usage_lang != "") {
1164 $lstr = "usage_lang = " . $ilDB->quote((string) $a_usage_lang, "text") . " AND ";
1165 }
1166
1167 // get usages in learning modules
1168 $q = "SELECT * FROM file_usage WHERE " . "usage_id = " . $ilDB->quote((int) $a_id, "integer")
1169 . " AND " . "usage_type = " . $ilDB->quote((string) $a_type, "text") . " AND " . $lstr
1170 . "usage_hist_nr = " . $ilDB->quote((int) $a_usage_hist_nr, "integer");
1171 $file_set = $ilDB->query($q);
1172 $ret = array();
1173 while ($file_rec = $ilDB->fetchAssoc($file_set)) {
1174 $ret[$file_rec["id"]] = $file_rec["id"];
1175 }
1176
1177 return $ret;
1178 }
1179
1180
1181 // TODO: What is this function good for??
1182 public function getXMLZip()
1183 {
1184 global $DIC;
1185 $ilias = $DIC['ilias'];
1186
1187 $zip = PATH_TO_ZIP;
1188
1189 exec($zip . ' ' . ilUtil::escapeShellArg($this->getDirectory() . '/' . $this->getFileName())
1190 . " " . ilUtil::escapeShellArg($this->getDirectory() . '/' . '1.zip'));
1191
1192 return $this->getDirectory() . '/1.zip';
1193 }
1194
1195
1196 public function addNewsNotification($a_lang_var)
1197 {
1198 // BEGIN WebDAV Suppress news notification for hidden files
1199 if ($this->isHidden()) {
1200 return;
1201 }
1202 // END WebDAV Suppress news notification for hidden files
1203
1204 global $DIC;
1205 $ilUser = $DIC['ilUser'];
1206
1207 // Add Notification to news
1208 include_once("./Services/News/classes/class.ilNewsItem.php");
1209 include_once("./Modules/File/classes/class.ilObjFileAccess.php");
1210 $news_item = new ilNewsItem();
1211 $news_item->setContext($this->getId(), $this->getType());
1212 $news_item->setPriority(NEWS_NOTICE);
1213 $news_item->setTitle($a_lang_var);
1214 $news_item->setContentIsLangVar(true);
1215 if ($this->getDescription() != "") {
1216 $news_item->setContent("<p>" . $this->getDescription() . "</p>");
1217 }
1218 $news_item->setUserId($ilUser->getId());
1219 $news_item->setVisibility(NEWS_USERS);
1220 $news_item->create();
1221 }
1222
1223
1230 public function initFileStorage()
1231 {
1232 $this->file_storage = new ilFSStorageFile($this->getId());
1233
1234 return true;
1235 }
1236
1237
1247 public function storeUnzipedFile($a_upload_file, $a_filename)
1248 {
1249 $this->setVersion($this->getVersion() + 1);
1250
1251 if (@!is_dir($this->getDirectory($this->getVersion()))) {
1252 ilUtil::makeDir($this->getDirectory($this->getVersion()));
1253 }
1254
1255 $file = $this->getDirectory($this->getVersion()) . "/" . $a_filename;
1256
1257 $file = ilFileUtils::getValidFilename($file);
1258
1259 ilFileUtils::rename($a_upload_file, $file);
1260
1261 // create preview
1262 $this->createPreview();
1263 }
1264
1265
1273 public static function _lookupAbsolutePath($obj_id, $a_version = null)
1274 {
1275 $file_object = new self($obj_id, false);
1276 $s = new FilePathSanitizer($file_object);
1277 $s->sanitizeIfNeeded();
1278
1279 return $file_object->getFile($a_version);
1280 }
1281
1282
1288 public function checkFileExtension($new_filename, $new_title)
1289 {
1290 include_once './Modules/File/classes/class.ilObjFileAccess.php';
1291 $fileExtension = ilObjFileAccess::_getFileExtension($new_filename);
1292 $titleExtension = ilObjFileAccess::_getFileExtension($new_title);
1293 if ($titleExtension != $fileExtension && strlen($fileExtension) > 0) {
1294 // remove old extension
1295 $pi = pathinfo($this->getFileName());
1296 $suffix = $pi["extension"];
1297 if ($suffix != "") {
1298 if (substr($new_title, strlen($new_title) - strlen($suffix) - 1) == "." . $suffix) {
1299 $new_title = substr($new_title, 0, strlen($new_title) - strlen($suffix) - 1);
1300 }
1301 }
1302 $new_title .= '.' . $fileExtension;
1303 }
1304
1305 return $new_title;
1306 }
1307
1308
1329 public function getVersions($version_ids = null) : array
1330 {
1331 $versions = (array) ilHistory::_getEntriesForObject($this->getId(), $this->getType());
1332
1333 if ($version_ids != null && count($version_ids) > 0) {
1334 foreach ($versions as $index => $version) {
1335 if (!in_array($version["hist_entry_id"], $version_ids, true)) {
1336 unset($versions[$index]);
1337 }
1338 }
1339 }
1340
1341 // add custom entries
1342 foreach ($versions as $index => $version) {
1344 $versions[$index] = array_merge($version, $params);
1345 }
1346
1347 // sort by version number (hist_entry_id will do for that)
1348 usort($versions, array($this, "compareVersions"));
1349
1350 return $versions;
1351 }
1352
1353
1361 public function getSpecificVersion($version_id)
1362 {
1363 include_once("./Services/History/classes/class.ilHistory.php");
1365 if ($version === false) {
1366 return false;
1367 }
1368
1369 // ilHistory returns different keys in _getEntryByHistoryID and _getEntriesForObject
1370 // so this makes it the same
1371 $version["hist_entry_id"] = $version["id"];
1372 $version["user_id"] = $version["usr_id"];
1373 $version["date"] = $version["hdate"];
1374 unset($version["id"], $version["usr_id"], $version["hdate"]);
1375
1376 // parse params
1378
1379 return array_merge($version, $params);
1380 }
1381
1382
1390 public function rollback($version_id)
1391 {
1392 global $DIC;
1393 $ilDB = $DIC['ilDB'];
1394 $ilUser = $DIC['ilUser'];
1395
1396 $source = $this->getSpecificVersion($version_id);
1397 if ($source === false) {
1398 $this->ilErr->raiseError($this->lng->txt("obj_not_found"), $this->ilErr->MESSAGE);
1399 }
1400
1401 // get the new version number
1402 $new_version_nr = $this->getMaxVersion() + 1;
1403 $this->setMaxVersion($new_version_nr);
1404
1405 // copy file
1406 $source_path = $this->getDirectory($source["version"]) . "/" . $source["filename"];
1407 $dest_dir = $this->getDirectory($new_version_nr);
1408 if (@!is_dir($dest_dir)) {
1409 ilUtil::makeDir($dest_dir);
1410 }
1411
1412 copy($source_path, $dest_dir . "/" . $source["filename"]);
1413
1414 // create new history entry based on the old one
1415 include_once("./Services/History/classes/class.ilHistory.php");
1416 // bugfix mantis 26236: added rollback info to version instead of max_version to ensure compatibility with older ilias versions
1417 ilHistory::_createEntry($this->getId(), "rollback", $source["filename"] . ","
1418 . $new_version_nr . "|"
1419 . $source["version"] . "|"
1420 . $ilUser->getId() . ","
1421 . $this->getMaxVersion());
1422
1423 // get id of newest entry
1424 $entries = ilHistory::_getEntriesForObject($this->getId());
1425 $newest_entry_id = 0;
1426 foreach ($entries as $entry) {
1427 if ($entry["action"] == "rollback") {
1428 $newest_entry_id = $entry["hist_entry_id"];
1429 }
1430 }
1431 $new_version = $this->getSpecificVersion($newest_entry_id);
1432 $new_version['version'] = $new_version_nr;
1433 $new_version['max_version'] = $new_version_nr;
1434
1435 // change user back to the original uploader
1436 ilHistory::_changeUserId($new_version["hist_entry_id"], $source["user_id"]);
1437
1438 // update this file with the new version
1439 $this->updateWithVersion($new_version);
1440
1441 $this->addNewsNotification("file_updated");
1442
1443 return $new_version;
1444 }
1445
1446
1452 protected function updateWithVersion($version)
1453 {
1454 // update title (checkFileExtension must be called before setFileName!)
1455 $this->setTitle($this->checkFileExtension($version["filename"], $this->getTitle()));
1456
1457 $this->setVersion($version["version"]);
1458 $this->setMaxVersion($version["max_version"]);
1459 $this->setFileName($version["filename"]);
1460
1461 // evaluate mime type (reset file type before)
1462 $this->setFileType("");
1463 $this->setFileType($this->guessFileType($version["filename"]));
1464
1465 // set filesize
1466 $this->determineFileSize();
1467
1468 $this->update();
1469
1470 // refresh preview
1471 $this->createPreview(true);
1472 }
1473
1474
1485 public function compareVersions($v1, $v2)
1486 {
1487 // v2 - v1 because version should be descending
1488 return (int) $v2["version"] - (int) $v1["version"];
1489 }
1490
1491
1500 private function parseInfoParams($entry)
1501 {
1502 $data = explode(",", $entry["info_params"]);
1503
1504 // bugfix: first created file had no version number
1505 // this is a workaround for all files created before the bug was fixed
1506 if (empty($data[1])) {
1507 $data[1] = "1";
1508 }
1509
1510 if (empty($data[2])) {
1511 $data[2] = "1";
1512 }
1513
1514// BEGIN bugfix #27391
1515 if (sizeof($data) > 3)
1516 {
1517 $last = sizeof($data) - 1;
1518 for ($n = 1; $n < $last - 1; $n++)
1519 {
1520 $data[0] .= "," . $data[$n];
1521 }
1522 $data[1] = $data[$last - 1];
1523 $data[2] = $data[$last];
1524 }
1525// END bugfix #27391
1526
1527 $result = array(
1528 "filename" => $data[0],
1529 "version" => $data[1],
1530 "max_version" => $data[2],
1531 "rollback_version" => "",
1532 "rollback_user_id" => "",
1533 );
1534
1535 // if rollback, the version contains the rollback version as well
1536 // bugfix mantis 26236: rollback info is read from version to ensure compatibility with older ilias versions
1537 if ($entry["action"] == "rollback") {
1538 $tokens = explode("|", $result["version"]);
1539 if (count($tokens) > 1) {
1540 $result["version"] = $tokens[0];
1541 $result["rollback_version"] = $tokens[1];
1542
1543 if (count($tokens) > 2) {
1544 $result["rollback_user_id"] = $tokens[2];
1545 }
1546 }
1547 }
1548
1549 return $result;
1550 }
1551
1552
1553 protected static function handleQuotaUpdate(ilObjFile $a_file)
1554 {
1555 include_once "Services/MediaObjects/classes/class.ilObjMediaObject.php";
1556 $mob = new ilObjMediaObject();
1557
1558 // file itself could be workspace item
1559 $parent_obj_ids = array($a_file->getId());
1560
1561 foreach ($a_file->getUsages() as $item) {
1562 $parent_obj_id = $mob->getParentObjectIdForUsage($item);
1563 if ($parent_obj_id
1564 && !in_array($parent_obj_id, $parent_obj_ids)
1565 ) {
1566 $parent_obj_ids[] = $parent_obj_id;
1567 }
1568 }
1569
1570 include_once "Services/DiskQuota/classes/class.ilDiskQuotaHandler.php";
1571 ilDiskQuotaHandler::handleUpdatedSourceObject($a_file->getType(), $a_file->getId(), $a_file->getDiskUsage(), $parent_obj_ids);
1572 }
1573
1574
1581 protected function createPreview($force = false)
1582 {
1583 // only normal files are supported
1584 if ($this->getMode() != self::MODE_OBJECT) {
1585 return;
1586 }
1587
1588 require_once("./Services/Preview/classes/class.ilPreview.php");
1589 ilPreview::createPreview($this, $force);
1590 }
1591
1592
1596 protected function deletePreview()
1597 {
1598 // only normal files are supported
1599 if ($this->getMode() != self::MODE_OBJECT) {
1600 return;
1601 }
1602
1603 require_once("./Services/Preview/classes/class.ilPreview.php");
1605 }
1606
1607
1611 public function setRating($a_value)
1612 {
1613 $this->rating = (bool) $a_value;
1614 }
1615
1616
1620 public function hasRating()
1621 {
1622 return $this->rating;
1623 }
1624
1625
1629 public function getPageCount()
1630 {
1631 return $this->page_count;
1632 }
1633
1634
1638 public function setPageCount($page_count)
1639 {
1640 $this->page_count = $page_count;
1641 }
1642
1643
1649 private function getArrayForDatabase($file_id = 0)
1650 {
1651 if ($file_id == 0) {
1652 $file_id = $this->getId();
1653 }
1654 return [
1655 'file_id' => ['integer', $file_id],
1656 'file_name' => ['text', $this->getFileName()],
1657 'file_type' => ['text', $this->getFileType()],
1658 'file_size' => ['integer', (int) $this->getFileSize()],
1659 'version' => ['integer', (int) $this->getVersion()],
1660 'max_version' => ['integer', (int) $this->getMaxVersion()],
1661 'f_mode' => ['text', $this->getMode()],
1662 'page_count' => ['text', $this->getPageCount()],
1663 'rating' => ['integer', $this->hasRating()],
1664 ];
1665 }
1666}
$result
$n
Definition: RandomTest.php:85
$metadata['__DYNAMIC:1__']
$path
Definition: aliased.php:25
$source
Definition: linkback.php:22
$_GET["client_id"]
An exception for terminatinating execution or to throw for unit testing.
const NEWS_USERS
const NEWS_NOTICE
static _write($a_type, $a_setting, $a_value, $a_user=0, $a_block_id=0)
Write setting to database.
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 ilFSStorageFile.
Class ilFileDelivery.
Class to report exception.
static getValidFilename($a_filename)
Get valid filename.
static rename($a_source, $a_target)
Rename a file.
static _removeEntryByHistoryID($a_hist_entry_id)
Removes a single entry from the history.
static _changeUserId($a_hist_entry_id, $new_user_id)
Changes the user id of the specified history entry.
static _removeEntriesForObject($a_obj_id)
remove all history entries for an object
static _getEntriesForObject($a_obj_id, $a_obj_type="")
get all history entries for an 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 _copyEntriesForObject($a_src_id, $a_dst_id)
copy all history entries for an object
static _getEntryByHistoryID($a_hist_entry_id)
returns a single history entry
static getLogger($a_component_id)
Get component logger.
static getMimeType($a_file='', $a_filename='', $a_mime='')
static _getDefaultVisibilityForRefId($a_ref_id)
Get default visibility for reference id.
static _lookupFileSize($a_id)
Quickly looks up the file size from the database and returns the number of bytes.
static _lookupVersion($a_id)
lookup version
static _getFileExtension($a_file_name)
Gets the file extension of the specified file name.
static _isFileHidden($a_file_name)
Returns true, if a file with the specified name, is usually hidden from the user.
static _isFileInline($a_file_name)
Returns true, if the specified file shall be displayed inline in the browser.
static _lookupDiskUsage($a_id)
Returns the number of bytes used on the harddisk by the file object with the specified object id.
Class ilObjFile.
getArrayForDatabase($file_id=0)
static _lookupFileSize($a_id)
Lookups the file size of the file in bytes.
static _lookupFileName($a_id)
raiseUploadError($a_raise=true)
setMaxVersion($a_max_version)
setFileSize($a_size)
clearDataDirectory()
clear data directory
static handleQuotaUpdate(ilObjFile $a_file)
updateWithVersion($version)
Updates the file object with the specified file version.
static _getFilesOfObject($a_type, $a_id, $a_usage_hist_nr=0, $a_usage_lang="-")
get all files of an object
const MODE_FILELIST
const MODE_OBJECT
doCreate($a_upload=false)
create object
addFileVersion($a_upload_file, $a_filename)
createProperties($a_upload=false)
The basic properties of a file object are stored in table object_data.
setAction($a_action)
getFile($a_hist_entry_id=null)
doUpdateMetaData()
update meta data
initFileStorage()
init file storage object
static _saveUsage($a_file_id, $a_type, $a_id, $a_usage_hist_nr=0, $a_usage_lang="-")
save usage
beforeMDUpdateListener($a_element)
copy($a_source, $a_destination)
copy file
createPreview($force=false)
Creates a preview for the file object.
setFileType($a_type)
doMDUpdateListener($a_element)
isInline()
Returns true, if this file should be displayed inline in a browser window.
__construct($a_id=0, $a_call_by_reference=true)
ilObjFile constructor.
getSpecificVersion($version_id)
Gets a specific file version.
static _lookupAbsolutePath($obj_id, $a_version=null)
doCreateMetaData()
create file object meta data
getVersions($version_ids=null)
Gets the file versions for this object.
setMode($a_mode)
mode is object or filelist
deleteVersions($a_hist_entry_ids=null)
Deletes the specified history entries or all entries if no ids are specified.
setFileName($a_name)
setRollbackUserId($a_rollback_user_id)
replaceFile($a_upload_file, $a_filename)
doCloneObject($a_new_obj, $a_target_id, $a_copy_id=0)
Clone.
export($a_target_dir)
export files of object to target directory note: target directory must be the export target directory...
setNoMetaDataCreation($a_status)
checkFileExtension($new_filename, $new_title)
Check if the file extension does still exist after an update of the title.
static _deleteAllUsages($a_type, $a_id, $a_usage_hist_nr=0, $a_usage_lang="-")
static delete all usages of
getDirectory($a_version=0)
getMode()
mode is object or filelist
setRating($a_value)
deletePreview()
Deletes the preview of the file object.
compareVersions($v1, $v2)
Compares two file versions.
static _writeFileType($a_id, $a_format)
setRollbackVersion($a_rollback_version)
addNewsNotification($a_lang_var)
determineFileSize($a_hist_entry_id=null)
Determine File Size.
setPageCount($page_count)
setVersion($a_version)
getUsages()
get all usages of file object
getFileExtension()
Returns the extension of the file name converted to lower-case.
static _lookupVersion($a_id)
lookup version
getDiskUsage()
Gets the disk usage of the object in bytes.
parseInfoParams($entry)
Parses the info parameters ("info_params") of the specified history entry.
guessFileType($a_file="")
Guesses the file type based on the current values returned by getFileType() and getFileExtension().
rollback($version_id)
Makes the specified version the current one and returns theSummary of rollbackVersion.
storeUnzipedFile($a_upload_file, $a_filename)
storeUnzipedFile
isHidden()
Returns true, if this file should be hidden in the repository view.
Class ilObjMediaObject.
Class ilObject2 This is an intermediate progress of ilObject class.
setTitle($a_title)
set object title
createMetaData()
create meta data entry
cloneMetaData($target_obj)
Copy meta data.
deleteMetaData()
delete meta data entry
updateMetaData()
update meta data entry
getType()
get object type @access public
getDescription()
get object description
update()
update object in db
getId()
get object id @access public
getTitle()
get object title @access public
static _lookupType($a_id, $a_reference=false)
lookup object type
static copyPreviews($a_src_id, $a_dest_id)
Copies the preview images from one preview to a new preview object.
static deletePreview($a_obj_id)
Deletes the preview for the object with the specified id.
static createPreview($a_obj, $a_force=false)
Creates the preview for the object with the specified id.
static getBytesForString($a_str)
Return string as byte array Note: Use this for debugging purposes only.
static delDir($a_dir, $a_clean_only=false)
removes a dir and all its content (subdirs and files) recursively
static escapeShellArg($a_arg)
static rCopy($a_sdir, $a_tdir, $preserveTimeAttributes=false)
Copies content of a directory $a_sdir recursively to a directory $a_tdir.
static stripSlashes($a_str, $a_strip_html=true, $a_allow="")
strip slashes if magic qoutes is enabled
static makeDirParents($a_dir)
Create a new directory and all parent directories.
static makeDir($a_dir)
creates a new directory and inherits all filesystem permissions of the parent directory You may pass ...
$r
Definition: example_031.php:79
Interface Location.
Definition: Location.php:17
$format
Definition: metadata.php:141
$index
Definition: metadata.php:60
$row
Class BaseForm.
redirection script todo: (a better solution should control the processing via a xml file)
$ret
Definition: parser.php:6
$s
Definition: pwgen.php:45
global $DIC
Definition: saml.php:7
foreach($_POST as $key=> $value) $res
global $ilDB
$ilUser
Definition: imgupload.php:18
$data
Definition: bench.php:6
$a_type
Definition: workflow.php:92