Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

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