ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
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 use ilObjFileSecureString;
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;
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 {
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
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();
481 } else {
482 // updateWithVersion() will trigger quota, too
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
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
783 }
784
785
789 public static function _lookupVersion($a_id)
790 {
791 require_once("./Modules/File/classes/class.ilObjFileAccess.php");
792
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
900 }
901
902
906 public function isHidden()
907 {
908 require_once 'Modules/File/classes/class.ilObjFileAccess.php';
909
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
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");
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}
$result
$_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.
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
getTitle()
get object title @access public
getId()
get object id @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 ...
Interface Location.
Definition: Location.php:17
$format
Definition: metadata.php:218
$index
Definition: metadata.php:128
$source
Definition: metadata.php:76
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
Class ChatMainBarProvider \MainMenu\Provider.
redirection script todo: (a better solution should control the processing via a xml file)
$ret
Definition: parser.php:6
$query
foreach($_POST as $key=> $value) $res
global $ilDB
$data
Definition: storeScorm.php:23
$ilUser
Definition: imgupload.php:18
$a_type
Definition: workflow.php:92
$DIC
Definition: xapitoken.php:46