[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 18 /** 19 * Definition of a class stored_file. 20 * 21 * @package core_files 22 * @copyright 2008 Petr Skoda {@link http://skodak.org} 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 defined('MOODLE_INTERNAL') || die(); 27 28 require_once($CFG->dirroot . '/lib/filestorage/file_progress.php'); 29 30 /** 31 * Class representing local files stored in a sha1 file pool. 32 * 33 * Since Moodle 2.0 file contents are stored in sha1 pool and 34 * all other file information is stored in new "files" database table. 35 * 36 * @package core_files 37 * @category files 38 * @copyright 2008 Petr Skoda {@link http://skodak.org} 39 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 40 * @since Moodle 2.0 41 */ 42 class stored_file { 43 /** @var file_storage file storage pool instance */ 44 private $fs; 45 /** @var stdClass record from the files table left join files_reference table */ 46 private $file_record; 47 /** @var string location of content files */ 48 private $filedir; 49 /** @var repository repository plugin instance */ 50 private $repository; 51 52 /** 53 * @var int Indicates a file handle of the type returned by fopen. 54 */ 55 const FILE_HANDLE_FOPEN = 0; 56 57 /** 58 * @var int Indicates a file handle of the type returned by gzopen. 59 */ 60 const FILE_HANDLE_GZOPEN = 1; 61 62 63 /** 64 * Constructor, this constructor should be called ONLY from the file_storage class! 65 * 66 * @param file_storage $fs file storage instance 67 * @param stdClass $file_record description of file 68 * @param string $filedir location of file directory with sh1 named content files 69 */ 70 public function __construct(file_storage $fs, stdClass $file_record, $filedir) { 71 global $DB, $CFG; 72 $this->fs = $fs; 73 $this->file_record = clone($file_record); // prevent modifications 74 $this->filedir = $filedir; // keep secret, do not expose! 75 76 if (!empty($file_record->repositoryid)) { 77 require_once("$CFG->dirroot/repository/lib.php"); 78 $this->repository = repository::get_repository_by_id($file_record->repositoryid, SYSCONTEXTID); 79 if ($this->repository->supported_returntypes() & FILE_REFERENCE != FILE_REFERENCE) { 80 // Repository cannot do file reference. 81 throw new moodle_exception('error'); 82 } 83 } else { 84 $this->repository = null; 85 } 86 // make sure all reference fields exist in file_record even when it is not a reference 87 foreach (array('referencelastsync', 'referencefileid', 'reference', 'repositoryid') as $key) { 88 if (empty($this->file_record->$key)) { 89 $this->file_record->$key = null; 90 } 91 } 92 } 93 94 /** 95 * Whether or not this is a external resource 96 * 97 * @return bool 98 */ 99 public function is_external_file() { 100 return !empty($this->repository); 101 } 102 103 /** 104 * Update some file record fields 105 * NOTE: Must remain protected 106 * 107 * @param stdClass $dataobject 108 */ 109 protected function update($dataobject) { 110 global $DB; 111 $updatereferencesneeded = false; 112 $keys = array_keys((array)$this->file_record); 113 foreach ($dataobject as $field => $value) { 114 if (in_array($field, $keys)) { 115 if ($field == 'contextid' and (!is_number($value) or $value < 1)) { 116 throw new file_exception('storedfileproblem', 'Invalid contextid'); 117 } 118 119 if ($field == 'component') { 120 $value = clean_param($value, PARAM_COMPONENT); 121 if (empty($value)) { 122 throw new file_exception('storedfileproblem', 'Invalid component'); 123 } 124 } 125 126 if ($field == 'filearea') { 127 $value = clean_param($value, PARAM_AREA); 128 if (empty($value)) { 129 throw new file_exception('storedfileproblem', 'Invalid filearea'); 130 } 131 } 132 133 if ($field == 'itemid' and (!is_number($value) or $value < 0)) { 134 throw new file_exception('storedfileproblem', 'Invalid itemid'); 135 } 136 137 138 if ($field == 'filepath') { 139 $value = clean_param($value, PARAM_PATH); 140 if (strpos($value, '/') !== 0 or strrpos($value, '/') !== strlen($value)-1) { 141 // path must start and end with '/' 142 throw new file_exception('storedfileproblem', 'Invalid file path'); 143 } 144 } 145 146 if ($field == 'filename') { 147 // folder has filename == '.', so we pass this 148 if ($value != '.') { 149 $value = clean_param($value, PARAM_FILE); 150 } 151 if ($value === '') { 152 throw new file_exception('storedfileproblem', 'Invalid file name'); 153 } 154 } 155 156 if ($field === 'timecreated' or $field === 'timemodified') { 157 if (!is_number($value)) { 158 throw new file_exception('storedfileproblem', 'Invalid timestamp'); 159 } 160 if ($value < 0) { 161 $value = 0; 162 } 163 } 164 165 if ($field === 'referencefileid') { 166 if (!is_null($value) and !is_number($value)) { 167 throw new file_exception('storedfileproblem', 'Invalid reference info'); 168 } 169 } 170 171 if (($field == 'contenthash' || $field == 'filesize') && $this->file_record->$field != $value) { 172 $updatereferencesneeded = true; 173 } 174 175 // adding the field 176 $this->file_record->$field = $value; 177 } else { 178 throw new coding_exception("Invalid field name, $field doesn't exist in file record"); 179 } 180 } 181 // Validate mimetype field 182 // we don't use {@link stored_file::get_content_file_location()} here becaues it will try to update file_record 183 $pathname = $this->get_pathname_by_contenthash(); 184 // try to recover the content from trash 185 if (!is_readable($pathname)) { 186 if (!$this->fs->try_content_recovery($this) or !is_readable($pathname)) { 187 throw new file_exception('storedfilecannotread', '', $pathname); 188 } 189 } 190 $mimetype = $this->fs->mimetype($pathname, $this->file_record->filename); 191 $this->file_record->mimetype = $mimetype; 192 193 $DB->update_record('files', $this->file_record); 194 if ($updatereferencesneeded) { 195 // Either filesize or contenthash of this file have changed. Update all files that reference to it. 196 $this->fs->update_references_to_storedfile($this); 197 } 198 } 199 200 /** 201 * Rename filename 202 * 203 * @param string $filepath file path 204 * @param string $filename file name 205 */ 206 public function rename($filepath, $filename) { 207 if ($this->fs->file_exists($this->get_contextid(), $this->get_component(), $this->get_filearea(), $this->get_itemid(), $filepath, $filename)) { 208 $a = new stdClass(); 209 $a->contextid = $this->get_contextid(); 210 $a->component = $this->get_component(); 211 $a->filearea = $this->get_filearea(); 212 $a->itemid = $this->get_itemid(); 213 $a->filepath = $filepath; 214 $a->filename = $filename; 215 throw new file_exception('storedfilenotcreated', $a, 'file exists, cannot rename'); 216 } 217 $filerecord = new stdClass; 218 $filerecord->filepath = $filepath; 219 $filerecord->filename = $filename; 220 // populate the pathname hash 221 $filerecord->pathnamehash = $this->fs->get_pathname_hash($this->file_record->contextid, $this->file_record->component, $this->file_record->filearea, $this->file_record->itemid, $filepath, $filename); 222 $this->update($filerecord); 223 } 224 225 /** 226 * Replace the content by providing another stored_file instance 227 * 228 * @deprecated since 2.6 229 * @see stored_file::replace_file_with() 230 * @param stored_file $storedfile 231 */ 232 public function replace_content_with(stored_file $storedfile) { 233 debugging('Function stored_file::replace_content_with() is deprecated. Please use stored_file::replace_file_with()', DEBUG_DEVELOPER); 234 $filerecord = new stdClass; 235 $contenthash = $storedfile->get_contenthash(); 236 if ($this->fs->content_exists($contenthash)) { 237 $filerecord->contenthash = $contenthash; 238 } else { 239 throw new file_exception('storedfileproblem', 'Invalid contenthash, content must be already in filepool', $contenthash); 240 } 241 $filerecord->filesize = $storedfile->get_filesize(); 242 $this->update($filerecord); 243 } 244 245 /** 246 * Replaces the fields that might have changed when file was overriden in filepicker: 247 * reference, contenthash, filesize, userid 248 * 249 * Note that field 'source' must be updated separately because 250 * it has different format for draft and non-draft areas and 251 * this function will usually be used to replace non-draft area 252 * file with draft area file. 253 * 254 * @param stored_file $newfile 255 * @throws coding_exception 256 */ 257 public function replace_file_with(stored_file $newfile) { 258 if ($newfile->get_referencefileid() && 259 $this->fs->get_references_count_by_storedfile($this)) { 260 // The new file is a reference. 261 // The current file has other local files referencing to it. 262 // Double reference is not allowed. 263 throw new moodle_exception('errordoublereference', 'repository'); 264 } 265 266 $filerecord = new stdClass; 267 $contenthash = $newfile->get_contenthash(); 268 if ($this->fs->content_exists($contenthash)) { 269 $filerecord->contenthash = $contenthash; 270 } else { 271 throw new file_exception('storedfileproblem', 'Invalid contenthash, content must be already in filepool', $contenthash); 272 } 273 $filerecord->filesize = $newfile->get_filesize(); 274 $filerecord->referencefileid = $newfile->get_referencefileid(); 275 $filerecord->userid = $newfile->get_userid(); 276 $this->update($filerecord); 277 } 278 279 /** 280 * Unlink the stored file from the referenced file 281 * 282 * This methods destroys the link to the record in files_reference table. This effectively 283 * turns the stored file from being an alias to a plain copy. However, the caller has 284 * to make sure that the actual file's content has beed synced prior to calling this method. 285 */ 286 public function delete_reference() { 287 global $DB; 288 289 if (!$this->is_external_file()) { 290 throw new coding_exception('An attempt to unlink a non-reference file.'); 291 } 292 293 $transaction = $DB->start_delegated_transaction(); 294 295 // Are we the only one referring to the original file? If so, delete the 296 // referenced file record. Note we do not use file_storage::search_references_count() 297 // here because we want to count draft files too and we are at a bit lower access level here. 298 $countlinks = $DB->count_records('files', 299 array('referencefileid' => $this->file_record->referencefileid)); 300 if ($countlinks == 1) { 301 $DB->delete_records('files_reference', array('id' => $this->file_record->referencefileid)); 302 } 303 304 // Update the underlying record in the database. 305 $update = new stdClass(); 306 $update->referencefileid = null; 307 $this->update($update); 308 309 $transaction->allow_commit(); 310 311 // Update our properties and the record in the memory. 312 $this->repository = null; 313 $this->file_record->repositoryid = null; 314 $this->file_record->reference = null; 315 $this->file_record->referencefileid = null; 316 $this->file_record->referencelastsync = null; 317 } 318 319 /** 320 * Is this a directory? 321 * 322 * Directories are only emulated, internally they are stored as empty 323 * files with a "." instead of name - this means empty directory contains 324 * exactly one empty file with name dot. 325 * 326 * @return bool true means directory, false means file 327 */ 328 public function is_directory() { 329 return ($this->file_record->filename === '.'); 330 } 331 332 /** 333 * Delete file from files table. 334 * 335 * The content of files stored in sha1 pool is reclaimed 336 * later - the occupied disk space is reclaimed much later. 337 * 338 * @return bool always true or exception if error occurred 339 */ 340 public function delete() { 341 global $DB; 342 343 if ($this->is_directory()) { 344 // Directories can not be referenced, just delete the record. 345 $DB->delete_records('files', array('id'=>$this->file_record->id)); 346 347 } else { 348 $transaction = $DB->start_delegated_transaction(); 349 350 // If there are other files referring to this file, convert them to copies. 351 if ($files = $this->fs->get_references_by_storedfile($this)) { 352 foreach ($files as $file) { 353 $this->fs->import_external_file($file); 354 } 355 } 356 357 // If this file is a reference (alias) to another file, unlink it first. 358 if ($this->is_external_file()) { 359 $this->delete_reference(); 360 } 361 362 // Now delete the file record. 363 $DB->delete_records('files', array('id'=>$this->file_record->id)); 364 365 $transaction->allow_commit(); 366 } 367 368 // Move pool file to trash if content not needed any more. 369 $this->fs->deleted_file_cleanup($this->file_record->contenthash); 370 return true; // BC only 371 } 372 373 /** 374 * Get file pathname by contenthash 375 * 376 * NOTE, this function is not calling sync_external_file, it assume the contenthash is current 377 * Protected - developers must not gain direct access to this function. 378 * 379 * @return string full path to pool file with file content 380 */ 381 protected function get_pathname_by_contenthash() { 382 // Detect is local file or not. 383 $contenthash = $this->file_record->contenthash; 384 $l1 = $contenthash[0].$contenthash[1]; 385 $l2 = $contenthash[2].$contenthash[3]; 386 return "$this->filedir/$l1/$l2/$contenthash"; 387 } 388 389 /** 390 * Get file pathname by given contenthash, this method will try to sync files 391 * 392 * Protected - developers must not gain direct access to this function. 393 * 394 * NOTE: do not make this public, we must not modify or delete the pool files directly! ;-) 395 * 396 * @return string full path to pool file with file content 397 **/ 398 protected function get_content_file_location() { 399 $this->sync_external_file(); 400 return $this->get_pathname_by_contenthash(); 401 } 402 403 /** 404 * adds this file path to a curl request (POST only) 405 * 406 * @param curl $curlrequest the curl request object 407 * @param string $key what key to use in the POST request 408 * @return void 409 */ 410 public function add_to_curl_request(&$curlrequest, $key) { 411 if (function_exists('curl_file_create')) { 412 // As of PHP 5.5, the usage of the @filename API for file uploading is deprecated. 413 $value = curl_file_create($this->get_content_file_location()); 414 } else { 415 $value = '@' . $this->get_content_file_location(); 416 } 417 $curlrequest->_tmp_file_post_params[$key] = $value; 418 } 419 420 /** 421 * Returns file handle - read only mode, no writing allowed into pool files! 422 * 423 * When you want to modify a file, create a new file and delete the old one. 424 * 425 * @param int $type Type of file handle (FILE_HANDLE_xx constant) 426 * @return resource file handle 427 */ 428 public function get_content_file_handle($type = self::FILE_HANDLE_FOPEN) { 429 $path = $this->get_content_file_location(); 430 if (!is_readable($path)) { 431 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) { 432 throw new file_exception('storedfilecannotread', '', $path); 433 } 434 } 435 switch ($type) { 436 case self::FILE_HANDLE_FOPEN: 437 // Binary reading. 438 return fopen($path, 'rb'); 439 case self::FILE_HANDLE_GZOPEN: 440 // Binary reading of file in gz format. 441 return gzopen($path, 'rb'); 442 default: 443 throw new coding_exception('Unexpected file handle type'); 444 } 445 } 446 447 /** 448 * Dumps file content to page. 449 */ 450 public function readfile() { 451 $path = $this->get_content_file_location(); 452 if (!is_readable($path)) { 453 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) { 454 throw new file_exception('storedfilecannotread', '', $path); 455 } 456 } 457 readfile_allow_large($path, $this->get_filesize()); 458 } 459 460 /** 461 * Returns file content as string. 462 * 463 * @return string content 464 */ 465 public function get_content() { 466 $path = $this->get_content_file_location(); 467 if (!is_readable($path)) { 468 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) { 469 throw new file_exception('storedfilecannotread', '', $path); 470 } 471 } 472 return file_get_contents($this->get_content_file_location()); 473 } 474 475 /** 476 * Copy content of file to given pathname. 477 * 478 * @param string $pathname real path to the new file 479 * @return bool success 480 */ 481 public function copy_content_to($pathname) { 482 $path = $this->get_content_file_location(); 483 if (!is_readable($path)) { 484 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) { 485 throw new file_exception('storedfilecannotread', '', $path); 486 } 487 } 488 return copy($path, $pathname); 489 } 490 491 /** 492 * Copy content of file to temporary folder and returns file path 493 * 494 * @param string $dir name of the temporary directory 495 * @param string $fileprefix prefix of temporary file. 496 * @return string|bool path of temporary file or false. 497 */ 498 public function copy_content_to_temp($dir = 'files', $fileprefix = 'tempup_') { 499 $tempfile = false; 500 if (!$dir = make_temp_directory($dir)) { 501 return false; 502 } 503 if (!$tempfile = tempnam($dir, $fileprefix)) { 504 return false; 505 } 506 if (!$this->copy_content_to($tempfile)) { 507 // something went wrong 508 @unlink($tempfile); 509 return false; 510 } 511 return $tempfile; 512 } 513 514 /** 515 * List contents of archive. 516 * 517 * @param file_packer $packer file packer instance 518 * @return array of file infos 519 */ 520 public function list_files(file_packer $packer) { 521 $archivefile = $this->get_content_file_location(); 522 return $packer->list_files($archivefile); 523 } 524 525 /** 526 * Extract file to given file path (real OS filesystem), existing files are overwritten. 527 * 528 * @param file_packer $packer file packer instance 529 * @param string $pathname target directory 530 * @param file_progress $progress Progress indicator callback or null if not required 531 * @return array|bool list of processed files; false if error 532 */ 533 public function extract_to_pathname(file_packer $packer, $pathname, 534 file_progress $progress = null) { 535 $archivefile = $this->get_content_file_location(); 536 return $packer->extract_to_pathname($archivefile, $pathname, null, $progress); 537 } 538 539 /** 540 * Extract file to given file path (real OS filesystem), existing files are overwritten. 541 * 542 * @param file_packer $packer file packer instance 543 * @param int $contextid context ID 544 * @param string $component component 545 * @param string $filearea file area 546 * @param int $itemid item ID 547 * @param string $pathbase path base 548 * @param int $userid user ID 549 * @param file_progress $progress Progress indicator callback or null if not required 550 * @return array|bool list of processed files; false if error 551 */ 552 public function extract_to_storage(file_packer $packer, $contextid, 553 $component, $filearea, $itemid, $pathbase, $userid = null, file_progress $progress = null) { 554 $archivefile = $this->get_content_file_location(); 555 return $packer->extract_to_storage($archivefile, $contextid, 556 $component, $filearea, $itemid, $pathbase, $userid, $progress); 557 } 558 559 /** 560 * Add file/directory into archive. 561 * 562 * @param file_archive $filearch file archive instance 563 * @param string $archivepath pathname in archive 564 * @return bool success 565 */ 566 public function archive_file(file_archive $filearch, $archivepath) { 567 if ($this->is_directory()) { 568 return $filearch->add_directory($archivepath); 569 } else { 570 $path = $this->get_content_file_location(); 571 if (!is_readable($path)) { 572 return false; 573 } 574 return $filearch->add_file_from_pathname($archivepath, $path); 575 } 576 } 577 578 /** 579 * Returns information about image, 580 * information is determined from the file content 581 * 582 * @return mixed array with width, height and mimetype; false if not an image 583 */ 584 public function get_imageinfo() { 585 $path = $this->get_content_file_location(); 586 if (!is_readable($path)) { 587 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) { 588 throw new file_exception('storedfilecannotread', '', $path); 589 } 590 } 591 $mimetype = $this->get_mimetype(); 592 if (!preg_match('|^image/|', $mimetype) || !filesize($path) || !($imageinfo = getimagesize($path))) { 593 return false; 594 } 595 $image = array('width'=>$imageinfo[0], 'height'=>$imageinfo[1], 'mimetype'=>image_type_to_mime_type($imageinfo[2])); 596 if (empty($image['width']) or empty($image['height']) or empty($image['mimetype'])) { 597 // gd can not parse it, sorry 598 return false; 599 } 600 return $image; 601 } 602 603 /** 604 * Verifies the file is a valid web image - gif, png and jpeg only. 605 * 606 * It should be ok to serve this image from server without any other security workarounds. 607 * 608 * @return bool true if file ok 609 */ 610 public function is_valid_image() { 611 $mimetype = $this->get_mimetype(); 612 if (!file_mimetype_in_typegroup($mimetype, 'web_image')) { 613 return false; 614 } 615 if (!$info = $this->get_imageinfo()) { 616 return false; 617 } 618 if ($info['mimetype'] !== $mimetype) { 619 return false; 620 } 621 // ok, GD likes this image 622 return true; 623 } 624 625 /** 626 * Returns parent directory, creates missing parents if needed. 627 * 628 * @return stored_file 629 */ 630 public function get_parent_directory() { 631 if ($this->file_record->filepath === '/' and $this->file_record->filename === '.') { 632 //root dir does not have parent 633 return null; 634 } 635 636 if ($this->file_record->filename !== '.') { 637 return $this->fs->create_directory($this->file_record->contextid, $this->file_record->component, $this->file_record->filearea, $this->file_record->itemid, $this->file_record->filepath); 638 } 639 640 $filepath = $this->file_record->filepath; 641 $filepath = trim($filepath, '/'); 642 $dirs = explode('/', $filepath); 643 array_pop($dirs); 644 $filepath = implode('/', $dirs); 645 $filepath = ($filepath === '') ? '/' : "/$filepath/"; 646 647 return $this->fs->create_directory($this->file_record->contextid, $this->file_record->component, $this->file_record->filearea, $this->file_record->itemid, $filepath); 648 } 649 650 /** 651 * Synchronize file if it is a reference and needs synchronizing 652 * 653 * Updates contenthash and filesize 654 */ 655 public function sync_external_file() { 656 if (!empty($this->repository)) { 657 $this->repository->sync_reference($this); 658 } 659 } 660 661 /** 662 * Returns context id of the file 663 * 664 * @return int context id 665 */ 666 public function get_contextid() { 667 return $this->file_record->contextid; 668 } 669 670 /** 671 * Returns component name - this is the owner of the areas, 672 * nothing else is allowed to read or modify the files directly!! 673 * 674 * @return string 675 */ 676 public function get_component() { 677 return $this->file_record->component; 678 } 679 680 /** 681 * Returns file area name, this divides files of one component into groups with different access control. 682 * All files in one area have the same access control. 683 * 684 * @return string 685 */ 686 public function get_filearea() { 687 return $this->file_record->filearea; 688 } 689 690 /** 691 * Returns returns item id of file. 692 * 693 * @return int 694 */ 695 public function get_itemid() { 696 return $this->file_record->itemid; 697 } 698 699 /** 700 * Returns file path - starts and ends with /, \ are not allowed. 701 * 702 * @return string 703 */ 704 public function get_filepath() { 705 return $this->file_record->filepath; 706 } 707 708 /** 709 * Returns file name or '.' in case of directories. 710 * 711 * @return string 712 */ 713 public function get_filename() { 714 return $this->file_record->filename; 715 } 716 717 /** 718 * Returns id of user who created the file. 719 * 720 * @return int 721 */ 722 public function get_userid() { 723 return $this->file_record->userid; 724 } 725 726 /** 727 * Returns the size of file in bytes. 728 * 729 * @return int bytes 730 */ 731 public function get_filesize() { 732 $this->sync_external_file(); 733 return $this->file_record->filesize; 734 } 735 736 /** 737 * Returns the size of file in bytes. 738 * 739 * @param int $filesize bytes 740 */ 741 public function set_filesize($filesize) { 742 debugging('Function stored_file::set_filesize() is deprecated. Please use stored_file::replace_file_with()', DEBUG_DEVELOPER); 743 $filerecord = new stdClass; 744 $filerecord->filesize = $filesize; 745 $this->update($filerecord); 746 } 747 748 /** 749 * Returns mime type of file. 750 * 751 * @return string 752 */ 753 public function get_mimetype() { 754 return $this->file_record->mimetype; 755 } 756 757 /** 758 * Returns unix timestamp of file creation date. 759 * 760 * @return int 761 */ 762 public function get_timecreated() { 763 return $this->file_record->timecreated; 764 } 765 766 /** 767 * Returns unix timestamp of last file modification. 768 * 769 * @return int 770 */ 771 public function get_timemodified() { 772 $this->sync_external_file(); 773 return $this->file_record->timemodified; 774 } 775 776 /** 777 * set timemodified 778 * 779 * @param int $timemodified 780 */ 781 public function set_timemodified($timemodified) { 782 $filerecord = new stdClass; 783 $filerecord->timemodified = $timemodified; 784 $this->update($filerecord); 785 } 786 787 /** 788 * Returns file status flag. 789 * 790 * @return int 0 means file OK, anything else is a problem and file can not be used 791 */ 792 public function get_status() { 793 return $this->file_record->status; 794 } 795 796 /** 797 * Returns file id. 798 * 799 * @return int 800 */ 801 public function get_id() { 802 return $this->file_record->id; 803 } 804 805 /** 806 * Returns sha1 hash of file content. 807 * 808 * @return string 809 */ 810 public function get_contenthash() { 811 $this->sync_external_file(); 812 return $this->file_record->contenthash; 813 } 814 815 /** 816 * Returns sha1 hash of all file path components sha1("contextid/component/filearea/itemid/dir/dir/filename.ext"). 817 * 818 * @return string 819 */ 820 public function get_pathnamehash() { 821 return $this->file_record->pathnamehash; 822 } 823 824 /** 825 * Returns the license type of the file, it is a short name referred from license table. 826 * 827 * @return string 828 */ 829 public function get_license() { 830 return $this->file_record->license; 831 } 832 833 /** 834 * Set license 835 * 836 * @param string $license license 837 */ 838 public function set_license($license) { 839 $filerecord = new stdClass; 840 $filerecord->license = $license; 841 $this->update($filerecord); 842 } 843 844 /** 845 * Returns the author name of the file. 846 * 847 * @return string 848 */ 849 public function get_author() { 850 return $this->file_record->author; 851 } 852 853 /** 854 * Set author 855 * 856 * @param string $author 857 */ 858 public function set_author($author) { 859 $filerecord = new stdClass; 860 $filerecord->author = $author; 861 $this->update($filerecord); 862 } 863 864 /** 865 * Returns the source of the file, usually it is a url. 866 * 867 * @return string 868 */ 869 public function get_source() { 870 return $this->file_record->source; 871 } 872 873 /** 874 * Set license 875 * 876 * @param string $license license 877 */ 878 public function set_source($source) { 879 $filerecord = new stdClass; 880 $filerecord->source = $source; 881 $this->update($filerecord); 882 } 883 884 885 /** 886 * Returns the sort order of file 887 * 888 * @return int 889 */ 890 public function get_sortorder() { 891 return $this->file_record->sortorder; 892 } 893 894 /** 895 * Set file sort order 896 * 897 * @param int $sortorder 898 * @return int 899 */ 900 public function set_sortorder($sortorder) { 901 $filerecord = new stdClass; 902 $filerecord->sortorder = $sortorder; 903 $this->update($filerecord); 904 } 905 906 /** 907 * Returns repository id 908 * 909 * @return int|null 910 */ 911 public function get_repository_id() { 912 if (!empty($this->repository)) { 913 return $this->repository->id; 914 } else { 915 return null; 916 } 917 } 918 919 /** 920 * get reference file id 921 * @return int 922 */ 923 public function get_referencefileid() { 924 return $this->file_record->referencefileid; 925 } 926 927 /** 928 * Get reference last sync time 929 * @return int 930 */ 931 public function get_referencelastsync() { 932 return $this->file_record->referencelastsync; 933 } 934 935 /** 936 * Get reference life time (in seconds) after which sync is required 937 * 938 * This data is no longer stored in DB or returned by repository. Each 939 * repository should decide by itself when to synchronise the references. 940 * 941 * @deprecated since 2.6 942 * @see repository::sync_reference() 943 * @return int 944 */ 945 public function get_referencelifetime() { 946 debugging('Function stored_file::get_referencelifetime() is deprecated.', DEBUG_DEVELOPER); 947 if ($this->repository) { 948 if (method_exists($this->repository, 'get_reference_file_lifetime')) { 949 return $this->repository->get_reference_file_lifetime($this->get_reference()); 950 } else { 951 return 24 * 60 * 60; 952 } 953 } else { 954 return 0; 955 } 956 } 957 /** 958 * Returns file reference 959 * 960 * @return string 961 */ 962 public function get_reference() { 963 return $this->file_record->reference; 964 } 965 966 /** 967 * Get human readable file reference information 968 * 969 * @return string 970 */ 971 public function get_reference_details() { 972 return $this->repository->get_reference_details($this->get_reference(), $this->get_status()); 973 } 974 975 /** 976 * Called after reference-file has been synchronized with the repository 977 * 978 * We update contenthash, filesize and status in files table if changed 979 * and we always update lastsync in files_reference table 980 * 981 * @param null|string $contenthash if set to null contenthash is not changed 982 * @param int $filesize new size of the file 983 * @param int $status new status of the file (0 means OK, 666 - source missing) 984 */ 985 public function set_synchronized($contenthash, $filesize, $status = 0) { 986 if (!$this->is_external_file()) { 987 return; 988 } 989 $now = time(); 990 if ($contenthash === null) { 991 $contenthash = $this->file_record->contenthash; 992 } 993 if ($contenthash != $this->file_record->contenthash) { 994 $oldcontenthash = $this->file_record->contenthash; 995 } 996 // this will update all entries in {files} that have the same filereference id 997 $this->fs->update_references($this->file_record->referencefileid, $now, null, $contenthash, $filesize, $status); 998 // we don't need to call update() for this object, just set the values of changed fields 999 $this->file_record->contenthash = $contenthash; 1000 $this->file_record->filesize = $filesize; 1001 $this->file_record->status = $status; 1002 $this->file_record->referencelastsync = $now; 1003 if (isset($oldcontenthash)) { 1004 $this->fs->deleted_file_cleanup($oldcontenthash); 1005 } 1006 } 1007 1008 /** 1009 * Sets the error status for a file that could not be synchronised 1010 */ 1011 public function set_missingsource() { 1012 $this->set_synchronized($this->file_record->contenthash, $this->file_record->filesize, 666); 1013 } 1014 1015 /** 1016 * Send file references 1017 * 1018 * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours) 1019 * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only 1020 * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin 1021 * @param array $options additional options affecting the file serving 1022 */ 1023 public function send_file($lifetime, $filter, $forcedownload, $options) { 1024 $this->repository->send_file($this, $lifetime, $filter, $forcedownload, $options); 1025 } 1026 1027 /** 1028 * Imports the contents of an external file into moodle filepool. 1029 * 1030 * @throws moodle_exception if file could not be downloaded or is too big 1031 * @param int $maxbytes throw an exception if file size is bigger than $maxbytes (0 means no limit) 1032 */ 1033 public function import_external_file_contents($maxbytes = 0) { 1034 if ($this->repository) { 1035 $this->repository->import_external_file_contents($this, $maxbytes); 1036 } 1037 } 1038 1039 /** 1040 * Gets a file relative to this file in the repository and sends it to the browser. 1041 * Checks the function repository::supports_relative_file() to make sure it can be used. 1042 * 1043 * @param string $relativepath the relative path to the file we are trying to access 1044 */ 1045 public function send_relative_file($relativepath) { 1046 if ($this->repository && $this->repository->supports_relative_file()) { 1047 $relativepath = clean_param($relativepath, PARAM_PATH); 1048 $this->repository->send_relative_file($this, $relativepath); 1049 } else { 1050 send_file_not_found(); 1051 } 1052 } 1053 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |