Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.11.x will end 14 Nov 2022 (12 months plus 6 months extension).
  • Bug fixes for security issues in 3.11.x will end 13 Nov 2023 (18 months plus 12 months extension).
  • PHP version: minimum PHP 7.3.0 Note: minimum PHP version has increased since Moodle 3.10. PHP 7.4.x is supported too.
   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   * Provides code used during file browsing
  20   *
  21   * @category  files
  22   * @package   mod_workshop
  23   * @copyright 2009 David Mudrak <david.mudrak@gmail.com>
  24   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  25   */
  26  
  27  defined('MOODLE_INTERNAL') || die();
  28  
  29  /**
  30   * Represents virtual root node for all submissions
  31   *
  32   * Workshop submission uses two fileareas: submission_content for editor's embeded media
  33   * and submission_attachment for attachments. In both, the itemid represents the submission id.
  34   * This container is used to display the list of all submissions in these areas (ie when
  35   * these areas are browsed with itemid == null).
  36   */
  37  class workshop_file_info_submissions_container extends file_info {
  38      protected $course;
  39      protected $cm;
  40      protected $areas;
  41      protected $filearea;
  42  
  43      public function __construct($browser, $course, $cm, $context, $areas, $filearea) {
  44          parent::__construct($browser, $context);
  45          $this->course   = $course;
  46          $this->cm       = $cm;
  47          $this->areas    = $areas;
  48          $this->filearea = $filearea;
  49      }
  50  
  51      /**
  52       * Returns list of standard virtual file/directory identification.
  53       * The difference from stored_file parameters is that null values
  54       * are allowed in all fields
  55       * @return array with keys contextid, filearea, itemid, filepath and filename
  56       */
  57      public function get_params() {
  58          return array('contextid'=>$this->context->id,
  59                       'component'=>'mod_workshop',
  60                       'filearea' =>$this->filearea,
  61                       'itemid'   =>null,
  62                       'filepath' =>null,
  63                       'filename' =>null);
  64      }
  65  
  66      /**
  67       * Returns localised visible name.
  68       * @return string
  69       */
  70      public function get_visible_name() {
  71          return $this->areas[$this->filearea];
  72      }
  73  
  74      /**
  75       * Can I add new files or directories?
  76       * @return bool
  77       */
  78      public function is_writable() {
  79          return false;
  80      }
  81  
  82      /**
  83       * Is directory?
  84       * @return bool
  85       */
  86      public function is_directory() {
  87          return true;
  88      }
  89  
  90  
  91      /**
  92       * Returns list of children nodes
  93       *
  94       * @return array of file_info instances
  95       */
  96      public function get_children() {
  97          return $this->get_filtered_children('*', false, true);
  98      }
  99  
 100      /**
 101       * Helper function to return files matching extensions or their count
 102       *
 103       * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
 104       * @param bool|int $countonly if false returns the children, if an int returns just the
 105       *    count of children but stops counting when $countonly number of children is reached
 106       * @param bool $returnemptyfolders if true returns items that don't have matching files inside
 107       * @return array|int array of file_info instances or the count
 108       */
 109      private function get_filtered_children($extensions = '*', $countonly = false, $returnemptyfolders = false) {
 110          global $DB;
 111          $params = array('contextid' => $this->context->id,
 112              'component' => 'mod_workshop',
 113              'filearea' => $this->filearea);
 114          $sql = 'SELECT DISTINCT itemid
 115                      FROM {files}
 116                      WHERE contextid = :contextid
 117                      AND component = :component
 118                      AND filearea = :filearea';
 119          if (!$returnemptyfolders) {
 120              $sql .= ' AND filename <> :emptyfilename';
 121              $params['emptyfilename'] = '.';
 122          }
 123          list($sql2, $params2) = $this->build_search_files_sql($extensions);
 124          $sql .= ' '.$sql2;
 125          $params = array_merge($params, $params2);
 126          if ($countonly !== false) {
 127              $sql .= ' ORDER BY itemid DESC';
 128          }
 129  
 130          $rs = $DB->get_recordset_sql($sql, $params);
 131          $children = array();
 132          foreach ($rs as $record) {
 133              if (($child = $this->browser->get_file_info($this->context, 'mod_workshop', $this->filearea, $record->itemid))
 134                      && ($returnemptyfolders || $child->count_non_empty_children($extensions))) {
 135                  $children[] = $child;
 136                  if ($countonly !== false && count($children) >= $countonly) {
 137                      break;
 138                  }
 139              }
 140          }
 141          $rs->close();
 142          if ($countonly !== false) {
 143              return count($children);
 144          }
 145          return $children;
 146      }
 147  
 148      /**
 149       * Returns list of children which are either files matching the specified extensions
 150       * or folders that contain at least one such file.
 151       *
 152       * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
 153       * @return array of file_info instances
 154       */
 155      public function get_non_empty_children($extensions = '*') {
 156          return $this->get_filtered_children($extensions, false);
 157      }
 158  
 159      /**
 160       * Returns the number of children which are either files matching the specified extensions
 161       * or folders containing at least one such file.
 162       *
 163       * NOTE: We don't need the exact number of non empty children if it is >=2
 164       * In this function 1 is never returned to avoid skipping the single subfolder
 165       *
 166       * @param string|array $extensions, for example '*' or array('.gif','.jpg')
 167       * @param int $limit stop counting after at least $limit non-empty children are found
 168       * @return int
 169       */
 170      public function count_non_empty_children($extensions = '*', $limit = 1) {
 171          return $this->get_filtered_children($extensions, $limit);
 172      }
 173  
 174      /**
 175       * Returns parent file_info instance
 176       * @return file_info or null for root
 177       */
 178      public function get_parent() {
 179          return $this->browser->get_file_info($this->context);
 180      }
 181  }
 182  
 183  
 184  /**
 185   * Represents virtual root node for all files in overall feedbacks
 186   *
 187   * Overall feedback uses two fileareas: overallfeedback_content for editor's embeded media
 188   * and overallfeedback_attachment for attachments. In both, the itemid represents the assessment id.
 189   * This container is used to display the list of all submissions in these areas (ie when
 190   * these areas are browsed with itemid == null).
 191   */
 192  class workshop_file_info_overallfeedback_container extends file_info {
 193      protected $course;
 194      protected $cm;
 195      protected $areas;
 196      protected $filearea;
 197  
 198      public function __construct($browser, $course, $cm, $context, $areas, $filearea) {
 199          parent::__construct($browser, $context);
 200          $this->course   = $course;
 201          $this->cm       = $cm;
 202          $this->areas    = $areas;
 203          $this->filearea = $filearea;
 204      }
 205  
 206      /**
 207       * Returns list of standard virtual file/directory identification
 208       *
 209       * The difference from stored_file parameters is that null values
 210       * are allowed in all fields.
 211       *
 212       * @return array with keys contextid, filearea, itemid, filepath and filename
 213       */
 214      public function get_params() {
 215          return array('contextid' => $this->context->id,
 216                       'component' => 'mod_workshop',
 217                       'filearea' => $this->filearea,
 218                       'itemid' => null,
 219                       'filepath' => null,
 220                       'filename' => null);
 221      }
 222  
 223      /**
 224       * Returns localised visible name
 225       *
 226       * @return string
 227       */
 228      public function get_visible_name() {
 229          return $this->areas[$this->filearea];
 230      }
 231  
 232      /**
 233       * Can I add new files or directories?
 234       *
 235       * @return bool
 236       */
 237      public function is_writable() {
 238          return false;
 239      }
 240  
 241      /**
 242       * Is directory?
 243       *
 244       * @return bool
 245       */
 246      public function is_directory() {
 247          return true;
 248      }
 249  
 250  
 251      /**
 252       * Returns list of children nodes
 253       *
 254       * @return array of file_info instances
 255       */
 256      public function get_children() {
 257          return $this->get_filtered_children('*', false, true);
 258      }
 259  
 260      /**
 261       * Helper function to return files matching extensions or their count
 262       *
 263       * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
 264       * @param bool|int $countonly if false returns the children, if an int returns just the
 265       *    count of children but stops counting when $countonly number of children is reached
 266       * @param bool $returnemptyfolders if true returns items that don't have matching files inside
 267       * @return array|int array of file_info instances or the count
 268       */
 269      private function get_filtered_children($extensions = '*', $countonly = false, $returnemptyfolders = false) {
 270          global $DB;
 271  
 272          $params = array('contextid' => $this->context->id,
 273              'component' => 'mod_workshop',
 274              'filearea' => $this->filearea);
 275          $sql = "SELECT DISTINCT itemid
 276                    FROM {files}
 277                   WHERE contextid = :contextid
 278                         AND component = :component
 279                         AND filearea = :filearea";
 280          if (!$returnemptyfolders) {
 281              $sql .= " AND filename <> :emptyfilename";
 282              $params['emptyfilename'] = '.';
 283          }
 284          list($sql2, $params2) = $this->build_search_files_sql($extensions);
 285          $sql .= ' '.$sql2;
 286          $params = array_merge($params, $params2);
 287          if ($countonly !== false) {
 288              $sql .= " ORDER BY itemid DESC";
 289          }
 290  
 291          $rs = $DB->get_recordset_sql($sql, $params);
 292          $children = array();
 293          foreach ($rs as $record) {
 294              if (($child = $this->browser->get_file_info($this->context, 'mod_workshop', $this->filearea, $record->itemid))
 295                      && ($returnemptyfolders || $child->count_non_empty_children($extensions))) {
 296                  $children[] = $child;
 297                  if ($countonly !== false && count($children) >= $countonly) {
 298                      break;
 299                  }
 300              }
 301          }
 302          $rs->close();
 303          if ($countonly !== false) {
 304              return count($children);
 305          }
 306          return $children;
 307      }
 308  
 309      /**
 310       * Returns list of children which are either files matching the specified extensions
 311       * or folders that contain at least one such file.
 312       *
 313       * @param string|array $extensions, either '*' or array of lowercase extensions, i.e. array('.gif','.jpg')
 314       * @return array of file_info instances
 315       */
 316      public function get_non_empty_children($extensions = '*') {
 317          return $this->get_filtered_children($extensions, false);
 318      }
 319  
 320      /**
 321       * Returns the number of children which are either files matching the specified extensions
 322       * or folders containing at least one such file.
 323       *
 324       * NOTE: We don't need the exact number of non empty children if it is >=2
 325       * In this function 1 is never returned to avoid skipping the single subfolder
 326       *
 327       * @param string|array $extensions, for example '*' or array('.gif','.jpg')
 328       * @param int $limit stop counting after at least $limit non-empty children are found
 329       * @return int
 330       */
 331      public function count_non_empty_children($extensions = '*', $limit = 1) {
 332          return $this->get_filtered_children($extensions, $limit);
 333      }
 334  
 335      /**
 336       * Returns parent file_info instance
 337       * @return file_info or null for root
 338       */
 339      public function get_parent() {
 340          return $this->browser->get_file_info($this->context);
 341      }
 342  }