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]

   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   * Test for extensions manager.
  19   *
  20   * @package    core_contentbank
  21   * @category   test
  22   * @copyright  2020 Amaia Anabitarte <amaia@moodle.com>
  23   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  24   */
  25  
  26  namespace core_contentbank;
  27  
  28  defined('MOODLE_INTERNAL') || die();
  29  
  30  use advanced_testcase;
  31  use context_block;
  32  use context_course;
  33  use context_coursecat;
  34  use context_module;
  35  use context_system;
  36  use context_user;
  37  use Exception;
  38  
  39  global $CFG;
  40  require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_contenttype.php');
  41  require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_content.php');
  42  
  43  /**
  44   * Test for extensions manager.
  45   *
  46   * @package    core_contentbank
  47   * @category   test
  48   * @copyright  2020 Amaia Anabitarte <amaia@moodle.com>
  49   * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  50   * @coversDefaultClass \core_contentbank\contentbank
  51   */
  52  class contentbank_test extends advanced_testcase {
  53  
  54      /**
  55       * Setup to ensure that fixtures are loaded.
  56       */
  57      public static function setupBeforeClass(): void {
  58          global $CFG;
  59  
  60          require_once($CFG->dirroot . '/contentbank/tests/fixtures/testable_contenttype.php');
  61      }
  62  
  63      /**
  64       * Data provider for test_get_extension_supporter.
  65       *
  66       * @return  array
  67       */
  68      public function get_extension_provider() {
  69          return [
  70              'H5P file' => ['something.h5p', '.h5p'],
  71              'PDF file' => ['something.pdf', '.pdf']
  72          ];
  73      }
  74  
  75      /**
  76       * Tests for get_extension() function.
  77       *
  78       * @dataProvider    get_extension_provider
  79       * @param   string  $filename    The filename given
  80       * @param   string   $expected   The extension of the file
  81       *
  82       * @covers ::get_extension
  83       */
  84      public function test_get_extension(string $filename, string $expected) {
  85          $this->resetAfterTest();
  86  
  87          $cb = new contentbank();
  88  
  89          $extension = $cb->get_extension($filename);
  90          $this->assertEquals($expected, $extension);
  91      }
  92  
  93      /**
  94       * Data provider for test_load_context_supported_extensions.
  95       *
  96       * @return  array
  97       */
  98      public function get_extension_supporters_provider() {
  99          return [
 100              'H5P first' => [['.h5p' => ['h5p', 'testable']], '.h5p', 'h5p'],
 101              'Testable first (but upload not implemented)' => [['.h5p' => ['testable', 'h5p']], '.h5p', 'h5p'],
 102          ];
 103      }
 104  
 105      /**
 106       * Tests for get_extension_supporter() function with admin permissions.
 107       *
 108       * @dataProvider    get_extension_supporters_provider
 109       * @param   array   $supporters   The content type plugin supporters for each extension
 110       * @param   string  $extension    The extension of the file given
 111       * @param   string  $expected   The supporter contenttype of the file
 112       *
 113       * @covers ::load_context_supported_extensions
 114       */
 115      public function test_get_extension_supporter_for_admins(array $supporters, string $extension, string $expected) {
 116          $this->resetAfterTest();
 117  
 118          $cb = new contentbank();
 119  
 120          $systemcontext = context_system::instance();
 121  
 122          // All contexts allowed for admins.
 123          $this->setAdminUser();
 124          $contextsupporters = $cb->load_context_supported_extensions($systemcontext);
 125          $this->assertArrayHasKey($extension, $contextsupporters);
 126          $this->assertEquals($expected, $contextsupporters[$extension]);
 127      }
 128  
 129      /**
 130       * Tests for get_extension_supporter() function with user default permissions.
 131       *
 132       * @dataProvider    get_extension_supporters_provider
 133       * @param   array   $supporters   The content type plugin supporters for each extension
 134       * @param   string  $extension    The extension of the file given
 135       * @param   string  $expected   The supporter contenttype of the file
 136       *
 137       * @covers ::load_context_supported_extensions
 138       */
 139      public function test_get_extension_supporter_for_users(array $supporters, string $extension, string $expected) {
 140          $this->resetAfterTest();
 141  
 142          $cb = new contentbank();
 143          $systemcontext = context_system::instance();
 144  
 145          // Set a user with no permissions.
 146          $user = $this->getDataGenerator()->create_user();
 147          $this->setUser($user);
 148  
 149          // Users with no capabilities can't upload content.
 150          $contextsupporters = $cb->load_context_supported_extensions($systemcontext);
 151          $this->assertEquals([], $contextsupporters);
 152      }
 153  
 154      /**
 155       * Tests for get_extension_supporter() function with teacher defaul permissions.
 156       *
 157       * @dataProvider    get_extension_supporters_provider
 158       * @param   array   $supporters   The content type plugin supporters for each extension
 159       * @param   string  $extension    The extension of the file given
 160       * @param   string  $expected   The supporter contenttype of the file
 161       *
 162       * @covers ::load_context_supported_extensions
 163       */
 164      public function test_get_extension_supporter_for_teachers(array $supporters, string $extension, string $expected) {
 165          $this->resetAfterTest();
 166  
 167          $cb = new contentbank();
 168  
 169          $course = $this->getDataGenerator()->create_course();
 170          $teacher = $this->getDataGenerator()->create_and_enrol($course, 'editingteacher');
 171          $this->setUser($teacher);
 172          $coursecontext = context_course::instance($course->id);
 173  
 174          // Teachers has permission in their context to upload supported by H5P content type.
 175          $contextsupporters = $cb->load_context_supported_extensions($coursecontext);
 176          $this->assertArrayHasKey($extension, $contextsupporters);
 177          $this->assertEquals($expected, $contextsupporters[$extension]);
 178      }
 179  
 180      /**
 181       * Tests for get_extension_supporter() function.
 182       *
 183       * @dataProvider    get_extension_supporters_provider
 184       * @param   array   $supporters   The content type plugin supporters for each extension
 185       * @param   string  $extension    The extension of the file given
 186       * @param   string  $expected   The supporter contenttype of the file
 187       *
 188       * @covers ::get_extension_supporter
 189       */
 190      public function test_get_extension_supporter(array $supporters, string $extension, string $expected) {
 191          $this->resetAfterTest();
 192  
 193          $cb = new contentbank();
 194          $systemcontext = context_system::instance();
 195          $this->setAdminUser();
 196  
 197          $supporter = $cb->get_extension_supporter($extension, $systemcontext);
 198          $this->assertEquals($expected, $supporter);
 199      }
 200  
 201      /**
 202       * Test the behaviour of search_contents().
 203       *
 204       * @dataProvider search_contents_provider
 205       * @param  string $search String to search.
 206       * @param  string $where Context where to search.
 207       * @param  int $expectedresult Expected result.
 208       * @param  array $contexts List of contexts where to create content.
 209       */
 210      public function test_search_contents(?string $search, string $where, int $expectedresult, array $contexts = [],
 211              array $contenttypes = null): void {
 212          global $DB, $CFG;
 213  
 214          $this->resetAfterTest();
 215          $this->setAdminUser();
 216  
 217          // Create users.
 218          $managerroleid = $DB->get_field('role', 'id', ['shortname' => 'manager']);
 219          $manager = $this->getDataGenerator()->create_user();
 220          $this->getDataGenerator()->role_assign($managerroleid, $manager->id);
 221  
 222          // Create a category and a course.
 223          $coursecat = $this->getDataGenerator()->create_category();
 224          $course = $this->getDataGenerator()->create_course();
 225          $existingcontexts = [];
 226          $existingcontexts['system'] = \context_system::instance();
 227          $existingcontexts['category'] = \context_coursecat::instance($coursecat->id);
 228          $existingcontexts['course'] = \context_course::instance($course->id);
 229  
 230          if (empty($where)) {
 231              $contextid = 0;
 232          } else {
 233              $contextid = $existingcontexts[$where]->id;
 234          }
 235  
 236          // Add some content to the content bank.
 237          $filepath = $CFG->dirroot . '/h5p/tests/fixtures/filltheblanks.h5p';
 238          $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
 239          foreach ($contexts as $context) {
 240              $contextinstance = $existingcontexts[$context];
 241              $records = $generator->generate_contentbank_data('contenttype_h5p', 3,
 242                  $manager->id, $contextinstance, false, $filepath);
 243          }
 244  
 245          // Search for some content.
 246          $cb = new contentbank();
 247          $contents = $cb->search_contents($search, $contextid, $contenttypes);
 248  
 249          $this->assertCount($expectedresult, $contents);
 250          if (!empty($contents) && !empty($search)) {
 251              foreach ($contents as $content) {
 252                  $this->assertStringContainsString($search, $content->get_name());
 253              }
 254          }
 255      }
 256  
 257      /**
 258       * Data provider for test_search_contents().
 259       *
 260       * @return array
 261       */
 262      public function search_contents_provider(): array {
 263  
 264          return [
 265              'Search all content in all contexts' => [
 266                  null,
 267                  '',
 268                  9,
 269                  ['system', 'category', 'course']
 270              ],
 271              'Search in all contexts for existing string in all contents' => [
 272                  'content',
 273                  '',
 274                  9,
 275                  ['system', 'category', 'course']
 276              ],
 277              'Search in all contexts for unexisting string in all contents' => [
 278                  'chocolate',
 279                  '',
 280                  0,
 281                  ['system', 'category', 'course']
 282              ],
 283              'Search in all contexts for existing string in some contents' => [
 284                  '1',
 285                  '',
 286                  3,
 287                  ['system', 'category', 'course']
 288              ],
 289              'Search in all contexts for existing string in some contents (create only 1 context)' => [
 290                  '1',
 291                  '',
 292                  1,
 293                  ['system']
 294              ],
 295              'Search in system context for existing string in all contents' => [
 296                  'content',
 297                  'system',
 298                  3,
 299                  ['system', 'category', 'course']
 300              ],
 301              'Search in category context for unexisting string in all contents' => [
 302                  'chocolate',
 303                  'category',
 304                  0,
 305                  ['system', 'category', 'course']
 306              ],
 307              'Search in course context for existing string in some contents' => [
 308                  '1',
 309                  'course',
 310                  1,
 311                  ['system', 'category', 'course']
 312              ],
 313              'Search in system context' => [
 314                  null,
 315                  'system',
 316                  3,
 317                  ['system', 'category', 'course']
 318              ],
 319              'Search in course context with existing content' => [
 320                  null,
 321                  'course',
 322                  3,
 323                  ['system', 'category', 'course']
 324              ],
 325              'Search in course context without existing content' => [
 326                  null,
 327                  'course',
 328                  0,
 329                  ['system', 'category']
 330              ],
 331              'Search in an empty contentbank' => [
 332                  null,
 333                  '',
 334                  0,
 335                  []
 336              ],
 337              'Search in a context in an empty contentbank' => [
 338                  null,
 339                  'system',
 340                  0,
 341                  []
 342              ],
 343              'Search for a string in an empty contentbank' => [
 344                  'content',
 345                  '',
 346                  0,
 347                  []
 348              ],
 349              'Search with unexisting content-type' => [
 350                  null,
 351                  'course',
 352                  0,
 353                  ['system', 'category', 'course'],
 354                  ['contenttype_unexisting'],
 355              ],
 356          ];
 357      }
 358  
 359      /**
 360       * Test create_content_from_file function.
 361       *
 362       * @covers ::create_content_from_file
 363       */
 364      public function test_create_content_from_file() {
 365          global $USER, $CFG;
 366  
 367          $this->resetAfterTest();
 368          $this->setAdminUser();
 369          $systemcontext = \context_system::instance();
 370          $name = 'greeting-card.h5p';
 371  
 372          // Create a dummy H5P file.
 373          $dummyh5p = array(
 374              'contextid' => $systemcontext->id,
 375              'component' => 'contentbank',
 376              'filearea' => 'public',
 377              'itemid' => 1,
 378              'filepath' => '/',
 379              'filename' => $name,
 380              'userid' => $USER->id
 381          );
 382          $path = $CFG->dirroot . '/h5p/tests/fixtures/' . $name;
 383          $dummyh5pfile = \core_h5p\helper::create_fake_stored_file_from_path($path);
 384  
 385          $cb = new contentbank();
 386          $content = $cb->create_content_from_file($systemcontext, $USER->id, $dummyh5pfile);
 387  
 388          $this->assertEquals('contenttype_h5p', $content->get_content_type());
 389          $this->assertInstanceOf('\\contenttype_h5p\\content', $content);
 390          $this->assertEquals($name, $content->get_name());
 391      }
 392  
 393      /**
 394       * Test the behaviour of delete_contents().
 395       *
 396       * @covers  ::delete_contents
 397       */
 398      public function test_delete_contents() {
 399          global $DB;
 400  
 401          $this->resetAfterTest();
 402          $cb = new \core_contentbank\contentbank();
 403  
 404          // Create a category and two courses.
 405          $systemcontext = context_system::instance();
 406          $coursecat = $this->getDataGenerator()->create_category();
 407          $coursecatcontext = context_coursecat::instance($coursecat->id);
 408          $course1 = $this->getDataGenerator()->create_course();
 409          $course1context = context_course::instance($course1->id);
 410          $course2 = $this->getDataGenerator()->create_course();
 411          $course2context = context_course::instance($course2->id);
 412  
 413          // Add some content to the content bank.
 414          $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
 415          $systemcontent = $generator->generate_contentbank_data(null, 3, 0, $systemcontext);
 416          $categorycontent = $generator->generate_contentbank_data(null, 3, 0, $coursecatcontext);
 417          $course1content = $generator->generate_contentbank_data(null, 3, 0, $course1context);
 418          $course2content = $generator->generate_contentbank_data(null, 3, 0, $course2context);
 419  
 420          // Check the content has been created as expected.
 421          $this->assertEquals(12, $DB->count_records('contentbank_content'));
 422  
 423          // Check the system content is deleted as expected and the rest of the content is not.
 424          $this->assertTrue($cb->delete_contents($systemcontext));
 425          $this->assertEquals(0, $DB->count_records('contentbank_content', ['contextid' => $systemcontext->id]));
 426          // And the rest of the context content exists.
 427          $this->assertEquals(9, $DB->count_records('contentbank_content'));
 428  
 429          // Check the course category content is deleted as expected and the rest of the content is not.
 430          $this->assertTrue($cb->delete_contents($coursecatcontext));
 431          $this->assertEquals(0, $DB->count_records('contentbank_content', ['contextid' => $coursecatcontext->id]));
 432          // And the rest of the context content exists.
 433          $this->assertEquals(6, $DB->count_records('contentbank_content'));
 434  
 435          // Check the course content is deleted as expected and the rest of the content is not.
 436          $this->assertTrue($cb->delete_contents($course1context));
 437          $this->assertEquals(0, $DB->count_records('contentbank_content', ['contextid' => $course1context->id]));
 438          // And the rest of the context content exists.
 439          $this->assertEquals(3, $DB->count_records('contentbank_content'));
 440      }
 441  
 442      /**
 443       * Test the behaviour of delete_contents() for empty content bank.
 444       *
 445       * @covers  ::delete_contents
 446       */
 447      public function test_delete_contents_for_empty_contentbank() {
 448  
 449          $this->resetAfterTest();
 450          $cb = new \core_contentbank\contentbank();
 451  
 452          // Create a category and two courses.
 453          $systemcontext = \context_system::instance();
 454          $coursecat = $this->getDataGenerator()->create_category();
 455          $coursecatcontext = \context_coursecat::instance($coursecat->id);
 456          $course = $this->getDataGenerator()->create_course();
 457          $coursecontext = \context_course::instance($course->id);
 458  
 459          // Check there's no error when trying to delete content from an empty content bank.
 460          $this->assertTrue($cb->delete_contents($systemcontext));
 461          $this->assertTrue($cb->delete_contents($coursecatcontext));
 462          $this->assertTrue($cb->delete_contents($coursecontext));
 463      }
 464  
 465      /**
 466       * Test the behaviour of move_contents().
 467       *
 468       * @covers  ::move_contents
 469       */
 470      public function test_move_contents() {
 471          global $DB;
 472  
 473          $this->resetAfterTest();
 474          $cb = new \core_contentbank\contentbank();
 475  
 476          // Create a category and two courses.
 477          $course1 = $this->getDataGenerator()->create_course();
 478          $course1context = context_course::instance($course1->id);
 479          $course2 = $this->getDataGenerator()->create_course();
 480          $course2context = context_course::instance($course2->id);
 481  
 482          // Add some content to the content bank.
 483          $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
 484          $course1content = $generator->generate_contentbank_data(null, 3, 0, $course1context);
 485          $course2content = $generator->generate_contentbank_data(null, 3, 0, $course2context);
 486  
 487          // Check the content has been created as expected.
 488          $this->assertEquals(6, $DB->count_records('contentbank_content'));
 489          $this->assertEquals(3, $DB->count_records('contentbank_content', ['contextid' => $course1context->id]));
 490  
 491          // Check the content is moved to another context as expected and the rest of the content is not.
 492          $this->assertTrue($cb->move_contents($course1context, $course2context));
 493          $this->assertEquals(6, $DB->count_records('contentbank_content'));
 494          $this->assertEquals(0, $DB->count_records('contentbank_content', ['contextid' => $course1context->id]));
 495          $this->assertEquals(6, $DB->count_records('contentbank_content', ['contextid' => $course2context->id]));
 496      }
 497  
 498      /**
 499       * Test the behaviour of move_contents() for empty content bank.
 500       *
 501       * @covers  ::move_contents
 502       */
 503      public function test_move_contents_for_empty_contentbank() {
 504  
 505          $this->resetAfterTest();
 506          $cb = new \core_contentbank\contentbank();
 507  
 508          // Create a category and two courses.
 509          $systemcontext = \context_system::instance();
 510          $course = $this->getDataGenerator()->create_course();
 511          $coursecontext = \context_course::instance($course->id);
 512  
 513          // Check there's no error when trying to move content context from an empty content bank.
 514          $this->assertTrue($cb->delete_contents($systemcontext, $coursecontext));
 515      }
 516  
 517      /**
 518       * Data provider for get_contenttypes_with_capability_feature.
 519       *
 520       * @return  array
 521       */
 522      public function get_contenttypes_with_capability_feature_provider(): array {
 523          return [
 524              'no-contenttypes_enabled' => [
 525                  'contenttypesenabled' => [],
 526                  'contenttypescanfeature' => [],
 527              ],
 528              'contenttype_enabled_noeditable' => [
 529                  'contenttypesenabled' => ['testable'],
 530                  'contenttypescanfeature' => [],
 531              ],
 532              'contenttype_enabled_editable' => [
 533                  'contenttypesenabled' => ['testable'],
 534                  'contenttypescanfeature' => ['testable'],
 535              ],
 536              'no-contenttype_enabled_editable' => [
 537                  'contenttypesenabled' => [],
 538                  'contenttypescanfeature' => ['testable'],
 539              ],
 540          ];
 541      }
 542  
 543      /**
 544       * Tests for get_contenttypes_with_capability_feature() function.
 545       *
 546       * @dataProvider    get_contenttypes_with_capability_feature_provider
 547       * @param   array $contenttypesenabled Content types enabled.
 548       * @param   array $contenttypescanfeature Content types the user has the permission to use the feature.
 549       *
 550       * @covers ::get_contenttypes_with_capability_feature
 551       */
 552      public function test_get_contenttypes_with_capability_feature(array $contenttypesenabled, array $contenttypescanfeature): void {
 553          $this->resetAfterTest();
 554  
 555          $cb = new contentbank();
 556  
 557          $plugins = [];
 558  
 559          // Content types not enabled where the user has permission to use a feature.
 560          if (empty($contenttypesenabled) && !empty($contenttypescanfeature)) {
 561              $enabled = false;
 562  
 563              // Mock core_plugin_manager class and the method get_plugins_of_type.
 564              $pluginmanager = $this->getMockBuilder(\core_plugin_manager::class)
 565                  ->disableOriginalConstructor()
 566                  ->onlyMethods(['get_plugins_of_type'])
 567                  ->getMock();
 568  
 569              // Replace protected singletoninstance reference (core_plugin_manager property) with mock object.
 570              $ref = new \ReflectionProperty(\core_plugin_manager::class, 'singletoninstance');
 571              $ref->setAccessible(true);
 572              $ref->setValue(null, $pluginmanager);
 573  
 574              // Return values of get_plugins_of_type method.
 575              foreach ($contenttypescanfeature as $contenttypepluginname) {
 576                  $contenttypeplugin = new \stdClass();
 577                  $contenttypeplugin->name = $contenttypepluginname;
 578                  $contenttypeplugin->type = 'contenttype';
 579                  // Add the feature to the fake content type.
 580                  $classname = "\\contenttype_$contenttypepluginname\\contenttype";
 581                  $classname::$featurestotest = ['test2'];
 582                  $plugins[] = $contenttypeplugin;
 583              }
 584  
 585              // Set expectations and return values.
 586              $pluginmanager->expects($this->once())
 587                  ->method('get_plugins_of_type')
 588                  ->with('contenttype')
 589                  ->willReturn($plugins);
 590          } else {
 591              $enabled = true;
 592              // Get access to private property enabledcontenttypes.
 593              $rc = new \ReflectionClass(\core_contentbank\contentbank::class);
 594              $rcp = $rc->getProperty('enabledcontenttypes');
 595              $rcp->setAccessible(true);
 596  
 597              foreach ($contenttypesenabled as $contenttypename) {
 598                  $plugins["\\contenttype_$contenttypename\\contenttype"] = $contenttypename;
 599                  // Add to the testable contenttype the feature to test.
 600                  if (in_array($contenttypename, $contenttypescanfeature)) {
 601                      $classname = "\\contenttype_$contenttypename\\contenttype";
 602                      $classname::$featurestotest = ['test2'];
 603                  }
 604              }
 605              // Set as enabled content types only those in the test.
 606              $rcp->setValue($cb, $plugins);
 607          }
 608  
 609          $actual = $cb->get_contenttypes_with_capability_feature('test2', null, $enabled);
 610          $this->assertEquals($contenttypescanfeature, array_values($actual));
 611      }
 612  
 613      /**
 614       * Test the behaviour of get_content_from_id()
 615       *
 616       * @covers  ::get_content_from_id
 617       */
 618      public function test_get_content_from_id() {
 619  
 620          $this->resetAfterTest();
 621          $cb = new \core_contentbank\contentbank();
 622  
 623          // Create a category and two courses.
 624          $systemcontext = context_system::instance();
 625  
 626          // Add some content to the content bank.
 627          $generator = $this->getDataGenerator()->get_plugin_generator('core_contentbank');
 628          $contents = $generator->generate_contentbank_data(null, 3, 0, $systemcontext);
 629          $content = reset($contents);
 630  
 631          // Get the content instance form id.
 632          $newinstance = $cb->get_content_from_id($content->get_id());
 633          $this->assertEquals($content->get_id(), $newinstance->get_id());
 634  
 635          // Now produce and exception with an innexistent id.
 636          $this->expectException(Exception::class);
 637          $cb->get_content_from_id(0);
 638      }
 639  
 640      /**
 641       * Test the behaviour of is_context_allowed().
 642       *
 643       * @covers ::is_context_allowed
 644       */
 645      public function test_is_context_allowed(): void {
 646          $this->resetAfterTest();
 647  
 648          $cb = new contentbank();
 649  
 650          // System context.
 651          $this->assertTrue($cb->is_context_allowed(context_system::instance()));
 652  
 653          // User context.
 654          $user = $this->getDataGenerator()->create_user();
 655          $this->assertFalse($cb->is_context_allowed(context_user::instance($user->id)));
 656  
 657          // Category context.
 658          $category = $this->getDataGenerator()->create_category();
 659          $this->assertTrue($cb->is_context_allowed(context_coursecat::instance($category->id)));
 660  
 661          // Course context.
 662          $course = $this->getDataGenerator()->create_course(['category' => $category->id]);
 663          $coursecontext = context_course::instance($course->id);
 664          $this->assertTrue($cb->is_context_allowed($coursecontext));
 665  
 666          // Module context.
 667          $module = $this->getDataGenerator()->create_module('page', ['course' => $course->id]);
 668          $this->assertFalse($cb->is_context_allowed(context_module::instance($module->cmid)));
 669  
 670          // Block context.
 671          $block = $this->getDataGenerator()->create_block('online_users', ['parentcontextid' => $coursecontext->id]);
 672          $this->assertFalse($cb->is_context_allowed(context_block::instance($block->id)));
 673      }
 674  }