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 39 and 401] [Versions 401 and 402] [Versions 401 and 403]

   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  namespace core;
  18  
  19  use file_info_context_course;
  20  use file_info_context_coursecat;
  21  use file_info_context_module;
  22  use file_info_stored;
  23  
  24  /**
  25   * Unit tests for file browser
  26   *
  27   * @package    core
  28   * @copyright  2017 Marina Glancy
  29   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  30   */
  31  class file_browser_test extends \advanced_testcase {
  32  
  33      /** @var int */
  34      protected $initialnonempty;
  35      /** @var int */
  36      protected $initialcategories;
  37      /** @var int */
  38      protected $initialcourses;
  39      /** @var int */
  40      protected $initialjpg;
  41      /** @var stdClass */
  42      protected $course1;
  43      /** @var stdClass */
  44      protected $course2;
  45      /** @var stdClass */
  46      protected $module1;
  47      /** @var stdClass */
  48      protected $module2;
  49      /** @var stdClass */
  50      protected $course1filerecord;
  51      /** @var stdClass */
  52      protected $teacher;
  53      /** @var stdClass */
  54      protected $teacherrole;
  55  
  56      /**
  57       * Set up
  58       */
  59      public function setUp(): void {
  60          global $DB;
  61          $this->resetAfterTest();
  62  
  63          $this->setAdminUser();
  64  
  65          $browser = get_file_browser();
  66          $fileinfo = $browser->get_file_info(\context_system::instance());
  67          $this->initialnonempty = $fileinfo->count_non_empty_children();
  68          $this->initialcategories = count(array_filter($fileinfo->get_children(), function($a) {
  69              return $a instanceof file_info_context_coursecat;
  70          }));
  71          $this->initialcourses = count(array_filter($fileinfo->get_children(), function($a) {
  72              return $a instanceof file_info_context_course;
  73          }));
  74          $this->initialcourses -= 1; // This includes the site course by default.
  75          $this->initialjpg = $fileinfo->count_non_empty_children(['.jpg']);
  76  
  77          $this->getDataGenerator()->create_category(); // Empty category.
  78          $this->course1 = $this->getDataGenerator()->create_course(); // Empty course.
  79  
  80          $this->course2 = $this->getDataGenerator()->create_course();
  81  
  82          // Add a file to course1 summary.
  83          $coursecontext1 = \context_course::instance($this->course1->id);
  84          $this->course1filerecord = array('contextid' => $coursecontext1->id,
  85              'component' => 'course',
  86              'filearea' => 'summary',
  87              'itemid' => '0',
  88              'filepath' => '/',
  89              'filename' => 'summaryfile.jpg');
  90          $fs = get_file_storage();
  91          $fs->create_file_from_string($this->course1filerecord, 'IMG');
  92  
  93          $this->module1 = $this->getDataGenerator()->create_module('resource', ['course' => $this->course2->id]); // Contains 1 file.
  94          $this->module2 = $this->getDataGenerator()->create_module('assign', ['course' => $this->course2->id]); // Contains no files.
  95  
  96          $this->teacher = $this->getDataGenerator()->create_user();
  97          $this->teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'));
  98  
  99          // Make sure we're testing what should be the default capabilities.
 100          assign_capability('moodle/restore:viewautomatedfilearea', CAP_ALLOW, $this->teacherrole->id, $coursecontext1);
 101  
 102          $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course1->id, $this->teacherrole->id);
 103          $this->getDataGenerator()->enrol_user($this->teacher->id, $this->course2->id, $this->teacherrole->id);
 104  
 105          $this->setUser($this->teacher);
 106      }
 107  
 108      /**
 109       * Test "Server files" from the system context
 110       */
 111      public function test_file_info_context_system() {
 112  
 113          // There is one non-empty category child and two category children.
 114  
 115          $browser = get_file_browser();
 116          $fileinfo = $browser->get_file_info(\context_system::instance());
 117          $this->assertNotEmpty($fileinfo->count_non_empty_children());
 118          $this->assertEquals($this->initialnonempty + 1, count($fileinfo->get_non_empty_children()));
 119          $categorychildren = array_filter($fileinfo->get_children(), function($a) {
 120              return $a instanceof file_info_context_coursecat;
 121          });
 122          $this->assertEquals($this->initialcategories + 1, count($categorychildren));
 123      }
 124  
 125      /**
 126       * Test "Server files" from the system context, hide Misc category
 127       */
 128      public function test_file_info_context_system_hidden() {
 129  
 130          // Hide the course category that contains our two courses. Teacher does not have cap to view hidden categories.
 131          \core_course_category::get($this->course1->category)->update(['visible' => 0]);
 132  
 133          // We should have two non-empty children in system context (courses).
 134          $browser = get_file_browser();
 135          $fileinfo = $browser->get_file_info(\context_system::instance());
 136          $this->assertNotEmpty($fileinfo->count_non_empty_children());
 137          $this->assertEquals($this->initialnonempty + 2, count($fileinfo->get_non_empty_children()));
 138  
 139          // Should be 1 category children (empty category).
 140          $categorychildren = array_filter($fileinfo->get_children(), function($a) {
 141              return $a instanceof file_info_context_coursecat;
 142          });
 143          $this->assertEquals($this->initialcategories, count($categorychildren));
 144  
 145          // Should be 2 course children - courses that belonged to hidden subcategory are now direct children of "System".
 146          $coursechildren = array_filter($fileinfo->get_children(), function($a) {
 147              return $a instanceof file_info_context_course;
 148          });
 149          $this->assertEquals($this->initialcourses + 2, count($coursechildren));
 150      }
 151  
 152      /**
 153       * Test "Server files" from the course category context
 154       */
 155      public function test_file_info_context_coursecat() {
 156  
 157          // There are two non-empty courses.
 158  
 159          $browser = get_file_browser();
 160          $fileinfo = $browser->get_file_info(\context_coursecat::instance($this->course2->category));
 161          $this->assertNotEmpty($fileinfo->count_non_empty_children());
 162          $this->assertEquals(2, count($fileinfo->get_non_empty_children()));
 163          $coursechildren = array_filter($fileinfo->get_children(), function($a) {
 164              return $a instanceof file_info_context_course;
 165          });
 166          $this->assertEquals($this->initialcourses + 2, count($coursechildren));
 167      }
 168  
 169      /**
 170       * Test "Server files" from the course category context, only look for .jpg
 171       */
 172      public function test_file_info_context_coursecat_jpg() {
 173  
 174          // There is one non-empty category child and two category children.
 175  
 176          $browser = get_file_browser();
 177          $fileinfo = $browser->get_file_info(\context_system::instance());
 178          $this->assertNotEmpty($fileinfo->count_non_empty_children(['.jpg']));
 179          $this->assertEquals($this->initialjpg + 1, count($fileinfo->get_non_empty_children(['.jpg'])));
 180      }
 181  
 182      /**
 183       * Test "Server files" from the course context (course1)
 184       */
 185      public function test_file_info_context_course_1() {
 186  
 187          $browser = get_file_browser();
 188          $fileinfo = $browser->get_file_info(\context_course::instance($this->course1->id));
 189          // Fileinfo element has only one non-empty child - "Course summary" file area.
 190          $this->assertNotEmpty($fileinfo->count_non_empty_children());
 191          $nonemptychildren = $fileinfo->get_non_empty_children();
 192          $this->assertEquals(1, count($nonemptychildren));
 193          $child = reset($nonemptychildren);
 194          $this->assertTrue($child instanceof file_info_stored);
 195          $this->assertEquals(['filename' => '.'] + $this->course1filerecord, $child->get_params());
 196          // Filearea "Course summary" has a child that is the actual image file.
 197          $this->assertEquals($this->course1filerecord, $child->get_children()[0]->get_params());
 198  
 199          // There are seven course-level file areas available to teachers with default caps and no modules in this course.
 200          $allchildren = $fileinfo->get_children();
 201          $this->assertEquals(7, count($allchildren));
 202          $modulechildren = array_filter($allchildren, function($a) {
 203              return $a instanceof file_info_context_module;
 204          });
 205          $this->assertEquals(0, count($modulechildren));
 206  
 207          // Admin can see seven course-level file areas.
 208          $this->setAdminUser();
 209          $fileinfo = $browser->get_file_info(\context_course::instance($this->course1->id));
 210          $this->assertEquals(7, count($fileinfo->get_children()));
 211      }
 212  
 213      /**
 214       * Test "Server files" from the course context (course1)
 215       */
 216      public function test_file_info_context_course_2() {
 217  
 218          // 2. Start from the course level.
 219          $browser = get_file_browser();
 220          $fileinfo = $browser->get_file_info(\context_course::instance($this->course2->id));
 221          $this->assertNotEmpty($fileinfo->count_non_empty_children());
 222          $nonemptychildren = $fileinfo->get_non_empty_children();
 223          $this->assertEquals(1, count($nonemptychildren));
 224          $child = reset($nonemptychildren);
 225          $this->assertTrue($child instanceof file_info_context_module);
 226          $this->assertEquals($this->module1->name.' (File)', $child->get_visible_name());
 227          $this->assertEquals(1, count($child->get_non_empty_children()));
 228          $this->assertEquals(1, $child->count_non_empty_children());
 229          $modulechildren = array_filter($fileinfo->get_children(), function($a) {
 230              return $a instanceof file_info_context_module;
 231          });
 232          $this->assertEquals(2, count($modulechildren));
 233      }
 234  
 235      /**
 236       * Test "Server files" from the course context (module1)
 237       */
 238      public function test_file_info_context_module_1() {
 239  
 240          $module1context = \context_module::instance($this->module1->cmid);
 241          $browser = get_file_browser();
 242          $fileinfo = $browser->get_file_info($module1context);
 243          $this->assertEquals($this->module1->name . ' (File)', $fileinfo->get_visible_name());
 244          $this->assertNotEmpty($fileinfo->count_non_empty_children());
 245          $nonemptychildren = $fileinfo->get_non_empty_children();
 246          $this->assertEquals(1, count($nonemptychildren));
 247          $child = reset($nonemptychildren);
 248          $this->assertTrue($child instanceof file_info_stored);
 249      }
 250  
 251      /**
 252       * Test "Server files" from the course context (module1)
 253       */
 254      public function test_file_info_context_module_2() {
 255  
 256          $module2context = \context_module::instance($this->module2->cmid);
 257          $browser = get_file_browser();
 258          $fileinfo = $browser->get_file_info($module2context);
 259          $this->assertEquals($this->module2->name.' (Assignment)', $fileinfo->get_visible_name());
 260          $this->assertEmpty($fileinfo->count_non_empty_children());
 261          $nonemptychildren = $fileinfo->get_non_empty_children();
 262          $this->assertEquals(0, count($nonemptychildren));
 263  
 264      }
 265  }