Differences Between: [Versions 311 and 400] [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403] [Versions 39 and 311]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Unit tests for lib/modinfolib.php. 19 * 20 * @package core 21 * @category phpunit 22 * @copyright 2012 Andrew Davis 23 */ 24 25 defined('MOODLE_INTERNAL') || die(); 26 27 global $CFG; 28 require_once($CFG->libdir . '/modinfolib.php'); 29 30 /** 31 * Unit tests for modinfolib.php 32 * 33 * @copyright 2012 Andrew Davis 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 class core_modinfolib_testcase extends advanced_testcase { 37 public function test_section_info_properties() { 38 global $DB, $CFG; 39 40 $this->resetAfterTest(); 41 $oldcfgenableavailability = $CFG->enableavailability; 42 $oldcfgenablecompletion = $CFG->enablecompletion; 43 set_config('enableavailability', 1); 44 set_config('enablecompletion', 1); 45 $this->setAdminUser(); 46 47 // Generate the course and pre-requisite module. 48 $course = $this->getDataGenerator()->create_course( 49 array('format' => 'topics', 50 'numsections' => 3, 51 'enablecompletion' => 1, 52 'groupmode' => SEPARATEGROUPS, 53 'forcegroupmode' => 0), 54 array('createsections' => true)); 55 $coursecontext = context_course::instance($course->id); 56 $prereqforum = $this->getDataGenerator()->create_module('forum', 57 array('course' => $course->id), 58 array('completion' => 1)); 59 60 // Add availability conditions. 61 $availability = '{"op":"&","showc":[true,true,true],"c":[' . 62 '{"type":"completion","cm":' . $prereqforum->cmid . ',"e":"' . 63 COMPLETION_COMPLETE . '"},' . 64 '{"type":"grade","id":666,"min":0.4},' . 65 '{"type":"profile","op":"contains","sf":"email","v":"test"}' . 66 ']}'; 67 $DB->set_field('course_sections', 'availability', $availability, 68 array('course' => $course->id, 'section' => 2)); 69 rebuild_course_cache($course->id, true); 70 $sectiondb = $DB->get_record('course_sections', array('course' => $course->id, 'section' => 2)); 71 72 // Create and enrol a student. 73 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST); 74 $student = $this->getDataGenerator()->create_user(); 75 role_assign($studentrole->id, $student->id, $coursecontext); 76 $enrolplugin = enrol_get_plugin('manual'); 77 $enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual')); 78 $enrolplugin->enrol_user($enrolinstance, $student->id); 79 $this->setUser($student); 80 81 // Get modinfo. 82 $modinfo = get_fast_modinfo($course->id); 83 $si = $modinfo->get_section_info(2); 84 85 $this->assertEquals($sectiondb->id, $si->id); 86 $this->assertEquals($sectiondb->course, $si->course); 87 $this->assertEquals($sectiondb->section, $si->section); 88 $this->assertEquals($sectiondb->name, $si->name); 89 $this->assertEquals($sectiondb->visible, $si->visible); 90 $this->assertEquals($sectiondb->summary, $si->summary); 91 $this->assertEquals($sectiondb->summaryformat, $si->summaryformat); 92 $this->assertEquals($sectiondb->sequence, $si->sequence); // Since this section does not contain invalid modules. 93 $this->assertEquals($availability, $si->availability); 94 95 // Dynamic fields, just test that they can be retrieved (must be carefully tested in each activity type). 96 $this->assertEquals(0, $si->available); 97 $this->assertNotEmpty($si->availableinfo); // Lists all unmet availability conditions. 98 $this->assertEquals(0, $si->uservisible); 99 100 // Restore settings. 101 set_config('enableavailability', $oldcfgenableavailability); 102 set_config('enablecompletion', $oldcfgenablecompletion); 103 } 104 105 public function test_cm_info_properties() { 106 global $DB, $CFG; 107 108 $this->resetAfterTest(); 109 $oldcfgenableavailability = $CFG->enableavailability; 110 $oldcfgenablecompletion = $CFG->enablecompletion; 111 set_config('enableavailability', 1); 112 set_config('enablecompletion', 1); 113 $this->setAdminUser(); 114 115 // Generate the course and pre-requisite module. 116 $course = $this->getDataGenerator()->create_course( 117 array('format' => 'topics', 118 'numsections' => 3, 119 'enablecompletion' => 1, 120 'groupmode' => SEPARATEGROUPS, 121 'forcegroupmode' => 0), 122 array('createsections' => true)); 123 $coursecontext = context_course::instance($course->id); 124 $prereqforum = $this->getDataGenerator()->create_module('forum', 125 array('course' => $course->id), 126 array('completion' => 1)); 127 128 // Generate module and add availability conditions. 129 $availability = '{"op":"&","showc":[true,true,true],"c":[' . 130 '{"type":"completion","cm":' . $prereqforum->cmid . ',"e":"' . 131 COMPLETION_COMPLETE . '"},' . 132 '{"type":"grade","id":666,"min":0.4},' . 133 '{"type":"profile","op":"contains","sf":"email","v":"test"}' . 134 ']}'; 135 $assign = $this->getDataGenerator()->create_module('assign', 136 array('course' => $course->id), 137 array('idnumber' => 123, 138 'groupmode' => VISIBLEGROUPS, 139 'availability' => $availability)); 140 rebuild_course_cache($course->id, true); 141 142 // Retrieve all related records from DB. 143 $assigndb = $DB->get_record('assign', array('id' => $assign->id)); 144 $moduletypedb = $DB->get_record('modules', array('name' => 'assign')); 145 $moduledb = $DB->get_record('course_modules', array('module' => $moduletypedb->id, 'instance' => $assign->id)); 146 $sectiondb = $DB->get_record('course_sections', array('id' => $moduledb->section)); 147 $modnamessingular = get_module_types_names(false); 148 $modnamesplural = get_module_types_names(true); 149 150 // Create and enrol a student. 151 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST); 152 $student = $this->getDataGenerator()->create_user(); 153 role_assign($studentrole->id, $student->id, $coursecontext); 154 $enrolplugin = enrol_get_plugin('manual'); 155 $enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual')); 156 $enrolplugin->enrol_user($enrolinstance, $student->id); 157 $this->setUser($student); 158 159 // Emulate data used in building course cache to receive the same instance of cached_cm_info as was used in building modinfo. 160 $rawmods = get_course_mods($course->id); 161 $cachedcminfo = assign_get_coursemodule_info($rawmods[$moduledb->id]); 162 163 // Get modinfo. 164 $modinfo = get_fast_modinfo($course->id); 165 $cm = $modinfo->instances['assign'][$assign->id]; 166 167 $this->assertEquals($moduledb->id, $cm->id); 168 $this->assertEquals($assigndb->id, $cm->instance); 169 $this->assertEquals($moduledb->course, $cm->course); 170 $this->assertEquals($moduledb->idnumber, $cm->idnumber); 171 $this->assertEquals($moduledb->added, $cm->added); 172 $this->assertEquals($moduledb->visible, $cm->visible); 173 $this->assertEquals($moduledb->visibleold, $cm->visibleold); 174 $this->assertEquals($moduledb->groupmode, $cm->groupmode); 175 $this->assertEquals(VISIBLEGROUPS, $cm->groupmode); 176 $this->assertEquals($moduledb->groupingid, $cm->groupingid); 177 $this->assertEquals($course->groupmodeforce, $cm->coursegroupmodeforce); 178 $this->assertEquals($course->groupmode, $cm->coursegroupmode); 179 $this->assertEquals(SEPARATEGROUPS, $cm->coursegroupmode); 180 $this->assertEquals($course->groupmodeforce ? $course->groupmode : $moduledb->groupmode, 181 $cm->effectivegroupmode); // (since mod_assign supports groups). 182 $this->assertEquals(VISIBLEGROUPS, $cm->effectivegroupmode); 183 $this->assertEquals($moduledb->indent, $cm->indent); 184 $this->assertEquals($moduledb->completion, $cm->completion); 185 $this->assertEquals($moduledb->completiongradeitemnumber, $cm->completiongradeitemnumber); 186 $this->assertEquals($moduledb->completionview, $cm->completionview); 187 $this->assertEquals($moduledb->completionexpected, $cm->completionexpected); 188 $this->assertEquals($moduledb->showdescription, $cm->showdescription); 189 $this->assertEquals(null, $cm->extra); // Deprecated field. Used in module types that don't return cached_cm_info. 190 $this->assertEquals($cachedcminfo->icon, $cm->icon); 191 $this->assertEquals($cachedcminfo->iconcomponent, $cm->iconcomponent); 192 $this->assertEquals('assign', $cm->modname); 193 $this->assertEquals($moduledb->module, $cm->module); 194 $this->assertEquals($cachedcminfo->name, $cm->name); 195 $this->assertEquals($sectiondb->section, $cm->sectionnum); 196 $this->assertEquals($moduledb->section, $cm->section); 197 $this->assertEquals($availability, $cm->availability); 198 $this->assertEquals(context_module::instance($moduledb->id), $cm->context); 199 $this->assertEquals($modnamessingular['assign'], $cm->modfullname); 200 $this->assertEquals($modnamesplural['assign'], $cm->modplural); 201 $this->assertEquals(new moodle_url('/mod/assign/view.php', array('id' => $moduledb->id)), $cm->url); 202 $this->assertEquals($cachedcminfo->customdata, $cm->customdata); 203 204 // Dynamic fields, just test that they can be retrieved (must be carefully tested in each activity type). 205 $this->assertNotEmpty($cm->availableinfo); // Lists all unmet availability conditions. 206 $this->assertEquals(0, $cm->uservisible); 207 $this->assertEquals('', $cm->extraclasses); 208 $this->assertEquals('', $cm->onclick); 209 $this->assertEquals(null, $cm->afterlink); 210 $this->assertEquals(null, $cm->afterediticons); 211 $this->assertEquals('', $cm->content); 212 213 // Attempt to access and set non-existing field. 214 $this->assertTrue(empty($modinfo->somefield)); 215 $this->assertFalse(isset($modinfo->somefield)); 216 $cm->somefield; 217 $this->assertDebuggingCalled(); 218 $cm->somefield = 'Some value'; 219 $this->assertDebuggingCalled(); 220 $this->assertEmpty($cm->somefield); 221 $this->assertDebuggingCalled(); 222 223 // Attempt to overwrite an existing field. 224 $prevvalue = $cm->name; 225 $this->assertNotEmpty($cm->name); 226 $this->assertFalse(empty($cm->name)); 227 $this->assertTrue(isset($cm->name)); 228 $cm->name = 'Illegal overwriting'; 229 $this->assertDebuggingCalled(); 230 $this->assertEquals($prevvalue, $cm->name); 231 $this->assertDebuggingNotCalled(); 232 233 // Restore settings. 234 set_config('enableavailability', $oldcfgenableavailability); 235 set_config('enablecompletion', $oldcfgenablecompletion); 236 } 237 238 public function test_matching_cacherev() { 239 global $DB, $CFG; 240 241 $this->resetAfterTest(); 242 $this->setAdminUser(); 243 $cache = cache::make('core', 'coursemodinfo'); 244 245 // Generate the course and pre-requisite module. 246 $course = $this->getDataGenerator()->create_course( 247 array('format' => 'topics', 248 'numsections' => 3), 249 array('createsections' => true)); 250 251 // Make sure the cacherev is set. 252 $cacherev = $DB->get_field('course', 'cacherev', array('id' => $course->id)); 253 $this->assertGreaterThan(0, $cacherev); 254 $prevcacherev = $cacherev; 255 256 // Reset course cache and make sure cacherev is bumped up but cache is empty. 257 rebuild_course_cache($course->id, true); 258 $cacherev = $DB->get_field('course', 'cacherev', array('id' => $course->id)); 259 $this->assertGreaterThan($prevcacherev, $cacherev); 260 $this->assertEmpty($cache->get($course->id)); 261 $prevcacherev = $cacherev; 262 263 // Build course cache. Cacherev should not change but cache is now not empty. Make sure cacherev is the same everywhere. 264 $modinfo = get_fast_modinfo($course->id); 265 $cacherev = $DB->get_field('course', 'cacherev', array('id' => $course->id)); 266 $this->assertEquals($prevcacherev, $cacherev); 267 $cachedvalue = $cache->get($course->id); 268 $this->assertNotEmpty($cachedvalue); 269 $this->assertEquals($cacherev, $cachedvalue->cacherev); 270 $this->assertEquals($cacherev, $modinfo->get_course()->cacherev); 271 $prevcacherev = $cacherev; 272 273 // Little trick to check that cache is not rebuilt druing the next step - substitute the value in MUC and later check that it is still there. 274 $cache->set($course->id, (object)array_merge((array)$cachedvalue, array('secretfield' => 1))); 275 276 // Clear static cache and call get_fast_modinfo() again (pretend we are in another request). Cache should not be rebuilt. 277 course_modinfo::clear_instance_cache(); 278 $modinfo = get_fast_modinfo($course->id); 279 $cacherev = $DB->get_field('course', 'cacherev', array('id' => $course->id)); 280 $this->assertEquals($prevcacherev, $cacherev); 281 $cachedvalue = $cache->get($course->id); 282 $this->assertNotEmpty($cachedvalue); 283 $this->assertEquals($cacherev, $cachedvalue->cacherev); 284 $this->assertNotEmpty($cachedvalue->secretfield); 285 $this->assertEquals($cacherev, $modinfo->get_course()->cacherev); 286 $prevcacherev = $cacherev; 287 288 // Rebuild course cache. Cacherev must be incremented everywhere. 289 rebuild_course_cache($course->id); 290 $cacherev = $DB->get_field('course', 'cacherev', array('id' => $course->id)); 291 $this->assertGreaterThan($prevcacherev, $cacherev); 292 $cachedvalue = $cache->get($course->id); 293 $this->assertNotEmpty($cachedvalue); 294 $this->assertEquals($cacherev, $cachedvalue->cacherev); 295 $modinfo = get_fast_modinfo($course->id); 296 $this->assertEquals($cacherev, $modinfo->get_course()->cacherev); 297 $prevcacherev = $cacherev; 298 299 // Update cacherev in DB and make sure the cache will be rebuilt on the next call to get_fast_modinfo(). 300 increment_revision_number('course', 'cacherev', 'id = ?', array($course->id)); 301 // We need to clear static cache for course_modinfo instances too. 302 course_modinfo::clear_instance_cache(); 303 $modinfo = get_fast_modinfo($course->id); 304 $cacherev = $DB->get_field('course', 'cacherev', array('id' => $course->id)); 305 $this->assertGreaterThan($prevcacherev, $cacherev); 306 $cachedvalue = $cache->get($course->id); 307 $this->assertNotEmpty($cachedvalue); 308 $this->assertEquals($cacherev, $cachedvalue->cacherev); 309 $this->assertEquals($cacherev, $modinfo->get_course()->cacherev); 310 $prevcacherev = $cacherev; 311 312 // Reset cache for all courses and make sure this course cache is reset. 313 rebuild_course_cache(0, true); 314 $cacherev = $DB->get_field('course', 'cacherev', array('id' => $course->id)); 315 $this->assertGreaterThan($prevcacherev, $cacherev); 316 $this->assertEmpty($cache->get($course->id)); 317 // Rebuild again. 318 $modinfo = get_fast_modinfo($course->id); 319 $cachedvalue = $cache->get($course->id); 320 $this->assertNotEmpty($cachedvalue); 321 $this->assertEquals($cacherev, $cachedvalue->cacherev); 322 $this->assertEquals($cacherev, $modinfo->get_course()->cacherev); 323 $prevcacherev = $cacherev; 324 325 // Purge all caches and make sure cacherev is increased and data from MUC erased. 326 purge_all_caches(); 327 $cacherev = $DB->get_field('course', 'cacherev', array('id' => $course->id)); 328 $this->assertGreaterThan($prevcacherev, $cacherev); 329 $this->assertEmpty($cache->get($course->id)); 330 } 331 332 public function test_course_modinfo_properties() { 333 global $USER, $DB; 334 335 $this->resetAfterTest(); 336 $this->setAdminUser(); 337 338 // Generate the course and some modules. Make one section hidden. 339 $course = $this->getDataGenerator()->create_course( 340 array('format' => 'topics', 341 'numsections' => 3), 342 array('createsections' => true)); 343 $DB->execute('UPDATE {course_sections} SET visible = 0 WHERE course = ? and section = ?', 344 array($course->id, 3)); 345 $coursecontext = context_course::instance($course->id); 346 $forum0 = $this->getDataGenerator()->create_module('forum', 347 array('course' => $course->id), array('section' => 0)); 348 $assign0 = $this->getDataGenerator()->create_module('assign', 349 array('course' => $course->id), array('section' => 0, 'visible' => 0)); 350 $forum1 = $this->getDataGenerator()->create_module('forum', 351 array('course' => $course->id), array('section' => 1)); 352 $assign1 = $this->getDataGenerator()->create_module('assign', 353 array('course' => $course->id), array('section' => 1)); 354 $page1 = $this->getDataGenerator()->create_module('page', 355 array('course' => $course->id), array('section' => 1)); 356 $page3 = $this->getDataGenerator()->create_module('page', 357 array('course' => $course->id), array('section' => 3)); 358 359 $modinfo = get_fast_modinfo($course->id); 360 361 $this->assertEquals(array($forum0->cmid, $assign0->cmid, $forum1->cmid, $assign1->cmid, $page1->cmid, $page3->cmid), 362 array_keys($modinfo->cms)); 363 $this->assertEquals($course->id, $modinfo->courseid); 364 $this->assertEquals($USER->id, $modinfo->userid); 365 $this->assertEquals(array(0 => array($forum0->cmid, $assign0->cmid), 366 1 => array($forum1->cmid, $assign1->cmid, $page1->cmid), 3 => array($page3->cmid)), $modinfo->sections); 367 $this->assertEquals(array('forum', 'assign', 'page'), array_keys($modinfo->instances)); 368 $this->assertEquals(array($assign0->id, $assign1->id), array_keys($modinfo->instances['assign'])); 369 $this->assertEquals(array($forum0->id, $forum1->id), array_keys($modinfo->instances['forum'])); 370 $this->assertEquals(array($page1->id, $page3->id), array_keys($modinfo->instances['page'])); 371 $this->assertEquals(groups_get_user_groups($course->id), $modinfo->groups); 372 $this->assertEquals(array(0 => array($forum0->cmid, $assign0->cmid), 373 1 => array($forum1->cmid, $assign1->cmid, $page1->cmid), 374 3 => array($page3->cmid)), $modinfo->get_sections()); 375 $this->assertEquals(array(0, 1, 2, 3), array_keys($modinfo->get_section_info_all())); 376 $this->assertEquals($forum0->cmid . ',' . $assign0->cmid, $modinfo->get_section_info(0)->sequence); 377 $this->assertEquals($forum1->cmid . ',' . $assign1->cmid . ',' . $page1->cmid, $modinfo->get_section_info(1)->sequence); 378 $this->assertEquals('', $modinfo->get_section_info(2)->sequence); 379 $this->assertEquals($page3->cmid, $modinfo->get_section_info(3)->sequence); 380 $this->assertEquals($course->id, $modinfo->get_course()->id); 381 $names = array_keys($modinfo->get_used_module_names()); 382 sort($names); 383 $this->assertEquals(array('assign', 'forum', 'page'), $names); 384 $names = array_keys($modinfo->get_used_module_names(true)); 385 sort($names); 386 $this->assertEquals(array('assign', 'forum', 'page'), $names); 387 // Admin can see hidden modules/sections. 388 $this->assertTrue($modinfo->cms[$assign0->cmid]->uservisible); 389 $this->assertTrue($modinfo->get_section_info(3)->uservisible); 390 391 // Get modinfo for non-current user (without capability to view hidden activities/sections). 392 $user = $this->getDataGenerator()->create_user(); 393 $modinfo = get_fast_modinfo($course->id, $user->id); 394 $this->assertEquals($user->id, $modinfo->userid); 395 $this->assertFalse($modinfo->cms[$assign0->cmid]->uservisible); 396 $this->assertFalse($modinfo->get_section_info(3)->uservisible); 397 398 // Attempt to access and set non-existing field. 399 $this->assertTrue(empty($modinfo->somefield)); 400 $this->assertFalse(isset($modinfo->somefield)); 401 $modinfo->somefield; 402 $this->assertDebuggingCalled(); 403 $modinfo->somefield = 'Some value'; 404 $this->assertDebuggingCalled(); 405 $this->assertEmpty($modinfo->somefield); 406 $this->assertDebuggingCalled(); 407 408 // Attempt to overwrite existing field. 409 $this->assertFalse(empty($modinfo->cms)); 410 $this->assertTrue(isset($modinfo->cms)); 411 $modinfo->cms = 'Illegal overwriting'; 412 $this->assertDebuggingCalled(); 413 $this->assertNotEquals('Illegal overwriting', $modinfo->cms); 414 } 415 416 public function test_is_user_access_restricted_by_capability() { 417 global $DB; 418 419 $this->resetAfterTest(); 420 421 // Create a course and a mod_assign instance. 422 $course = $this->getDataGenerator()->create_course(); 423 $assign = $this->getDataGenerator()->create_module('assign', array('course'=>$course->id)); 424 425 // Create and enrol a student. 426 $coursecontext = context_course::instance($course->id); 427 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST); 428 $student = $this->getDataGenerator()->create_user(); 429 role_assign($studentrole->id, $student->id, $coursecontext); 430 $enrolplugin = enrol_get_plugin('manual'); 431 $enrolinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'manual')); 432 $enrolplugin->enrol_user($enrolinstance, $student->id); 433 $this->setUser($student); 434 435 // Make sure student can see the module. 436 $cm = get_fast_modinfo($course->id)->instances['assign'][$assign->id]; 437 $this->assertTrue($cm->uservisible); 438 $this->assertFalse($cm->is_user_access_restricted_by_capability()); 439 440 // Prohibit student to view mod_assign for the course. 441 role_change_permission($studentrole->id, $coursecontext, 'mod/assign:view', CAP_PROHIBIT); 442 get_fast_modinfo($course->id, 0, true); 443 $cm = get_fast_modinfo($course->id)->instances['assign'][$assign->id]; 444 $this->assertFalse($cm->uservisible); 445 $this->assertTrue($cm->is_user_access_restricted_by_capability()); 446 447 // Restore permission to student to view mod_assign for the course. 448 role_change_permission($studentrole->id, $coursecontext, 'mod/assign:view', CAP_INHERIT); 449 get_fast_modinfo($course->id, 0, true); 450 $cm = get_fast_modinfo($course->id)->instances['assign'][$assign->id]; 451 $this->assertTrue($cm->uservisible); 452 $this->assertFalse($cm->is_user_access_restricted_by_capability()); 453 454 // Prohibit student to view mod_assign for the particular module. 455 role_change_permission($studentrole->id, context_module::instance($cm->id), 'mod/assign:view', CAP_PROHIBIT); 456 get_fast_modinfo($course->id, 0, true); 457 $cm = get_fast_modinfo($course->id)->instances['assign'][$assign->id]; 458 $this->assertFalse($cm->uservisible); 459 $this->assertTrue($cm->is_user_access_restricted_by_capability()); 460 461 // Check calling get_fast_modinfo() for different user: 462 $this->setAdminUser(); 463 $cm = get_fast_modinfo($course->id)->instances['assign'][$assign->id]; 464 $this->assertTrue($cm->uservisible); 465 $this->assertFalse($cm->is_user_access_restricted_by_capability()); 466 $cm = get_fast_modinfo($course->id, $student->id)->instances['assign'][$assign->id]; 467 $this->assertFalse($cm->uservisible); 468 $this->assertTrue($cm->is_user_access_restricted_by_capability()); 469 } 470 471 /** 472 * Tests for function cm_info::get_course_module_record() 473 */ 474 public function test_cm_info_get_course_module_record() { 475 global $DB; 476 477 $this->resetAfterTest(); 478 $this->setAdminUser(); 479 480 set_config('enableavailability', 1); 481 set_config('enablecompletion', 1); 482 483 $course = $this->getDataGenerator()->create_course( 484 array('format' => 'topics', 'numsections' => 3, 'enablecompletion' => 1), 485 array('createsections' => true)); 486 $mods = array(); 487 $mods[0] = $this->getDataGenerator()->create_module('forum', array('course' => $course->id)); 488 $mods[1] = $this->getDataGenerator()->create_module('assign', 489 array('course' => $course->id, 490 'section' => 3, 491 'idnumber' => '12345', 492 'showdescription' => true 493 )); 494 // Pick a small valid availability value to use. 495 $availabilityvalue = '{"op":"|","show":true,"c":[{"type":"date","d":">=","t":4}]}'; 496 $mods[2] = $this->getDataGenerator()->create_module('book', 497 array('course' => $course->id, 498 'indent' => 5, 499 'availability' => $availabilityvalue, 500 'showdescription' => false, 501 'completion' => true, 502 'completionview' => true, 503 'completionexpected' => time() + 5000, 504 )); 505 $mods[3] = $this->getDataGenerator()->create_module('forum', 506 array('course' => $course->id, 507 'visible' => 0, 508 'groupmode' => 1, 509 'availability' => null)); 510 $mods[4] = $this->getDataGenerator()->create_module('forum', 511 array('course' => $course->id, 512 'grouping' => 12)); 513 514 $modinfo = get_fast_modinfo($course->id); 515 516 // Make sure that object returned by get_course_module_record(false) has exactly the same fields as DB table 'course_modules'. 517 $dbfields = array_keys($DB->get_columns('course_modules')); 518 sort($dbfields); 519 $cmrecord = $modinfo->get_cm($mods[0]->cmid)->get_course_module_record(); 520 $cmrecordfields = array_keys((array)$cmrecord); 521 sort($cmrecordfields); 522 $this->assertEquals($dbfields, $cmrecordfields); 523 524 // Make sure that object returned by get_course_module_record(true) has exactly the same fields 525 // as object returned by get_coursemodule_from_id(,,,true,); 526 $cmrecordfull = $modinfo->get_cm($mods[0]->cmid)->get_course_module_record(true); 527 $cmrecordfullfields = array_keys((array)$cmrecordfull); 528 $cm = get_coursemodule_from_id(null, $mods[0]->cmid, 0, true, MUST_EXIST); 529 $cmfields = array_keys((array)$cm); 530 $this->assertEquals($cmfields, $cmrecordfullfields); 531 532 // Make sure that object returned by get_course_module_record(true) has exactly the same fields 533 // as object returned by get_coursemodule_from_instance(,,,true,); 534 $cm = get_coursemodule_from_instance('forum', $mods[0]->id, null, true, MUST_EXIST); 535 $cmfields = array_keys((array)$cm); 536 $this->assertEquals($cmfields, $cmrecordfullfields); 537 538 // Make sure the objects have the same properties. 539 $cm1 = get_coursemodule_from_id(null, $mods[0]->cmid, 0, true, MUST_EXIST); 540 $cm2 = get_coursemodule_from_instance('forum', $mods[0]->id, 0, true, MUST_EXIST); 541 $cminfo = $modinfo->get_cm($mods[0]->cmid); 542 $record = $DB->get_record('course_modules', array('id' => $mods[0]->cmid)); 543 $this->assertEquals($record, $cminfo->get_course_module_record()); 544 $this->assertEquals($cm1, $cminfo->get_course_module_record(true)); 545 $this->assertEquals($cm2, $cminfo->get_course_module_record(true)); 546 547 $cm1 = get_coursemodule_from_id(null, $mods[1]->cmid, 0, true, MUST_EXIST); 548 $cm2 = get_coursemodule_from_instance('assign', $mods[1]->id, 0, true, MUST_EXIST); 549 $cminfo = $modinfo->get_cm($mods[1]->cmid); 550 $record = $DB->get_record('course_modules', array('id' => $mods[1]->cmid)); 551 $this->assertEquals($record, $cminfo->get_course_module_record()); 552 $this->assertEquals($cm1, $cminfo->get_course_module_record(true)); 553 $this->assertEquals($cm2, $cminfo->get_course_module_record(true)); 554 555 $cm1 = get_coursemodule_from_id(null, $mods[2]->cmid, 0, true, MUST_EXIST); 556 $cm2 = get_coursemodule_from_instance('book', $mods[2]->id, 0, true, MUST_EXIST); 557 $cminfo = $modinfo->get_cm($mods[2]->cmid); 558 $record = $DB->get_record('course_modules', array('id' => $mods[2]->cmid)); 559 $this->assertEquals($record, $cminfo->get_course_module_record()); 560 $this->assertEquals($cm1, $cminfo->get_course_module_record(true)); 561 $this->assertEquals($cm2, $cminfo->get_course_module_record(true)); 562 563 $cm1 = get_coursemodule_from_id(null, $mods[3]->cmid, 0, true, MUST_EXIST); 564 $cm2 = get_coursemodule_from_instance('forum', $mods[3]->id, 0, true, MUST_EXIST); 565 $cminfo = $modinfo->get_cm($mods[3]->cmid); 566 $record = $DB->get_record('course_modules', array('id' => $mods[3]->cmid)); 567 $this->assertEquals($record, $cminfo->get_course_module_record()); 568 $this->assertEquals($cm1, $cminfo->get_course_module_record(true)); 569 $this->assertEquals($cm2, $cminfo->get_course_module_record(true)); 570 571 $cm1 = get_coursemodule_from_id(null, $mods[4]->cmid, 0, true, MUST_EXIST); 572 $cm2 = get_coursemodule_from_instance('forum', $mods[4]->id, 0, true, MUST_EXIST); 573 $cminfo = $modinfo->get_cm($mods[4]->cmid); 574 $record = $DB->get_record('course_modules', array('id' => $mods[4]->cmid)); 575 $this->assertEquals($record, $cminfo->get_course_module_record()); 576 $this->assertEquals($cm1, $cminfo->get_course_module_record(true)); 577 $this->assertEquals($cm2, $cminfo->get_course_module_record(true)); 578 579 } 580 581 /** 582 * Tests the availability property that has been added to course modules 583 * and sections (just to see that it is correctly saved and accessed). 584 */ 585 public function test_availability_property() { 586 global $DB, $CFG; 587 588 $this->resetAfterTest(); 589 590 // Create a course with two modules and three sections. 591 $course = $this->getDataGenerator()->create_course( 592 array('format' => 'topics', 'numsections' => 3), 593 array('createsections' => true)); 594 $forum = $this->getDataGenerator()->create_module('forum', 595 array('course' => $course->id)); 596 $forum2 = $this->getDataGenerator()->create_module('forum', 597 array('course' => $course->id)); 598 599 // Get modinfo. Check that availability is null for both cm and sections. 600 $modinfo = get_fast_modinfo($course->id); 601 $cm = $modinfo->get_cm($forum->cmid); 602 $this->assertNull($cm->availability); 603 $section = $modinfo->get_section_info(1, MUST_EXIST); 604 $this->assertNull($section->availability); 605 606 // Update availability for cm and section in database. 607 $DB->set_field('course_modules', 'availability', '{}', array('id' => $cm->id)); 608 $DB->set_field('course_sections', 'availability', '{}', array('id' => $section->id)); 609 610 // Clear cache and get modinfo again. 611 rebuild_course_cache($course->id, true); 612 get_fast_modinfo(0, 0, true); 613 $modinfo = get_fast_modinfo($course->id); 614 615 // Check values that were changed. 616 $cm = $modinfo->get_cm($forum->cmid); 617 $this->assertEquals('{}', $cm->availability); 618 $section = $modinfo->get_section_info(1, MUST_EXIST); 619 $this->assertEquals('{}', $section->availability); 620 621 // Check other values are still null. 622 $cm = $modinfo->get_cm($forum2->cmid); 623 $this->assertNull($cm->availability); 624 $section = $modinfo->get_section_info(2, MUST_EXIST); 625 $this->assertNull($section->availability); 626 } 627 628 /** 629 * Tests for get_groups() method. 630 */ 631 public function test_get_groups() { 632 $this->resetAfterTest(); 633 $generator = $this->getDataGenerator(); 634 635 // Create courses. 636 $course1 = $generator->create_course(); 637 $course2 = $generator->create_course(); 638 $course3 = $generator->create_course(); 639 640 // Create users. 641 $user1 = $generator->create_user(); 642 $user2 = $generator->create_user(); 643 $user3 = $generator->create_user(); 644 645 // Enrol users on courses. 646 $generator->enrol_user($user1->id, $course1->id); 647 $generator->enrol_user($user2->id, $course2->id); 648 $generator->enrol_user($user3->id, $course2->id); 649 $generator->enrol_user($user3->id, $course3->id); 650 651 // Create groups. 652 $group1 = $generator->create_group(array('courseid' => $course1->id)); 653 $group2 = $generator->create_group(array('courseid' => $course2->id)); 654 $group3 = $generator->create_group(array('courseid' => $course2->id)); 655 656 // Assign users to groups and assert the result. 657 $this->assertTrue($generator->create_group_member(array('groupid' => $group1->id, 'userid' => $user1->id))); 658 $this->assertTrue($generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user2->id))); 659 $this->assertTrue($generator->create_group_member(array('groupid' => $group3->id, 'userid' => $user2->id))); 660 $this->assertTrue($generator->create_group_member(array('groupid' => $group2->id, 'userid' => $user3->id))); 661 662 // Create groupings. 663 $grouping1 = $generator->create_grouping(array('courseid' => $course1->id)); 664 $grouping2 = $generator->create_grouping(array('courseid' => $course2->id)); 665 666 // Assign and assert group to groupings. 667 groups_assign_grouping($grouping1->id, $group1->id); 668 groups_assign_grouping($grouping2->id, $group2->id); 669 groups_assign_grouping($grouping2->id, $group3->id); 670 671 // Test with one single group. 672 $modinfo = get_fast_modinfo($course1, $user1->id); 673 $groups = $modinfo->get_groups($grouping1->id); 674 $this->assertCount(1, $groups); 675 $this->assertArrayHasKey($group1->id, $groups); 676 677 // Test with two groups. 678 $modinfo = get_fast_modinfo($course2, $user2->id); 679 $groups = $modinfo->get_groups(); 680 $this->assertCount(2, $groups); 681 $this->assertTrue(in_array($group2->id, $groups)); 682 $this->assertTrue(in_array($group3->id, $groups)); 683 684 // Test with no groups. 685 $modinfo = get_fast_modinfo($course3, $user3->id); 686 $groups = $modinfo->get_groups(); 687 $this->assertCount(0, $groups); 688 $this->assertArrayNotHasKey($group1->id, $groups); 689 } 690 691 /** 692 * Tests the function for constructing a cm_info from mixed data. 693 */ 694 public function test_create() { 695 global $CFG, $DB; 696 $this->resetAfterTest(); 697 698 // Create a course and an activity. 699 $generator = $this->getDataGenerator(); 700 $course = $generator->create_course(); 701 $page = $generator->create_module('page', array('course' => $course->id, 702 'name' => 'Annie')); 703 704 // Null is passed through. 705 $this->assertNull(cm_info::create(null)); 706 707 // Stdclass object turns into cm_info. 708 $cm = cm_info::create( 709 (object)array('id' => $page->cmid, 'course' => $course->id)); 710 $this->assertInstanceOf('cm_info', $cm); 711 $this->assertEquals('Annie', $cm->name); 712 713 // A cm_info object stays as cm_info. 714 $this->assertSame($cm, cm_info::create($cm)); 715 716 // Invalid object (missing fields) causes error. 717 try { 718 cm_info::create((object)array('id' => $page->cmid)); 719 $this->fail(); 720 } catch (Exception $e) { 721 $this->assertInstanceOf('coding_exception', $e); 722 } 723 724 // Create a second hidden activity. 725 $hiddenpage = $generator->create_module('page', array('course' => $course->id, 726 'name' => 'Annie', 'visible' => 0)); 727 728 // Create 2 user accounts, one is a manager who can see everything. 729 $user = $generator->create_user(); 730 $generator->enrol_user($user->id, $course->id); 731 $manager = $generator->create_user(); 732 $generator->enrol_user($manager->id, $course->id, 733 $DB->get_field('role', 'id', array('shortname' => 'manager'), MUST_EXIST)); 734 735 // User can see the normal page but not the hidden one. 736 $cm = cm_info::create((object)array('id' => $page->cmid, 'course' => $course->id), 737 $user->id); 738 $this->assertTrue($cm->uservisible); 739 $cm = cm_info::create((object)array('id' => $hiddenpage->cmid, 'course' => $course->id), 740 $user->id); 741 $this->assertFalse($cm->uservisible); 742 743 // Manager can see the hidden one too. 744 $cm = cm_info::create((object)array('id' => $hiddenpage->cmid, 'course' => $course->id), 745 $manager->id); 746 $this->assertTrue($cm->uservisible); 747 } 748 749 /** 750 * Tests function for getting $course and $cm at once quickly from modinfo 751 * based on cmid or cm record. 752 */ 753 public function test_get_course_and_cm_from_cmid() { 754 global $CFG, $DB; 755 $this->resetAfterTest(); 756 757 // Create a course and an activity. 758 $generator = $this->getDataGenerator(); 759 $course = $generator->create_course(array('shortname' => 'Halls')); 760 $page = $generator->create_module('page', array('course' => $course->id, 761 'name' => 'Annie')); 762 763 // Successful usage. 764 list($course, $cm) = get_course_and_cm_from_cmid($page->cmid); 765 $this->assertEquals('Halls', $course->shortname); 766 $this->assertInstanceOf('cm_info', $cm); 767 $this->assertEquals('Annie', $cm->name); 768 769 // Specified module type. 770 list($course, $cm) = get_course_and_cm_from_cmid($page->cmid, 'page'); 771 $this->assertEquals('Annie', $cm->name); 772 773 // With id in object. 774 $fakecm = (object)array('id' => $page->cmid); 775 list($course, $cm) = get_course_and_cm_from_cmid($fakecm); 776 $this->assertEquals('Halls', $course->shortname); 777 $this->assertEquals('Annie', $cm->name); 778 779 // With both id and course in object. 780 $fakecm->course = $course->id; 781 list($course, $cm) = get_course_and_cm_from_cmid($fakecm); 782 $this->assertEquals('Halls', $course->shortname); 783 $this->assertEquals('Annie', $cm->name); 784 785 // With supplied course id. 786 list($course, $cm) = get_course_and_cm_from_cmid($page->cmid, 'page', $course->id); 787 $this->assertEquals('Annie', $cm->name); 788 789 // With supplied course object (modified just so we can check it is 790 // indeed reusing the supplied object). 791 $course->silly = true; 792 list($course, $cm) = get_course_and_cm_from_cmid($page->cmid, 'page', $course); 793 $this->assertEquals('Annie', $cm->name); 794 $this->assertTrue($course->silly); 795 796 // Incorrect module type. 797 try { 798 get_course_and_cm_from_cmid($page->cmid, 'forum'); 799 $this->fail(); 800 } catch (moodle_exception $e) { 801 $this->assertEquals('invalidcoursemodule', $e->errorcode); 802 } 803 804 // Invalid module name. 805 try { 806 get_course_and_cm_from_cmid($page->cmid, 'pigs can fly'); 807 $this->fail(); 808 } catch (coding_exception $e) { 809 $this->assertStringContainsString('Invalid modulename parameter', $e->getMessage()); 810 } 811 812 // Doesn't exist. 813 try { 814 get_course_and_cm_from_cmid($page->cmid + 1); 815 $this->fail(); 816 } catch (moodle_exception $e) { 817 $this->assertInstanceOf('dml_exception', $e); 818 } 819 820 // Create a second hidden activity. 821 $hiddenpage = $generator->create_module('page', array('course' => $course->id, 822 'name' => 'Annie', 'visible' => 0)); 823 824 // Create 2 user accounts, one is a manager who can see everything. 825 $user = $generator->create_user(); 826 $generator->enrol_user($user->id, $course->id); 827 $manager = $generator->create_user(); 828 $generator->enrol_user($manager->id, $course->id, 829 $DB->get_field('role', 'id', array('shortname' => 'manager'), MUST_EXIST)); 830 831 // User can see the normal page but not the hidden one. 832 list($course, $cm) = get_course_and_cm_from_cmid($page->cmid, 'page', 0, $user->id); 833 $this->assertTrue($cm->uservisible); 834 list($course, $cm) = get_course_and_cm_from_cmid($hiddenpage->cmid, 'page', 0, $user->id); 835 $this->assertFalse($cm->uservisible); 836 837 // Manager can see the hidden one too. 838 list($course, $cm) = get_course_and_cm_from_cmid($hiddenpage->cmid, 'page', 0, $manager->id); 839 $this->assertTrue($cm->uservisible); 840 } 841 842 /** 843 * Tests function for getting $course and $cm at once quickly from modinfo 844 * based on instance id or record. 845 */ 846 public function test_get_course_and_cm_from_instance() { 847 global $CFG, $DB; 848 $this->resetAfterTest(); 849 850 // Create a course and an activity. 851 $generator = $this->getDataGenerator(); 852 $course = $generator->create_course(array('shortname' => 'Halls')); 853 $page = $generator->create_module('page', array('course' => $course->id, 854 'name' => 'Annie')); 855 856 // Successful usage. 857 list($course, $cm) = get_course_and_cm_from_instance($page->id, 'page'); 858 $this->assertEquals('Halls', $course->shortname); 859 $this->assertInstanceOf('cm_info', $cm); 860 $this->assertEquals('Annie', $cm->name); 861 862 // With id in object. 863 $fakeinstance = (object)array('id' => $page->id); 864 list($course, $cm) = get_course_and_cm_from_instance($fakeinstance, 'page'); 865 $this->assertEquals('Halls', $course->shortname); 866 $this->assertEquals('Annie', $cm->name); 867 868 // With both id and course in object. 869 $fakeinstance->course = $course->id; 870 list($course, $cm) = get_course_and_cm_from_instance($fakeinstance, 'page'); 871 $this->assertEquals('Halls', $course->shortname); 872 $this->assertEquals('Annie', $cm->name); 873 874 // With supplied course id. 875 list($course, $cm) = get_course_and_cm_from_instance($page->id, 'page', $course->id); 876 $this->assertEquals('Annie', $cm->name); 877 878 // With supplied course object (modified just so we can check it is 879 // indeed reusing the supplied object). 880 $course->silly = true; 881 list($course, $cm) = get_course_and_cm_from_instance($page->id, 'page', $course); 882 $this->assertEquals('Annie', $cm->name); 883 $this->assertTrue($course->silly); 884 885 // Doesn't exist (or is wrong type). 886 try { 887 get_course_and_cm_from_instance($page->id, 'forum'); 888 $this->fail(); 889 } catch (moodle_exception $e) { 890 $this->assertInstanceOf('dml_exception', $e); 891 } 892 893 // Invalid module name. 894 try { 895 get_course_and_cm_from_cmid($page->cmid, '1337 h4x0ring'); 896 $this->fail(); 897 } catch (coding_exception $e) { 898 $this->assertStringContainsString('Invalid modulename parameter', $e->getMessage()); 899 } 900 901 // Create a second hidden activity. 902 $hiddenpage = $generator->create_module('page', array('course' => $course->id, 903 'name' => 'Annie', 'visible' => 0)); 904 905 // Create 2 user accounts, one is a manager who can see everything. 906 $user = $generator->create_user(); 907 $generator->enrol_user($user->id, $course->id); 908 $manager = $generator->create_user(); 909 $generator->enrol_user($manager->id, $course->id, 910 $DB->get_field('role', 'id', array('shortname' => 'manager'), MUST_EXIST)); 911 912 // User can see the normal page but not the hidden one. 913 list($course, $cm) = get_course_and_cm_from_cmid($page->cmid, 'page', 0, $user->id); 914 $this->assertTrue($cm->uservisible); 915 list($course, $cm) = get_course_and_cm_from_cmid($hiddenpage->cmid, 'page', 0, $user->id); 916 $this->assertFalse($cm->uservisible); 917 918 // Manager can see the hidden one too. 919 list($course, $cm) = get_course_and_cm_from_cmid($hiddenpage->cmid, 'page', 0, $manager->id); 920 $this->assertTrue($cm->uservisible); 921 } 922 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body