Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.2.x will end 22 April 2024 (12 months).
  • Bug fixes for security issues in 4.2.x will end 7 October 2024 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.1.x is supported too.
/files/ -> renderer.php (source)

Differences Between: [Versions 310 and 402] [Versions 311 and 402] [Versions 39 and 402] [Versions 400 and 402] [Versions 401 and 402] [Versions 402 and 403]

   1  <?php
   2  ///////////////////////////////////////////////////////////////////////////
   3  //                                                                       //
   4  // This file is part of Moodle - http://moodle.org/                      //
   5  // Moodle - Modular Object-Oriented Dynamic Learning Environment         //
   6  //                                                                       //
   7  // Moodle is free software: you can redistribute it and/or modify        //
   8  // it under the terms of the GNU General Public License as published by  //
   9  // the Free Software Foundation, either version 3 of the License, or     //
  10  // (at your option) any later version.                                   //
  11  //                                                                       //
  12  // Moodle is distributed in the hope that it will be useful,             //
  13  // but WITHOUT ANY WARRANTY; without even the implied warranty of        //
  14  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         //
  15  // GNU General Public License for more details.                          //
  16  //                                                                       //
  17  // You should have received a copy of the GNU General Public License     //
  18  // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.       //
  19  //                                                                       //
  20  ///////////////////////////////////////////////////////////////////////////
  21  
  22  defined('MOODLE_INTERNAL') || die();
  23  
  24  /**
  25   * Rendering of files viewer related widgets.
  26   * @package   core
  27   * @subpackage file
  28   * @copyright 2010 Dongsheng Cai
  29   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  30   * @since     Moodle 2.0
  31   */
  32  
  33  /**
  34   * File browser render
  35   *
  36   * @copyright 2010 Dongsheng Cai
  37   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  38   * @since     Moodle 2.0
  39   */
  40  class core_files_renderer extends plugin_renderer_base {
  41  
  42      public function files_tree_viewer(file_info $file_info, array $options = null) {
  43          $tree = new files_tree_viewer($file_info, $options);
  44          return $this->render($tree);
  45      }
  46  
  47      public function render_files_tree_viewer(files_tree_viewer $tree) {
  48          $html = $this->output->heading_with_help(get_string('coursefiles'), 'courselegacyfiles', 'moodle');
  49  
  50          $html .= $this->output->container_start('coursefilesbreadcrumb');
  51          foreach($tree->path as $path) {
  52              $html .= $path;
  53              $html .= ' / ';
  54          }
  55          $html .= $this->output->container_end();
  56  
  57          $html .= $this->output->box_start();
  58          $table = new html_table();
  59          $table->head = array(get_string('name'), get_string('lastmodified'), get_string('size', 'repository'), get_string('type', 'repository'));
  60          $table->align = array('left', 'left', 'left', 'left');
  61          $table->width = '100%';
  62          $table->data = array();
  63  
  64          foreach ($tree->tree as $file) {
  65              $filedate = $filesize = $filetype = '';
  66              if ($file['filedate']) {
  67                  $filedate = userdate($file['filedate'], get_string('strftimedatetimeshort', 'langconfig'));
  68              }
  69              if (empty($file['isdir'])) {
  70                  if ($file['filesize']) {
  71                      $filesize = display_size($file['filesize']);
  72                  }
  73                  $fileicon = file_file_icon($file, 24);
  74                  $filetype = get_mimetype_description($file);
  75              } else {
  76                  $fileicon = file_folder_icon(24);
  77              }
  78              $table->data[] = array(
  79                  html_writer::link($file['url'], $this->output->pix_icon($fileicon, get_string('icon')) . ' ' . $file['filename']),
  80                  $filedate,
  81                  $filesize,
  82                  $filetype
  83                  );
  84          }
  85  
  86          $html .= html_writer::table($table);
  87          $html .= $this->output->single_button(new moodle_url('/files/coursefilesedit.php', array('contextid'=>$tree->context->id)), get_string('coursefilesedit'), 'get');
  88          $html .= $this->output->box_end();
  89          return $html;
  90      }
  91  
  92      /**
  93       * Prints the file manager and initializes all necessary libraries
  94       *
  95       * <pre>
  96       * $fm = new form_filemanager($options);
  97       * $output = get_renderer('core', 'files');
  98       * echo $output->render($fm);
  99       * </pre>
 100       *
 101       * @param form_filemanager $fm File manager to render
 102       * @return string HTML fragment
 103       */
 104      public function render_form_filemanager($fm) {
 105          $html = $this->fm_print_generallayout($fm);
 106          $module = array(
 107              'name'=>'form_filemanager',
 108              'fullpath'=>'/lib/form/filemanager.js',
 109              'requires' => array('moodle-core-notification-dialogue', 'core_filepicker', 'base', 'io-base', 'node', 'json', 'core_dndupload', 'panel', 'resize-plugin', 'dd-plugin'),
 110              'strings' => array(
 111                  array('error', 'moodle'), array('info', 'moodle'), array('confirmdeletefile', 'repository'),
 112                  array('draftareanofiles', 'repository'), array('entername', 'repository'), array('enternewname', 'repository'),
 113                  array('invalidjson', 'repository'), array('popupblockeddownload', 'repository'),
 114                  array('unknownoriginal', 'repository'), array('confirmdeletefolder', 'repository'),
 115                  array('confirmdeletefilewithhref', 'repository'), array('confirmrenamefolder', 'repository'),
 116                  array('confirmrenamefile', 'repository'), array('newfolder', 'repository'), array('edit', 'moodle'),
 117                  array('originalextensionchange', 'repository'), array('originalextensionremove', 'repository'),
 118                  array('aliaseschange', 'repository'), ['nofilesselected', 'repository'],
 119                  ['confirmdeleteselectedfile', 'repository'], ['selectall', 'moodle'], ['deselectall', 'moodle'],
 120                  ['selectallornone', 'form'],
 121              )
 122          );
 123          if ($this->page->requires->should_create_one_time_item_now('core_file_managertemplate')) {
 124              $this->page->requires->js_init_call('M.form_filemanager.set_templates',
 125                      array($this->filemanager_js_templates()), true, $module);
 126          }
 127          $this->page->requires->js_call_amd('core/checkbox-toggleall', 'init');
 128          $this->page->requires->js_init_call('M.form_filemanager.init', array($fm->options), true, $module);
 129  
 130          // non javascript file manager
 131          $html .= '<noscript>';
 132          $html .= "<div><object type='text/html' data='".$fm->get_nonjsurl()."' height='160' width='600' style='border:1px solid #000'></object></div>";
 133          $html .= '</noscript>';
 134  
 135  
 136          return $html;
 137      }
 138  
 139      /**
 140       * Returns html for displaying one file manager
 141       *
 142       * @param form_filemanager $fm
 143       * @return string
 144       */
 145      protected function fm_print_generallayout($fm) {
 146          $context = [
 147                  'client_id' => $fm->options->client_id,
 148                  'helpicon' => $this->help_icon('setmainfile', 'repository'),
 149                  'restrictions' => $this->fm_print_restrictions($fm)
 150          ];
 151          return $this->render_from_template('core/filemanager_page_generallayout', $context);
 152      }
 153  
 154      /**
 155       * FileManager JS template for displaying one file in 'icon view' mode.
 156       *
 157       * Except for elements described in fp_js_template_iconfilename, this template may also
 158       * contain element with class 'fp-contextmenu'. If context menu is available for this
 159       * file, the top element will receive the additional class 'fp-hascontextmenu' and
 160       * the element with class 'fp-contextmenu' will hold onclick event for displaying
 161       * the context menu.
 162       *
 163       * @see fp_js_template_iconfilename()
 164       * @return string
 165       */
 166      protected function fm_js_template_iconfilename() {
 167          $rv = '
 168  <div class="fp-file">
 169      <a href="#" class="d-block aabtn">
 170      <div style="position:relative;">
 171          <div class="fp-thumbnail"></div>
 172          <div class="fp-reficons1"></div>
 173          <div class="fp-reficons2"></div>
 174      </div>
 175      <div class="fp-filename-field">
 176          <div class="fp-filename text-truncate"></div>
 177      </div>
 178      </a>
 179      <a class="fp-contextmenu btn btn-icon btn-light border icon-no-margin icon-size-3" href="#">
 180          <span>'.$this->pix_icon('i/menu', '▶').'</span></a>
 181  </div>';
 182          return $rv;
 183      }
 184  
 185      /**
 186       * FileManager JS template for displaying file name in 'table view' and 'tree view' modes.
 187       *
 188       * Except for elements described in fp_js_template_listfilename, this template may also
 189       * contain element with class 'fp-contextmenu'. If context menu is available for this
 190       * file, the top element will receive the additional class 'fp-hascontextmenu' and
 191       * the element with class 'fp-contextmenu' will hold onclick event for displaying
 192       * the context menu.
 193       *
 194       * @todo MDL-32736 remove onclick="return false;"
 195       * @see fp_js_template_listfilename()
 196       * @return string
 197       */
 198      protected function fm_js_template_listfilename() {
 199          $rv = '
 200  <span class="fp-filename-icon">
 201      <a href="#">
 202      <span class="fp-icon"></span>
 203      <span class="fp-reficons1"></span>
 204      <span class="fp-reficons2"></span>
 205      <span class="fp-filename"></span>
 206      </a>
 207      <a class="fp-contextmenu" href="#" onclick="return false;">'.$this->pix_icon('i/menu', '▶').'</a>
 208  </span>';
 209          return $rv;
 210      }
 211  
 212      /**
 213       * FileManager JS template for displaying 'Make new folder' dialog.
 214       *
 215       * Must be wrapped in an element, CSS for this element must define width and height of the window;
 216       *
 217       * Must have one input element with type="text" (for users to enter the new folder name);
 218       *
 219       * content of element with class 'fp-dlg-curpath' will be replaced with current path where
 220       * new folder is about to be created;
 221       * elements with classes 'fp-dlg-butcreate' and 'fp-dlg-butcancel' will hold onclick events;
 222       *
 223       * @return string
 224       */
 225      protected function fm_js_template_mkdir() {
 226          $rv = '
 227  <div class="filemanager fp-mkdir-dlg" role="dialog" aria-live="assertive" aria-labelledby="fp-mkdir-dlg-title">
 228      <div class="fp-mkdir-dlg-text">
 229          <label id="fp-mkdir-dlg-title">' . get_string('newfoldername', 'repository') . '</label><br/>
 230          <input type="text" class="form-control"/>
 231      </div>
 232      <button class="fp-dlg-butcreate btn-primary btn">'.get_string('makeafolder').'</button>
 233      <button class="fp-dlg-butcancel btn-cancel btn">'.get_string('cancel').'</button>
 234  </div>';
 235          return $rv;
 236      }
 237  
 238      /**
 239       * FileManager JS template for error/info message displayed as a separate popup window.
 240       *
 241       * @see fp_js_template_message()
 242       * @return string
 243       */
 244      protected function fm_js_template_message() {
 245          return $this->fp_js_template_message();
 246      }
 247  
 248      /**
 249       * FileManager JS template for window with file information/actions.
 250       *
 251       */
 252      protected function fm_js_template_fileselectlayout() {
 253          $context = [
 254                  'helpicon' => $this->help_icon('setmainfile', 'repository'),
 255                  'licensehelpicon' => $this->create_license_help_icon_context(),
 256                  'columns' => true
 257          ];
 258          return $this->render_from_template('core/filemanager_fileselect', $context);
 259      }
 260  
 261      /**
 262       * FileManager JS template for popup confirm dialogue window.
 263       *
 264       * @return string
 265       */
 266      protected function fm_js_template_confirmdialog() {
 267          return $this->render_from_template('core/filemanager_confirmdialog', []);
 268      }
 269  
 270      /**
 271       * Returns all FileManager JavaScript templates as an array.
 272       *
 273       * @return array
 274       */
 275      public function filemanager_js_templates() {
 276          $class_methods = get_class_methods($this);
 277          $templates = array();
 278          foreach ($class_methods as $method_name) {
 279              if (preg_match('/^fm_js_template_(.*)$/', $method_name, $matches))
 280              $templates[$matches[1]] = $this->$method_name();
 281          }
 282          return $templates;
 283      }
 284  
 285      /**
 286       * Displays restrictions for the file manager
 287       *
 288       * @param form_filemanager $fm
 289       * @return string
 290       */
 291      protected function fm_print_restrictions($fm) {
 292          $maxbytes = display_size($fm->options->maxbytes, 0);
 293          $strparam = (object) array('size' => $maxbytes, 'attachments' => $fm->options->maxfiles,
 294              'areasize' => display_size($fm->options->areamaxbytes, 0));
 295          $hasmaxfiles = !empty($fm->options->maxfiles) && $fm->options->maxfiles > 0;
 296          $hasarealimit = !empty($fm->options->areamaxbytes) && $fm->options->areamaxbytes != -1;
 297          if ($hasmaxfiles && $hasarealimit) {
 298              $maxsize = get_string('maxsizeandattachmentsandareasize', 'moodle', $strparam);
 299          } else if ($hasmaxfiles) {
 300              $maxsize = get_string('maxsizeandattachments', 'moodle', $strparam);
 301          } else if ($hasarealimit) {
 302              $maxsize = get_string('maxsizeandareasize', 'moodle', $strparam);
 303          } else {
 304              $maxsize = get_string('maxfilesize', 'moodle', $maxbytes);
 305          }
 306  
 307          return '<span>'. $maxsize . '</span>';
 308      }
 309  
 310      /**
 311       * Template for FilePicker with general layout (not QuickUpload).
 312       *
 313       *
 314       * @return string
 315       */
 316      protected function fp_js_template_generallayout() {
 317          return $this->render_from_template('core/filemanager_modal_generallayout', []);
 318      }
 319  
 320      /**
 321       * FilePicker JS template for displaying one file in 'icon view' mode.
 322       *
 323       * the element with class 'fp-thumbnail' will be resized to the repository thumbnail size
 324       * (both width and height, unless min-width and/or min-height is set in CSS) and the content of
 325       * an element will be replaced with an appropriate img;
 326       *
 327       * the width of element with class 'fp-filename' will be set to the repository thumbnail width
 328       * (unless min-width is set in css) and the content of an element will be replaced with filename
 329       * supplied by repository;
 330       *
 331       * top element(s) will have class fp-folder if the element is a folder;
 332       *
 333       * List of files will have parent <div> element with class 'fp-iconview'
 334       *
 335       * @return string
 336       */
 337      protected function fp_js_template_iconfilename() {
 338          $rv = '
 339  <a class="fp-file" href="#" >
 340      <div style="position:relative;">
 341          <div class="fp-thumbnail"></div>
 342          <div class="fp-reficons1"></div>
 343          <div class="fp-reficons2"></div>
 344      </div>
 345      <div class="fp-filename-field">
 346          <p class="fp-filename text-truncate"></p>
 347      </div>
 348  </a>';
 349          return $rv;
 350      }
 351  
 352      /**
 353       * FilePicker JS template for displaying file name in 'table view' and 'tree view' modes.
 354       *
 355       * content of the element with class 'fp-icon' will be replaced with an appropriate img;
 356       *
 357       * content of element with class 'fp-filename' will be replaced with filename supplied by
 358       * repository;
 359       *
 360       * top element(s) will have class fp-folder if the element is a folder;
 361       *
 362       * Note that tree view and table view are the YUI widgets and therefore there are no
 363       * other templates. The widgets will be wrapped in <div> with class fp-treeview or
 364       * fp-tableview (respectfully).
 365       *
 366       * @return string
 367       */
 368      protected function fp_js_template_listfilename() {
 369          $rv = '
 370  <span class="fp-filename-icon">
 371      <a href="#">
 372          <span class="fp-icon"></span>
 373          <span class="fp-filename"></span>
 374      </a>
 375  </span>';
 376          return $rv;
 377      }
 378  
 379      /**
 380       * FilePicker JS template for displaying link/loading progress for fetching of the next page
 381       *
 382       * This text is added to .fp-content AFTER .fp-iconview/.fp-treeview/.fp-tableview
 383       *
 384       * Must have one parent element with class 'fp-nextpage'. It will be assigned additional
 385       * class 'loading' during loading of the next page (it is recommended that in this case the link
 386       * becomes unavailable). Also must contain one element <a> or <button> that will hold
 387       * onclick event for displaying of the next page. The event will be triggered automatically
 388       * when user scrolls to this link.
 389       *
 390       * @return string
 391       */
 392      protected function fp_js_template_nextpage() {
 393          $rv = '
 394  <div class="fp-nextpage">
 395      <div class="fp-nextpage-link"><a href="#">'.get_string('more').'</a></div>
 396      <div class="fp-nextpage-loading">
 397          ' . $this->pix_icon('i/loading_small', '') . '
 398      </div>
 399  </div>';
 400          return $rv;
 401      }
 402  
 403      /**
 404       * FilePicker JS template for window appearing to select a file.
 405       *
 406       * @return string
 407       */
 408      protected function fp_js_template_selectlayout() {
 409          $context = [
 410              'licensehelpicon' => $this->create_license_help_icon_context()
 411          ];
 412          return $this->render_from_template('core/filemanager_selectlayout', $context);
 413      }
 414  
 415      /**
 416       * FilePicker JS template for 'Upload file' repository
 417       *
 418       * @return string
 419       */
 420      protected function fp_js_template_uploadform() {
 421          $context = [
 422              'licensehelpicon' => $this->create_license_help_icon_context()
 423          ];
 424          return $this->render_from_template('core/filemanager_uploadform', $context);
 425      }
 426  
 427      /**
 428       * FilePicker JS template to display during loading process (inside element with class 'fp-content').
 429       *
 430       * @return string
 431       */
 432      protected function fp_js_template_loading() {
 433          return '
 434  <div class="fp-content-loading">
 435      <div class="fp-content-center">
 436          ' . $this->pix_icon('i/loading_small', '') . '
 437      </div>
 438  </div>';
 439      }
 440  
 441      /**
 442       * FilePicker JS template for error (inside element with class 'fp-content').
 443       *
 444       * must have element with class 'fp-error', its content will be replaced with error text
 445       * and the error code will be assigned as additional class to this element
 446       * used errors: invalidjson, nofilesavailable, norepositoriesavailable
 447       *
 448       * @return string
 449       */
 450      protected function fp_js_template_error() {
 451          $rv = '
 452  <div class="fp-content-error" ><div class="fp-error"></div></div>';
 453          return $rv;
 454      }
 455  
 456      /**
 457       * FilePicker JS template for error/info message displayed as a separate popup window.
 458       *
 459       * Must be wrapped in one element, CSS for this element must define
 460       * width and height of the window. It will be assigned with an additional class 'fp-msg-error'
 461       * or 'fp-msg-info' depending on message type;
 462       *
 463       * content of element with class 'fp-msg-text' will be replaced with error/info text;
 464       *
 465       * element with class 'fp-msg-butok' will hold onclick event
 466       *
 467       * @return string
 468       */
 469      protected function fp_js_template_message() {
 470          $rv = '
 471  <div class="file-picker fp-msg" role="alertdialog" aria-live="assertive" aria-labelledby="fp-msg-labelledby">
 472      <p class="fp-msg-text" id="fp-msg-labelledby"></p>
 473      <button class="fp-msg-butok btn-primary btn">'.get_string('ok').'</button>
 474  </div>';
 475          return $rv;
 476      }
 477  
 478      /**
 479       * FilePicker JS template for popup dialogue window asking for action when file with the same name already exists.
 480       *
 481       * @return string
 482       */
 483      protected function fp_js_template_processexistingfile() {
 484          return $this->render_from_template('core/filemanager_processexistingfile', []);
 485      }
 486  
 487      /**
 488       * FilePicker JS template for popup dialogue window asking for action when file with the same name already exists
 489       * (multiple-file version).
 490       *
 491       * @return string
 492       */
 493      protected function fp_js_template_processexistingfilemultiple() {
 494          return $this->render_from_template('core/filemanager_processexistingfilemultiple', []);
 495      }
 496  
 497      /**
 498       * FilePicker JS template for repository login form including templates for each element type
 499       *
 500       * @return string
 501       */
 502      protected function fp_js_template_loginform() {
 503          return $this->render_from_template('core/filemanager_loginform', []);
 504      }
 505  
 506      /**
 507       * Returns all FilePicker JavaScript templates as an array.
 508       *
 509       * @return array
 510       */
 511      public function filepicker_js_templates() {
 512          $class_methods = get_class_methods($this);
 513          $templates = array();
 514          foreach ($class_methods as $method_name) {
 515              if (preg_match('/^fp_js_template_(.*)$/', $method_name, $matches))
 516              $templates[$matches[1]] = $this->$method_name();
 517          }
 518          return $templates;
 519      }
 520  
 521      /**
 522       * Returns HTML for default repository searchform to be passed to Filepicker
 523       *
 524       * This will be used as contents for search form defined in generallayout template
 525       * (form with id {TOOLSEARCHID}).
 526       * Default contents is one text input field with name="s"
 527       */
 528      public function repository_default_searchform() {
 529          return $this->render_from_template('core/filemanager_default_searchform', []);
 530      }
 531  
 532      /**
 533       * Create the context for rendering help icon with license links displaying all licenses and sources.
 534       *
 535       * @return \stdClass $iconcontext the context for rendering license help info.
 536       */
 537      protected function create_license_help_icon_context() : stdClass {
 538          $licensecontext = new stdClass();
 539  
 540          $licenses = [];
 541          // Discard licenses without a name or source from enabled licenses.
 542          foreach (license_manager::get_active_licenses() as $license) {
 543              if (!empty($license->fullname) && !empty($license->source)) {
 544                  $licenses[] = $license;
 545              }
 546          }
 547  
 548          $licensecontext->licenses = $licenses;
 549          $helptext = $this->render_from_template('core/filemanager_licenselinks', $licensecontext);
 550  
 551          $iconcontext = new stdClass();
 552          $iconcontext->text = $helptext;
 553          $iconcontext->alt = get_string('helpprefix2', 'moodle', get_string('chooselicense', 'repository'));
 554  
 555          return $iconcontext;
 556      }
 557  }
 558  
 559  /**
 560   * Data structure representing a general moodle file tree viewer
 561   *
 562   * @copyright 2010 Dongsheng Cai
 563   * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 564   * @since     Moodle 2.0
 565   */
 566  class files_tree_viewer implements renderable {
 567      public $tree;
 568      public $path;
 569      public $context;
 570  
 571      /** @var array file tree viewer options. */
 572      protected array $options = [];
 573  
 574      /**
 575       * Constructor of moodle_file_tree_viewer class
 576       * @param file_info $file_info
 577       * @param array $options
 578       */
 579      public function __construct(file_info $file_info, array $options = null) {
 580          global $CFG;
 581  
 582          //note: this MUST NOT use get_file_storage() !!!!!!!!!!!!!!!!!!!!!!!!!!!!
 583          $this->options = (array)$options;
 584          $this->context = $options['context'];
 585  
 586          $this->tree = array();
 587          $children = $file_info->get_children();
 588          $current_file_params = $file_info->get_params();
 589          $parent_info = $file_info->get_parent();
 590          $level = $parent_info;
 591          $this->path = array();
 592          while ($level) {
 593              $params = $level->get_params();
 594              $context = context::instance_by_id($params['contextid']);
 595              // $this->context is current context
 596              if ($context->id != $this->context->id or empty($params['filearea'])) {
 597                  break;
 598              }
 599              // unset unused parameters
 600              unset($params['component']);
 601              unset($params['filearea']);
 602              unset($params['filename']);
 603              unset($params['itemid']);
 604              $url = new moodle_url('/files/index.php', $params);
 605              $this->path[] = html_writer::link($url, $level->get_visible_name());
 606              $level = $level->get_parent();
 607          }
 608          $this->path = array_reverse($this->path);
 609          if ($current_file_params['filepath'] != '/') {
 610              $this->path[] = $file_info->get_visible_name();
 611          }
 612  
 613          foreach ($children as $child) {
 614              $filedate = $child->get_timemodified();
 615              $filesize = $child->get_filesize();
 616              $mimetype = $child->get_mimetype();
 617              $params = $child->get_params();
 618              unset($params['component']);
 619              unset($params['filearea']);
 620              unset($params['filename']);
 621              unset($params['itemid']);
 622              $fileitem = array(
 623                      'params'   => $params,
 624                      'filename' => $child->get_visible_name(),
 625                      'mimetype' => $child->get_mimetype(),
 626                      'filedate' => $filedate ? $filedate : '',
 627                      'filesize' => $filesize ? $filesize : ''
 628                      );
 629              $url = new moodle_url('/files/index.php', $params);
 630              if ($child->is_directory()) {
 631                  $fileitem['isdir'] = true;
 632                  $fileitem['url'] = $url->out(false);
 633              } else {
 634                  $fileitem['url'] = $child->get_url();
 635              }
 636              $this->tree[] = $fileitem;
 637          }
 638      }
 639  }