Merge branch 'wip-MDL-62796-master' of git://github.com/marinaglancy/moodle
[moodle.git] / lib / tests / accesslib_test.php
blob3ff61927e08c0957d24fdd3b737ca065b158087e
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
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/>.
17 /**
18 * Full functional accesslib test.
20 * @package core
21 * @category phpunit
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();
29 /**
30 * Functional test for accesslib.php
32 * Note: execution may take many minutes especially on slower servers.
34 class core_accesslib_testcase extends advanced_testcase {
35 /**
36 * Verify comparison of context instances in phpunit asserts.
38 public function test_context_comparisons() {
39 $frontpagecontext1 = context_course::instance(SITEID);
40 context_helper::reset_caches();
41 $frontpagecontext2 = context_course::instance(SITEID);
42 $this->assertEquals($frontpagecontext1, $frontpagecontext2);
44 $user1 = context_user::instance(1);
45 $user2 = context_user::instance(2);
46 $this->assertNotEquals($user1, $user2);
49 /**
50 * Test resetting works.
52 public function test_accesslib_clear_all_caches() {
53 global $ACCESSLIB_PRIVATE;
55 $this->resetAfterTest();
57 $this->setAdminUser();
58 load_all_capabilities();
60 $this->assertNotEmpty($ACCESSLIB_PRIVATE->accessdatabyuser);
61 accesslib_clear_all_caches_for_unit_testing();
62 $this->assertEmpty($ACCESSLIB_PRIVATE->dirtycontexts);
63 $this->assertEmpty($ACCESSLIB_PRIVATE->accessdatabyuser);
66 /**
67 * Check modifying capability record is not exposed to other code.
69 public function test_capabilities_mutation() {
70 $oldcap = get_capability_info('moodle/site:config');
71 $cap = get_capability_info('moodle/site:config');
72 unset($cap->name);
73 $newcap = get_capability_info('moodle/site:config');
75 $this->assertFalse(isset($cap->name));
76 $this->assertTrue(isset($newcap->name));
77 $this->assertTrue(isset($oldcap->name));
80 /**
81 * Test getting of role access
83 public function test_get_role_access() {
84 global $DB;
86 $roles = $DB->get_records('role');
87 foreach ($roles as $role) {
88 $access = get_role_access($role->id);
90 $this->assertTrue(is_array($access));
91 $this->assertTrue(is_array($access['ra']));
92 $this->assertFalse(isset($access['rdef']));
93 $this->assertFalse(isset($access['rdef_count']));
94 $this->assertFalse(isset($access['loaded']));
95 $this->assertTrue(isset($access['time']));
96 $this->assertTrue(is_array($access['rsw']));
99 // Note: the data is validated in the functional permission evaluation test at the end of this testcase.
103 * Test getting of guest role.
105 public function test_get_guest_role() {
106 global $CFG;
108 $guest = get_guest_role();
109 $this->assertEquals('guest', $guest->archetype);
110 $this->assertEquals('guest', $guest->shortname);
112 $this->assertEquals($CFG->guestroleid, $guest->id);
116 * Test if user is admin.
118 public function test_is_siteadmin() {
119 global $DB, $CFG;
121 $this->resetAfterTest();
123 $users = $DB->get_records('user');
125 foreach ($users as $user) {
126 $this->setUser(0);
127 if ($user->username === 'admin') {
128 $this->assertTrue(is_siteadmin($user));
129 $this->assertTrue(is_siteadmin($user->id));
130 $this->setUser($user);
131 $this->assertTrue(is_siteadmin());
132 $this->assertTrue(is_siteadmin(null));
133 } else {
134 $this->assertFalse(is_siteadmin($user));
135 $this->assertFalse(is_siteadmin($user->id));
136 $this->setUser($user);
137 $this->assertFalse(is_siteadmin());
138 $this->assertFalse(is_siteadmin(null));
142 // Change the site admin list and check that it still works with
143 // multiple admins. We do this with userids only (not real user
144 // accounts) because it makes the test simpler.
145 $before = $CFG->siteadmins;
146 set_config('siteadmins', '666,667,668');
147 $this->assertTrue(is_siteadmin(666));
148 $this->assertTrue(is_siteadmin(667));
149 $this->assertTrue(is_siteadmin(668));
150 $this->assertFalse(is_siteadmin(669));
151 set_config('siteadmins', '13');
152 $this->assertTrue(is_siteadmin(13));
153 $this->assertFalse(is_siteadmin(666));
154 set_config('siteadmins', $before);
158 * Test if user is enrolled in a course
160 public function test_is_enrolled() {
161 global $DB;
163 $this->resetAfterTest();
165 // Generate data.
166 $user = $this->getDataGenerator()->create_user();
167 $course = $this->getDataGenerator()->create_course();
168 $coursecontext = context_course::instance($course->id);
169 $role = $DB->get_record('role', array('shortname'=>'student'));
171 // There should be a manual enrolment as part of the default install.
172 $plugin = enrol_get_plugin('manual');
173 $instance = $DB->get_record('enrol', array(
174 'courseid' => $course->id,
175 'enrol' => 'manual',
177 $this->assertNotSame(false, $instance);
179 // Enrol the user in the course.
180 $plugin->enrol_user($instance, $user->id, $role->id);
182 // We'll test with the mod/assign:submit capability.
183 $capability= 'mod/assign:submit';
184 $this->assertTrue($DB->record_exists('capabilities', array('name' => $capability)));
186 // Switch to our user.
187 $this->setUser($user);
189 // Ensure that the user has the capability first.
190 $this->assertTrue(has_capability($capability, $coursecontext, $user->id));
192 // We first test whether the user is enrolled on the course as this
193 // seeds the cache, then we test for the capability.
194 $this->assertTrue(is_enrolled($coursecontext, $user, '', true));
195 $this->assertTrue(is_enrolled($coursecontext, $user, $capability));
197 // Prevent the capability for this user role.
198 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
199 $coursecontext->mark_dirty();
200 $this->assertFalse(has_capability($capability, $coursecontext, $user->id));
202 // Again, we seed the cache first by checking initial enrolment,
203 // and then we test the actual capability.
204 $this->assertTrue(is_enrolled($coursecontext, $user, '', true));
205 $this->assertFalse(is_enrolled($coursecontext, $user, $capability));
209 * Test logged in test.
211 public function test_isloggedin() {
212 global $USER;
214 $this->resetAfterTest();
216 $USER->id = 0;
217 $this->assertFalse(isloggedin());
218 $USER->id = 1;
219 $this->assertTrue(isloggedin());
223 * Test guest user test.
225 public function test_isguestuser() {
226 global $DB;
228 $this->resetAfterTest();
230 $guest = $DB->get_record('user', array('username'=>'guest'));
231 $this->setUser(0);
232 $this->assertFalse(isguestuser());
233 $this->setAdminUser();
234 $this->assertFalse(isguestuser());
235 $this->assertTrue(isguestuser($guest));
236 $this->assertTrue(isguestuser($guest->id));
237 $this->setUser($guest);
238 $this->assertTrue(isguestuser());
240 $users = $DB->get_records('user');
241 foreach ($users as $user) {
242 if ($user->username === 'guest') {
243 continue;
245 $this->assertFalse(isguestuser($user));
250 * Test capability riskiness.
252 public function test_is_safe_capability() {
253 global $DB;
254 // Note: there is not much to test, just make sure no notices are throw for the most dangerous cap.
255 $capability = $DB->get_record('capabilities', array('name'=>'moodle/site:config'), '*', MUST_EXIST);
256 $this->assertFalse(is_safe_capability($capability));
260 * Test context fetching.
262 public function test_get_context_info_array() {
263 $this->resetAfterTest();
265 $syscontext = context_system::instance();
266 $user = $this->getDataGenerator()->create_user();
267 $usercontext = context_user::instance($user->id);
268 $course = $this->getDataGenerator()->create_course();
269 $catcontext = context_coursecat::instance($course->category);
270 $coursecontext = context_course::instance($course->id);
271 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
272 $modcontext = context_module::instance($page->cmid);
273 $cm = get_coursemodule_from_instance('page', $page->id);
274 $block1 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$coursecontext->id));
275 $block1context = context_block::instance($block1->id);
276 $block2 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$modcontext->id));
277 $block2context = context_block::instance($block2->id);
279 $result = get_context_info_array($syscontext->id);
280 $this->assertCount(3, $result);
281 $this->assertEquals($syscontext, $result[0]);
282 $this->assertNull($result[1]);
283 $this->assertNull($result[2]);
285 $result = get_context_info_array($usercontext->id);
286 $this->assertCount(3, $result);
287 $this->assertEquals($usercontext, $result[0]);
288 $this->assertNull($result[1]);
289 $this->assertNull($result[2]);
291 $result = get_context_info_array($catcontext->id);
292 $this->assertCount(3, $result);
293 $this->assertEquals($catcontext, $result[0]);
294 $this->assertNull($result[1]);
295 $this->assertNull($result[2]);
297 $result = get_context_info_array($coursecontext->id);
298 $this->assertCount(3, $result);
299 $this->assertEquals($coursecontext, $result[0]);
300 $this->assertEquals($course->id, $result[1]->id);
301 $this->assertSame($course->shortname, $result[1]->shortname);
302 $this->assertNull($result[2]);
304 $result = get_context_info_array($block1context->id);
305 $this->assertCount(3, $result);
306 $this->assertEquals($block1context, $result[0]);
307 $this->assertEquals($course->id, $result[1]->id);
308 $this->assertEquals($course->shortname, $result[1]->shortname);
309 $this->assertNull($result[2]);
311 $result = get_context_info_array($modcontext->id);
312 $this->assertCount(3, $result);
313 $this->assertEquals($modcontext, $result[0]);
314 $this->assertEquals($course->id, $result[1]->id);
315 $this->assertSame($course->shortname, $result[1]->shortname);
316 $this->assertEquals($cm->id, $result[2]->id);
318 $result = get_context_info_array($block2context->id);
319 $this->assertCount(3, $result);
320 $this->assertEquals($block2context, $result[0]);
321 $this->assertEquals($course->id, $result[1]->id);
322 $this->assertSame($course->shortname, $result[1]->shortname);
323 $this->assertEquals($cm->id, $result[2]->id);
327 * Test looking for course contacts.
329 public function test_has_coursecontact_role() {
330 global $DB, $CFG;
332 $this->resetAfterTest();
334 $users = $DB->get_records('user');
336 // Nobody is expected to have any course level roles.
337 $this->assertNotEmpty($CFG->coursecontact);
338 foreach ($users as $user) {
339 $this->assertFalse(has_coursecontact_role($user->id));
342 $user = $this->getDataGenerator()->create_user();
343 $course = $this->getDataGenerator()->create_course();
344 role_assign($CFG->coursecontact, $user->id, context_course::instance($course->id));
345 $this->assertTrue(has_coursecontact_role($user->id));
349 * Test creation of roles.
351 public function test_create_role() {
352 global $DB;
354 $this->resetAfterTest();
356 $id = create_role('New student role', 'student2', 'New student description', 'student');
357 $role = $DB->get_record('role', array('id'=>$id));
359 $this->assertNotEmpty($role);
360 $this->assertSame('New student role', $role->name);
361 $this->assertSame('student2', $role->shortname);
362 $this->assertSame('New student description', $role->description);
363 $this->assertSame('student', $role->archetype);
367 * Test adding of capabilities to roles.
369 public function test_assign_capability() {
370 global $DB;
372 $this->resetAfterTest();
374 $user = $this->getDataGenerator()->create_user();
375 $syscontext = context_system::instance();
376 $frontcontext = context_course::instance(SITEID);
377 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
378 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // Any capability assigned to student by default.
379 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')));
380 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')));
382 $this->setUser($user);
383 $result = assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $frontcontext->id);
384 $this->assertTrue($result);
385 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
386 $this->assertNotEmpty($permission);
387 $this->assertEquals(CAP_ALLOW, $permission->permission);
388 $this->assertEquals($user->id, $permission->modifierid);
390 $this->setUser(0);
391 $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $frontcontext->id, false);
392 $this->assertTrue($result);
393 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
394 $this->assertNotEmpty($permission);
395 $this->assertEquals(CAP_ALLOW, $permission->permission);
396 $this->assertEquals($user->id, $permission->modifierid);
398 $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $frontcontext->id, true);
399 $this->assertTrue($result);
400 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
401 $this->assertNotEmpty($permission);
402 $this->assertEquals(CAP_PROHIBIT, $permission->permission);
403 $this->assertEquals(0, $permission->modifierid);
405 $result = assign_capability('moodle/backup:backupcourse', CAP_INHERIT, $student->id, $frontcontext->id);
406 $this->assertTrue($result);
407 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
408 $this->assertEmpty($permission);
410 // Test event trigger.
411 $rolecapabilityevent = \core\event\role_capabilities_updated::create(array('context' => $syscontext,
412 'objectid' => $student->id,
413 'other' => array('name' => $student->shortname)
415 $expectedlegacylog = array(SITEID, 'role', 'view', 'admin/roles/define.php?action=view&roleid=' . $student->id,
416 $student->shortname, '', $user->id);
417 $rolecapabilityevent->set_legacy_logdata($expectedlegacylog);
418 $rolecapabilityevent->add_record_snapshot('role', $student);
420 $sink = $this->redirectEvents();
421 $rolecapabilityevent->trigger();
422 $events = $sink->get_events();
423 $sink->close();
424 $event = array_pop($events);
426 $this->assertInstanceOf('\core\event\role_capabilities_updated', $event);
427 $expectedurl = new moodle_url('/admin/roles/define.php', array('action' => 'view', 'roleid' => $student->id));
428 $this->assertEquals($expectedurl, $event->get_url());
429 $this->assertEventLegacyLogData($expectedlegacylog, $event);
430 $this->assertEventContextNotUsed($event);
434 * Test removing of capabilities from roles.
436 public function test_unassign_capability() {
437 global $DB;
439 $this->resetAfterTest();
441 $syscontext = context_system::instance();
442 $frontcontext = context_course::instance(SITEID);
443 $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
444 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // Any capability assigned to manager by default.
445 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $frontcontext->id);
447 $this->assertTrue($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')));
450 $result = unassign_capability('moodle/backup:backupcourse', $manager->id, $syscontext->id);
451 $this->assertTrue($result);
452 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
453 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
454 unassign_capability('moodle/backup:backupcourse', $manager->id, $frontcontext);
455 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
457 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $syscontext->id);
458 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $frontcontext->id);
459 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
461 $result = unassign_capability('moodle/backup:backupcourse', $manager->id);
462 $this->assertTrue($result);
463 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
464 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
468 * Test role assigning.
470 public function test_role_assign() {
471 global $DB, $USER;
473 $this->resetAfterTest();
475 $user = $this->getDataGenerator()->create_user();
476 $course = $this->getDataGenerator()->create_course();
477 $role = $DB->get_record('role', array('shortname'=>'student'));
479 $this->setUser(0);
480 $context = context_system::instance();
481 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
482 role_assign($role->id, $user->id, $context->id);
483 $ras = $DB->get_record('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id));
484 $this->assertNotEmpty($ras);
485 $this->assertSame('', $ras->component);
486 $this->assertSame('0', $ras->itemid);
487 $this->assertEquals($USER->id, $ras->modifierid);
489 $this->setAdminUser();
490 $context = context_course::instance($course->id);
491 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
492 role_assign($role->id, $user->id, $context->id, 'enrol_self', 1, 666);
493 $ras = $DB->get_record('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id));
494 $this->assertNotEmpty($ras);
495 $this->assertSame('enrol_self', $ras->component);
496 $this->assertSame('1', $ras->itemid);
497 $this->assertEquals($USER->id, $ras->modifierid);
498 $this->assertEquals(666, $ras->timemodified);
500 // Test event triggered.
502 $user2 = $this->getDataGenerator()->create_user();
503 $sink = $this->redirectEvents();
504 $raid = role_assign($role->id, $user2->id, $context->id);
505 $events = $sink->get_events();
506 $sink->close();
507 $this->assertCount(1, $events);
508 $event = $events[0];
509 $this->assertInstanceOf('\core\event\role_assigned', $event);
510 $this->assertSame('role', $event->target);
511 $this->assertSame('role', $event->objecttable);
512 $this->assertEquals($role->id, $event->objectid);
513 $this->assertEquals($context->id, $event->contextid);
514 $this->assertEquals($user2->id, $event->relateduserid);
515 $this->assertCount(3, $event->other);
516 $this->assertEquals($raid, $event->other['id']);
517 $this->assertSame('', $event->other['component']);
518 $this->assertEquals(0, $event->other['itemid']);
519 $this->assertInstanceOf('moodle_url', $event->get_url());
520 $this->assertSame('role_assigned', $event::get_legacy_eventname());
521 $roles = get_all_roles();
522 $rolenames = role_fix_names($roles, $context, ROLENAME_ORIGINAL, true);
523 $expectedlegacylog = array($course->id, 'role', 'assign',
524 'admin/roles/assign.php?contextid='.$context->id.'&roleid='.$role->id, $rolenames[$role->id], '', $USER->id);
525 $this->assertEventLegacyLogData($expectedlegacylog, $event);
529 * Test role unassigning.
531 public function test_role_unassign() {
532 global $DB, $USER;
534 $this->resetAfterTest();
536 $user = $this->getDataGenerator()->create_user();
537 $course = $this->getDataGenerator()->create_course();
538 $role = $DB->get_record('role', array('shortname'=>'student'));
540 $context = context_course::instance($course->id);
541 role_assign($role->id, $user->id, $context->id);
542 $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
543 role_unassign($role->id, $user->id, $context->id);
544 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
546 role_assign($role->id, $user->id, $context->id, 'enrol_self', 1);
547 $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
548 role_unassign($role->id, $user->id, $context->id, 'enrol_self', 1);
549 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
551 // Test event triggered.
553 role_assign($role->id, $user->id, $context->id);
554 $sink = $this->redirectEvents();
555 role_unassign($role->id, $user->id, $context->id);
556 $events = $sink->get_events();
557 $sink->close();
558 $this->assertCount(1, $events);
559 $event = $events[0];
560 $this->assertInstanceOf('\core\event\role_unassigned', $event);
561 $this->assertSame('role', $event->target);
562 $this->assertSame('role', $event->objecttable);
563 $this->assertEquals($role->id, $event->objectid);
564 $this->assertEquals($context->id, $event->contextid);
565 $this->assertEquals($user->id, $event->relateduserid);
566 $this->assertCount(3, $event->other);
567 $this->assertSame('', $event->other['component']);
568 $this->assertEquals(0, $event->other['itemid']);
569 $this->assertInstanceOf('moodle_url', $event->get_url());
570 $roles = get_all_roles();
571 $rolenames = role_fix_names($roles, $context, ROLENAME_ORIGINAL, true);
572 $expectedlegacylog = array($course->id, 'role', 'unassign',
573 'admin/roles/assign.php?contextid='.$context->id.'&roleid='.$role->id, $rolenames[$role->id], '', $USER->id);
574 $this->assertEventLegacyLogData($expectedlegacylog, $event);
578 * Test role unassigning.
580 public function test_role_unassign_all() {
581 global $DB;
583 $this->resetAfterTest();
585 $user = $this->getDataGenerator()->create_user();
586 $course = $this->getDataGenerator()->create_course();
587 $role = $DB->get_record('role', array('shortname'=>'student'));
588 $role2 = $DB->get_record('role', array('shortname'=>'teacher'));
589 $syscontext = context_system::instance();
590 $coursecontext = context_course::instance($course->id);
591 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
592 $modcontext = context_module::instance($page->cmid);
594 role_assign($role->id, $user->id, $syscontext->id);
595 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
596 $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id)));
597 role_unassign_all(array('userid'=>$user->id, 'roleid'=>$role->id));
598 $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id)));
600 role_assign($role->id, $user->id, $syscontext->id);
601 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
602 role_assign($role->id, $user->id, $modcontext->id);
603 $this->assertEquals(3, $DB->count_records('role_assignments', array('userid'=>$user->id)));
604 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id), false);
605 $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id)));
606 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id), true);
607 $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id)));
608 role_unassign_all(array('userid'=>$user->id));
609 $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id)));
611 role_assign($role->id, $user->id, $syscontext->id);
612 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
613 role_assign($role->id, $user->id, $coursecontext->id);
614 role_assign($role->id, $user->id, $modcontext->id);
615 $this->assertEquals(4, $DB->count_records('role_assignments', array('userid'=>$user->id)));
616 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id, 'component'=>'enrol_self'), true, true);
617 $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id)));
619 // Test events triggered.
621 role_assign($role2->id, $user->id, $coursecontext->id);
622 role_assign($role2->id, $user->id, $modcontext->id);
623 $sink = $this->redirectEvents();
624 role_unassign_all(array('userid'=>$user->id, 'roleid'=>$role2->id));
625 $events = $sink->get_events();
626 $sink->close();
627 $this->assertCount(2, $events);
628 $this->assertInstanceOf('\core\event\role_unassigned', $events[0]);
629 $this->assertInstanceOf('\core\event\role_unassigned', $events[1]);
633 * Test role queries.
635 public function test_get_roles_with_capability() {
636 global $DB;
638 $this->resetAfterTest();
640 $syscontext = context_system::instance();
641 $frontcontext = context_course::instance(SITEID);
642 $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
643 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
645 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // Any capability is ok.
646 $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse'));
648 $roles = get_roles_with_capability('moodle/backup:backupcourse');
649 $this->assertEquals(array(), $roles);
651 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $syscontext->id);
652 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $manager->id, $frontcontext->id);
653 assign_capability('moodle/backup:backupcourse', CAP_PREVENT, $teacher->id, $frontcontext->id);
655 $roles = get_roles_with_capability('moodle/backup:backupcourse');
656 $this->assertEquals(array($teacher->id, $manager->id), array_keys($roles), '', 0, 10, true);
658 $roles = get_roles_with_capability('moodle/backup:backupcourse', CAP_ALLOW);
659 $this->assertEquals(array($manager->id), array_keys($roles), '', 0, 10, true);
661 $roles = get_roles_with_capability('moodle/backup:backupcourse', null, $syscontext);
662 $this->assertEquals(array($manager->id), array_keys($roles), '', 0, 10, true);
666 * Test deleting of roles.
668 public function test_delete_role() {
669 global $DB;
671 $this->resetAfterTest();
673 $role = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
674 $user = $this->getDataGenerator()->create_user();
675 role_assign($role->id, $user->id, context_system::instance());
676 $course = $this->getDataGenerator()->create_course();
677 $rolename = (object)array('roleid'=>$role->id, 'name'=>'Man', 'contextid'=>context_course::instance($course->id)->id);
678 $DB->insert_record('role_names', $rolename);
680 $this->assertTrue($DB->record_exists('role_assignments', array('roleid'=>$role->id)));
681 $this->assertTrue($DB->record_exists('role_capabilities', array('roleid'=>$role->id)));
682 $this->assertTrue($DB->record_exists('role_names', array('roleid'=>$role->id)));
683 $this->assertTrue($DB->record_exists('role_context_levels', array('roleid'=>$role->id)));
684 $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$role->id)));
685 $this->assertTrue($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id)));
686 $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$role->id)));
687 $this->assertTrue($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id)));
689 // Delete role and get event.
690 $sink = $this->redirectEvents();
691 $result = delete_role($role->id);
692 $events = $sink->get_events();
693 $sink->close();
694 $event = array_pop($events);
696 $this->assertTrue($result);
697 $this->assertFalse($DB->record_exists('role', array('id'=>$role->id)));
698 $this->assertFalse($DB->record_exists('role_assignments', array('roleid'=>$role->id)));
699 $this->assertFalse($DB->record_exists('role_capabilities', array('roleid'=>$role->id)));
700 $this->assertFalse($DB->record_exists('role_names', array('roleid'=>$role->id)));
701 $this->assertFalse($DB->record_exists('role_context_levels', array('roleid'=>$role->id)));
702 $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$role->id)));
703 $this->assertFalse($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id)));
704 $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$role->id)));
705 $this->assertFalse($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id)));
707 // Test triggered event.
708 $this->assertInstanceOf('\core\event\role_deleted', $event);
709 $this->assertSame('role', $event->target);
710 $this->assertSame('role', $event->objecttable);
711 $this->assertSame($role->id, $event->objectid);
712 $this->assertEquals(context_system::instance(), $event->get_context());
713 $this->assertSame($role->shortname, $event->other['shortname']);
714 $this->assertSame($role->description, $event->other['description']);
715 $this->assertSame($role->archetype, $event->other['archetype']);
717 $expectedlegacylog = array(SITEID, 'role', 'delete', 'admin/roles/manage.php?action=delete&roleid='.$role->id,
718 $role->shortname, '');
719 $this->assertEventLegacyLogData($expectedlegacylog, $event);
723 * Test fetching of all roles.
725 public function test_get_all_roles() {
726 global $DB;
728 $this->resetAfterTest();
730 $allroles = get_all_roles();
731 $this->assertInternalType('array', $allroles);
732 $this->assertCount(8, $allroles); // There are 8 roles is standard install.
734 $role = reset($allroles);
735 $role = (array)$role;
737 $this->assertEquals(array('id', 'name', 'shortname', 'description', 'sortorder', 'archetype'), array_keys($role), '', 0, 10, true);
739 foreach ($allroles as $roleid => $role) {
740 $this->assertEquals($role->id, $roleid);
743 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
744 $course = $this->getDataGenerator()->create_course();
745 $coursecontext = context_course::instance($course->id);
746 $otherid = create_role('Other role', 'other', 'Some other role', '');
747 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
748 $DB->insert_record('role_names', $teacherename);
749 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
750 $DB->insert_record('role_names', $otherrename);
751 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id), '', 'roleid, name');
753 $allroles = get_all_roles($coursecontext);
754 $this->assertInternalType('array', $allroles);
755 $this->assertCount(9, $allroles);
756 $role = reset($allroles);
757 $role = (array)$role;
759 $this->assertEquals(array('id', 'name', 'shortname', 'description', 'sortorder', 'archetype', 'coursealias'), array_keys($role), '', 0, 10, true);
761 foreach ($allroles as $roleid => $role) {
762 $this->assertEquals($role->id, $roleid);
763 if (isset($renames[$roleid])) {
764 $this->assertSame($renames[$roleid], $role->coursealias);
765 } else {
766 $this->assertNull($role->coursealias);
772 * Test getting of all archetypes.
774 public function test_get_role_archetypes() {
775 $archetypes = get_role_archetypes();
776 $this->assertCount(8, $archetypes); // There are 8 archetypes in standard install.
777 foreach ($archetypes as $k => $v) {
778 $this->assertSame($k, $v);
783 * Test getting of roles with given archetype.
785 public function test_get_archetype_roles() {
786 $this->resetAfterTest();
788 // New install should have 1 role for each archetype.
789 $archetypes = get_role_archetypes();
790 foreach ($archetypes as $archetype) {
791 $roles = get_archetype_roles($archetype);
792 $this->assertCount(1, $roles);
793 $role = reset($roles);
794 $this->assertSame($archetype, $role->archetype);
797 create_role('New student role', 'student2', 'New student description', 'student');
798 $roles = get_archetype_roles('student');
799 $this->assertCount(2, $roles);
803 * Test aliased role names.
805 public function test_role_get_name() {
806 global $DB;
808 $this->resetAfterTest();
810 $allroles = $DB->get_records('role');
811 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
812 $course = $this->getDataGenerator()->create_course();
813 $coursecontext = context_course::instance($course->id);
814 $otherid = create_role('Other role', 'other', 'Some other role', '');
815 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
816 $DB->insert_record('role_names', $teacherename);
817 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
818 $DB->insert_record('role_names', $otherrename);
819 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id), '', 'roleid, name');
821 foreach ($allroles as $role) {
822 // Get localised name from lang pack.
823 $this->assertSame('', $role->name);
824 $name = role_get_name($role, null, ROLENAME_ORIGINAL);
825 $this->assertNotEmpty($name);
826 $this->assertNotEquals($role->shortname, $name);
828 if (isset($renames[$role->id])) {
829 $this->assertSame($renames[$role->id], role_get_name($role, $coursecontext));
830 $this->assertSame($renames[$role->id], role_get_name($role, $coursecontext, ROLENAME_ALIAS));
831 $this->assertSame($renames[$role->id], role_get_name($role, $coursecontext, ROLENAME_ALIAS_RAW));
832 $this->assertSame("{$renames[$role->id]} ($name)", role_get_name($role, $coursecontext, ROLENAME_BOTH));
833 } else {
834 $this->assertSame($name, role_get_name($role, $coursecontext));
835 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_ALIAS));
836 $this->assertNull(role_get_name($role, $coursecontext, ROLENAME_ALIAS_RAW));
837 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_BOTH));
839 $this->assertSame($name, role_get_name($role));
840 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_ORIGINAL));
841 $this->assertSame($name, role_get_name($role, null, ROLENAME_ORIGINAL));
842 $this->assertSame($role->shortname, role_get_name($role, $coursecontext, ROLENAME_SHORT));
843 $this->assertSame($role->shortname, role_get_name($role, null, ROLENAME_SHORT));
844 $this->assertSame("$name ($role->shortname)", role_get_name($role, $coursecontext, ROLENAME_ORIGINALANDSHORT));
845 $this->assertSame("$name ($role->shortname)", role_get_name($role, null, ROLENAME_ORIGINALANDSHORT));
846 $this->assertNull(role_get_name($role, null, ROLENAME_ALIAS_RAW));
851 * Test tweaking of role name arrays.
853 public function test_role_fix_names() {
854 global $DB;
856 $this->resetAfterTest();
858 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
859 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
860 $otherid = create_role('Other role', 'other', 'Some other role', '');
861 $anotherid = create_role('Another role', 'another', 'Yet another other role', '');
862 $allroles = $DB->get_records('role');
864 $syscontext = context_system::instance();
865 $frontcontext = context_course::instance(SITEID);
866 $course = $this->getDataGenerator()->create_course();
867 $coursecontext = context_course::instance($course->id);
868 $category = $DB->get_record('course_categories', array('id'=>$course->category), '*', MUST_EXIST);
869 $categorycontext = context_coursecat::instance($category->id);
871 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
872 $DB->insert_record('role_names', $teacherename);
873 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
874 $DB->insert_record('role_names', $otherrename);
875 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id), '', 'roleid, name');
877 // Make sure all localname contain proper values for each ROLENAME_ constant,
878 // note role_get_name() on frontpage is used to get the original name for future compatibility.
879 $roles = $allroles;
880 unset($roles[$student->id]); // Remove one role to make sure no role is added or removed.
881 $rolenames = array();
882 foreach ($roles as $role) {
883 $rolenames[$role->id] = $role->name;
886 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
887 foreach ($alltypes as $type) {
888 $fixed = role_fix_names($roles, $coursecontext, $type);
889 $this->assertCount(count($roles), $fixed);
890 foreach ($fixed as $roleid => $rolename) {
891 $this->assertInstanceOf('stdClass', $rolename);
892 $role = $allroles[$roleid];
893 $name = role_get_name($role, $coursecontext, $type);
894 $this->assertSame($name, $rolename->localname);
896 $fixed = role_fix_names($rolenames, $coursecontext, $type);
897 $this->assertCount(count($rolenames), $fixed);
898 foreach ($fixed as $roleid => $rolename) {
899 $role = $allroles[$roleid];
900 $name = role_get_name($role, $coursecontext, $type);
901 $this->assertSame($name, $rolename);
907 * Test role default allows.
909 public function test_get_default_role_archetype_allows() {
910 $archetypes = get_role_archetypes();
911 foreach ($archetypes as $archetype) {
913 $result = get_default_role_archetype_allows('assign', $archetype);
914 $this->assertInternalType('array', $result);
916 $result = get_default_role_archetype_allows('override', $archetype);
917 $this->assertInternalType('array', $result);
919 $result = get_default_role_archetype_allows('switch', $archetype);
920 $this->assertInternalType('array', $result);
922 $result = get_default_role_archetype_allows('view', $archetype);
923 $this->assertInternalType('array', $result);
926 $result = get_default_role_archetype_allows('assign', '');
927 $this->assertSame(array(), $result);
929 $result = get_default_role_archetype_allows('override', '');
930 $this->assertSame(array(), $result);
932 $result = get_default_role_archetype_allows('switch', '');
933 $this->assertSame(array(), $result);
935 $result = get_default_role_archetype_allows('view', '');
936 $this->assertSame(array(), $result);
938 $result = get_default_role_archetype_allows('assign', 'wrongarchetype');
939 $this->assertSame(array(), $result);
940 $this->assertDebuggingCalled();
942 $result = get_default_role_archetype_allows('override', 'wrongarchetype');
943 $this->assertSame(array(), $result);
944 $this->assertDebuggingCalled();
946 $result = get_default_role_archetype_allows('switch', 'wrongarchetype');
947 $this->assertSame(array(), $result);
948 $this->assertDebuggingCalled();
950 $result = get_default_role_archetype_allows('view', 'wrongarchetype');
951 $this->assertSame(array(), $result);
952 $this->assertDebuggingCalled();
956 * Test allowing of role assignments.
958 public function test_core_role_set_assign_allowed() {
959 global $DB, $CFG;
961 $this->resetAfterTest();
963 $otherid = create_role('Other role', 'other', 'Some other role', '');
964 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
966 $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id)));
967 core_role_set_assign_allowed($otherid, $student->id);
968 $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id)));
970 // Test event trigger.
971 $allowroleassignevent = \core\event\role_allow_assign_updated::create(array('context' => context_system::instance()));
972 $sink = $this->redirectEvents();
973 $allowroleassignevent->trigger();
974 $events = $sink->get_events();
975 $sink->close();
976 $event = array_pop($events);
977 $this->assertInstanceOf('\core\event\role_allow_assign_updated', $event);
978 $mode = 'assign';
979 $baseurl = new moodle_url('/admin/roles/allow.php', array('mode' => $mode));
980 $expectedlegacylog = array(SITEID, 'role', 'edit allow ' . $mode, str_replace($CFG->wwwroot . '/', '', $baseurl));
981 $this->assertEventLegacyLogData($expectedlegacylog, $event);
985 * Test allowing of role overrides.
987 public function test_core_role_set_override_allowed() {
988 global $DB, $CFG;
990 $this->resetAfterTest();
992 $otherid = create_role('Other role', 'other', 'Some other role', '');
993 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
995 $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id)));
996 core_role_set_override_allowed($otherid, $student->id);
997 $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id)));
999 // Test event trigger.
1000 $allowroleassignevent = \core\event\role_allow_override_updated::create(array('context' => context_system::instance()));
1001 $sink = $this->redirectEvents();
1002 $allowroleassignevent->trigger();
1003 $events = $sink->get_events();
1004 $sink->close();
1005 $event = array_pop($events);
1006 $this->assertInstanceOf('\core\event\role_allow_override_updated', $event);
1007 $mode = 'override';
1008 $baseurl = new moodle_url('/admin/roles/allow.php', array('mode' => $mode));
1009 $expectedlegacylog = array(SITEID, 'role', 'edit allow ' . $mode, str_replace($CFG->wwwroot . '/', '', $baseurl));
1010 $this->assertEventLegacyLogData($expectedlegacylog, $event);
1014 * Test allowing of role switching.
1016 public function test_core_role_set_switch_allowed() {
1017 global $DB, $CFG;
1019 $this->resetAfterTest();
1021 $otherid = create_role('Other role', 'other', 'Some other role', '');
1022 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1024 $this->assertFalse($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id)));
1025 core_role_set_switch_allowed($otherid, $student->id);
1026 $this->assertTrue($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id)));
1028 // Test event trigger.
1029 $allowroleassignevent = \core\event\role_allow_switch_updated::create(array('context' => context_system::instance()));
1030 $sink = $this->redirectEvents();
1031 $allowroleassignevent->trigger();
1032 $events = $sink->get_events();
1033 $sink->close();
1034 $event = array_pop($events);
1035 $this->assertInstanceOf('\core\event\role_allow_switch_updated', $event);
1036 $mode = 'switch';
1037 $baseurl = new moodle_url('/admin/roles/allow.php', array('mode' => $mode));
1038 $expectedlegacylog = array(SITEID, 'role', 'edit allow ' . $mode, str_replace($CFG->wwwroot . '/', '', $baseurl));
1039 $this->assertEventLegacyLogData($expectedlegacylog, $event);
1043 * Test allowing of role switching.
1045 public function test_core_role_set_view_allowed() {
1046 global $DB, $CFG;
1048 $this->resetAfterTest();
1050 $otherid = create_role('Other role', 'other', 'Some other role', '');
1051 $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
1053 $this->assertFalse($DB->record_exists('role_allow_view', array('roleid' => $otherid, 'allowview' => $student->id)));
1054 core_role_set_view_allowed($otherid, $student->id);
1055 $this->assertTrue($DB->record_exists('role_allow_view', array('roleid' => $otherid, 'allowview' => $student->id)));
1057 // Test event trigger.
1058 $allowroleassignevent = \core\event\role_allow_view_updated::create(array('context' => context_system::instance()));
1059 $sink = $this->redirectEvents();
1060 $allowroleassignevent->trigger();
1061 $events = $sink->get_events();
1062 $sink->close();
1063 $event = array_pop($events);
1064 $this->assertInstanceOf('\core\event\role_allow_view_updated', $event);
1065 $mode = 'view';
1066 $baseurl = new moodle_url('/admin/roles/allow.php', array('mode' => $mode));
1067 $expectedlegacylog = array(SITEID, 'role', 'edit allow ' . $mode, str_replace($CFG->wwwroot . '/', '', $baseurl));
1068 $this->assertEventLegacyLogData($expectedlegacylog, $event);
1072 * Test returning of assignable roles in context.
1074 public function test_get_assignable_roles() {
1075 global $DB;
1077 $this->resetAfterTest();
1079 $course = $this->getDataGenerator()->create_course();
1080 $coursecontext = context_course::instance($course->id);
1082 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1083 $teacher = $this->getDataGenerator()->create_user();
1084 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1085 $teacherename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1086 $DB->insert_record('role_names', $teacherename);
1088 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1089 $student = $this->getDataGenerator()->create_user();
1090 role_assign($studentrole->id, $student->id, $coursecontext);
1092 $contexts = $DB->get_records('context');
1093 $users = $DB->get_records('user');
1094 $allroles = $DB->get_records('role');
1096 // Evaluate all results for all users in all contexts.
1097 foreach ($users as $user) {
1098 $this->setUser($user);
1099 foreach ($contexts as $contextid => $unused) {
1100 $context = context_helper::instance_by_id($contextid);
1101 $roles = get_assignable_roles($context, ROLENAME_SHORT);
1102 foreach ($allroles as $roleid => $role) {
1103 if (isset($roles[$roleid])) {
1104 if (is_siteadmin()) {
1105 $this->assertTrue($DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel, 'roleid'=>$roleid)));
1106 } else {
1107 $this->assertTrue(user_can_assign($context, $roleid), "u:$user->id r:$roleid");
1109 $this->assertEquals($role->shortname, $roles[$roleid]);
1110 } else {
1111 $allowed = $DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel, 'roleid'=>$roleid));
1112 if (is_siteadmin()) {
1113 $this->assertFalse($allowed);
1114 } else {
1115 $this->assertFalse($allowed and user_can_assign($context, $roleid), "u:$user->id, r:{$allroles[$roleid]->name}, c:$context->contextlevel");
1122 // Not-logged-in user.
1123 $this->setUser(0);
1124 foreach ($contexts as $contextid => $unused) {
1125 $context = context_helper::instance_by_id($contextid);
1126 $roles = get_assignable_roles($context, ROLENAME_SHORT);
1127 $this->assertSame(array(), $roles);
1130 // Test current user.
1131 $this->setUser(0);
1132 $admin = $DB->get_record('user', array('username'=>'admin'), '*', MUST_EXIST);
1133 $roles1 = get_assignable_roles($coursecontext, ROLENAME_SHORT, false, $admin);
1134 $roles2 = get_assignable_roles($coursecontext, ROLENAME_SHORT, false, $admin->id);
1135 $this->setAdminUser();
1136 $roles3 = get_assignable_roles($coursecontext, ROLENAME_SHORT);
1137 $this->assertSame($roles1, $roles3);
1138 $this->assertSame($roles2, $roles3);
1140 // Test parameter defaults.
1141 $this->setAdminUser();
1142 $roles1 = get_assignable_roles($coursecontext);
1143 $roles2 = get_assignable_roles($coursecontext, ROLENAME_ALIAS, false, $admin);
1144 $this->assertEquals($roles2, $roles1);
1146 // Verify returned names - let's allow all roles everywhere to simplify this a bit.
1147 $alllevels = context_helper::get_all_levels();
1148 $alllevels = array_keys($alllevels);
1149 foreach ($allroles as $roleid => $role) {
1150 set_role_contextlevels($roleid, $alllevels);
1152 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
1153 foreach ($alltypes as $type) {
1154 $rolenames = role_fix_names($allroles, $coursecontext, $type);
1155 $roles = get_assignable_roles($coursecontext, $type, false, $admin);
1156 foreach ($roles as $roleid => $rolename) {
1157 $this->assertSame($rolenames[$roleid]->localname, $rolename);
1161 // Verify counts.
1162 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
1163 foreach ($alltypes as $type) {
1164 $roles = get_assignable_roles($coursecontext, $type, false, $admin);
1165 list($rolenames, $rolecounts, $nameswithcounts) = get_assignable_roles($coursecontext, $type, true, $admin);
1166 $this->assertEquals($roles, $rolenames);
1167 foreach ($rolenames as $roleid => $name) {
1168 if ($roleid == $teacherrole->id or $roleid == $studentrole->id) {
1169 $this->assertEquals(1, $rolecounts[$roleid]);
1170 } else {
1171 $this->assertEquals(0, $rolecounts[$roleid]);
1173 $this->assertSame("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]);
1179 * Test getting of all switchable roles.
1181 public function test_get_switchable_roles() {
1182 global $DB;
1184 $this->resetAfterTest();
1186 $course = $this->getDataGenerator()->create_course();
1187 $coursecontext = context_course::instance($course->id);
1189 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1190 $teacher = $this->getDataGenerator()->create_user();
1191 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1192 $teacherename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1193 $DB->insert_record('role_names', $teacherename);
1195 $contexts = $DB->get_records('context');
1196 $users = $DB->get_records('user');
1197 $allroles = $DB->get_records('role');
1199 // Evaluate all results for all users in all contexts.
1200 foreach ($users as $user) {
1201 $this->setUser($user);
1202 foreach ($contexts as $contextid => $unused) {
1203 $context = context_helper::instance_by_id($contextid);
1204 $roles = get_switchable_roles($context);
1205 foreach ($allroles as $roleid => $role) {
1206 if (is_siteadmin()) {
1207 $this->assertTrue(isset($roles[$roleid]));
1208 } else {
1209 $parents = $context->get_parent_context_ids(true);
1210 $pcontexts = implode(',' , $parents);
1211 $allowed = $DB->record_exists_sql(
1212 "SELECT r.id
1213 FROM {role} r
1214 JOIN {role_allow_switch} ras ON ras.allowswitch = r.id
1215 JOIN {role_assignments} ra ON ra.roleid = ras.roleid
1216 WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid
1218 array('userid'=>$user->id, 'roleid'=>$roleid)
1220 if (isset($roles[$roleid])) {
1221 $this->assertTrue($allowed);
1222 } else {
1223 $this->assertFalse($allowed);
1227 if (isset($roles[$roleid])) {
1228 $coursecontext = $context->get_course_context(false);
1229 $this->assertSame(role_get_name($role, $coursecontext), $roles[$roleid]);
1237 * Test getting of all overridable roles.
1239 public function test_get_overridable_roles() {
1240 global $DB;
1242 $this->resetAfterTest();
1244 $course = $this->getDataGenerator()->create_course();
1245 $coursecontext = context_course::instance($course->id);
1247 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1248 $teacher = $this->getDataGenerator()->create_user();
1249 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1250 $teacherename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1251 $DB->insert_record('role_names', $teacherename);
1252 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // Any capability is ok.
1253 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $teacherrole->id, $coursecontext->id);
1255 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1256 $student = $this->getDataGenerator()->create_user();
1257 role_assign($studentrole->id, $student->id, $coursecontext);
1259 $contexts = $DB->get_records('context');
1260 $users = $DB->get_records('user');
1261 $allroles = $DB->get_records('role');
1263 // Evaluate all results for all users in all contexts.
1264 foreach ($users as $user) {
1265 $this->setUser($user);
1266 foreach ($contexts as $contextid => $unused) {
1267 $context = context_helper::instance_by_id($contextid);
1268 $roles = get_overridable_roles($context, ROLENAME_SHORT);
1269 foreach ($allroles as $roleid => $role) {
1270 $hascap = has_any_capability(array('moodle/role:safeoverride', 'moodle/role:override'), $context);
1271 if (is_siteadmin()) {
1272 $this->assertTrue(isset($roles[$roleid]));
1273 } else {
1274 $parents = $context->get_parent_context_ids(true);
1275 $pcontexts = implode(',' , $parents);
1276 $allowed = $DB->record_exists_sql(
1277 "SELECT r.id
1278 FROM {role} r
1279 JOIN {role_allow_override} rao ON r.id = rao.allowoverride
1280 JOIN {role_assignments} ra ON rao.roleid = ra.roleid
1281 WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid
1283 array('userid'=>$user->id, 'roleid'=>$roleid)
1285 if (isset($roles[$roleid])) {
1286 $this->assertTrue($hascap);
1287 $this->assertTrue($allowed);
1288 } else {
1289 $this->assertFalse($hascap and $allowed);
1293 if (isset($roles[$roleid])) {
1294 $this->assertEquals($role->shortname, $roles[$roleid]);
1300 // Test parameter defaults.
1301 $this->setAdminUser();
1302 $roles1 = get_overridable_roles($coursecontext);
1303 $roles2 = get_overridable_roles($coursecontext, ROLENAME_ALIAS, false);
1304 $this->assertEquals($roles2, $roles1);
1306 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
1307 foreach ($alltypes as $type) {
1308 $rolenames = role_fix_names($allroles, $coursecontext, $type);
1309 $roles = get_overridable_roles($coursecontext, $type, false);
1310 foreach ($roles as $roleid => $rolename) {
1311 $this->assertSame($rolenames[$roleid]->localname, $rolename);
1315 // Verify counts.
1316 $roles = get_overridable_roles($coursecontext, ROLENAME_ALIAS, false);
1317 list($rolenames, $rolecounts, $nameswithcounts) = get_overridable_roles($coursecontext, ROLENAME_ALIAS, true);
1318 $this->assertEquals($roles, $rolenames);
1319 foreach ($rolenames as $roleid => $name) {
1320 if ($roleid == $teacherrole->id) {
1321 $this->assertEquals(1, $rolecounts[$roleid]);
1322 } else {
1323 $this->assertEquals(0, $rolecounts[$roleid]);
1325 $this->assertSame("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]);
1330 * Test getting of all overridable roles.
1332 public function test_get_viewable_roles_course() {
1333 global $DB;
1335 $this->resetAfterTest();
1337 $course = $this->getDataGenerator()->create_course();
1338 $coursecontext = context_course::instance($course->id);
1340 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST);
1341 $teacher = $this->getDataGenerator()->create_user();
1342 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1344 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
1345 $studentrolerename = (object) array('roleid' => $studentrole->id, 'name' => 'Učitel', 'contextid' => $coursecontext->id);
1346 $DB->insert_record('role_names', $studentrolerename);
1348 // By default teacher can see student.
1349 $this->setUser($teacher);
1350 $viewableroles = get_viewable_roles($coursecontext);
1351 $this->assertContains($studentrolerename->name, array_values($viewableroles));
1352 // Remove view permission.
1353 $DB->delete_records('role_allow_view', array('roleid' => $teacherrole->id, 'allowview' => $studentrole->id));
1354 $viewableroles = get_viewable_roles($coursecontext);
1355 // Teacher can no longer see student role.
1356 $this->assertNotContains($studentrolerename->name, array_values($viewableroles));
1357 // Allow again teacher to view student.
1358 core_role_set_view_allowed($teacherrole->id, $studentrole->id);
1359 // Teacher can now see student role.
1360 $viewableroles = get_viewable_roles($coursecontext);
1361 $this->assertContains($studentrolerename->name, array_values($viewableroles));
1365 * Test getting of all overridable roles.
1367 public function test_get_viewable_roles_system() {
1368 global $DB;
1370 $this->resetAfterTest();
1372 $context = context_system::instance();
1374 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST);
1375 $teacher = $this->getDataGenerator()->create_user();
1376 role_assign($teacherrole->id, $teacher->id, $context);
1378 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
1379 $studentrolename = role_get_name($studentrole, $context);
1381 // By default teacher can see student.
1382 $this->setUser($teacher);
1383 $viewableroles = get_viewable_roles($context);
1384 $this->assertContains($studentrolename, array_values($viewableroles));
1385 // Remove view permission.
1386 $DB->delete_records('role_allow_view', array('roleid' => $teacherrole->id, 'allowview' => $studentrole->id));
1387 $viewableroles = get_viewable_roles($context);
1388 // Teacher can no longer see student role.
1389 $this->assertNotContains($studentrolename, array_values($viewableroles));
1390 // Allow again teacher to view student.
1391 core_role_set_view_allowed($teacherrole->id, $studentrole->id);
1392 // Teacher can now see student role.
1393 $viewableroles = get_viewable_roles($context);
1394 $this->assertContains($studentrolename, array_values($viewableroles));
1398 * Test we have context level defaults.
1400 public function test_get_default_contextlevels() {
1401 $archetypes = get_role_archetypes();
1402 $alllevels = context_helper::get_all_levels();
1403 foreach ($archetypes as $archetype) {
1404 $defaults = get_default_contextlevels($archetype);
1405 $this->assertInternalType('array', $defaults);
1406 foreach ($defaults as $level) {
1407 $this->assertTrue(isset($alllevels[$level]));
1413 * Test role context level setup.
1415 public function test_set_role_contextlevels() {
1416 global $DB;
1418 $this->resetAfterTest();
1420 $roleid = create_role('New student role', 'student2', 'New student description', 'student');
1422 $this->assertFalse($DB->record_exists('role_context_levels', array('roleid' => $roleid)));
1424 set_role_contextlevels($roleid, array(CONTEXT_COURSE, CONTEXT_MODULE));
1425 $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel');
1426 $this->assertCount(2, $levels);
1427 $this->assertTrue(isset($levels[CONTEXT_COURSE]));
1428 $this->assertTrue(isset($levels[CONTEXT_MODULE]));
1430 set_role_contextlevels($roleid, array(CONTEXT_COURSE));
1431 $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel');
1432 $this->assertCount(1, $levels);
1433 $this->assertTrue(isset($levels[CONTEXT_COURSE]));
1437 * Test getting of role context levels
1439 public function test_get_roles_for_contextlevels() {
1440 global $DB;
1442 $allroles = get_all_roles();
1443 foreach (context_helper::get_all_levels() as $level => $unused) {
1444 $roles = get_roles_for_contextlevels($level);
1445 foreach ($allroles as $roleid => $unused) {
1446 $exists = $DB->record_exists('role_context_levels', array('contextlevel'=>$level, 'roleid'=>$roleid));
1447 if (in_array($roleid, $roles)) {
1448 $this->assertTrue($exists);
1449 } else {
1450 $this->assertFalse($exists);
1457 * Test default enrol roles.
1459 public function test_get_default_enrol_roles() {
1460 $this->resetAfterTest();
1462 $course = $this->getDataGenerator()->create_course();
1463 $coursecontext = context_course::instance($course->id);
1465 $id2 = create_role('New student role', 'student2', 'New student description', 'student');
1466 set_role_contextlevels($id2, array(CONTEXT_COURSE));
1468 $allroles = get_all_roles();
1469 $expected = array($id2=>$allroles[$id2]);
1471 foreach (get_role_archetypes() as $archetype) {
1472 $defaults = get_default_contextlevels($archetype);
1473 if (in_array(CONTEXT_COURSE, $defaults)) {
1474 $roles = get_archetype_roles($archetype);
1475 foreach ($roles as $role) {
1476 $expected[$role->id] = $role;
1481 $roles = get_default_enrol_roles($coursecontext);
1482 foreach ($allroles as $role) {
1483 $this->assertEquals(isset($expected[$role->id]), isset($roles[$role->id]));
1484 if (isset($roles[$role->id])) {
1485 $this->assertSame(role_get_name($role, $coursecontext), $roles[$role->id]);
1491 * Test getting of role users.
1493 public function test_get_role_users() {
1494 global $DB;
1496 $this->resetAfterTest();
1498 $systemcontext = context_system::instance();
1499 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1500 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1501 $noeditteacherrole = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
1502 $course = $this->getDataGenerator()->create_course();
1503 $coursecontext = context_course::instance($course->id);
1504 $otherid = create_role('Other role', 'other', 'Some other role', '');
1505 $teacherrename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1506 $DB->insert_record('role_names', $teacherrename);
1507 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
1508 $DB->insert_record('role_names', $otherrename);
1510 $user1 = $this->getDataGenerator()->create_user(array('firstname'=>'John', 'lastname'=>'Smith'));
1511 role_assign($teacherrole->id, $user1->id, $coursecontext->id);
1512 $user2 = $this->getDataGenerator()->create_user(array('firstname'=>'Jan', 'lastname'=>'Kovar'));
1513 role_assign($teacherrole->id, $user2->id, $systemcontext->id);
1514 $user3 = $this->getDataGenerator()->create_user();
1515 $this->getDataGenerator()->enrol_user($user3->id, $course->id, $teacherrole->id);
1516 $user4 = $this->getDataGenerator()->create_user();
1517 $this->getDataGenerator()->enrol_user($user4->id, $course->id, $studentrole->id);
1518 $this->getDataGenerator()->enrol_user($user4->id, $course->id, $noeditteacherrole->id);
1520 $group = $this->getDataGenerator()->create_group(array('courseid'=>$course->id));
1521 groups_add_member($group, $user3);
1523 $users = get_role_users($teacherrole->id, $coursecontext);
1524 $this->assertCount(2, $users);
1525 $this->assertArrayHasKey($user1->id, $users);
1526 $this->assertEquals($users[$user1->id]->id, $user1->id);
1527 $this->assertEquals($users[$user1->id]->roleid, $teacherrole->id);
1528 $this->assertEquals($users[$user1->id]->rolename, $teacherrole->name);
1529 $this->assertEquals($users[$user1->id]->roleshortname, $teacherrole->shortname);
1530 $this->assertEquals($users[$user1->id]->rolecoursealias, $teacherrename->name);
1531 $this->assertArrayHasKey($user3->id, $users);
1532 $this->assertEquals($users[$user3->id]->id, $user3->id);
1533 $this->assertEquals($users[$user3->id]->roleid, $teacherrole->id);
1534 $this->assertEquals($users[$user3->id]->rolename, $teacherrole->name);
1535 $this->assertEquals($users[$user3->id]->roleshortname, $teacherrole->shortname);
1536 $this->assertEquals($users[$user3->id]->rolecoursealias, $teacherrename->name);
1538 $users = get_role_users($teacherrole->id, $coursecontext, true);
1539 $this->assertCount(3, $users);
1541 $users = get_role_users($teacherrole->id, $coursecontext, true, '', null, null, '', 2, 1);
1542 $this->assertCount(1, $users);
1544 $users = get_role_users($teacherrole->id, $coursecontext, false, 'u.id, u.email, u.idnumber', 'u.idnumber');
1545 $this->assertCount(2, $users);
1546 $this->assertArrayHasKey($user1->id, $users);
1547 $this->assertArrayHasKey($user3->id, $users);
1549 $users = get_role_users($teacherrole->id, $coursecontext, false, 'u.id, u.email');
1550 $this->assertDebuggingCalled('get_role_users() adding u.lastname, u.firstname to the query result because they were required by $sort but missing in $fields');
1551 $this->assertCount(2, $users);
1552 $this->assertArrayHasKey($user1->id, $users);
1553 $this->assertObjectHasAttribute('lastname', $users[$user1->id]);
1554 $this->assertObjectHasAttribute('firstname', $users[$user1->id]);
1555 $this->assertArrayHasKey($user3->id, $users);
1556 $this->assertObjectHasAttribute('lastname', $users[$user3->id]);
1557 $this->assertObjectHasAttribute('firstname', $users[$user3->id]);
1559 $users = get_role_users($teacherrole->id, $coursecontext, false, 'u.id AS id_alias');
1560 $this->assertDebuggingCalled('get_role_users() adding u.lastname, u.firstname to the query result because they were required by $sort but missing in $fields');
1561 $this->assertCount(2, $users);
1562 $this->assertArrayHasKey($user1->id, $users);
1563 $this->assertObjectHasAttribute('id_alias', $users[$user1->id]);
1564 $this->assertObjectHasAttribute('lastname', $users[$user1->id]);
1565 $this->assertObjectHasAttribute('firstname', $users[$user1->id]);
1566 $this->assertArrayHasKey($user3->id, $users);
1567 $this->assertObjectHasAttribute('id_alias', $users[$user3->id]);
1568 $this->assertObjectHasAttribute('lastname', $users[$user3->id]);
1569 $this->assertObjectHasAttribute('firstname', $users[$user3->id]);
1571 $users = get_role_users($teacherrole->id, $coursecontext, false, 'u.id, u.email, u.idnumber', 'u.idnumber', null, $group->id);
1572 $this->assertCount(1, $users);
1573 $this->assertArrayHasKey($user3->id, $users);
1575 $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'));
1576 $this->assertCount(1, $users);
1577 $this->assertArrayHasKey($user1->id, $users);
1579 $users = get_role_users(array($noeditteacherrole->id, $studentrole->id), $coursecontext, false, 'ra.id', 'ra.id');
1580 $this->assertDebuggingNotCalled();
1581 $users = get_role_users(array($noeditteacherrole->id, $studentrole->id), $coursecontext, false, 'ra.userid', 'ra.userid');
1582 $this->assertDebuggingCalled('get_role_users() without specifying one single roleid needs to be called prefixing ' .
1583 'role assignments id (ra.id) as unique field, you can use $fields param for it.');
1584 $users = get_role_users(array($noeditteacherrole->id, $studentrole->id), $coursecontext, false);
1585 $this->assertDebuggingCalled('get_role_users() without specifying one single roleid needs to be called prefixing ' .
1586 'role assignments id (ra.id) as unique field, you can use $fields param for it.');
1587 $users = get_role_users(array($noeditteacherrole->id, $studentrole->id), $coursecontext,
1588 false, 'u.id, u.firstname', 'u.id, u.firstname');
1589 $this->assertDebuggingCalled('get_role_users() without specifying one single roleid needs to be called prefixing ' .
1590 'role assignments id (ra.id) as unique field, you can use $fields param for it.');
1594 * Test used role query.
1596 public function test_get_roles_used_in_context() {
1597 global $DB;
1599 $this->resetAfterTest();
1601 $systemcontext = context_system::instance();
1602 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1603 $course = $this->getDataGenerator()->create_course();
1604 $coursecontext = context_course::instance($course->id);
1605 $otherid = create_role('Other role', 'other', 'Some other role', '');
1606 $teacherrename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1607 $DB->insert_record('role_names', $teacherrename);
1608 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
1609 $DB->insert_record('role_names', $otherrename);
1611 $user1 = $this->getDataGenerator()->create_user();
1612 role_assign($teacherrole->id, $user1->id, $coursecontext->id);
1614 $roles = get_roles_used_in_context($coursecontext);
1615 $this->assertCount(1, $roles);
1616 $role = reset($roles);
1617 $roleid = key($roles);
1618 $this->assertEquals($roleid, $role->id);
1619 $this->assertEquals($teacherrole->id, $role->id);
1620 $this->assertSame($teacherrole->name, $role->name);
1621 $this->assertSame($teacherrole->shortname, $role->shortname);
1622 $this->assertEquals($teacherrole->sortorder, $role->sortorder);
1623 $this->assertSame($teacherrename->name, $role->coursealias);
1625 $user2 = $this->getDataGenerator()->create_user();
1626 role_assign($teacherrole->id, $user2->id, $systemcontext->id);
1627 role_assign($otherid, $user2->id, $systemcontext->id);
1629 $roles = get_roles_used_in_context($systemcontext);
1630 $this->assertCount(2, $roles);
1634 * Test roles used in course.
1636 public function test_get_user_roles_in_course() {
1637 global $DB, $CFG;
1639 $this->resetAfterTest();
1641 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1642 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1643 $managerrole = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST);
1644 $course = $this->getDataGenerator()->create_course();
1645 $coursecontext = context_course::instance($course->id);
1646 $teacherrename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1647 $DB->insert_record('role_names', $teacherrename);
1649 $roleids = explode(',', $CFG->profileroles); // Should include teacher and student in new installs.
1650 $this->assertTrue(in_array($teacherrole->id, $roleids));
1651 $this->assertTrue(in_array($studentrole->id, $roleids));
1652 $this->assertFalse(in_array($managerrole->id, $roleids));
1654 $user1 = $this->getDataGenerator()->create_user();
1655 role_assign($teacherrole->id, $user1->id, $coursecontext->id);
1656 role_assign($studentrole->id, $user1->id, $coursecontext->id);
1657 $user2 = $this->getDataGenerator()->create_user();
1658 role_assign($studentrole->id, $user2->id, $coursecontext->id);
1659 $user3 = $this->getDataGenerator()->create_user();
1660 $user4 = $this->getDataGenerator()->create_user();
1661 role_assign($managerrole->id, $user4->id, $coursecontext->id);
1663 $this->setAdminUser();
1665 $roles = get_user_roles_in_course($user1->id, $course->id);
1666 $this->assertEquals(1, preg_match_all('/,/', $roles, $matches));
1667 $this->assertTrue(strpos($roles, role_get_name($teacherrole, $coursecontext)) !== false);
1669 $roles = get_user_roles_in_course($user2->id, $course->id);
1670 $this->assertEquals(0, preg_match_all('/,/', $roles, $matches));
1671 $this->assertTrue(strpos($roles, role_get_name($studentrole, $coursecontext)) !== false);
1673 $roles = get_user_roles_in_course($user3->id, $course->id);
1674 $this->assertSame('', $roles);
1676 // Managers should be able to see a link to their own role type, given they can assign it in the context.
1677 $this->setUser($user4);
1678 $roles = get_user_roles_in_course($user4->id, $course->id);
1679 $this->assertNotEmpty($roles);
1680 $this->assertEquals(1, count(explode(',', $roles)));
1681 $this->assertTrue(strpos($roles, role_get_name($managerrole, $coursecontext)) !== false);
1683 // Managers should see 2 roles if viewing a user who has been enrolled as a student and a teacher in the course.
1684 $roles = get_user_roles_in_course($user1->id, $course->id);
1685 $this->assertEquals(2, count(explode(',', $roles)));
1686 $this->assertTrue(strpos($roles, role_get_name($studentrole, $coursecontext)) !== false);
1687 $this->assertTrue(strpos($roles, role_get_name($teacherrole, $coursecontext)) !== false);
1689 // Students should not see the manager role if viewing a manager's profile.
1690 $this->setUser($user2);
1691 $roles = get_user_roles_in_course($user4->id, $course->id);
1692 $this->assertEmpty($roles); // Should see 0 roles on the manager's profile.
1693 $this->assertFalse(strpos($roles, role_get_name($managerrole, $coursecontext)) !== false);
1697 * Test get_user_roles and get_users_roles
1699 public function test_get_user_roles() {
1700 global $DB, $CFG;
1702 $this->resetAfterTest();
1704 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1705 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1706 $course = $this->getDataGenerator()->create_course();
1707 $coursecontext = context_course::instance($course->id);
1708 $teacherrename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1709 $DB->insert_record('role_names', $teacherrename);
1711 $roleids = explode(',', $CFG->profileroles); // Should include teacher and student in new installs.
1713 $user1 = $this->getDataGenerator()->create_user();
1714 role_assign($teacherrole->id, $user1->id, $coursecontext->id);
1715 role_assign($studentrole->id, $user1->id, $coursecontext->id);
1716 $user2 = $this->getDataGenerator()->create_user();
1717 role_assign($studentrole->id, $user2->id, $coursecontext->id);
1718 $user3 = $this->getDataGenerator()->create_user();
1720 $u1roles = get_user_roles($coursecontext, $user1->id);
1722 $u2roles = get_user_roles($coursecontext, $user2->id);
1724 $allroles = get_users_roles($coursecontext, [], false);
1725 $specificuserroles = get_users_roles($coursecontext, [$user1->id, $user2->id]);
1726 $this->assertEquals($u1roles, $allroles[$user1->id]);
1727 $this->assertEquals($u1roles, $specificuserroles[$user1->id]);
1728 $this->assertEquals($u2roles, $allroles[$user2->id]);
1729 $this->assertEquals($u2roles, $specificuserroles[$user2->id]);
1733 * Test has_capability(), has_any_capability() and has_all_capabilities().
1735 public function test_has_capability_and_friends() {
1736 global $DB;
1738 $this->resetAfterTest();
1740 $course = $this->getDataGenerator()->create_course();
1741 $coursecontext = context_course::instance($course->id);
1742 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1743 $teacher = $this->getDataGenerator()->create_user();
1744 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1745 $admin = $DB->get_record('user', array('username'=>'admin'));
1747 // Note: Here are used default capabilities, the full test is in permission evaluation bellow,
1748 // use two capabilities that teacher has and one does not, none of them should be allowed for not-logged-in user.
1750 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupsection')));
1751 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse')));
1752 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/site:approvecourse')));
1754 $sca = array('moodle/backup:backupsection', 'moodle/backup:backupcourse', 'moodle/site:approvecourse');
1755 $sc = array('moodle/backup:backupsection', 'moodle/backup:backupcourse');
1757 $this->setUser(0);
1758 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext));
1759 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext));
1760 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext));
1761 $this->assertFalse(has_any_capability($sca, $coursecontext));
1762 $this->assertFalse(has_all_capabilities($sca, $coursecontext));
1764 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $teacher));
1765 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $teacher));
1766 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $teacher));
1767 $this->assertTrue(has_any_capability($sca, $coursecontext, $teacher));
1768 $this->assertTrue(has_all_capabilities($sc, $coursecontext, $teacher));
1769 $this->assertFalse(has_all_capabilities($sca, $coursecontext, $teacher));
1771 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $admin));
1772 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $admin));
1773 $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext, $admin));
1774 $this->assertTrue(has_any_capability($sca, $coursecontext, $admin));
1775 $this->assertTrue(has_all_capabilities($sc, $coursecontext, $admin));
1776 $this->assertTrue(has_all_capabilities($sca, $coursecontext, $admin));
1778 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, $admin, false));
1779 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, $admin, false));
1780 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $admin, false));
1781 $this->assertFalse(has_any_capability($sca, $coursecontext, $admin, false));
1782 $this->assertFalse(has_all_capabilities($sc, $coursecontext, $admin, false));
1783 $this->assertFalse(has_all_capabilities($sca, $coursecontext, $admin, false));
1785 $this->setUser($teacher);
1786 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext));
1787 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext));
1788 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext));
1789 $this->assertTrue(has_any_capability($sca, $coursecontext));
1790 $this->assertTrue(has_all_capabilities($sc, $coursecontext));
1791 $this->assertFalse(has_all_capabilities($sca, $coursecontext));
1793 $this->setAdminUser();
1794 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext));
1795 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext));
1796 $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext));
1797 $this->assertTrue(has_any_capability($sca, $coursecontext));
1798 $this->assertTrue(has_all_capabilities($sc, $coursecontext));
1799 $this->assertTrue(has_all_capabilities($sca, $coursecontext));
1801 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, 0));
1802 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, 0));
1803 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, 0));
1804 $this->assertFalse(has_any_capability($sca, $coursecontext, 0));
1805 $this->assertFalse(has_all_capabilities($sca, $coursecontext, 0));
1809 * Test that the caching in get_role_definitions() and get_role_definitions_uncached()
1810 * works as intended.
1812 public function test_role_definition_caching() {
1813 global $DB;
1815 $this->resetAfterTest();
1817 // Get some role ids.
1818 $authenticatedrole = $DB->get_record('role', array('shortname' => 'user'), '*', MUST_EXIST);
1819 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
1820 $emptyroleid = create_role('No capabilities', 'empty', 'A role with no capabilties');
1821 $course = $this->getDataGenerator()->create_course();
1822 $coursecontext = context_course::instance($course->id);
1824 // Instantiate the cache instance, since that does DB queries (get_config)
1825 // and we don't care about those.
1826 cache::make('core', 'roledefs');
1828 // One database query is not necessarily one database read, it seems. Find out how many.
1829 $startdbreads = $DB->perf_get_reads();
1830 $rs = $DB->get_recordset('user');
1831 $rs->close();
1832 $readsperquery = $DB->perf_get_reads() - $startdbreads;
1834 // Now load some role definitions, and check when it queries the database.
1836 // Load the capabilities for two roles. Should be one query.
1837 $startdbreads = $DB->perf_get_reads();
1838 get_role_definitions([$authenticatedrole->id, $studentrole->id]);
1839 $this->assertEquals(1 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1841 // Load the capabilities for same two roles. Should not query the DB.
1842 $startdbreads = $DB->perf_get_reads();
1843 get_role_definitions([$authenticatedrole->id, $studentrole->id]);
1844 $this->assertEquals(0 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1846 // Include a third role. Should do one DB query.
1847 $startdbreads = $DB->perf_get_reads();
1848 get_role_definitions([$authenticatedrole->id, $studentrole->id, $emptyroleid]);
1849 $this->assertEquals(1 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1851 // Repeat call. No DB queries.
1852 $startdbreads = $DB->perf_get_reads();
1853 get_role_definitions([$authenticatedrole->id, $studentrole->id, $emptyroleid]);
1854 $this->assertEquals(0 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1856 // Alter a role.
1857 role_change_permission($studentrole->id, $coursecontext, 'moodle/course:tag', CAP_ALLOW);
1859 // Should now know to do one query.
1860 $startdbreads = $DB->perf_get_reads();
1861 get_role_definitions([$authenticatedrole->id, $studentrole->id]);
1862 $this->assertEquals(1 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1864 // Now clear the in-memory cache, and verify that it does not query the DB.
1865 // Cannot use accesslib_clear_all_caches_for_unit_testing since that also
1866 // clears the MUC cache.
1867 global $ACCESSLIB_PRIVATE;
1868 $ACCESSLIB_PRIVATE->cacheroledefs = array();
1870 // Get all roles. Should not need the DB.
1871 $startdbreads = $DB->perf_get_reads();
1872 get_role_definitions([$authenticatedrole->id, $studentrole->id, $emptyroleid]);
1873 $this->assertEquals(0 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1877 * Tests get_user_capability_course() which checks a capability across all courses.
1879 public function test_get_user_capability_course() {
1880 global $CFG, $USER;
1882 $this->resetAfterTest();
1884 $generator = $this->getDataGenerator();
1885 $cap = 'moodle/course:view';
1887 // The structure being created here is this:
1889 // All tests work with the single capability 'moodle/course:view'.
1891 // ROLE DEF/OVERRIDE ROLE ASSIGNS
1892 // Role: Allow Prohib Empty Def user u1 u2 u3 u4 u5 u6 u7 u8
1893 // System ALLOW PROHIBIT A E A+E
1894 // cat1 ALLOW
1895 // C1 (ALLOW) P
1896 // C2 ALLOW E P
1897 // cat2 PREVENT
1898 // C3 ALLOW E
1899 // C4
1900 // Misc. A
1901 // C5 PREVENT A
1902 // C6 PROHIBIT
1904 // Front-page and guest role stuff from the end of this test not included in the diagram.
1906 // Create a role which allows course:view and one that prohibits it, and one neither.
1907 $allowroleid = $generator->create_role();
1908 $prohibitroleid = $generator->create_role();
1909 $emptyroleid = $generator->create_role();
1910 $systemcontext = context_system::instance();
1911 assign_capability($cap, CAP_ALLOW, $allowroleid, $systemcontext->id);
1912 assign_capability($cap, CAP_PROHIBIT, $prohibitroleid, $systemcontext->id);
1914 // Create two categories (nested).
1915 $cat1 = $generator->create_category();
1916 $cat2 = $generator->create_category(['parent' => $cat1->id]);
1918 // Create six courses - two in cat1, two in cat2, and two in default category.
1919 // Shortnames are used for a sorting test. Otherwise they are not significant.
1920 $c1 = $generator->create_course(['category' => $cat1->id, 'shortname' => 'Z']);
1921 $c2 = $generator->create_course(['category' => $cat1->id, 'shortname' => 'Y']);
1922 $c3 = $generator->create_course(['category' => $cat2->id, 'shortname' => 'X']);
1923 $c4 = $generator->create_course(['category' => $cat2->id]);
1924 $c5 = $generator->create_course();
1925 $c6 = $generator->create_course();
1927 // Category overrides: in cat 1, empty role is allowed; in cat 2, empty role is prevented.
1928 assign_capability($cap, CAP_ALLOW, $emptyroleid,
1929 context_coursecat::instance($cat1->id)->id);
1930 assign_capability($cap, CAP_PREVENT, $emptyroleid,
1931 context_coursecat::instance($cat2->id)->id);
1933 // Course overrides: in C5, allow role is prevented; in C6, empty role is prohibited; in
1934 // C3, empty role is allowed.
1935 assign_capability($cap, CAP_PREVENT, $allowroleid,
1936 context_course::instance($c5->id)->id);
1937 assign_capability($cap, CAP_PROHIBIT, $emptyroleid,
1938 context_course::instance($c6->id)->id);
1939 assign_capability($cap, CAP_ALLOW, $emptyroleid,
1940 context_course::instance($c3->id)->id);
1941 assign_capability($cap, CAP_ALLOW, $prohibitroleid,
1942 context_course::instance($c2->id)->id);
1944 // User 1 has no roles except default user role.
1945 $u1 = $generator->create_user();
1947 // It returns false (annoyingly) if there are no courses.
1948 $this->assertFalse(get_user_capability_course($cap, $u1->id, true, '', 'id'));
1950 // Final override: in C1, default user role is allowed.
1951 assign_capability($cap, CAP_ALLOW, $CFG->defaultuserroleid,
1952 context_course::instance($c1->id)->id);
1954 // Should now get C1 only.
1955 $courses = get_user_capability_course($cap, $u1->id, true, '', 'id');
1956 $this->assert_course_ids([$c1->id], $courses);
1958 // User 2 has allow role (system wide).
1959 $u2 = $generator->create_user();
1960 role_assign($allowroleid, $u2->id, $systemcontext->id);
1962 // Should get everything except C5.
1963 $courses = get_user_capability_course($cap, $u2->id, true, '', 'id');
1964 $this->assert_course_ids([SITEID, $c1->id, $c2->id, $c3->id, $c4->id, $c6->id], $courses);
1966 // User 3 has empty role (system wide).
1967 $u3 = $generator->create_user();
1968 role_assign($emptyroleid, $u3->id, $systemcontext->id);
1970 // Should get cat 1 courses but not cat2, except C3.
1971 $courses = get_user_capability_course($cap, $u3->id, true, '', 'id');
1972 $this->assert_course_ids([$c1->id, $c2->id, $c3->id], $courses);
1974 // User 4 has allow and empty role (system wide).
1975 $u4 = $generator->create_user();
1976 role_assign($allowroleid, $u4->id, $systemcontext->id);
1977 role_assign($emptyroleid, $u4->id, $systemcontext->id);
1979 // Should get everything except C5 and C6.
1980 $courses = get_user_capability_course($cap, $u4->id, true, '', 'id');
1981 $this->assert_course_ids([SITEID, $c1->id, $c2->id, $c3->id, $c4->id], $courses);
1983 // User 5 has allow role in default category only.
1984 $u5 = $generator->create_user();
1985 role_assign($allowroleid, $u5->id, context_coursecat::instance($c5->category)->id);
1987 // Should get C1 and the default category courses but not C5.
1988 $courses = get_user_capability_course($cap, $u5->id, true, '', 'id');
1989 $this->assert_course_ids([$c1->id, $c6->id], $courses);
1991 // User 6 has a bunch of course roles: prohibit role in C1, empty role in C3, allow role in
1992 // C6.
1993 $u6 = $generator->create_user();
1994 role_assign($prohibitroleid, $u6->id, context_course::instance($c1->id)->id);
1995 role_assign($emptyroleid, $u6->id, context_course::instance($c3->id)->id);
1996 role_assign($allowroleid, $u6->id, context_course::instance($c5->id)->id);
1998 // Should get C3 only because the allow role is prevented in C5.
1999 $courses = get_user_capability_course($cap, $u6->id, true, '', 'id');
2000 $this->assert_course_ids([$c3->id], $courses);
2002 // User 7 has empty role in C2.
2003 $u7 = $generator->create_user();
2004 role_assign($emptyroleid, $u7->id, context_course::instance($c2->id)->id);
2006 // Should get C1 by the default user role override, and C2 by the cat1 level override.
2007 $courses = get_user_capability_course($cap, $u7->id, true, '', 'id');
2008 $this->assert_course_ids([$c1->id, $c2->id], $courses);
2010 // User 8 has prohibit role as system context, to verify that prohibits can't be overridden.
2011 $u8 = $generator->create_user();
2012 role_assign($prohibitroleid, $u8->id, context_course::instance($c2->id)->id);
2014 // Should get C1 by the default user role override, no other courses because the prohibit cannot be overridden.
2015 $courses = get_user_capability_course($cap, $u8->id, true, '', 'id');
2016 $this->assert_course_ids([$c1->id], $courses);
2018 // Admin user gets everything....
2019 $courses = get_user_capability_course($cap, get_admin()->id, true, '', 'id');
2020 $this->assert_course_ids([SITEID, $c1->id, $c2->id, $c3->id, $c4->id, $c5->id, $c6->id],
2021 $courses);
2023 // Unless you turn off doanything, when it only has the things a user with no role does.
2024 $courses = get_user_capability_course($cap, get_admin()->id, false, '', 'id');
2025 $this->assert_course_ids([$c1->id], $courses);
2027 // Using u3 as an example, test the limit feature.
2028 $courses = get_user_capability_course($cap, $u3->id, true, '', 'id', 2);
2029 $this->assert_course_ids([$c1->id, $c2->id], $courses);
2031 // Check sorting.
2032 $courses = get_user_capability_course($cap, $u3->id, true, '', 'shortname');
2033 $this->assert_course_ids([$c3->id, $c2->id, $c1->id], $courses);
2035 // Check returned fields - default.
2036 $courses = get_user_capability_course($cap, $u3->id, true, '', 'id');
2037 $this->assertEquals((object)['id' => $c1->id], $courses[0]);
2039 // Add a selection of fields, including the context ones with special handling.
2040 $courses = get_user_capability_course($cap, $u3->id, true, 'shortname, ctxlevel, ctxdepth, ctxinstance', 'id');
2041 $this->assertEquals((object)['id' => $c1->id, 'shortname' => 'Z', 'ctxlevel' => 50,
2042 'ctxdepth' => 3, 'ctxinstance' => $c1->id], $courses[0]);
2044 // Test front page role - user 1 has no roles, but if we change the front page role
2045 // definition so that it has our capability, then they should see the front page course.
2046 // as well as C1.
2047 assign_capability($cap, CAP_ALLOW, $CFG->defaultfrontpageroleid, $systemcontext->id);
2048 $courses = get_user_capability_course($cap, $u1->id, true, '', 'id');
2049 $this->assert_course_ids([SITEID, $c1->id], $courses);
2051 // Check that temporary guest access (in this case, given on course 2 for user 1)
2052 // also is included, if it has this capability.
2053 assign_capability($cap, CAP_ALLOW, $CFG->guestroleid, $systemcontext->id);
2054 $this->setUser($u1);
2055 load_temp_course_role(context_course::instance($c2->id), $CFG->guestroleid);
2056 $courses = get_user_capability_course($cap, $USER->id, true, '', 'id');
2057 $this->assert_course_ids([SITEID, $c1->id, $c2->id], $courses);
2061 * Extracts an array of course ids to make the above test script shorter.
2063 * @param int[] $expected Array of expected course ids
2064 * @param stdClass[] $courses Array of course objects
2066 protected function assert_course_ids(array $expected, array $courses) {
2067 $courseids = array_map(function($c) {
2068 return $c->id;
2069 }, $courses);
2070 $this->assertEquals($expected, $courseids);
2074 * Test if course creator future capability lookup works.
2076 public function test_guess_if_creator_will_have_course_capability() {
2077 global $DB, $CFG, $USER;
2079 $this->resetAfterTest();
2081 $category = $this->getDataGenerator()->create_category();
2082 $course = $this->getDataGenerator()->create_course(array('category'=>$category->id));
2084 $syscontext = context_system::instance();
2085 $categorycontext = context_coursecat::instance($category->id);
2086 $coursecontext = context_course::instance($course->id);
2087 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
2088 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
2089 $creatorrole = $DB->get_record('role', array('shortname'=>'coursecreator'), '*', MUST_EXIST);
2090 $managerrole = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
2092 $this->assertEquals($teacherrole->id, $CFG->creatornewroleid);
2094 $creator = $this->getDataGenerator()->create_user();
2095 $manager = $this->getDataGenerator()->create_user();
2096 role_assign($managerrole->id, $manager->id, $categorycontext);
2098 $this->assertFalse(has_capability('moodle/course:view', $categorycontext, $creator));
2099 $this->assertFalse(has_capability('moodle/role:assign', $categorycontext, $creator));
2100 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $creator));
2101 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $creator));
2102 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $creator));
2103 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $creator));
2105 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext, $manager));
2106 $this->assertTrue(has_capability('moodle/course:visibility', $categorycontext, $manager));
2107 $this->assertTrue(has_capability('moodle/course:visibility', $coursecontext, $manager));
2108 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $manager->id));
2109 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $manager->id));
2111 $this->assertEquals(0, $USER->id);
2112 $this->assertFalse(has_capability('moodle/course:view', $categorycontext));
2113 $this->assertFalse(has_capability('moodle/role:assign', $categorycontext));
2114 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext));
2115 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext));
2116 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext));
2117 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext));
2119 $this->setUser($manager);
2120 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext));
2121 $this->assertTrue(has_capability('moodle/course:visibility', $categorycontext));
2122 $this->assertTrue(has_capability('moodle/course:visibility', $coursecontext));
2123 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext));
2124 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext));
2126 $this->setAdminUser();
2127 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext));
2128 $this->assertTrue(has_capability('moodle/course:visibility', $categorycontext));
2129 $this->assertTrue(has_capability('moodle/course:visibility', $coursecontext));
2130 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext));
2131 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext));
2132 $this->setUser(0);
2134 role_assign($creatorrole->id, $creator->id, $categorycontext);
2136 $this->assertFalse(has_capability('moodle/role:assign', $categorycontext, $creator));
2137 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $creator));
2138 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $creator));
2139 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $creator));
2140 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $creator));
2142 $this->setUser($creator);
2143 $this->assertFalse(has_capability('moodle/role:assign', $categorycontext, null));
2144 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, null));
2145 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, null));
2146 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, null));
2147 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, null));
2148 $this->setUser(0);
2150 set_config('creatornewroleid', $studentrole->id);
2152 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $creator));
2153 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $creator));
2154 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $creator));
2155 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $creator));
2157 set_config('creatornewroleid', $teacherrole->id);
2159 role_change_permission($managerrole->id, $categorycontext, 'moodle/course:visibility', CAP_PREVENT);
2160 role_assign($creatorrole->id, $manager->id, $categorycontext);
2162 $this->assertTrue(has_capability('moodle/course:view', $categorycontext, $manager));
2163 $this->assertTrue(has_capability('moodle/course:view', $coursecontext, $manager));
2164 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext, $manager));
2165 $this->assertTrue(has_capability('moodle/role:assign', $coursecontext, $manager));
2166 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $manager));
2167 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $manager));
2168 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $manager));
2169 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $manager));
2171 role_change_permission($managerrole->id, $categorycontext, 'moodle/course:view', CAP_PREVENT);
2172 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext, $manager));
2173 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $manager));
2174 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $manager));
2175 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $manager));
2176 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $manager));
2178 $this->getDataGenerator()->enrol_user($manager->id, $course->id, 0);
2180 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext, $manager));
2181 $this->assertTrue(has_capability('moodle/role:assign', $coursecontext, $manager));
2182 $this->assertTrue(is_enrolled($coursecontext, $manager));
2183 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $manager));
2184 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $manager));
2185 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $manager));
2186 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $manager));
2188 // Test problems.
2190 try {
2191 guess_if_creator_will_have_course_capability('moodle/course:visibility', $syscontext, $creator);
2192 $this->fail('Exception expected when non course/category context passed to guess_if_creator_will_have_course_capability()');
2193 } catch (moodle_exception $e) {
2194 $this->assertInstanceOf('coding_exception', $e);
2199 * Test require_capability() exceptions.
2201 public function test_require_capability() {
2202 $this->resetAfterTest();
2204 $syscontext = context_system::instance();
2206 $this->setUser(0);
2207 $this->assertFalse(has_capability('moodle/site:config', $syscontext));
2208 try {
2209 require_capability('moodle/site:config', $syscontext);
2210 $this->fail('Exception expected from require_capability()');
2211 } catch (moodle_exception $e) {
2212 $this->assertInstanceOf('required_capability_exception', $e);
2214 $this->setAdminUser();
2215 $this->assertFalse(has_capability('moodle/site:config', $syscontext, 0));
2216 try {
2217 require_capability('moodle/site:config', $syscontext, 0);
2218 $this->fail('Exception expected from require_capability()');
2219 } catch (moodle_exception $e) {
2220 $this->assertInstanceOf('required_capability_exception', $e);
2222 $this->assertFalse(has_capability('moodle/site:config', $syscontext, null, false));
2223 try {
2224 require_capability('moodle/site:config', $syscontext, null, false);
2225 $this->fail('Exception expected from require_capability()');
2226 } catch (moodle_exception $e) {
2227 $this->assertInstanceOf('required_capability_exception', $e);
2232 * Test that enrolled users SQL does not return any values for users in
2233 * other courses.
2235 public function test_get_enrolled_sql_different_course() {
2236 global $DB;
2238 $this->resetAfterTest();
2240 $course = $this->getDataGenerator()->create_course();
2241 $context = context_course::instance($course->id);
2242 $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
2243 $user = $this->getDataGenerator()->create_user();
2245 // This user should not appear anywhere, we're not interested in that context.
2246 $course2 = $this->getDataGenerator()->create_course();
2247 $this->getDataGenerator()->enrol_user($user->id, $course2->id, $student->id);
2249 $enrolled = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, false);
2250 $active = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, true);
2251 $suspended = get_suspended_userids($context);
2253 $this->assertFalse(isset($enrolled[$user->id]));
2254 $this->assertFalse(isset($active[$user->id]));
2255 $this->assertFalse(isset($suspended[$user->id]));
2256 $this->assertCount(0, $enrolled);
2257 $this->assertCount(0, $active);
2258 $this->assertCount(0, $suspended);
2262 * Test that enrolled users SQL does not return any values for role
2263 * assignments without an enrolment.
2265 public function test_get_enrolled_sql_role_only() {
2266 global $DB;
2268 $this->resetAfterTest();
2270 $course = $this->getDataGenerator()->create_course();
2271 $context = context_course::instance($course->id);
2272 $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
2273 $user = $this->getDataGenerator()->create_user();
2275 // Role assignment is not the same as course enrollment.
2276 role_assign($student->id, $user->id, $context->id);
2278 $enrolled = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, false);
2279 $active = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, true);
2280 $suspended = get_suspended_userids($context);
2282 $this->assertFalse(isset($enrolled[$user->id]));
2283 $this->assertFalse(isset($active[$user->id]));
2284 $this->assertFalse(isset($suspended[$user->id]));
2285 $this->assertCount(0, $enrolled);
2286 $this->assertCount(0, $active);
2287 $this->assertCount(0, $suspended);
2291 * Test that multiple enrolments for the same user are counted correctly.
2293 public function test_get_enrolled_sql_multiple_enrolments() {
2294 global $DB;
2296 $this->resetAfterTest();
2298 $course = $this->getDataGenerator()->create_course();
2299 $context = context_course::instance($course->id);
2300 $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
2301 $user = $this->getDataGenerator()->create_user();
2303 // Add a suspended enrol.
2304 $selfinstance = $DB->get_record('enrol', array('courseid' => $course->id, 'enrol' => 'self'));
2305 $selfplugin = enrol_get_plugin('self');
2306 $selfplugin->update_status($selfinstance, ENROL_INSTANCE_ENABLED);
2307 $this->getDataGenerator()->enrol_user($user->id, $course->id, $student->id, 'self', 0, 0, ENROL_USER_SUSPENDED);
2309 // Should be enrolled, but not active - user is suspended.
2310 $enrolled = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, false);
2311 $active = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, true);
2312 $suspended = get_suspended_userids($context);
2314 $this->assertTrue(isset($enrolled[$user->id]));
2315 $this->assertFalse(isset($active[$user->id]));
2316 $this->assertTrue(isset($suspended[$user->id]));
2317 $this->assertCount(1, $enrolled);
2318 $this->assertCount(0, $active);
2319 $this->assertCount(1, $suspended);
2321 // Add an active enrol for the user. Any active enrol makes them enrolled.
2322 $this->getDataGenerator()->enrol_user($user->id, $course->id, $student->id);
2324 // User should be active now.
2325 $enrolled = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, false);
2326 $active = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, true);
2327 $suspended = get_suspended_userids($context);
2329 $this->assertTrue(isset($enrolled[$user->id]));
2330 $this->assertTrue(isset($active[$user->id]));
2331 $this->assertFalse(isset($suspended[$user->id]));
2332 $this->assertCount(1, $enrolled);
2333 $this->assertCount(1, $active);
2334 $this->assertCount(0, $suspended);
2338 public function get_enrolled_sql_provider() {
2339 return array(
2340 array(
2341 // Two users who are enrolled.
2342 'users' => array(
2343 array(
2344 'enrolled' => true,
2345 'active' => true,
2347 array(
2348 'enrolled' => true,
2349 'active' => true,
2352 'counts' => array(
2353 'enrolled' => 2,
2354 'active' => 2,
2355 'suspended' => 0,
2358 array(
2359 // A user who is suspended.
2360 'users' => array(
2361 array(
2362 'status' => ENROL_USER_SUSPENDED,
2363 'enrolled' => true,
2364 'suspended' => true,
2367 'counts' => array(
2368 'enrolled' => 1,
2369 'active' => 0,
2370 'suspended' => 1,
2373 array(
2374 // One of each.
2375 'users' => array(
2376 array(
2377 'enrolled' => true,
2378 'active' => true,
2380 array(
2381 'status' => ENROL_USER_SUSPENDED,
2382 'enrolled' => true,
2383 'suspended' => true,
2386 'counts' => array(
2387 'enrolled' => 2,
2388 'active' => 1,
2389 'suspended' => 1,
2392 array(
2393 // One user who is not yet enrolled.
2394 'users' => array(
2395 array(
2396 'timestart' => DAYSECS,
2397 'enrolled' => true,
2398 'active' => false,
2399 'suspended' => true,
2402 'counts' => array(
2403 'enrolled' => 1,
2404 'active' => 0,
2405 'suspended' => 1,
2408 array(
2409 // One user who is no longer enrolled
2410 'users' => array(
2411 array(
2412 'timeend' => -DAYSECS,
2413 'enrolled' => true,
2414 'active' => false,
2415 'suspended' => true,
2418 'counts' => array(
2419 'enrolled' => 1,
2420 'active' => 0,
2421 'suspended' => 1,
2424 array(
2425 // One user who is not yet enrolled, and one who is no longer enrolled.
2426 'users' => array(
2427 array(
2428 'timeend' => -DAYSECS,
2429 'enrolled' => true,
2430 'active' => false,
2431 'suspended' => true,
2433 array(
2434 'timestart' => DAYSECS,
2435 'enrolled' => true,
2436 'active' => false,
2437 'suspended' => true,
2440 'counts' => array(
2441 'enrolled' => 2,
2442 'active' => 0,
2443 'suspended' => 2,
2450 * @dataProvider get_enrolled_sql_provider
2452 public function test_get_enrolled_sql_course($users, $counts) {
2453 global $DB;
2455 $this->resetAfterTest();
2457 $course = $this->getDataGenerator()->create_course();
2458 $context = context_course::instance($course->id);
2459 $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
2460 $createdusers = array();
2462 foreach ($users as &$userdata) {
2463 $user = $this->getDataGenerator()->create_user();
2464 $userdata['id'] = $user->id;
2466 $timestart = 0;
2467 $timeend = 0;
2468 $status = null;
2469 if (isset($userdata['timestart'])) {
2470 $timestart = time() + $userdata['timestart'];
2472 if (isset($userdata['timeend'])) {
2473 $timeend = time() + $userdata['timeend'];
2475 if (isset($userdata['status'])) {
2476 $status = $userdata['status'];
2479 // Enrol the user in the course.
2480 $this->getDataGenerator()->enrol_user($user->id, $course->id, $student->id, 'manual', $timestart, $timeend, $status);
2483 // After all users have been enroled, check expectations.
2484 $enrolled = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, false);
2485 $active = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, true);
2486 $suspended = get_suspended_userids($context);
2488 foreach ($users as $userdata) {
2489 if (isset($userdata['enrolled']) && $userdata['enrolled']) {
2490 $this->assertTrue(isset($enrolled[$userdata['id']]));
2491 } else {
2492 $this->assertFalse(isset($enrolled[$userdata['id']]));
2495 if (isset($userdata['active']) && $userdata['active']) {
2496 $this->assertTrue(isset($active[$userdata['id']]));
2497 } else {
2498 $this->assertFalse(isset($active[$userdata['id']]));
2501 if (isset($userdata['suspended']) && $userdata['suspended']) {
2502 $this->assertTrue(isset($suspended[$userdata['id']]));
2503 } else {
2504 $this->assertFalse(isset($suspended[$userdata['id']]));
2508 $this->assertCount($counts['enrolled'], $enrolled);
2509 $this->assertCount($counts['active'], $active);
2510 $this->assertCount($counts['suspended'], $suspended);
2514 * A small functional test of permission evaluations.
2516 public function test_permission_evaluation() {
2517 global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;
2519 $this->resetAfterTest();
2521 $generator = $this->getDataGenerator();
2523 // Fill the site with some real data.
2524 $testcategories = array();
2525 $testcourses = array();
2526 $testpages = array();
2527 $testblocks = array();
2528 $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
2530 $systemcontext = context_system::instance();
2531 $frontpagecontext = context_course::instance(SITEID);
2533 // Add block to system context.
2534 $bi = $generator->create_block('online_users');
2535 context_block::instance($bi->id);
2536 $testblocks[] = $bi->id;
2538 // Some users.
2539 $testusers = array();
2540 for ($i=0; $i<20; $i++) {
2541 $user = $generator->create_user();
2542 $testusers[$i] = $user->id;
2543 $usercontext = context_user::instance($user->id);
2545 // Add block to user profile.
2546 $bi = $generator->create_block('online_users', array('parentcontextid'=>$usercontext->id));
2547 $testblocks[] = $bi->id;
2549 // Deleted user - should be ignored everywhere, can not have context.
2550 $generator->create_user(array('deleted'=>1));
2552 // Add block to frontpage.
2553 $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagecontext->id));
2554 $frontpageblockcontext = context_block::instance($bi->id);
2555 $testblocks[] = $bi->id;
2557 // Add a resource to frontpage.
2558 $page = $generator->create_module('page', array('course'=>$SITE->id));
2559 $testpages[] = $page->cmid;
2560 $frontpagepagecontext = context_module::instance($page->cmid);
2562 // Add block to frontpage resource.
2563 $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagepagecontext->id));
2564 $frontpagepageblockcontext = context_block::instance($bi->id);
2565 $testblocks[] = $bi->id;
2567 // Some nested course categories with courses.
2568 $manualenrol = enrol_get_plugin('manual');
2569 $parentcat = 0;
2570 for ($i=0; $i<5; $i++) {
2571 $cat = $generator->create_category(array('parent'=>$parentcat));
2572 $testcategories[] = $cat->id;
2573 $catcontext = context_coursecat::instance($cat->id);
2574 $parentcat = $cat->id;
2576 if ($i >= 4) {
2577 continue;
2580 // Add resource to each category.
2581 $bi = $generator->create_block('online_users', array('parentcontextid'=>$catcontext->id));
2582 context_block::instance($bi->id);
2584 // Add a few courses to each category.
2585 for ($j=0; $j<6; $j++) {
2586 $course = $generator->create_course(array('category'=>$cat->id));
2587 $testcourses[] = $course->id;
2588 $coursecontext = context_course::instance($course->id);
2590 if ($j >= 5) {
2591 continue;
2593 // Add manual enrol instance.
2594 $manualenrol->add_default_instance($DB->get_record('course', array('id'=>$course->id)));
2596 // Add block to each course.
2597 $bi = $generator->create_block('online_users', array('parentcontextid'=>$coursecontext->id));
2598 $testblocks[] = $bi->id;
2600 // Add a resource to each course.
2601 $page = $generator->create_module('page', array('course'=>$course->id));
2602 $testpages[] = $page->cmid;
2603 $modcontext = context_module::instance($page->cmid);
2605 // Add block to each module.
2606 $bi = $generator->create_block('online_users', array('parentcontextid'=>$modcontext->id));
2607 $testblocks[] = $bi->id;
2611 // Make sure all contexts were created properly.
2612 $count = 1; // System.
2613 $count += $DB->count_records('user', array('deleted'=>0));
2614 $count += $DB->count_records('course_categories');
2615 $count += $DB->count_records('course');
2616 $count += $DB->count_records('course_modules');
2617 $count += $DB->count_records('block_instances');
2618 $this->assertEquals($count, $DB->count_records('context'));
2619 $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
2620 $this->assertEquals(0, $DB->count_records('context', array('path'=>null)));
2623 // Test context_helper::get_level_name() method.
2625 $levels = context_helper::get_all_levels();
2626 foreach ($levels as $level => $classname) {
2627 $name = context_helper::get_level_name($level);
2628 $this->assertNotEmpty($name);
2632 // Test context::instance_by_id(), context_xxx::instance() methods.
2634 $context = context::instance_by_id($frontpagecontext->id);
2635 $this->assertSame(CONTEXT_COURSE, $context->contextlevel);
2636 $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING));
2637 try {
2638 context::instance_by_id(-1);
2639 $this->fail('exception expected');
2640 } catch (moodle_exception $e) {
2641 $this->assertTrue(true);
2643 $this->assertInstanceOf('context_system', context_system::instance());
2644 $this->assertInstanceOf('context_coursecat', context_coursecat::instance($testcategories[0]));
2645 $this->assertInstanceOf('context_course', context_course::instance($testcourses[0]));
2646 $this->assertInstanceOf('context_module', context_module::instance($testpages[0]));
2647 $this->assertInstanceOf('context_block', context_block::instance($testblocks[0]));
2649 $this->assertFalse(context_coursecat::instance(-1, IGNORE_MISSING));
2650 $this->assertFalse(context_course::instance(-1, IGNORE_MISSING));
2651 $this->assertFalse(context_module::instance(-1, IGNORE_MISSING));
2652 $this->assertFalse(context_block::instance(-1, IGNORE_MISSING));
2653 try {
2654 context_coursecat::instance(-1);
2655 $this->fail('exception expected');
2656 } catch (moodle_exception $e) {
2657 $this->assertTrue(true);
2659 try {
2660 context_course::instance(-1);
2661 $this->fail('exception expected');
2662 } catch (moodle_exception $e) {
2663 $this->assertTrue(true);
2665 try {
2666 context_module::instance(-1);
2667 $this->fail('exception expected');
2668 } catch (moodle_exception $e) {
2669 $this->assertTrue(true);
2671 try {
2672 context_block::instance(-1);
2673 $this->fail('exception expected');
2674 } catch (moodle_exception $e) {
2675 $this->assertTrue(true);
2679 // Test $context->get_url(), $context->get_context_name(), $context->get_capabilities() methods.
2681 $testcontexts = array();
2682 $testcontexts[CONTEXT_SYSTEM] = context_system::instance();
2683 $testcontexts[CONTEXT_COURSECAT] = context_coursecat::instance($testcategories[0]);
2684 $testcontexts[CONTEXT_COURSE] = context_course::instance($testcourses[0]);
2685 $testcontexts[CONTEXT_MODULE] = context_module::instance($testpages[0]);
2686 $testcontexts[CONTEXT_BLOCK] = context_block::instance($testblocks[0]);
2688 foreach ($testcontexts as $context) {
2689 $name = $context->get_context_name(true, true);
2690 $this->assertNotEmpty($name);
2692 $this->assertInstanceOf('moodle_url', $context->get_url());
2694 $caps = $context->get_capabilities();
2695 $this->assertTrue(is_array($caps));
2696 foreach ($caps as $cap) {
2697 $cap = (array)$cap;
2698 $this->assertSame(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask'));
2701 unset($testcontexts);
2703 // Test $context->get_course_context() method.
2705 $this->assertFalse($systemcontext->get_course_context(false));
2706 try {
2707 $systemcontext->get_course_context();
2708 $this->fail('exception expected');
2709 } catch (moodle_exception $e) {
2710 $this->assertInstanceOf('coding_exception', $e);
2712 $context = context_coursecat::instance($testcategories[0]);
2713 $this->assertFalse($context->get_course_context(false));
2714 try {
2715 $context->get_course_context();
2716 $this->fail('exception expected');
2717 } catch (moodle_exception $e) {
2718 $this->assertInstanceOf('coding_exception', $e);
2720 $this->assertEquals($frontpagecontext, $frontpagecontext->get_course_context(true));
2721 $this->assertEquals($frontpagecontext, $frontpagepagecontext->get_course_context(true));
2722 $this->assertEquals($frontpagecontext, $frontpagepageblockcontext->get_course_context(true));
2725 // Test $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() methods.
2727 $userid = reset($testusers);
2728 $usercontext = context_user::instance($userid);
2729 $this->assertEquals($systemcontext, $usercontext->get_parent_context());
2730 $this->assertEquals(array($systemcontext->id=>$systemcontext), $usercontext->get_parent_contexts());
2731 $this->assertEquals(array($usercontext->id=>$usercontext, $systemcontext->id=>$systemcontext), $usercontext->get_parent_contexts(true));
2733 $this->assertEquals(array(), $systemcontext->get_parent_contexts());
2734 $this->assertEquals(array($systemcontext->id=>$systemcontext), $systemcontext->get_parent_contexts(true));
2735 $this->assertEquals(array(), $systemcontext->get_parent_context_ids());
2736 $this->assertEquals(array($systemcontext->id), $systemcontext->get_parent_context_ids(true));
2738 $this->assertEquals($systemcontext, $frontpagecontext->get_parent_context());
2739 $this->assertEquals(array($systemcontext->id=>$systemcontext), $frontpagecontext->get_parent_contexts());
2740 $this->assertEquals(array($frontpagecontext->id=>$frontpagecontext, $systemcontext->id=>$systemcontext), $frontpagecontext->get_parent_contexts(true));
2741 $this->assertEquals(array($systemcontext->id), $frontpagecontext->get_parent_context_ids());
2742 $this->assertEquals(array($frontpagecontext->id, $systemcontext->id), $frontpagecontext->get_parent_context_ids(true));
2744 $this->assertFalse($systemcontext->get_parent_context());
2745 $frontpagecontext = context_course::instance($SITE->id);
2746 $parent = $systemcontext;
2747 foreach ($testcategories as $catid) {
2748 $catcontext = context_coursecat::instance($catid);
2749 $this->assertEquals($parent, $catcontext->get_parent_context());
2750 $parent = $catcontext;
2752 $this->assertEquals($frontpagecontext, $frontpagepagecontext->get_parent_context());
2753 $this->assertEquals($frontpagecontext, $frontpageblockcontext->get_parent_context());
2754 $this->assertEquals($frontpagepagecontext, $frontpagepageblockcontext->get_parent_context());
2757 // Test $context->get_child_contexts() method.
2759 $children = $systemcontext->get_child_contexts();
2760 $this->resetDebugging();
2761 $this->assertEquals(count($children)+1, $DB->count_records('context'));
2763 $context = context_coursecat::instance($testcategories[3]);
2764 $children = $context->get_child_contexts();
2765 $countcats = 0;
2766 $countcourses = 0;
2767 $countblocks = 0;
2768 foreach ($children as $child) {
2769 if ($child->contextlevel == CONTEXT_COURSECAT) {
2770 $countcats++;
2772 if ($child->contextlevel == CONTEXT_COURSE) {
2773 $countcourses++;
2775 if ($child->contextlevel == CONTEXT_BLOCK) {
2776 $countblocks++;
2779 $this->assertCount(8, $children);
2780 $this->assertEquals(1, $countcats);
2781 $this->assertEquals(6, $countcourses);
2782 $this->assertEquals(1, $countblocks);
2784 $context = context_course::instance($testcourses[2]);
2785 $children = $context->get_child_contexts();
2787 $context = context_module::instance($testpages[3]);
2788 $children = $context->get_child_contexts();
2789 $this->assertCount(1, $children);
2791 $context = context_block::instance($testblocks[1]);
2792 $children = $context->get_child_contexts();
2793 $this->assertCount(0, $children);
2795 unset($children);
2796 unset($countcats);
2797 unset($countcourses);
2798 unset($countblocks);
2801 // Test context_helper::reset_caches() method.
2803 context_helper::reset_caches();
2804 $this->assertEquals(0, context_inspection::test_context_cache_size());
2805 context_course::instance($SITE->id);
2806 $this->assertEquals(1, context_inspection::test_context_cache_size());
2809 // Test context preloading.
2811 context_helper::reset_caches();
2812 $sql = "SELECT ".context_helper::get_preload_record_columns_sql('c')."
2813 FROM {context} c
2814 WHERE c.contextlevel <> ".CONTEXT_SYSTEM;
2815 $records = $DB->get_records_sql($sql);
2816 $firstrecord = reset($records);
2817 $columns = context_helper::get_preload_record_columns('c');
2818 $firstrecord = (array)$firstrecord;
2819 $this->assertSame(array_keys($firstrecord), array_values($columns));
2820 context_helper::reset_caches();
2821 foreach ($records as $record) {
2822 context_helper::preload_from_record($record);
2823 $this->assertEquals(new stdClass(), $record);
2825 $this->assertEquals(count($records), context_inspection::test_context_cache_size());
2826 unset($records);
2827 unset($columns);
2829 context_helper::reset_caches();
2830 context_helper::preload_course($SITE->id);
2831 $numfrontpagemodules = $DB->count_records('course_modules', array('course' => $SITE->id));
2832 $this->assertEquals(3 + $numfrontpagemodules, context_inspection::test_context_cache_size()); // Depends on number of default blocks.
2834 // Test assign_capability(), unassign_capability() functions.
2836 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2837 $this->assertFalse($rc);
2838 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext->id);
2839 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2840 $this->assertEquals(CAP_ALLOW, $rc->permission);
2841 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext->id);
2842 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2843 $this->assertEquals(CAP_ALLOW, $rc->permission);
2844 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext, true);
2845 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2846 $this->assertEquals(CAP_PREVENT, $rc->permission);
2848 assign_capability('moodle/site:accessallgroups', CAP_INHERIT, $allroles['teacher'], $frontpagecontext);
2849 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2850 $this->assertFalse($rc);
2851 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext);
2852 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true);
2853 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2854 $this->assertFalse($rc);
2855 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true);
2856 unset($rc);
2858 accesslib_clear_all_caches_for_unit_testing(); // Must be done after assign_capability().
2861 // Test role_assign(), role_unassign(), role_unassign_all() functions.
2863 $context = context_course::instance($testcourses[1]);
2864 $this->assertEquals(0, $DB->count_records('role_assignments', array('contextid'=>$context->id)));
2865 role_assign($allroles['teacher'], $testusers[1], $context->id);
2866 role_assign($allroles['teacher'], $testusers[2], $context->id);
2867 role_assign($allroles['manager'], $testusers[1], $context->id);
2868 $this->assertEquals(3, $DB->count_records('role_assignments', array('contextid'=>$context->id)));
2869 role_unassign($allroles['teacher'], $testusers[1], $context->id);
2870 $this->assertEquals(2, $DB->count_records('role_assignments', array('contextid'=>$context->id)));
2871 role_unassign_all(array('contextid'=>$context->id));
2872 $this->assertEquals(0, $DB->count_records('role_assignments', array('contextid'=>$context->id)));
2873 unset($context);
2875 accesslib_clear_all_caches_for_unit_testing(); // Just in case.
2878 // Test has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends functions.
2880 $adminid = get_admin()->id;
2881 $guestid = $CFG->siteguest;
2883 // Enrol some users into some courses.
2884 $course1 = $DB->get_record('course', array('id'=>$testcourses[22]), '*', MUST_EXIST);
2885 $course2 = $DB->get_record('course', array('id'=>$testcourses[7]), '*', MUST_EXIST);
2886 $cms = $DB->get_records('course_modules', array('course'=>$course1->id), 'id');
2887 $cm1 = reset($cms);
2888 $blocks = $DB->get_records('block_instances', array('parentcontextid'=>context_module::instance($cm1->id)->id), 'id');
2889 $block1 = reset($blocks);
2890 $instance1 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course1->id));
2891 $instance2 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course2->id));
2892 for ($i=0; $i<9; $i++) {
2893 $manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']);
2895 $manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']);
2896 $manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']);
2898 for ($i=10; $i<15; $i++) {
2899 $manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']);
2901 $manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']);
2903 // Add tons of role assignments - the more the better.
2904 role_assign($allroles['coursecreator'], $testusers[11], context_coursecat::instance($testcategories[2]));
2905 role_assign($allroles['manager'], $testusers[12], context_coursecat::instance($testcategories[1]));
2906 role_assign($allroles['student'], $testusers[9], context_module::instance($cm1->id));
2907 role_assign($allroles['teacher'], $testusers[8], context_module::instance($cm1->id));
2908 role_assign($allroles['guest'], $testusers[13], context_course::instance($course1->id));
2909 role_assign($allroles['teacher'], $testusers[7], context_block::instance($block1->id));
2910 role_assign($allroles['manager'], $testusers[9], context_block::instance($block1->id));
2911 role_assign($allroles['editingteacher'], $testusers[9], context_course::instance($course1->id));
2913 role_assign($allroles['teacher'], $adminid, context_course::instance($course1->id));
2914 role_assign($allroles['editingteacher'], $adminid, context_block::instance($block1->id));
2916 // Add tons of overrides - the more the better.
2917 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpageblockcontext, true);
2918 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpageblockcontext, true);
2919 assign_capability('moodle/block:view', CAP_PROHIBIT, $allroles['guest'], $frontpageblockcontext, true);
2920 assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['user'], $frontpageblockcontext, true);
2921 assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['student'], $frontpageblockcontext, true);
2923 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $CFG->defaultuserroleid, $frontpagepagecontext, true);
2924 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagepagecontext, true);
2925 assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $frontpagepagecontext, true);
2926 assign_capability('mod/page:view', CAP_ALLOW, $allroles['user'], $frontpagepagecontext, true);
2927 assign_capability('moodle/page:view', CAP_ALLOW, $allroles['student'], $frontpagepagecontext, true);
2929 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpagecontext, true);
2930 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext, true);
2931 assign_capability('mod/page:view', CAP_ALLOW, $allroles['guest'], $frontpagecontext, true);
2932 assign_capability('mod/page:view', CAP_PROHIBIT, $allroles['user'], $frontpagecontext, true);
2934 assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $systemcontext, true);
2936 // Prepare for prohibit test.
2937 role_assign($allroles['editingteacher'], $testusers[19], context_system::instance());
2938 role_assign($allroles['teacher'], $testusers[19], context_course::instance($testcourses[17]));
2939 role_assign($allroles['editingteacher'], $testusers[19], context_course::instance($testcourses[17]));
2940 assign_capability('moodle/course:update', CAP_PROHIBIT, $allroles['teacher'], context_course::instance($testcourses[17]), true);
2942 accesslib_clear_all_caches_for_unit_testing(); /// Must be done after assign_capability().
2944 // Extra tests for guests and not-logged-in users because they can not be verified by cross checking
2945 // with get_users_by_capability() where they are ignored.
2946 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid));
2947 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid));
2948 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid));
2949 $this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid));
2951 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0));
2952 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0));
2953 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0));
2954 $this->assertFalse(has_capability('mod/page:view', $systemcontext, 0));
2956 $this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11]));
2957 $this->assertTrue(has_capability('moodle/course:create', context_coursecat::instance($testcategories[2]), $testusers[11]));
2958 $this->assertFalse(has_capability('moodle/course:create', context_course::instance($testcourses[1]), $testusers[11]));
2959 $this->assertTrue(has_capability('moodle/course:create', context_course::instance($testcourses[19]), $testusers[11]));
2961 $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[1]), $testusers[9]));
2962 $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[19]), $testusers[9]));
2963 $this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9]));
2965 // Test prohibits.
2966 $this->assertTrue(has_capability('moodle/course:update', context_system::instance(), $testusers[19]));
2967 $ids = get_users_by_capability(context_system::instance(), 'moodle/course:update', 'u.id');
2968 $this->assertArrayHasKey($testusers[19], $ids);
2969 $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[17]), $testusers[19]));
2970 $ids = get_users_by_capability(context_course::instance($testcourses[17]), 'moodle/course:update', 'u.id');
2971 $this->assertArrayNotHasKey($testusers[19], $ids);
2973 // Test the list of enrolled users.
2974 $coursecontext = context_course::instance($course1->id);
2975 $enrolled = get_enrolled_users($coursecontext);
2976 $this->assertCount(10, $enrolled);
2977 for ($i=0; $i<10; $i++) {
2978 $this->assertTrue(isset($enrolled[$testusers[$i]]));
2980 $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
2981 $this->assertCount(1, $enrolled);
2982 $this->assertTrue(isset($enrolled[$testusers[9]]));
2983 unset($enrolled);
2985 // Role switching.
2986 $userid = $testusers[9];
2987 $USER = $DB->get_record('user', array('id'=>$userid));
2988 load_all_capabilities();
2989 $coursecontext = context_course::instance($course1->id);
2990 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
2991 $this->assertFalse(is_role_switched($course1->id));
2992 role_switch($allroles['student'], $coursecontext);
2993 $this->assertTrue(is_role_switched($course1->id));
2994 $this->assertEquals($allroles['student'], $USER->access['rsw'][$coursecontext->path]);
2995 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
2996 reload_all_capabilities();
2997 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
2998 role_switch(0, $coursecontext);
2999 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
3000 $userid = $adminid;
3001 $USER = $DB->get_record('user', array('id'=>$userid));
3002 load_all_capabilities();
3003 $coursecontext = context_course::instance($course1->id);
3004 $blockcontext = context_block::instance($block1->id);
3005 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
3006 role_switch($allroles['student'], $coursecontext);
3007 $this->assertEquals($allroles['student'], $USER->access['rsw'][$coursecontext->path]);
3008 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
3009 reload_all_capabilities();
3010 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
3011 load_all_capabilities();
3012 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
3014 // Temp course role for enrol.
3015 $DB->delete_records('cache_flags', array()); // This prevents problem with dirty contexts immediately resetting the temp role - this is a known problem...
3016 $userid = $testusers[5];
3017 $roleid = $allroles['editingteacher'];
3018 $USER = $DB->get_record('user', array('id'=>$userid));
3019 load_all_capabilities();
3020 $coursecontext = context_course::instance($course1->id);
3021 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
3022 $this->assertFalse(isset($USER->access['ra'][$coursecontext->path][$roleid]));
3023 load_temp_course_role($coursecontext, $roleid);
3024 $this->assertEquals($USER->access['ra'][$coursecontext->path][$roleid], $roleid);
3025 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
3026 remove_temp_course_roles($coursecontext);
3027 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
3028 load_temp_course_role($coursecontext, $roleid);
3029 reload_all_capabilities();
3030 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
3031 $USER = new stdClass();
3032 $USER->id = 0;
3034 // Now cross check has_capability() with get_users_by_capability(), each using different code paths,
3035 // they have to be kept in sync, usually only one of them breaks, so we know when something is wrong,
3036 // at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users).
3037 $contexts = $DB->get_records('context', array(), 'id');
3038 $contexts = array_values($contexts);
3039 $capabilities = $DB->get_records('capabilities', array(), 'id');
3040 $capabilities = array_values($capabilities);
3041 $roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']);
3042 $userids = array_values($testusers);
3043 $userids[] = get_admin()->id;
3045 if (!PHPUNIT_LONGTEST) {
3046 $contexts = array_slice($contexts, 0, 10);
3047 $capabilities = array_slice($capabilities, 0, 5);
3048 $userids = array_slice($userids, 0, 5);
3051 foreach ($userids as $userid) { // No guest or deleted.
3052 // Each user gets 0-10 random roles.
3053 $rcount = rand(0, 10);
3054 for ($j=0; $j<$rcount; $j++) {
3055 $roleid = $roles[rand(0, count($roles)-1)];
3056 $contextid = $contexts[rand(0, count($contexts)-1)]->id;
3057 role_assign($roleid, $userid, $contextid);
3061 $permissions = array(CAP_ALLOW, CAP_PREVENT, CAP_INHERIT, CAP_PREVENT);
3062 $maxoverrides = count($contexts)*10;
3063 for ($j=0; $j<$maxoverrides; $j++) {
3064 $roleid = $roles[rand(0, count($roles)-1)];
3065 $contextid = $contexts[rand(0, count($contexts)-1)]->id;
3066 $permission = $permissions[rand(0, count($permissions)-1)];
3067 $capname = $capabilities[rand(0, count($capabilities)-1)]->name;
3068 assign_capability($capname, $permission, $roleid, $contextid, true);
3070 unset($permissions);
3071 unset($roles);
3073 accesslib_clear_all_caches_for_unit_testing(); // must be done after assign_capability().
3075 // Test time - let's set up some real user, just in case the logic for USER affects the others...
3076 $USER = $DB->get_record('user', array('id'=>$testusers[3]));
3077 load_all_capabilities();
3079 $userids[] = $CFG->siteguest;
3080 $userids[] = 0; // Not-logged-in user.
3081 $userids[] = -1; // Non-existent user.
3083 foreach ($contexts as $crecord) {
3084 $context = context::instance_by_id($crecord->id);
3085 if ($coursecontext = $context->get_course_context(false)) {
3086 $enrolled = get_enrolled_users($context);
3087 } else {
3088 $enrolled = array();
3090 foreach ($capabilities as $cap) {
3091 $allowed = get_users_by_capability($context, $cap->name, 'u.id, u.username');
3092 if ($enrolled) {
3093 $enrolledwithcap = get_enrolled_users($context, $cap->name);
3094 } else {
3095 $enrolledwithcap = array();
3097 foreach ($userids as $userid) {
3098 if ($userid == 0 or isguestuser($userid)) {
3099 if ($userid == 0) {
3100 $CFG->forcelogin = true;
3101 $this->assertFalse(has_capability($cap->name, $context, $userid));
3102 unset($CFG->forcelogin);
3104 if (($cap->captype === 'write') or ($cap->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))) {
3105 $this->assertFalse(has_capability($cap->name, $context, $userid));
3107 $this->assertFalse(isset($allowed[$userid]));
3108 } else {
3109 if (is_siteadmin($userid)) {
3110 $this->assertTrue(has_capability($cap->name, $context, $userid, true));
3112 $hascap = has_capability($cap->name, $context, $userid, false);
3113 $this->assertSame($hascap, isset($allowed[$userid]), "Capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
3114 if (isset($enrolled[$userid])) {
3115 $this->assertSame(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
3121 // Back to nobody.
3122 $USER = new stdClass();
3123 $USER->id = 0;
3124 unset($contexts);
3125 unset($userids);
3126 unset($capabilities);
3128 // Now let's do all the remaining tests that break our carefully prepared fake site.
3131 // Test $context->mark_dirty() method.
3133 $DB->delete_records('cache_flags', array());
3134 accesslib_clear_all_caches(false);
3135 $systemcontext->mark_dirty();
3136 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
3137 $this->assertTrue(isset($dirty[$systemcontext->path]));
3138 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$systemcontext->path]));
3141 // Test $context->reload_if_dirty() method.
3143 $DB->delete_records('cache_flags', array());
3144 accesslib_clear_all_caches(false);
3145 load_all_capabilities();
3146 $context = context_course::instance($testcourses[2]);
3147 $page = $DB->get_record('page', array('course'=>$testcourses[2]));
3148 $pagecm = get_coursemodule_from_instance('page', $page->id);
3149 $pagecontext = context_module::instance($pagecm->id);
3151 $context->mark_dirty();
3152 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
3153 $USER->access['test'] = true;
3154 $context->reload_if_dirty();
3155 $this->assertFalse(isset($USER->access['test']));
3157 $context->mark_dirty();
3158 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
3159 $USER->access['test'] = true;
3160 $pagecontext->reload_if_dirty();
3161 $this->assertFalse(isset($USER->access['test']));
3164 // Test context_helper::build_all_paths() method.
3166 $oldcontexts = $DB->get_records('context', array(), 'id');
3167 $DB->set_field_select('context', 'path', null, "contextlevel <> ".CONTEXT_SYSTEM);
3168 $DB->set_field_select('context', 'depth', 0, "contextlevel <> ".CONTEXT_SYSTEM);
3169 context_helper::build_all_paths();
3170 $newcontexts = $DB->get_records('context', array(), 'id');
3171 $this->assertEquals($oldcontexts, $newcontexts);
3172 unset($oldcontexts);
3173 unset($newcontexts);
3176 // Test $context->reset_paths() method.
3178 $context = context_course::instance($testcourses[2]);
3179 $children = $context->get_child_contexts();
3180 $context->reset_paths(false);
3181 $this->assertNull($DB->get_field('context', 'path', array('id'=>$context->id)));
3182 $this->assertEquals(0, $DB->get_field('context', 'depth', array('id'=>$context->id)));
3183 foreach ($children as $child) {
3184 $this->assertNull($DB->get_field('context', 'path', array('id'=>$child->id)));
3185 $this->assertEquals(0, $DB->get_field('context', 'depth', array('id'=>$child->id)));
3187 $this->assertEquals(count($children)+1, $DB->count_records('context', array('depth'=>0)));
3188 $this->assertEquals(count($children)+1, $DB->count_records('context', array('path'=>null)));
3190 $context = context_course::instance($testcourses[2]);
3191 $context->reset_paths(true);
3192 $context = context_course::instance($testcourses[2]);
3193 $this->assertSame($context->path, $DB->get_field('context', 'path', array('id'=>$context->id)));
3194 $this->assertSame($context->depth, $DB->get_field('context', 'depth', array('id'=>$context->id)));
3195 $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
3196 $this->assertEquals(0, $DB->count_records('context', array('path'=>null)));
3199 // Test $context->update_moved() method.
3201 accesslib_clear_all_caches(false);
3202 $DB->delete_records('cache_flags', array());
3203 $course = $DB->get_record('course', array('id'=>$testcourses[0]));
3204 $context = context_course::instance($course->id);
3205 $oldpath = $context->path;
3206 $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
3207 $categorycontext = context_coursecat::instance($miscid);
3208 $course->category = $miscid;
3209 $DB->update_record('course', $course);
3210 $context->update_moved($categorycontext);
3212 $context = context_course::instance($course->id);
3213 $this->assertEquals($categorycontext, $context->get_parent_context());
3214 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
3215 $this->assertTrue(isset($dirty[$oldpath]));
3216 $this->assertTrue(isset($dirty[$context->path]));
3219 // Test $context->delete_content() method.
3221 context_helper::reset_caches();
3222 $context = context_module::instance($testpages[3]);
3223 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
3224 $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
3225 $context->delete_content();
3226 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
3227 $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
3230 // Test $context->delete() method.
3232 context_helper::reset_caches();
3233 $context = context_module::instance($testpages[4]);
3234 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
3235 $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
3236 $bi = $DB->get_record('block_instances', array('parentcontextid'=>$context->id));
3237 $bicontext = context_block::instance($bi->id);
3238 $DB->delete_records('cache_flags', array());
3239 $context->delete(); // Should delete also linked blocks.
3240 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
3241 $this->assertTrue(isset($dirty[$context->path]));
3242 $this->assertFalse($DB->record_exists('context', array('id'=>$context->id)));
3243 $this->assertFalse($DB->record_exists('context', array('id'=>$bicontext->id)));
3244 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_MODULE, 'instanceid'=>$testpages[4])));
3245 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK, 'instanceid'=>$bi->id)));
3246 $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
3247 context_module::instance($testpages[4]);
3250 // Test context_helper::delete_instance() method.
3252 context_helper::reset_caches();
3253 $lastcourse = array_pop($testcourses);
3254 $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
3255 $coursecontext = context_course::instance($lastcourse);
3256 $this->assertEquals(1, context_inspection::test_context_cache_size());
3257 $this->assertNotEquals(CONTEXT_COURSE, $coursecontext->instanceid);
3258 $DB->delete_records('cache_flags', array());
3259 context_helper::delete_instance(CONTEXT_COURSE, $lastcourse);
3260 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
3261 $this->assertTrue(isset($dirty[$coursecontext->path]));
3262 $this->assertEquals(0, context_inspection::test_context_cache_size());
3263 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
3264 context_course::instance($lastcourse);
3267 // Test context_helper::create_instances() method.
3269 $prevcount = $DB->count_records('context');
3270 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
3271 context_helper::create_instances(null, true);
3272 $this->assertSame($DB->count_records('context'), $prevcount);
3273 $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
3274 $this->assertEquals(0, $DB->count_records('context', array('path'=>null)));
3276 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
3277 $DB->delete_records('block_instances', array());
3278 $prevcount = $DB->count_records('context');
3279 $DB->delete_records_select('context', 'contextlevel <> '.CONTEXT_SYSTEM);
3280 context_helper::create_instances(null, true);
3281 $this->assertSame($prevcount, $DB->count_records('context'));
3282 $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
3283 $this->assertEquals(0, $DB->count_records('context', array('path'=>null)));
3285 // Test context_helper::cleanup_instances() method.
3287 $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
3288 $DB->delete_records('course', array('id'=>$lastcourse));
3289 $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
3290 $DB->delete_records('course_categories', array('id'=>$lastcategory));
3291 $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
3292 $DB->delete_records('user', array('id'=>$lastuser));
3293 $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
3294 $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
3295 context_helper::cleanup_instances();
3296 $count = 1; // System.
3297 $count += $DB->count_records('user', array('deleted'=>0));
3298 $count += $DB->count_records('course_categories');
3299 $count += $DB->count_records('course');
3300 $count += $DB->count_records('course_modules');
3301 $count += $DB->count_records('block_instances');
3302 $this->assertEquals($count, $DB->count_records('context'));
3305 // Test context cache size restrictions.
3307 $testusers= array();
3308 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
3309 $user = $generator->create_user();
3310 $testusers[$i] = $user->id;
3312 context_helper::create_instances(null, true);
3313 context_helper::reset_caches();
3314 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
3315 context_user::instance($testusers[$i]);
3316 if ($i == CONTEXT_CACHE_MAX_SIZE - 1) {
3317 $this->assertEquals(CONTEXT_CACHE_MAX_SIZE, context_inspection::test_context_cache_size());
3318 } else if ($i == CONTEXT_CACHE_MAX_SIZE) {
3319 // Once the limit is reached roughly 1/3 of records should be removed from cache.
3320 $this->assertEquals((int)ceil(CONTEXT_CACHE_MAX_SIZE * (2/3) + 101), context_inspection::test_context_cache_size());
3323 // We keep the first 100 cached.
3324 $prevsize = context_inspection::test_context_cache_size();
3325 for ($i=0; $i<100; $i++) {
3326 context_user::instance($testusers[$i]);
3327 $this->assertEquals($prevsize, context_inspection::test_context_cache_size());
3329 context_user::instance($testusers[102]);
3330 $this->assertEquals($prevsize+1, context_inspection::test_context_cache_size());
3331 unset($testusers);
3335 // Test basic test of legacy functions.
3336 // Note: watch out, the fake site might be pretty borked already.
3338 $this->assertEquals(get_system_context(), context_system::instance());
3339 $this->assertDebuggingCalled('get_system_context() is deprecated, please use context_system::instance() instead.', DEBUG_DEVELOPER);
3341 foreach ($DB->get_records('context') as $contextid => $record) {
3342 $context = context::instance_by_id($contextid);
3343 $this->assertEquals($context, get_context_instance($record->contextlevel, $record->instanceid));
3344 $this->assertDebuggingCalled('get_context_instance() is deprecated, please use context_xxxx::instance() instead.', DEBUG_DEVELOPER);
3347 // Make sure a debugging is thrown.
3348 get_context_instance($record->contextlevel, $record->instanceid);
3349 $this->assertDebuggingCalled('get_context_instance() is deprecated, please use context_xxxx::instance() instead.', DEBUG_DEVELOPER);
3350 get_system_context();
3351 $this->assertDebuggingCalled('get_system_context() is deprecated, please use context_system::instance() instead.', DEBUG_DEVELOPER);
3355 * Test updating of role capabilities during upgrade
3357 public function test_update_capabilities() {
3358 global $DB, $SITE;
3360 $this->resetAfterTest(true);
3362 $froncontext = context_course::instance($SITE->id);
3363 $student = $DB->get_record('role', array('archetype'=>'student'));
3364 $teacher = $DB->get_record('role', array('archetype'=>'teacher'));
3366 $existingcaps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
3368 $this->assertFalse(isset($existingcaps['moodle/site:restore'])); // Moved to new 'moodle/restore:restorecourse'.
3369 $this->assertTrue(isset($existingcaps['moodle/restore:restorecourse'])); // New cap from 'moodle/site:restore'.
3370 $this->assertTrue(isset($existingcaps['moodle/site:sendmessage'])); // New capability.
3371 $this->assertTrue(isset($existingcaps['moodle/backup:backupcourse']));
3372 $this->assertTrue(isset($existingcaps['moodle/backup:backupsection'])); // Cloned from 'moodle/backup:backupcourse'.
3373 $this->assertTrue(isset($existingcaps['moodle/site:approvecourse'])); // Updated bitmask.
3374 $this->assertTrue(isset($existingcaps['moodle/course:manageactivities']));
3375 $this->assertTrue(isset($existingcaps['mod/page:addinstance'])); // Cloned from core 'moodle/course:manageactivities'.
3377 // Fake state before upgrade.
3378 $DB->set_field('capabilities', 'name', 'moodle/site:restore', array('name'=>'moodle/restore:restorecourse'));
3379 $DB->set_field('role_capabilities', 'capability', 'moodle/site:restore', array('capability'=>'moodle/restore:restorecourse'));
3380 assign_capability('moodle/site:restore', CAP_PROHIBIT, $teacher->id, $froncontext->id, true);
3381 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/site:restore', 'roleid'=>$teacher->id), 'contextid, permission', 'contextid, permission'));
3383 $DB->delete_records('role_capabilities', array('capability'=>'moodle/site:sendmessage'));
3384 $DB->delete_records('capabilities', array('name'=>'moodle/site:sendmessage'));
3386 $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupsection'));
3387 $DB->delete_records('capabilities', array('name'=>'moodle/backup:backupsection'));
3388 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $froncontext->id, true);
3389 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $teacher->id, $froncontext->id, true);
3391 $DB->set_field('capabilities', 'riskbitmask', 0, array('name'=>'moodle/site:approvecourse'));
3393 $DB->delete_records('role_capabilities', array('capability'=>'mod/page:addinstance'));
3394 $DB->delete_records('capabilities', array('name'=>'mod/page:addinstance'));
3395 assign_capability('moodle/course:manageactivities', CAP_PROHIBIT, $student->id, $froncontext->id, true);
3396 assign_capability('moodle/course:manageactivities', CAP_ALLOW, $teacher->id, $froncontext->id, true);
3398 // Execute core.
3399 update_capabilities('moodle');
3401 // Only core should be upgraded.
3402 $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
3404 $this->assertFalse(isset($existingcaps['moodle/site:restore']));
3405 $this->assertTrue(isset($caps['moodle/restore:restorecourse']));
3406 $this->assertEquals($existingcaps['moodle/restore:restorecourse'], $caps['moodle/restore:restorecourse']);
3407 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/restore:restorecourse', 'roleid'=>$teacher->id), 'contextid, permission', 'contextid, permission'));
3408 $this->assertEquals($perms1, $perms2);
3410 $this->assertTrue(isset($caps['moodle/site:sendmessage']));
3411 $this->assertEquals($existingcaps['moodle/site:sendmessage'], $caps['moodle/site:sendmessage']);
3413 $this->assertTrue(isset($caps['moodle/backup:backupsection']));
3414 $this->assertEquals($existingcaps['moodle/backup:backupsection'], $caps['moodle/backup:backupsection']);
3415 $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/backup:backupcourse', 'moodle/backup:backupsection'));
3416 foreach ($roles as $role) {
3417 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
3418 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupsection', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
3419 $this->assertEquals($perms1, $perms2);
3422 $this->assertTrue(isset($caps['moodle/site:approvecourse']));
3423 $this->assertEquals($existingcaps['moodle/site:approvecourse'], $caps['moodle/site:approvecourse']);
3425 $this->assertFalse(isset($caps['mod/page:addinstance']));
3427 // Execute plugin.
3428 update_capabilities('mod_page');
3429 $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
3430 $this->assertTrue(isset($caps['mod/page:addinstance']));
3431 $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/course:manageactivities', 'mod/page:addinstance'));
3432 foreach ($roles as $role) {
3433 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/course:manageactivities', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
3434 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'mod/page:addinstance', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
3436 $this->assertEquals($perms1, $perms2);
3440 * Tests reset_role_capabilities function.
3442 public function test_reset_role_capabilities() {
3443 global $DB;
3444 $this->resetAfterTest(true);
3445 $generator = $this->getDataGenerator();
3447 // Create test course and user, enrol one in the other.
3448 $course = $generator->create_course();
3449 $user = $generator->create_user();
3450 $roleid = $DB->get_field('role', 'id', array('shortname' => 'student'), MUST_EXIST);
3451 $generator->enrol_user($user->id, $course->id, $roleid);
3453 // Change student role so it DOES have 'mod/forum:addinstance'.
3454 $systemcontext = context_system::instance();
3455 assign_capability('mod/forum:addinstance', CAP_ALLOW, $roleid, $systemcontext->id);
3457 // Override course so it does NOT allow students 'mod/forum:viewdiscussion'.
3458 $coursecontext = context_course::instance($course->id);
3459 assign_capability('mod/forum:viewdiscussion', CAP_PREVENT, $roleid, $coursecontext->id);
3461 // Check expected capabilities so far.
3462 $this->assertTrue(has_capability('mod/forum:addinstance', $coursecontext, $user));
3463 $this->assertFalse(has_capability('mod/forum:viewdiscussion', $coursecontext, $user));
3465 // Oops, allowing student to add forums was a mistake, let's reset the role.
3466 reset_role_capabilities($roleid);
3468 // Check new expected capabilities - role capabilities should have been reset,
3469 // while the override at course level should remain.
3470 $this->assertFalse(has_capability('mod/forum:addinstance', $coursecontext, $user));
3471 $this->assertFalse(has_capability('mod/forum:viewdiscussion', $coursecontext, $user));
3475 * Tests count_role_users function.
3477 public function test_count_role_users() {
3478 global $DB;
3479 $this->resetAfterTest(true);
3480 $generator = self::getDataGenerator();
3481 // Create a course in a category, and some users.
3482 $category = $generator->create_category();
3483 $course = $generator->create_course(array('category' => $category->id));
3484 $user1 = $generator->create_user();
3485 $user2 = $generator->create_user();
3486 $user3 = $generator->create_user();
3487 $user4 = $generator->create_user();
3488 $user5 = $generator->create_user();
3489 $roleid1 = $DB->get_field('role', 'id', array('shortname' => 'manager'), MUST_EXIST);
3490 $roleid2 = $DB->get_field('role', 'id', array('shortname' => 'coursecreator'), MUST_EXIST);
3491 // Enrol two users as managers onto the course, and 1 onto the category.
3492 $generator->enrol_user($user1->id, $course->id, $roleid1);
3493 $generator->enrol_user($user2->id, $course->id, $roleid1);
3494 $generator->role_assign($roleid1, $user3->id, context_coursecat::instance($category->id));
3495 // Enrol 1 user as a coursecreator onto the course, and another onto the category.
3496 // This is to ensure we do not count users with roles that are not specified.
3497 $generator->enrol_user($user4->id, $course->id, $roleid2);
3498 $generator->role_assign($roleid2, $user5->id, context_coursecat::instance($category->id));
3499 // Check that the correct users are found on the course.
3500 $this->assertEquals(2, count_role_users($roleid1, context_course::instance($course->id), false));
3501 $this->assertEquals(3, count_role_users($roleid1, context_course::instance($course->id), true));
3502 // Check for the category.
3503 $this->assertEquals(1, count_role_users($roleid1, context_coursecat::instance($category->id), false));
3504 $this->assertEquals(1, count_role_users($roleid1, context_coursecat::instance($category->id), true));
3505 // Have a user with the same role at both the category and course level.
3506 $generator->role_assign($roleid1, $user1->id, context_coursecat::instance($category->id));
3507 // The course level checks should remain the same.
3508 $this->assertEquals(2, count_role_users($roleid1, context_course::instance($course->id), false));
3509 $this->assertEquals(3, count_role_users($roleid1, context_course::instance($course->id), true));
3513 * Test updating of role capabilities during upgrade
3514 * @return void
3516 public function test_get_with_capability_sql() {
3517 global $DB;
3519 $this->resetAfterTest();
3521 $course = $this->getDataGenerator()->create_course();
3522 $coursecontext = context_course::instance($course->id);
3523 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST);
3524 $teacher = $this->getDataGenerator()->create_user();
3525 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
3526 $student = $this->getDataGenerator()->create_user();
3527 $guest = $DB->get_record('user', array('username' => 'guest'));
3529 role_assign($teacherrole->id, $teacher->id, $coursecontext);
3530 role_assign($studentrole->id, $student->id, $coursecontext);
3531 $admin = $DB->get_record('user', array('username' => 'admin'));
3533 // Note: Here are used default capabilities, the full test is in permission evaluation below,
3534 // use two capabilities that teacher has and one does not, none of them should be allowed for not-logged-in user.
3535 $this->assertTrue($DB->record_exists('capabilities', array('name' => 'moodle/backup:backupcourse')));
3536 $this->assertTrue($DB->record_exists('capabilities', array('name' => 'moodle/site:approvecourse')));
3538 list($sql, $params) = get_with_capability_sql($coursecontext, 'moodle/backup:backupcourse');
3539 $users = $DB->get_records_sql($sql, $params);
3541 $this->assertTrue(array_key_exists($teacher->id, $users));
3542 $this->assertFalse(array_key_exists($admin->id, $users));
3543 $this->assertFalse(array_key_exists($student->id, $users));
3544 $this->assertFalse(array_key_exists($guest->id, $users));
3546 list($sql, $params) = get_with_capability_sql($coursecontext, 'moodle/site:approvecourse');
3547 $users = $DB->get_records_sql($sql, $params);
3549 $this->assertFalse(array_key_exists($teacher->id, $users));
3550 $this->assertFalse(array_key_exists($admin->id, $users));
3551 $this->assertFalse(array_key_exists($student->id, $users));
3552 $this->assertFalse(array_key_exists($guest->id, $users));
3554 // Test role override.
3555 assign_capability('moodle/site:backupcourse', CAP_PROHIBIT, $teacherrole->id, $coursecontext, true);
3556 assign_capability('moodle/site:backupcourse', CAP_ALLOW, $studentrole->id, $coursecontext, true);
3558 list($sql, $params) = get_with_capability_sql($coursecontext, 'moodle/site:backupcourse');
3559 $users = $DB->get_records_sql($sql, $params);
3561 $this->assertFalse(array_key_exists($teacher->id, $users));
3562 $this->assertFalse(array_key_exists($admin->id, $users));
3563 $this->assertTrue(array_key_exists($student->id, $users));
3564 $this->assertFalse(array_key_exists($guest->id, $users));
3568 * Test the get_profile_roles() function.
3570 public function test_get_profile_roles() {
3571 global $DB;
3572 $this->resetAfterTest();
3574 $course = $this->getDataGenerator()->create_course();
3575 $coursecontext = context_course::instance($course->id);
3577 // Assign a student role.
3578 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST);
3579 $user1 = $this->getDataGenerator()->create_user();
3580 role_assign($studentrole->id, $user1->id, $coursecontext);
3582 // Assign an editing teacher role.
3583 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST);
3584 $user2 = $this->getDataGenerator()->create_user();
3585 role_assign($teacherrole->id, $user2->id, $coursecontext);
3587 // Create a custom role that can be assigned at course level, but don't assign it yet.
3588 create_role('Custom role', 'customrole', 'Custom course role');
3589 $customrole = $DB->get_record('role', array('shortname' => 'customrole'), '*', MUST_EXIST);
3590 set_role_contextlevels($customrole->id, [CONTEXT_COURSE]);
3591 core_role_set_assign_allowed($teacherrole->id, $customrole->id); // Allow teacher to assign the role in the course.
3593 // Set the site policy 'profileroles' to show student, teacher and non-editing teacher roles (i.e. not the custom role).
3594 $neteacherrole = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
3595 set_config('profileroles', "{$studentrole->id}, {$teacherrole->id}, {$neteacherrole->id}");
3597 // A student in the course (given they can't assign roles) should see those roles which are:
3598 // - listed in the 'profileroles' site policy AND
3599 // - are assigned in the course context (or parent contexts).
3600 // In this case, the non-editing teacher role is not assigned and should not be returned.
3601 $expected = [
3602 $teacherrole->id => (object) [
3603 'id' => $teacherrole->id,
3604 'name' => '',
3605 'shortname' => $teacherrole->shortname,
3606 'sortorder' => $teacherrole->sortorder,
3607 'coursealias' => null
3609 $studentrole->id => (object) [
3610 'id' => $studentrole->id,
3611 'name' => '',
3612 'shortname' => $studentrole->shortname,
3613 'sortorder' => $studentrole->sortorder,
3614 'coursealias' => null
3617 $this->setUser($user1);
3618 $this->assertEquals($expected, get_profile_roles($coursecontext));
3620 // An editing teacher should also see only 2 roles at this stage as only 2 roles are assigned: 'teacher' and 'student'.
3621 $this->setUser($user2);
3622 $this->assertEquals($expected, get_profile_roles($coursecontext));
3624 // Assign a custom role in the course.
3625 $user3 = $this->getDataGenerator()->create_user();
3626 role_assign($customrole->id, $user3->id, $coursecontext);
3628 // Confirm that the teacher can see the custom role now that it's assigned.
3629 $expectedteacher = [
3630 $teacherrole->id => (object) [
3631 'id' => $teacherrole->id,
3632 'name' => '',
3633 'shortname' => $teacherrole->shortname,
3634 'sortorder' => $teacherrole->sortorder,
3635 'coursealias' => null
3637 $studentrole->id => (object) [
3638 'id' => $studentrole->id,
3639 'name' => '',
3640 'shortname' => $studentrole->shortname,
3641 'sortorder' => $studentrole->sortorder,
3642 'coursealias' => null
3644 $customrole->id => (object) [
3645 'id' => $customrole->id,
3646 'name' => 'Custom role',
3647 'shortname' => $customrole->shortname,
3648 'sortorder' => $customrole->sortorder,
3649 'coursealias' => null
3652 $this->setUser($user2);
3653 $this->assertEquals($expectedteacher, get_profile_roles($coursecontext));
3655 // And that the student can't, because the role isn't included in the 'profileroles' site policy.
3656 $expectedstudent = [
3657 $teacherrole->id => (object) [
3658 'id' => $teacherrole->id,
3659 'name' => '',
3660 'shortname' => $teacherrole->shortname,
3661 'sortorder' => $teacherrole->sortorder,
3662 'coursealias' => null
3664 $studentrole->id => (object) [
3665 'id' => $studentrole->id,
3666 'name' => '',
3667 'shortname' => $studentrole->shortname,
3668 'sortorder' => $studentrole->sortorder,
3669 'coursealias' => null
3672 $this->setUser($user1);
3673 $this->assertEquals($expectedstudent, get_profile_roles($coursecontext));
3675 // If we have no roles listed in the site policy, the teacher should be able to see the assigned roles.
3676 $expectedteacher = [
3677 $studentrole->id => (object) [
3678 'id' => $studentrole->id,
3679 'name' => '',
3680 'shortname' => $studentrole->shortname,
3681 'sortorder' => $studentrole->sortorder,
3682 'coursealias' => null
3684 $customrole->id => (object) [
3685 'id' => $customrole->id,
3686 'name' => 'Custom role',
3687 'shortname' => $customrole->shortname,
3688 'sortorder' => $customrole->sortorder,
3689 'coursealias' => null
3691 $teacherrole->id => (object) [
3692 'id' => $teacherrole->id,
3693 'name' => '',
3694 'shortname' => $teacherrole->shortname,
3695 'sortorder' => $teacherrole->sortorder,
3696 'coursealias' => null
3699 set_config('profileroles', "");
3700 $this->setUser($user2);
3701 $this->assertEquals($expectedteacher, get_profile_roles($coursecontext));
3706 * Context caching fixture
3708 class context_inspection extends context_helper {
3709 public static function test_context_cache_size() {
3710 return self::$cache_count;