[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/filestorage/ -> stored_file.php (source)

   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  }


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1