2 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
18 * Full functional accesslib test
22 * @copyright 2011 Petr Skoda {@link http://skodak.org}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die();
30 * Context caching fixture
32 class context_inspection extends context_helper {
33 public static function test_context_cache_size() {
34 return self::$cache_count;
40 * Functional test for accesslib.php
42 * Note: execution may take many minutes especially on slower servers.
44 class accesslib_testcase extends advanced_testcase {
46 //TODO: add more tests for the remaining accesslib parts such as enrol related api
49 * Verify comparison of context instances in phpunit asserts
52 public function test_context_comparisons() {
53 $frontpagecontext1 = context_course::instance(SITEID);
54 context_helper::reset_caches();
55 $frontpagecontext2 = context_course::instance(SITEID);
56 $this->assertEquals($frontpagecontext1, $frontpagecontext2);
58 $user1 = context_user::instance(1);
59 $user2 = context_user::instance(2);
60 $this->assertNotEquals($user1, $user2);
64 * Test resetting works.
66 public function test_accesslib_clear_all_caches() {
67 global $ACCESSLIB_PRIVATE;
69 $this->resetAfterTest();
71 $this->setAdminUser();
72 load_all_capabilities();
74 $this->assertNotEmpty($ACCESSLIB_PRIVATE->rolepermissions);
75 $this->assertNotEmpty($ACCESSLIB_PRIVATE->rolepermissions);
76 $this->assertNotEmpty($ACCESSLIB_PRIVATE->accessdatabyuser);
77 accesslib_clear_all_caches(true);
78 $this->assertEmpty($ACCESSLIB_PRIVATE->rolepermissions);
79 $this->assertEmpty($ACCESSLIB_PRIVATE->rolepermissions);
80 $this->assertEmpty($ACCESSLIB_PRIVATE->dirtycontexts);
81 $this->assertEmpty($ACCESSLIB_PRIVATE->accessdatabyuser);
85 * Test getting of role access
88 public function test_get_role_access() {
91 $roles = $DB->get_records('role');
92 foreach ($roles as $role) {
93 $access = get_role_access($role->id);
95 $this->assertTrue(is_array($access));
96 $this->assertTrue(is_array($access['ra']));
97 $this->assertTrue(is_array($access['rdef']));
98 $this->assertTrue(isset($access['rdef_count']));
99 $this->assertTrue(is_array($access['loaded']));
100 $this->assertTrue(isset($access['time']));
101 $this->assertTrue(is_array($access['rsw']));
104 // Note: the data is validated in the functional permission evaluation test at the end of this testcase.
108 * Test getting of guest role.
111 public function test_get_guest_role() {
114 $guest = get_guest_role();
115 $this->assertEquals('guest', $guest->archetype);
116 $this->assertEquals('guest', $guest->shortname);
118 $this->assertEquals($CFG->guestroleid, $guest->id);
122 * Test if user is admin.
125 public function test_is_siteadmin() {
128 $this->resetAfterTest();
130 $users = $DB->get_records('user');
132 foreach ($users as $user) {
134 if ($user->username === 'admin') {
135 $this->assertTrue(is_siteadmin($user));
136 $this->assertTrue(is_siteadmin($user->id));
137 $this->setUser($user);
138 $this->assertTrue(is_siteadmin());
139 $this->assertTrue(is_siteadmin(null));
141 $this->assertFalse(is_siteadmin($user));
142 $this->assertFalse(is_siteadmin($user->id));
143 $this->setUser($user);
144 $this->assertFalse(is_siteadmin());
145 $this->assertFalse(is_siteadmin(null));
149 // Change the site admin list and check that it still works with
150 // multiple admins. We do this with userids only (not real user
151 // accounts) because it makes the test simpler.
152 $before = $CFG->siteadmins;
153 set_config('siteadmins', '666,667,668');
154 $this->assertTrue(is_siteadmin(666));
155 $this->assertTrue(is_siteadmin(667));
156 $this->assertTrue(is_siteadmin(668));
157 $this->assertFalse(is_siteadmin(669));
158 set_config('siteadmins', '13');
159 $this->assertTrue(is_siteadmin(13));
160 $this->assertFalse(is_siteadmin(666));
161 set_config('siteadmins', $before);
165 * Test if user is enrolled in a course
168 public function test_is_enrolled() {
172 $user = $this->getDataGenerator()->create_user();
173 $course = $this->getDataGenerator()->create_course();
174 $coursecontext = context_course::instance($course->id);
175 $role = $DB->get_record('role', array('shortname'=>'student'));
177 // There should be a manual enrolment as part of the default install
178 $plugin = enrol_get_plugin('manual');
179 $instance = $DB->get_record('enrol', array(
180 'courseid' => $course->id,
183 $this->assertNotEquals($instance, false);
185 // Enrol the user in the course
186 $plugin->enrol_user($instance, $user->id, $role->id);
188 // We'll test with the mod/assign:submit capability
189 $capability= 'mod/assign:submit';
190 $this->assertTrue($DB->record_exists('capabilities', array('name' => $capability)));
192 // Switch to our user
193 $this->setUser($user);
195 // Ensure that the user has the capability first
196 $this->assertTrue(has_capability($capability, $coursecontext, $user->id));
198 // We first test whether the user is enrolled on the course as this
199 // seeds the cache, then we test for the capability
200 $this->assertTrue(is_enrolled($coursecontext, $user, '', true));
201 $this->assertTrue(is_enrolled($coursecontext, $user, $capability));
203 // Prevent the capability for this user role
204 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
205 $coursecontext->mark_dirty();
206 $this->assertFalse(has_capability($capability, $coursecontext, $user->id));
208 // Again, we seed the cache first by checking initial enrolment,
209 // and then we test the actual capability
210 $this->assertTrue(is_enrolled($coursecontext, $user, '', true));
211 $this->assertFalse(is_enrolled($coursecontext, $user, $capability));
213 // We need variable states to be reset for the next test
214 $this->resetAfterTest(true);
218 * Test logged in test.
221 public function test_isloggedin() {
224 $this->resetAfterTest();
227 $this->assertFalse(isloggedin());
229 $this->assertTrue(isloggedin());
233 * Test guest user test.
236 public function test_isguestuser() {
239 $this->resetAfterTest();
241 $guest = $DB->get_record('user', array('username'=>'guest'));
243 $this->assertFalse(isguestuser());
244 $this->setAdminUser();
245 $this->assertFalse(isguestuser());
246 $this->assertTrue(isguestuser($guest));
247 $this->assertTrue(isguestuser($guest->id));
248 $this->setUser($guest);
249 $this->assertTrue(isguestuser());
251 $users = $DB->get_records('user');
252 foreach ($users as $user) {
253 if ($user->username === 'guest') {
256 $this->assertFalse(isguestuser($user));
261 * Test capability riskiness.
264 public function test_is_safe_capability() {
266 // Note: there is not much to test, just make sure no notices are throw for the most dangerous cap.
267 $capability = $DB->get_record('capabilities', array('name'=>'moodle/site:config'), '*', MUST_EXIST);
268 $this->assertFalse(is_safe_capability($capability));
272 * Test context fetching.
275 public function test_get_context_info_array() {
276 $this->resetAfterTest();
278 $syscontext = context_system::instance();
279 $user = $this->getDataGenerator()->create_user();
280 $usercontext = context_user::instance($user->id);
281 $course = $this->getDataGenerator()->create_course();
282 $catcontext = context_coursecat::instance($course->category);
283 $coursecontext = context_course::instance($course->id);
284 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
285 $modcontext = context_module::instance($page->cmid);
286 $cm = get_coursemodule_from_instance('page', $page->id);
287 $block1 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$coursecontext->id));
288 $block1context = context_block::instance($block1->id);
289 $block2 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$modcontext->id));
290 $block2context = context_block::instance($block2->id);
292 $result = get_context_info_array($syscontext->id);
293 $this->assertCount(3, $result);
294 $this->assertSame($syscontext, $result[0]);
295 $this->assertSame(null, $result[1]);
296 $this->assertSame(null, $result[2]);
298 $result = get_context_info_array($usercontext->id);
299 $this->assertCount(3, $result);
300 $this->assertSame($usercontext, $result[0]);
301 $this->assertSame(null, $result[1]);
302 $this->assertSame(null, $result[2]);
304 $result = get_context_info_array($catcontext->id);
305 $this->assertCount(3, $result);
306 $this->assertSame($catcontext, $result[0]);
307 $this->assertSame(null, $result[1]);
308 $this->assertSame(null, $result[2]);
310 $result = get_context_info_array($coursecontext->id);
311 $this->assertCount(3, $result);
312 $this->assertSame($coursecontext, $result[0]);
313 $this->assertEquals($course->id, $result[1]->id);
314 $this->assertEquals($course->shortname, $result[1]->shortname);
315 $this->assertSame(null, $result[2]);
317 $result = get_context_info_array($block1context->id);
318 $this->assertCount(3, $result);
319 $this->assertSame($block1context, $result[0]);
320 $this->assertEquals($course->id, $result[1]->id);
321 $this->assertEquals($course->shortname, $result[1]->shortname);
322 $this->assertSame(null, $result[2]);
324 $result = get_context_info_array($modcontext->id);
325 $this->assertCount(3, $result);
326 $this->assertSame($modcontext, $result[0]);
327 $this->assertEquals($course->id, $result[1]->id);
328 $this->assertEquals($course->shortname, $result[1]->shortname);
329 $this->assertEquals($cm->id, $result[2]->id);
330 $this->assertEquals($cm->groupmembersonly, $result[2]->groupmembersonly);
332 $result = get_context_info_array($block2context->id);
333 $this->assertCount(3, $result);
334 $this->assertSame($block2context, $result[0]);
335 $this->assertEquals($course->id, $result[1]->id);
336 $this->assertEquals($course->shortname, $result[1]->shortname);
337 $this->assertEquals($cm->id, $result[2]->id);
338 $this->assertEquals($cm->groupmembersonly, $result[2]->groupmembersonly);
342 * Test looking for course contacts.
345 public function test_has_coursecontact_role() {
348 $this->resetAfterTest();
350 $users = $DB->get_records('user');
352 // Nobody is expected to have any course level roles.
353 $this->assertNotEmpty($CFG->coursecontact);
354 foreach($users as $user) {
355 $this->assertFalse(has_coursecontact_role($user->id));
358 $user = $this->getDataGenerator()->create_user();
359 $course = $this->getDataGenerator()->create_course();
360 role_assign($CFG->coursecontact, $user->id, context_course::instance($course->id));
361 $this->assertTrue(has_coursecontact_role($user->id));
365 * Test creation of roles.
368 public function test_create_role() {
371 $this->resetAfterTest();
373 $id = create_role('New student role', 'student2', 'New student description', 'student');
374 $role = $DB->get_record('role', array('id'=>$id));
376 $this->assertNotEmpty($role);
377 $this->assertEquals('New student role', $role->name);
378 $this->assertEquals('student2', $role->shortname);
379 $this->assertEquals('New student description', $role->description);
380 $this->assertEquals('student', $role->archetype);
384 * Test adding of capabilities to roles.
386 public function test_assign_capability() {
389 $this->resetAfterTest();
391 $user = $this->getDataGenerator()->create_user();
392 $syscontext = context_system::instance();
393 $frontcontext = context_course::instance(SITEID);
394 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
395 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability assigned to student by default
396 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')));
397 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')));
399 $this->setUser($user);
400 $result = assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $frontcontext->id);
401 $this->assertTrue($result);
402 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
403 $this->assertNotEmpty($permission);
404 $this->assertEquals(CAP_ALLOW, $permission->permission);
405 $this->assertEquals($user->id, $permission->modifierid);
408 $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $frontcontext->id, false);
409 $this->assertTrue($result);
410 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
411 $this->assertNotEmpty($permission);
412 $this->assertEquals(CAP_ALLOW, $permission->permission);
413 $this->assertEquals(3, $permission->modifierid);
415 $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $frontcontext->id, true);
416 $this->assertTrue($result);
417 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
418 $this->assertNotEmpty($permission);
419 $this->assertEquals(CAP_PROHIBIT, $permission->permission);
420 $this->assertEquals(0, $permission->modifierid);
422 $result = assign_capability('moodle/backup:backupcourse', CAP_INHERIT, $student->id, $frontcontext->id);
423 $this->assertTrue($result);
424 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
425 $this->assertEmpty($permission);
429 * Test removing of capabilities from roles.
431 public function test_unassign_capability() {
434 $this->resetAfterTest();
436 $syscontext = context_system::instance();
437 $frontcontext = context_course::instance(SITEID);
438 $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
439 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability assigned to manager by default
440 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $frontcontext->id);
442 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
443 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
445 $result = unassign_capability('moodle/backup:backupcourse', $manager->id, $syscontext->id);
446 $this->assertTrue($result);
447 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
448 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
449 unassign_capability('moodle/backup:backupcourse', $manager->id, $frontcontext);
450 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
452 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $syscontext->id);
453 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $frontcontext->id);
454 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
456 $result = unassign_capability('moodle/backup:backupcourse', $manager->id);
457 $this->assertTrue($result);
458 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
459 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
463 * Test role assigning
465 public function test_role_assign() {
468 $this->resetAfterTest();
470 $user = $this->getDataGenerator()->create_user();
471 $course = $this->getDataGenerator()->create_course();
472 $role = $DB->get_record('role', array('shortname'=>'student'));
475 $context = context_system::instance();
476 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
477 role_assign($role->id, $user->id, $context->id);
478 $ras = $DB->get_record('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id));
479 $this->assertNotEmpty($ras);
480 $this->assertSame('', $ras->component);
481 $this->assertSame('0', $ras->itemid);
482 $this->assertEquals($USER->id, $ras->modifierid);
484 $this->setAdminUser();
485 $context = context_course::instance($course->id);
486 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
487 role_assign($role->id, $user->id, $context->id, 'enrol_self', 1, 666);
488 $ras = $DB->get_record('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id));
489 $this->assertNotEmpty($ras);
490 $this->assertSame('enrol_self', $ras->component);
491 $this->assertSame('1', $ras->itemid);
492 $this->assertEquals($USER->id, $ras->modifierid);
493 $this->assertEquals(666, $ras->timemodified);
497 * Test role unassigning
500 public function test_role_unassign() {
503 $this->resetAfterTest();
505 $user = $this->getDataGenerator()->create_user();
506 $course = $this->getDataGenerator()->create_course();
507 $role = $DB->get_record('role', array('shortname'=>'student'));
509 $context = context_system::instance();
510 role_assign($role->id, $user->id, $context->id);
511 $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
512 role_unassign($role->id, $user->id, $context->id);
513 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
515 role_assign($role->id, $user->id, $context->id, 'enrol_self', 1);
516 $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
517 role_unassign($role->id, $user->id, $context->id, 'enrol_self', 1);
518 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
522 * Test role unassigning
525 public function test_role_unassign_all() {
528 $this->resetAfterTest();
530 $user = $this->getDataGenerator()->create_user();
531 $course = $this->getDataGenerator()->create_course();
532 $role = $DB->get_record('role', array('shortname'=>'student'));
533 $syscontext = context_system::instance();
534 $coursecontext = context_course::instance($course->id);
535 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
536 $modcontext = context_module::instance($page->cmid);
538 role_assign($role->id, $user->id, $syscontext->id);
539 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
540 $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id)));
541 role_unassign_all(array('userid'=>$user->id, 'roleid'=>$role->id));
542 $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id)));
544 role_assign($role->id, $user->id, $syscontext->id);
545 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
546 role_assign($role->id, $user->id, $modcontext->id);
547 $this->assertEquals(3, $DB->count_records('role_assignments', array('userid'=>$user->id)));
548 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id), false);
549 $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id)));
550 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id), true);
551 $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id)));
552 role_unassign_all(array('userid'=>$user->id));
553 $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id)));
555 role_assign($role->id, $user->id, $syscontext->id);
556 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
557 role_assign($role->id, $user->id, $coursecontext->id);
558 role_assign($role->id, $user->id, $modcontext->id);
559 $this->assertEquals(4, $DB->count_records('role_assignments', array('userid'=>$user->id)));
560 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id, 'component'=>'enrol_self'), true, true);
561 $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id)));
568 public function test_get_roles_with_capability() {
571 $this->resetAfterTest();
573 $syscontext = context_system::instance();
574 $frontcontext = context_course::instance(SITEID);
575 $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
576 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
578 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability is ok
579 $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse'));
581 $roles = get_roles_with_capability('moodle/backup:backupcourse');
582 $this->assertEquals(array(), $roles);
584 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $syscontext->id);
585 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $manager->id, $frontcontext->id);
586 assign_capability('moodle/backup:backupcourse', CAP_PREVENT, $teacher->id, $frontcontext->id);
588 $roles = get_roles_with_capability('moodle/backup:backupcourse');
589 $this->assertEquals(array($teacher->id, $manager->id), array_keys($roles), '', 0, 10, true);
591 $roles = get_roles_with_capability('moodle/backup:backupcourse', CAP_ALLOW);
592 $this->assertEquals(array($manager->id), array_keys($roles), '', 0, 10, true);
594 $roles = get_roles_with_capability('moodle/backup:backupcourse', NULL, $syscontext);
595 $this->assertEquals(array($manager->id), array_keys($roles), '', 0, 10, true);
599 * Test deleting of roles.
602 public function test_delete_role() {
605 $this->resetAfterTest();
607 $role = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
608 $user = $this->getDataGenerator()->create_user();
609 role_assign($role->id, $user->id, context_system::instance());
610 $course = $this->getDataGenerator()->create_course();
611 $rolename = (object)array('roleid'=>$role->id, 'name'=>'Man', 'contextid'=>context_course::instance($course->id)->id);
612 $DB->insert_record('role_names', $rolename);
614 $this->assertTrue($DB->record_exists('role_assignments', array('roleid'=>$role->id)));
615 $this->assertTrue($DB->record_exists('role_capabilities', array('roleid'=>$role->id)));
616 $this->assertTrue($DB->record_exists('role_names', array('roleid'=>$role->id)));
617 $this->assertTrue($DB->record_exists('role_context_levels', array('roleid'=>$role->id)));
618 $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$role->id)));
619 $this->assertTrue($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id)));
620 $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$role->id)));
621 $this->assertTrue($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id)));
623 $result = delete_role($role->id);
624 $this->assertTrue($result);
625 $this->assertFalse($DB->record_exists('role', array('id'=>$role->id)));
626 $this->assertFalse($DB->record_exists('role_assignments', array('roleid'=>$role->id)));
627 $this->assertFalse($DB->record_exists('role_capabilities', array('roleid'=>$role->id)));
628 $this->assertFalse($DB->record_exists('role_names', array('roleid'=>$role->id)));
629 $this->assertFalse($DB->record_exists('role_context_levels', array('roleid'=>$role->id)));
630 $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$role->id)));
631 $this->assertFalse($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id)));
632 $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$role->id)));
633 $this->assertFalse($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id)));
637 * Test fetching of all roles.
640 public function test_get_all_roles() {
643 $this->resetAfterTest();
645 $allroles = get_all_roles();
646 $this->assertEquals('array', gettype($allroles));
647 $this->assertCount(8, $allroles); // there are 8 roles is standard install
649 $role = reset($allroles);
650 $role = (array)$role;
652 $this->assertEquals(array('id', 'name', 'shortname', 'description', 'sortorder', 'archetype'), array_keys($role), '', 0, 10, true);
654 foreach($allroles as $roleid => $role) {
655 $this->assertEquals($role->id, $roleid);
658 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
659 $course = $this->getDataGenerator()->create_course();
660 $coursecontext = context_course::instance($course->id);
661 $otherid = create_role('Other role', 'other', 'Some other role', '');
662 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
663 $DB->insert_record('role_names', $teacherename);
664 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
665 $DB->insert_record('role_names', $otherrename);
666 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id), '', 'roleid,name');
668 $allroles = get_all_roles($coursecontext);
669 $this->assertEquals('array', gettype($allroles));
670 $this->assertCount(9, $allroles);
671 $role = reset($allroles);
672 $role = (array)$role;
674 $this->assertEquals(array('id', 'name', 'shortname', 'description', 'sortorder', 'archetype', 'coursealias'), array_keys($role), '', 0, 10, true);
676 foreach($allroles as $roleid => $role) {
677 $this->assertEquals($role->id, $roleid);
678 if (isset($renames[$roleid])) {
679 $this->assertSame($renames[$roleid], $role->coursealias);
681 $this->assertSame(null, $role->coursealias);
687 * Test getting of all archetypes.
690 public function test_get_role_archetypes() {
691 $archetypes = get_role_archetypes();
692 $this->assertCount(8, $archetypes); // there are 8 archetypes in standard install
693 foreach ($archetypes as $k=>$v) {
694 $this->assertSame($k, $v);
699 * Test getting of roles with given archetype.
702 public function test_get_archetype_roles() {
703 $this->resetAfterTest();
705 // New install should have 1 role for each archetype.
706 $archetypes = get_role_archetypes();
707 foreach ($archetypes as $archetype) {
708 $roles = get_archetype_roles($archetype);
709 $this->assertCount(1, $roles);
710 $role = reset($roles);
711 $this->assertEquals($archetype, $role->archetype);
714 create_role('New student role', 'student2', 'New student description', 'student');
715 $roles = get_archetype_roles('student');
716 $this->assertCount(2, $roles);
720 * Test aliased role names
723 public function test_role_get_name() {
726 $this->resetAfterTest();
728 $allroles = $DB->get_records('role');
729 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
730 $course = $this->getDataGenerator()->create_course();
731 $coursecontext = context_course::instance($course->id);
732 $otherid = create_role('Other role', 'other', 'Some other role', '');
733 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
734 $DB->insert_record('role_names', $teacherename);
735 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
736 $DB->insert_record('role_names', $otherrename);
737 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id), '', 'roleid,name');
739 foreach ($allroles as $role) {
740 // Get localised name from lang pack.
741 $this->assertSame('', $role->name);
742 $name = role_get_name($role, null, ROLENAME_ORIGINAL);
743 $this->assertNotEmpty($name);
744 $this->assertNotEquals($role->shortname, $name);
746 if (isset($renames[$role->id])) {
747 $this->assertSame($renames[$role->id], role_get_name($role, $coursecontext));
748 $this->assertSame($renames[$role->id], role_get_name($role, $coursecontext, ROLENAME_ALIAS));
749 $this->assertSame($renames[$role->id], role_get_name($role, $coursecontext, ROLENAME_ALIAS_RAW));
750 $this->assertSame("{$renames[$role->id]} ($name)", role_get_name($role, $coursecontext, ROLENAME_BOTH));
752 $this->assertSame($name, role_get_name($role, $coursecontext));
753 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_ALIAS));
754 $this->assertSame(null, role_get_name($role, $coursecontext, ROLENAME_ALIAS_RAW));
755 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_BOTH));
757 $this->assertSame($name, role_get_name($role));
758 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_ORIGINAL));
759 $this->assertSame($name, role_get_name($role, null, ROLENAME_ORIGINAL));
760 $this->assertSame($role->shortname, role_get_name($role, $coursecontext, ROLENAME_SHORT));
761 $this->assertSame($role->shortname, role_get_name($role, null, ROLENAME_SHORT));
762 $this->assertSame("$name ($role->shortname)", role_get_name($role, $coursecontext, ROLENAME_ORIGINALANDSHORT));
763 $this->assertSame("$name ($role->shortname)", role_get_name($role, null, ROLENAME_ORIGINALANDSHORT));
764 $this->assertSame(null, role_get_name($role, null, ROLENAME_ALIAS_RAW));
769 * Test tweaking of role name arrays
772 public function test_role_fix_names() {
775 $this->resetAfterTest();
777 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
778 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
779 $otherid = create_role('Other role', 'other', 'Some other role', '');
780 $anotherid = create_role('Another role', 'another', 'Yet another other role', '');
781 $allroles = $DB->get_records('role');
783 $syscontext = context_system::instance();
784 $frontcontext = context_course::instance(SITEID);
785 $course = $this->getDataGenerator()->create_course();
786 $coursecontext = context_course::instance($course->id);
787 $category = $DB->get_record('course_categories', array('id'=>$course->category), '*', MUST_EXIST);
788 $categorycontext = context_coursecat::instance($category->id);
790 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
791 $DB->insert_record('role_names', $teacherename);
792 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
793 $DB->insert_record('role_names', $otherrename);
794 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id), '', 'roleid,name');
796 // Make sure all localname contain proper values for each ROLENAME_ constant,
797 // note role_get_name() on frontpage is used to get the original name for future comatibility.
799 unset($roles[$student->id]); // Remove one roel to make sure no role is added or removed.
800 $rolenames = array();
801 foreach ($roles as $role) {
802 $rolenames[$role->id] = $role->name;
805 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
806 foreach ($alltypes as $type) {
807 $fixed = role_fix_names($roles, $coursecontext, $type);
808 $this->assertCount(count($roles), $fixed);
809 foreach($fixed as $roleid=>$rolename) {
810 $this->assertInstanceOf('stdClass', $rolename);
811 $role = $allroles[$roleid];
812 $name = role_get_name($role, $coursecontext, $type);
813 $this->assertSame($name, $rolename->localname);
815 $fixed = role_fix_names($rolenames, $coursecontext, $type);
816 $this->assertCount(count($rolenames), $fixed);
817 foreach($fixed as $roleid=>$rolename) {
818 $role = $allroles[$roleid];
819 $name = role_get_name($role, $coursecontext, $type);
820 $this->assertSame($name, $rolename);
826 * Test role default allows.
828 public function test_get_default_role_archetype_allows() {
829 $archetypes = get_role_archetypes();
830 foreach ($archetypes as $archetype) {
832 $result = get_default_role_archetype_allows('assign', $archetype);
833 $this->assertTrue(is_array($result));
835 $result = get_default_role_archetype_allows('override', $archetype);
836 $this->assertTrue(is_array($result));
838 $result = get_default_role_archetype_allows('switch', $archetype);
839 $this->assertTrue(is_array($result));
842 $result = get_default_role_archetype_allows('assign', '');
843 $this->assertSame(array(), $result);
845 $result = get_default_role_archetype_allows('override', '');
846 $this->assertSame(array(), $result);
848 $result = get_default_role_archetype_allows('switch', '');
849 $this->assertSame(array(), $result);
851 $result = get_default_role_archetype_allows('assign', 'wrongarchetype');
852 $this->assertSame(array(), $result);
853 $this->assertDebuggingCalled();
855 $result = get_default_role_archetype_allows('override', 'wrongarchetype');
856 $this->assertSame(array(), $result);
857 $this->assertDebuggingCalled();
859 $result = get_default_role_archetype_allows('switch', 'wrongarchetype');
860 $this->assertSame(array(), $result);
861 $this->assertDebuggingCalled();
865 * Test allowing of role assignments.
868 public function test_allow_assign() {
871 $this->resetAfterTest();
873 $otherid = create_role('Other role', 'other', 'Some other role', '');
874 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
876 $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id)));
877 allow_assign($otherid, $student->id);
878 $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id)));
882 * Test allowing of role overrides.
885 public function test_allow_override() {
888 $this->resetAfterTest();
890 $otherid = create_role('Other role', 'other', 'Some other role', '');
891 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
893 $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id)));
894 allow_override($otherid, $student->id);
895 $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id)));
899 * Test allowing of role switching.
902 public function test_allow_switch() {
905 $this->resetAfterTest();
907 $otherid = create_role('Other role', 'other', 'Some other role', '');
908 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
910 $this->assertFalse($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id)));
911 allow_switch($otherid, $student->id);
912 $this->assertTrue($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id)));
916 * Test returning of assignable roles in context.
919 public function test_get_assignable_roles() {
922 $this->resetAfterTest();
924 $course = $this->getDataGenerator()->create_course();
925 $coursecontext = context_course::instance($course->id);
927 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
928 $teacher = $this->getDataGenerator()->create_user();
929 role_assign($teacherrole->id, $teacher->id, $coursecontext);
930 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
931 $DB->insert_record('role_names', $teacherename);
933 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
934 $student = $this->getDataGenerator()->create_user();
935 role_assign($studentrole->id, $student->id, $coursecontext);
937 $contexts = $DB->get_records('context');
938 $users = $DB->get_records('user');
939 $allroles = $DB->get_records('role');
941 // Evaluate all results for all users in all contexts.
942 foreach($users as $user) {
943 $this->setUser($user);
944 foreach ($contexts as $contextid=>$unused) {
945 $context = context_helper::instance_by_id($contextid);
946 $roles = get_assignable_roles($context, ROLENAME_SHORT);
947 foreach ($allroles as $roleid=>$role) {
948 if (isset($roles[$roleid])) {
949 if (is_siteadmin()) {
950 $this->assertTrue($DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel, 'roleid'=>$roleid)));
952 $this->assertTrue(user_can_assign($context, $roleid), "u:$user->id r:$roleid");
954 $this->assertEquals($role->shortname, $roles[$roleid]);
956 $allowed = $DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel, 'roleid'=>$roleid));
957 if (is_siteadmin()) {
958 $this->assertFalse($allowed);
960 $this->assertFalse($allowed and user_can_assign($context, $roleid), "u:$user->id, r:{$allroles[$roleid]->name}, c:$context->contextlevel");
967 // not-logged-in user
969 foreach ($contexts as $contextid=>$unused) {
970 $context = context_helper::instance_by_id($contextid);
971 $roles = get_assignable_roles($context, ROLENAME_SHORT);
972 $this->assertSame(array(), $roles);
975 // Test current user.
977 $admin = $DB->get_record('user', array('username'=>'admin'), '*', MUST_EXIST);
978 $roles1 = get_assignable_roles($coursecontext, ROLENAME_SHORT, false, $admin);
979 $roles2 = get_assignable_roles($coursecontext, ROLENAME_SHORT, false, $admin->id);
980 $this->setAdminUser();
981 $roles3 = get_assignable_roles($coursecontext, ROLENAME_SHORT);
982 $this->assertSame($roles1, $roles3);
983 $this->assertSame($roles2, $roles3);
985 // Test parameter defaults.
986 $this->setAdminUser();
987 $roles1 = get_assignable_roles($coursecontext);
988 $roles2 = get_assignable_roles($coursecontext, ROLENAME_ALIAS, false, $admin);
989 $this->assertEquals($roles2, $roles1);
991 // Verify returned names - let's allow all roles everywhere to simplify this a bit.
992 $alllevels = context_helper::get_all_levels();
993 $alllevels = array_keys($alllevels);
994 foreach($allroles as $roleid=>$role) {
995 set_role_contextlevels($roleid, $alllevels);
997 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
998 foreach ($alltypes as $type) {
999 $rolenames = role_fix_names($allroles, $coursecontext, $type);
1000 $roles = get_assignable_roles($coursecontext, $type, false, $admin);
1001 foreach ($roles as $roleid=>$rolename) {
1002 $this->assertSame($rolenames[$roleid]->localname, $rolename);
1007 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
1008 foreach ($alltypes as $type) {
1009 $roles = get_assignable_roles($coursecontext, $type, false, $admin);
1010 list($rolenames, $rolecounts, $nameswithcounts) = get_assignable_roles($coursecontext, $type, true, $admin);
1011 $this->assertEquals($roles, $rolenames);
1012 foreach ($rolenames as $roleid=>$name) {
1013 if ($roleid == $teacherrole->id or $roleid == $studentrole->id) {
1014 $this->assertEquals(1, $rolecounts[$roleid]);
1016 $this->assertEquals(0, $rolecounts[$roleid]);
1018 $this->assertEquals("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]);
1024 * Test getting of all switchable roles.
1027 public function test_get_switchable_roles() {
1030 $this->resetAfterTest();
1032 $course = $this->getDataGenerator()->create_course();
1033 $coursecontext = context_course::instance($course->id);
1035 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1036 $teacher = $this->getDataGenerator()->create_user();
1037 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1038 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1039 $DB->insert_record('role_names', $teacherename);
1041 $contexts = $DB->get_records('context');
1042 $users = $DB->get_records('user');
1043 $allroles = $DB->get_records('role');
1045 // Evaluate all results for all users in all contexts.
1046 foreach($users as $user) {
1047 $this->setUser($user);
1048 foreach ($contexts as $contextid=>$unused) {
1049 $context = context_helper::instance_by_id($contextid);
1050 $roles = get_switchable_roles($context);
1051 foreach ($allroles as $roleid=>$role) {
1052 if (is_siteadmin()) {
1053 $this->assertTrue(isset($roles[$roleid]));
1055 $parents = $context->get_parent_context_ids(true);
1056 $pcontexts = implode(',' , $parents);
1057 $allowed = $DB->record_exists_sql(
1060 JOIN {role_allow_switch} ras ON ras.allowswitch = r.id
1061 JOIN {role_assignments} ra ON ra.roleid = ras.roleid
1062 WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid
1064 array('userid'=>$user->id, 'roleid'=>$roleid)
1066 if (isset($roles[$roleid])) {
1067 $this->assertTrue($allowed);
1069 $this->assertFalse($allowed);
1073 if (isset($roles[$roleid])) {
1074 $coursecontext = $context->get_course_context(false);
1075 $this->assertEquals(role_get_name($role, $coursecontext), $roles[$roleid]);
1083 * Test getting of all overridable roles.
1086 public function test_get_overridable_roles() {
1089 $this->resetAfterTest();
1091 $course = $this->getDataGenerator()->create_course();
1092 $coursecontext = context_course::instance($course->id);
1094 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1095 $teacher = $this->getDataGenerator()->create_user();
1096 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1097 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1098 $DB->insert_record('role_names', $teacherename);
1099 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability is ok
1100 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $teacher->id, $coursecontext->id);
1102 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1103 $student = $this->getDataGenerator()->create_user();
1104 role_assign($studentrole->id, $student->id, $coursecontext);
1106 $contexts = $DB->get_records('context');
1107 $users = $DB->get_records('user');
1108 $allroles = $DB->get_records('role');
1110 // Evaluate all results for all users in all contexts.
1111 foreach($users as $user) {
1112 $this->setUser($user);
1113 foreach ($contexts as $contextid=>$unused) {
1114 $context = context_helper::instance_by_id($contextid);
1115 $roles = get_overridable_roles($context, ROLENAME_SHORT);
1116 foreach ($allroles as $roleid=>$role) {
1117 $hascap = has_any_capability(array('moodle/role:safeoverride', 'moodle/role:override'), $context);
1118 if (is_siteadmin()) {
1119 $this->assertTrue(isset($roles[$roleid]));
1121 $parents = $context->get_parent_context_ids(true);
1122 $pcontexts = implode(',' , $parents);
1123 $allowed = $DB->record_exists_sql(
1126 JOIN {role_allow_override} rao ON r.id = rao.allowoverride
1127 JOIN {role_assignments} ra ON rao.roleid = ra.roleid
1128 WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid
1130 array('userid'=>$user->id, 'roleid'=>$roleid)
1132 if (isset($roles[$roleid])) {
1133 $this->assertTrue($hascap);
1134 $this->assertTrue($allowed);
1136 $this->assertFalse($hascap and $allowed);
1140 if (isset($roles[$roleid])) {
1141 $this->assertEquals($role->shortname, $roles[$roleid]);
1147 // Test parameter defaults.
1148 $this->setAdminUser();
1149 $roles1 = get_overridable_roles($coursecontext);
1150 $roles2 = get_overridable_roles($coursecontext, ROLENAME_ALIAS, false);
1151 $this->assertEquals($roles2, $roles1);
1153 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
1154 foreach ($alltypes as $type) {
1155 $rolenames = role_fix_names($allroles, $coursecontext, $type);
1156 $roles = get_overridable_roles($coursecontext, $type, false);
1157 foreach ($roles as $roleid=>$rolename) {
1158 $this->assertSame($rolenames[$roleid]->localname, $rolename);
1163 $roles = get_overridable_roles($coursecontext, ROLENAME_ALIAS, false);
1164 list($rolenames, $rolecounts, $nameswithcounts) = get_overridable_roles($coursecontext, ROLENAME_ALIAS, true);
1165 $this->assertEquals($roles, $rolenames);
1166 foreach ($rolenames as $roleid=>$name) {
1167 if ($roleid == $teacherrole->id) {
1168 $this->assertEquals(1, $rolecounts[$roleid]);
1170 $this->assertEquals(0, $rolecounts[$roleid]);
1172 $this->assertEquals("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]);
1177 * Test we have context level defaults.
1180 public function test_get_default_contextlevels() {
1181 $archetypes = get_role_archetypes();
1182 $alllevels = context_helper::get_all_levels();
1183 foreach ($archetypes as $archetype) {
1184 $defaults = get_default_contextlevels($archetype);
1185 $this->assertTrue(is_array($defaults));
1186 foreach ($defaults as $level) {
1187 $this->assertTrue(isset($alllevels[$level]));
1193 * Test role context level setup.
1196 public function test_set_role_contextlevels() {
1199 $this->resetAfterTest();
1201 $roleid = create_role('New student role', 'student2', 'New student description', 'student');
1203 $this->assertFalse($DB->record_exists('role_context_levels', array('roleid' => $roleid)));
1205 set_role_contextlevels($roleid, array(CONTEXT_COURSE, CONTEXT_MODULE));
1206 $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel');
1207 $this->assertCount(2, $levels);
1208 $this->assertTrue(isset($levels[CONTEXT_COURSE]));
1209 $this->assertTrue(isset($levels[CONTEXT_MODULE]));
1211 set_role_contextlevels($roleid, array(CONTEXT_COURSE));
1212 $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel');
1213 $this->assertCount(1, $levels);
1214 $this->assertTrue(isset($levels[CONTEXT_COURSE]));
1218 * Test getting of role context levels
1221 public function test_get_roles_for_contextlevels() {
1224 $allroles = get_all_roles();
1225 foreach (context_helper::get_all_levels() as $level=>$unused) {
1226 $roles = get_roles_for_contextlevels($level);
1227 foreach ($allroles as $roleid=>$unused) {
1228 $exists = $DB->record_exists('role_context_levels', array('contextlevel'=>$level, 'roleid'=>$roleid));
1229 if (in_array($roleid, $roles)) {
1230 $this->assertTrue($exists);
1232 $this->assertFalse($exists);
1239 * Test default enrol roles.
1242 public function test_get_default_enrol_roles() {
1243 $this->resetAfterTest();
1245 $course = $this->getDataGenerator()->create_course();
1246 $coursecontext = context_course::instance($course->id);
1248 $id2 = create_role('New student role', 'student2', 'New student description', 'student');
1249 set_role_contextlevels($id2, array(CONTEXT_COURSE));
1251 $allroles = get_all_roles();
1252 $expected = array($id2=>$allroles[$id2]);
1254 foreach(get_role_archetypes() as $archetype) {
1255 $defaults = get_default_contextlevels($archetype);
1256 if (in_array(CONTEXT_COURSE, $defaults)) {
1257 $roles = get_archetype_roles($archetype);
1258 foreach($roles as $role) {
1259 $expected[$role->id] = $role;
1264 $roles = get_default_enrol_roles($coursecontext);
1265 foreach ($allroles as $role) {
1266 $this->assertEquals(isset($expected[$role->id]), isset($roles[$role->id]));
1267 if (isset($roles[$role->id])) {
1268 $this->assertEquals(role_get_name($role, $coursecontext), $roles[$role->id]);
1274 * Test getting of role users.
1277 public function test_get_role_users() {
1280 $this->resetAfterTest();
1282 $systemcontext = context_system::instance();
1283 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1284 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1285 $course = $this->getDataGenerator()->create_course();
1286 $coursecontext = context_course::instance($course->id);
1287 $otherid = create_role('Other role', 'other', 'Some other role', '');
1288 $teacherrename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1289 $DB->insert_record('role_names', $teacherrename);
1290 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
1291 $DB->insert_record('role_names', $otherrename);
1293 $user1 = $this->getDataGenerator()->create_user(array('firstname'=>'John', 'lastname'=>'Smith'));
1294 role_assign($teacherrole->id, $user1->id, $coursecontext->id);
1295 $user2 = $this->getDataGenerator()->create_user(array('firstname'=>'Jan', 'lastname'=>'Kovar'));
1296 role_assign($teacherrole->id, $user2->id, $systemcontext->id);
1297 $user3 = $this->getDataGenerator()->create_user();
1298 $this->getDataGenerator()->enrol_user($user3->id, $course->id, $teacherrole->id);
1299 $user4 = $this->getDataGenerator()->create_user();
1300 $this->getDataGenerator()->enrol_user($user4->id, $course->id, $studentrole->id);
1302 $group = $this->getDataGenerator()->create_group(array('courseid'=>$course->id));
1303 groups_add_member($group, $user3);
1305 $users = get_role_users($teacherrole->id, $coursecontext);
1306 $this->assertCount(2, $users);
1307 $this->assertArrayHasKey($user1->id, $users);
1308 $this->assertEquals($users[$user1->id]->id, $user1->id);
1309 $this->assertEquals($users[$user1->id]->roleid, $teacherrole->id);
1310 $this->assertEquals($users[$user1->id]->rolename, $teacherrole->name);
1311 $this->assertEquals($users[$user1->id]->roleshortname, $teacherrole->shortname);
1312 $this->assertEquals($users[$user1->id]->rolecoursealias, $teacherrename->name);
1313 $this->assertArrayHasKey($user3->id, $users);
1314 $this->assertEquals($users[$user3->id]->id, $user3->id);
1315 $this->assertEquals($users[$user3->id]->roleid, $teacherrole->id);
1316 $this->assertEquals($users[$user3->id]->rolename, $teacherrole->name);
1317 $this->assertEquals($users[$user3->id]->roleshortname, $teacherrole->shortname);
1318 $this->assertEquals($users[$user3->id]->rolecoursealias, $teacherrename->name);
1320 $users = get_role_users($teacherrole->id, $coursecontext, true);
1321 $this->assertCount(3, $users);
1323 $users = get_role_users($teacherrole->id, $coursecontext, true, '', null, null, '', 2, 1);
1324 $this->assertCount(1, $users);
1326 $users = get_role_users($teacherrole->id, $coursecontext, false, 'u.id, u.email, u.idnumber', 'u.idnumber');
1327 $this->assertCount(2, $users);
1328 $this->assertArrayHasKey($user1->id, $users);
1329 $this->assertArrayHasKey($user3->id, $users);
1331 $users = get_role_users($teacherrole->id, $coursecontext, false, 'u.id, u.email, u.idnumber', 'u.idnumber', null, $group->id);
1332 $this->assertCount(1, $users);
1333 $this->assertArrayHasKey($user3->id, $users);
1335 $users = get_role_users($teacherrole->id, $coursecontext, true, 'u.id, u.email, u.idnumber, u.firstname', 'u.idnumber', null, '', '', '', 'u.firstname = :xfirstname', array('xfirstname'=>'John'));
1336 $this->assertCount(1, $users);
1337 $this->assertArrayHasKey($user1->id, $users);
1341 * Test used role query.
1344 public function test_get_roles_used_in_context() {
1347 $this->resetAfterTest();
1349 $systemcontext = context_system::instance();
1350 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1351 $course = $this->getDataGenerator()->create_course();
1352 $coursecontext = context_course::instance($course->id);
1353 $otherid = create_role('Other role', 'other', 'Some other role', '');
1354 $teacherrename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1355 $DB->insert_record('role_names', $teacherrename);
1356 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
1357 $DB->insert_record('role_names', $otherrename);
1359 $user1 = $this->getDataGenerator()->create_user();
1360 role_assign($teacherrole->id, $user1->id, $coursecontext->id);
1362 $roles = get_roles_used_in_context($coursecontext);
1363 $this->assertCount(1, $roles);
1364 $role = reset($roles);
1365 $roleid = key($roles);
1366 $this->assertEquals($roleid, $role->id);
1367 $this->assertEquals($teacherrole->id, $role->id);
1368 $this->assertEquals($teacherrole->name, $role->name);
1369 $this->assertEquals($teacherrole->shortname, $role->shortname);
1370 $this->assertEquals($teacherrole->sortorder, $role->sortorder);
1371 $this->assertEquals($teacherrename->name, $role->coursealias);
1373 $user2 = $this->getDataGenerator()->create_user();
1374 role_assign($teacherrole->id, $user2->id, $systemcontext->id);
1375 role_assign($otherid, $user2->id, $systemcontext->id);
1377 $roles = get_roles_used_in_context($systemcontext);
1378 $this->assertCount(2, $roles);
1382 * Test roles used in course.
1385 public function test_get_user_roles_in_course() {
1388 $this->resetAfterTest();
1390 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1391 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1392 $course = $this->getDataGenerator()->create_course();
1393 $coursecontext = context_course::instance($course->id);
1394 $teacherrename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1395 $DB->insert_record('role_names', $teacherrename);
1397 $roleids = explode(',', $CFG->profileroles); // should include teacher and student in new installs
1398 $this->assertTrue(in_array($teacherrole->id, $roleids));
1399 $this->assertTrue(in_array($studentrole->id, $roleids));
1401 $user1 = $this->getDataGenerator()->create_user();
1402 role_assign($teacherrole->id, $user1->id, $coursecontext->id);
1403 role_assign($studentrole->id, $user1->id, $coursecontext->id);
1404 $user2 = $this->getDataGenerator()->create_user();
1405 role_assign($studentrole->id, $user2->id, $coursecontext->id);
1406 $user3 = $this->getDataGenerator()->create_user();
1408 $roles = get_user_roles_in_course($user1->id, $course->id);
1409 $this->assertEquals(1, preg_match_all('/,/', $roles, $matches));
1410 $this->assertTrue(strpos($roles, role_get_name($teacherrole, $coursecontext)) !== false);
1412 $roles = get_user_roles_in_course($user2->id, $course->id);
1413 $this->assertEquals(0, preg_match_all('/,/', $roles, $matches));
1414 $this->assertTrue(strpos($roles, role_get_name($studentrole, $coursecontext)) !== false);
1416 $roles = get_user_roles_in_course($user3->id, $course->id);
1417 $this->assertSame('', $roles);
1421 * Test has_capability(), has_any_capability() and has_all_capabilities().
1423 public function test_has_capability_and_friends() {
1426 $this->resetAfterTest();
1428 $course = $this->getDataGenerator()->create_course();
1429 $coursecontext = context_course::instance($course->id);
1430 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1431 $teacher = $this->getDataGenerator()->create_user();
1432 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1433 $admin = $DB->get_record('user', array('username'=>'admin'));
1435 // Note: Here are used default capabilities, the full test is in permission evaluation bellow,
1436 // use two capabilities that teacher has and one does not, none of them should be allowed for not-logged-in user.
1438 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupsection')));
1439 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse')));
1440 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/site:approvecourse')));
1442 $sca = array('moodle/backup:backupsection', 'moodle/backup:backupcourse', 'moodle/site:approvecourse');
1443 $sc = array('moodle/backup:backupsection', 'moodle/backup:backupcourse');
1446 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext));
1447 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext));
1448 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext));
1449 $this->assertFalse(has_any_capability($sca, $coursecontext));
1450 $this->assertFalse(has_all_capabilities($sca, $coursecontext));
1452 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $teacher));
1453 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $teacher));
1454 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $teacher));
1455 $this->assertTrue(has_any_capability($sca, $coursecontext, $teacher));
1456 $this->assertTrue(has_all_capabilities($sc, $coursecontext, $teacher));
1457 $this->assertFalse(has_all_capabilities($sca, $coursecontext, $teacher));
1459 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $admin));
1460 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $admin));
1461 $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext, $admin));
1462 $this->assertTrue(has_any_capability($sca, $coursecontext, $admin));
1463 $this->assertTrue(has_all_capabilities($sc, $coursecontext, $admin));
1464 $this->assertTrue(has_all_capabilities($sca, $coursecontext, $admin));
1466 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, $admin, false));
1467 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, $admin, false));
1468 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $admin, false));
1469 $this->assertFalse(has_any_capability($sca, $coursecontext, $admin, false));
1470 $this->assertFalse(has_all_capabilities($sc, $coursecontext, $admin, false));
1471 $this->assertFalse(has_all_capabilities($sca, $coursecontext, $admin, false));
1473 $this->setUser($teacher);
1474 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext));
1475 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext));
1476 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext));
1477 $this->assertTrue(has_any_capability($sca, $coursecontext));
1478 $this->assertTrue(has_all_capabilities($sc, $coursecontext));
1479 $this->assertFalse(has_all_capabilities($sca, $coursecontext));
1481 $this->setAdminUser();
1482 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext));
1483 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext));
1484 $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext));
1485 $this->assertTrue(has_any_capability($sca, $coursecontext));
1486 $this->assertTrue(has_all_capabilities($sc, $coursecontext));
1487 $this->assertTrue(has_all_capabilities($sca, $coursecontext));
1489 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, 0));
1490 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, 0));
1491 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, 0));
1492 $this->assertFalse(has_any_capability($sca, $coursecontext, 0));
1493 $this->assertFalse(has_all_capabilities($sca, $coursecontext, 0));
1497 * Test require_capability() exceptions.
1500 public function test_require_capability() {
1501 $this->resetAfterTest();
1503 $syscontext = context_system::instance();
1506 $this->assertFalse(has_capability('moodle/site:config', $syscontext));
1508 require_capability('moodle/site:config', $syscontext);
1509 $this->fail('Exception expected from require_capability()');
1510 } catch (Exception $e) {
1511 $this->assertInstanceOf('required_capability_exception', $e);
1513 $this->setAdminUser();
1514 $this->assertFalse(has_capability('moodle/site:config', $syscontext, 0));
1516 require_capability('moodle/site:config', $syscontext, 0);
1517 $this->fail('Exception expected from require_capability()');
1518 } catch (Exception $e) {
1519 $this->assertInstanceOf('required_capability_exception', $e);
1521 $this->assertFalse(has_capability('moodle/site:config', $syscontext, null, false));
1523 require_capability('moodle/site:config', $syscontext, null, false);
1524 $this->fail('Exception expected from require_capability()');
1525 } catch (Exception $e) {
1526 $this->assertInstanceOf('required_capability_exception', $e);
1533 * A small functional test of permission evaluations.
1536 public function test_permission_evaluation() {
1537 global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;
1539 $this->resetAfterTest(true);
1541 $generator = $this->getDataGenerator();
1543 // Fill the site with some real data
1544 $testcategories = array();
1545 $testcourses = array();
1546 $testpages = array();
1547 $testblocks = array();
1548 $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
1550 $systemcontext = context_system::instance();
1551 $frontpagecontext = context_course::instance(SITEID);
1553 // Add block to system context
1554 $bi = $generator->create_block('online_users');
1555 context_block::instance($bi->id);
1556 $testblocks[] = $bi->id;
1559 $testusers = array();
1560 for($i=0; $i<20; $i++) {
1561 $user = $generator->create_user();
1562 $testusers[$i] = $user->id;
1563 $usercontext = context_user::instance($user->id);
1565 // Add block to user profile
1566 $bi = $generator->create_block('online_users', array('parentcontextid'=>$usercontext->id));
1567 $testblocks[] = $bi->id;
1569 // Deleted user - should be ignored everywhere, can not have context
1570 $generator->create_user(array('deleted'=>1));
1572 // Add block to frontpage
1573 $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagecontext->id));
1574 $frontpageblockcontext = context_block::instance($bi->id);
1575 $testblocks[] = $bi->id;
1577 // Add a resource to frontpage
1578 $page = $generator->create_module('page', array('course'=>$SITE->id));
1579 $testpages[] = $page->id;
1580 $frontpagepagecontext = context_module::instance($page->cmid);
1582 // Add block to frontpage resource
1583 $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagepagecontext->id));
1584 $frontpagepageblockcontext = context_block::instance($bi->id);
1585 $testblocks[] = $bi->id;
1587 // Some nested course categories with courses
1588 $manualenrol = enrol_get_plugin('manual');
1590 for($i=0; $i<5; $i++) {
1591 $cat = $generator->create_category(array('parent'=>$parentcat));
1592 $testcategories[] = $cat->id;
1593 $catcontext = context_coursecat::instance($cat->id);
1594 $parentcat = $cat->id;
1600 // Add resource to each category
1601 $bi = $generator->create_block('online_users', array('parentcontextid'=>$catcontext->id));
1602 context_block::instance($bi->id);
1604 // Add a few courses to each category
1605 for($j=0; $j<6; $j++) {
1606 $course = $generator->create_course(array('category'=>$cat->id));
1607 $testcourses[] = $course->id;
1608 $coursecontext = context_course::instance($course->id);
1613 // Add manual enrol instance
1614 $manualenrol->add_default_instance($DB->get_record('course', array('id'=>$course->id)));
1616 // Add block to each course
1617 $bi = $generator->create_block('online_users', array('parentcontextid'=>$coursecontext->id));
1618 $testblocks[] = $bi->id;
1620 // Add a resource to each course
1621 $page = $generator->create_module('page', array('course'=>$course->id));
1622 $testpages[] = $page->id;
1623 $modcontext = context_module::instance($page->cmid);
1625 // Add block to each module
1626 $bi = $generator->create_block('online_users', array('parentcontextid'=>$modcontext->id));
1627 $testblocks[] = $bi->id;
1631 // Make sure all contexts were created properly
1632 $count = 1; //system
1633 $count += $DB->count_records('user', array('deleted'=>0));
1634 $count += $DB->count_records('course_categories');
1635 $count += $DB->count_records('course');
1636 $count += $DB->count_records('course_modules');
1637 $count += $DB->count_records('block_instances');
1638 $this->assertEquals($DB->count_records('context'), $count);
1639 $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
1640 $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
1643 // ====== context_helper::get_level_name() ================================
1645 $levels = context_helper::get_all_levels();
1646 foreach ($levels as $level=>$classname) {
1647 $name = context_helper::get_level_name($level);
1648 $this->assertFalse(empty($name));
1652 // ======= context::instance_by_id(), context_xxx::instance();
1654 $context = context::instance_by_id($frontpagecontext->id);
1655 $this->assertSame($context->contextlevel, CONTEXT_COURSE);
1656 $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING));
1658 context::instance_by_id(-1);
1659 $this->fail('exception expected');
1660 } catch (Exception $e) {
1661 $this->assertTrue(true);
1663 $this->assertTrue(context_system::instance() instanceof context_system);
1664 $this->assertTrue(context_coursecat::instance($testcategories[0]) instanceof context_coursecat);
1665 $this->assertTrue(context_course::instance($testcourses[0]) instanceof context_course);
1666 $this->assertTrue(context_module::instance($testpages[0]) instanceof context_module);
1667 $this->assertTrue(context_block::instance($testblocks[0]) instanceof context_block);
1669 $this->assertFalse(context_coursecat::instance(-1, IGNORE_MISSING));
1670 $this->assertFalse(context_course::instance(-1, IGNORE_MISSING));
1671 $this->assertFalse(context_module::instance(-1, IGNORE_MISSING));
1672 $this->assertFalse(context_block::instance(-1, IGNORE_MISSING));
1674 context_coursecat::instance(-1);
1675 $this->fail('exception expected');
1676 } catch (Exception $e) {
1677 $this->assertTrue(true);
1680 context_course::instance(-1);
1681 $this->fail('exception expected');
1682 } catch (Exception $e) {
1683 $this->assertTrue(true);
1686 context_module::instance(-1);
1687 $this->fail('exception expected');
1688 } catch (Exception $e) {
1689 $this->assertTrue(true);
1692 context_block::instance(-1);
1693 $this->fail('exception expected');
1694 } catch (Exception $e) {
1695 $this->assertTrue(true);
1699 // ======= $context->get_url(), $context->get_context_name(), $context->get_capabilities() =========
1701 $testcontexts = array();
1702 $testcontexts[CONTEXT_SYSTEM] = context_system::instance();
1703 $testcontexts[CONTEXT_COURSECAT] = context_coursecat::instance($testcategories[0]);
1704 $testcontexts[CONTEXT_COURSE] = context_course::instance($testcourses[0]);
1705 $testcontexts[CONTEXT_MODULE] = context_module::instance($testpages[0]);
1706 $testcontexts[CONTEXT_BLOCK] = context_block::instance($testblocks[0]);
1708 foreach ($testcontexts as $context) {
1709 $name = $context->get_context_name(true, true);
1710 $this->assertFalse(empty($name));
1712 $this->assertTrue($context->get_url() instanceof moodle_url);
1714 $caps = $context->get_capabilities();
1715 $this->assertTrue(is_array($caps));
1716 foreach ($caps as $cap) {
1718 $this->assertSame(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask'));
1721 unset($testcontexts);
1723 // ===== $context->get_course_context() =========================================
1725 $this->assertFalse($systemcontext->get_course_context(false));
1727 $systemcontext->get_course_context();
1728 $this->fail('exception expected');
1729 } catch (Exception $e) {
1730 $this->assertTrue(true);
1732 $context = context_coursecat::instance($testcategories[0]);
1733 $this->assertFalse($context->get_course_context(false));
1735 $context->get_course_context();
1736 $this->fail('exception expected');
1737 } catch (Exception $e) {
1738 $this->assertTrue(true);
1740 $this->assertSame($frontpagecontext->get_course_context(true), $frontpagecontext);
1741 $this->assertSame($frontpagepagecontext->get_course_context(true), $frontpagecontext);
1742 $this->assertSame($frontpagepageblockcontext->get_course_context(true), $frontpagecontext);
1745 // ======= $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() =======
1747 $userid = reset($testusers);
1748 $usercontext = context_user::instance($userid);
1749 $this->assertSame($usercontext->get_parent_context(), $systemcontext);
1750 $this->assertSame($usercontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
1751 $this->assertSame($usercontext->get_parent_contexts(true), array($usercontext->id=>$usercontext, $systemcontext->id=>$systemcontext));
1753 $this->assertSame($systemcontext->get_parent_contexts(), array());
1754 $this->assertSame($systemcontext->get_parent_contexts(true), array($systemcontext->id=>$systemcontext));
1755 $this->assertSame($systemcontext->get_parent_context_ids(), array());
1756 $this->assertSame($systemcontext->get_parent_context_ids(true), array($systemcontext->id));
1758 $this->assertSame($frontpagecontext->get_parent_context(), $systemcontext);
1759 $this->assertSame($frontpagecontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
1760 $this->assertSame($frontpagecontext->get_parent_contexts(true), array($frontpagecontext->id=>$frontpagecontext, $systemcontext->id=>$systemcontext));
1761 $this->assertSame($frontpagecontext->get_parent_context_ids(), array($systemcontext->id));
1762 $this->assertEquals($frontpagecontext->get_parent_context_ids(true), array($frontpagecontext->id, $systemcontext->id));
1764 $this->assertSame($systemcontext->get_parent_context(), false);
1765 $frontpagecontext = context_course::instance($SITE->id);
1766 $parent = $systemcontext;
1767 foreach ($testcategories as $catid) {
1768 $catcontext = context_coursecat::instance($catid);
1769 $this->assertSame($catcontext->get_parent_context(), $parent);
1770 $parent = $catcontext;
1772 $this->assertSame($frontpagepagecontext->get_parent_context(), $frontpagecontext);
1773 $this->assertSame($frontpageblockcontext->get_parent_context(), $frontpagecontext);
1774 $this->assertSame($frontpagepageblockcontext->get_parent_context(), $frontpagepagecontext);
1777 // ====== $context->get_child_contexts() ================================
1779 $children = $systemcontext->get_child_contexts();
1780 $this->resetDebugging();
1781 $this->assertEquals(count($children)+1, $DB->count_records('context'));
1783 $context = context_coursecat::instance($testcategories[3]);
1784 $children = $context->get_child_contexts();
1788 foreach ($children as $child) {
1789 if ($child->contextlevel == CONTEXT_COURSECAT) {
1792 if ($child->contextlevel == CONTEXT_COURSE) {
1795 if ($child->contextlevel == CONTEXT_BLOCK) {
1799 $this->assertEquals(count($children), 8);
1800 $this->assertEquals($countcats, 1);
1801 $this->assertEquals($countcourses, 6);
1802 $this->assertEquals($countblocks, 1);
1804 $context = context_course::instance($testcourses[2]);
1805 $children = $context->get_child_contexts();
1806 $this->assertEquals(count($children), 7); // depends on number of default blocks
1808 $context = context_module::instance($testpages[3]);
1809 $children = $context->get_child_contexts();
1810 $this->assertEquals(count($children), 1);
1812 $context = context_block::instance($testblocks[1]);
1813 $children = $context->get_child_contexts();
1814 $this->assertEquals(count($children), 0);
1818 unset($countcourses);
1819 unset($countblocks);
1822 // ======= context_helper::reset_caches() ============================
1824 context_helper::reset_caches();
1825 $this->assertEquals(context_inspection::test_context_cache_size(), 0);
1826 context_course::instance($SITE->id);
1827 $this->assertEquals(context_inspection::test_context_cache_size(), 1);
1830 // ======= context preloading ========================================
1832 context_helper::reset_caches();
1833 $sql = "SELECT ".context_helper::get_preload_record_columns_sql('c')."
1835 WHERE c.contextlevel <> ".CONTEXT_SYSTEM;
1836 $records = $DB->get_records_sql($sql);
1837 $firstrecord = reset($records);
1838 $columns = context_helper::get_preload_record_columns('c');
1839 $firstrecord = (array)$firstrecord;
1840 $this->assertSame(array_keys($firstrecord), array_values($columns));
1841 context_helper::reset_caches();
1842 foreach ($records as $record) {
1843 context_helper::preload_from_record($record);
1844 $this->assertEquals($record, new stdClass());
1846 $this->assertEquals(context_inspection::test_context_cache_size(), count($records));
1850 context_helper::reset_caches();
1851 context_helper::preload_course($SITE->id);
1852 $numfrontpagemodules = $DB->count_records('course_modules', array('course' => $SITE->id));
1853 $this->assertEquals(6 + $numfrontpagemodules, context_inspection::test_context_cache_size()); // depends on number of default blocks
1855 // ====== assign_capability(), unassign_capability() ====================
1857 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1858 $this->assertFalse($rc);
1859 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext->id);
1860 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1861 $this->assertEquals($rc->permission, CAP_ALLOW);
1862 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext->id);
1863 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1864 $this->assertEquals($rc->permission, CAP_ALLOW);
1865 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext, true);
1866 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1867 $this->assertEquals($rc->permission, CAP_PREVENT);
1869 assign_capability('moodle/site:accessallgroups', CAP_INHERIT, $allroles['teacher'], $frontpagecontext);
1870 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1871 $this->assertFalse($rc);
1872 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext);
1873 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true);
1874 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1875 $this->assertFalse($rc);
1876 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true);
1879 accesslib_clear_all_caches(false); // must be done after assign_capability()
1882 // ======= role_assign(), role_unassign(), role_unassign_all() ==============
1884 $context = context_course::instance($testcourses[1]);
1885 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
1886 role_assign($allroles['teacher'], $testusers[1], $context->id);
1887 role_assign($allroles['teacher'], $testusers[2], $context->id);
1888 role_assign($allroles['manager'], $testusers[1], $context->id);
1889 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 3);
1890 role_unassign($allroles['teacher'], $testusers[1], $context->id);
1891 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 2);
1892 role_unassign_all(array('contextid'=>$context->id));
1893 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
1896 accesslib_clear_all_caches(false); // just in case
1899 // ====== has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends ========================
1901 $adminid = get_admin()->id;
1902 $guestid = $CFG->siteguest;
1904 // Enrol some users into some courses
1905 $course1 = $DB->get_record('course', array('id'=>$testcourses[22]), '*', MUST_EXIST);
1906 $course2 = $DB->get_record('course', array('id'=>$testcourses[7]), '*', MUST_EXIST);
1907 $cms = $DB->get_records('course_modules', array('course'=>$course1->id), 'id');
1909 $blocks = $DB->get_records('block_instances', array('parentcontextid'=>context_module::instance($cm1->id)->id), 'id');
1910 $block1 = reset($blocks);
1911 $instance1 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course1->id));
1912 $instance2 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course2->id));
1913 for($i=0; $i<9; $i++) {
1914 $manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']);
1916 $manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']);
1917 $manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']);
1919 for($i=10; $i<15; $i++) {
1920 $manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']);
1922 $manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']);
1924 // Add tons of role assignments - the more the better
1925 role_assign($allroles['coursecreator'], $testusers[11], context_coursecat::instance($testcategories[2]));
1926 role_assign($allroles['manager'], $testusers[12], context_coursecat::instance($testcategories[1]));
1927 role_assign($allroles['student'], $testusers[9], context_module::instance($cm1->id));
1928 role_assign($allroles['teacher'], $testusers[8], context_module::instance($cm1->id));
1929 role_assign($allroles['guest'], $testusers[13], context_course::instance($course1->id));
1930 role_assign($allroles['teacher'], $testusers[7], context_block::instance($block1->id));
1931 role_assign($allroles['manager'], $testusers[9], context_block::instance($block1->id));
1932 role_assign($allroles['editingteacher'], $testusers[9], context_course::instance($course1->id));
1934 role_assign($allroles['teacher'], $adminid, context_course::instance($course1->id));
1935 role_assign($allroles['editingteacher'], $adminid, context_block::instance($block1->id));
1937 // Add tons of overrides - the more the better
1938 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpageblockcontext, true);
1939 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpageblockcontext, true);
1940 assign_capability('moodle/block:view', CAP_PROHIBIT, $allroles['guest'], $frontpageblockcontext, true);
1941 assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['user'], $frontpageblockcontext, true);
1942 assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['student'], $frontpageblockcontext, true);
1944 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $CFG->defaultuserroleid, $frontpagepagecontext, true);
1945 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagepagecontext, true);
1946 assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $frontpagepagecontext, true);
1947 assign_capability('mod/page:view', CAP_ALLOW, $allroles['user'], $frontpagepagecontext, true);
1948 assign_capability('moodle/page:view', CAP_ALLOW, $allroles['student'], $frontpagepagecontext, true);
1950 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpagecontext, true);
1951 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext, true);
1952 assign_capability('mod/page:view', CAP_ALLOW, $allroles['guest'], $frontpagecontext, true);
1953 assign_capability('mod/page:view', CAP_PROHIBIT, $allroles['user'], $frontpagecontext, true);
1955 assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $systemcontext, true);
1957 accesslib_clear_all_caches(false); // must be done after assign_capability()
1959 // Extra tests for guests and not-logged-in users because they can not be verified by cross checking
1960 // with get_users_by_capability() where they are ignored
1961 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid));
1962 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid));
1963 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid));
1964 $this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid));
1966 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0));
1967 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0));
1968 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0));
1969 $this->assertFalse(has_capability('mod/page:view', $systemcontext, 0));
1971 $this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11]));
1972 $this->assertTrue(has_capability('moodle/course:create', context_coursecat::instance($testcategories[2]), $testusers[11]));
1973 $this->assertFalse(has_capability('moodle/course:create', context_course::instance($testcourses[1]), $testusers[11]));
1974 $this->assertTrue(has_capability('moodle/course:create', context_course::instance($testcourses[19]), $testusers[11]));
1976 $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[1]), $testusers[9]));
1977 $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[19]), $testusers[9]));
1978 $this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9]));
1980 // Test the list of enrolled users
1981 $coursecontext = context_course::instance($course1->id);
1982 $enrolled = get_enrolled_users($coursecontext);
1983 $this->assertEquals(count($enrolled), 10);
1984 for($i=0; $i<10; $i++) {
1985 $this->assertTrue(isset($enrolled[$testusers[$i]]));
1987 $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
1988 $this->assertEquals(count($enrolled), 1);
1989 $this->assertTrue(isset($enrolled[$testusers[9]]));
1993 $userid = $testusers[9];
1994 $USER = $DB->get_record('user', array('id'=>$userid));
1995 load_all_capabilities();
1996 $coursecontext = context_course::instance($course1->id);
1997 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
1998 $this->assertFalse(is_role_switched($course1->id));
1999 role_switch($allroles['student'], $coursecontext);
2000 $this->assertTrue(is_role_switched($course1->id));
2001 $this->assertEquals($USER->access['rsw'][$coursecontext->path], $allroles['student']);
2002 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
2003 reload_all_capabilities();
2004 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
2005 role_switch(0, $coursecontext);
2006 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
2008 $USER = $DB->get_record('user', array('id'=>$userid));
2009 load_all_capabilities();
2010 $coursecontext = context_course::instance($course1->id);
2011 $blockcontext = context_block::instance($block1->id);
2012 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
2013 role_switch($allroles['student'], $coursecontext);
2014 $this->assertEquals($USER->access['rsw'][$coursecontext->path], $allroles['student']);
2015 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
2016 reload_all_capabilities();
2017 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
2018 load_all_capabilities();
2019 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
2021 // temp course role for enrol
2022 $DB->delete_records('cache_flags', array()); // this prevents problem with dirty contexts immediately resetting the temp role - this is a known problem...
2023 $userid = $testusers[5];
2024 $roleid = $allroles['editingteacher'];
2025 $USER = $DB->get_record('user', array('id'=>$userid));
2026 load_all_capabilities();
2027 $coursecontext = context_course::instance($course1->id);
2028 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
2029 $this->assertFalse(isset($USER->access['ra'][$coursecontext->path][$roleid]));
2030 load_temp_course_role($coursecontext, $roleid);
2031 $this->assertEquals($USER->access['ra'][$coursecontext->path][$roleid], $roleid);
2032 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
2033 remove_temp_course_roles($coursecontext);
2034 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
2035 load_temp_course_role($coursecontext, $roleid);
2036 reload_all_capabilities();
2037 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
2038 $USER = new stdClass();
2041 // Now cross check has_capability() with get_users_by_capability(), each using different code paths,
2042 // they have to be kept in sync, usually only one of them breaks, so we know when something is wrong,
2043 // at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users)
2044 $contexts = $DB->get_records('context', array(), 'id');
2045 $contexts = array_values($contexts);
2046 $capabilities = $DB->get_records('capabilities', array(), 'id');
2047 $capabilities = array_values($capabilities);
2048 $roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']);
2049 $userids = array_values($testusers);
2050 $userids[] = get_admin()->id;
2052 if (!PHPUNIT_LONGTEST) {
2053 $contexts = array_slice($contexts, 0, 10);
2054 $capabilities = array_slice($capabilities, 0, 5);
2055 $userids = array_slice($userids, 0, 5);
2060 foreach($userids as $userid) { // no guest or deleted
2061 // each user gets 0-10 random roles
2062 $rcount = rand(0, 10);
2063 for($j=0; $j<$rcount; $j++) {
2064 $roleid = $roles[rand(0, count($roles)-1)];
2065 $contextid = $contexts[rand(0, count($contexts)-1)]->id;
2066 role_assign($roleid, $userid, $contextid);
2070 $permissions = array(CAP_ALLOW, CAP_PREVENT, CAP_INHERIT, CAP_PREVENT);
2071 $maxoverrides = count($contexts)*10;
2072 for($j=0; $j<$maxoverrides; $j++) {
2073 $roleid = $roles[rand(0, count($roles)-1)];
2074 $contextid = $contexts[rand(0, count($contexts)-1)]->id;
2075 $permission = $permissions[rand(0,count($permissions)-1)];
2076 $capname = $capabilities[rand(0, count($capabilities)-1)]->name;
2077 assign_capability($capname, $permission, $roleid, $contextid, true);
2079 unset($permissions);
2082 accesslib_clear_all_caches(false); // must be done after assign_capability()
2084 // Test time - let's set up some real user, just in case the logic for USER affects the others...
2085 $USER = $DB->get_record('user', array('id'=>$testusers[3]));
2086 load_all_capabilities();
2088 $userids[] = $CFG->siteguest;
2089 $userids[] = 0; // not-logged-in user
2090 $userids[] = -1; // non-existent user
2092 foreach ($contexts as $crecord) {
2093 $context = context::instance_by_id($crecord->id);
2094 if ($coursecontext = $context->get_course_context(false)) {
2095 $enrolled = get_enrolled_users($context);
2097 $enrolled = array();
2099 foreach ($capabilities as $cap) {
2100 $allowed = get_users_by_capability($context, $cap->name, 'u.id, u.username');
2102 $enrolledwithcap = get_enrolled_users($context, $cap->name);
2104 $enrolledwithcap = array();
2106 foreach ($userids as $userid) {
2107 if ($userid == 0 or isguestuser($userid)) {
2109 $CFG->forcelogin = true;
2110 $this->assertFalse(has_capability($cap->name, $context, $userid));
2111 unset($CFG->forcelogin);
2113 if (($cap->captype === 'write') or ($cap->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))) {
2114 $this->assertFalse(has_capability($cap->name, $context, $userid));
2116 $this->assertFalse(isset($allowed[$userid]));
2118 if (is_siteadmin($userid)) {
2119 $this->assertTrue(has_capability($cap->name, $context, $userid, true));
2121 $hascap = has_capability($cap->name, $context, $userid, false);
2122 $this->assertSame($hascap, isset($allowed[$userid]), "Capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
2123 if (isset($enrolled[$userid])) {
2124 $this->assertSame(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
2131 $USER = new stdClass();
2135 unset($capabilities);
2137 // Now let's do all the remaining tests that break our carefully prepared fake site
2141 // ======= $context->mark_dirty() =======================================
2143 $DB->delete_records('cache_flags', array());
2144 accesslib_clear_all_caches(false);
2145 $systemcontext->mark_dirty();
2146 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2147 $this->assertTrue(isset($dirty[$systemcontext->path]));
2148 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$systemcontext->path]));
2151 // ======= $context->reload_if_dirty(); =================================
2153 $DB->delete_records('cache_flags', array());
2154 accesslib_clear_all_caches(false);
2155 load_all_capabilities();
2156 $context = context_course::instance($testcourses[2]);
2157 $page = $DB->get_record('page', array('course'=>$testcourses[2]));
2158 $pagecm = get_coursemodule_from_instance('page', $page->id);
2159 $pagecontext = context_module::instance($pagecm->id);
2161 $context->mark_dirty();
2162 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
2163 $USER->access['test'] = true;
2164 $context->reload_if_dirty();
2165 $this->assertFalse(isset($USER->access['test']));
2167 $context->mark_dirty();
2168 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
2169 $USER->access['test'] = true;
2170 $pagecontext->reload_if_dirty();
2171 $this->assertFalse(isset($USER->access['test']));
2174 // ======= context_helper::build_all_paths() ============================
2176 $oldcontexts = $DB->get_records('context', array(), 'id');
2177 $DB->set_field_select('context', 'path', NULL, "contextlevel <> ".CONTEXT_SYSTEM);
2178 $DB->set_field_select('context', 'depth', 0, "contextlevel <> ".CONTEXT_SYSTEM);
2179 context_helper::build_all_paths();
2180 $newcontexts = $DB->get_records('context', array(), 'id');
2181 $this->assertEquals($oldcontexts, $newcontexts);
2182 unset($oldcontexts);
2183 unset($newcontexts);
2186 // ======= $context->reset_paths() ======================================
2188 $context = context_course::instance($testcourses[2]);
2189 $children = $context->get_child_contexts();
2190 $context->reset_paths(false);
2191 $this->assertSame($DB->get_field('context', 'path', array('id'=>$context->id)), NULL);
2192 $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), 0);
2193 foreach ($children as $child) {
2194 $this->assertSame($DB->get_field('context', 'path', array('id'=>$child->id)), NULL);
2195 $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$child->id)), 0);
2197 $this->assertEquals(count($children)+1, $DB->count_records('context', array('depth'=>0)));
2198 $this->assertEquals(count($children)+1, $DB->count_records('context', array('path'=>NULL)));
2200 $context = context_course::instance($testcourses[2]);
2201 $context->reset_paths(true);
2202 $context = context_course::instance($testcourses[2]);
2203 $this->assertEquals($DB->get_field('context', 'path', array('id'=>$context->id)), $context->path);
2204 $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), $context->depth);
2205 $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
2206 $this->assertEquals(0, $DB->count_records('context', array('path'=>NULL)));
2209 // ====== $context->update_moved(); ======================================
2211 accesslib_clear_all_caches(false);
2212 $DB->delete_records('cache_flags', array());
2213 $course = $DB->get_record('course', array('id'=>$testcourses[0]));
2214 $context = context_course::instance($course->id);
2215 $oldpath = $context->path;
2216 $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
2217 $categorycontext = context_coursecat::instance($miscid);
2218 $course->category = $miscid;
2219 $DB->update_record('course', $course);
2220 $context->update_moved($categorycontext);
2222 $context = context_course::instance($course->id);
2223 $this->assertEquals($context->get_parent_context(), $categorycontext);
2224 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2225 $this->assertTrue(isset($dirty[$oldpath]));
2226 $this->assertTrue(isset($dirty[$context->path]));
2229 // ====== $context->delete_content() =====================================
2231 context_helper::reset_caches();
2232 $context = context_module::instance($testpages[3]);
2233 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
2234 $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2235 $context->delete_content();
2236 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
2237 $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2240 // ====== $context->delete() =============================
2242 context_helper::reset_caches();
2243 $context = context_module::instance($testpages[4]);
2244 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
2245 $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2246 $bi = $DB->get_record('block_instances', array('parentcontextid'=>$context->id));
2247 $bicontext = context_block::instance($bi->id);
2248 $DB->delete_records('cache_flags', array());
2249 $context->delete(); // should delete also linked blocks
2250 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2251 $this->assertTrue(isset($dirty[$context->path]));
2252 $this->assertFalse($DB->record_exists('context', array('id'=>$context->id)));
2253 $this->assertFalse($DB->record_exists('context', array('id'=>$bicontext->id)));
2254 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_MODULE, 'instanceid'=>$testpages[4])));
2255 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK, 'instanceid'=>$bi->id)));
2256 $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2257 context_module::instance($testpages[4]);
2260 // ====== context_helper::delete_instance() =============================
2262 context_helper::reset_caches();
2263 $lastcourse = array_pop($testcourses);
2264 $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
2265 $coursecontext = context_course::instance($lastcourse);
2266 $this->assertEquals(context_inspection::test_context_cache_size(), 1);
2267 $this->assertFalse($coursecontext->instanceid == CONTEXT_COURSE);
2268 $DB->delete_records('cache_flags', array());
2269 context_helper::delete_instance(CONTEXT_COURSE, $lastcourse);
2270 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2271 $this->assertTrue(isset($dirty[$coursecontext->path]));
2272 $this->assertEquals(context_inspection::test_context_cache_size(), 0);
2273 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
2274 context_course::instance($lastcourse);
2277 // ======= context_helper::create_instances() ==========================
2279 $prevcount = $DB->count_records('context');
2280 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
2281 context_helper::create_instances(null, true);
2282 $this->assertSame($DB->count_records('context'), $prevcount);
2283 $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
2284 $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
2286 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
2287 $DB->delete_records('block_instances', array());
2288 $prevcount = $DB->count_records('context');
2289 $DB->delete_records_select('context', 'contextlevel <> '.CONTEXT_SYSTEM);
2290 context_helper::create_instances(null, true);
2291 $this->assertSame($DB->count_records('context'), $prevcount);
2292 $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
2293 $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
2296 // ======= context_helper::cleanup_instances() ==========================
2298 $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
2299 $DB->delete_records('course', array('id'=>$lastcourse));
2300 $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
2301 $DB->delete_records('course_categories', array('id'=>$lastcategory));
2302 $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
2303 $DB->delete_records('user', array('id'=>$lastuser));
2304 $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
2305 $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
2306 context_helper::cleanup_instances();
2307 $count = 1; //system
2308 $count += $DB->count_records('user', array('deleted'=>0));
2309 $count += $DB->count_records('course_categories');
2310 $count += $DB->count_records('course');
2311 $count += $DB->count_records('course_modules');
2312 $count += $DB->count_records('block_instances');
2313 $this->assertEquals($DB->count_records('context'), $count);
2316 // ======= context cache size restrictions ==============================
2318 $testusers= array();
2319 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
2320 $user = $generator->create_user();
2321 $testusers[$i] = $user->id;
2323 context_helper::create_instances(null, true);
2324 context_helper::reset_caches();
2325 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
2326 context_user::instance($testusers[$i]);
2327 if ($i == CONTEXT_CACHE_MAX_SIZE - 1) {
2328 $this->assertEquals(context_inspection::test_context_cache_size(), CONTEXT_CACHE_MAX_SIZE);
2329 } else if ($i == CONTEXT_CACHE_MAX_SIZE) {
2330 // once the limit is reached roughly 1/3 of records should be removed from cache
2331 $this->assertEquals(context_inspection::test_context_cache_size(), (int)(CONTEXT_CACHE_MAX_SIZE * (2/3) +102));
2334 // We keep the first 100 cached
2335 $prevsize = context_inspection::test_context_cache_size();
2336 for ($i=0; $i<100; $i++) {
2337 context_user::instance($testusers[$i]);
2338 $this->assertEquals(context_inspection::test_context_cache_size(), $prevsize);
2340 context_user::instance($testusers[102]);
2341 $this->assertEquals(context_inspection::test_context_cache_size(), $prevsize+1);
2346 // =================================================================
2347 // ======= basic test of legacy functions ==========================
2348 // =================================================================
2349 // note: watch out, the fake site might be pretty borked already
2351 $this->assertSame(get_system_context(), context_system::instance());
2353 foreach ($DB->get_records('context') as $contextid=>$record) {
2354 $context = context::instance_by_id($contextid);
2355 $this->assertSame(get_context_instance_by_id($contextid, IGNORE_MISSING), $context);
2356 $this->assertSame(get_context_instance($record->contextlevel, $record->instanceid), $context);
2357 $this->assertSame(get_parent_contexts($context), $context->get_parent_context_ids());
2358 if ($context->id == SYSCONTEXTID) {
2359 $this->assertSame(get_parent_contextid($context), false);
2361 $this->assertSame(get_parent_contextid($context), $context->get_parent_context()->id);
2365 $children = get_child_contexts($systemcontext);
2366 // Using assertEquals here as assertSame fails for some reason...
2367 $this->assertEquals($children, $systemcontext->get_child_contexts());
2368 $this->assertEquals(count($children), $DB->count_records('context')-1);
2369 $this->resetDebugging();
2372 // Make sure a debugging is thrown.
2373 get_context_instance($record->contextlevel, $record->instanceid);
2374 $this->assertDebuggingCalled('get_context_instance() is deprecated, please use context_xxxx::instance() instead.', DEBUG_DEVELOPER);
2375 get_context_instance_by_id($record->id);
2376 $this->assertDebuggingCalled('get_context_instance_by_id() is deprecated, please use context::instance_by_id($id) instead.', DEBUG_DEVELOPER);
2377 get_system_context();
2378 $this->assertDebuggingCalled('get_system_context() is deprecated, please use context_system::instance() instead.', DEBUG_DEVELOPER);
2379 get_parent_contexts($context);
2380 $this->assertDebuggingCalled('get_parent_contexts() is deprecated, please use $context->get_parent_context_ids() instead.', DEBUG_DEVELOPER);
2381 get_parent_contextid($context);
2382 $this->assertDebuggingCalled('get_parent_contextid() is deprecated, please use $context->get_parent_context() instead.', DEBUG_DEVELOPER);
2383 get_child_contexts($frontpagecontext);
2384 $this->assertDebuggingCalled('get_child_contexts() is deprecated, please use $context->get_child_contexts() instead.', DEBUG_DEVELOPER);
2386 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
2388 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK)));
2390 $DB->set_field('context', 'depth', 0, array('contextlevel'=>CONTEXT_BLOCK));
2391 build_context_path();
2392 $this->assertFalse($DB->record_exists('context', array('depth'=>0)));
2394 $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
2395 $DB->delete_records('course', array('id'=>$lastcourse));
2396 $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
2397 $DB->delete_records('course_categories', array('id'=>$lastcategory));
2398 $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
2399 $DB->delete_records('user', array('id'=>$lastuser));
2400 $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
2401 $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
2403 $count = 1; //system
2404 $count += $DB->count_records('user', array('deleted'=>0));
2405 $count += $DB->count_records('course_categories');
2406 $count += $DB->count_records('course');
2407 $count += $DB->count_records('course_modules');
2408 $count += $DB->count_records('block_instances');
2409 $this->assertEquals($DB->count_records('context'), $count);
2411 context_helper::reset_caches();
2412 preload_course_contexts($SITE->id);
2413 $this->assertEquals(1 + $DB->count_records('course_modules', array('course' => $SITE->id)),
2414 context_inspection::test_context_cache_size());
2416 context_helper::reset_caches();
2417 list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx');
2418 $sql = "SELECT c.id $select FROM {course_categories} c $join";
2419 $records = $DB->get_records_sql($sql);
2420 foreach ($records as $record) {
2421 context_instance_preload($record);
2422 $record = (array)$record;
2423 $this->assertEquals(1, count($record)); // only id left
2425 $this->assertEquals(count($records), context_inspection::test_context_cache_size());
2427 accesslib_clear_all_caches(true);
2428 $DB->delete_records('cache_flags', array());
2429 mark_context_dirty($systemcontext->path);
2430 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2431 $this->assertTrue(isset($dirty[$systemcontext->path]));
2433 accesslib_clear_all_caches(false);
2434 $DB->delete_records('cache_flags', array());
2435 $course = $DB->get_record('course', array('id'=>$testcourses[2]));
2436 $context = context_course::instance($course->id);
2437 $oldpath = $context->path;
2438 $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
2439 $categorycontext = context_coursecat::instance($miscid);
2440 $course->category = $miscid;
2441 $DB->update_record('course', $course);
2442 context_moved($context, $categorycontext);
2443 $context = context_course::instance($course->id);
2444 $this->assertEquals($context->get_parent_context(), $categorycontext);
2446 $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
2447 delete_context(CONTEXT_COURSE, $testcourses[2]);
2448 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
2450 $name = get_contextlevel_name(CONTEXT_COURSE);
2451 $this->assertFalse(empty($name));
2453 $context = context_course::instance($testcourses[2]);
2454 $name = print_context_name($context);
2455 $this->assertFalse(empty($name));
2457 $url = get_context_url($coursecontext);
2458 $this->assertFalse($url instanceof modole_url);
2460 $pagecm = get_coursemodule_from_instance('page', $testpages[7]);
2461 $context = context_module::instance($pagecm->id);
2462 $coursecontext = get_course_context($context);
2463 $this->assertEquals($coursecontext->contextlevel, CONTEXT_COURSE);
2464 $this->assertEquals(get_courseid_from_context($context), $pagecm->course);
2466 $caps = fetch_context_capabilities($systemcontext);
2467 $this->assertTrue(is_array($caps));
2472 * Test updating of role capabilities during upgrade
2475 public function test_update_capabilities() {
2478 $this->resetAfterTest(true);
2480 $froncontext = context_course::instance($SITE->id);
2481 $student = $DB->get_record('role', array('archetype'=>'student'));
2482 $teacher = $DB->get_record('role', array('archetype'=>'teacher'));
2484 $existingcaps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
2486 $this->assertFalse(isset($existingcaps['moodle/site:restore'])); // moved to new 'moodle/restore:restorecourse'
2487 $this->assertTrue(isset($existingcaps['moodle/restore:restorecourse'])); // new cap from 'moodle/site:restore'
2488 $this->assertTrue(isset($existingcaps['moodle/site:sendmessage'])); // new capability
2489 $this->assertTrue(isset($existingcaps['moodle/backup:backupcourse']));
2490 $this->assertTrue(isset($existingcaps['moodle/backup:backupsection'])); // cloned from 'moodle/backup:backupcourse'
2491 $this->assertTrue(isset($existingcaps['moodle/site:approvecourse'])); // updated bitmask
2492 $this->assertTrue(isset($existingcaps['moodle/course:manageactivities']));
2493 $this->assertTrue(isset($existingcaps['mod/page:addinstance'])); // cloned from core 'moodle/course:manageactivities'
2495 // fake state before upgrade
2496 $DB->set_field('capabilities', 'name', 'moodle/site:restore', array('name'=>'moodle/restore:restorecourse'));
2497 $DB->set_field('role_capabilities', 'capability', 'moodle/site:restore', array('capability'=>'moodle/restore:restorecourse'));
2498 assign_capability('moodle/site:restore', CAP_PROHIBIT, $teacher->id, $froncontext->id, true);
2499 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/site:restore', 'roleid'=>$teacher->id), 'contextid, permission', 'contextid, permission'));
2501 $DB->delete_records('role_capabilities', array('capability'=>'moodle/site:sendmessage'));
2502 $DB->delete_records('capabilities', array('name'=>'moodle/site:sendmessage'));
2504 $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupsection'));
2505 $DB->delete_records('capabilities', array('name'=>'moodle/backup:backupsection'));
2506 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $froncontext->id, true);
2507 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $teacher->id, $froncontext->id, true);
2509 $DB->set_field('capabilities', 'riskbitmask', 0, array('name'=>'moodle/site:approvecourse'));
2511 $DB->delete_records('role_capabilities', array('capability'=>'mod/page:addinstance'));
2512 $DB->delete_records('capabilities', array('name'=>'mod/page:addinstance'));
2513 assign_capability('moodle/course:manageactivities', CAP_PROHIBIT, $student->id, $froncontext->id, true);
2514 assign_capability('moodle/course:manageactivities', CAP_ALLOW, $teacher->id, $froncontext->id, true);
2517 update_capabilities('moodle');
2519 // only core should be upgraded
2520 $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
2522 $this->assertFalse(isset($existingcaps['moodle/site:restore']));
2523 $this->assertTrue(isset($caps['moodle/restore:restorecourse']));
2524 $this->assertEquals($existingcaps['moodle/restore:restorecourse'], $caps['moodle/restore:restorecourse']);
2525 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/restore:restorecourse', 'roleid'=>$teacher->id), 'contextid, permission', 'contextid, permission'));
2526 $this->assertEquals($perms1, $perms2);
2528 $this->assertTrue(isset($caps['moodle/site:sendmessage']));
2529 $this->assertEquals($existingcaps['moodle/site:sendmessage'], $caps['moodle/site:sendmessage']);
2531 $this->assertTrue(isset($caps['moodle/backup:backupsection']));
2532 $this->assertEquals($existingcaps['moodle/backup:backupsection'], $caps['moodle/backup:backupsection']);
2533 $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/backup:backupcourse', 'moodle/backup:backupsection'));
2534 foreach ($roles as $role) {
2535 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2536 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupsection', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2537 $this->assertEquals($perms1, $perms2);
2540 $this->assertTrue(isset($caps['moodle/site:approvecourse']));
2541 $this->assertEquals($existingcaps['moodle/site:approvecourse'], $caps['moodle/site:approvecourse']);
2543 $this->assertFalse(isset($caps['mod/page:addinstance']));
2546 update_capabilities('mod_page');
2547 $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
2548 $this->assertTrue(isset($caps['mod/page:addinstance']));
2549 $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/course:manageactivities', 'mod/page:addinstance'));
2550 foreach ($roles as $role) {
2551 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/course:manageactivities', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2552 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'mod/page:addinstance', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2554 $this->assertEquals($perms1, $perms2);