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.
   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   * Utility class for browsing of files.
  20   *
  21   * @package   core_files
  22   * @copyright 2008 Petr Skoda (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->libdir/filebrowser/file_info.php");
  29  
  30  // general area types
  31  require_once("$CFG->libdir/filebrowser/file_info_stored.php");
  32  require_once("$CFG->libdir/filebrowser/virtual_root_file.php");
  33  
  34  // description of available areas in each context level
  35  require_once("$CFG->libdir/filebrowser/file_info_context_system.php");
  36  require_once("$CFG->libdir/filebrowser/file_info_context_user.php");
  37  require_once("$CFG->libdir/filebrowser/file_info_context_coursecat.php");
  38  require_once("$CFG->libdir/filebrowser/file_info_context_course.php");
  39  require_once("$CFG->libdir/filebrowser/file_info_context_module.php");
  40  
  41  /**
  42   * This class provides the main entry point for other code wishing to get information about files.
  43   *
  44   * The whole file storage for a Moodle site can be seen as a huge virtual tree.
  45   * The spine of the tree is the tree of contexts (system, course-categories,
  46   * courses, modules, also users). Then, within each context, there may be any number of
  47   * file areas, and a file area contains folders and files. The various file_info
  48   * subclasses return info about the things in this tree. They should be obtained
  49   * from an instance of this class.
  50   *
  51   * This virtual tree is different for each user depending of his/her current permissions.
  52   * Some branches such as draft areas are hidden, but accessible.
  53   *
  54   * Always use this abstraction when you need to access module files from core code.
  55    *
  56   * @package   core_files
  57   * @category  files
  58   * @copyright 2008 Petr Skoda (http://skodak.org)
  59   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  60  */
  61  class file_browser {
  62  
  63      /** @var array cached list of enrolled courses.  */
  64      protected $enrolledcourses = null;
  65  
  66      /**
  67       * Looks up file_info instance
  68       *
  69       * @param stdClass $context context object
  70       * @param string $component component
  71       * @param string $filearea file area
  72       * @param int $itemid item ID
  73       * @param string $filepath file path
  74       * @param string $filename file name
  75       * @return file_info|null file_info instance or null if not found or access not allowed
  76       */
  77      public function get_file_info($context = NULL, $component = NULL, $filearea = NULL, $itemid = NULL, $filepath = NULL, $filename = NULL) {
  78          if (!$context) {
  79              $context = context_system::instance();
  80          }
  81          switch ($context->contextlevel) {
  82              case CONTEXT_SYSTEM:
  83                  return $this->get_file_info_context_system($context, $component, $filearea, $itemid, $filepath, $filename);
  84              case CONTEXT_USER:
  85                  return $this->get_file_info_context_user($context, $component, $filearea, $itemid, $filepath, $filename);
  86              case CONTEXT_COURSECAT:
  87                  return $this->get_file_info_context_coursecat($context, $component, $filearea, $itemid, $filepath, $filename);
  88              case CONTEXT_COURSE:
  89                  return $this->get_file_info_context_course($context, $component, $filearea, $itemid, $filepath, $filename);
  90              case CONTEXT_MODULE:
  91                  return $this->get_file_info_context_module($context, $component, $filearea, $itemid, $filepath, $filename);
  92          }
  93  
  94          return null;
  95      }
  96  
  97      /**
  98       * Returns info about the files at System context
  99       * @todo MDL-33372 - Provide a way of displaying recent files for blog entries.
 100       *
 101       * @param object $context context object
 102       * @param string $component component
 103       * @param string $filearea file area
 104       * @param int $itemid item ID
 105       * @param string $filepath file path
 106       * @param string $filename file name
 107       * @return file_info instance or null if not found or access not allowed
 108       */
 109      private function get_file_info_context_system($context, $component, $filearea, $itemid, $filepath, $filename) {
 110          $level = new file_info_context_system($this, $context);
 111          return $level->get_file_info($component, $filearea, $itemid, $filepath, $filename);
 112          // nothing supported at this context yet
 113      }
 114  
 115      /**
 116       * Returns info about the files at User context
 117       *
 118       * @param stdClass $context context object
 119       * @param string $component component
 120       * @param string $filearea file area
 121       * @param int $itemid item ID
 122       * @param string $filepath file path
 123       * @param string $filename file name
 124       * @return file_info|null file_info instance or null if not found or access not allowed
 125       */
 126      private function get_file_info_context_user($context, $component, $filearea, $itemid, $filepath, $filename) {
 127          global $DB, $USER;
 128          if ($context->instanceid == $USER->id) {
 129              $user = $USER;
 130          } else {
 131              $user = $DB->get_record('user', array('id'=>$context->instanceid));
 132          }
 133  
 134          if (isguestuser($user)) {
 135              // guests do not have any files
 136              return null;
 137          }
 138  
 139          if ($user->deleted) {
 140              return null;
 141          }
 142  
 143          $level = new file_info_context_user($this, $context, $user);
 144          return $level->get_file_info($component, $filearea, $itemid, $filepath, $filename);
 145      }
 146  
 147      /**
 148       * Returns info about the files at Course category context
 149       *
 150       * @param stdClass $context context object
 151       * @param string $component component
 152       * @param string $filearea file area
 153       * @param int $itemid item ID
 154       * @param string $filepath file path
 155       * @param string $filename file name
 156       * @return file_info|null file_info instance or null if not found or access not allowed
 157       */
 158      private function get_file_info_context_coursecat($context, $component, $filearea, $itemid, $filepath, $filename) {
 159          global $DB;
 160  
 161          if (!$category = $DB->get_record('course_categories', array('id'=>$context->instanceid))) {
 162              return null;
 163          }
 164  
 165          $level = new file_info_context_coursecat($this, $context, $category);
 166          return $level->get_file_info($component, $filearea, $itemid, $filepath, $filename);
 167      }
 168  
 169      /**
 170       * Returns info about the files at Course category context
 171       *
 172       * @param stdClass $context context object
 173       * @param string $component component
 174       * @param string $filearea file area
 175       * @param int $itemid item ID
 176       * @param string $filepath file path
 177       * @param string $filename file name
 178       * @return file_info|null file_info instance or null if not found or access not allowed
 179       */
 180      private function get_file_info_context_course($context, $component, $filearea, $itemid, $filepath, $filename) {
 181          global $DB, $COURSE;
 182  
 183          if ($context->instanceid == $COURSE->id) {
 184              $course = $COURSE;
 185          } else if (!$course = $DB->get_record('course', array('id'=>$context->instanceid))) {
 186              return null;
 187          }
 188  
 189          $level = new file_info_context_course($this, $context, $course);
 190          return $level->get_file_info($component, $filearea, $itemid, $filepath, $filename);
 191      }
 192  
 193      /**
 194       * Returns info about the files at Course category context
 195       *
 196       * @param context $context context object
 197       * @param string $component component
 198       * @param string $filearea file area
 199       * @param int $itemid item ID
 200       * @param string $filepath file path
 201       * @param string $filename file name
 202       * @return file_info|null file_info instance or null if not found or access not allowed
 203       */
 204      private function get_file_info_context_module($context, $component, $filearea, $itemid, $filepath, $filename) {
 205          if (!($context instanceof context_module)) {
 206              return null;
 207          }
 208          $coursecontext = $context->get_course_context();
 209          $modinfo = get_fast_modinfo($coursecontext->instanceid);
 210          $cm = $modinfo->get_cm($context->instanceid);
 211  
 212          if (empty($cm->uservisible)) {
 213              return null;
 214          }
 215  
 216          $level = new file_info_context_module($this, $context, $cm->get_course(), $cm, $cm->modname);
 217          return $level->get_file_info($component, $filearea, $itemid, $filepath, $filename);
 218      }
 219  
 220      /**
 221       * Check if user is enrolled into the course
 222       *
 223       * This function keeps a cache of enrolled courses because it may be called multiple times for many courses in one request
 224       *
 225       * @param int $courseid
 226       * @return bool
 227       */
 228      public function is_enrolled($courseid) {
 229          if ($this->enrolledcourses === null || PHPUNIT_TEST) {
 230              // Since get_file_browser() returns a statically cached object we can't rely on cache
 231              // inside the file_browser class in the unittests.
 232              // TODO MDL-59964 remove this caching when it's implemented inside enrol_get_my_courses().
 233              $this->enrolledcourses = enrol_get_my_courses(['id']);
 234          }
 235          return array_key_exists($courseid, $this->enrolledcourses);
 236      }
 237  }