1<?php 2/* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */ 3 4use ILIAS\File\Sanitation\FilePathSanitizer; 5use ILIAS\Filesystem\Exception\FileNotFoundException; 6use ILIAS\Filesystem\Util\LegacyPathHelper; 7use ILIAS\FileUpload\Location; 8 9require_once("Services/Object/classes/class.ilObject2.php"); 10require_once('Modules/File/classes/class.ilFSStorageFile.php'); 11 12/** 13 * Class ilObjFile 14 * 15 * @author Sascha Hofmann <shofmann@databay.de> 16 * @author Fabian Schmid <fs@studer-raimann.ch> 17 * @version $Id$ 18 * 19 * @ingroup ModulesFile 20 */ 21class ilObjFile extends ilObject2 22{ 23 const MODE_FILELIST = "filelist"; 24 const MODE_OBJECT = "object"; 25 /** 26 * @var bool 27 */ 28 protected $no_meta_data_creation; 29 /** 30 * @var string 31 */ 32 protected $filename = ''; 33 /** 34 * @var string 35 */ 36 protected $filetype = ''; 37 /** 38 * @var string 39 */ 40 protected $filemaxsize = "20000000"; // not used yet 41 /** 42 * @var string 43 */ 44 protected $filesize; 45 /** 46 * @var bool 47 */ 48 public $raise_upload_error; 49 /** 50 * @var string 51 */ 52 public $mode = self::MODE_OBJECT; 53 /** 54 * @var int 55 */ 56 protected $page_count = 0; 57 /** 58 * @var bool 59 */ 60 protected $rating = false; 61 /** 62 * @var \ilFSStorageFile 63 */ 64 private $file_storage = null; 65 /** 66 * @var \ilLogger 67 */ 68 protected $log = null; 69 /** 70 * @var int 71 */ 72 protected $version = 1; 73 /** 74 * @var int 75 */ 76 protected $max_version = 1; 77 /** 78 * @var string 79 */ 80 protected $action = null; 81 /** 82 * @var int 83 */ 84 protected $rollback_version = null; 85 /** 86 * @var int 87 */ 88 protected $rollback_user_id = null; 89 90 91 /** 92 * ilObjFile constructor. 93 * 94 * @param int $a_id ID of the object, ref_id or obj_id possible 95 * @param bool $a_call_by_reference defines the $a_id a ref_id 96 */ 97 public function __construct($a_id = 0, $a_call_by_reference = true) 98 { 99 $this->version = 0; 100 $this->max_version = 0; 101 $this->raise_upload_error = true; 102 103 $this->log = ilLoggerFactory::getLogger('file'); 104 105 parent::__construct($a_id, $a_call_by_reference); 106 107 if ($this->getId()) { 108 $this->initFileStorage(); 109 } 110 } 111 112 113 public function initType() 114 { 115 $this->type = "file"; 116 } 117 118 119 /** 120 * create object 121 * 122 * @param bool upload mode (if enabled no entries in file_data will be done) 123 */ 124 protected function doCreate($a_upload = false) 125 { 126 $this->createProperties($a_upload); 127 } 128 129 130 /** 131 * The basic properties of a file object are stored in table object_data. 132 * This is not sufficient for a file object. Therefore we create additional 133 * properties in table file_data. 134 * This method has been put into a separate operation, to allow a WebDAV Null resource 135 * (class.ilObjNull.php) to become a file object. 136 */ 137 public function createProperties($a_upload = false) 138 { 139 global $DIC; 140 141 // Create file directory 142 $this->initFileStorage(); 143 $this->file_storage->create(); 144 145 if ($a_upload) { 146 return true; 147 } 148 149 // not upload mode 150 ilHistory::_createEntry($this->getId(), "create", $this->getFileName() . ",1" . ",1"); 151 $this->addNewsNotification("file_created"); 152 153 // New Item 154 $default_visibility = ilNewsItem::_getDefaultVisibilityForRefId($_GET['ref_id']); 155 if ($default_visibility == "public") { 156 ilBlockSetting::_write("news", "public_notifications", 1, 0, $this->getId()); 157 } 158 159 // log creation 160 $this->log->debug("ilObjFile::createProperties, ID: " . $this->getId() . ", Name: " 161 . $this->getFileName() . ", Type: " . $this->getFileType() . ", Size: " 162 . $this->getFileSize() . ", Mode: " . $this->getMode() . ", Name(Bytes): " 163 . implode(":", ilStr::getBytesForString($this->getFileName()))); 164 $this->log->logStack(ilLogLevel::DEBUG); 165 166 $DIC->database()->insert('file_data', $this->getArrayForDatabase()); 167 168 //add metadata to database 169 $metadata = [ 170 'meta_lifecycle_id' => ['integer', $DIC->database()->nextId('il_meta_lifecycle')], 171 'rbac_id' => ['integer', $this->getId()], 172 'obj_id' => ['integer', $this->getId()], 173 'obj_type' => ['text', "file"], 174 'meta_version' => ['integer', (int) $this->getVersion()], 175 ]; 176 $DIC->database()->insert('il_meta_lifecycle', $metadata); 177 178 // no meta data handling for file list files 179 if ($this->getMode() != self::MODE_FILELIST) { 180 $this->createMetaData(); 181 } 182 } 183 184 185 /** 186 * @param bool $a_status 187 */ 188 public function setNoMetaDataCreation($a_status) 189 { 190 $this->no_meta_data_creation = (bool) $a_status; 191 } 192 193 194 protected function beforeCreateMetaData() 195 { 196 return !(bool) $this->no_meta_data_creation; 197 } 198 199 200 protected function beforeUpdateMetaData() 201 { 202 return !(bool) $this->no_meta_data_creation; 203 } 204 205 206 /** 207 * create file object meta data 208 */ 209 protected function doCreateMetaData() 210 { 211 // add technical section with file size and format 212 $md_obj = new ilMD($this->getId(), 0, $this->getType()); 213 $technical = $md_obj->addTechnical(); 214 $technical->setSize($this->getFileSize()); 215 $technical->save(); 216 $format = $technical->addFormat(); 217 $format->setFormat($this->getFileType()); 218 $format->save(); 219 $technical->update(); 220 } 221 222 223 protected function beforeMDUpdateListener($a_element) 224 { 225 // Check file extension 226 // Removing the file extension is not allowed 227 include_once 'Services/MetaData/classes/class.ilMD.php'; 228 $md = new ilMD($this->getId(), 0, $this->getType()); 229 if (!is_object($md_gen = $md->getGeneral())) { 230 return false; 231 } 232 $title = $this->checkFileExtension($this->getFileName(), $md_gen->getTitle()); 233 $md_gen->setTitle($title); 234 $md_gen->update(); 235 236 return true; 237 } 238 239 240 protected function doMDUpdateListener($a_element) 241 { 242 // handling for technical section 243 include_once 'Services/MetaData/classes/class.ilMD.php'; 244 245 switch ($a_element) { 246 case 'Technical': 247 248 // Update Format (size is not stored in db) 249 $md = new ilMD($this->getId(), 0, $this->getType()); 250 if (!is_object($md_technical = $md->getTechnical())) { 251 return false; 252 } 253 254 foreach ($md_technical->getFormatIds() as $id) { 255 $md_format = $md_technical->getFormat($id); 256 ilObjFile::_writeFileType($this->getId(), $md_format->getFormat()); 257 $this->setFileType($md_format->getFormat()); 258 break; 259 } 260 261 break; 262 } 263 264 return true; 265 } 266 267 268 /** 269 * @param int $a_version 270 * 271 * @return string 272 */ 273 public function getDirectory($a_version = 0) 274 { 275 $version_subdir = ""; 276 277 if ($a_version) { 278 // BEGIN WebDAV Avoid double slash before version subdirectory 279 $version_subdir = sprintf("%03d", $a_version); 280 // END WebDAV Avoid double slash before version subdirectory 281 } 282 283 if (!is_object($this->file_storage)) { 284 $this->initFileStorage(); 285 } 286 287 $str = $this->file_storage->getAbsolutePath() . '/' . $version_subdir; 288 289 return $str; 290 } 291 292 293 public function createDirectory() 294 { 295 ilUtil::makeDirParents($this->getDirectory()); 296 } 297 298 299 public function raiseUploadError($a_raise = true) 300 { 301 $this->raise_upload_error = $a_raise; 302 } 303 304 305 /** 306 * @param $a_upload_file 307 * @param $a_filename 308 * @param bool $a_prevent_preview 309 * 310 * @return \ILIAS\FileUpload\DTO\UploadResult 311 * @throws \ILIAS\FileUpload\Collection\Exception\NoSuchElementException 312 * @throws \ILIAS\FileUpload\Exception\IllegalStateException 313 */ 314 public function getUploadFile($a_upload_file, $a_filename, $a_prevent_preview = false) 315 { 316 global $DIC; 317 318 $upload = $DIC->upload(); 319 $result = null; 320 321 if ($upload->hasUploads()) { 322 if (!$upload->hasBeenProcessed()) { 323 $upload->process(); 324 } 325 /** 326 * @var $result \ILIAS\FileUpload\DTO\UploadResult 327 */ 328 $result = $upload->getResults()[$a_upload_file]; 329 if ($result->getStatus()->getCode() === \ILIAS\FileUpload\DTO\ProcessingStatus::OK) { 330 $metadata = $result->getMetaData(); 331 if ($metadata->has(ilCountPDFPagesPreProcessors::PAGE_COUNT)) { 332 $this->setPageCount($metadata->get(ilCountPDFPagesPreProcessors::PAGE_COUNT)); 333 $this->doUpdate(); 334 } 335 $a_name = $result->getName(); 336 $this->setFileName($a_name); 337 338 // bugfix mantis 26236: 339 // ensure that version and max_version are correct to prevent the upload file from being versioned incorrectly 340 if ($this->getVersion() > 0) { 341 $file_hist_entries = (array) ilHistory::_getEntriesForObject($this->getId(), $this->getType()); 342 $highest_version = 0; 343 foreach ($file_hist_entries as $file_hist_entry) { 344 $version = $this->parseInfoParams($file_hist_entry)['version']; 345 if ($version > $highest_version) { 346 $highest_version = $version; 347 } 348 } 349 if ($this->getVersion() < $highest_version) { 350 $this->setVersion($highest_version); 351 } 352 if ($this->getVersion() > $this->getMaxVersion()) { 353 $this->setMaxVersion($this->getVersion()); 354 } 355 } 356 357 $this->setVersion($this->getMaxVersion() + 1); 358 $this->setMaxVersion($this->getMaxVersion() + 1); 359 360 if (!is_dir($this->getDirectory($this->getVersion()))) { 361 ilUtil::makeDirParents($this->getDirectory($this->getVersion())); 362 } 363 364 $target_directory = $this->getDirectory($this->getVersion()) . "/"; 365 $relative_path_to_file = LegacyPathHelper::createRelativePath($target_directory); 366 367 $upload->moveOneFileTo($result, $relative_path_to_file, Location::STORAGE); 368 369 $this->handleQuotaUpdate($this); 370 371 // create preview? 372 if (!$a_prevent_preview) { 373 $this->createPreview(false); 374 } 375 } else { 376 throw new ilFileException('not supported File'); 377 } 378 } 379 380 return $result; 381 } 382 383 384 /** 385 * @param $a_upload_file 386 * @param $a_filename 387 * 388 * @return \ILIAS\FileUpload\DTO\UploadResult 389 * @throws \ILIAS\FileUpload\Collection\Exception\NoSuchElementException 390 * @throws \ILIAS\FileUpload\Exception\IllegalStateException 391 */ 392 public function replaceFile($a_upload_file, $a_filename) 393 { 394 if ($result = $this->getUploadFile($a_upload_file, $a_filename, true)) { 395 ilHistory::_createEntry($this->getId(), "replace", $a_filename . "," . $this->getVersion() . "," . $this->getMaxVersion()); 396 $this->addNewsNotification("file_updated"); 397 398 // create preview 399 $this->createPreview(true); 400 } 401 402 return $result; 403 } 404 405 406 /** 407 * @param $a_upload_file 408 * @param $a_filename 409 * 410 * @return \ILIAS\FileUpload\DTO\UploadResult 411 * @throws \ILIAS\FileUpload\Collection\Exception\NoSuchElementException 412 * @throws \ILIAS\FileUpload\Exception\IllegalStateException 413 */ 414 public function addFileVersion($a_upload_file, $a_filename) 415 { 416 if ($result = $this->getUploadFile($a_upload_file, $a_filename, true)) { 417 ilHistory::_createEntry($this->getId(), "new_version", $result->getName() . "," . $this->getVersion() . "," . $this->getMaxVersion()); 418 $this->addNewsNotification("file_updated"); 419 420 // create preview 421 $this->createPreview($this->getVersion() > 1); 422 } 423 424 return $result; 425 } 426 427 428 /** 429 * copy file 430 */ 431 public function copy($a_source, $a_destination) 432 { 433 return copy($a_source, $this->getDirectory() . "/" . $a_destination); 434 } 435 436 437 /** 438 * clear data directory 439 */ 440 public function clearDataDirectory() 441 { 442 ilUtil::delDir($this->getDirectory()); 443 $this->createDirectory(); 444 } 445 446 447 /** 448 * Deletes the specified history entries or all entries if no ids are specified. 449 * 450 * @param array $a_hist_entry_ids The ids of the entries to delete or null to delete all entries 451 */ 452 public function deleteVersions($a_hist_entry_ids = null) 453 { 454 if ($a_hist_entry_ids == null || count($a_hist_entry_ids) < 1) { 455 $this->clearDataDirectory(); 456 457 ilHistory::_removeEntriesForObject($this->getId()); 458 459 self::handleQuotaUpdate($this); 460 } else { 461 $actualVersionDeleted = false; 462 463 // get all versions 464 $versions = $this->getVersions(); 465 466 // delete each version 467 foreach ($a_hist_entry_ids as $hist_id) { 468 $entry = null; 469 470 // get version 471 foreach ($versions as $index => $version) { 472 if ($version["hist_entry_id"] == $hist_id) { 473 // remove each history entry 474 ilHistory::_removeEntryByHistoryID($hist_id); 475 476 // delete directory 477 $version_dir = $this->getDirectory($version["version"]); 478 ilUtil::delDir($version_dir); 479 480 // is actual version? 481 if ($version["version"] == $this->getVersion()) { 482 $actualVersionDeleted = true; 483 } 484 485 // remove from array 486 unset($versions[$index]); 487 break; 488 } 489 } 490 } 491 492 // update actual version if it was deleted before 493 if ($actualVersionDeleted) { 494 // get newest version (already sorted by getVersions) 495 $version = reset($versions); 496 $version['max_version'] = $this->getMaxVersion(); 497 $this->updateWithVersion($version); 498 } else { 499 // updateWithVersion() will trigger quota, too 500 self::handleQuotaUpdate($this); 501 } 502 } 503 } 504 505 506 protected function doRead() 507 { 508 global $DIC; 509 510 $q = "SELECT * FROM file_data WHERE file_id = %s"; 511 $r = $DIC->database()->queryF($q, ['integer'], [$this->getId()]); 512 $row = $r->fetchObject(); 513 514 $this->setFileName($row->file_name); 515 $this->setFileType($row->file_type); 516 $this->setFileSize($row->file_size); 517 $this->setVersion($row->version ? $row->version : 1); 518 $this->setMaxVersion($row->max_version ? $row->max_version : 1); 519 $this->setMode($row->f_mode); 520 $this->setRating($row->rating); 521 $this->setPageCount($row->page_count); 522 523 $this->initFileStorage(); 524 } 525 526 527 protected function beforeUpdate() 528 { 529 // no meta data handling for file list files 530 if ($this->getMode() != self::MODE_FILELIST) { 531 $this->updateMetaData(); 532 } 533 534 return true; 535 } 536 537 538 protected function doUpdate() 539 { 540 global $DIC; 541 542 $a_columns = $this->getArrayForDatabase(); 543 $DIC->database()->update('file_data', $a_columns, [ 544 'file_id' => [ 545 'integer', 546 $this->getId(), 547 ], 548 ]); 549 550 // update metadata with the current file version 551 $meta_version_column = ['meta_version' => ['integer', (int) $this->getVersion()]]; 552 $DIC->database()->update('il_meta_lifecycle', $meta_version_column, [ 553 'obj_id' => [ 554 'integer', 555 $this->getId(), 556 ], 557 ]); 558 559 self::handleQuotaUpdate($this); 560 561 return true; 562 } 563 564 565 /** 566 * update meta data 567 */ 568 protected function doUpdateMetaData() 569 { 570 // add technical section with file size and format 571 $md_obj = new ilMD($this->getId(), 0, $this->getType()); 572 if (!is_object($technical = $md_obj->getTechnical())) { 573 $technical = $md_obj->addTechnical(); 574 $technical->save(); 575 } 576 $technical->setSize($this->getFileSize()); 577 578 $format_ids = $technical->getFormatIds(); 579 if (count($format_ids) > 0) { 580 $format = $technical->getFormat($format_ids[0]); 581 $format->setFormat($this->getFileType()); 582 $format->update(); 583 } else { 584 $format = $technical->addFormat(); 585 $format->setFormat($this->getFileType()); 586 $format->save(); 587 } 588 $technical->update(); 589 } 590 591 592 /** 593 * @param string $a_name 594 */ 595 public function setFileName($a_name) 596 { 597 $this->filename = $a_name; 598 } 599 600 601 /** 602 * @return string 603 */ 604 public function getFileName() 605 { 606 return $this->filename; 607 } 608 609 610 /** 611 * @param string $a_type 612 */ 613 public function setFileType($a_type) 614 { 615 $this->filetype = $a_type; 616 } 617 618 619 /** 620 * @return string 621 */ 622 public function getFileType() 623 { 624 return $this->filetype; 625 } 626 627 628 /** 629 * @param $a_size 630 */ 631 public function setFileSize($a_size) 632 { 633 $this->filesize = $a_size; 634 } 635 636 637 public function getFileSize() 638 { 639 return $this->filesize; 640 } 641 642 643 public function setAction($a_action) 644 { 645 $this->action = $a_action; 646 } 647 648 649 public function getAction() 650 { 651 return $this->action; 652 } 653 654 655 public function setRollbackVersion($a_rollback_version) 656 { 657 $this->rollback_version = $a_rollback_version; 658 } 659 660 661 public function getRollbackVersion() 662 { 663 return $this->rollback_version; 664 } 665 666 667 public function setRollbackUserId($a_rollback_user_id) 668 { 669 $this->rollback_user_id = $a_rollback_user_id; 670 } 671 672 673 public function getRollbackUserId() 674 { 675 return $this->rollback_user_id; 676 } 677 678 679 /** 680 * Gets the disk usage of the object in bytes. 681 * 682 * @access public 683 * @return integer the disk usage in bytes 684 */ 685 public function getDiskUsage() 686 { 687 require_once("./Modules/File/classes/class.ilObjFileAccess.php"); 688 689 return ilObjFileAccess::_lookupDiskUsage($this->id); 690 } 691 692 693 // END PATCH WebDAV Encapsulate file access in ilObjFile class. 694 public function getFile($a_hist_entry_id = null) 695 { 696 if (is_null($a_hist_entry_id)) { 697 $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName(); 698 } else { 699 require_once("./Services/History/classes/class.ilHistory.php"); 700 $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id); 701 702 if ($entry === false) { 703 return false; 704 } 705 706 $data = $this->parseInfoParams($entry); 707 $file = $this->getDirectory($data["version"]) . "/" . $data["filename"]; 708 } 709 710 return $file; 711 } 712 713 714 // END PATCH WebDAV Encapsulate file access in ilObjFile class. 715 716 public function setVersion($a_version) 717 { 718 $this->version = $a_version; 719 } 720 721 722 public function getVersion() 723 { 724 return $this->version; 725 } 726 727 728 public function setMaxVersion($a_max_version) 729 { 730 $this->max_version = $a_max_version; 731 } 732 733 734 public function getMaxVersion() 735 { 736 return $this->max_version; 737 } 738 739 740 /** 741 * mode is object or filelist 742 * 743 * @param string $a_mode mode 744 */ 745 public function setMode($a_mode) 746 { 747 $this->mode = $a_mode; 748 } 749 750 751 /** 752 * mode is object or filelist 753 * 754 * @return string mode 755 */ 756 public function getMode() 757 { 758 return $this->mode; 759 } 760 761 762 public static function _writeFileType($a_id, $a_format) 763 { 764 global $DIC; 765 $ilDB = $DIC['ilDB']; 766 767 $q = "UPDATE file_data SET " . " file_type = " . $ilDB->quote($a_format, 'text') 768 . " WHERE file_id = " . $ilDB->quote($a_id, 'integer'); 769 $res = $ilDB->manipulate($q); 770 } 771 772 773 /** 774 * @param $a_id 775 * 776 * @return string 777 * @deprecated Static methods will be removed in a future version of ILIAS 778 */ 779 public static function _lookupFileName($a_id) 780 { 781 global $DIC; 782 $ilDB = $DIC['ilDB']; 783 784 $q = "SELECT * FROM file_data WHERE file_id = " . $ilDB->quote($a_id, 'integer'); 785 $r = $ilDB->query($q); 786 $row = $r->fetchRow(ilDBConstants::FETCHMODE_OBJECT); 787 788 $strip_slashes = ilUtil::stripSlashes($row->file_name); 789 790 return $strip_slashes; 791 } 792 793 794 /** Lookups the file size of the file in bytes. */ 795 public static function _lookupFileSize($a_id) 796 { 797 require_once("./Modules/File/classes/class.ilObjFileAccess.php"); 798 799 return ilObjFileAccess::_lookupFileSize($a_id); 800 } 801 802 803 /** 804 * lookup version 805 */ 806 public static function _lookupVersion($a_id) 807 { 808 require_once("./Modules/File/classes/class.ilObjFileAccess.php"); 809 810 return ilObjFileAccess::_lookupVersion($a_id); 811 } 812 813 814 /** 815 * Determine File Size 816 */ 817 public function determineFileSize($a_hist_entry_id = null) 818 { 819 if (is_null($a_hist_entry_id)) { 820 $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName(); 821 } else { 822 require_once("./Services/History/classes/class.ilHistory.php"); 823 $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id); 824 825 if ($entry === false) { 826 return false; 827 } 828 829 $data = $this->parseInfoParams($entry); 830 $file = $this->getDirectory($data["version"]) . "/" . $data["filename"]; 831 } 832 if (is_file($file)) { 833 $this->setFileSize(filesize($file)); 834 } 835 } 836 837 838 /** 839 * @param null $a_hist_entry_id 840 * 841 * @return bool 842 */ 843 public function sendFile($a_hist_entry_id = null) 844 { 845 $s = new FilePathSanitizer($this); 846 $s->sanitizeIfNeeded(); 847 848 if (is_null($a_hist_entry_id)) { 849 $file = $this->getDirectory($this->getVersion()) . "/" . $this->getFileName(); 850 $file = ilFileUtils::getValidFilename($file); 851 } else { 852 $entry = ilHistory::_getEntryByHistoryID($a_hist_entry_id); 853 $data = $this->parseInfoParams($entry); 854 $file = $this->getDirectory($data["version"]) . "/" . $data["filename"]; 855 } 856 857 858 if ($this->file_storage->fileExists($file)) { 859 global $DIC; 860 $ilClientIniFile = $DIC['ilClientIniFile']; 861 /** 862 * @var $ilClientIniFile ilIniFile 863 */ 864 865 $ilFileDelivery = new ilFileDelivery($file); 866 $ilFileDelivery->setDisposition($this->isInline() ? ilFileDelivery::DISP_INLINE : ilFileDelivery::DISP_ATTACHMENT); 867 $ilFileDelivery->setMimeType($this->guessFileType($file)); 868 $ilFileDelivery->setConvertFileNameToAsci((bool) !$ilClientIniFile->readVariable('file_access', 'disable_ascii')); 869 870 // also returning the 'real' filename if a history file is delivered 871 if ($ilClientIniFile->readVariable('file_access', 'download_with_uploaded_filename') 872 != '1' 873 && is_null($a_hist_entry_id) 874 ) { 875 $ilFileDelivery->setDownloadFileName(ilFileUtils::getValidFilename($this->getTitle())); 876 } else { 877 // $download_file_name = basename($file); 878 /* FSX Info: basename has a Bug with Japanese and other characters, see: 879 * http://stackoverflow.com/questions/32115609/basename-fail-when-file-name-start-by-an-accent 880 * Therefore we can no longer use basename(); 881 */ 882 $parts = explode(DIRECTORY_SEPARATOR, $file); 883 $download_file_name = end($parts); 884 $download_file_name = ilFileUtils::getValidFilename($download_file_name); 885 $ilFileDelivery->setDownloadFileName($download_file_name); 886 } 887 $ilFileDelivery->deliver(); 888 889 return true; 890 } 891 892 throw new FileNotFoundException($this->lng->txt('file_not_found_sec')); 893 } 894 895 896 /** 897 * Returns the extension of the file name converted to lower-case. 898 * e.g. returns 'pdf' for 'document.pdf'. 899 */ 900 public function getFileExtension() 901 { 902 require_once 'Modules/File/classes/class.ilObjFileAccess.php'; 903 904 return ilObjFileAccess::_getFileExtension($this->getTitle()); 905 } 906 907 908 /** 909 * Returns true, if this file should be displayed inline in a browser 910 * window. This is especially useful for PDF documents, HTML pages, 911 * and for images which are directly supported by the browser. 912 */ 913 public function isInline() 914 { 915 require_once 'Modules/File/classes/class.ilObjFileAccess.php'; 916 917 return ilObjFileAccess::_isFileInline($this->getTitle()); 918 } 919 920 921 /** 922 * Returns true, if this file should be hidden in the repository view. 923 */ 924 public function isHidden() 925 { 926 require_once 'Modules/File/classes/class.ilObjFileAccess.php'; 927 928 return ilObjFileAccess::_isFileHidden($this->getTitle()); 929 } 930 // END WebDAV: Get file extension, determine if file is inline, guess file type. 931 932 933 /** 934 * Guesses the file type based on the current values returned by getFileType() 935 * and getFileExtension(). 936 * If getFileType() returns 'application/octet-stream', the file extension is 937 * used to guess a more accurate file type. 938 */ 939 public function guessFileType($a_file = "") 940 { 941 $path = pathinfo($a_file); 942 if ($path["extension"] != "") { 943 $filename = $path["basename"]; 944 } else { 945 $filename = "dummy." . $this->getFileExtension(); 946 } 947 include_once("./Services/Utilities/classes/class.ilMimeTypeUtil.php"); 948 $mime = ilMimeTypeUtil::getMimeType($a_file, $filename, $this->getFileType()); 949 950 return $mime; 951 } 952 953 954 /** 955 * Clone 956 * 957 * @access public 958 * 959 * @param object clone 960 * @param int target id 961 * @param int copy id 962 * 963 */ 964 protected function doCloneObject($a_new_obj, $a_target_id, $a_copy_id = 0) 965 { 966 global $DIC; 967 $ilDB = $DIC['ilDB']; 968 969 $a_new_obj->createDirectory(); 970 $this->cloneMetaData($a_new_obj); 971 972 // Copy all file versions 973 ilUtil::rCopy($this->getDirectory(), $a_new_obj->getDirectory()); 974 975 // object created now copy other settings 976 // bugfix mantis 26131 977 $DIC->database()->insert('file_data', $this->getArrayForDatabase($a_new_obj->getId())); 978 979 // copy all previews 980 require_once("./Services/Preview/classes/class.ilPreview.php"); 981 ilPreview::copyPreviews($this->getId(), $a_new_obj->getId()); 982 983 // copy history entries 984 require_once("./Services/History/classes/class.ilHistory.php"); 985 ilHistory::_copyEntriesForObject($this->getId(), $a_new_obj->getId()); 986 987 // Copy learning progress settings 988 include_once('Services/Tracking/classes/class.ilLPObjSettings.php'); 989 $obj_settings = new ilLPObjSettings($this->getId()); 990 $obj_settings->cloneSettings($a_new_obj->getId()); 991 unset($obj_settings); 992 993 // add news notification 994 $a_new_obj->addNewsNotification("file_created"); 995 996 return $a_new_obj; 997 } 998 999 1000 protected function beforeDelete() 1001 { 1002 global $DIC; 1003 $ilDB = $DIC['ilDB']; 1004 1005 // check, if file is used somewhere 1006 $usages = $this->getUsages(); 1007 if (count($usages) == 0) { 1008 return true; 1009 } 1010 1011 return false; 1012 } 1013 1014 1015 protected function doDelete() 1016 { 1017 global $DIC; 1018 $ilDB = $DIC['ilDB']; 1019 1020 // delete file data entry 1021 $q = "DELETE FROM file_data WHERE file_id = " . $ilDB->quote($this->getId(), 'integer'); 1022 $this->ilias->db->query($q); 1023 1024 // delete history entries 1025 require_once("./Services/History/classes/class.ilHistory.php"); 1026 ilHistory::_removeEntriesForObject($this->getId()); 1027 1028 self::handleQuotaUpdate($this); 1029 1030 // delete entire directory and its content 1031 if (@is_dir($this->getDirectory())) { 1032 ilUtil::delDir($this->getDirectory()); 1033 } 1034 1035 // delete meta data 1036 if ($this->getMode() != self::MODE_FILELIST) { 1037 $this->deleteMetaData(); 1038 } 1039 1040 // delete preview 1041 $this->deletePreview(); 1042 } 1043 1044 1045 /** 1046 * export files of object to target directory 1047 * note: target directory must be the export target directory, 1048 * "/objects/il_<inst>_file_<file_id>/..." will be appended to this directory 1049 * 1050 * @param string $a_target_dir target directory 1051 */ 1052 public function export($a_target_dir) 1053 { 1054 $subdir = "il_" . IL_INST_ID . "_file_" . $this->getId(); 1055 ilUtil::makeDir($a_target_dir . "/objects/" . $subdir); 1056 1057 $filedir = $this->getDirectory($this->getVersion()); 1058 1059 if (@!is_dir($filedir)) { 1060 $filedir = $this->getDirectory(); 1061 } 1062 1063 ilUtil::rCopy($filedir, $a_target_dir . "/objects/" . $subdir); 1064 } 1065 1066 1067 /** 1068 * static delete all usages of 1069 */ 1070 public static function _deleteAllUsages($a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-") 1071 { 1072 global $DIC; 1073 $ilDB = $DIC['ilDB']; 1074 1075 $and_hist = ($a_usage_hist_nr !== false) ? " AND usage_hist_nr = " 1076 . $ilDB->quote($a_usage_hist_nr, "integer") : ""; 1077 1078 $file_ids = array(); 1079 $set = $ilDB->query("SELECT id FROM file_usage" . " WHERE usage_type = " 1080 . $ilDB->quote($a_type, "text") . " AND usage_id= " 1081 . $ilDB->quote($a_id, "integer") . " AND usage_lang= " 1082 . $ilDB->quote($a_usage_lang, "text") . $and_hist); 1083 while ($row = $ilDB->fetchAssoc($set)) { 1084 $file_ids[] = $row["id"]; 1085 } 1086 1087 $ilDB->manipulate("DELETE FROM file_usage WHERE usage_type = " 1088 . $ilDB->quote($a_type, "text") . " AND usage_id = " 1089 . $ilDB->quote((int) $a_id, "integer") . " AND usage_lang= " 1090 . $ilDB->quote($a_usage_lang, "text") . " AND usage_hist_nr = " 1091 . $ilDB->quote((int) $a_usage_hist_nr, "integer")); 1092 1093 foreach ($file_ids as $file_id) { 1094 self::handleQuotaUpdate(new self($file_id, false)); 1095 } 1096 } 1097 1098 1099 /** 1100 * save usage 1101 */ 1102 public static function _saveUsage($a_file_id, $a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-") 1103 { 1104 global $DIC; 1105 $ilDB = $DIC['ilDB']; 1106 1107 // check if file really exists 1108 if (ilObject::_lookupType($a_file_id) != "file") { 1109 return; 1110 } 1111 // #15143 1112 $ilDB->replace("file_usage", array( 1113 "id" => array("integer", (int) $a_file_id), 1114 "usage_type" => array("text", (string) $a_type), 1115 "usage_id" => array("integer", (int) $a_id), 1116 "usage_hist_nr" => array("integer", (int) $a_usage_hist_nr), 1117 "usage_lang" => array("text", $a_usage_lang), 1118 ), array()); 1119 1120 self::handleQuotaUpdate(new self($a_file_id, false)); 1121 } 1122 1123 1124 /** 1125 * get all usages of file object 1126 */ 1127 public function getUsages() 1128 { 1129 global $DIC; 1130 $ilDB = $DIC['ilDB']; 1131 1132 // get usages in learning modules 1133 $q = "SELECT * FROM file_usage WHERE id = " . $ilDB->quote($this->getId(), "integer"); 1134 $us_set = $ilDB->query($q); 1135 $ret = array(); 1136 while ($us_rec = $ilDB->fetchAssoc($us_set)) { 1137 $ret[] = array( 1138 "type" => $us_rec["usage_type"], 1139 "id" => $us_rec["usage_id"], 1140 "lang" => $us_rec["usage_lang"], 1141 "hist_nr" => $us_rec["usage_hist_nr"], 1142 ); 1143 } 1144 1145 return $ret; 1146 } 1147 1148 1149 /** 1150 * get all files of an object 1151 * 1152 * @param string $a_type object type (e.g. "lm:pg") 1153 * @param int $a_id object id 1154 * 1155 * @return array array of file ids 1156 */ 1157 public static function _getFilesOfObject($a_type, $a_id, $a_usage_hist_nr = 0, $a_usage_lang = "-") 1158 { 1159 global $DIC; 1160 $ilDB = $DIC['ilDB']; 1161 1162 $lstr = ""; 1163 if ($a_usage_lang != "") { 1164 $lstr = "usage_lang = " . $ilDB->quote((string) $a_usage_lang, "text") . " AND "; 1165 } 1166 1167 // get usages in learning modules 1168 $q = "SELECT * FROM file_usage WHERE " . "usage_id = " . $ilDB->quote((int) $a_id, "integer") 1169 . " AND " . "usage_type = " . $ilDB->quote((string) $a_type, "text") . " AND " . $lstr 1170 . "usage_hist_nr = " . $ilDB->quote((int) $a_usage_hist_nr, "integer"); 1171 $file_set = $ilDB->query($q); 1172 $ret = array(); 1173 while ($file_rec = $ilDB->fetchAssoc($file_set)) { 1174 $ret[$file_rec["id"]] = $file_rec["id"]; 1175 } 1176 1177 return $ret; 1178 } 1179 1180 1181 // TODO: What is this function good for?? 1182 public function getXMLZip() 1183 { 1184 global $DIC; 1185 $ilias = $DIC['ilias']; 1186 1187 $zip = PATH_TO_ZIP; 1188 1189 exec($zip . ' ' . ilUtil::escapeShellArg($this->getDirectory() . '/' . $this->getFileName()) 1190 . " " . ilUtil::escapeShellArg($this->getDirectory() . '/' . '1.zip')); 1191 1192 return $this->getDirectory() . '/1.zip'; 1193 } 1194 1195 1196 public function addNewsNotification($a_lang_var) 1197 { 1198 // BEGIN WebDAV Suppress news notification for hidden files 1199 if ($this->isHidden()) { 1200 return; 1201 } 1202 // END WebDAV Suppress news notification for hidden files 1203 1204 global $DIC; 1205 $ilUser = $DIC['ilUser']; 1206 1207 // Add Notification to news 1208 include_once("./Services/News/classes/class.ilNewsItem.php"); 1209 include_once("./Modules/File/classes/class.ilObjFileAccess.php"); 1210 $news_item = new ilNewsItem(); 1211 $news_item->setContext($this->getId(), $this->getType()); 1212 $news_item->setPriority(NEWS_NOTICE); 1213 $news_item->setTitle($a_lang_var); 1214 $news_item->setContentIsLangVar(true); 1215 if ($this->getDescription() != "") { 1216 $news_item->setContent("<p>" . $this->getDescription() . "</p>"); 1217 } 1218 $news_item->setUserId($ilUser->getId()); 1219 $news_item->setVisibility(NEWS_USERS); 1220 $news_item->create(); 1221 } 1222 1223 1224 /** 1225 * init file storage object 1226 * 1227 * @access public 1228 * 1229 */ 1230 public function initFileStorage() 1231 { 1232 $this->file_storage = new ilFSStorageFile($this->getId()); 1233 1234 return true; 1235 } 1236 1237 1238 /** 1239 * storeUnzipedFile 1240 * 1241 * Stores Files unzipped from uploaded archive in filesystem 1242 * 1243 * @param string $a_upload_file 1244 * @param string $a_filename 1245 */ 1246 1247 public function storeUnzipedFile($a_upload_file, $a_filename) 1248 { 1249 $this->setVersion($this->getVersion() + 1); 1250 1251 if (@!is_dir($this->getDirectory($this->getVersion()))) { 1252 ilUtil::makeDir($this->getDirectory($this->getVersion())); 1253 } 1254 1255 $file = $this->getDirectory($this->getVersion()) . "/" . $a_filename; 1256 1257 $file = ilFileUtils::getValidFilename($file); 1258 1259 ilFileUtils::rename($a_upload_file, $file); 1260 1261 // create preview 1262 $this->createPreview(); 1263 } 1264 1265 1266 /** 1267 * @param $obj_id 1268 * @param null $a_version 1269 * 1270 * @return bool|string 1271 * @throws \ILIAS\Filesystem\Exception\DirectoryNotFoundException 1272 */ 1273 public static function _lookupAbsolutePath($obj_id, $a_version = null) 1274 { 1275 $file_object = new self($obj_id, false); 1276 $s = new FilePathSanitizer($file_object); 1277 $s->sanitizeIfNeeded(); 1278 1279 return $file_object->getFile($a_version); 1280 } 1281 1282 1283 /** 1284 * Check if the file extension does still exist after an update of the title 1285 * 1286 * @return 1287 */ 1288 public function checkFileExtension($new_filename, $new_title) 1289 { 1290 include_once './Modules/File/classes/class.ilObjFileAccess.php'; 1291 $fileExtension = ilObjFileAccess::_getFileExtension($new_filename); 1292 $titleExtension = ilObjFileAccess::_getFileExtension($new_title); 1293 if ($titleExtension != $fileExtension && strlen($fileExtension) > 0) { 1294 // remove old extension 1295 $pi = pathinfo($this->getFileName()); 1296 $suffix = $pi["extension"]; 1297 if ($suffix != "") { 1298 if (substr($new_title, strlen($new_title) - strlen($suffix) - 1) == "." . $suffix) { 1299 $new_title = substr($new_title, 0, strlen($new_title) - strlen($suffix) - 1); 1300 } 1301 } 1302 $new_title .= '.' . $fileExtension; 1303 } 1304 1305 return $new_title; 1306 } 1307 1308 1309 /** 1310 * Gets the file versions for this object. 1311 * 1312 * @param array $version_ids The file versions to get. If not specified all versions are 1313 * returned. 1314 * 1315 * @return array The file versions. 1316 * 1317 * Example: array ( 1318 * 'date' => '2019-07-25 11:19:51', 1319 * 'user_id' => '6', 1320 * 'obj_id' => '287', 1321 * 'obj_type' => 'file', 1322 * 'action' => 'create', 1323 * 'info_params' => 'chicken_outlined.pdf,1,1', 1324 * 'user_comment' => '', 1325 * 'hist_entry_id' => '3', 1326 * 'title' => NULL, 1327 * ) 1328 */ 1329 public function getVersions($version_ids = null) : array 1330 { 1331 $versions = (array) ilHistory::_getEntriesForObject($this->getId(), $this->getType()); 1332 1333 if ($version_ids != null && count($version_ids) > 0) { 1334 foreach ($versions as $index => $version) { 1335 if (!in_array($version["hist_entry_id"], $version_ids, true)) { 1336 unset($versions[$index]); 1337 } 1338 } 1339 } 1340 1341 // add custom entries 1342 foreach ($versions as $index => $version) { 1343 $params = $this->parseInfoParams($version); 1344 $versions[$index] = array_merge($version, $params); 1345 } 1346 1347 // sort by version number (hist_entry_id will do for that) 1348 usort($versions, array($this, "compareVersions")); 1349 1350 return $versions; 1351 } 1352 1353 1354 /** 1355 * Gets a specific file version. 1356 * 1357 * @param int $version_id The version id to get. 1358 * 1359 * @return array The specific version or false if the version was not found. 1360 */ 1361 public function getSpecificVersion($version_id) 1362 { 1363 include_once("./Services/History/classes/class.ilHistory.php"); 1364 $version = ilHistory::_getEntryByHistoryID($version_id); 1365 if ($version === false) { 1366 return false; 1367 } 1368 1369 // ilHistory returns different keys in _getEntryByHistoryID and _getEntriesForObject 1370 // so this makes it the same 1371 $version["hist_entry_id"] = $version["id"]; 1372 $version["user_id"] = $version["usr_id"]; 1373 $version["date"] = $version["hdate"]; 1374 unset($version["id"], $version["usr_id"], $version["hdate"]); 1375 1376 // parse params 1377 $params = $this->parseInfoParams($version); 1378 1379 return array_merge($version, $params); 1380 } 1381 1382 1383 /** 1384 * Makes the specified version the current one and returns theSummary of rollbackVersion 1385 * 1386 * @param int $version_id The id of the version to make the current one. 1387 * 1388 * @return array The new actual version. 1389 */ 1390 public function rollback($version_id) 1391 { 1392 global $DIC; 1393 $ilDB = $DIC['ilDB']; 1394 $ilUser = $DIC['ilUser']; 1395 1396 $source = $this->getSpecificVersion($version_id); 1397 if ($source === false) { 1398 $this->ilErr->raiseError($this->lng->txt("obj_not_found"), $this->ilErr->MESSAGE); 1399 } 1400 1401 // get the new version number 1402 $new_version_nr = $this->getMaxVersion() + 1; 1403 $this->setMaxVersion($new_version_nr); 1404 1405 // copy file 1406 $source_path = $this->getDirectory($source["version"]) . "/" . $source["filename"]; 1407 $dest_dir = $this->getDirectory($new_version_nr); 1408 if (@!is_dir($dest_dir)) { 1409 ilUtil::makeDir($dest_dir); 1410 } 1411 1412 copy($source_path, $dest_dir . "/" . $source["filename"]); 1413 1414 // create new history entry based on the old one 1415 include_once("./Services/History/classes/class.ilHistory.php"); 1416 // bugfix mantis 26236: added rollback info to version instead of max_version to ensure compatibility with older ilias versions 1417 ilHistory::_createEntry($this->getId(), "rollback", $source["filename"] . "," 1418 . $new_version_nr . "|" 1419 . $source["version"] . "|" 1420 . $ilUser->getId() . "," 1421 . $this->getMaxVersion()); 1422 1423 // get id of newest entry 1424 $entries = ilHistory::_getEntriesForObject($this->getId()); 1425 $newest_entry_id = 0; 1426 foreach ($entries as $entry) { 1427 if ($entry["action"] == "rollback") { 1428 $newest_entry_id = $entry["hist_entry_id"]; 1429 } 1430 } 1431 $new_version = $this->getSpecificVersion($newest_entry_id); 1432 $new_version['version'] = $new_version_nr; 1433 $new_version['max_version'] = $new_version_nr; 1434 1435 // change user back to the original uploader 1436 ilHistory::_changeUserId($new_version["hist_entry_id"], $source["user_id"]); 1437 1438 // update this file with the new version 1439 $this->updateWithVersion($new_version); 1440 1441 $this->addNewsNotification("file_updated"); 1442 1443 return $new_version; 1444 } 1445 1446 1447 /** 1448 * Updates the file object with the specified file version. 1449 * 1450 * @param array $version The version to update the file object with. 1451 */ 1452 protected function updateWithVersion($version) 1453 { 1454 // update title (checkFileExtension must be called before setFileName!) 1455 $this->setTitle($this->checkFileExtension($version["filename"], $this->getTitle())); 1456 1457 $this->setVersion($version["version"]); 1458 $this->setMaxVersion($version["max_version"]); 1459 $this->setFileName($version["filename"]); 1460 1461 // evaluate mime type (reset file type before) 1462 $this->setFileType(""); 1463 $this->setFileType($this->guessFileType($version["filename"])); 1464 1465 // set filesize 1466 $this->determineFileSize(); 1467 1468 $this->update(); 1469 1470 // refresh preview 1471 $this->createPreview(true); 1472 } 1473 1474 1475 /** 1476 * Compares two file versions. 1477 * 1478 * @param array $v1 First file version to compare. 1479 * @param array $v2 Second file version to compare. 1480 * 1481 * @return int Returns an integer less than, equal to, or greater than zero if the first 1482 * argument is considered to be respectively less than, equal to, or greater than 1483 * the second. 1484 */ 1485 public function compareVersions($v1, $v2) 1486 { 1487 // v2 - v1 because version should be descending 1488 return (int) $v2["version"] - (int) $v1["version"]; 1489 } 1490 1491 1492 /** 1493 * Parses the info parameters ("info_params") of the specified history entry. 1494 * 1495 * @param array $entry The history entry. 1496 * 1497 * @return array Returns an array containing the "filename" and "version" contained within the 1498 * "info_params". 1499 */ 1500 private function parseInfoParams($entry) 1501 { 1502 $data = explode(",", $entry["info_params"]); 1503 1504 // bugfix: first created file had no version number 1505 // this is a workaround for all files created before the bug was fixed 1506 if (empty($data[1])) { 1507 $data[1] = "1"; 1508 } 1509 1510 if (empty($data[2])) { 1511 $data[2] = "1"; 1512 } 1513 1514// BEGIN bugfix #27391 1515 if (sizeof($data) > 3) 1516 { 1517 $last = sizeof($data) - 1; 1518 for ($n = 1; $n < $last - 1; $n++) 1519 { 1520 $data[0] .= "," . $data[$n]; 1521 } 1522 $data[1] = $data[$last - 1]; 1523 $data[2] = $data[$last]; 1524 } 1525// END bugfix #27391 1526 1527 $result = array( 1528 "filename" => $data[0], 1529 "version" => $data[1], 1530 "max_version" => $data[2], 1531 "rollback_version" => "", 1532 "rollback_user_id" => "", 1533 ); 1534 1535 // if rollback, the version contains the rollback version as well 1536 // bugfix mantis 26236: rollback info is read from version to ensure compatibility with older ilias versions 1537 if ($entry["action"] == "rollback") { 1538 $tokens = explode("|", $result["version"]); 1539 if (count($tokens) > 1) { 1540 $result["version"] = $tokens[0]; 1541 $result["rollback_version"] = $tokens[1]; 1542 1543 if (count($tokens) > 2) { 1544 $result["rollback_user_id"] = $tokens[2]; 1545 } 1546 } 1547 } 1548 1549 return $result; 1550 } 1551 1552 1553 protected static function handleQuotaUpdate(ilObjFile $a_file) 1554 { 1555 include_once "Services/MediaObjects/classes/class.ilObjMediaObject.php"; 1556 $mob = new ilObjMediaObject(); 1557 1558 // file itself could be workspace item 1559 $parent_obj_ids = array($a_file->getId()); 1560 1561 foreach ($a_file->getUsages() as $item) { 1562 $parent_obj_id = $mob->getParentObjectIdForUsage($item); 1563 if ($parent_obj_id 1564 && !in_array($parent_obj_id, $parent_obj_ids) 1565 ) { 1566 $parent_obj_ids[] = $parent_obj_id; 1567 } 1568 } 1569 1570 include_once "Services/DiskQuota/classes/class.ilDiskQuotaHandler.php"; 1571 ilDiskQuotaHandler::handleUpdatedSourceObject($a_file->getType(), $a_file->getId(), $a_file->getDiskUsage(), $parent_obj_ids); 1572 } 1573 1574 1575 /** 1576 * Creates a preview for the file object. 1577 * 1578 * @param bool $force true, to force the creation of the preview; false, to create the preview 1579 * only if the file is newer. 1580 */ 1581 protected function createPreview($force = false) 1582 { 1583 // only normal files are supported 1584 if ($this->getMode() != self::MODE_OBJECT) { 1585 return; 1586 } 1587 1588 require_once("./Services/Preview/classes/class.ilPreview.php"); 1589 ilPreview::createPreview($this, $force); 1590 } 1591 1592 1593 /** 1594 * Deletes the preview of the file object. 1595 */ 1596 protected function deletePreview() 1597 { 1598 // only normal files are supported 1599 if ($this->getMode() != self::MODE_OBJECT) { 1600 return; 1601 } 1602 1603 require_once("./Services/Preview/classes/class.ilPreview.php"); 1604 ilPreview::deletePreview($this->getId()); 1605 } 1606 1607 1608 /** 1609 * @param bool $a_value 1610 */ 1611 public function setRating($a_value) 1612 { 1613 $this->rating = (bool) $a_value; 1614 } 1615 1616 1617 /** 1618 * @return bool 1619 */ 1620 public function hasRating() 1621 { 1622 return $this->rating; 1623 } 1624 1625 1626 /** 1627 * @return int 1628 */ 1629 public function getPageCount() 1630 { 1631 return $this->page_count; 1632 } 1633 1634 1635 /** 1636 * @param int $page_count 1637 */ 1638 public function setPageCount($page_count) 1639 { 1640 $this->page_count = $page_count; 1641 } 1642 1643 1644 /** 1645 * @param int $file_id (part of bugfix mantis 26131) 1646 * 1647 * @return array 1648 */ 1649 private function getArrayForDatabase($file_id = 0) 1650 { 1651 if ($file_id == 0) { 1652 $file_id = $this->getId(); 1653 } 1654 return [ 1655 'file_id' => ['integer', $file_id], 1656 'file_name' => ['text', $this->getFileName()], 1657 'file_type' => ['text', $this->getFileType()], 1658 'file_size' => ['integer', (int) $this->getFileSize()], 1659 'version' => ['integer', (int) $this->getVersion()], 1660 'max_version' => ['integer', (int) $this->getMaxVersion()], 1661 'f_mode' => ['text', $this->getMode()], 1662 'page_count' => ['text', $this->getPageCount()], 1663 'rating' => ['integer', $this->hasRating()], 1664 ]; 1665 } 1666} 1667