Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 3.10.x will end 8 November 2021 (12 months).
  • Bug fixes for security issues in 3.10.x will end 9 May 2022 (18 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 310 and 311] [Versions 310 and 400] [Versions 310 and 401] [Versions 310 and 402] [Versions 310 and 403] [Versions 39 and 310]

   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   * Content bank repository browser unit tests.
  19   *
  20   * @package    repository_contentbank
  21   * @copyright  2020 Mihail Geshoski <mihail@moodle.com>
  22   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  23   */
  24  
  25  defined('MOODLE_INTERNAL') || die();
  26  
  27  global $CFG;
  28  
  29  require_once("$CFG->dirroot/repository/lib.php");
  30  
  31  /**
  32   * Tests for the content bank browser class.
  33   *
  34   * @package    repository_contentbank
  35   * @copyright  2020 Mihail Geshoski <mihail@moodle.com>
  36   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  37   */
  38  class repository_contentbank_browser_testcase extends advanced_testcase {
  39  
  40      /**
  41       * Test get_content() in the system context with users that have capability to access/view content bank content
  42       * within the system context. By default, every authenticated user should be able to access/view the content in
  43       * the system context.
  44       */
  45      public function test_get_content_system_context_user_has_capabilities() {
  46          global $DB;
  47  
  48          $this->resetAfterTest(true);
  49  
  50          $systemcontext = \context_system::instance();
  51          // Create a course category $coursecategory.
  52          $coursecategory = $this->getDataGenerator()->create_category(['name' => 'Category']);
  53          $coursecatcontext = \context_coursecat::instance($coursecategory->id);
  54  
  55          // Get the default 'Miscellaneous' category.
  56          $miscellaneouscat = \core_course_category::get(1);
  57          $miscellaneouscatcontext = \context_coursecat::instance($miscellaneouscat->id);
  58  
  59          // Create course.
  60          $course = $this->getDataGenerator()->create_course(['category' => $coursecategory->id]);
  61  
  62          $admin = get_admin();
  63          // Create a user (not enrolled in a course).
  64          $user = $this->getDataGenerator()->create_user();
  65  
  66          // Add some content to the content bank.
  67          $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
  68          // Add some content bank files in the system context.
  69          $contentbankcontents = $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
  70              $systemcontext, true);
  71  
  72          // Log in as admin.
  73          $this->setUser($admin);
  74          // Get the content bank nodes displayed to the admin in the system context.
  75          $browser = new \repository_contentbank\browser\contentbank_browser_context_system($systemcontext);
  76          $repositorycontentnodes = $browser->get_content();
  77          // All content nodes should be available to the admin user.
  78          // There should be a total of 5 nodes, 3 file nodes representing the existing content bank files in the
  79          // system context and 2 folder nodes representing the default course category 'Miscellaneous' and 'Category'.
  80          $this->assertCount(5, $repositorycontentnodes);
  81          $contextfolders = [
  82              [
  83                  'name' => 'Miscellaneous',
  84                  'contextid' => $miscellaneouscatcontext->id
  85              ],
  86              [
  87                  'name' => 'Category',
  88                  'contextid' => $coursecatcontext->id
  89              ]
  90          ];
  91          $expected = $this->generate_expected_content($contextfolders, $contentbankcontents);
  92          $this->assertEqualsCanonicalizing($expected, $repositorycontentnodes);
  93  
  94          // Log in as a user.
  95          $this->setUser($user);
  96          // Get the content bank nodes displayed to an authenticated user in the system context.
  97          $browser = new \repository_contentbank\browser\contentbank_browser_context_system($systemcontext);
  98          $repositorycontentnodes = $browser->get_content();
  99          // There should be 3 nodes representing the existing content bank files in the system context.
 100          // The course category context folder node should be ignored as the user does not have an access to
 101          // the content of the category's courses.
 102          $this->assertCount(3, $repositorycontentnodes);
 103          $expected = $this->generate_expected_content([], $contentbankcontents);
 104          $this->assertEqualsCanonicalizing($expected, $repositorycontentnodes);
 105  
 106          // Enrol the user as an editing teacher in the course.
 107          $editingteacherrole = $DB->get_field('role', 'id', ['shortname' => 'editingteacher']);
 108          $this->getDataGenerator()->enrol_user($user->id, $course->id, $editingteacherrole);
 109  
 110           // Get the content bank nodes displayed to the editing teacher in the system context.
 111          $browser = new \repository_contentbank\browser\contentbank_browser_context_system($systemcontext);
 112          $repositorycontentnodes = $browser->get_content();
 113          // All content nodes should now be available to the editing teacher.
 114          // There should be a total of 4 nodes, 3 file nodes representing the existing content bank files in the
 115          // system context and 1 folder node representing the course category 'Category' (The editing teacher is now
 116          // enrolled in a course from the category).
 117          $this->assertCount(4, $repositorycontentnodes);
 118          $contextfolders = [
 119              [
 120                  'name' => 'Category',
 121                  'contextid' => $coursecatcontext->id
 122              ]
 123          ];
 124          $expected = $this->generate_expected_content($contextfolders, $contentbankcontents);
 125          $this->assertEqualsCanonicalizing($expected, $repositorycontentnodes);
 126      }
 127  
 128      /**
 129       * Test get_content() in the system context with users that do not have a capability to access/view content bank
 130       * content within the system context. By default, every non-authenticated user should not be able to access/view
 131       * the content in the system context.
 132       */
 133      public function test_get_content_system_context_user_missing_capabilities() {
 134          $this->resetAfterTest(true);
 135  
 136          $systemcontext = \context_system::instance();
 137  
 138          $admin = get_admin();
 139          // Add some content to the content bank.
 140          $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
 141          // Add some content bank files in the system context.
 142  
 143          $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id, $systemcontext, true);
 144          // Log out.
 145          $this->setUser();
 146          // Get the content bank nodes displayed to a non-authenticated user in the system context.
 147          $browser = new \repository_contentbank\browser\contentbank_browser_context_system($systemcontext);
 148          $repositorycontents = $browser->get_content();
 149          // Content nodes should not be available to the non-authenticated user in the system context.
 150          $this->assertCount(0, $repositorycontents);
 151      }
 152  
 153      /**
 154       * Test get_content() in the course category context with users that have capability to access/view content
 155       * bank content within the course category context. By default, every authenticated user that has access to
 156       * any category course should be able to access/view the content in the course category context.
 157       */
 158      public function test_get_content_course_category_context_user_has_capabilities() {
 159          $this->resetAfterTest(true);
 160  
 161          // Create a course category.
 162          $category = $this->getDataGenerator()->create_category(['name' => 'Category']);
 163          $coursecatcontext = \context_coursecat::instance($category->id);
 164          // Create course1.
 165          $course1 = $this->getDataGenerator()->create_course(['fullname' => 'Course1', 'category' => $category->id]);
 166          $course1context = \context_course::instance($course1->id);
 167          // Create course2.
 168          $course2 = $this->getDataGenerator()->create_course(['fullname' => 'Course2', 'category' => $category->id]);
 169          $course2context = \context_course::instance($course2->id);
 170  
 171          $admin = get_admin();
 172          // Create editing teacher enrolled in course1.
 173          $editingteacher = $this->getDataGenerator()->create_and_enrol($course1, 'editingteacher');
 174  
 175          // Add some content to the content bank.
 176          $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
 177          // Add some content bank files in the course category context.
 178          $contentbankcontents = $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
 179              $coursecatcontext, true);
 180  
 181          $this->setUser($admin);
 182          // Get the content bank nodes displayed to the admin in the course category context.
 183          $browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($coursecatcontext);
 184          $repositorycontents = $browser->get_content();
 185          // All content nodes should be available to the admin user.
 186          // There should be a total of 5 nodes, 3 file nodes representing the existing content bank files in the
 187          // course category context and 2 folder nodes representing the courses 'Course1' and 'Course2'.
 188          $this->assertCount(5, $repositorycontents);
 189          $contextfolders = [
 190              [
 191                  'name' => 'Course1',
 192                  'contextid' => $course1context->id
 193              ],
 194              [
 195                  'name' => 'Course2',
 196                  'contextid' => $course2context->id
 197              ]
 198          ];
 199          $expected = $this->generate_expected_content($contextfolders, $contentbankcontents);
 200          $this->assertEqualsCanonicalizing($expected, $repositorycontents);
 201  
 202          // Log in as an editing teacher enrolled in a child course.
 203          $this->setUser($editingteacher);
 204          // Get the content bank nodes displayed to the editing teacher in the course category context.
 205          $browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($coursecatcontext);
 206          $repositorycontents = $browser->get_content();
 207          // There should be a total of 4 nodes, 3 file nodes representing the existing content bank files in the
 208          // course category context and 1 folder node representing the course 'Course1' (The editing teacher is only
 209          // enrolled in course1).
 210          $this->assertCount(4, $repositorycontents);
 211          $contextfolders = [
 212              [
 213                  'name' => 'Course1',
 214                  'contextid' => $course1context->id
 215              ]
 216          ];
 217          $expected = $this->generate_expected_content($contextfolders, $contentbankcontents);
 218          $this->assertEqualsCanonicalizing($expected, $repositorycontents);
 219      }
 220  
 221      /**
 222       * Test get_content() in the course category context with users that do not have capability to access/view content
 223       * bank content within the course category context. By default, every non-authenticated user or authenticated users
 224       * that cannot access/view course content from the course category should not be able to access/view the
 225       * content in the course category context.
 226       */
 227      public function test_get_content_course_category_context_user_missing_capabilities() {
 228          $this->resetAfterTest(true);
 229  
 230           // Create a course category 'Category'.
 231          $category = $this->getDataGenerator()->create_category(['name' => 'Category']);
 232          // Create course1 in 'Category'.
 233          $course1 = $this->getDataGenerator()->create_course(['fullname' => 'Course1', 'category' => $category->id]);
 234          // Create course2 in 'Miscellaneous' by default.
 235          $course2 = $this->getDataGenerator()->create_course(['fullname' => 'Course2']);
 236          // Create a teacher enrolled in course1.
 237          $teacher = $this->getDataGenerator()->create_and_enrol($course1, 'teacher');
 238          // Create an editing teacher enrolled in course2.
 239          $editingteacher = $this->getDataGenerator()->create_and_enrol($course2, 'editingteacher');
 240  
 241          $admin = get_admin();
 242          // Add some content to the content bank.
 243          $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
 244          // Add some content bank files in the 'Category' context.
 245          $coursecatcontext = \context_coursecat::instance($category->id);
 246          $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
 247              $coursecatcontext, true);
 248  
 249          // Log in as a non-editing teacher.
 250          $this->setUser($teacher);
 251          // Get the content bank nodes displayed to a non-editing teacher in the 'Category' context.
 252          $browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($coursecatcontext);
 253          $repositorycontents = $browser->get_content();
 254          // Content nodes should not be available to a non-editing teacher in the 'Category' context.
 255          $this->assertCount(0, $repositorycontents);
 256  
 257          // Log in as an editing teacher.
 258          $this->setUser($editingteacher);
 259          // Get the content bank nodes displayed to a an editing teacher in the 'Category' context.
 260          $browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($coursecatcontext);
 261          $repositorycontents = $browser->get_content();
 262          // Content nodes should not be available to an editing teacher in the 'Category' context.
 263          $this->assertCount(0, $repositorycontents);
 264  
 265          // Log out.
 266          $this->setUser();
 267          // Get the content bank nodes displayed to a non-authenticated user in the course category context.
 268          $browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($coursecatcontext);
 269          $repositorycontents = $browser->get_content();
 270          // Content nodes should not be available to the non-authenticated user in the course category context.
 271          $this->assertCount(0, $repositorycontents);
 272      }
 273  
 274      /**
 275       * Test get_content() in the course context with users that have capability to access/view content
 276       * bank content within the course context. By default, admin, managers, course creators, editing teachers enrolled
 277       * in the course should be able to access/view the content.
 278       */
 279      public function test_get_content_course_context_user_has_capabilities() {
 280          $this->resetAfterTest(true);
 281  
 282          // Create course1.
 283          $course = $this->getDataGenerator()->create_course(['fullname' => 'Course']);
 284          $coursecontext = \context_course::instance($course->id);
 285  
 286          $admin = get_admin();
 287          // Create editing teacher enrolled in course.
 288          $editingteacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 289  
 290          // Add some content to the content bank.
 291          $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
 292          // Add some content bank files in the course context.
 293          $contentbankcontents = $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
 294              $coursecontext, true);
 295  
 296          $this->setUser($admin);
 297          // Get the content bank nodes displayed to the admin in the course context.
 298          $browser = new \repository_contentbank\browser\contentbank_browser_context_course($coursecontext);
 299          $repositorycontents = $browser->get_content();
 300          // All content nodes should be available to the admin user.
 301          // There should be 3 file nodes representing the existing content bank files in the
 302          // course context.
 303          $this->assertCount(3, $repositorycontents);
 304          $expected = $this->generate_expected_content([], $contentbankcontents);
 305          $this->assertEqualsCanonicalizing($expected, $repositorycontents);
 306  
 307          // Log in as an editing teacher.
 308          $this->setUser($editingteacher);
 309          // All content nodes should also be available to the editing teacher.
 310          // Get the content bank nodes displayed to the editing teacher in the course context.
 311          $browser = new \repository_contentbank\browser\contentbank_browser_context_course($coursecontext);
 312          $repositorycontents = $browser->get_content();
 313          // There should be 3 file nodes representing the existing content bank files in the
 314          // course context.
 315          $this->assertCount(3, $repositorycontents);
 316          $expected = $this->generate_expected_content([], $contentbankcontents);
 317          $this->assertEqualsCanonicalizing($expected, $repositorycontents);
 318      }
 319  
 320      /**
 321       * Test get_content() in the course context with users that do not have capability to access/view content
 322       * bank content within the course context. By default, every user which is not an admin, manager, course creator,
 323       * editing teacher enrolled in the course should not be able to access/view the content.
 324       */
 325      public function test_get_content_course_context_user_missing_capabilities() {
 326          $this->resetAfterTest(true);
 327  
 328          // Create course1.
 329          $course1 = $this->getDataGenerator()->create_course(['fullname' => 'Course1']);
 330          $course1context = \context_course::instance($course1->id);
 331          // Create course2.
 332          $course2 = $this->getDataGenerator()->create_course(['fullname' => 'Course2']);
 333          $course2context = \context_course::instance($course2->id);
 334  
 335          $admin = get_admin();
 336          // Create non-editing teacher enrolled in course1.
 337          $teacher = $this->getDataGenerator()->create_and_enrol($course1, 'teacher');
 338           // Create editing teacher enrolled in course1.
 339          $editingteacher = $this->getDataGenerator()->create_and_enrol($course1, 'editingteacher');
 340  
 341          // Add some content to the content bank.
 342          $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
 343          // Add some content bank files in the course1 context.
 344          $generator->generate_contentbank_data('contenttype_h5p', 2, $admin->id,
 345              $course1context, true);
 346          // Add some content bank files in the course2 context.
 347          $generator->generate_contentbank_data('contenttype_h5p', 3, $admin->id,
 348              $course2context, true);
 349  
 350          // Log in as a non-editing teacher.
 351          $this->setUser($teacher);
 352          // Get the content bank nodes displayed to the non-editing teacher in the course1 context.
 353          $browser = new \repository_contentbank\browser\contentbank_browser_context_course($course1context);
 354          $repositorycontents = $browser->get_content();
 355          // Content nodes should not be available to the teacher in the course1 context.
 356          $this->assertCount(0, $repositorycontents);
 357  
 358          // Log in as editing teacher.
 359          $this->setUser($editingteacher);
 360          // Get the content bank nodes displayed to the editing teacher in the course2 context.
 361          $browser = new \repository_contentbank\browser\contentbank_browser_context_course($course2context);
 362          $repositorycontents = $browser->get_content();
 363          // Content nodes should not be available to the teacher in the course2 context. The editing teacher is not
 364          // enrolled in this course.
 365          $this->assertCount(0, $repositorycontents);
 366      }
 367  
 368      /**
 369       * Test get_navigation() in the system context.
 370       */
 371      public function test_get_navigation_system_context() {
 372          $this->resetAfterTest(true);
 373  
 374          $systemcontext = \context_system::instance();
 375  
 376          $browser = new \repository_contentbank\browser\contentbank_browser_context_system($systemcontext);
 377          $navigation = $browser->get_navigation();
 378          // The navigation array should contain only 1 element, representing the system navigation node.
 379          $this->assertCount(1, $navigation);
 380          $expected = [
 381              \repository_contentbank\helper::create_navigation_node($systemcontext)
 382          ];
 383          $this->assertEquals($expected, $navigation);
 384      }
 385  
 386      /**
 387       * Test get_navigation() in the course category context.
 388       */
 389      public function test_get_navigation_course_category_context() {
 390          $this->resetAfterTest(true);
 391  
 392          $systemcontext = \context_system::instance();
 393          // Create a course category.
 394          $category = $this->getDataGenerator()->create_category(['name' => 'category']);
 395          $categorycontext = \context_coursecat::instance($category->id);
 396          // Create a course subcategory.
 397          $subcategory = $this->getDataGenerator()->create_category(['name' => 'subcategory', 'parent' => $category->id]);
 398          $subcategorytcontext = \context_coursecat::instance($subcategory->id);
 399  
 400          // Get navigation nodes in the category context.
 401          $browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($categorycontext);
 402          $navigation = $browser->get_navigation();
 403          // The navigation array should contain 2 elements, representing the system and course category
 404          // navigation nodes.
 405          $this->assertCount(2, $navigation);
 406          $expected = [
 407              \repository_contentbank\helper::create_navigation_node($systemcontext),
 408              \repository_contentbank\helper::create_navigation_node($categorycontext)
 409          ];
 410          $this->assertEquals($expected, $navigation);
 411  
 412          // Get navigation nodes in the subcategory context.
 413          $browser = new \repository_contentbank\browser\contentbank_browser_context_coursecat($subcategorytcontext);
 414          $navigation = $browser->get_navigation();
 415          // The navigation array should contain 3 elements, representing the system, category and subcategory
 416          // navigation nodes.
 417          $this->assertCount(3, $navigation);
 418          $expected = [
 419              \repository_contentbank\helper::create_navigation_node($systemcontext),
 420              \repository_contentbank\helper::create_navigation_node($categorycontext),
 421              \repository_contentbank\helper::create_navigation_node($subcategorytcontext)
 422          ];
 423          $this->assertEquals($expected, $navigation);
 424      }
 425  
 426      /**
 427       * Test get_navigation() in the course context.
 428       */
 429      public function test_get_navigation_course_context() {
 430          $this->resetAfterTest(true);
 431  
 432          $systemcontext = \context_system::instance();
 433          // Create a category.
 434          $category = $this->getDataGenerator()->create_category(['name' => 'category']);
 435          $categorycontext = \context_coursecat::instance($category->id);
 436          // Create a subcategory.
 437          $subcategory = $this->getDataGenerator()->create_category(['name' => 'category', 'parent' => $category->id]);
 438          $subcategorycontext = \context_coursecat::instance($subcategory->id);
 439          // Create a course in category.
 440          $categorycourse = $this->getDataGenerator()->create_course(['category' => $category->id]);
 441          $categorycoursecontext = \context_course::instance($categorycourse->id);
 442          // Create a course in subcategory.
 443          $subcategorycourse = $this->getDataGenerator()->create_course(['category' => $subcategory->id]);
 444          $subcategorycoursecontext = \context_course::instance($subcategorycourse->id);
 445  
 446          // Get navigation nodes in the category course context.
 447          $browser = new \repository_contentbank\browser\contentbank_browser_context_course($categorycoursecontext);
 448          $navigation = $browser->get_navigation();
 449          // The navigation array should contain 3 elements, representing the system, category and course
 450          // navigation nodes.
 451          $this->assertCount(3, $navigation);
 452          $expected = [
 453              \repository_contentbank\helper::create_navigation_node($systemcontext),
 454              \repository_contentbank\helper::create_navigation_node($categorycontext),
 455              \repository_contentbank\helper::create_navigation_node($categorycoursecontext)
 456          ];
 457          $this->assertEquals($expected, $navigation);
 458  
 459          // Get navigation nodes in the subcategory course context.
 460          $browser = new \repository_contentbank\browser\contentbank_browser_context_course($subcategorycoursecontext);
 461          $navigation = $browser->get_navigation();
 462          // The navigation array should contain 4 elements, representing the system, category, subcategory and
 463          // subcategory course navigation nodes.
 464          $this->assertCount(4, $navigation);
 465          $expected = [
 466              \repository_contentbank\helper::create_navigation_node($systemcontext),
 467              \repository_contentbank\helper::create_navigation_node($categorycontext),
 468              \repository_contentbank\helper::create_navigation_node($subcategorycontext),
 469              \repository_contentbank\helper::create_navigation_node($subcategorycoursecontext)
 470          ];
 471          $this->assertEquals($expected, $navigation);
 472      }
 473  
 474      /**
 475       * Generate the expected array of content bank nodes.
 476       *
 477       * @param array $contextfolders The array containing the expected folder nodes
 478       * @param array $contentbankcontents The array containing the expected contents
 479       * @return array[] The expected array of content bank nodes
 480       */
 481      private function generate_expected_content(array $contextfolders = [], array $contentbankcontents = []): array {
 482  
 483          $expected = [];
 484          if (!empty($contextfolders)) {
 485              foreach ($contextfolders as $contextfolder) {
 486                  $expected[] = \repository_contentbank\helper::create_context_folder_node($contextfolder['name'],
 487                      base64_encode(json_encode(['contextid' => $contextfolder['contextid']])));
 488              }
 489          }
 490          if (!empty($contentbankcontents)) {
 491              foreach ($contentbankcontents as $content) {
 492                  $expected[] = \repository_contentbank\helper::create_contentbank_content_node($content);
 493              }
 494          }
 495          return $expected;
 496      }
 497  }