[ Index ] |
PHP Cross Reference of Unnamed Project |
[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 * Function stored_file::replace_content_with() is deprecated. Please use stored_file::replace_file_with() 227 * 228 * @deprecated since Moodle 2.6 MDL-42016 - please do not use this function any more. 229 * @see stored_file::replace_file_with() 230 */ 231 public function replace_content_with(stored_file $storedfile) { 232 throw new coding_exception('Function stored_file::replace_content_with() can not be used any more . ' . 233 'Please use stored_file::replace_file_with()'); 234 } 235 236 /** 237 * Replaces the fields that might have changed when file was overriden in filepicker: 238 * reference, contenthash, filesize, userid 239 * 240 * Note that field 'source' must be updated separately because 241 * it has different format for draft and non-draft areas and 242 * this function will usually be used to replace non-draft area 243 * file with draft area file. 244 * 245 * @param stored_file $newfile 246 * @throws coding_exception 247 */ 248 public function replace_file_with(stored_file $newfile) { 249 if ($newfile->get_referencefileid() && 250 $this->fs->get_references_count_by_storedfile($this)) { 251 // The new file is a reference. 252 // The current file has other local files referencing to it. 253 // Double reference is not allowed. 254 throw new moodle_exception('errordoublereference', 'repository'); 255 } 256 257 $filerecord = new stdClass; 258 $contenthash = $newfile->get_contenthash(); 259 if ($this->fs->content_exists($contenthash)) { 260 $filerecord->contenthash = $contenthash; 261 } else { 262 throw new file_exception('storedfileproblem', 'Invalid contenthash, content must be already in filepool', $contenthash); 263 } 264 $filerecord->filesize = $newfile->get_filesize(); 265 $filerecord->referencefileid = $newfile->get_referencefileid(); 266 $filerecord->userid = $newfile->get_userid(); 267 $this->update($filerecord); 268 } 269 270 /** 271 * Unlink the stored file from the referenced file 272 * 273 * This methods destroys the link to the record in files_reference table. This effectively 274 * turns the stored file from being an alias to a plain copy. However, the caller has 275 * to make sure that the actual file's content has beed synced prior to calling this method. 276 */ 277 public function delete_reference() { 278 global $DB; 279 280 if (!$this->is_external_file()) { 281 throw new coding_exception('An attempt to unlink a non-reference file.'); 282 } 283 284 $transaction = $DB->start_delegated_transaction(); 285 286 // Are we the only one referring to the original file? If so, delete the 287 // referenced file record. Note we do not use file_storage::search_references_count() 288 // here because we want to count draft files too and we are at a bit lower access level here. 289 $countlinks = $DB->count_records('files', 290 array('referencefileid' => $this->file_record->referencefileid)); 291 if ($countlinks == 1) { 292 $DB->delete_records('files_reference', array('id' => $this->file_record->referencefileid)); 293 } 294 295 // Update the underlying record in the database. 296 $update = new stdClass(); 297 $update->referencefileid = null; 298 $this->update($update); 299 300 $transaction->allow_commit(); 301 302 // Update our properties and the record in the memory. 303 $this->repository = null; 304 $this->file_record->repositoryid = null; 305 $this->file_record->reference = null; 306 $this->file_record->referencefileid = null; 307 $this->file_record->referencelastsync = null; 308 } 309 310 /** 311 * Is this a directory? 312 * 313 * Directories are only emulated, internally they are stored as empty 314 * files with a "." instead of name - this means empty directory contains 315 * exactly one empty file with name dot. 316 * 317 * @return bool true means directory, false means file 318 */ 319 public function is_directory() { 320 return ($this->file_record->filename === '.'); 321 } 322 323 /** 324 * Delete file from files table. 325 * 326 * The content of files stored in sha1 pool is reclaimed 327 * later - the occupied disk space is reclaimed much later. 328 * 329 * @return bool always true or exception if error occurred 330 */ 331 public function delete() { 332 global $DB; 333 334 if ($this->is_directory()) { 335 // Directories can not be referenced, just delete the record. 336 $DB->delete_records('files', array('id'=>$this->file_record->id)); 337 338 } else { 339 $transaction = $DB->start_delegated_transaction(); 340 341 // If there are other files referring to this file, convert them to copies. 342 if ($files = $this->fs->get_references_by_storedfile($this)) { 343 foreach ($files as $file) { 344 $this->fs->import_external_file($file); 345 } 346 } 347 348 // If this file is a reference (alias) to another file, unlink it first. 349 if ($this->is_external_file()) { 350 $this->delete_reference(); 351 } 352 353 // Now delete the file record. 354 $DB->delete_records('files', array('id'=>$this->file_record->id)); 355 356 $transaction->allow_commit(); 357 } 358 359 // Move pool file to trash if content not needed any more. 360 $this->fs->deleted_file_cleanup($this->file_record->contenthash); 361 return true; // BC only 362 } 363 364 /** 365 * Get file pathname by contenthash 366 * 367 * NOTE, this function is not calling sync_external_file, it assume the contenthash is current 368 * Protected - developers must not gain direct access to this function. 369 * 370 * @return string full path to pool file with file content 371 */ 372 protected function get_pathname_by_contenthash() { 373 // Detect is local file or not. 374 $contenthash = $this->file_record->contenthash; 375 $l1 = $contenthash[0].$contenthash[1]; 376 $l2 = $contenthash[2].$contenthash[3]; 377 return "$this->filedir/$l1/$l2/$contenthash"; 378 } 379 380 /** 381 * Get file pathname by given contenthash, this method will try to sync files 382 * 383 * Protected - developers must not gain direct access to this function. 384 * 385 * NOTE: do not make this public, we must not modify or delete the pool files directly! ;-) 386 * 387 * @return string full path to pool file with file content 388 **/ 389 protected function get_content_file_location() { 390 $this->sync_external_file(); 391 return $this->get_pathname_by_contenthash(); 392 } 393 394 /** 395 * adds this file path to a curl request (POST only) 396 * 397 * @param curl $curlrequest the curl request object 398 * @param string $key what key to use in the POST request 399 * @return void 400 */ 401 public function add_to_curl_request(&$curlrequest, $key) { 402 if (function_exists('curl_file_create')) { 403 // As of PHP 5.5, the usage of the @filename API for file uploading is deprecated. 404 $value = curl_file_create($this->get_content_file_location()); 405 } else { 406 $value = '@' . $this->get_content_file_location(); 407 } 408 $curlrequest->_tmp_file_post_params[$key] = $value; 409 } 410 411 /** 412 * Returns file handle - read only mode, no writing allowed into pool files! 413 * 414 * When you want to modify a file, create a new file and delete the old one. 415 * 416 * @param int $type Type of file handle (FILE_HANDLE_xx constant) 417 * @return resource file handle 418 */ 419 public function get_content_file_handle($type = self::FILE_HANDLE_FOPEN) { 420 $path = $this->get_content_file_location(); 421 if (!is_readable($path)) { 422 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) { 423 throw new file_exception('storedfilecannotread', '', $path); 424 } 425 } 426 switch ($type) { 427 case self::FILE_HANDLE_FOPEN: 428 // Binary reading. 429 return fopen($path, 'rb'); 430 case self::FILE_HANDLE_GZOPEN: 431 // Binary reading of file in gz format. 432 return gzopen($path, 'rb'); 433 default: 434 throw new coding_exception('Unexpected file handle type'); 435 } 436 } 437 438 /** 439 * Dumps file content to page. 440 */ 441 public function readfile() { 442 $path = $this->get_content_file_location(); 443 if (!is_readable($path)) { 444 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) { 445 throw new file_exception('storedfilecannotread', '', $path); 446 } 447 } 448 readfile_allow_large($path, $this->get_filesize()); 449 } 450 451 /** 452 * Returns file content as string. 453 * 454 * @return string content 455 */ 456 public function get_content() { 457 $path = $this->get_content_file_location(); 458 if (!is_readable($path)) { 459 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) { 460 throw new file_exception('storedfilecannotread', '', $path); 461 } 462 } 463 return file_get_contents($this->get_content_file_location()); 464 } 465 466 /** 467 * Copy content of file to given pathname. 468 * 469 * @param string $pathname real path to the new file 470 * @return bool success 471 */ 472 public function copy_content_to($pathname) { 473 $path = $this->get_content_file_location(); 474 if (!is_readable($path)) { 475 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) { 476 throw new file_exception('storedfilecannotread', '', $path); 477 } 478 } 479 return copy($path, $pathname); 480 } 481 482 /** 483 * Copy content of file to temporary folder and returns file path 484 * 485 * @param string $dir name of the temporary directory 486 * @param string $fileprefix prefix of temporary file. 487 * @return string|bool path of temporary file or false. 488 */ 489 public function copy_content_to_temp($dir = 'files', $fileprefix = 'tempup_') { 490 $tempfile = false; 491 if (!$dir = make_temp_directory($dir)) { 492 return false; 493 } 494 if (!$tempfile = tempnam($dir, $fileprefix)) { 495 return false; 496 } 497 if (!$this->copy_content_to($tempfile)) { 498 // something went wrong 499 @unlink($tempfile); 500 return false; 501 } 502 return $tempfile; 503 } 504 505 /** 506 * List contents of archive. 507 * 508 * @param file_packer $packer file packer instance 509 * @return array of file infos 510 */ 511 public function list_files(file_packer $packer) { 512 $archivefile = $this->get_content_file_location(); 513 return $packer->list_files($archivefile); 514 } 515 516 /** 517 * Extract file to given file path (real OS filesystem), existing files are overwritten. 518 * 519 * @param file_packer $packer file packer instance 520 * @param string $pathname target directory 521 * @param file_progress $progress Progress indicator callback or null if not required 522 * @return array|bool list of processed files; false if error 523 */ 524 public function extract_to_pathname(file_packer $packer, $pathname, 525 file_progress $progress = null) { 526 $archivefile = $this->get_content_file_location(); 527 return $packer->extract_to_pathname($archivefile, $pathname, null, $progress); 528 } 529 530 /** 531 * Extract file to given file path (real OS filesystem), existing files are overwritten. 532 * 533 * @param file_packer $packer file packer instance 534 * @param int $contextid context ID 535 * @param string $component component 536 * @param string $filearea file area 537 * @param int $itemid item ID 538 * @param string $pathbase path base 539 * @param int $userid user ID 540 * @param file_progress $progress Progress indicator callback or null if not required 541 * @return array|bool list of processed files; false if error 542 */ 543 public function extract_to_storage(file_packer $packer, $contextid, 544 $component, $filearea, $itemid, $pathbase, $userid = null, file_progress $progress = null) { 545 $archivefile = $this->get_content_file_location(); 546 return $packer->extract_to_storage($archivefile, $contextid, 547 $component, $filearea, $itemid, $pathbase, $userid, $progress); 548 } 549 550 /** 551 * Add file/directory into archive. 552 * 553 * @param file_archive $filearch file archive instance 554 * @param string $archivepath pathname in archive 555 * @return bool success 556 */ 557 public function archive_file(file_archive $filearch, $archivepath) { 558 if ($this->is_directory()) { 559 return $filearch->add_directory($archivepath); 560 } else { 561 $path = $this->get_content_file_location(); 562 if (!is_readable($path)) { 563 return false; 564 } 565 return $filearch->add_file_from_pathname($archivepath, $path); 566 } 567 } 568 569 /** 570 * Returns information about image, 571 * information is determined from the file content 572 * 573 * @return mixed array with width, height and mimetype; false if not an image 574 */ 575 public function get_imageinfo() { 576 $path = $this->get_content_file_location(); 577 if (!is_readable($path)) { 578 if (!$this->fs->try_content_recovery($this) or !is_readable($path)) { 579 throw new file_exception('storedfilecannotread', '', $path); 580 } 581 } 582 $mimetype = $this->get_mimetype(); 583 if (!preg_match('|^image/|', $mimetype) || !filesize($path) || !($imageinfo = getimagesize($path))) { 584 return false; 585 } 586 $image = array('width'=>$imageinfo[0], 'height'=>$imageinfo[1], 'mimetype'=>image_type_to_mime_type($imageinfo[2])); 587 if (empty($image['width']) or empty($image['height']) or empty($image['mimetype'])) { 588 // gd can not parse it, sorry 589 return false; 590 } 591 return $image; 592 } 593 594 /** 595 * Verifies the file is a valid web image - gif, png and jpeg only. 596 * 597 * It should be ok to serve this image from server without any other security workarounds. 598 * 599 * @return bool true if file ok 600 */ 601 public function is_valid_image() { 602 $mimetype = $this->get_mimetype(); 603 if (!file_mimetype_in_typegroup($mimetype, 'web_image')) { 604 return false; 605 } 606 if (!$info = $this->get_imageinfo()) { 607 return false; 608 } 609 if ($info['mimetype'] !== $mimetype) { 610 return false; 611 } 612 // ok, GD likes this image 613 return true; 614 } 615 616 /** 617 * Returns parent directory, creates missing parents if needed. 618 * 619 * @return stored_file 620 */ 621 public function get_parent_directory() { 622 if ($this->file_record->filepath === '/' and $this->file_record->filename === '.') { 623 //root dir does not have parent 624 return null; 625 } 626 627 if ($this->file_record->filename !== '.') { 628 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); 629 } 630 631 $filepath = $this->file_record->filepath; 632 $filepath = trim($filepath, '/'); 633 $dirs = explode('/', $filepath); 634 array_pop($dirs); 635 $filepath = implode('/', $dirs); 636 $filepath = ($filepath === '') ? '/' : "/$filepath/"; 637 638 return $this->fs->create_directory($this->file_record->contextid, $this->file_record->component, $this->file_record->filearea, $this->file_record->itemid, $filepath); 639 } 640 641 /** 642 * Synchronize file if it is a reference and needs synchronizing 643 * 644 * Updates contenthash and filesize 645 */ 646 public function sync_external_file() { 647 if (!empty($this->repository)) { 648 $this->repository->sync_reference($this); 649 } 650 } 651 652 /** 653 * Returns context id of the file 654 * 655 * @return int context id 656 */ 657 public function get_contextid() { 658 return $this->file_record->contextid; 659 } 660 661 /** 662 * Returns component name - this is the owner of the areas, 663 * nothing else is allowed to read or modify the files directly!! 664 * 665 * @return string 666 */ 667 public function get_component() { 668 return $this->file_record->component; 669 } 670 671 /** 672 * Returns file area name, this divides files of one component into groups with different access control. 673 * All files in one area have the same access control. 674 * 675 * @return string 676 */ 677 public function get_filearea() { 678 return $this->file_record->filearea; 679 } 680 681 /** 682 * Returns returns item id of file. 683 * 684 * @return int 685 */ 686 public function get_itemid() { 687 return $this->file_record->itemid; 688 } 689 690 /** 691 * Returns file path - starts and ends with /, \ are not allowed. 692 * 693 * @return string 694 */ 695 public function get_filepath() { 696 return $this->file_record->filepath; 697 } 698 699 /** 700 * Returns file name or '.' in case of directories. 701 * 702 * @return string 703 */ 704 public function get_filename() { 705 return $this->file_record->filename; 706 } 707 708 /** 709 * Returns id of user who created the file. 710 * 711 * @return int 712 */ 713 public function get_userid() { 714 return $this->file_record->userid; 715 } 716 717 /** 718 * Returns the size of file in bytes. 719 * 720 * @return int bytes 721 */ 722 public function get_filesize() { 723 $this->sync_external_file(); 724 return $this->file_record->filesize; 725 } 726 727 /** 728 * Function stored_file::set_filesize() is deprecated. Please use stored_file::replace_file_with 729 * 730 * @deprecated since Moodle 2.6 MDL-42016 - please do not use this function any more. 731 * @see stored_file::replace_file_with() 732 */ 733 public function set_filesize($filesize) { 734 throw new coding_exception('Function stored_file::set_filesize() can not be used any more. ' . 735 'Please use stored_file::replace_file_with()'); 736 } 737 738 /** 739 * Returns mime type of file. 740 * 741 * @return string 742 */ 743 public function get_mimetype() { 744 return $this->file_record->mimetype; 745 } 746 747 /** 748 * Returns unix timestamp of file creation date. 749 * 750 * @return int 751 */ 752 public function get_timecreated() { 753 return $this->file_record->timecreated; 754 } 755 756 /** 757 * Returns unix timestamp of last file modification. 758 * 759 * @return int 760 */ 761 public function get_timemodified() { 762 $this->sync_external_file(); 763 return $this->file_record->timemodified; 764 } 765 766 /** 767 * set timemodified 768 * 769 * @param int $timemodified 770 */ 771 public function set_timemodified($timemodified) { 772 $filerecord = new stdClass; 773 $filerecord->timemodified = $timemodified; 774 $this->update($filerecord); 775 } 776 777 /** 778 * Returns file status flag. 779 * 780 * @return int 0 means file OK, anything else is a problem and file can not be used 781 */ 782 public function get_status() { 783 return $this->file_record->status; 784 } 785 786 /** 787 * Returns file id. 788 * 789 * @return int 790 */ 791 public function get_id() { 792 return $this->file_record->id; 793 } 794 795 /** 796 * Returns sha1 hash of file content. 797 * 798 * @return string 799 */ 800 public function get_contenthash() { 801 $this->sync_external_file(); 802 return $this->file_record->contenthash; 803 } 804 805 /** 806 * Returns sha1 hash of all file path components sha1("contextid/component/filearea/itemid/dir/dir/filename.ext"). 807 * 808 * @return string 809 */ 810 public function get_pathnamehash() { 811 return $this->file_record->pathnamehash; 812 } 813 814 /** 815 * Returns the license type of the file, it is a short name referred from license table. 816 * 817 * @return string 818 */ 819 public function get_license() { 820 return $this->file_record->license; 821 } 822 823 /** 824 * Set license 825 * 826 * @param string $license license 827 */ 828 public function set_license($license) { 829 $filerecord = new stdClass; 830 $filerecord->license = $license; 831 $this->update($filerecord); 832 } 833 834 /** 835 * Returns the author name of the file. 836 * 837 * @return string 838 */ 839 public function get_author() { 840 return $this->file_record->author; 841 } 842 843 /** 844 * Set author 845 * 846 * @param string $author 847 */ 848 public function set_author($author) { 849 $filerecord = new stdClass; 850 $filerecord->author = $author; 851 $this->update($filerecord); 852 } 853 854 /** 855 * Returns the source of the file, usually it is a url. 856 * 857 * @return string 858 */ 859 public function get_source() { 860 return $this->file_record->source; 861 } 862 863 /** 864 * Set license 865 * 866 * @param string $license license 867 */ 868 public function set_source($source) { 869 $filerecord = new stdClass; 870 $filerecord->source = $source; 871 $this->update($filerecord); 872 } 873 874 875 /** 876 * Returns the sort order of file 877 * 878 * @return int 879 */ 880 public function get_sortorder() { 881 return $this->file_record->sortorder; 882 } 883 884 /** 885 * Set file sort order 886 * 887 * @param int $sortorder 888 * @return int 889 */ 890 public function set_sortorder($sortorder) { 891 $filerecord = new stdClass; 892 $filerecord->sortorder = $sortorder; 893 $this->update($filerecord); 894 } 895 896 /** 897 * Returns repository id 898 * 899 * @return int|null 900 */ 901 public function get_repository_id() { 902 if (!empty($this->repository)) { 903 return $this->repository->id; 904 } else { 905 return null; 906 } 907 } 908 909 /** 910 * get reference file id 911 * @return int 912 */ 913 public function get_referencefileid() { 914 return $this->file_record->referencefileid; 915 } 916 917 /** 918 * Get reference last sync time 919 * @return int 920 */ 921 public function get_referencelastsync() { 922 return $this->file_record->referencelastsync; 923 } 924 925 /** 926 * Function stored_file::get_referencelifetime() is deprecated as reference 927 * life time is no longer stored in DB or returned by repository. Each 928 * repository should decide by itself when to synchronise the references. 929 * 930 * @deprecated since Moodle 2.6 MDL-42016 - please do not use this function any more. 931 * @see repository::sync_reference() 932 */ 933 public function get_referencelifetime() { 934 throw new coding_exception('Function stored_file::get_referencelifetime() can not be used any more. ' . 935 'See repository::sync_reference().'); 936 } 937 /** 938 * Returns file reference 939 * 940 * @return string 941 */ 942 public function get_reference() { 943 return $this->file_record->reference; 944 } 945 946 /** 947 * Get human readable file reference information 948 * 949 * @return string 950 */ 951 public function get_reference_details() { 952 return $this->repository->get_reference_details($this->get_reference(), $this->get_status()); 953 } 954 955 /** 956 * Called after reference-file has been synchronized with the repository 957 * 958 * We update contenthash, filesize and status in files table if changed 959 * and we always update lastsync in files_reference table 960 * 961 * @param null|string $contenthash if set to null contenthash is not changed 962 * @param int $filesize new size of the file 963 * @param int $status new status of the file (0 means OK, 666 - source missing) 964 * @param int $timemodified last time modified of the source, if known 965 */ 966 public function set_synchronized($contenthash, $filesize, $status = 0, $timemodified = null) { 967 if (!$this->is_external_file()) { 968 return; 969 } 970 $now = time(); 971 if ($contenthash === null) { 972 $contenthash = $this->file_record->contenthash; 973 } 974 if ($contenthash != $this->file_record->contenthash) { 975 $oldcontenthash = $this->file_record->contenthash; 976 } 977 // this will update all entries in {files} that have the same filereference id 978 $this->fs->update_references($this->file_record->referencefileid, $now, null, $contenthash, $filesize, $status, $timemodified); 979 // we don't need to call update() for this object, just set the values of changed fields 980 $this->file_record->contenthash = $contenthash; 981 $this->file_record->filesize = $filesize; 982 $this->file_record->status = $status; 983 $this->file_record->referencelastsync = $now; 984 if ($timemodified) { 985 $this->file_record->timemodified = $timemodified; 986 } 987 if (isset($oldcontenthash)) { 988 $this->fs->deleted_file_cleanup($oldcontenthash); 989 } 990 } 991 992 /** 993 * Sets the error status for a file that could not be synchronised 994 */ 995 public function set_missingsource() { 996 $this->set_synchronized($this->file_record->contenthash, $this->file_record->filesize, 666); 997 } 998 999 /** 1000 * Send file references 1001 * 1002 * @param int $lifetime Number of seconds before the file should expire from caches (default 24 hours) 1003 * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only 1004 * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin 1005 * @param array $options additional options affecting the file serving 1006 */ 1007 public function send_file($lifetime, $filter, $forcedownload, $options) { 1008 $this->repository->send_file($this, $lifetime, $filter, $forcedownload, $options); 1009 } 1010 1011 /** 1012 * Imports the contents of an external file into moodle filepool. 1013 * 1014 * @throws moodle_exception if file could not be downloaded or is too big 1015 * @param int $maxbytes throw an exception if file size is bigger than $maxbytes (0 means no limit) 1016 */ 1017 public function import_external_file_contents($maxbytes = 0) { 1018 if ($this->repository) { 1019 $this->repository->import_external_file_contents($this, $maxbytes); 1020 } 1021 } 1022 1023 /** 1024 * Gets a file relative to this file in the repository and sends it to the browser. 1025 * Checks the function repository::supports_relative_file() to make sure it can be used. 1026 * 1027 * @param string $relativepath the relative path to the file we are trying to access 1028 */ 1029 public function send_relative_file($relativepath) { 1030 if ($this->repository && $this->repository->supports_relative_file()) { 1031 $relativepath = clean_param($relativepath, PARAM_PATH); 1032 $this->repository->send_relative_file($this, $relativepath); 1033 } else { 1034 send_file_not_found(); 1035 } 1036 } 1037 1038 /** 1039 * Generates a thumbnail for this stored_file. 1040 * 1041 * If the GD library has at least version 2 and PNG support is available, the returned data 1042 * is the content of a transparent PNG file containing the thumbnail. Otherwise, the function 1043 * returns contents of a JPEG file with black background containing the thumbnail. 1044 * 1045 * @param int $width the width of the requested thumbnail 1046 * @param int $height the height of the requested thumbnail 1047 * @return string|bool false if a problem occurs, the thumbnail image data otherwise 1048 */ 1049 public function generate_image_thumbnail($width, $height) { 1050 if (empty($width) or empty($height)) { 1051 return false; 1052 } 1053 1054 // Fetch the image information for this image. 1055 $imageinfo = @getimagesizefromstring($this->get_content()); 1056 if (empty($imageinfo)) { 1057 return false; 1058 } 1059 1060 // Create a new image from the file. 1061 $original = @imagecreatefromstring($this->get_content()); 1062 1063 // Generate the thumbnail. 1064 return generate_image_thumbnail_from_image($original, $imageinfo, $width, $height); 1065 } 1066 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |