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 310 and 401] [Versions 311 and 401] [Versions 39 and 401] [Versions 400 and 401]

   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  /**
  20   * This file is used to browse repositories in non-javascript mode
  21   *
  22   * @since Moodle 2.0
  23   * @package    core
  24   * @subpackage repository
  25   * @copyright  2009 Dongsheng Cai <dongsheng@moodle.com>
  26   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  27   */
  28  
  29  require_once('../config.php');
  30  require_once($CFG->libdir.'/filelib.php');
  31  require_once ('lib.php');
  32  /// Wait as long as it takes for this script to finish
  33  core_php_time_limit::raise();
  34  
  35  require_sesskey();
  36  require_login();
  37  
  38  // disable blocks in this page
  39  $PAGE->set_pagelayout('embedded');
  40  
  41  // general parameters
  42  $action      = optional_param('action', '',        PARAM_ALPHA);
  43  $client_id   = optional_param('client_id', '', PARAM_RAW);    // client ID
  44  $itemid      = optional_param('itemid', '',        PARAM_INT);
  45  
  46  // parameters for repository
  47  $callback    = optional_param('callback', '',      PARAM_CLEANHTML);
  48  $contextid   = optional_param('ctx_id',    SYSCONTEXTID, PARAM_INT);    // context ID
  49  $courseid    = optional_param('course',    SITEID, PARAM_INT);    // course ID
  50  $env         = optional_param('env', 'filepicker', PARAM_ALPHA);  // opened in file picker, file manager or html editor
  51  $filename    = optional_param('filename', '',      PARAM_FILE);
  52  $fileurl     = optional_param('fileurl', '',       PARAM_RAW);
  53  $thumbnail   = optional_param('thumbnail', '',     PARAM_RAW);
  54  $targetpath  = optional_param('targetpath', '',    PARAM_PATH);
  55  $repo_id     = optional_param('repo_id', 0,        PARAM_INT);    // repository ID
  56  $req_path    = optional_param('p', '',             PARAM_RAW);    // the path in repository
  57  $curr_page   = optional_param('page', '',          PARAM_RAW);    // What page in repository?
  58  $search_text = optional_param('s', '',             PARAM_CLEANHTML);
  59  $maxfiles    = optional_param('maxfiles', -1,      PARAM_INT);    // maxfiles
  60  $maxbytes    = optional_param('maxbytes',  0,      PARAM_INT);    // maxbytes
  61  $subdirs     = optional_param('subdirs',  0,       PARAM_INT);    // maxbytes
  62  $areamaxbytes   = optional_param('areamaxbytes', FILE_AREA_MAX_BYTES_UNLIMITED, PARAM_INT);    // Area maxbytes.
  63  $accepted_types = optional_param_array('accepted_types', '*', PARAM_RAW);
  64  
  65  // the path to save files
  66  $savepath = optional_param('savepath', '/',    PARAM_PATH);
  67  // path in draft area
  68  $draftpath = optional_param('draftpath', '/',    PARAM_PATH);
  69  
  70  
  71  // user context
  72  $user_context = context_user::instance($USER->id);
  73  
  74  $PAGE->set_context($user_context);
  75  if (!$course = $DB->get_record('course', array('id'=>$courseid))) {
  76      throw new \moodle_exception('invalidcourseid');
  77  }
  78  $PAGE->set_course($course);
  79  
  80  if ($repo_id) {
  81      // Get repository instance information
  82      $repooptions = array(
  83          'ajax' => false,
  84          'mimetypes' => $accepted_types
  85      );
  86      $repo = repository::get_repository_by_id($repo_id, $contextid, $repooptions);
  87  
  88      // Check permissions
  89      $repo->check_capability();
  90  }
  91  
  92  $context = context::instance_by_id($contextid);
  93  
  94  // Make sure maxbytes passed is within site filesize limits.
  95  $maxbytes = get_user_max_upload_file_size($context, $CFG->maxbytes, $course->maxbytes, $maxbytes);
  96  
  97  $params = array('ctx_id' => $contextid, 'itemid' => $itemid, 'env' => $env, 'course'=>$courseid, 'maxbytes'=>$maxbytes, 'areamaxbytes'=>$areamaxbytes, 'maxfiles'=>$maxfiles, 'subdirs'=>$subdirs, 'sesskey'=>sesskey());
  98  $params['action'] = 'browse';
  99  $params['draftpath'] = $draftpath;
 100  $home_url = new moodle_url('/repository/draftfiles_manager.php', $params);
 101  
 102  $params['savepath'] = $savepath;
 103  $params['repo_id'] = $repo_id;
 104  $url = new moodle_url("/repository/filepicker.php", $params);
 105  $PAGE->set_url('/repository/filepicker.php', $params);
 106  
 107  switch ($action) {
 108  case 'upload':
 109      // The uploaded file has been processed in plugin construct function
 110      // redirect to default page
 111      try {
 112          $repo->upload('', $maxbytes);
 113          redirect($home_url, get_string('uploadsucc','repository'));
 114      } catch (moodle_exception $e) {
 115          // inject target URL
 116          $e->link = $PAGE->url->out();
 117          echo $OUTPUT->header(); // hack: we need the embedded header here, standard error printing would not use it
 118          throw $e;
 119      }
 120      break;
 121  
 122  case 'search':
 123      echo '<div><a href="' . $home_url->out() . '">'.get_string('back', 'repository')."</a></div>";
 124      try {
 125          $search_result = $repo->search($search_text);
 126          $search_result['issearchresult'] = true;
 127          $search_result['repo_id'] = $repo_id;
 128  
 129          // TODO: need a better solution
 130          $purl = new moodle_url($url, array('search_paging' => 1, 'action' => 'search', 'repo_id' => $repo_id));
 131          $pagingbar = new paging_bar($search_result['total'], $search_result['page'] - 1, $search_result['perpage'], $purl, 'p');
 132          echo $OUTPUT->render($pagingbar);
 133  
 134          echo '<table>';
 135          foreach ($search_result['list'] as $item) {
 136              echo '<tr>';
 137              echo '<td>';
 138              $style = '';
 139              if (isset($item['thumbnail_height'])) {
 140                  $style .= 'max-height:'.$item['thumbnail_height'].'px;';
 141              }
 142              if (isset($item['thumbnail_width'])) {
 143                  $style .= 'max-width:'.$item['thumbnail_width'].'px;';
 144              }
 145              echo html_writer::empty_tag('img', array('src' => $item['thumbnail'], 'alt' => '', 'style' => $style));
 146              echo '</td><td>';
 147              if (!empty($item['url'])) {
 148                  echo html_writer::link($item['url'], s($item['title']), array('target'=>'_blank'));
 149              } else {
 150                  echo s($item['title']);
 151              }
 152              echo '</td>';
 153              echo '<td>';
 154              echo '<form method="post">';
 155              echo '<input type="hidden" name="fileurl" value="'.s($item['source']).'"/>';
 156              echo '<input type="hidden" name="action" value="confirm"/>';
 157              echo '<input type="hidden" name="filename" value="'.s($item['title']).'"/>';
 158              echo '<input type="hidden" name="thumbnail" value="'.s($item['thumbnail']).'"/>';
 159              echo '<input type="submit" value="'.s(get_string('select','repository')).'" />';
 160              echo '</form>';
 161              echo '</td>';
 162              echo '</tr>';
 163          }
 164          echo '</table>';
 165      } catch (repository_exception $e) {
 166      }
 167      break;
 168  
 169  case 'list':
 170  case 'sign':
 171      echo $OUTPUT->header();
 172  
 173      echo $OUTPUT->container_start();
 174      echo html_writer::link($url, get_string('back', 'repository'));
 175      echo $OUTPUT->container_end();
 176  
 177      if ($repo->check_login()) {
 178          $list = $repo->get_listing($req_path, $curr_page);
 179          $dynload = !empty($list['dynload'])?true:false;
 180          if (!empty($list['upload'])) {
 181              echo '<form action="'.$url->out().'" method="post" enctype="multipart/form-data" style="display:inline">';
 182              echo '<label>'.$list['upload']['label'].': </label>';
 183              echo '<input type="file" name="repo_upload_file" /><br />';
 184              echo '<input type="hidden" name="action" value="upload" /><br />';
 185              echo '<input type="hidden" name="draftpath" value="'.s($draftpath).'" /><br />';
 186              echo '<input type="hidden" name="savepath" value="'.s($savepath).'" /><br />';
 187              echo '<input type="hidden" name="repo_id" value="'.s($repo_id).'" /><br />';
 188              echo '<input type="submit" value="'.s(get_string('upload', 'repository')).'" />';
 189              echo '</form>';
 190          } else {
 191              if (!empty($list['path'])) {
 192                  foreach ($list['path'] as $p) {
 193                      //echo '<form method="post" style="display:inline">';
 194                      //echo '<input type="hidden" name="p" value="'.s($p['path']).'"';
 195                      //echo '<input type="hidden" name="action" value="list"';
 196                      //echo '<input type="hidden" name="draftpath" value="'.s($draftpath).'" /><br />';
 197                      //echo '<input type="hidden" name="savepath" value="'.s($savepath).'" /><br />';
 198                      //echo '<input style="display:inline" type="submit" value="'.s($p['name']).'" />';
 199                      //echo '</form>';
 200  
 201                      $pathurl = new moodle_url($url, array(
 202                          'p'=>$p['path'],
 203                          'action'=>'list',
 204                          'draftpath'=>$draftpath,
 205                          'savepath'=>$savepath
 206                          ));
 207                      echo '<strong>' . html_writer::link($pathurl, s($p['name'])) . '</strong>';
 208                      echo '<span> / </span>';
 209                  }
 210              }
 211              if (!empty($list['page'])) {
 212                  // TODO MDL-28482: need a better solution
 213                  // paging_bar is not a good option because it starts page numbering from 0 and
 214                  // repositories number pages starting from 1.
 215                  $pagingurl = new moodle_url("/repository/filepicker.php?action=list&itemid=$itemid&ctx_id=$contextid&repo_id=$repo_id&course=$courseid&sesskey=".  sesskey());
 216                  if (!isset($list['perpage']) && !isset($list['total'])) {
 217                      $list['perpage'] = 10; // instead of setting perpage&total we use number of pages, the result is the same
 218                  }
 219                  if (empty($list['total'])) {
 220                      if ($list['pages'] == -1) {
 221                          $total = ($list['page'] + 2) * $list['perpage'];
 222                      } else {
 223                          $total = $list['pages'] * $list['perpage'];
 224                      }
 225                  } else {
 226                      $total = $list['total'];
 227                  }
 228                  echo $OUTPUT->paging_bar($total, $list['page'], $list['perpage'], $pagingurl);
 229              }
 230              echo '<table>';
 231              foreach ($list['list'] as $item) {
 232                  echo '<tr>';
 233                  echo '<td>';
 234                  $style = '';
 235                  if (isset($item['thumbnail_height'])) {
 236                      $style .= 'max-height:'.$item['thumbnail_height'].'px;';
 237                  }
 238                  if (isset($item['thumbnail_width'])) {
 239                      $style .= 'max-width:'.$item['thumbnail_width'].'px;';
 240                  }
 241                  echo html_writer::empty_tag('img', array('src' => $item['thumbnail'], 'style' => $style));
 242                  echo '</td><td>';
 243                  if (!empty($item['url'])) {
 244                      echo html_writer::link($item['url'], s($item['title']), array('target'=>'_blank'));
 245                  } else {
 246                      echo s($item['title']);
 247                  }
 248                  echo '</td>';
 249                  echo '<td>';
 250                  if (!isset($item['children'])) {
 251                      echo '<form method="post">';
 252                      echo '<input type="hidden" name="fileurl" value="'.s($item['source']).'"/>';
 253                      echo '<input type="hidden" name="action" value="confirm"/>';
 254                      echo '<input type="hidden" name="draftpath" value="'.s($draftpath).'" /><br />';
 255                      echo '<input type="hidden" name="savepath" value="'.s($savepath).'" /><br />';
 256                      echo '<input type="hidden" name="filename" value="'.s($item['title']).'"/>';
 257                      echo '<input type="hidden" name="thumbnail" value="'.s($item['thumbnail']).'"/>';
 258                      echo '<input type="submit" value="'.s(get_string('select','repository')).'" />';
 259                      echo '</form>';
 260                  } else {
 261                      echo '<form method="post">';
 262                      echo '<input type="hidden" name="p" value="'.s($item['path']).'"/>';
 263                      echo '<input type="submit" value="'.s(get_string('enter', 'repository')).'" />';
 264                      echo '</form>';
 265                  }
 266                  echo '</td>';
 267                  echo '</tr>';
 268              }
 269              echo '</table>';
 270          }
 271      } else {
 272          echo '<form method="post">';
 273          echo '<input type="hidden" name="action" value="sign" />';
 274          echo '<input type="hidden" name="repo_id" value="'.s($repo_id).'" />';
 275          $repo->print_login();
 276          echo '</form>';
 277      }
 278      echo $OUTPUT->footer();
 279      break;
 280  
 281  case 'download':
 282      // Check that user has permission to access this file
 283      if (!$repo->file_is_accessible($fileurl)) {
 284          throw new \moodle_exception('storedfilecannotread');
 285      }
 286      $record = new stdClass();
 287      $reference = $repo->get_file_reference($fileurl);
 288  
 289      $sourcefield = $repo->get_file_source_info($fileurl);
 290      $record->source = repository::build_source_field($sourcefield);
 291  
 292      // If file is already a reference, set $fileurl = file source, $repo = file repository
 293      // note that in this case user may not have permission to access the source file directly
 294      // so no file_browser/file_info can be used below
 295      if ($repo->has_moodle_files()) {
 296          $file = repository::get_moodle_file($reference);
 297          if ($file && $file->is_external_file()) {
 298              $sourcefield = $file->get_source(); // remember the original source
 299              $record->source = $repo::build_source_field($sourcefield);
 300              $reference = $file->get_reference();
 301              $repo_id = $file->get_repository_id();
 302              $repo = repository::get_repository_by_id($repo_id, $contextid, $repooptions);
 303          }
 304      }
 305  
 306      $record->filepath = $savepath;
 307      $record->filename = $filename;
 308      $record->component = 'user';
 309      $record->filearea = 'draft';
 310      $record->itemid   = $itemid;
 311      $record->license  = '';
 312      $record->author   = '';
 313  
 314      $now = time();
 315      $record->timecreated  = $now;
 316      $record->timemodified = $now;
 317      $record->userid       = $USER->id;
 318      $record->contextid = $user_context->id;
 319      $record->sortorder = 0;
 320  
 321      if ($repo->has_moodle_files()) {
 322          $fileinfo = $repo->copy_to_area($reference, $record, $maxbytes, $areamaxbytes);
 323          redirect($home_url, get_string('downloadsucc', 'repository'));
 324      } else {
 325          $thefile = $repo->get_file($reference, $filename);
 326          if (!empty($thefile['path'])) {
 327              $filesize = filesize($thefile['path']);
 328              if ($maxbytes != -1 && $filesize>$maxbytes) {
 329                  unlink($thefile['path']);
 330                  throw new \moodle_exception('maxbytes');
 331              }
 332              // Ensure the file will not make the area exceed its size limit.
 333              if (file_is_draft_area_limit_reached($record->itemid, $areamaxbytes, $filesize)) {
 334                  unlink($thefile['path']);
 335                  throw new \moodle_exception('maxareabytes');
 336              }
 337              // Ensure the user does not upload too many draft files in a short period.
 338              if (file_is_draft_areas_limit_reached($USER->id)) {
 339                  unlink($thefile['path']);
 340                  throw new \moodle_exception('maxdraftitemids');
 341              }
 342              try {
 343                  $info = repository::move_to_filepool($thefile['path'], $record);
 344                  redirect($home_url, get_string('downloadsucc', 'repository'));
 345              } catch (moodle_exception $e) {
 346                  // inject target URL
 347                  $e->link = $PAGE->url->out();
 348                  echo $OUTPUT->header(); // hack: we need the embedded header here, standard error printing would not use it
 349                  throw $e;
 350              }
 351          } else {
 352              throw new \moodle_exception('cannotdownload', 'repository');
 353          }
 354      }
 355  
 356      break;
 357  
 358  case 'confirm':
 359      echo $OUTPUT->header();
 360      echo '<div><a href="'.s($PAGE->url->out(false)).'">'.get_string('back', 'repository').'</a></div>';
 361      echo '<img src="'.$thumbnail.'" />';
 362      echo '<form method="post">';
 363      echo '<table>';
 364      echo '  <tr>';
 365      echo '    <td>'. html_writer::label(get_string('filename', 'repository'), 'filename'). '</td>';
 366      echo '    <td><input type="text" id="filename" name="filename" value="'.s($filename).'" /></td>';
 367      echo '    <td><input type="hidden" name="fileurl" value="'.s($fileurl).'" /></td>';
 368      echo '    <td><input type="hidden" name="action" value="download" /></td>';
 369      echo '    <td><input type="hidden" name="itemid" value="'.s($itemid).'" /></td>';
 370      echo '  </tr>';
 371      echo '</table>';
 372      echo '<div>';
 373      // the save path
 374      echo ' <input name="draftpath" type="hidden" value="'.s($draftpath).'" />';
 375      echo ' <input name="savepath" type="hidden" value="'.s($savepath).'" />';
 376      echo ' <input type="submit" value="'.s(get_string('download', 'repository')).'" />';
 377      echo '</div>';
 378      echo '</form>';
 379      echo $OUTPUT->footer();
 380      break;
 381  
 382  default:
 383  case 'plugins':
 384      $params = array();
 385      $params['context'] = array($user_context, context_system::instance());
 386      $params['currentcontext'] = $PAGE->context;
 387      $params['return_types'] = FILE_INTERNAL;
 388  
 389      $repos = repository::get_instances($params);
 390      echo $OUTPUT->header();
 391      echo html_writer::link($home_url->out(false), get_string('backtodraftfiles', 'repository'));
 392      echo '<div>';
 393      echo '<ul>';
 394      foreach($repos as $repo) {
 395          $info = $repo->get_meta();
 396  
 397          $aurl = clone($url);
 398          $aurl->params(array('savepath'=>$savepath, 'action' => 'list', 'repo_id' => $info->id, 'draftpath'=>$draftpath));
 399  
 400          echo '<li>';
 401          echo html_writer::empty_tag('img', array('src'=>$info->icon, 'alt'=>$info->name, 'class'=>'icon icon-pre'));
 402          echo html_writer::link($aurl, s($info->name));
 403          echo '</li>';
 404      }
 405      echo '</ul>';
 406      echo '</div>';
 407      echo $OUTPUT->footer();
 408      break;
 409  }