ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 
7 
8 require_once("Services/Object/classes/class.ilObject2.php");
9 require_once('Modules/File/classes/class.ilFSStorageFile.php');
10 
20 class ilObjFile extends ilObject2
21 {
22  const MODE_FILELIST = "filelist";
23  const MODE_OBJECT = "object";
31  protected $filename = '';
35  protected $filetype = '';
39  protected $filemaxsize = "20000000"; // not used yet
43  protected $filesize;
51  public $mode = self::MODE_OBJECT;
55  protected $page_count = 0;
59  protected $rating = false;
63  private $file_storage = null;
67  protected $log = null;
71  protected $version = 1;
72 
73 
80  public function __construct($a_id = 0, $a_call_by_reference = true)
81  {
82  $this->version = 0;
83  $this->raise_upload_error = true;
84 
85  $this->log = ilLoggerFactory::getLogger('file');
86 
87  parent::__construct($a_id, $a_call_by_reference);
88 
89  if ($this->getId()) {
90  $this->initFileStorage();
91  }
92  }
93 
94 
95  public function initType()
96  {
97  $this->type = "file";
98  }
99 
100 
106  protected function doCreate($a_upload = false)
107  {
108  $this->createProperties($a_upload);
109  }
110 
111 
119  public function createProperties($a_upload = false)
120  {
121  global $DIC;
122 
123  // Create file directory
124  $this->initFileStorage();
125  $this->file_storage->create();
126 
127  if ($a_upload) {
128  return true;
129  }
130 
131  // not upload mode
132  ilHistory::_createEntry($this->getId(), "create", $this->getFileName() . ",1");
133  $this->addNewsNotification("file_created");
134 
135  // New Item
136  $default_visibility = ilNewsItem::_getDefaultVisibilityForRefId($_GET['ref_id']);
137  if ($default_visibility == "public") {
138  ilBlockSetting::_write("news", "public_notifications", 1, 0, $this->getId());
139  }
140 
141  // log creation
142  $this->log->debug("ilObjFile::createProperties, ID: " . $this->getId() . ", Name: "
143  . $this->getFileName() . ", Type: " . $this->getFileType() . ", Size: "
144  . $this->getFileSize() . ", Mode: " . $this->getMode() . ", Name(Bytes): "
145  . implode(":", ilStr::getBytesForString($this->getFileName())));
146  $this->log->logStack(ilLogLevel::DEBUG);
147 
148  $DIC->database()->insert('file_data', $this->getArrayForDatabase());
149 
150  // no meta data handling for file list files
151  if ($this->getMode() != self::MODE_FILELIST) {
152  $this->createMetaData();
153  }
154  }
155 
156 
160  public function setNoMetaDataCreation($a_status)
161  {
162  $this->no_meta_data_creation = (bool) $a_status;
163  }
164 
165 
166  protected function beforeCreateMetaData()
167  {
168  return !(bool) $this->no_meta_data_creation;
169  }
170 
171 
172  protected function beforeUpdateMetaData()
173  {
174  return !(bool) $this->no_meta_data_creation;
175  }
176 
177 
181  protected function doCreateMetaData()
182  {
183  // add technical section with file size and format
184  $md_obj = new ilMD($this->getId(), 0, $this->getType());
185  $technical = $md_obj->addTechnical();
186  $technical->setSize($this->getFileSize());
187  $technical->save();
188  $format = $technical->addFormat();
189  $format->setFormat($this->getFileType());
190  $format->save();
191  $technical->update();
192  }
193 
194 
195  protected function beforeMDUpdateListener($a_element)
196  {
197  // Check file extension
198  // Removing the file extension is not allowed
199  include_once 'Services/MetaData/classes/class.ilMD.php';
200  $md = new ilMD($this->getId(), 0, $this->getType());
201  if (!is_object($md_gen = $md->getGeneral())) {
202  return false;
203  }
204  $title = $this->checkFileExtension($this->getFileName(), $md_gen->getTitle());
205  $md_gen->setTitle($title);
206  $md_gen->update();
207 
208  return true;
209  }
210 
211 
212  protected function doMDUpdateListener($a_element)
213  {
214  // handling for technical section
215  include_once 'Services/MetaData/classes/class.ilMD.php';
216 
217  switch ($a_element) {
218  case 'Technical':
219 
220  // Update Format (size is not stored in db)
221  $md = new ilMD($this->getId(), 0, $this->getType());
222  if (!is_object($md_technical = $md->getTechnical())) {
223  return false;
224  }
225 
226  foreach ($md_technical->getFormatIds() as $id) {
227  $md_format = $md_technical->getFormat($id);
228  ilObjFile::_writeFileType($this->getId(), $md_format->getFormat());
229  $this->setFileType($md_format->getFormat());
230  break;
231  }
232 
233  break;
234  }
235 
236  return true;
237  }
238 
239 
245  public function getDirectory($a_version = 0)
246  {
247  $version_subdir = "";
248 
249  if ($a_version) {
250  // BEGIN WebDAV Avoid double slash before version subdirectory
251  $version_subdir = sprintf("%03d", $a_version);
252  // END WebDAV Avoid double slash before version subdirectory
253  }
254 
255  if (!is_object($this->file_storage)) {
256  $this->initFileStorage();
257  }
258 
259  $str = $this->file_storage->getAbsolutePath() . '/' . $version_subdir;
260 
261  return $str;
262  }
263 
264 
265  public function createDirectory()
266  {
268  }
269 
270 
271  public function raiseUploadError($a_raise = true)
272  {
273  $this->raise_upload_error = $a_raise;
274  }
275 
276 
286  public function getUploadFile($a_upload_file, $a_filename, $a_prevent_preview = false)
287  {
288  global $DIC;
289 
290  $upload = $DIC->upload();
291  $result = null;
292 
293  if ($upload->hasUploads()) {
294  if ($upload->hasBeenProcessed() !== true) {
295  if (PATH_TO_GHOSTSCRIPT !== "") {
296  $upload->register(new ilCountPDFPagesPreProcessors());
297  }
298  $upload->process();
299  }
303  $result = $upload->getResults()[$a_upload_file];
304  if ($result->getStatus()->getCode() === \ILIAS\FileUpload\DTO\ProcessingStatus::OK) {
305  $metadata = $result->getMetaData();
308  $this->doUpdate();
309  }
310  $a_name = $result->getName();
311  $this->setFileName($a_name);
312 
313  $this->setVersion($this->getVersion() + 1);
314 
315  if (!is_dir($this->getDirectory($this->getVersion()))) {
317  }
318 
319  $target_directory = $this->getDirectory($this->getVersion()) . "/";
320  $relative_path_to_file = LegacyPathHelper::createRelativePath($target_directory);
321 
322  $upload->moveOneFileTo($result, $relative_path_to_file, Location::STORAGE);
323 
324  $this->handleQuotaUpdate($this);
325 
326  // create preview?
327  if (!$a_prevent_preview) {
328  $this->createPreview(false);
329  }
330  } else {
331  throw new ilFileException('not supported File');
332  }
333  }
334 
335  return $result;
336  }
337 
338 
346  public function replaceFile($a_upload_file, $a_filename)
347  {
348  if ($result = $this->getUploadFile($a_upload_file, $a_filename, true)) {
349  ilHistory::_createEntry($this->getId(), "replace", $a_filename . "," . $this->getVersion());
350  $this->addNewsNotification("file_updated");
351 
352  // create preview
353  $this->createPreview(true);
354  }
355 
356  return $result;
357  }
358 
359 
360  public function addFileVersion($a_upload_file, $a_filename)
361  {
362  if ($result = $this->getUploadFile($a_upload_file, $a_filename, true)) {
363  ilHistory::_createEntry($this->getId(), "new_version", $result->getName() . "," . $this->getVersion());
364  $this->addNewsNotification("file_updated");
365 
366  // create preview
367  $this->createPreview($this->getVersion() > 1);
368  }
369 
370  return $result;
371  }
372 
373 
377  public function copy($a_source, $a_destination)
378  {
379  return copy($a_source, $this->getDirectory() . "/" . $a_destination);
380  }
381 
382 
386  public function clearDataDirectory()
387  {
388  ilUtil::delDir($this->getDirectory());
389  $this->createDirectory();
390  }
391 
392 
398  public function deleteVersions($a_hist_entry_ids = null)
399  {
400  global $DIC;
401  $ilDB = $DIC['ilDB'];
402 
403  if ($a_hist_entry_ids == null || count($a_hist_entry_ids) < 1) {
404  $ilDB->manipulate("UPDATE file_data SET version = 1 WHERE file_id = "
405  . $ilDB->quote($this->getId(), 'integer'));
406  $this->setVersion(0);
407  $this->clearDataDirectory();
408 
410 
411  self::handleQuotaUpdate($this);
412  } else {
413  $actualVersionDeleted = false;
414 
415  // get all versions
416  $versions = $this->getVersions();
417 
418  // delete each version
419  foreach ($a_hist_entry_ids as $hist_id) {
420  $entry = null;
421 
422  // get version
423  foreach ($versions as $index => $version) {
424  if ($version["hist_entry_id"] == $hist_id) {
425  // remove each history entry
427 
428  // delete directory
429  $version_dir = $this->getDirectory($version["version"]);
430  ilUtil::delDir($version_dir);
431 
432  // is actual version?
433  if ($version["version"] == $this->getVersion()) {
434  $actualVersionDeleted = true;
435  }
436 
437  // remove from array
438  unset($versions[$index]);
439  break;
440  }
441  }
442  }
443 
444  // update actual version if it was deleted before
445  if ($actualVersionDeleted) {
446  // get newest version (already sorted by getVersions)
447  $version = reset($versions);
448  $this->updateWithVersion($version);
449  } else {
450  // updateWithVersion() will trigger quota, too
451  self::handleQuotaUpdate($this);
452  }
453  }
454  }
455 
456 
457  protected function doRead()
458  {
459  global $DIC;
460 
461  $q = "SELECT * FROM file_data WHERE file_id = %s";
462  $r = $DIC->database()->queryF($q, ['integer'], [$this->getId()]);
463  $row = $r->fetchObject();
464 
465  $this->setFileName($row->file_name);
466  $this->setFileType($row->file_type);
467  $this->setFileSize($row->file_size);
468  $this->setVersion($row->version ? $row->version : 1);
469  $this->setMode($row->f_mode);
470  $this->setRating($row->rating);
471  $this->setPageCount($row->page_count);
472 
473  $this->initFileStorage();
474  }
475 
476 
477  protected function beforeUpdate()
478  {
479  // no meta data handling for file list files
480  if ($this->getMode() != self::MODE_FILELIST) {
481  $this->updateMetaData();
482  }
483 
484  return true;
485  }
486 
487 
488  protected function doUpdate()
489  {
490  global $DIC;
491 
492  $a_columns = $this->getArrayForDatabase();
493  $DIC->database()->update('file_data', $a_columns, [
494  'file_id' => [
495  'integer',
496  $this->getId(),
497  ],
498  ]);
499 
500  self::handleQuotaUpdate($this);
501 
502  return true;
503  }
504 
505 
509  protected function doUpdateMetaData()
510  {
511  // add technical section with file size and format
512  $md_obj = new ilMD($this->getId(), 0, $this->getType());
513  if (!is_object($technical = $md_obj->getTechnical())) {
514  $technical = $md_obj->addTechnical();
515  $technical->save();
516  }
517  $technical->setSize($this->getFileSize());
518 
519  $format_ids = $technical->getFormatIds();
520  if (count($format_ids) > 0) {
521  $format = $technical->getFormat($format_ids[0]);
522  $format->setFormat($this->getFileType());
523  $format->update();
524  } else {
525  $format = $technical->addFormat();
526  $format->setFormat($this->getFileType());
527  $format->save();
528  }
529  $technical->update();
530  }
531 
532 
536  public function setFileName($a_name)
537  {
538  $this->filename = $a_name;
539  }
540 
541 
545  public function getFileName()
546  {
547  return $this->filename;
548  }
549 
550 
554  public function setFileType($a_type)
555  {
556  $this->filetype = $a_type;
557  }
558 
559 
563  public function getFileType()
564  {
565  return $this->filetype;
566  }
567 
568 
572  public function setFileSize($a_size)
573  {
574  $this->filesize = $a_size;
575  }
576 
577 
578  public function getFileSize()
579  {
580  return $this->filesize;
581  }
582 
583 
590  public function getDiskUsage()
591  {
592  require_once("./Modules/File/classes/class.ilObjFileAccess.php");
593 
594  return ilObjFileAccess::_lookupDiskUsage($this->id);
595  }
596 
597 
598  // END PATCH WebDAV Encapsulate file access in ilObjFile class.
599  public function getFile($a_hist_entry_id = null)
600  {
601  if (is_null($a_hist_entry_id)) {
602  $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName();
603  } else {
604  require_once("./Services/History/classes/class.ilHistory.php");
605  $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
606 
607  if ($entry === false) {
608  return false;
609  }
610 
611  $data = $this->parseInfoParams($entry);
612  $file = $this->getDirectory($data["version"]) . "/" . $data["filename"];
613  }
614 
615  return $file;
616  }
617 
618 
619  // END PATCH WebDAV Encapsulate file access in ilObjFile class.
620 
621  public function setVersion($a_version)
622  {
623  $this->version = $a_version;
624  }
625 
626 
627  public function getVersion()
628  {
629  return $this->version;
630  }
631 
632 
638  public function setMode($a_mode)
639  {
640  $this->mode = $a_mode;
641  }
642 
643 
649  public function getMode()
650  {
651  return $this->mode;
652  }
653 
654 
655  public static function _writeFileType($a_id, $a_format)
656  {
657  global $DIC;
658  $ilDB = $DIC['ilDB'];
659 
660  $q = "UPDATE file_data SET " . " file_type = " . $ilDB->quote($a_format, 'text')
661  . " WHERE file_id = " . $ilDB->quote($a_id, 'integer');
662  $res = $ilDB->manipulate($q);
663  }
664 
665 
672  public static function _lookupFileName($a_id)
673  {
674  global $DIC;
675  $ilDB = $DIC['ilDB'];
676 
677  $q = "SELECT * FROM file_data WHERE file_id = " . $ilDB->quote($a_id, 'integer');
678  $r = $ilDB->query($q);
680 
681  $strip_slashes = ilUtil::stripSlashes($row->file_name);
682 
683  return $strip_slashes;
684  }
685 
686 
688  public static function _lookupFileSize($a_id)
689  {
690  require_once("./Modules/File/classes/class.ilObjFileAccess.php");
691 
692  return ilObjFileAccess::_lookupFileSize($a_id);
693  }
694 
695 
699  public static function _lookupVersion($a_id)
700  {
701  require_once("./Modules/File/classes/class.ilObjFileAccess.php");
702 
703  return ilObjFileAccess::_lookupVersion($a_id);
704  }
705 
706 
710  public function determineFileSize($a_hist_entry_id = null)
711  {
712  if (is_null($a_hist_entry_id)) {
713  $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName();
714  } else {
715  require_once("./Services/History/classes/class.ilHistory.php");
716  $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
717 
718  if ($entry === false) {
719  return false;
720  }
721 
722  $data = $this->parseInfoParams($entry);
723  $file = $this->getDirectory($data["version"]) . "/" . $data["filename"];
724  }
725  if (is_file($file)) {
726  $this->setFileSize(filesize($file));
727  }
728  }
729 
730 
736  public function sendFile($a_hist_entry_id = null)
737  {
738  $s = new FilePathSanitizer($this);
739  $s->sanitizeIfNeeded();
740 
741  if (is_null($a_hist_entry_id)) {
742  $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName();
743  } else {
744  $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
745  $data = $this->parseInfoParams($entry);
746  $file = $this->getDirectory($data["version"]) . "/" . $data["filename"];
747  }
748 
750 
751  if ($this->file_storage->fileExists($file)) {
752  global $DIC;
753  $ilClientIniFile = $DIC['ilClientIniFile'];
758  $ilFileDelivery = new ilFileDelivery($file);
759  $ilFileDelivery->setDisposition($this->isInline() ? ilFileDelivery::DISP_INLINE : ilFileDelivery::DISP_ATTACHMENT);
760  $ilFileDelivery->setMimeType($this->guessFileType($file));
761  $ilFileDelivery->setConvertFileNameToAsci((bool) !$ilClientIniFile->readVariable('file_access', 'disable_ascii'));
762 
763  // also returning the 'real' filename if a history file is delivered
764  if ($ilClientIniFile->readVariable('file_access', 'download_with_uploaded_filename')
765  != '1'
766  && is_null($a_hist_entry_id)
767  ) {
768  $ilFileDelivery->setDownloadFileName(ilFileUtils::getValidFilename($this->getTitle()));
769  } else {
770  // $download_file_name = basename($file);
771  /* FSX Info: basename has a Bug with Japanese and other characters, see:
772  * http://stackoverflow.com/questions/32115609/basename-fail-when-file-name-start-by-an-accent
773  * Therefore we can no longer use basename();
774  */
775  $parts = explode(DIRECTORY_SEPARATOR, $file);
776  $download_file_name = end($parts);
777  $download_file_name = ilFileUtils::getValidFilename($download_file_name);
778  $ilFileDelivery->setDownloadFileName($download_file_name);
779  }
780  $ilFileDelivery->deliver();
781 
782  return true;
783  }
784 
785  throw new \ILIAS\Filesystem\Exception\FileNotFoundException("This file cannot be found in ILIAS or has been blocked due to security reasons.");
786  }
787 
788 
793  public function getFileExtension()
794  {
795  require_once 'Modules/File/classes/class.ilObjFileAccess.php';
796 
798  }
799 
800 
806  public function isInline()
807  {
808  require_once 'Modules/File/classes/class.ilObjFileAccess.php';
809 
810  return ilObjFileAccess::_isFileInline($this->getTitle());
811  }
812 
813 
817  public function isHidden()
818  {
819  require_once 'Modules/File/classes/class.ilObjFileAccess.php';
820 
821  return ilObjFileAccess::_isFileHidden($this->getTitle());
822  }
823  // END WebDAV: Get file extension, determine if file is inline, guess file type.
824 
825 
832  public function guessFileType($a_file = "")
833  {
834  $path = pathinfo($a_file);
835  if ($path["extension"] != "") {
836  $filename = $path["basename"];
837  } else {
838  $filename = "dummy." . $this->getFileExtension();
839  }
840  include_once("./Services/Utilities/classes/class.ilMimeTypeUtil.php");
841  $mime = ilMimeTypeUtil::getMimeType($a_file, $filename, $this->getFileType());
842 
843  return $mime;
844  }
845 
846 
857  protected function doCloneObject($a_new_obj, $a_target_id, $a_copy_id = 0)
858  {
859  global $DIC;
860  $ilDB = $DIC['ilDB'];
861 
862  $a_new_obj->createDirectory();
863  $this->cloneMetaData($a_new_obj);
864 
865  // Copy all file versions
866  ilUtil::rCopy($this->getDirectory(), $a_new_obj->getDirectory());
867 
868  // object created now copy other settings
869  $query = "INSERT INTO file_data (file_id,file_name,file_type,file_size,version,rating,f_mode) VALUES ("
870  . $ilDB->quote($a_new_obj->getId(), 'integer') . ","
871  . $ilDB->quote($this->getFileName(), 'text') . ","
872  . $ilDB->quote($this->getFileType(), 'text') . ","
873  . $ilDB->quote((int) $this->getFileSize(), 'integer') . ", "
874  . $ilDB->quote($this->getVersion(), 'integer') . ", "
875  . $ilDB->quote($this->hasRating(), 'integer') . ", "
876  . $ilDB->quote($this->getMode(), 'text') . ")";
877  $res = $ilDB->manipulate($query);
878 
879  // copy all previews
880  require_once("./Services/Preview/classes/class.ilPreview.php");
881  ilPreview::copyPreviews($this->getId(), $a_new_obj->getId());
882 
883  // copy history entries
884  require_once("./Services/History/classes/class.ilHistory.php");
885  ilHistory::_copyEntriesForObject($this->getId(), $a_new_obj->getId());
886 
887  // Copy learning progress settings
888  include_once('Services/Tracking/classes/class.ilLPObjSettings.php');
889  $obj_settings = new ilLPObjSettings($this->getId());
890  $obj_settings->cloneSettings($a_new_obj->getId());
891  unset($obj_settings);
892 
893  // add news notification
894  $a_new_obj->addNewsNotification("file_created");
895 
896  return $a_new_obj;
897  }
898 
899 
900  protected function beforeDelete()
901  {
902  global $DIC;
903  $ilDB = $DIC['ilDB'];
904 
905  // check, if file is used somewhere
906  $usages = $this->getUsages();
907  if (count($usages) == 0) {
908  return true;
909  }
910 
911  return false;
912  }
913 
914 
915  protected function doDelete()
916  {
917  global $DIC;
918  $ilDB = $DIC['ilDB'];
919 
920  // delete file data entry
921  $q = "DELETE FROM file_data WHERE file_id = " . $ilDB->quote($this->getId(), 'integer');
922  $this->ilias->db->query($q);
923 
924  // delete history entries
925  require_once("./Services/History/classes/class.ilHistory.php");
927 
928  self::handleQuotaUpdate($this);
929 
930  // delete entire directory and its content
931  if (@is_dir($this->getDirectory())) {
932  ilUtil::delDir($this->getDirectory());
933  }
934 
935  // delete meta data
936  if ($this->getMode() != self::MODE_FILELIST) {
937  $this->deleteMetaData();
938  }
939 
940  // delete preview
941  $this->deletePreview();
942  }
943 
944 
952  public function export($a_target_dir)
953  {
954  $subdir = "il_" . IL_INST_ID . "_file_" . $this->getId();
955  ilUtil::makeDir($a_target_dir . "/objects/" . $subdir);
956 
957  $filedir = $this->getDirectory($this->getVersion());
958 
959  if (@!is_dir($filedir)) {
960  $filedir = $this->getDirectory();
961  }
962 
963  ilUtil::rCopy($filedir, $a_target_dir . "/objects/" . $subdir);
964  }
965 
966 
970  public static function _deleteAllUsages($a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
971  {
972  global $DIC;
973  $ilDB = $DIC['ilDB'];
974 
975  $and_hist = ($a_usage_hist_nr !== false) ? " AND usage_hist_nr = "
976  . $ilDB->quote($a_usage_hist_nr, "integer") : "";
977 
978  $file_ids = array();
979  $set = $ilDB->query("SELECT id FROM file_usage" . " WHERE usage_type = "
980  . $ilDB->quote($a_type, "text") . " AND usage_id= "
981  . $ilDB->quote($a_id, "integer") . " AND usage_lang= "
982  . $ilDB->quote($a_usage_lang, "text") . $and_hist);
983  while ($row = $ilDB->fetchAssoc($set)) {
984  $file_ids[] = $row["id"];
985  }
986 
987  $ilDB->manipulate("DELETE FROM file_usage WHERE usage_type = "
988  . $ilDB->quote($a_type, "text") . " AND usage_id = "
989  . $ilDB->quote((int) $a_id, "integer") . " AND usage_lang= "
990  . $ilDB->quote($a_usage_lang, "text") . " AND usage_hist_nr = "
991  . $ilDB->quote((int) $a_usage_hist_nr, "integer"));
992 
993  foreach ($file_ids as $file_id) {
994  self::handleQuotaUpdate(new self($file_id, false));
995  }
996  }
997 
998 
1002  public static function _saveUsage($a_file_id, $a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
1003  {
1004  global $DIC;
1005  $ilDB = $DIC['ilDB'];
1006 
1007  // check if file really exists
1008  if (ilObject::_lookupType($a_file_id) != "file") {
1009  return;
1010  }
1011  // #15143
1012  $ilDB->replace("file_usage", array(
1013  "id" => array("integer", (int) $a_file_id),
1014  "usage_type" => array("text", (string) $a_type),
1015  "usage_id" => array("integer", (int) $a_id),
1016  "usage_hist_nr" => array("integer", (int) $a_usage_hist_nr),
1017  "usage_lang" => array("text", $a_usage_lang),
1018  ), array());
1019 
1020  self::handleQuotaUpdate(new self($a_file_id, false));
1021  }
1022 
1023 
1027  public function getUsages()
1028  {
1029  global $DIC;
1030  $ilDB = $DIC['ilDB'];
1031 
1032  // get usages in learning modules
1033  $q = "SELECT * FROM file_usage WHERE id = " . $ilDB->quote($this->getId(), "integer");
1034  $us_set = $ilDB->query($q);
1035  $ret = array();
1036  while ($us_rec = $ilDB->fetchAssoc($us_set)) {
1037  $ret[] = array(
1038  "type" => $us_rec["usage_type"],
1039  "id" => $us_rec["usage_id"],
1040  "lang" => $us_rec["usage_lang"],
1041  "hist_nr" => $us_rec["usage_hist_nr"],
1042  );
1043  }
1044 
1045  return $ret;
1046  }
1047 
1048 
1057  public static function _getFilesOfObject($a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
1058  {
1059  global $DIC;
1060  $ilDB = $DIC['ilDB'];
1061 
1062  $lstr = "";
1063  if ($a_usage_lang != "") {
1064  $lstr = "usage_lang = " . $ilDB->quote((string) $a_usage_lang, "text") . " AND ";
1065  }
1066 
1067  // get usages in learning modules
1068  $q = "SELECT * FROM file_usage WHERE " . "usage_id = " . $ilDB->quote((int) $a_id, "integer")
1069  . " AND " . "usage_type = " . $ilDB->quote((string) $a_type, "text") . " AND " . $lstr
1070  . "usage_hist_nr = " . $ilDB->quote((int) $a_usage_hist_nr, "integer");
1071  $file_set = $ilDB->query($q);
1072  $ret = array();
1073  while ($file_rec = $ilDB->fetchAssoc($file_set)) {
1074  $ret[$file_rec["id"]] = $file_rec["id"];
1075  }
1076 
1077  return $ret;
1078  }
1079 
1080 
1081  // TODO: What is this function good for??
1082  public function getXMLZip()
1083  {
1084  global $DIC;
1085  $ilias = $DIC['ilias'];
1086 
1087  $zip = PATH_TO_ZIP;
1088 
1089  exec($zip . ' ' . ilUtil::escapeShellArg($this->getDirectory() . '/' . $this->getFileName())
1090  . " " . ilUtil::escapeShellArg($this->getDirectory() . '/' . '1.zip'));
1091 
1092  return $this->getDirectory() . '/1.zip';
1093  }
1094 
1095 
1096  public function addNewsNotification($a_lang_var)
1097  {
1098  // BEGIN WebDAV Suppress news notification for hidden files
1099  if ($this->isHidden()) {
1100  return;
1101  }
1102  // END WebDAV Suppress news notification for hidden files
1103 
1104  global $DIC;
1105  $ilUser = $DIC['ilUser'];
1106 
1107  // Add Notification to news
1108  include_once("./Services/News/classes/class.ilNewsItem.php");
1109  include_once("./Modules/File/classes/class.ilObjFileAccess.php");
1110  $news_item = new ilNewsItem();
1111  $news_item->setContext($this->getId(), $this->getType());
1112  $news_item->setPriority(NEWS_NOTICE);
1113  $news_item->setTitle($a_lang_var);
1114  $news_item->setContentIsLangVar(true);
1115  if ($this->getDescription() != "") {
1116  $news_item->setContent("<p>" . $this->getDescription() . "</p>");
1117  }
1118  $news_item->setUserId($ilUser->getId());
1119  $news_item->setVisibility(NEWS_USERS);
1120  $news_item->create();
1121  }
1122 
1123 
1130  public function initFileStorage()
1131  {
1132  $this->file_storage = new ilFSStorageFile($this->getId());
1133 
1134  return true;
1135  }
1136 
1137 
1147  public function storeUnzipedFile($a_upload_file, $a_filename)
1148  {
1149  $this->setVersion($this->getVersion() + 1);
1150 
1151  if (@!is_dir($this->getDirectory($this->getVersion()))) {
1152  ilUtil::makeDir($this->getDirectory($this->getVersion()));
1153  }
1154 
1155  $file = $this->getDirectory($this->getVersion()) . "/" . $a_filename;
1156 
1157  ilFileUtils::rename($a_upload_file, $file);
1158 
1159  // create preview
1160  $this->createPreview();
1161  }
1162 
1163 
1171  public static function _lookupAbsolutePath($obj_id, $a_version = null)
1172  {
1173  $file_object = new self($obj_id, false);
1174  $s = new FilePathSanitizer($file_object);
1175  $s->sanitizeIfNeeded();
1176 
1177  return $file_object->getFile($a_version);
1178  }
1179 
1180 
1186  public function checkFileExtension($new_filename, $new_title)
1187  {
1188  include_once './Modules/File/classes/class.ilObjFileAccess.php';
1189  $fileExtension = ilObjFileAccess::_getFileExtension($new_filename);
1190  $titleExtension = ilObjFileAccess::_getFileExtension($new_title);
1191  if ($titleExtension != $fileExtension && strlen($fileExtension) > 0) {
1192  // remove old extension
1193  $pi = pathinfo($this->getFileName());
1194  $suffix = $pi["extension"];
1195  if ($suffix != "") {
1196  if (substr($new_title, strlen($new_title) - strlen($suffix) - 1) == "." . $suffix) {
1197  $new_title = substr($new_title, 0, strlen($new_title) - strlen($suffix) - 1);
1198  }
1199  }
1200  $new_title .= '.' . $fileExtension;
1201  }
1202 
1203  return $new_title;
1204  }
1205 
1206 
1215  public function getVersions($version_ids = null)
1216  {
1217  include_once("./Services/History/classes/class.ilHistory.php");
1218  $versions = ilHistory::_getEntriesForObject($this->getId(), $this->getType());
1219 
1220  if ($version_ids != null && count($version_ids) > 0) {
1221  foreach ($versions as $index => $version) {
1222  if (!in_array($version["hist_entry_id"], $version_ids, true)) {
1223  unset($versions[$index]);
1224  }
1225  }
1226  }
1227 
1228  // add custom entries
1229  foreach ($versions as $index => $version) {
1230  $params = $this->parseInfoParams($version);
1231  $versions[$index] = array_merge($version, $params);
1232  }
1233 
1234  // sort by version number (hist_entry_id will do for that)
1235  usort($versions, array($this, "compareVersions"));
1236 
1237  return $versions;
1238  }
1239 
1240 
1248  public function getSpecificVersion($version_id)
1249  {
1250  include_once("./Services/History/classes/class.ilHistory.php");
1252  if ($version === false) {
1253  return false;
1254  }
1255 
1256  // ilHistory returns different keys in _getEntryByHistoryID and _getEntriesForObject
1257  // so this makes it the same
1258  $version["hist_entry_id"] = $version["id"];
1259  $version["user_id"] = $version["usr_id"];
1260  $version["date"] = $version["hdate"];
1261  unset($version["id"], $version["usr_id"], $version["hdate"]);
1262 
1263  // parse params
1264  $params = $this->parseInfoParams($version);
1265 
1266  return array_merge($version, $params);
1267  }
1268 
1269 
1277  public function rollback($version_id)
1278  {
1279  global $DIC;
1280  $ilDB = $DIC['ilDB'];
1281  $ilUser = $DIC['ilUser'];
1282 
1283  $source = $this->getSpecificVersion($version_id);
1284  if ($source === false) {
1285  $this->ilErr->raiseError($this->lng->txt("obj_not_found"), $this->ilErr->MESSAGE);
1286  }
1287 
1288  // get the new version number
1289  $new_version_nr = $this->getVersion() + 1;
1290 
1291  // copy file
1292  $source_path = $this->getDirectory($source["version"]) . "/" . $source["filename"];
1293  $dest_dir = $this->getDirectory($new_version_nr);
1294  if (@!is_dir($dest_dir)) {
1295  ilUtil::makeDir($dest_dir);
1296  }
1297 
1298  copy($source_path, $dest_dir . "/" . $source["filename"]);
1299 
1300  // create new history entry based on the old one
1301  include_once("./Services/History/classes/class.ilHistory.php");
1302  ilHistory::_createEntry($this->getId(), "rollback", $source["filename"] . ","
1303  . $new_version_nr . "|"
1304  . $source["version"] . "|"
1305  . $ilUser->getId());
1306 
1307  // get id of newest entry
1308  // bugfix mantis 23596
1309  $entries = ilHistory::_getEntriesForObject($this->getId());
1310  $newest_entry_id = 0;
1311  foreach ($entries as $entry) {
1312  if ($entry["action"] == "rollback") {
1313  $newest_entry_id = $entry["hist_entry_id"];
1314  }
1315  }
1316  $new_version = $this->getSpecificVersion($newest_entry_id);
1317 
1318  // change user back to the original uploader
1319  ilHistory::_changeUserId($new_version["hist_entry_id"], $source["user_id"]);
1320 
1321  // update this file with the new version
1322  $this->updateWithVersion($new_version);
1323 
1324  $this->addNewsNotification("file_updated");
1325 
1326  return $new_version;
1327  }
1328 
1329 
1335  protected function updateWithVersion($version)
1336  {
1337  // update title (checkFileExtension must be called before setFileName!)
1338  $this->setTitle($this->checkFileExtension($version["filename"], $this->getTitle()));
1339 
1340  $this->setVersion($version["version"]);
1341  $this->setFileName($version["filename"]);
1342 
1343  // evaluate mime type (reset file type before)
1344  $this->setFileType("");
1345  $this->setFileType($this->guessFileType($version["filename"]));
1346 
1347  // set filesize
1348  $this->determineFileSize();
1349 
1350  $this->update();
1351 
1352  // refresh preview
1353  $this->createPreview(true);
1354  }
1355 
1356 
1367  public function compareVersions($v1, $v2)
1368  {
1369  // v2 - v1 because version should be descending
1370  return (int) $v2["version"] - (int) $v1["version"];
1371  }
1372 
1373 
1382  public function parseInfoParams($entry)
1383  {
1384  $data = preg_split("/(.*),(.*)/", $entry["info_params"], 0, PREG_SPLIT_DELIM_CAPTURE
1385  | PREG_SPLIT_NO_EMPTY);
1386 
1387  // bugfix: first created file had no version number
1388  // this is a workaround for all files created before the bug was fixed
1389  if (empty($data[1])) {
1390  $data[1] = "1";
1391  }
1392 
1393  $result = array(
1394  "filename" => $data[0],
1395  "version" => $data[1],
1396  "rollback_version" => "",
1397  "rollback_user_id" => "",
1398  );
1399 
1400  // if rollback, the version contains the rollback version as well
1401  if ($entry["action"] == "rollback") {
1402  $tokens = explode("|", $result["version"]);
1403  if (count($tokens) > 1) {
1404  $result["version"] = $tokens[0];
1405  $result["rollback_version"] = $tokens[1];
1406 
1407  if (count($tokens) > 2) {
1408  $result["rollback_user_id"] = $tokens[2];
1409  }
1410  }
1411  }
1412 
1413  return $result;
1414  }
1415 
1416 
1417  protected static function handleQuotaUpdate(ilObjFile $a_file)
1418  {
1419  include_once "Services/MediaObjects/classes/class.ilObjMediaObject.php";
1420  $mob = new ilObjMediaObject();
1421 
1422  // file itself could be workspace item
1423  $parent_obj_ids = array($a_file->getId());
1424 
1425  foreach ($a_file->getUsages() as $item) {
1426  $parent_obj_id = $mob->getParentObjectIdForUsage($item);
1427  if ($parent_obj_id
1428  && !in_array($parent_obj_id, $parent_obj_ids)
1429  ) {
1430  $parent_obj_ids[] = $parent_obj_id;
1431  }
1432  }
1433 
1434  include_once "Services/DiskQuota/classes/class.ilDiskQuotaHandler.php";
1435  ilDiskQuotaHandler::handleUpdatedSourceObject($a_file->getType(), $a_file->getId(), $a_file->getDiskUsage(), $parent_obj_ids);
1436  }
1437 
1438 
1445  protected function createPreview($force = false)
1446  {
1447  // only normal files are supported
1448  if ($this->getMode() != self::MODE_OBJECT) {
1449  return;
1450  }
1451 
1452  require_once("./Services/Preview/classes/class.ilPreview.php");
1453  ilPreview::createPreview($this, $force);
1454  }
1455 
1456 
1460  protected function deletePreview()
1461  {
1462  // only normal files are supported
1463  if ($this->getMode() != self::MODE_OBJECT) {
1464  return;
1465  }
1466 
1467  require_once("./Services/Preview/classes/class.ilPreview.php");
1468  ilPreview::deletePreview($this->getId());
1469  }
1470 
1471 
1475  public function setRating($a_value)
1476  {
1477  $this->rating = (bool) $a_value;
1478  }
1479 
1480 
1484  public function hasRating()
1485  {
1486  return $this->rating;
1487  }
1488 
1489 
1493  public function getPageCount()
1494  {
1495  return $this->page_count;
1496  }
1497 
1498 
1502  public function setPageCount($page_count)
1503  {
1504  $this->page_count = $page_count;
1505  }
1506 
1507 
1511  private function getArrayForDatabase()
1512  {
1513  return [
1514  'file_id' => ['integer', $this->getId()],
1515  'file_name' => ['text', $this->getFileName()],
1516  'file_type' => ['text', $this->getFileType()],
1517  'file_size' => ['integer', (int) $this->getFileSize()],
1518  'version' => ['integer', (int) $this->getVersion()],
1519  'f_mode' => ['text', $this->getMode()],
1520  'page_count' => ['text', $this->getPageCount()],
1521  'rating' => ['integer', $this->hasRating()],
1522  ];
1523  }
1524 }
$params
Definition: disable.php:11
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...
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.
$format
Definition: metadata.php:141
static _write($a_type, $a_setting, $a_value, $a_user=0, $a_block_id=0)
Write setting to database.
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.
global $DIC
Definition: saml.php:7
$_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)
$s
Definition: pwgen.php:45
$index
Definition: metadata.php:60
setFileSize($a_size)
$metadata['__DYNAMIC:1__']
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
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
$r
Definition: example_031.php:79
static _copyEntriesForObject($a_src_id, $a_dst_id)
copy all history entries for an object
foreach($_POST as $key=> $value) $res
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
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.
$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)
Create styles array
The data for the language used.
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.
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
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.
static _removeEntriesForObject($a_obj_id)
remove all history entries for an object
Class ilObject2 This is an intermediate progress of ilObject class.
Class ilCountPDFPagesPreProcessors.
static getLogger($a_component_id)
Get component logger.
raiseUploadError($a_raise=true)
Class ilFSStorageFile.
const NEWS_USERS
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
doMDUpdateListener($a_element)
$source
Definition: linkback.php:22
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.
__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.