Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 4.1.x will end 13 November 2023 (12 months).
  • Bug fixes for security issues in 4.1.x will end 10 November 2025 (36 months).
  • PHP version: minimum PHP 7.4.0 Note: minimum PHP version has increased since Moodle 4.0. PHP 8.0.x is supported too.

Differences Between: [Versions 401 and 402] [Versions 401 and 403]

   1  <?php
   2  
   3  // This file is part of Moodle - http://moodle.org/
   4  //
   5  // Moodle is free software: you can redistribute it and/or modify
   6  // it under the terms of the GNU General Public License as published by
   7  // the Free Software Foundation, either version 3 of the License, or
   8  // (at your option) any later version.
   9  //
  10  // Moodle is distributed in the hope that it will be useful,
  11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13  // GNU General Public License for more details.
  14  //
  15  // You should have received a copy of the GNU General Public License
  16  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
  17  
  18  /**
  19   * This plugin is used to access recent used files
  20   *
  21   * @since Moodle 2.0
  22   * @package    repository_recent
  23   * @copyright  2010 Dongsheng Cai {@link http://dongsheng.org}
  24   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  require_once($CFG->dirroot . '/repository/lib.php');
  27  
  28  /**
  29   * repository_recent class is used to browse recent used files
  30   *
  31   * @since Moodle 2.0
  32   * @package    repository_recent
  33   * @copyright  2010 Dongsheng Cai {@link http://dongsheng.org}
  34   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  35   */
  36  define('DEFAULT_RECENT_FILES_NUM', 50);
  37  
  38  /**
  39   * DEFAULT_RECENT_FILES_TIME_LIMIT - default time limit.
  40   */
  41  define('DEFAULT_RECENT_FILES_TIME_LIMIT', 6 * 4 * WEEKSECS);
  42  class repository_recent extends repository {
  43  
  44      /** @var int only retrieve files within the time limit */
  45      protected $timelimit;
  46  
  47      /**
  48       * Initialize recent plugin
  49       * @param int $repositoryid
  50       * @param int $context
  51       * @param array $options
  52       */
  53      public function __construct($repositoryid, $context = SYSCONTEXTID, $options = array()) {
  54          parent::__construct($repositoryid, $context, $options);
  55          $number = get_config('recent', 'recentfilesnumber');
  56          $number = (int)$number;
  57          if (empty($number)) {
  58              $this->number = DEFAULT_RECENT_FILES_NUM;
  59          } else {
  60              $this->number = $number;
  61          }
  62          $timelimit = get_config('recent', 'recentfilestimelimit');
  63          $this->timelimit = (int)$timelimit;
  64      }
  65  
  66      /**
  67       * recent plugin doesn't require login, so list all files
  68       * @return mixed
  69       */
  70      public function print_login() {
  71          return $this->get_listing();
  72      }
  73  
  74      /**
  75       * Only return files within the time limit
  76       *
  77       * @param int $limitfrom retrieve the files from
  78       * @param int $limit limit number of the files
  79       * @param int $timelimit only return files with the time limit
  80       * @return array list of recent files
  81       */
  82      private function get_recent_files($limitfrom = 0, $limit = DEFAULT_RECENT_FILES_NUM, $timelimit = 0) {
  83          // XXX: get current itemid
  84          global $USER, $DB, $itemid;
  85          $timelimitsql = '';
  86          if ($timelimit > 0) {
  87              $timelimitsql = "AND timemodified >= :timelimit";
  88              $timelimitparam = ['timelimit' => time() - $timelimit];
  89          }
  90          // This SQL will ignore draft files if not owned by current user.
  91          // Ignore all file references.
  92          $sql = "SELECT files1.id, files1.contextid, files1.component, files1.filearea,
  93                         files1.itemid, files1.filepath, files1.filename, files1.pathnamehash
  94                    FROM {files} files1
  95                    JOIN (
  96                        SELECT contenthash, filename, MAX(id) AS id
  97                          FROM {files}
  98                         WHERE userid = :userid
  99                           AND referencefileid is NULL
 100                           AND filename != :filename
 101                           AND ((filearea = :filearea1 AND itemid = :itemid) OR filearea != :filearea2)
 102                           $timelimitsql
 103                      GROUP BY contenthash, filename
 104                    ) files2 ON files1.id = files2.id
 105                ORDER BY files1.timemodified DESC";
 106          $params = array(
 107              'userid' => $USER->id,
 108              'filename' => '.',
 109              'filearea1' => 'draft',
 110              'itemid' => $itemid,
 111              'filearea2' => 'draft');
 112          if (isset($timelimitparam)) {
 113              $params = array_merge($params, $timelimitparam);
 114          }
 115          $rs = $DB->get_recordset_sql($sql, $params, $limitfrom, $limit);
 116          $result = array();
 117          foreach ($rs as $file_record) {
 118              $info = array();
 119              $info['contextid'] = $file_record->contextid;
 120              $info['itemid'] = $file_record->itemid;
 121              $info['filearea'] = $file_record->filearea;
 122              $info['component'] = $file_record->component;
 123              $info['filepath'] = $file_record->filepath;
 124              $info['filename'] = $file_record->filename;
 125              $result[$file_record->pathnamehash] = $info;
 126          }
 127          $rs->close();
 128          return $result;
 129      }
 130  
 131      /**
 132       * Get file listing
 133       *
 134       * @param string $encodedpath
 135       * @param string $path not used by this plugin
 136       * @return mixed
 137       */
 138      public function get_listing($encodedpath = '', $page = '') {
 139          global $OUTPUT;
 140          $ret = array();
 141          $ret['dynload'] = true;
 142          $ret['nosearch'] = true;
 143          $ret['nologin'] = true;
 144          $list = array();
 145          $files = $this->get_recent_files(0, $this->number, $this->timelimit);
 146  
 147          try {
 148              foreach ($files as $file) {
 149                  // Check that file exists and accessible, retrieve size/date info
 150                  $browser = get_file_browser();
 151                  $context = context::instance_by_id($file['contextid']);
 152                  $fileinfo = $browser->get_file_info($context, $file['component'],
 153                          $file['filearea'], $file['itemid'], $file['filepath'], $file['filename']);
 154                  if ($fileinfo) {
 155                      $params = base64_encode(json_encode($file));
 156                      $node = array(
 157                          'title' => $fileinfo->get_visible_name(),
 158                          'size' => $fileinfo->get_filesize(),
 159                          'datemodified' => $fileinfo->get_timemodified(),
 160                          'datecreated' => $fileinfo->get_timecreated(),
 161                          'author' => $fileinfo->get_author(),
 162                          'license' => $fileinfo->get_license(),
 163                          'source'=> $params,
 164                          'icon' => $OUTPUT->image_url(file_file_icon($fileinfo, 24))->out(false),
 165                          'thumbnail' => $OUTPUT->image_url(file_file_icon($fileinfo, 90))->out(false),
 166                      );
 167                      if ($imageinfo = $fileinfo->get_imageinfo()) {
 168                          $fileurl = new moodle_url($fileinfo->get_url());
 169                          $node['realthumbnail'] = $fileurl->out(false, array('preview' => 'thumb', 'oid' => $fileinfo->get_timemodified()));
 170                          $node['realicon'] = $fileurl->out(false, array('preview' => 'tinyicon', 'oid' => $fileinfo->get_timemodified()));
 171                          $node['image_width'] = $imageinfo['width'];
 172                          $node['image_height'] = $imageinfo['height'];
 173                      }
 174                      $list[] = $node;
 175                  }
 176              }
 177          } catch (Exception $e) {
 178              throw new repository_exception('emptyfilelist', 'repository_recent');
 179          }
 180          $ret['list'] = array_filter($list, array($this, 'filter'));
 181          return $ret;
 182      }
 183  
 184      public static function get_type_option_names() {
 185          return array('recentfilesnumber', 'recentfilestimelimit', 'pluginname');
 186      }
 187  
 188      public static function type_config_form($mform, $classname = 'repository') {
 189          parent::type_config_form($mform, $classname);
 190          $number = get_config('repository_recent', 'recentfilesnumber');
 191          if (empty($number)) {
 192              $number = DEFAULT_RECENT_FILES_NUM;
 193          }
 194          $mform->addElement('text', 'recentfilesnumber', get_string('recentfilesnumber', 'repository_recent'));
 195          $mform->setType('recentfilesnumber', PARAM_INT);
 196          $mform->setDefault('recentfilesnumber', $number);
 197  
 198          $mform->addElement('duration', 'recentfilestimelimit',
 199              get_string('timelimit', 'repository_recent'), ['units' => [DAYSECS, WEEKSECS], 'optional' => true]);
 200          $mform->addHelpButton('recentfilestimelimit', 'timelimit', 'repository_recent');
 201          $mform->setDefault('recentfilestimelimit', DEFAULT_RECENT_FILES_TIME_LIMIT);
 202      }
 203  
 204      /**
 205       * This plugin doesn't support to link to external links
 206       *
 207       * @return int
 208       */
 209      public function supported_returntypes() {
 210          return FILE_INTERNAL;
 211      }
 212  
 213      /**
 214       * Repository method to make sure that user can access particular file.
 215       *
 216       * This is checked when user tries to pick the file from repository to deal with
 217       * potential parameter substitutions is request
 218       *
 219       * @todo MDL-33805 remove this function when recent files are managed correctly
 220       *
 221       * @param string $source
 222       * @return bool whether the file is accessible by current user
 223       */
 224      public function file_is_accessible($source) {
 225          global $USER;
 226          $reference = $this->get_file_reference($source);
 227          $file = self::get_moodle_file($reference);
 228          return (!empty($file) && $file->get_userid() == $USER->id);
 229      }
 230  
 231      /**
 232       * Does this repository used to browse moodle files?
 233       *
 234       * @return boolean
 235       */
 236      public function has_moodle_files() {
 237          return true;
 238      }
 239  
 240      /**
 241       * Is this repository accessing private data?
 242       *
 243       * @return bool
 244       */
 245      public function contains_private_data() {
 246          return false;
 247      }
 248  }