Search moodle.org's
Developer Documentation

See Release Notes

  • Bug fixes for general core bugs in 4.3.x will end 7 October 2024 (12 months).
  • Bug fixes for security issues in 4.3.x will end 21 April 2025 (18 months).
  • PHP version: minimum PHP 8.0.0 Note: minimum PHP version has increased since Moodle 4.1. PHP 8.2.x is supported too.
   1  <?php
   2  // This file is part of Moodle - https://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 <https://www.gnu.org/licenses/>.
  16  
  17  namespace core\context;
  18  
  19  use core\context, core\context_helper;
  20  
  21  /**
  22   * Unit tests for module context class.
  23   *
  24   * NOTE: more tests are in lib/tests/accesslib_test.php
  25   *
  26   * @package   core
  27   * @copyright Petr Skoda
  28   * @license   https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
  29   * @coversDefaultClass \core\context\module
  30   */
  31  class module_test extends \advanced_testcase {
  32      /**
  33       * Tests legacy class.
  34       * @coversNothing
  35       */
  36      public function test_legacy_classname() {
  37          $this->resetAfterTest();
  38  
  39          $course = $this->getDataGenerator()->create_course();
  40          $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id]);
  41          $context = module::instance($page->cmid);
  42  
  43          $this->assertInstanceOf(module::class, $context);
  44          $this->assertInstanceOf(\context_module::class, $context);
  45      }
  46  
  47      /**
  48       * Tests covered methods.
  49       * @covers ::instance
  50       * @covers \core\context::instance_by_id
  51       */
  52      public function test_factory_methods() {
  53          $this->resetAfterTest();
  54  
  55          $course = $this->getDataGenerator()->create_course();
  56          $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id]);
  57          $context = module::instance($page->cmid);
  58  
  59          $this->assertInstanceOf(module::class, $context);
  60          $this->assertSame((string)$page->cmid, $context->instanceid);
  61  
  62          $context = context::instance_by_id($context->id);
  63          $this->assertInstanceOf(module::class, $context);
  64          $this->assertSame((string)$page->cmid, $context->instanceid);
  65      }
  66  
  67      /**
  68       * Tests covered method.
  69       * @covers ::get_short_name
  70       */
  71      public function test_get_short_name() {
  72          $this->assertSame('module', module::get_short_name());
  73      }
  74  
  75      /**
  76       * Tests context level.
  77       * @coversNothing
  78       */
  79      public function test_level() {
  80          $this->assertSame(70, module::LEVEL);
  81          $this->assertSame(CONTEXT_MODULE, module::LEVEL);
  82      }
  83  
  84      /**
  85       * Tests covered method.
  86       * @covers ::get_level_name
  87       */
  88      public function test_get_level_name() {
  89          $this->assertSame('Activity module', module::get_level_name());
  90      }
  91  
  92      /**
  93       * Tests covered method.
  94       * @covers ::get_context_name
  95       */
  96      public function test_get_context_name() {
  97          $this->resetAfterTest();
  98  
  99          $course = $this->getDataGenerator()->create_course();
 100          $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id, 'name' => 'Pokus']);
 101          $context = module::instance($page->cmid);
 102  
 103          $this->assertSame('Page: Pokus', $context->get_context_name());
 104          $this->assertSame('Page: Pokus', $context->get_context_name(true));
 105          $this->assertSame('Pokus', $context->get_context_name(false));
 106          $this->assertSame('Pokus', $context->get_context_name(false, true));
 107          $this->assertSame('Page: Pokus', $context->get_context_name(true, true, false));
 108      }
 109  
 110      /**
 111       * Tests covered method.
 112       * @covers ::get_url
 113       */
 114      public function test_get_url() {
 115          $this->resetAfterTest();
 116  
 117          $course = $this->getDataGenerator()->create_course();
 118          $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id, 'name' => 'Pokus']);
 119          $context = module::instance($page->cmid);
 120  
 121          $expected = new \moodle_url('/mod/page/view.php', ['id' => $page->cmid]);
 122          $url = $context->get_url();
 123          $this->assertInstanceOf(\moodle_url::class, $url);
 124          $this->assertSame($expected->out(), $url->out());
 125      }
 126  
 127      /**
 128       * Tests covered methods.
 129       * @covers ::get_instance_table()
 130       * @covers ::get_behat_reference_columns()
 131       * @covers \core\context_helper::resolve_behat_reference
 132       */
 133      public function test_resolve_behat_reference() {
 134          global $DB;
 135          $this->resetAfterTest();
 136  
 137          $course = $this->getDataGenerator()->create_course();
 138          $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id, 'idnumber' => 'xyz']);
 139          $instance = $DB->get_record('course_modules', ['id' => $page->cmid], '*', MUST_EXIST);
 140          $context = module::instance($instance->id);
 141  
 142          $result = context_helper::resolve_behat_reference('Activity module', $instance->idnumber);
 143          $this->assertSame($context->id, $result->id);
 144  
 145          $result = context_helper::resolve_behat_reference('module', $instance->idnumber);
 146          $this->assertSame($context->id, $result->id);
 147  
 148          $result = context_helper::resolve_behat_reference('70', $instance->idnumber);
 149          $this->assertSame($context->id, $result->id);
 150  
 151          $result = context_helper::resolve_behat_reference('Activity module', 'dshjkdshjkhjsadjhdsa');
 152          $this->assertNull($result);
 153  
 154          $result = context_helper::resolve_behat_reference('Activity module', '');
 155          $this->assertNull($result);
 156      }
 157  
 158      /**
 159       * Tests covered method.
 160       * @covers ::get_compatible_role_archetypes
 161       */
 162      public function test_get_compatible_role_archetypes() {
 163          global $DB;
 164  
 165          $allarchetypes = $DB->get_fieldset_select('role', 'DISTINCT archetype', 'archetype IS NOT NULL');
 166          foreach ($allarchetypes as $allarchetype) {
 167              $levels = context_helper::get_compatible_levels($allarchetype);
 168              if ($allarchetype === 'editingteacher' || $allarchetype === 'teacher' || $allarchetype === 'student') {
 169                  $this->assertContains(module::LEVEL, $levels, "$allarchetype is expected to be compatible with context");
 170              } else {
 171                  $this->assertNotContains(module::LEVEL, $levels, "$allarchetype is not expected to be compatible with context");
 172              }
 173          }
 174      }
 175  
 176      /**
 177       * Tests covered method.
 178       * @covers ::get_possible_parent_levels
 179       */
 180      public function test_get_possible_parent_levels() {
 181          $this->assertSame([course::LEVEL], module::get_possible_parent_levels());
 182      }
 183  
 184      /**
 185       * Tests covered method.
 186       * @covers ::get_capabilities
 187       */
 188      public function test_get_capabilities() {
 189          $this->resetAfterTest();
 190  
 191          $course = $this->getDataGenerator()->create_course();
 192          $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id, 'name' => 'Pokus']);
 193          $context = module::instance($page->cmid);
 194  
 195          $capabilities = $context->get_capabilities();
 196          $capabilities = convert_to_array($capabilities);
 197          $capabilities = array_column($capabilities, 'name');
 198          $this->assertContains('mod/page:view', $capabilities);
 199          $this->assertNotContains('mod/url:view', $capabilities);
 200          $this->assertNotContains('moodle/course:view', $capabilities);
 201          $this->assertNotContains('moodle/category:manage', $capabilities);
 202          $this->assertNotContains('moodle/user:viewalldetails', $capabilities);
 203      }
 204  
 205      /**
 206       * Tests covered method.
 207       * @covers ::create_level_instances
 208       */
 209      public function test_create_level_instances() {
 210          global $DB;
 211          $this->resetAfterTest();
 212  
 213          $course = $this->getDataGenerator()->create_course();
 214          $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id, 'name' => 'Pokus']);
 215          $context = module::instance($page->cmid);
 216  
 217          $DB->delete_records('context', ['id' => $context->id]);
 218          context_helper::create_instances(module::LEVEL);
 219          $record = $DB->get_record('context', ['contextlevel' => module::LEVEL, 'instanceid' => $page->cmid], '*', MUST_EXIST);
 220      }
 221  
 222      /**
 223       * Tests covered method.
 224       * @covers ::get_child_contexts
 225       */
 226      public function test_get_child_contexts() {
 227          $this->resetAfterTest();
 228  
 229          $course = $this->getDataGenerator()->create_course();
 230          $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id, 'name' => 'Pokus']);
 231          $context = module::instance($page->cmid);
 232  
 233          $children = $context->get_child_contexts();
 234          $this->assertCount(0, $children);
 235      }
 236  
 237      /**
 238       * Tests covered method.
 239       * @covers ::get_cleanup_sql
 240       */
 241      public function test_get_cleanup_sql() {
 242          global $DB;
 243          $this->resetAfterTest();
 244  
 245          $course = $this->getDataGenerator()->create_course();
 246          $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id, 'name' => 'Pokus']);
 247          $context = module::instance($page->cmid);
 248  
 249          $DB->delete_records('course_modules', ['id' => $page->cmid]);
 250          $DB->delete_records('page', ['id' => $page->id]);
 251  
 252          context_helper::cleanup_instances();
 253          $this->assertFalse($DB->record_exists('context', ['contextlevel' => module::LEVEL, 'instanceid' => $page->cmid]));
 254      }
 255  
 256      /**
 257       * Tests covered method.
 258       * @covers ::build_paths
 259       */
 260      public function test_build_paths() {
 261          global $DB;
 262          $this->resetAfterTest();
 263  
 264          $syscontext = system::instance();
 265          $course = $this->getDataGenerator()->create_course();
 266          $coursecontext = course::instance($course->id);
 267          $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id, 'name' => 'Pokus']);
 268          $pagecontext = module::instance($page->cmid);
 269  
 270          $DB->set_field('context', 'depth', 1, ['id' => $pagecontext->id]);
 271          $DB->set_field('context', 'path', '/0', ['id' => $pagecontext->id]);
 272  
 273          context_helper::build_all_paths(true);
 274  
 275          $record = $DB->get_record('context', ['id' => $pagecontext->id]);
 276          $categorycontext = coursecat::instance($course->category);
 277          $this->assertSame('4', $record->depth);
 278          $this->assertSame('/' . $syscontext->id . '/' . $categorycontext->id . '/'
 279              . $coursecontext->id . '/' . $record->id, $record->path);
 280      }
 281  
 282      /**
 283       * Tests covered method.
 284       * @covers ::set_locked
 285       */
 286      public function test_set_locked() {
 287          global $DB;
 288          $this->resetAfterTest();
 289  
 290          $course = $this->getDataGenerator()->create_course();
 291          $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id, 'name' => 'Pokus']);
 292          $context = module::instance($page->cmid);
 293  
 294          $context->set_locked(true);
 295          $context = module::instance($page->cmid);
 296          $this->assertTrue($context->locked);
 297          $record = $DB->get_record('context', ['id' => $context->id]);
 298          $this->assertSame('1', $record->locked);
 299  
 300          $context->set_locked(false);
 301          $context = module::instance($page->cmid);
 302          $this->assertFalse($context->locked);
 303          $record = $DB->get_record('context', ['id' => $context->id]);
 304          $this->assertSame('0', $record->locked);
 305      }
 306  }