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; 18 19 /** 20 * Unit tests for context helper class. 21 * 22 * NOTE: more tests are in lib/tests/accesslib_test.php 23 * 24 * @package core 25 * @copyright Petr Skoda 26 * @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 27 * @coversDefaultClass \core\context_helper 28 */ 29 class context_helper_test extends \advanced_testcase { 30 /** 31 * Tests covered method. 32 * @covers ::parse_external_level 33 */ 34 public function test_parse_external_level() { 35 $this->assertSame(context\system::class, context_helper::parse_external_level('system')); 36 $this->assertSame(context\system::class, context_helper::parse_external_level(CONTEXT_SYSTEM)); 37 $this->assertSame(context\system::class, context_helper::parse_external_level((string)CONTEXT_SYSTEM)); 38 39 $this->assertSame(context\user::class, context_helper::parse_external_level('user')); 40 $this->assertSame(context\user::class, context_helper::parse_external_level(CONTEXT_USER)); 41 $this->assertSame(context\user::class, context_helper::parse_external_level((string)CONTEXT_USER)); 42 43 $this->assertSame(context\coursecat::class, context_helper::parse_external_level('coursecat')); 44 $this->assertSame(context\coursecat::class, context_helper::parse_external_level(CONTEXT_COURSECAT)); 45 $this->assertSame(context\coursecat::class, context_helper::parse_external_level((string)CONTEXT_COURSECAT)); 46 47 $this->assertSame(context\course::class, context_helper::parse_external_level('course')); 48 $this->assertSame(context\course::class, context_helper::parse_external_level(CONTEXT_COURSE)); 49 $this->assertSame(context\course::class, context_helper::parse_external_level((string)CONTEXT_COURSE)); 50 51 $this->assertSame(context\module::class, context_helper::parse_external_level('module')); 52 $this->assertSame(context\module::class, context_helper::parse_external_level(CONTEXT_MODULE)); 53 $this->assertSame(context\module::class, context_helper::parse_external_level((string)CONTEXT_MODULE)); 54 55 $this->assertSame(context\block::class, context_helper::parse_external_level('block')); 56 $this->assertSame(context\block::class, context_helper::parse_external_level(CONTEXT_BLOCK)); 57 $this->assertSame(context\block::class, context_helper::parse_external_level((string)CONTEXT_BLOCK)); 58 59 $this->assertNull(context_helper::parse_external_level('core_system')); 60 $this->assertNull(context_helper::parse_external_level('xsystem')); 61 $this->assertNull(context_helper::parse_external_level(1)); 62 $this->assertNull(context_helper::parse_external_level('')); 63 } 64 65 /** 66 * Tests covered method. 67 * @covers ::resolve_behat_reference 68 */ 69 public function test_resolve_behat_reference() { 70 $this->assertNull(context_helper::resolve_behat_reference('blahbla', 'blahbla')); 71 $this->assertNull(context_helper::resolve_behat_reference('', '')); 72 $this->assertNull(context_helper::resolve_behat_reference('0', '')); 73 74 $syscontext = context\system::instance(); 75 $result = context_helper::resolve_behat_reference('System', ''); 76 $this->assertSame($syscontext->id, $result->id); 77 78 $syscontext = context\system::instance(); 79 $result = context_helper::resolve_behat_reference('10', ''); 80 $this->assertSame($syscontext->id, $result->id); 81 82 // The rest is tested in each context class test. 83 } 84 85 /** 86 * Tests covered method. 87 * @covers ::get_class_for_level 88 */ 89 public function test_get_class_for_level() { 90 $this->assertSame(context\system::class, context_helper::get_class_for_level(CONTEXT_SYSTEM)); 91 $this->assertSame(context\system::class, context_helper::get_class_for_level((string)CONTEXT_SYSTEM)); 92 93 $this->assertSame(context\user::class, context_helper::get_class_for_level(CONTEXT_USER)); 94 $this->assertSame(context\user::class, context_helper::get_class_for_level((string)CONTEXT_USER)); 95 96 $this->assertSame(context\coursecat::class, context_helper::get_class_for_level(CONTEXT_COURSECAT)); 97 $this->assertSame(context\coursecat::class, context_helper::get_class_for_level((string)CONTEXT_COURSECAT)); 98 99 $this->assertSame(context\course::class, context_helper::get_class_for_level(CONTEXT_COURSE)); 100 $this->assertSame(context\course::class, context_helper::get_class_for_level((string)CONTEXT_COURSE)); 101 102 $this->assertSame(context\module::class, context_helper::get_class_for_level(CONTEXT_MODULE)); 103 $this->assertSame(context\module::class, context_helper::get_class_for_level((string)CONTEXT_MODULE)); 104 105 $this->assertSame(context\block::class, context_helper::get_class_for_level(CONTEXT_BLOCK)); 106 $this->assertSame(context\block::class, context_helper::get_class_for_level((string)CONTEXT_BLOCK)); 107 108 try { 109 context_helper::get_class_for_level(1); 110 $this->fail('Exception expected if level does not exist'); 111 } catch (\moodle_exception $e) { 112 $this->assertInstanceOf(\coding_exception::class, $e); 113 $this->assertSame('Coding error detected, it must be fixed by a programmer: Invalid context level specified', 114 $e->getMessage()); 115 } 116 } 117 118 /** 119 * Tests covered method. 120 * @covers ::get_all_levels 121 */ 122 public function test_get_all_levels() { 123 $levels = context_helper::get_all_levels(); 124 125 $this->assertArrayHasKey(CONTEXT_SYSTEM, $levels); 126 $this->assertSame(context\system::class, $levels[CONTEXT_SYSTEM]); 127 128 $this->assertArrayHasKey(CONTEXT_USER, $levels); 129 $this->assertSame(context\user::class, $levels[CONTEXT_USER]); 130 131 $this->assertArrayHasKey(CONTEXT_COURSECAT, $levels); 132 $this->assertSame(context\coursecat::class, $levels[CONTEXT_COURSECAT]); 133 134 $this->assertArrayHasKey(CONTEXT_COURSE, $levels); 135 $this->assertSame(context\course::class, $levels[CONTEXT_COURSE]); 136 137 $this->assertArrayHasKey(CONTEXT_MODULE, $levels); 138 $this->assertSame(context\module::class, $levels[CONTEXT_MODULE]); 139 140 $this->assertArrayHasKey(CONTEXT_BLOCK, $levels); 141 $this->assertSame(context\block::class, $levels[CONTEXT_BLOCK]); 142 143 $sorted = $levels; 144 ksort($sorted, SORT_NUMERIC); 145 $block = $sorted[CONTEXT_BLOCK]; 146 unset($sorted[CONTEXT_BLOCK]); 147 $sorted[CONTEXT_BLOCK] = $block; 148 $this->assertSame(array_keys($sorted), array_keys($levels)); 149 150 // Make sure level is set properly. 151 foreach ($levels as $level => $classname) { 152 $this->assertEquals($level, $classname::LEVEL); 153 if ($level != CONTEXT_SYSTEM) { 154 $this->assertGreaterThan(CONTEXT_SYSTEM, $level); 155 } 156 } 157 } 158 159 /** 160 * Tests covered method. 161 * @covers ::get_child_levels 162 */ 163 public function test_get_child_levels() { 164 $alllevels = context_helper::get_all_levels(); 165 166 $childlevels = context_helper::get_child_levels(CONTEXT_SYSTEM); 167 $this->assertSame(count($alllevels) - 1, count($childlevels)); 168 169 $childlevels = context_helper::get_child_levels(CONTEXT_USER); 170 $this->assertNotContains(CONTEXT_SYSTEM, $childlevels); 171 $this->assertNotContains(CONTEXT_USER, $childlevels); 172 $this->assertNotContains(CONTEXT_COURSECAT, $childlevels); 173 $this->assertNotContains(CONTEXT_COURSE, $childlevels); 174 $this->assertNotContains(CONTEXT_MODULE, $childlevels); 175 $this->assertContains(CONTEXT_BLOCK, $childlevels); 176 177 $childlevels = context_helper::get_child_levels(CONTEXT_COURSECAT); 178 $this->assertNotContains(CONTEXT_SYSTEM, $childlevels); 179 $this->assertNotContains(CONTEXT_USER, $childlevels); 180 $this->assertContains(CONTEXT_COURSECAT, $childlevels); 181 $this->assertContains(CONTEXT_COURSE, $childlevels); 182 $this->assertContains(CONTEXT_MODULE, $childlevels); 183 $this->assertContains(CONTEXT_BLOCK, $childlevels); 184 185 $childlevels = context_helper::get_child_levels(CONTEXT_COURSE); 186 $this->assertNotContains(CONTEXT_SYSTEM, $childlevels); 187 $this->assertNotContains(CONTEXT_USER, $childlevels); 188 $this->assertNotContains(CONTEXT_COURSECAT, $childlevels); 189 $this->assertNotContains(CONTEXT_COURSE, $childlevels); 190 $this->assertContains(CONTEXT_MODULE, $childlevels); 191 $this->assertContains(CONTEXT_BLOCK, $childlevels); 192 193 $childlevels = context_helper::get_child_levels(CONTEXT_MODULE); 194 $this->assertNotContains(CONTEXT_SYSTEM, $childlevels); 195 $this->assertNotContains(CONTEXT_USER, $childlevels); 196 $this->assertNotContains(CONTEXT_COURSECAT, $childlevels); 197 $this->assertNotContains(CONTEXT_COURSE, $childlevels); 198 $this->assertNotContains(CONTEXT_MODULE, $childlevels); 199 $this->assertContains(CONTEXT_BLOCK, $childlevels); 200 201 $childlevels = context_helper::get_child_levels(CONTEXT_BLOCK); 202 $this->assertCount(0, $childlevels); 203 } 204 205 /** 206 * Tests covered method. 207 * @covers ::get_compatible_levels 208 */ 209 public function test_get_compatible_levels() { 210 $levels = context_helper::get_compatible_levels('manager'); 211 $this->assertContains(CONTEXT_SYSTEM, $levels); 212 $this->assertNotContains(CONTEXT_USER, $levels); 213 $this->assertContains(CONTEXT_COURSECAT, $levels); 214 $this->assertContains(CONTEXT_COURSE, $levels); 215 $this->assertNotContains(CONTEXT_MODULE, $levels); 216 $this->assertNotContains(CONTEXT_BLOCK, $levels); 217 218 $levels = context_helper::get_compatible_levels('coursecreator'); 219 $this->assertContains(CONTEXT_SYSTEM, $levels); 220 $this->assertNotContains(CONTEXT_USER, $levels); 221 $this->assertContains(CONTEXT_COURSECAT, $levels); 222 $this->assertNotContains(CONTEXT_COURSE, $levels); 223 $this->assertNotContains(CONTEXT_MODULE, $levels); 224 $this->assertNotContains(CONTEXT_BLOCK, $levels); 225 226 $levels = context_helper::get_compatible_levels('editingteacher'); 227 $this->assertNotContains(CONTEXT_SYSTEM, $levels); 228 $this->assertNotContains(CONTEXT_USER, $levels); 229 $this->assertNotContains(CONTEXT_COURSECAT, $levels); 230 $this->assertContains(CONTEXT_COURSE, $levels); 231 $this->assertContains(CONTEXT_MODULE, $levels); 232 $this->assertNotContains(CONTEXT_BLOCK, $levels); 233 234 $levels = context_helper::get_compatible_levels('teacher'); 235 $this->assertNotContains(CONTEXT_SYSTEM, $levels); 236 $this->assertNotContains(CONTEXT_USER, $levels); 237 $this->assertNotContains(CONTEXT_COURSECAT, $levels); 238 $this->assertContains(CONTEXT_COURSE, $levels); 239 $this->assertContains(CONTEXT_MODULE, $levels); 240 $this->assertNotContains(CONTEXT_BLOCK, $levels); 241 242 $levels = context_helper::get_compatible_levels('student'); 243 $this->assertNotContains(CONTEXT_SYSTEM, $levels); 244 $this->assertNotContains(CONTEXT_USER, $levels); 245 $this->assertNotContains(CONTEXT_COURSECAT, $levels); 246 $this->assertContains(CONTEXT_COURSE, $levels); 247 $this->assertContains(CONTEXT_MODULE, $levels); 248 $this->assertNotContains(CONTEXT_BLOCK, $levels); 249 250 $levels = context_helper::get_compatible_levels('user'); 251 $this->assertCount(0, $levels); 252 253 $levels = context_helper::get_compatible_levels('guest'); 254 $this->assertCount(0, $levels); 255 256 $levels = context_helper::get_compatible_levels('frontpage'); 257 $this->assertCount(0, $levels); 258 } 259 260 /** 261 * Tests covered method. 262 * @covers ::cleanup_instances 263 */ 264 public function test_cleanup_instances() { 265 global $DB; 266 267 $this->resetAfterTest(); 268 $this->preventResetByRollback(); 269 270 $prevcount = $DB->count_records('context', []); 271 context_helper::cleanup_instances(); 272 $count = $DB->count_records('context', []); 273 $this->assertSame($prevcount, $count); 274 275 // Insert bogus records for each level and see if they get removed, 276 // more test should be in tests for each context level. 277 $alllevels = context_helper::get_all_levels(); 278 foreach ($alllevels as $classname) { 279 if ($classname::LEVEL == CONTEXT_SYSTEM) { 280 continue; 281 } 282 $record = new \stdClass(); 283 $record->contextlevel = $classname::LEVEL; 284 $record->instanceid = 9999999999; 285 $record->path = null; 286 $record->depth = '2'; 287 $record->id = $DB->insert_record('context', $record); 288 $DB->set_field('context', 'path', SYSCONTEXTID . '/' . $record->id, ['id' => $record->id]); 289 } 290 context_helper::cleanup_instances(); 291 $count = $DB->count_records('context', []); 292 $this->assertSame($prevcount, $count); 293 } 294 295 /** 296 * Tests covered method. 297 * @covers ::create_instances 298 */ 299 public function test_create_instances() { 300 global $DB; 301 302 $this->resetAfterTest(); 303 $this->preventResetByRollback(); 304 305 $user = $this->getDataGenerator()->create_user(); 306 $usercontext = context\user::instance($user->id); 307 $category = $this->getDataGenerator()->create_category(); 308 $categorycontext = context\coursecat::instance($category->id); 309 $course = $this->getDataGenerator()->create_course(); 310 $coursecontext = context\course::instance($course->id); 311 $page = $this->getDataGenerator()->create_module('page', ['course' => $course->id]); 312 $pagecontext = context\module::instance($page->cmid); 313 314 $prevcount = $DB->count_records('context', []); 315 $DB->delete_records('context', ['id' => $usercontext->id]); 316 $DB->delete_records('context', ['id' => $categorycontext->id]); 317 $DB->delete_records('context', ['id' => $coursecontext->id]); 318 $DB->delete_records('context', ['id' => $pagecontext->id]); 319 320 context_helper::create_instances(); 321 $count = $DB->count_records('context', []); 322 $this->assertSame($prevcount, $count); 323 } 324 325 /** 326 * Tests covered method. 327 * @covers ::build_all_paths 328 */ 329 public function test_build_all_paths() { 330 $this->resetAfterTest(); 331 $this->preventResetByRollback(); 332 333 // Just make sure there are no fatal errors for now. 334 context_helper::build_all_paths(true); 335 context_helper::build_all_paths(); 336 } 337 338 /** 339 * Tests covered method. 340 * @covers ::reset_caches 341 */ 342 public function test_reset_caches() { 343 $this->resetAfterTest(); 344 $this->preventResetByRollback(); 345 346 // Just make sure there are no fatal errors for now. 347 context_helper::reset_caches(); 348 } 349 350 /** 351 * Tests covered method. 352 * @covers ::get_preload_record_columns 353 */ 354 public function test_get_preload_record_columns() { 355 $expected = array ( 356 'testalias.id' => 'ctxid', 357 'testalias.path' => 'ctxpath', 358 'testalias.depth' => 'ctxdepth', 359 'testalias.contextlevel' => 'ctxlevel', 360 'testalias.instanceid' => 'ctxinstance', 361 'testalias.locked' => 'ctxlocked', 362 ); 363 $result = context_helper::get_preload_record_columns('testalias'); 364 $this->assertSame($expected, $result); 365 } 366 367 /** 368 * Tests covered method. 369 * @covers ::get_preload_record_columns_sql 370 */ 371 public function test_get_preload_record_columns_sql() { 372 global $DB; 373 374 $result = context_helper::get_preload_record_columns_sql('testalias'); 375 $expected = 'testalias.id AS ctxid, testalias.path AS ctxpath, testalias.depth AS ctxdepth,' 376 .' testalias.contextlevel AS ctxlevel, testalias.instanceid AS ctxinstance, testalias.locked AS ctxlocked'; 377 $this->assertSame($expected, $result); 378 379 $sql = "SELECT id, $result 380 FROM {context} testalias"; 381 $DB->get_records_sql($sql, []); 382 } 383 384 /** 385 * Tests covered method. 386 * @covers ::preload_from_record 387 */ 388 public function test_preload_from_record() { 389 global $DB; 390 391 $select = context_helper::get_preload_record_columns_sql('testalias'); 392 $sql = "SELECT id, $select 393 FROM {context} testalias"; 394 $records = $DB->get_records_sql($sql, []); 395 foreach ($records as $record) { 396 $this->assertNull(context_helper::preload_from_record($record)); 397 } 398 399 $this->assertDebuggingNotCalled(); 400 $record = reset($records); 401 unset($record->ctxlevel); 402 $this->assertNull(context_helper::preload_from_record($record)); 403 } 404 405 /** 406 * Tests covered method. 407 * @covers ::preload_contexts_by_id 408 */ 409 public function test_preload_contexts_by_id() { 410 global $DB; 411 412 $contextids = $DB->get_fieldset_sql("SELECT id FROM {context}", []); 413 context_helper::preload_contexts_by_id($contextids); 414 context_helper::preload_contexts_by_id($contextids); 415 416 context_helper::reset_caches(); 417 context_helper::preload_contexts_by_id($contextids); 418 } 419 420 /** 421 * Tests covered method. 422 * @covers ::preload_course 423 */ 424 public function test_preload_course() { 425 global $SITE; 426 context_helper::preload_course($SITE->id); 427 } 428 429 /** 430 * Tests covered method. 431 * @covers ::delete_instance 432 */ 433 public function test_delete_instance() { 434 $this->resetAfterTest(); 435 436 $user = $this->getDataGenerator()->create_user(); 437 $category = $this->getDataGenerator()->create_category(); 438 $course = $this->getDataGenerator()->create_course(); 439 $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id)); 440 441 // This is a bit silly test, it might start failing in the future 442 // because the instances are not deleted before deleting the contexts. 443 context_helper::delete_instance(CONTEXT_USER, $user->id); 444 context_helper::delete_instance(CONTEXT_COURSECAT, $category->id); 445 context_helper::delete_instance(CONTEXT_COURSE, $course->id); 446 context_helper::delete_instance(CONTEXT_MODULE, $page->cmid); 447 } 448 449 /** 450 * Tests covered method. 451 * @covers ::get_level_name 452 */ 453 public function test_get_level_name() { 454 $allevels = context_helper::get_all_levels(); 455 foreach ($allevels as $level => $classname) { 456 $name = context_helper::get_level_name($level); 457 $this->assertIsString($name); 458 } 459 460 $this->assertSame('System', context_helper::get_level_name(CONTEXT_SYSTEM)); 461 $this->assertSame('User', context_helper::get_level_name(CONTEXT_USER)); 462 $this->assertSame('Category', context_helper::get_level_name(CONTEXT_COURSECAT)); 463 $this->assertSame('Course', context_helper::get_level_name(CONTEXT_COURSE)); 464 $this->assertSame('Activity module', context_helper::get_level_name(CONTEXT_MODULE)); 465 $this->assertSame('Block', context_helper::get_level_name(CONTEXT_BLOCK)); 466 } 467 468 /** 469 * Tests covered method. 470 * @covers ::get_navigation_filter_context 471 */ 472 public function test_get_navigation_filter_context() { 473 global $CFG; 474 $this->resetAfterTest(); 475 476 $user = $this->getDataGenerator()->create_user(); 477 $usercontext = context\user::instance($user->id); 478 $category = $this->getDataGenerator()->create_category(); 479 $categorycontext = context\coursecat::instance($category->id); 480 $course = $this->getDataGenerator()->create_course(); 481 $coursecontext = context\course::instance($course->id); 482 $page = $this->getDataGenerator()->create_module('page', array('course' => $course->id)); 483 $pagecontext = context\module::instance($page->cmid); 484 $systemcontext = context\system::instance(); 485 486 // Default is OFF. 487 $this->assertSame('0', $CFG->filternavigationwithsystemcontext); 488 489 // First test passed values are returned if disabled. 490 set_config('filternavigationwithsystemcontext', '0'); 491 492 $this->assertNull(context_helper::get_navigation_filter_context(null)); 493 494 $filtercontext = context_helper::get_navigation_filter_context($systemcontext); 495 $this->assertSame($systemcontext, $filtercontext); 496 497 $filtercontext = context_helper::get_navigation_filter_context($usercontext); 498 $this->assertSame($usercontext, $filtercontext); 499 500 $filtercontext = context_helper::get_navigation_filter_context($categorycontext); 501 $this->assertSame($categorycontext, $filtercontext); 502 503 $filtercontext = context_helper::get_navigation_filter_context($coursecontext); 504 $this->assertSame($coursecontext, $filtercontext); 505 506 $filtercontext = context_helper::get_navigation_filter_context($pagecontext); 507 $this->assertSame($pagecontext, $filtercontext); 508 509 // Now test that any input returns system context if enabled. 510 set_config('filternavigationwithsystemcontext', '1'); 511 512 $filtercontext = context_helper::get_navigation_filter_context(null); 513 $this->assertSame($systemcontext->id, $filtercontext->id); 514 515 $filtercontext = context_helper::get_navigation_filter_context($systemcontext); 516 $this->assertSame($systemcontext->id, $filtercontext->id); 517 518 $filtercontext = context_helper::get_navigation_filter_context($usercontext); 519 $this->assertSame($systemcontext->id, $filtercontext->id); 520 521 $filtercontext = context_helper::get_navigation_filter_context($categorycontext); 522 $this->assertSame($systemcontext->id, $filtercontext->id); 523 524 $filtercontext = context_helper::get_navigation_filter_context($coursecontext); 525 $this->assertSame($systemcontext->id, $filtercontext->id); 526 527 $filtercontext = context_helper::get_navigation_filter_context($pagecontext); 528 $this->assertSame($systemcontext->id, $filtercontext->id); 529 } 530 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body