ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilObjFile.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once "Services/Object/classes/class.ilObject2.php";
5 include_once('Modules/File/classes/class.ilFSStorageFile.php');
6 
18 class ilObjFile extends ilObject2
19 {
20  var $filename;
21  var $filetype;
22  var $filemaxsize = "20000000"; // not used yet
24  var $mode = "object";
25  protected $rating;
26 
27  private $file_storage = null;
28 
29 
36  function __construct($a_id = 0,$a_call_by_reference = true)
37  {
38  $this->version = 0;
39  $this->raise_upload_error = true;
40  parent::__construct($a_id,$a_call_by_reference);
41 
42  if($this->getId())
43  {
44  $this->initFileStorage();
45  }
46  }
47 
48  function initType()
49  {
50  $this->type = "file";
51  }
52 
58  protected function doCreate($a_upload = false, $a_prevent_meta_data_creation = false)
59  {
60  //BEGIN WebDAV Move Property creation into a method of its own.
61  $this->createProperties($a_upload);
62  //END WebDAV Move Property creation into a method of its own.
63  }
64 
65  //BEGIN WebDAV: Move Property creation into a method of its own.
73  function createProperties($a_upload = false, $a_prevent_meta_data_creation = false)
74  {
75  global $ilDB,$tree;
76 
77  // Create file directory
78  $this->initFileStorage();
79  $this->file_storage->create();
80 
81  if($a_upload)
82  {
83  return true;
84  }
85 
86  // not upload mode
87  require_once("./Services/History/classes/class.ilHistory.php");
88  ilHistory::_createEntry($this->getId(), "create", $this->getFileName().",1");
89  $this->addNewsNotification("file_created");
90 
91 
92  require_once("./Services/News/classes/class.ilNewsItem.php");
93  $default_visibility = ilNewsItem::_getDefaultVisibilityForRefId($_GET['ref_id']);
94  if ($default_visibility == "public")
95  {
96  ilBlockSetting::_write("news", "public_notifications",
97  1, 0, $this->getId());
98  }
99 
100  $q = "INSERT INTO file_data (file_id,file_name,file_type,file_size,version,f_mode) "
101  ."VALUES (".$ilDB->quote($this->getId() ,'integer').","
102  .$ilDB->quote($this->getFileName() ,'text').","
103  .$ilDB->quote($this->getFileType() ,'text').","
104  .$ilDB->quote((int) $this->getFileSize() ,'integer').","
105  .$ilDB->quote(1 ,'integer').",".$ilDB->quote($this->getMode() ,'text').")";
106  $res = $ilDB->manipulate($q);
107 
108  // no meta data handling for file list files
109  if ($this->getMode() != "filelist" && !$a_prevent_meta_data_creation)
110  {
111  $this->createMetaData();
112  }
113  }
114  //END WebDAV: Move Property creation into a method of its own.
115 
119  protected function doCreateMetaData()
120  {
121  // add technical section with file size and format
122  $md_obj =& new ilMD($this->getId(),0,$this->getType());
123  $technical = $md_obj->addTechnical();
124  $technical->setSize($this->getFileSize());
125  $technical->save();
126  $format = $technical->addFormat();
127  $format->setFormat($this->getFileType());
128  $format->save();
129  $technical->update();
130  }
131 
132  protected function beforeMDUpdateListener($a_element)
133  {
134  // Check file extension
135  // Removing the file extension is not allowed
136  include_once 'Services/MetaData/classes/class.ilMD.php';
137  $md = new ilMD($this->getId(),0, $this->getType());
138  if(!is_object($md_gen = $md->getGeneral()))
139  {
140  return false;
141  }
142  $title = $this->checkFileExtension($this->getFileName(), $md_gen->getTitle());
143  $md_gen->setTitle($title);
144  $md_gen->update();
145  return true;
146  }
147 
148  protected function doMDUpdateListener($a_element)
149  {
150  // handling for technical section
151  include_once 'Services/MetaData/classes/class.ilMD.php';
152 //echo "-".$a_element."-";
153  switch($a_element)
154  {
155  case 'Technical':
156 
157  // Update Format (size is not stored in db)
158  $md = new ilMD($this->getId(),0, $this->getType());
159  if(!is_object($md_technical = $md->getTechnical()))
160  {
161  return false;
162  }
163 
164  foreach($md_technical->getFormatIds() as $id)
165  {
166  $md_format = $md_technical->getFormat($id);
167  ilObjFile::_writeFileType($this->getId(),$md_format->getFormat());
168  $this->setFileType($md_format->getFormat());
169  break;
170  }
171 
172  break;
173  }
174  return true;
175  }
176 
177 
178  function getDirectory($a_version = 0)
179  {
180  $version_subdir = "";
181 
182  if ($a_version)
183  {
184  // BEGIN WebDAV Avoid double slash before version subdirectory
185  $version_subdir = sprintf("%03d", $a_version);
186  // END WebDAV Avoid double slash before version subdirectory
187  }
188 
189  if(!is_object($this->file_storage))
190  {
191  $this->initFileStorage();
192  }
193 
194  return $this->file_storage->getAbsolutePath().'/'.$version_subdir;
195  }
196 
197  function createDirectory()
198  {
200  }
201 
202  function raiseUploadError($a_raise = true)
203  {
204  $this->raise_upload_error = $a_raise;
205  }
206 
207  function getUploadFile($a_upload_file, $a_filename, $a_prevent_preview = false)
208  {
209  $this->setVersion($this->getVersion() + 1);
210 
211  if (@!is_dir($this->getDirectory($this->getVersion())))
212  {
214  }
215 
216  $file = $this->getDirectory($this->getVersion())."/".$a_filename;
217  //move_uploaded_file($a_upload_file, $file);
218  ilUtil::moveUploadedFile($a_upload_file, $a_filename, $file, $this->raise_upload_error);
219 
220  $this->handleQuotaUpdate($this);
221 
222  // create preview?
223  if (!$a_prevent_preview)
224  {
225  $this->createPreview(false);
226  }
227  }
228 
232  function replaceFile($a_upload_file, $a_filename)
233  {
234  $this->getUploadFile($a_upload_file, $a_filename, true);
235 
236  require_once("./Services/History/classes/class.ilHistory.php");
238  $this->getId(),
239  "replace",
240  $a_filename.",".$this->getVersion()
241  );
242  $this->setFilename($a_filename);
243  $this->addNewsNotification("file_updated");
244 
245  // create preview
246  $this->createPreview(true);
247  }
248 
249 
250  public function addFileVersion($a_upload_file,$a_filename)
251  {
252  $this->getUploadFile($a_upload_file, $a_filename, true);
253 
254  require_once("./Services/History/classes/class.ilHistory.php");
256  $this->getId(),
257  "new_version",
258  $a_filename.",".$this->getVersion()
259  );
260  $this->setFilename($a_filename);
261  $this->addNewsNotification("file_updated");
262 
263  // create preview
264  $this->createPreview($this->getVersion() > 1);
265  }
266 
267 
271  function copy($a_source,$a_destination)
272  {
273  return copy($a_source,$this->getDirectory()."/".$a_destination);
274  }
275 
280  {
281  ilUtil::delDir($this->getDirectory());
282  $this->createDirectory();
283  }
284 
290  public function deleteVersions($a_hist_entry_ids = null)
291  {
292  global $ilDB;
293 
294  require_once("./Services/History/classes/class.ilHistory.php");
295 
296  if ($a_hist_entry_ids == null || count($a_hist_entry_ids) < 1)
297  {
298  $ilDB->manipulate("UPDATE file_data SET version = 1 WHERE file_id = ".$ilDB->quote($this->getId() ,'integer'));
299  $this->setVersion(0);
300  $this->clearDataDirectory();
301 
303 
305  }
306  else
307  {
308  $actualVersionDeleted = false;
309 
310  // get all versions
311  $versions = $this->getVersions();
312 
313  // delete each version
314  foreach ($a_hist_entry_ids as $hist_id)
315  {
316  $entry = null;
317 
318  // get version
319  foreach ($versions as $index => $version)
320  {
321  if ($version["hist_entry_id"] == $hist_id)
322  {
323  // remove each history entry
325 
326  // delete directory
327  $version_dir = $this->getDirectory($version["version"]);
328  ilUtil::delDir($version_dir);
329 
330  // is actual version?
331  if ($version["version"] == $this->getVersion())
332  $actualVersionDeleted = true;
333 
334  // remove from array
335  unset($versions[$index]);
336  break;
337  }
338  }
339  }
340 
341  // update actual version if it was deleted before
342  if ($actualVersionDeleted)
343  {
344  // get newest version (already sorted by getVersions)
345  $version = reset($versions);
346  $this->updateWithVersion($version);
347  }
348  else
349  {
350  // updateWithVersion() will trigger quota, too
352  }
353  }
354  }
355 
359  protected function doRead()
360  {
361  global $ilDB;
362 
363  $q = "SELECT * FROM file_data WHERE file_id = ".$ilDB->quote($this->getId() ,'integer');
364  $r = $this->ilias->db->query($q);
365  $row = $r->fetchRow(DB_FETCHMODE_OBJECT);
366 
367  $this->setFileName($row->file_name);
368  $this->setFileType($row->file_type);
369  $this->setFileSize($row->file_size);
370  $this->setVersion($row->version);
371  $this->setMode($row->f_mode);
372  $this->setRating($row->rating);
373 
374  $this->initFileStorage();
375  }
376 
377  protected function beforeUpdate()
378  {
379  // no meta data handling for file list files
380  if ($this->getMode() != "filelist")
381  {
382  $this->updateMetaData();
383  }
384 
385  return true;
386  }
387 
391  protected function doUpdate()
392  {
393  global $ilDB, $ilLog;
394 
395  //$ilLog->write(__METHOD__.' File type: '.$this->getFileType());
396 
397  $q = "UPDATE file_data SET file_name = ".$ilDB->quote($this->getFileName() ,'text').
398  ", file_type = ".$ilDB->quote($this->getFiletype() ,'text')." ".
399  ", file_size = ".$ilDB->quote((int) $this->getFileSize() ,'integer')." ".
400  ", version = ".$ilDB->quote($this->getVersion() ,'integer')." ".
401  ", f_mode = ".$ilDB->quote($this->getMode() ,'text')." ".
402  ", rating = ".$ilDB->quote($this->hasRating() ,'integer')." ".
403  "WHERE file_id = ".$ilDB->quote($this->getId() ,'integer');
404  $res = $ilDB->manipulate($q);
405 
407 
408  return true;
409  }
410 
414  protected function doUpdateMetaData()
415  {
416  // add technical section with file size and format
417  $md_obj =& new ilMD($this->getId(),0,$this->getType());
418  if(!is_object($technical = $md_obj->getTechnical()))
419  {
420  $technical = $md_obj->addTechnical();
421  $technical->save();
422  }
423  $technical->setSize($this->getFileSize());
424 
425  $format_ids = $technical->getFormatIds();
426  if (count($format_ids) > 0)
427  {
428  $format = $technical->getFormat($format_ids[0]);
429  $format->setFormat($this->getFileType());
430  $format->update();
431  }
432  else
433  {
434  $format = $technical->addFormat();
435  $format->setFormat($this->getFileType());
436  $format->save();
437  }
438  $technical->update();
439  }
440 
444  function setFileName($a_name)
445  {
446  $this->filename = $a_name;
447  }
448 
449  function getFileName()
450  {
451  return $this->filename;
452  }
453 
454  function setFileType($a_type)
455  {
456  global $ilLog;
457 
458 
459  $this->filetype = $a_type;
460  }
461 
462  function getFileType()
463  {
464  return $this->filetype;
465  }
466 
467  function setFileSize($a_size)
468  {
469  $this->filesize = $a_size;
470  }
471 
472  function getFileSize()
473  {
474  return $this->filesize;
475  }
482  function getDiskUsage()
483  {
484  require_once("./Modules/File/classes/class.ilObjFileAccess.php");
485  return ilObjFileAccess::_lookupDiskUsage($this->id);
486  }
487 
488 
489  // END PATCH WebDAV Encapsulate file access in ilObjFile class.
490  function getFile($a_hist_entry_id = null)
491  {
492  if (is_null($a_hist_entry_id))
493  {
494  $file = $this->getDirectory($this->getVersion())."/".$this->getFileName();
495  }
496  else
497  {
498  require_once("./Services/History/classes/class.ilHistory.php");
499  $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
500 
501  if ($entry === false)
502  {
503  return false;
504  }
505 
506  $data = $this->parseInfoParams($entry);
507  $file = $this->getDirectory($data["version"])."/".$data["filename"];
508  }
509  return $file;
510  }
511  // END PATCH WebDAV Encapsulate file access in ilObjFile class.
512 
513  function setVersion($a_version)
514  {
515  $this->version = $a_version;
516  }
517 
518  function getVersion()
519  {
520  return $this->version;
521  }
522 
528  function setMode($a_mode)
529  {
530  $this->mode = $a_mode;
531  }
532 
538  function getMode()
539  {
540  return $this->mode;
541  }
542 
543  function _writeFileType($a_id ,$a_format)
544  {
545  global $ilDB;
546 
547  $q = "UPDATE file_data SET ".
548  " file_type = ".$ilDB->quote($a_format ,'text').
549  " WHERE file_id = ".$ilDB->quote($a_id ,'integer');
550  $res = $ilDB->manipulate($q);
551 
552  }
553 
554  function _lookupFileName($a_id)
555  {
556  global $ilDB;
557 
558  $q = "SELECT * FROM file_data WHERE file_id = ".$ilDB->quote($a_id ,'integer');
559  $r = $ilDB->query($q);
560  $row = $r->fetchRow(DB_FETCHMODE_OBJECT);
561 
562  return ilUtil::stripSlashes($row->file_name);
563  }
564 
565 
567  function _lookupFileSize($a_id)
568  {
569  require_once("./Modules/File/classes/class.ilObjFileAccess.php");
570  return ilObjFileAccess::_lookupFileSize($a_id);
571  }
572 
576  function _lookupVersion($a_id)
577  {
578  require_once("./Modules/File/classes/class.ilObjFileAccess.php");
579  return ilObjFileAccess::_lookupVersion($a_id);
580  }
581 
585  function determineFileSize($a_hist_entry_id = null)
586  {
587  if (is_null($a_hist_entry_id))
588  {
589  $file = $this->getDirectory($this->getVersion())."/".$this->getFileName();
590  }
591  else
592  {
593  require_once("./Services/History/classes/class.ilHistory.php");
594  $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
595 
596  if ($entry === false)
597  {
598  return false;
599  }
600 
601  $data = $this->parseInfoParams($entry);
602  $file = $this->getDirectory($data["version"])."/".$data["filename"];
603  }
604  if (is_file($file))
605  {
606  $this->setFileSize(filesize($file));
607  }
608  }
609 
610  function sendFile($a_hist_entry_id = null)
611  {
612  if (is_null($a_hist_entry_id))
613  {
614  $file = $this->getDirectory($this->getVersion())."/".$this->getFileName();
615 
616  // if not found lookup for file in file object's main directory for downward c ompability
617  if (@!is_file($file))
618  {
619  $file = $this->getDirectory()."/".$this->getFileName();
620  }
621  }
622  else
623  {
624  require_once("./Services/History/classes/class.ilHistory.php");
625  $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id);
626 
627  if ($entry === false)
628  {
629  echo "3";return false;
630  }
631 
632  $data = $this->parseInfoParams($entry);
633  $file = $this->getDirectory($data["version"])."/".$data["filename"];
634 
635  // if not found lookup for file in file object's main directory for downward compability
636  if (@!is_file($file))
637  {
638  $file = $this->getDirectory()."/".$data[0];
639  }
640 
641  // BEGIN WebDAV removed duplicated code
642  // END WebDAV removed duplicated code
643  }
644 
645  if (@is_file($file))
646  {
647  global $ilClientIniFile;
648 
649  // also returning the 'real' filename if a history file is delivered
650  if ($ilClientIniFile->readVariable('file_access','download_with_uploaded_filename') != '1' && is_null($a_hist_entry_id))
651  {
652  ilUtil::deliverFile($file, $this->getTitle(), $this->guessFileType($file), $this->isInline());
653  }
654  else
655  {
656  ilUtil::deliverFile($file, basename($file), $this->guessFileType($file), $this->isInline());
657  }
658  return true;
659  }
660 
661  return false;
662  }
663 
664  // BEGIN WebDAV: Get file extension, determine if file is inline, guess file type.
669  function getFileExtension() {
670  require_once 'Modules/File/classes/class.ilObjFileAccess.php';
672  }
678  function isInline() {
679  require_once 'Modules/File/classes/class.ilObjFileAccess.php';
680  return ilObjFileAccess::_isFileInline($this->getTitle());
681  }
685  function isHidden() {
686  require_once 'Modules/File/classes/class.ilObjFileAccess.php';
687  return ilObjFileAccess::_isFileHidden($this->getTitle());
688  }
689  // END WebDAV: Get file extension, determine if file is inline, guess file type.
690 
697  function guessFileType($a_file = "") {
698 
699  $path = pathinfo($a_file);
700  if ($path["extension"] != "")
701  {
702  $filename = $path["basename"];
703  }
704  else
705  {
706  $filename = "dummy.".$this->getFileExtension();
707  }
708  include_once("./Services/Utilities/classes/class.ilMimeTypeUtil.php");
709  $mime = ilMimeTypeUtil::getMimeType($a_file, $filename, $this->getFileType());
710  return $mime;
711 
712 /*
713  $fileType = $this->getFileType();
714  if (strlen($fileType) == 0) {
715  $fileType = 'application/octet-stream';
716  }
717 
718  // Firefox browser assigns 'application/x-pdf' to PDF files, but
719  // it can only handle them if the have the mime-type 'application/pdf'.
720  if ($fileType == 'application/x-pdf')
721  {
722  $fileType = 'application/pdf';
723  }
724 
725  if ($fileType == 'application/octet-stream')
726  {
727  $fileExtension = $this->getFileExtension();
728  $mimeArray = array(
729  'mpeg' => 'video/mpeg',
730  'mp3' => 'audio/mpeg',
731  'pdf' => 'application/pdf',
732  'gif' => 'image/gif',
733  'jpg' => 'image/jpg',
734  'png' => 'image/png',
735  'htm' => 'text/html',
736  'html' => 'text/html',
737  'wma' => 'video/x-ms-wma',
738  'wmv' => 'video/x-ms-wmv',
739  'swf' => 'application/x-shockwave-flash',
740  );
741  if (array_key_exists($fileExtension, $mimeArray))
742  {
743  $fileType = $mimeArray[$fileExtension];
744  }
745  }
746  return $fileType;
747 */
748  }
749 
759  protected function doCloneObject($a_new_obj,$a_target_id,$a_copy_id = 0)
760  {
761  global $ilDB;
762 
763  $a_new_obj->createDirectory();
764  $this->cloneMetaData($a_new_obj);
765 
766  // Copy all file versions
767  ilUtil::rCopy($this->getDirectory(),$a_new_obj->getDirectory());
768 
769  // object created now copy other settings
770  $query = "INSERT INTO file_data (file_id,file_name,file_type,file_size,version,rating,f_mode) VALUES (".
771  $ilDB->quote($a_new_obj->getId() ,'integer').",".
772  $ilDB->quote($this->getFileName() ,'text').",".
773  $ilDB->quote($this->getFileType() ,'text').",".
774  $ilDB->quote((int) $this->getFileSize() ,'integer').", ".
775  $ilDB->quote($this->getVersion() ,'integer').", ".
776  $ilDB->quote($this->hasRating() ,'integer').", ".
777  $ilDB->quote($this->getMode() ,'text').")";
778  $res = $ilDB->manipulate($query);
779 
780  // copy all previews
781  require_once("./Services/Preview/classes/class.ilPreview.php");
782  ilPreview::copyPreviews($this->getId(), $a_new_obj->getId());
783 
784  // copy history entries
785  require_once("./Services/History/classes/class.ilHistory.php");
786  ilHistory::_copyEntriesForObject($this->getId(),$a_new_obj->getId());
787 
788  // add news notification
789  $a_new_obj->addNewsNotification("file_created");
790 
791  return $a_new_obj;
792  }
793 
794  protected function beforeDelete()
795  {
796  global $ilDB;
797 
798  // check, if file is used somewhere
799  $usages = $this->getUsages();
800  if (count($usages) == 0)
801  {
802  return true;
803  }
804  return false;
805  }
806 
807  protected function doDelete()
808  {
809  global $ilDB;
810 
811  // delete file data entry
812  $q = "DELETE FROM file_data WHERE file_id = ".$ilDB->quote($this->getId() ,'integer');
813  $this->ilias->db->query($q);
814 
815  // delete history entries
816  require_once("./Services/History/classes/class.ilHistory.php");
818 
819  // delete entire directory and its content
820  if (@is_dir($this->getDirectory()))
821  {
822  ilUtil::delDir($this->getDirectory());
823  }
824 
825  // delete meta data
826  if ($this->getMode() != "filelist")
827  {
828  $this->deleteMetaData();
829  }
830 
832 
833  // delete preview
834  $this->deletePreview();
835  }
836 
844  function export($a_target_dir)
845  {
846  $subdir = "il_".IL_INST_ID."_file_".$this->getId();
847  ilUtil::makeDir($a_target_dir."/objects/".$subdir);
848 
849  $filedir = $this->getDirectory($this->getVersion());
850 
851  if (@!is_dir($filedir))
852  {
853  $filedir = $this->getDirectory();
854  }
855 
856  ilUtil::rCopy($filedir, $a_target_dir."/objects/".$subdir);
857  }
858 
862  function _deleteAllUsages($a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
863  {
864  global $ilDB;
865 
866  $and_hist = ($a_usage_hist_nr !== false)
867  ? " AND usage_hist_nr = ".$ilDB->quote($a_usage_hist_nr, "integer")
868  : "";
869 
870  $file_ids = array();
871  $set = $ilDB->query("SELECT id FROM file_usage".
872  " WHERE usage_type = ".$ilDB->quote($a_type, "text").
873  " AND usage_id= ".$ilDB->quote($a_id, "integer").
874  " AND usage_lang= ".$ilDB->quote($a_usage_lang, "text").
875  $and_hist);
876  while($row = $ilDB->fetchAssoc($set))
877  {
878  $file_ids[] = $row["id"];
879  }
880 
881  $ilDB->manipulate("DELETE FROM file_usage WHERE usage_type = ".
882  $ilDB->quote($a_type, "text").
883  " AND usage_id = ".$ilDB->quote((int) $a_id, "integer").
884  " AND usage_lang= ".$ilDB->quote($a_usage_lang, "text").
885  " AND usage_hist_nr = ".$ilDB->quote((int) $a_usage_hist_nr, "integer"));
886 
887  foreach($file_ids as $file_id)
888  {
889  self::handleQuotaUpdate(new self($file_id, false));
890  }
891  }
892 
896  function _saveUsage($a_file_id, $a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
897  {
898  global $ilDB;
899 
900  /*
901  $ilDB->manipulate("DELETE FROM file_usage WHERE usage_type = ".
902  $ilDB->quote((string) $a_type, "text").
903  " AND usage_id = ".$ilDB->quote((int) $a_id, "integer").
904  " AND usage_lang = ".$ilDB->quote($a_usage_lang, "text").
905  " AND usage_hist_nr = ".$ilDB->quote((int) $a_usage_hist_nr, "integer").
906  " AND id = ".$ilDB->quote((int) $a_file_id, "integer"));
907 
908  $ilDB->manipulate("INSERT INTO file_usage (id, usage_type, usage_id, usage_hist_nr, usage_lang) VALUES".
909  " (".$ilDB->quote((int) $a_file_id, "integer").",".
910  $ilDB->quote((string) $a_type, "text").",".
911  $ilDB->quote((int) $a_id, "integer").",".
912  $ilDB->quote((int) $a_usage_hist_nr, "integer").",".
913  $ilDB->quote($a_usage_lang, "text").
914  ")");
915  */
916 
917  // #15143
918  $ilDB->replace("file_usage",
919  array(
920  "id" => array("integer", (int) $a_file_id),
921  "usage_type" => array("text", (string) $a_type),
922  "usage_id" => array("integer", (int) $a_id),
923  "usage_hist_nr" => array("integer", (int) $a_usage_hist_nr),
924  "usage_lang" => array("text", $a_usage_lang)
925  ),
926  array()
927  );
928 
929  self::handleQuotaUpdate(new self($a_file_id, false));
930  }
931 
935  function getUsages()
936  {
937  global $ilDB;
938 
939  // get usages in learning modules
940  $q = "SELECT * FROM file_usage WHERE id = ".$ilDB->quote($this->getId(), "integer");
941  $us_set = $ilDB->query($q);
942  $ret = array();
943  while($us_rec = $ilDB->fetchAssoc($us_set))
944  {
945  $ret[] = array("type" => $us_rec["usage_type"],
946  "id" => $us_rec["usage_id"],
947  "lang" => $us_rec["usage_lang"],
948  "hist_nr" => $us_rec["usage_hist_nr"]);
949  }
950 
951  return $ret;
952  }
953 
962  function _getFilesOfObject($a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-")
963  {
964  global $ilDB;
965 
966  // get usages in learning modules
967  $q = "SELECT * FROM file_usage WHERE ".
968  "usage_id = ".$ilDB->quote((int) $a_id, "integer")." AND ".
969  "usage_type = ".$ilDB->quote((string) $a_type, "text")." AND ".
970  "usage_lang = ".$ilDB->quote((string) $a_usage_lang, "text")." AND ".
971  "usage_hist_nr = ".$ilDB->quote((int) $a_usage_hist_nr, "integer");
972  $file_set = $ilDB->query($q);
973  $ret = array();
974  while($file_rec = $ilDB->fetchAssoc($file_set))
975  {
976  $ret[$file_rec["id"]] = $file_rec["id"];
977  }
978 
979  return $ret;
980  }
981 
982  // TODO: What is this function good for??
983  function getXMLZip()
984  {
985  global $ilias;
986 
987  $zip = PATH_TO_ZIP;
988 
989  exec($zip.' '.ilUtil::escapeShellArg($this->getDirectory().'/'.$this->getFileName())." ".
990  ilUtil::escapeShellArg($this->getDirectory().'/'.'1.zip'));
991 
992  return $this->getDirectory().'/1.zip';
993  }
994 
995  function addNewsNotification($a_lang_var)
996  {
997  // BEGIN WebDAV Suppress news notification for hidden files
998  if ($this->isHidden()) {
999  return;
1000  }
1001  // END WebDAV Suppress news notification for hidden files
1002 
1003  global $ilUser;
1004 
1005  // Add Notification to news
1006  include_once("./Services/News/classes/class.ilNewsItem.php");
1007  include_once("./Modules/File/classes/class.ilObjFileAccess.php");
1008  $news_item = new ilNewsItem();
1009  $news_item->setContext($this->getId(), $this->getType());
1010  $news_item->setPriority(NEWS_NOTICE);
1011  $news_item->setTitle($a_lang_var);
1012  $news_item->setContentIsLangVar(true);
1013  if ($this->getDescription() != "")
1014  {
1015  $news_item->setContent(
1016  "<p>".
1017  $this->getDescription()."</p>");
1018  }
1019  $news_item->setUserId($ilUser->getId());
1020  $news_item->setVisibility(NEWS_USERS);
1021  $news_item->create();
1022  }
1023 
1030  public function initFileStorage()
1031  {
1032  $this->file_storage = new ilFSStorageFile($this->getId());
1033  return true;
1034  }
1044  function storeUnzipedFile($a_upload_file, $a_filename)
1045  {
1046  $this->setVersion($this->getVersion() + 1);
1047 
1048  if (@!is_dir($this->getDirectory($this->getVersion())))
1049  {
1050  ilUtil::makeDir($this->getDirectory($this->getVersion()));
1051  }
1052 
1053  $file = $this->getDirectory($this->getVersion())."/".$a_filename;
1054  //move_uploaded_file($a_upload_file, $file);
1055  rename($a_upload_file, $file);
1056 
1057  // create preview
1058  $this->createPreview();
1059  }
1060 
1065  public static function _lookupAbsolutePath ($obj_id, $a_version = null)
1066  {
1067  $file_storage = new ilFSStorageFile($obj_id);
1069  $version_subdir = "";
1070 
1071  if (!is_numeric($a_version))
1072  {
1073  $a_version = ilObjFile::_lookupVersion ($obj_id);
1074  }
1075  $version_subdir = DIRECTORY_SEPARATOR.sprintf("%03d", $a_version);
1076  return $file_storage->getAbsolutePath().$version_subdir.DIRECTORY_SEPARATOR.$filename;
1077  }
1078 
1083  public function checkFileExtension($new_filename,$new_title)
1084  {
1085  include_once './Modules/File/classes/class.ilObjFileAccess.php';
1086  $fileExtension = ilObjFileAccess::_getFileExtension($new_filename);
1087  $titleExtension = ilObjFileAccess::_getFileExtension($new_title);
1088  if ($titleExtension != $fileExtension && strlen($fileExtension) > 0)
1089  {
1090  // remove old extension
1091  $pi = pathinfo($this->getFileName());
1092  $suffix = $pi["extension"];
1093  if ($suffix != "")
1094  {
1095  if (substr($new_title,
1096  strlen($new_title) - strlen($suffix) - 1)
1097  == ".".$suffix)
1098  {
1099  $new_title = substr($new_title, 0, strlen($new_title) - strlen($suffix) - 1);
1100  }
1101  }
1102  $new_title .= '.'.$fileExtension;
1103  }
1104  return $new_title;
1105  }
1106 
1113  public function getVersions($version_ids = null)
1114  {
1115  include_once("./Services/History/classes/class.ilHistory.php");
1116  $versions = ilHistory::_getEntriesForObject($this->getId(), $this->getType());
1117 
1118  if ($version_ids != null && count($version_ids) > 0)
1119  {
1120  foreach ($versions as $index => $version)
1121  {
1122  if (!in_array($version["hist_entry_id"], $version_ids, true))
1123  {
1124  unset($versions[$index]);
1125  }
1126  }
1127  }
1128 
1129  // add custom entries
1130  foreach ($versions as $index => $version)
1131  {
1132  $params = $this->parseInfoParams($version);
1133  $versions[$index] = array_merge($version, $params);
1134  }
1135 
1136  // sort by version number (hist_entry_id will do for that)
1137  usort($versions, array($this, "compareVersions"));
1138 
1139  return $versions;
1140  }
1141 
1148  public function getSpecificVersion($version_id)
1149  {
1150  include_once("./Services/History/classes/class.ilHistory.php");
1151  $version = ilHistory::_getEntryByHistoryID($version_id);
1152  if ($version === false)
1153  return false;
1154 
1155  // ilHistory returns different keys in _getEntryByHistoryID and _getEntriesForObject
1156  // so this makes it the same
1157  $version["hist_entry_id"] = $version["id"];
1158  $version["user_id"] = $version["usr_id"];
1159  $version["date"] = $version["hdate"];
1160  unset($version["id"], $version["usr_id"], $version["hdate"]);
1161 
1162  // parse params
1163  $params = $this->parseInfoParams($version);
1164  return array_merge($version, $params);
1165  }
1166 
1173  public function rollback($version_id)
1174  {
1175  global $ilDB, $ilUser;
1176 
1177  $source = $this->getSpecificVersion($version_id);
1178  if ($source === false)
1179  {
1180  $this->ilErr->raiseError($this->lng->txt("obj_not_found"), $this->ilErr->MESSAGE);
1181  }
1182 
1183  // get the new version number
1184  $new_version_nr = $this->getVersion() + 1;
1185 
1186  // copy file
1187  $source_path = $this->getDirectory($source["version"]) . "/" . $source["filename"];
1188  $dest_dir = $this->getDirectory($new_version_nr);
1189  if (@!is_dir($dest_dir))
1190  ilUtil::makeDir($dest_dir);
1191 
1192  copy($source_path, $dest_dir . "/" . $source["filename"]);
1193 
1194  // create new history entry based on the old one
1195  include_once("./Services/History/classes/class.ilHistory.php");
1197  $this->getId(),
1198  "rollback",
1199  $source["filename"] . "," . $new_version_nr . "|" . $source["version"] . "|" . $ilUser->getId());
1200 
1201  // get id of newest entry
1202  $new_version = $this->getSpecificVersion($ilDB->getLastInsertId());
1203 
1204  // change user back to the original uploader
1205  ilHistory::_changeUserId($new_version["hist_entry_id"], $source["user_id"]);
1206 
1207  // update this file with the new version
1208  $this->updateWithVersion($new_version);
1209 
1210  $this->addNewsNotification("file_updated");
1211 
1212  return $new_version;
1213  }
1214 
1220  protected function updateWithVersion($version)
1221  {
1222  // update title (checkFileExtension must be called before setFileName!)
1223  $this->setTitle($this->checkFileExtension($version["filename"], $this->getTitle()));
1224 
1225  $this->setVersion($version["version"]);
1226  $this->setFileName($version["filename"]);
1227 
1228  // evaluate mime type (reset file type before)
1229  $this->setFileType("");
1230  $this->setFileType($this->guessFileType($version["filename"]));
1231 
1232  // set filesize
1233  $this->determineFileSize();
1234 
1235  $this->update();
1236 
1237  // refresh preview
1238  $this->createPreview(true);
1239  }
1240 
1248  function compareVersions($v1, $v2)
1249  {
1250  // v2 - v1 because version should be descending
1251  return (int)$v2["version"] - (int)$v1["version"];
1252  }
1253 
1260  function parseInfoParams($entry)
1261  {
1262  $data = preg_split("/(.*),(.*)/", $entry["info_params"], 0, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
1263 
1264  // bugfix: first created file had no version number
1265  // this is a workaround for all files created before the bug was fixed
1266  if (empty($data[1]))
1267  $data[1] = "1";
1268 
1269  $result = array("filename" => $data[0], "version" => $data[1], "rollback_version" => "", "rollback_user_id" => "");
1270 
1271  // if rollback, the version contains the rollback version as well
1272  if ($entry["action"] == "rollback")
1273  {
1274  $tokens = explode("|", $result["version"]);
1275  if (count($tokens) > 1)
1276  {
1277  $result["version"] = $tokens[0];
1278  $result["rollback_version"] = $tokens[1];
1279 
1280  if (count($tokens) > 2)
1281  $result["rollback_user_id"] = $tokens[2];
1282  }
1283  }
1284 
1285  return $result;
1286  }
1287 
1288  protected static function handleQuotaUpdate(ilObjFile $a_file)
1289  {
1290  include_once "Services/MediaObjects/classes/class.ilObjMediaObject.php";
1291  $mob = new ilObjMediaObject();
1292 
1293  // file itself could be workspace item
1294  $parent_obj_ids = array($a_file->getId());
1295 
1296  foreach($a_file->getUsages() as $item)
1297  {
1298  $parent_obj_id = $mob->getParentObjectIdForUsage($item);
1299  if($parent_obj_id &&
1300  !in_array($parent_obj_id, $parent_obj_ids))
1301  {
1302  $parent_obj_ids[]= $parent_obj_id;
1303  }
1304  }
1305 
1306  include_once "Services/DiskQuota/classes/class.ilDiskQuotaHandler.php";
1308  $a_file->getId(),
1309  $a_file->getDiskUsage(),
1310  $parent_obj_ids);
1311  }
1312 
1318  protected function createPreview($force = false)
1319  {
1320  // only normal files are supported
1321  if ($this->getMode() != "object")
1322  return;
1323 
1324  require_once("./Services/Preview/classes/class.ilPreview.php");
1325  ilPreview::createPreview($this, $force);
1326  }
1327 
1331  protected function deletePreview()
1332  {
1333  // only normal files are supported
1334  if ($this->getMode() != "object")
1335  return;
1336 
1337  require_once("./Services/Preview/classes/class.ilPreview.php");
1338  ilPreview::deletePreview($this->getId());
1339  }
1340 
1341  public function setRating($a_value)
1342  {
1343  $this->rating = (bool)$a_value;
1344  }
1345 
1346  public function hasRating()
1347  {
1348  return $this->rating;
1349  }
1350 
1351 } // END class.ilObjFile
1352 ?>