[ Index ]

PHP Cross Reference of moodle-2.8

title

Body

[close]

/repository/filesystem/ -> lib.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   * This plugin is used to access files on server file system
  19   *
  20   * @since Moodle 2.0
  21   * @package    repository_filesystem
  22   * @copyright  2010 Dongsheng Cai {@link http://dongsheng.org}
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  require_once($CFG->dirroot . '/repository/lib.php');
  26  require_once($CFG->libdir . '/filelib.php');
  27  
  28  /**
  29   * repository_filesystem class
  30   *
  31   * Create a repository from your local filesystem
  32   * *NOTE* for security issue, we use a fixed repository path
  33   * which is %moodledata%/repository
  34   *
  35   * @package    repository
  36   * @copyright  2009 Dongsheng Cai {@link http://dongsheng.org}
  37   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38   */
  39  class repository_filesystem extends repository {
  40  
  41      /**
  42       * The subdirectory of the instance.
  43       *
  44       * @var string
  45       */
  46      protected $subdir;
  47  
  48      /**
  49       * Constructor
  50       *
  51       * @param int $repositoryid repository ID
  52       * @param int $context context ID
  53       * @param array $options
  54       */
  55      public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
  56          parent::__construct($repositoryid, $context, $options);
  57          $this->subdir = $this->get_option('fs_path');
  58      }
  59  
  60      /**
  61       * Get the list of files and directories in that repository.
  62       *
  63       * @param string $path to browse.
  64       * @param string $page page number.
  65       * @return array list of files and folders.
  66       */
  67      public function get_listing($path = '', $page = '') {
  68          global $OUTPUT;
  69  
  70          $list = array();
  71          $list['list'] = array();
  72          $list['manage'] = false;
  73          $list['dynload'] = true;
  74          $list['nologin'] = true;
  75          $list['nosearch'] = true;
  76          $list['path'] = array(
  77              array('name' => get_string('root', 'repository_filesystem'), 'path' => '')
  78          );
  79  
  80          $path = trim($path, '/');
  81          if (!$this->is_in_repository($path)) {
  82              // In case of doubt on the path, reset to default.
  83              $path = '';
  84          }
  85          $abspath = rtrim($this->get_rootpath() . $path, '/') . '/';
  86  
  87          // Construct the breadcrumb.
  88          $trail = '';
  89          if ($path !== '') {
  90              $parts = explode('/', $path);
  91              if (count($parts) > 1) {
  92                  foreach ($parts as $part) {
  93                      if (!empty($part)) {
  94                          $trail .= '/' . $part;
  95                          $list['path'][] = array('name' => $part, 'path' => $trail);
  96                      }
  97                  }
  98              } else {
  99                  $list['path'][] = array('name' => $path, 'path' => $path);
 100              }
 101          }
 102  
 103          // Retrieve list of files and directories and sort them.
 104          $fileslist = array();
 105          $dirslist = array();
 106          if ($dh = opendir($abspath)) {
 107              while (($file = readdir($dh)) != false) {
 108                  if ($file != '.' and $file != '..') {
 109                      if (is_file($abspath . $file)) {
 110                          $fileslist[] = $file;
 111                      } else {
 112                          $dirslist[] = $file;
 113                      }
 114                  }
 115              }
 116          }
 117          core_collator::asort($fileslist, core_collator::SORT_NATURAL);
 118          core_collator::asort($dirslist, core_collator::SORT_NATURAL);
 119  
 120          // Fill the $list['list'].
 121          foreach ($dirslist as $file) {
 122              $list['list'][] = array(
 123                  'title' => $file,
 124                  'children' => array(),
 125                  'datecreated' => filectime($abspath . $file),
 126                  'datemodified' => filemtime($abspath . $file),
 127                  'thumbnail' => $OUTPUT->pix_url(file_folder_icon(90))->out(false),
 128                  'path' => $path . '/' . $file
 129              );
 130          }
 131          foreach ($fileslist as $file) {
 132              $node = array(
 133                  'title' => $file,
 134                  'source' => $path . '/' . $file,
 135                  'size' => filesize($abspath . $file),
 136                  'datecreated' => filectime($abspath . $file),
 137                  'datemodified' => filemtime($abspath . $file),
 138                  'thumbnail' => $OUTPUT->pix_url(file_extension_icon($file, 90))->out(false),
 139                  'icon' => $OUTPUT->pix_url(file_extension_icon($file, 24))->out(false)
 140              );
 141              if (file_extension_in_typegroup($file, 'image') && ($imageinfo = @getimagesize($abspath . $file))) {
 142                  // This means it is an image and we can return dimensions and try to generate thumbnail/icon.
 143                  $token = $node['datemodified'] . $node['size']; // To prevent caching by browser.
 144                  $node['realthumbnail'] = $this->get_thumbnail_url($path . '/' . $file, 'thumb', $token)->out(false);
 145                  $node['realicon'] = $this->get_thumbnail_url($path . '/' . $file, 'icon', $token)->out(false);
 146                  $node['image_width'] = $imageinfo[0];
 147                  $node['image_height'] = $imageinfo[1];
 148              }
 149              $list['list'][] = $node;
 150          }
 151          $list['list'] = array_filter($list['list'], array($this, 'filter'));
 152          return $list;
 153      }
 154  
 155  
 156      /**
 157       * To check whether the user is logged in.
 158       *
 159       * @return bool
 160       */
 161      public function check_login() {
 162          return true;
 163      }
 164  
 165      /**
 166       * Show the login screen, if required.
 167       *
 168       * @return string
 169       */
 170      public function print_login() {
 171          return true;
 172      }
 173  
 174      /**
 175       * Is it possible to do a global search?
 176       *
 177       * @return bool
 178       */
 179      public function global_search() {
 180          return false;
 181      }
 182  
 183      /**
 184       * Return file path.
 185       * @return array
 186       */
 187      public function get_file($file, $title = '') {
 188          global $CFG;
 189          $file = ltrim($file, '/');
 190          if (!$this->is_in_repository($file)) {
 191              throw new repository_exception('Invalid file requested.');
 192          }
 193          $file = $this->get_rootpath() . $file;
 194  
 195          // This is a hack to prevent move_to_file deleting files in local repository.
 196          $CFG->repository_no_delete = true;
 197          return array('path' => $file, 'url' => '');
 198      }
 199  
 200      /**
 201       * Return the source information
 202       *
 203       * @param stdClass $filepath
 204       * @return string|null
 205       */
 206      public function get_file_source_info($filepath) {
 207          return $filepath;
 208      }
 209  
 210      /**
 211       * Logout from repository instance
 212       *
 213       * @return string
 214       */
 215      public function logout() {
 216          return true;
 217      }
 218  
 219      /**
 220       * Return names of the instance options.
 221       *
 222       * @return array
 223       */
 224      public static function get_instance_option_names() {
 225          return array('fs_path', 'relativefiles');
 226      }
 227  
 228      /**
 229       * Save settings for repository instance
 230       *
 231       * @param array $options settings
 232       * @return bool
 233       */
 234      public function set_option($options = array()) {
 235          $options['fs_path'] = clean_param($options['fs_path'], PARAM_PATH);
 236          $options['relativefiles'] = clean_param($options['relativefiles'], PARAM_INT);
 237          $ret = parent::set_option($options);
 238          return $ret;
 239      }
 240  
 241      /**
 242       * Edit/Create Instance Settings Moodle form
 243       *
 244       * @param moodleform $mform Moodle form (passed by reference)
 245       */
 246      public static function instance_config_form($mform) {
 247          global $CFG;
 248          if (has_capability('moodle/site:config', context_system::instance())) {
 249              $path = $CFG->dataroot . '/repository/';
 250              if (!is_dir($path)) {
 251                  mkdir($path, $CFG->directorypermissions, true);
 252              }
 253              if ($handle = opendir($path)) {
 254                  $fieldname = get_string('path', 'repository_filesystem');
 255                  $choices = array();
 256                  while (false !== ($file = readdir($handle))) {
 257                      if (is_dir($path . $file) && $file != '.' && $file != '..') {
 258                          $choices[$file] = $file;
 259                          $fieldname = '';
 260                      }
 261                  }
 262                  if (empty($choices)) {
 263                      $mform->addElement('static', '', '', get_string('nosubdir', 'repository_filesystem', $path));
 264                      $mform->addElement('hidden', 'fs_path', '');
 265                      $mform->setType('fs_path', PARAM_PATH);
 266                  } else {
 267                      $mform->addElement('select', 'fs_path', $fieldname, $choices);
 268                      $mform->addElement('static', null, '',  get_string('information', 'repository_filesystem', $path));
 269                  }
 270                  closedir($handle);
 271              }
 272              $mform->addElement('checkbox', 'relativefiles', get_string('relativefiles', 'repository_filesystem'),
 273                  get_string('relativefiles_desc', 'repository_filesystem'));
 274              $mform->setType('relativefiles', PARAM_INT);
 275  
 276          } else {
 277              $mform->addElement('static', null, '',  get_string('nopermissions', 'error', get_string('configplugin',
 278                  'repository_filesystem')));
 279              return false;
 280          }
 281      }
 282  
 283      /**
 284       * Create an instance for this plug-in
 285       *
 286       * @static
 287       * @param string $type the type of the repository
 288       * @param int $userid the user id
 289       * @param stdClass $context the context
 290       * @param array $params the options for this instance
 291       * @param int $readonly whether to create it readonly or not (defaults to not)
 292       * @return mixed
 293       */
 294      public static function create($type, $userid, $context, $params, $readonly=0) {
 295          if (has_capability('moodle/site:config', context_system::instance())) {
 296              return parent::create($type, $userid, $context, $params, $readonly);
 297          } else {
 298              require_capability('moodle/site:config', context_system::instance());
 299              return false;
 300          }
 301      }
 302  
 303      /**
 304       * Validate repository plugin instance form
 305       *
 306       * @param moodleform $mform moodle form
 307       * @param array $data form data
 308       * @param array $errors errors
 309       * @return array errors
 310       */
 311      public static function instance_form_validation($mform, $data, $errors) {
 312          $fspath = clean_param(trim($data['fs_path'], '/'), PARAM_PATH);
 313          if (empty($fspath) && !is_numeric($fspath)) {
 314              $errors['fs_path'] = get_string('invalidadminsettingname', 'error', 'fs_path');
 315          }
 316          return $errors;
 317      }
 318  
 319      /**
 320       * User cannot use the external link to dropbox
 321       *
 322       * @return int
 323       */
 324      public function supported_returntypes() {
 325          return FILE_INTERNAL | FILE_REFERENCE;
 326      }
 327  
 328      /**
 329       * Return human readable reference information
 330       *
 331       * @param string $reference value of DB field files_reference.reference
 332       * @param int $filestatus status of the file, 0 - ok, 666 - source missing
 333       * @return string
 334       */
 335      public function get_reference_details($reference, $filestatus = 0) {
 336          $details = $this->get_name().': '.$reference;
 337          if ($filestatus) {
 338              return get_string('lostsource', 'repository', $details);
 339          } else {
 340              return $details;
 341          }
 342      }
 343  
 344      public function sync_reference(stored_file $file) {
 345          if ($file->get_referencelastsync() + 60 > time()) {
 346              // Does not cost us much to synchronise within our own filesystem, check every 1 minute.
 347              return false;
 348          }
 349          static $issyncing = false;
 350          if ($issyncing) {
 351              // Avoid infinite recursion when calling $file->get_filesize() and get_contenthash().
 352              return;
 353          }
 354          $filepath = $this->get_rootpath() . ltrim($file->get_reference(), '/');
 355          if ($this->is_in_repository($file->get_reference()) && file_exists($filepath) && is_readable($filepath)) {
 356              $fs = get_file_storage();
 357              $issyncing = true;
 358              if (file_extension_in_typegroup($filepath, 'web_image')) {
 359                  $contenthash = sha1_file($filepath);
 360                  if ($file->get_contenthash() == $contenthash) {
 361                      // File did not change since the last synchronisation.
 362                      $filesize = filesize($filepath);
 363                  } else {
 364                      // Copy file into moodle filepool (used to generate an image thumbnail).
 365                      list($contenthash, $filesize, $newfile) = $fs->add_file_to_pool($filepath);
 366                  }
 367              } else {
 368                  // Update only file size so file will NOT be copied into moodle filepool.
 369                  $contenthash = null;
 370                  $filesize = filesize($filepath);
 371              }
 372              $issyncing = false;
 373              $file->set_synchronized($contenthash, $filesize);
 374          } else {
 375              $file->set_missingsource();
 376          }
 377          return true;
 378      }
 379  
 380      /**
 381       * Repository method to serve the referenced file
 382       *
 383       * @see send_stored_file
 384       *
 385       * @param stored_file $storedfile the file that contains the reference
 386       * @param int $lifetime Number of seconds before the file should expire from caches (null means $CFG->filelifetime)
 387       * @param int $filter 0 (default)=no filtering, 1=all files, 2=html files only
 388       * @param bool $forcedownload If true (default false), forces download of file rather than view in browser/plugin
 389       * @param array $options additional options affecting the file serving
 390       */
 391      public function send_file($storedfile, $lifetime=null , $filter=0, $forcedownload=false, array $options = null) {
 392          $reference = $storedfile->get_reference();
 393          $file = $this->get_rootpath() . ltrim($reference, '/');
 394          if ($this->is_in_repository($reference) && is_readable($file)) {
 395              $filename = $storedfile->get_filename();
 396              if ($options && isset($options['filename'])) {
 397                  $filename = $options['filename'];
 398              }
 399              $dontdie = ($options && isset($options['dontdie']));
 400              send_file($file, $filename, $lifetime , $filter, false, $forcedownload, '', $dontdie);
 401          } else {
 402              send_file_not_found();
 403          }
 404      }
 405  
 406      /**
 407       * Is this repository accessing private data?
 408       *
 409       * @return bool
 410       */
 411      public function contains_private_data() {
 412          return false;
 413      }
 414  
 415      /**
 416       * Return the rootpath of this repository instance.
 417       *
 418       * Trim() is a necessary step to ensure that the subdirectory is not '/'.
 419       *
 420       * @return string path
 421       * @throws repository_exception If the subdir is unsafe, or invalid.
 422       */
 423      public function get_rootpath() {
 424          global $CFG;
 425          $subdir = clean_param(trim($this->subdir, '/'), PARAM_PATH);
 426          $path = $CFG->dataroot . '/repository/' . $this->subdir . '/';
 427          if ((empty($this->subdir) && !is_numeric($this->subdir)) || $subdir != $this->subdir || !is_dir($path)) {
 428              throw new repository_exception('The instance is not properly configured, invalid path.');
 429          }
 430          return $path;
 431      }
 432  
 433      /**
 434       * Checks if $path is part of this repository.
 435       *
 436       * Try to prevent $path hacks such as ../ .
 437       *
 438       * We do not use clean_param(, PARAM_PATH) here because it also trims down some
 439       * characters that are allowed, like < > ' . But we do ensure that the directory
 440       * is safe by checking that it starts with $rootpath.
 441       *
 442       * @param string $path relative path to a file or directory in the repo.
 443       * @return boolean false when not.
 444       */
 445      protected function is_in_repository($path) {
 446          $rootpath = $this->get_rootpath();
 447          if (strpos(realpath($rootpath . $path), realpath($rootpath)) !== 0) {
 448              return false;
 449          }
 450          return true;
 451      }
 452  
 453      /**
 454       * Returns url of thumbnail file.
 455       *
 456       * @param string $filepath current path in repository (dir and filename)
 457       * @param string $thumbsize 'thumb' or 'icon'
 458       * @param string $token identifier of the file contents - to prevent browser from caching changed file
 459       * @return moodle_url
 460       */
 461      protected function get_thumbnail_url($filepath, $thumbsize, $token) {
 462          return moodle_url::make_pluginfile_url($this->context->id, 'repository_filesystem', $thumbsize, $this->id,
 463                  '/' . trim($filepath, '/') . '/', $token);
 464      }
 465  
 466      /**
 467       * Returns the stored thumbnail file, generates it if not present.
 468       *
 469       * @param string $filepath current path in repository (dir and filename)
 470       * @param string $thumbsize 'thumb' or 'icon'
 471       * @return null|stored_file
 472       */
 473      public function get_thumbnail($filepath, $thumbsize) {
 474          global $CFG;
 475  
 476          $filepath = trim($filepath, '/');
 477          $origfile = $this->get_rootpath() . $filepath;
 478          // As thumbnail filename we use original file content hash.
 479          if (!$this->is_in_repository($filepath) || !($filecontents = @file_get_contents($origfile))) {
 480              // File is not found or is not readable.
 481              return null;
 482          }
 483          $filename = sha1($filecontents);
 484          unset($filecontents);
 485  
 486          // Try to get generated thumbnail for this file.
 487          $fs = get_file_storage();
 488          if (!($file = $fs->get_file(SYSCONTEXTID, 'repository_filesystem', $thumbsize, $this->id, '/' . $filepath . '/',
 489                  $filename))) {
 490              // Thumbnail not found . Generate and store thumbnail.
 491              require_once($CFG->libdir . '/gdlib.php');
 492              if ($thumbsize === 'thumb') {
 493                  $size = 90;
 494              } else {
 495                  $size = 24;
 496              }
 497              if (!$data = @generate_image_thumbnail($origfile, $size, $size)) {
 498                  // Generation failed.
 499                  return null;
 500              }
 501              $record = array(
 502                  'contextid' => SYSCONTEXTID,
 503                  'component' => 'repository_filesystem',
 504                  'filearea' => $thumbsize,
 505                  'itemid' => $this->id,
 506                  'filepath' => '/' . $filepath . '/',
 507                  'filename' => $filename,
 508              );
 509              $file = $fs->create_file_from_string($record, $data);
 510          }
 511          return $file;
 512      }
 513  
 514      /**
 515       * Run in cron for particular repository instance. Removes thumbnails for deleted/modified files.
 516       *
 517       * @param stored_file[] $storedfiles
 518       */
 519      public function remove_obsolete_thumbnails($storedfiles) {
 520          // Group found files by filepath ('filepath' in Moodle file storage is dir+name in filesystem repository).
 521          $files = array();
 522          foreach ($storedfiles as $file) {
 523              if (!isset($files[$file->get_filepath()])) {
 524                  $files[$file->get_filepath()] = array();
 525              }
 526              $files[$file->get_filepath()][] = $file;
 527          }
 528  
 529          // Loop through all files and make sure the original exists and has the same contenthash.
 530          $deletedcount = 0;
 531          foreach ($files as $filepath => $filesinpath) {
 532              if ($filecontents = @file_get_contents($this->get_rootpath() . trim($filepath, '/'))) {
 533                  // The 'filename' in Moodle file storage is contenthash of the file in filesystem repository.
 534                  $filename = sha1($filecontents);
 535                  foreach ($filesinpath as $file) {
 536                      if ($file->get_filename() !== $filename && $file->get_filename() !== '.') {
 537                          // Contenthash does not match, this is an old thumbnail.
 538                          $deletedcount++;
 539                          $file->delete();
 540                      }
 541                  }
 542              } else {
 543                  // Thumbnail exist but file not.
 544                  foreach ($filesinpath as $file) {
 545                      if ($file->get_filename() !== '.') {
 546                          $deletedcount++;
 547                      }
 548                      $file->delete();
 549                  }
 550              }
 551          }
 552          if ($deletedcount) {
 553              mtrace(" instance {$this->id}: deleted $deletedcount thumbnails");
 554          }
 555      }
 556  
 557      /**
 558       *  Gets a file relative to this file in the repository and sends it to the browser.
 559       *
 560       * @param stored_file $mainfile The main file we are trying to access relative files for.
 561       * @param string $relativepath the relative path to the file we are trying to access.
 562       */
 563      public function send_relative_file(stored_file $mainfile, $relativepath) {
 564          global $CFG;
 565          // Check if this repository is allowed to use relative linking.
 566          $allowlinks = $this->supports_relative_file();
 567          if (!empty($allowlinks)) {
 568              // Get path to the mainfile.
 569              $mainfilepath = $mainfile->get_source();
 570  
 571              // Strip out filename from the path.
 572              $filename = $mainfile->get_filename();
 573              $basepath = strstr($mainfilepath, $filename, true);
 574  
 575              $fullrelativefilepath = realpath($this->get_rootpath().$basepath.$relativepath);
 576  
 577              // Sanity check to make sure this path is inside this repository and the file exists.
 578              if (strpos($fullrelativefilepath, $this->get_rootpath()) === 0 && file_exists($fullrelativefilepath)) {
 579                  send_file($fullrelativefilepath, basename($relativepath), null, 0);
 580              }
 581          }
 582          send_file_not_found();
 583      }
 584  
 585      /**
 586       * helper function to check if the repository supports send_relative_file.
 587       *
 588       * @return true|false
 589       */
 590      public function supports_relative_file() {
 591          return $this->get_option('relativefiles');
 592      }
 593  }
 594  
 595  /**
 596   * Generates and sends the thumbnail for an image in filesystem.
 597   *
 598   * @param stdClass $course course object
 599   * @param stdClass $cm course module object
 600   * @param stdClass $context context object
 601   * @param string $filearea file area
 602   * @param array $args extra arguments
 603   * @param bool $forcedownload whether or not force download
 604   * @param array $options additional options affecting the file serving
 605   * @return bool
 606   */
 607  function repository_filesystem_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options=array()) {
 608      global $OUTPUT, $CFG;
 609      // Allowed filearea is either thumb or icon - size of the thumbnail.
 610      if ($filearea !== 'thumb' && $filearea !== 'icon') {
 611          return false;
 612      }
 613  
 614      // As itemid we pass repository instance id.
 615      $itemid = array_shift($args);
 616      // Filename is some token that we can ignore (used only to make sure browser does not serve cached copy when file is changed).
 617      array_pop($args);
 618      // As filepath we use full filepath (dir+name) of the file in this instance of filesystem repository.
 619      $filepath = implode('/', $args);
 620  
 621      // Make sure file exists in the repository and is accessible.
 622      $repo = repository::get_repository_by_id($itemid, $context);
 623      $repo->check_capability();
 624      // Find stored or generated thumbnail.
 625      if (!($file = $repo->get_thumbnail($filepath, $filearea))) {
 626          // Generation failed, redirect to default icon for file extension.
 627          redirect($OUTPUT->pix_url(file_extension_icon($file, 90)));
 628      }
 629      // The thumbnails should not be changing much, but maybe the default lifetime is too long.
 630      $lifetime = $CFG->filelifetime;
 631      if ($lifetime > 60*10) {
 632          $lifetime = 60*10;
 633      }
 634      send_stored_file($file, $lifetime, 0, $forcedownload, $options);
 635  }
 636  
 637  /**
 638   * Cron callback for repository_filesystem. Deletes the thumbnails for deleted or changed files.
 639   */
 640  function repository_filesystem_cron() {
 641      $fs = get_file_storage();
 642      // Find all generated thumbnails and group them in array by itemid (itemid == repository instance id).
 643      $allfiles = array_merge(
 644              $fs->get_area_files(SYSCONTEXTID, 'repository_filesystem', 'thumb'),
 645              $fs->get_area_files(SYSCONTEXTID, 'repository_filesystem', 'icon')
 646      );
 647      $filesbyitem = array();
 648      foreach ($allfiles as $file) {
 649          if (!isset($filesbyitem[$file->get_itemid()])) {
 650              $filesbyitem[$file->get_itemid()] = array();
 651          }
 652          $filesbyitem[$file->get_itemid()][] = $file;
 653      }
 654      // Find all instances of repository_filesystem.
 655      $instances = repository::get_instances(array('type' => 'filesystem'));
 656      // Loop through all itemids of generated thumbnails.
 657      foreach ($filesbyitem as $itemid => $files) {
 658          if (!isset($instances[$itemid]) || !($instances[$itemid] instanceof repository_filesystem)) {
 659              // Instance was deleted.
 660              $fs->delete_area_files(SYSCONTEXTID, 'repository_filesystem', 'thumb', $itemid);
 661              $fs->delete_area_files(SYSCONTEXTID, 'repository_filesystem', 'icon', $itemid);
 662              mtrace(" instance $itemid does not exist: deleted all thumbnails");
 663          } else {
 664              // Instance has some generated thumbnails, check that they are not outdated.
 665              $instances[$itemid]->remove_obsolete_thumbnails($files);
 666          }
 667      }
 668  }


Generated: Fri Nov 28 20:29:05 2014 Cross-referenced by PHPXref 0.7.1