2 // This file is part of Moodle - http://moodle.org/
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 * Full functional accesslib test.
22 * @copyright 2011 Petr Skoda {@link http://skodak.org}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') ||
die();
30 * Functional test for accesslib.php
32 * Note: execution may take many minutes especially on slower servers.
34 class core_accesslib_testcase
extends advanced_testcase
{
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);
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
);
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');
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
));
81 * Test getting of role access
83 public function test_get_role_access() {
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() {
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() {
121 $this->resetAfterTest();
123 $users = $DB->get_records('user');
125 foreach ($users as $user) {
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));
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() {
163 $this->resetAfterTest();
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
,
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 $this->assertFalse(has_capability($capability, $coursecontext, $user->id
));
201 // Again, we seed the cache first by checking initial enrolment,
202 // and then we test the actual capability.
203 $this->assertTrue(is_enrolled($coursecontext, $user, '', true));
204 $this->assertFalse(is_enrolled($coursecontext, $user, $capability));
208 * Test logged in test.
210 public function test_isloggedin() {
213 $this->resetAfterTest();
216 $this->assertFalse(isloggedin());
218 $this->assertTrue(isloggedin());
222 * Test guest user test.
224 public function test_isguestuser() {
227 $this->resetAfterTest();
229 $guest = $DB->get_record('user', array('username'=>'guest'));
231 $this->assertFalse(isguestuser());
232 $this->setAdminUser();
233 $this->assertFalse(isguestuser());
234 $this->assertTrue(isguestuser($guest));
235 $this->assertTrue(isguestuser($guest->id
));
236 $this->setUser($guest);
237 $this->assertTrue(isguestuser());
239 $users = $DB->get_records('user');
240 foreach ($users as $user) {
241 if ($user->username
=== 'guest') {
244 $this->assertFalse(isguestuser($user));
249 * Test capability riskiness.
251 public function test_is_safe_capability() {
253 // Note: there is not much to test, just make sure no notices are throw for the most dangerous cap.
254 $capability = $DB->get_record('capabilities', array('name'=>'moodle/site:config'), '*', MUST_EXIST
);
255 $this->assertFalse(is_safe_capability($capability));
259 * Test context fetching.
261 public function test_get_context_info_array() {
262 $this->resetAfterTest();
264 $syscontext = context_system
::instance();
265 $user = $this->getDataGenerator()->create_user();
266 $usercontext = context_user
::instance($user->id
);
267 $course = $this->getDataGenerator()->create_course();
268 $catcontext = context_coursecat
::instance($course->category
);
269 $coursecontext = context_course
::instance($course->id
);
270 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id
));
271 $modcontext = context_module
::instance($page->cmid
);
272 $cm = get_coursemodule_from_instance('page', $page->id
);
273 $block1 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$coursecontext->id
));
274 $block1context = context_block
::instance($block1->id
);
275 $block2 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$modcontext->id
));
276 $block2context = context_block
::instance($block2->id
);
278 $result = get_context_info_array($syscontext->id
);
279 $this->assertCount(3, $result);
280 $this->assertEquals($syscontext, $result[0]);
281 $this->assertNull($result[1]);
282 $this->assertNull($result[2]);
284 $result = get_context_info_array($usercontext->id
);
285 $this->assertCount(3, $result);
286 $this->assertEquals($usercontext, $result[0]);
287 $this->assertNull($result[1]);
288 $this->assertNull($result[2]);
290 $result = get_context_info_array($catcontext->id
);
291 $this->assertCount(3, $result);
292 $this->assertEquals($catcontext, $result[0]);
293 $this->assertNull($result[1]);
294 $this->assertNull($result[2]);
296 $result = get_context_info_array($coursecontext->id
);
297 $this->assertCount(3, $result);
298 $this->assertEquals($coursecontext, $result[0]);
299 $this->assertEquals($course->id
, $result[1]->id
);
300 $this->assertSame($course->shortname
, $result[1]->shortname
);
301 $this->assertNull($result[2]);
303 $result = get_context_info_array($block1context->id
);
304 $this->assertCount(3, $result);
305 $this->assertEquals($block1context, $result[0]);
306 $this->assertEquals($course->id
, $result[1]->id
);
307 $this->assertEquals($course->shortname
, $result[1]->shortname
);
308 $this->assertNull($result[2]);
310 $result = get_context_info_array($modcontext->id
);
311 $this->assertCount(3, $result);
312 $this->assertEquals($modcontext, $result[0]);
313 $this->assertEquals($course->id
, $result[1]->id
);
314 $this->assertSame($course->shortname
, $result[1]->shortname
);
315 $this->assertEquals($cm->id
, $result[2]->id
);
317 $result = get_context_info_array($block2context->id
);
318 $this->assertCount(3, $result);
319 $this->assertEquals($block2context, $result[0]);
320 $this->assertEquals($course->id
, $result[1]->id
);
321 $this->assertSame($course->shortname
, $result[1]->shortname
);
322 $this->assertEquals($cm->id
, $result[2]->id
);
326 * Test looking for course contacts.
328 public function test_has_coursecontact_role() {
331 $this->resetAfterTest();
333 $users = $DB->get_records('user');
335 // Nobody is expected to have any course level roles.
336 $this->assertNotEmpty($CFG->coursecontact
);
337 foreach ($users as $user) {
338 $this->assertFalse(has_coursecontact_role($user->id
));
341 $user = $this->getDataGenerator()->create_user();
342 $course = $this->getDataGenerator()->create_course();
343 role_assign($CFG->coursecontact
, $user->id
, context_course
::instance($course->id
));
344 $this->assertTrue(has_coursecontact_role($user->id
));
348 * Test creation of roles.
350 public function test_create_role() {
353 $this->resetAfterTest();
355 $id = create_role('New student role', 'student2', 'New student description', 'student');
356 $role = $DB->get_record('role', array('id'=>$id));
358 $this->assertNotEmpty($role);
359 $this->assertSame('New student role', $role->name
);
360 $this->assertSame('student2', $role->shortname
);
361 $this->assertSame('New student description', $role->description
);
362 $this->assertSame('student', $role->archetype
);
366 * Test adding of capabilities to roles.
368 public function test_assign_capability() {
371 $this->resetAfterTest();
373 $user = $this->getDataGenerator()->create_user();
374 $syscontext = context_system
::instance();
375 $frontcontext = context_course
::instance(SITEID
);
376 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST
);
377 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // Any capability assigned to student by default.
378 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id
, 'roleid'=>$student->id
, 'capability'=>'moodle/backup:backupcourse')));
379 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id
, 'roleid'=>$student->id
, 'capability'=>'moodle/backup:backupcourse')));
381 $this->setUser($user);
382 $result = assign_capability('moodle/backup:backupcourse', CAP_ALLOW
, $student->id
, $frontcontext->id
);
383 $this->assertTrue($result);
384 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id
, 'roleid'=>$student->id
, 'capability'=>'moodle/backup:backupcourse'));
385 $this->assertNotEmpty($permission);
386 $this->assertEquals(CAP_ALLOW
, $permission->permission
);
387 $this->assertEquals($user->id
, $permission->modifierid
);
390 $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT
, $student->id
, $frontcontext->id
, false);
391 $this->assertTrue($result);
392 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id
, 'roleid'=>$student->id
, 'capability'=>'moodle/backup:backupcourse'));
393 $this->assertNotEmpty($permission);
394 $this->assertEquals(CAP_ALLOW
, $permission->permission
);
395 $this->assertEquals($user->id
, $permission->modifierid
);
397 $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT
, $student->id
, $frontcontext->id
, true);
398 $this->assertTrue($result);
399 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id
, 'roleid'=>$student->id
, 'capability'=>'moodle/backup:backupcourse'));
400 $this->assertNotEmpty($permission);
401 $this->assertEquals(CAP_PROHIBIT
, $permission->permission
);
402 $this->assertEquals(0, $permission->modifierid
);
404 $result = assign_capability('moodle/backup:backupcourse', CAP_INHERIT
, $student->id
, $frontcontext->id
);
405 $this->assertTrue($result);
406 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id
, 'roleid'=>$student->id
, 'capability'=>'moodle/backup:backupcourse'));
407 $this->assertEmpty($permission);
409 // Test event trigger.
410 $rolecapabilityevent = \core\event\role_capabilities_updated
::create(array('context' => $syscontext,
411 'objectid' => $student->id
,
412 'other' => array('name' => $student->shortname
)
414 $expectedlegacylog = array(SITEID
, 'role', 'view', 'admin/roles/define.php?action=view&roleid=' . $student->id
,
415 $student->shortname
, '', $user->id
);
416 $rolecapabilityevent->set_legacy_logdata($expectedlegacylog);
417 $rolecapabilityevent->add_record_snapshot('role', $student);
419 $sink = $this->redirectEvents();
420 $rolecapabilityevent->trigger();
421 $events = $sink->get_events();
423 $event = array_pop($events);
425 $this->assertInstanceOf('\core\event\role_capabilities_updated', $event);
426 $expectedurl = new moodle_url('/admin/roles/define.php', array('action' => 'view', 'roleid' => $student->id
));
427 $this->assertEquals($expectedurl, $event->get_url());
428 $this->assertEventLegacyLogData($expectedlegacylog, $event);
429 $this->assertEventContextNotUsed($event);
433 * Test removing of capabilities from roles.
435 public function test_unassign_capability() {
438 $this->resetAfterTest();
440 $syscontext = context_system
::instance();
441 $frontcontext = context_course
::instance(SITEID
);
442 $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST
);
443 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // Any capability assigned to manager by default.
444 assign_capability('moodle/backup:backupcourse', CAP_ALLOW
, $manager->id
, $frontcontext->id
);
446 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id
, 'roleid'=>$manager->id
, 'capability'=>'moodle/backup:backupcourse')));
447 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id
, 'roleid'=>$manager->id
, 'capability'=>'moodle/backup:backupcourse')));
449 $result = unassign_capability('moodle/backup:backupcourse', $manager->id
, $syscontext->id
);
450 $this->assertTrue($result);
451 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id
, 'roleid'=>$manager->id
, 'capability'=>'moodle/backup:backupcourse')));
452 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id
, 'roleid'=>$manager->id
, 'capability'=>'moodle/backup:backupcourse')));
453 unassign_capability('moodle/backup:backupcourse', $manager->id
, $frontcontext);
454 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id
, 'roleid'=>$manager->id
, 'capability'=>'moodle/backup:backupcourse')));
456 assign_capability('moodle/backup:backupcourse', CAP_ALLOW
, $manager->id
, $syscontext->id
);
457 assign_capability('moodle/backup:backupcourse', CAP_ALLOW
, $manager->id
, $frontcontext->id
);
458 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id
, 'roleid'=>$manager->id
, 'capability'=>'moodle/backup:backupcourse')));
460 $result = unassign_capability('moodle/backup:backupcourse', $manager->id
);
461 $this->assertTrue($result);
462 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id
, 'roleid'=>$manager->id
, 'capability'=>'moodle/backup:backupcourse')));
463 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id
, 'roleid'=>$manager->id
, 'capability'=>'moodle/backup:backupcourse')));
467 * Test role assigning.
469 public function test_role_assign() {
472 $this->resetAfterTest();
474 $user = $this->getDataGenerator()->create_user();
475 $course = $this->getDataGenerator()->create_course();
476 $role = $DB->get_record('role', array('shortname'=>'student'));
479 $context = context_system
::instance();
480 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id
, 'roleid'=>$role->id
, 'contextid'=>$context->id
)));
481 role_assign($role->id
, $user->id
, $context->id
);
482 $ras = $DB->get_record('role_assignments', array('userid'=>$user->id
, 'roleid'=>$role->id
, 'contextid'=>$context->id
));
483 $this->assertNotEmpty($ras);
484 $this->assertSame('', $ras->component
);
485 $this->assertSame('0', $ras->itemid
);
486 $this->assertEquals($USER->id
, $ras->modifierid
);
488 $this->setAdminUser();
489 $context = context_course
::instance($course->id
);
490 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id
, 'roleid'=>$role->id
, 'contextid'=>$context->id
)));
491 role_assign($role->id
, $user->id
, $context->id
, 'enrol_self', 1, 666);
492 $ras = $DB->get_record('role_assignments', array('userid'=>$user->id
, 'roleid'=>$role->id
, 'contextid'=>$context->id
));
493 $this->assertNotEmpty($ras);
494 $this->assertSame('enrol_self', $ras->component
);
495 $this->assertSame('1', $ras->itemid
);
496 $this->assertEquals($USER->id
, $ras->modifierid
);
497 $this->assertEquals(666, $ras->timemodified
);
499 // Test event triggered.
501 $user2 = $this->getDataGenerator()->create_user();
502 $sink = $this->redirectEvents();
503 $raid = role_assign($role->id
, $user2->id
, $context->id
);
504 $events = $sink->get_events();
506 $this->assertCount(1, $events);
508 $this->assertInstanceOf('\core\event\role_assigned', $event);
509 $this->assertSame('role', $event->target
);
510 $this->assertSame('role', $event->objecttable
);
511 $this->assertEquals($role->id
, $event->objectid
);
512 $this->assertEquals($context->id
, $event->contextid
);
513 $this->assertEquals($user2->id
, $event->relateduserid
);
514 $this->assertCount(3, $event->other
);
515 $this->assertEquals($raid, $event->other
['id']);
516 $this->assertSame('', $event->other
['component']);
517 $this->assertEquals(0, $event->other
['itemid']);
518 $this->assertInstanceOf('moodle_url', $event->get_url());
519 $this->assertSame('role_assigned', $event::get_legacy_eventname());
520 $roles = get_all_roles();
521 $rolenames = role_fix_names($roles, $context, ROLENAME_ORIGINAL
, true);
522 $expectedlegacylog = array($course->id
, 'role', 'assign',
523 'admin/roles/assign.php?contextid='.$context->id
.'&roleid='.$role->id
, $rolenames[$role->id
], '', $USER->id
);
524 $this->assertEventLegacyLogData($expectedlegacylog, $event);
528 * Test role unassigning.
530 public function test_role_unassign() {
533 $this->resetAfterTest();
535 $user = $this->getDataGenerator()->create_user();
536 $course = $this->getDataGenerator()->create_course();
537 $role = $DB->get_record('role', array('shortname'=>'student'));
539 $context = context_course
::instance($course->id
);
540 role_assign($role->id
, $user->id
, $context->id
);
541 $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id
, 'roleid'=>$role->id
, 'contextid'=>$context->id
)));
542 role_unassign($role->id
, $user->id
, $context->id
);
543 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id
, 'roleid'=>$role->id
, 'contextid'=>$context->id
)));
545 role_assign($role->id
, $user->id
, $context->id
, 'enrol_self', 1);
546 $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id
, 'roleid'=>$role->id
, 'contextid'=>$context->id
)));
547 role_unassign($role->id
, $user->id
, $context->id
, 'enrol_self', 1);
548 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id
, 'roleid'=>$role->id
, 'contextid'=>$context->id
)));
550 // Test event triggered.
552 role_assign($role->id
, $user->id
, $context->id
);
553 $sink = $this->redirectEvents();
554 role_unassign($role->id
, $user->id
, $context->id
);
555 $events = $sink->get_events();
557 $this->assertCount(1, $events);
559 $this->assertInstanceOf('\core\event\role_unassigned', $event);
560 $this->assertSame('role', $event->target
);
561 $this->assertSame('role', $event->objecttable
);
562 $this->assertEquals($role->id
, $event->objectid
);
563 $this->assertEquals($context->id
, $event->contextid
);
564 $this->assertEquals($user->id
, $event->relateduserid
);
565 $this->assertCount(3, $event->other
);
566 $this->assertSame('', $event->other
['component']);
567 $this->assertEquals(0, $event->other
['itemid']);
568 $this->assertInstanceOf('moodle_url', $event->get_url());
569 $roles = get_all_roles();
570 $rolenames = role_fix_names($roles, $context, ROLENAME_ORIGINAL
, true);
571 $expectedlegacylog = array($course->id
, 'role', 'unassign',
572 'admin/roles/assign.php?contextid='.$context->id
.'&roleid='.$role->id
, $rolenames[$role->id
], '', $USER->id
);
573 $this->assertEventLegacyLogData($expectedlegacylog, $event);
577 * Test role unassigning.
579 public function test_role_unassign_all() {
582 $this->resetAfterTest();
584 $user = $this->getDataGenerator()->create_user();
585 $course = $this->getDataGenerator()->create_course();
586 $role = $DB->get_record('role', array('shortname'=>'student'));
587 $role2 = $DB->get_record('role', array('shortname'=>'teacher'));
588 $syscontext = context_system
::instance();
589 $coursecontext = context_course
::instance($course->id
);
590 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id
));
591 $modcontext = context_module
::instance($page->cmid
);
593 role_assign($role->id
, $user->id
, $syscontext->id
);
594 role_assign($role->id
, $user->id
, $coursecontext->id
, 'enrol_self', 1);
595 $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id
)));
596 role_unassign_all(array('userid'=>$user->id
, 'roleid'=>$role->id
));
597 $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id
)));
599 role_assign($role->id
, $user->id
, $syscontext->id
);
600 role_assign($role->id
, $user->id
, $coursecontext->id
, 'enrol_self', 1);
601 role_assign($role->id
, $user->id
, $modcontext->id
);
602 $this->assertEquals(3, $DB->count_records('role_assignments', array('userid'=>$user->id
)));
603 role_unassign_all(array('userid'=>$user->id
, 'contextid'=>$coursecontext->id
), false);
604 $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id
)));
605 role_unassign_all(array('userid'=>$user->id
, 'contextid'=>$coursecontext->id
), true);
606 $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id
)));
607 role_unassign_all(array('userid'=>$user->id
));
608 $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id
)));
610 role_assign($role->id
, $user->id
, $syscontext->id
);
611 role_assign($role->id
, $user->id
, $coursecontext->id
, 'enrol_self', 1);
612 role_assign($role->id
, $user->id
, $coursecontext->id
);
613 role_assign($role->id
, $user->id
, $modcontext->id
);
614 $this->assertEquals(4, $DB->count_records('role_assignments', array('userid'=>$user->id
)));
615 role_unassign_all(array('userid'=>$user->id
, 'contextid'=>$coursecontext->id
, 'component'=>'enrol_self'), true, true);
616 $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id
)));
618 // Test events triggered.
620 role_assign($role2->id
, $user->id
, $coursecontext->id
);
621 role_assign($role2->id
, $user->id
, $modcontext->id
);
622 $sink = $this->redirectEvents();
623 role_unassign_all(array('userid'=>$user->id
, 'roleid'=>$role2->id
));
624 $events = $sink->get_events();
626 $this->assertCount(2, $events);
627 $this->assertInstanceOf('\core\event\role_unassigned', $events[0]);
628 $this->assertInstanceOf('\core\event\role_unassigned', $events[1]);
634 public function test_get_roles_with_capability() {
637 $this->resetAfterTest();
639 $syscontext = context_system
::instance();
640 $frontcontext = context_course
::instance(SITEID
);
641 $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST
);
642 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST
);
644 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // Any capability is ok.
645 $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse'));
647 $roles = get_roles_with_capability('moodle/backup:backupcourse');
648 $this->assertEquals(array(), $roles);
650 assign_capability('moodle/backup:backupcourse', CAP_ALLOW
, $manager->id
, $syscontext->id
);
651 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT
, $manager->id
, $frontcontext->id
);
652 assign_capability('moodle/backup:backupcourse', CAP_PREVENT
, $teacher->id
, $frontcontext->id
);
654 $roles = get_roles_with_capability('moodle/backup:backupcourse');
655 $this->assertEquals(array($teacher->id
, $manager->id
), array_keys($roles), '', 0, 10, true);
657 $roles = get_roles_with_capability('moodle/backup:backupcourse', CAP_ALLOW
);
658 $this->assertEquals(array($manager->id
), array_keys($roles), '', 0, 10, true);
660 $roles = get_roles_with_capability('moodle/backup:backupcourse', null, $syscontext);
661 $this->assertEquals(array($manager->id
), array_keys($roles), '', 0, 10, true);
665 * Test deleting of roles.
667 public function test_delete_role() {
670 $this->resetAfterTest();
672 $role = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST
);
673 $user = $this->getDataGenerator()->create_user();
674 role_assign($role->id
, $user->id
, context_system
::instance());
675 $course = $this->getDataGenerator()->create_course();
676 $rolename = (object)array('roleid'=>$role->id
, 'name'=>'Man', 'contextid'=>context_course
::instance($course->id
)->id
);
677 $DB->insert_record('role_names', $rolename);
679 $this->assertTrue($DB->record_exists('role_assignments', array('roleid'=>$role->id
)));
680 $this->assertTrue($DB->record_exists('role_capabilities', array('roleid'=>$role->id
)));
681 $this->assertTrue($DB->record_exists('role_names', array('roleid'=>$role->id
)));
682 $this->assertTrue($DB->record_exists('role_context_levels', array('roleid'=>$role->id
)));
683 $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$role->id
)));
684 $this->assertTrue($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id
)));
685 $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$role->id
)));
686 $this->assertTrue($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id
)));
688 // Delete role and get event.
689 $sink = $this->redirectEvents();
690 $result = delete_role($role->id
);
691 $events = $sink->get_events();
693 $event = array_pop($events);
695 $this->assertTrue($result);
696 $this->assertFalse($DB->record_exists('role', array('id'=>$role->id
)));
697 $this->assertFalse($DB->record_exists('role_assignments', array('roleid'=>$role->id
)));
698 $this->assertFalse($DB->record_exists('role_capabilities', array('roleid'=>$role->id
)));
699 $this->assertFalse($DB->record_exists('role_names', array('roleid'=>$role->id
)));
700 $this->assertFalse($DB->record_exists('role_context_levels', array('roleid'=>$role->id
)));
701 $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$role->id
)));
702 $this->assertFalse($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id
)));
703 $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$role->id
)));
704 $this->assertFalse($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id
)));
706 // Test triggered event.
707 $this->assertInstanceOf('\core\event\role_deleted', $event);
708 $this->assertSame('role', $event->target
);
709 $this->assertSame('role', $event->objecttable
);
710 $this->assertSame($role->id
, $event->objectid
);
711 $this->assertEquals(context_system
::instance(), $event->get_context());
712 $this->assertSame($role->shortname
, $event->other
['shortname']);
713 $this->assertSame($role->description
, $event->other
['description']);
714 $this->assertSame($role->archetype
, $event->other
['archetype']);
716 $expectedlegacylog = array(SITEID
, 'role', 'delete', 'admin/roles/manage.php?action=delete&roleid='.$role->id
,
717 $role->shortname
, '');
718 $this->assertEventLegacyLogData($expectedlegacylog, $event);
722 * Test fetching of all roles.
724 public function test_get_all_roles() {
727 $this->resetAfterTest();
729 $allroles = get_all_roles();
730 $this->assertInternalType('array', $allroles);
731 $this->assertCount(8, $allroles); // There are 8 roles is standard install.
733 $role = reset($allroles);
734 $role = (array)$role;
736 $this->assertEquals(array('id', 'name', 'shortname', 'description', 'sortorder', 'archetype'), array_keys($role), '', 0, 10, true);
738 foreach ($allroles as $roleid => $role) {
739 $this->assertEquals($role->id
, $roleid);
742 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST
);
743 $course = $this->getDataGenerator()->create_course();
744 $coursecontext = context_course
::instance($course->id
);
745 $otherid = create_role('Other role', 'other', 'Some other role', '');
746 $teacherename = (object)array('roleid'=>$teacher->id
, 'name'=>'Učitel', 'contextid'=>$coursecontext->id
);
747 $DB->insert_record('role_names', $teacherename);
748 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id
);
749 $DB->insert_record('role_names', $otherrename);
750 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id
), '', 'roleid, name');
752 $allroles = get_all_roles($coursecontext);
753 $this->assertInternalType('array', $allroles);
754 $this->assertCount(9, $allroles);
755 $role = reset($allroles);
756 $role = (array)$role;
758 $this->assertEquals(array('id', 'name', 'shortname', 'description', 'sortorder', 'archetype', 'coursealias'), array_keys($role), '', 0, 10, true);
760 foreach ($allroles as $roleid => $role) {
761 $this->assertEquals($role->id
, $roleid);
762 if (isset($renames[$roleid])) {
763 $this->assertSame($renames[$roleid], $role->coursealias
);
765 $this->assertNull($role->coursealias
);
771 * Test getting of all archetypes.
773 public function test_get_role_archetypes() {
774 $archetypes = get_role_archetypes();
775 $this->assertCount(8, $archetypes); // There are 8 archetypes in standard install.
776 foreach ($archetypes as $k => $v) {
777 $this->assertSame($k, $v);
782 * Test getting of roles with given archetype.
784 public function test_get_archetype_roles() {
785 $this->resetAfterTest();
787 // New install should have 1 role for each archetype.
788 $archetypes = get_role_archetypes();
789 foreach ($archetypes as $archetype) {
790 $roles = get_archetype_roles($archetype);
791 $this->assertCount(1, $roles);
792 $role = reset($roles);
793 $this->assertSame($archetype, $role->archetype
);
796 create_role('New student role', 'student2', 'New student description', 'student');
797 $roles = get_archetype_roles('student');
798 $this->assertCount(2, $roles);
802 * Test aliased role names.
804 public function test_role_get_name() {
807 $this->resetAfterTest();
809 $allroles = $DB->get_records('role');
810 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST
);
811 $course = $this->getDataGenerator()->create_course();
812 $coursecontext = context_course
::instance($course->id
);
813 $otherid = create_role('Other role', 'other', 'Some other role', '');
814 $teacherename = (object)array('roleid'=>$teacher->id
, 'name'=>'Učitel', 'contextid'=>$coursecontext->id
);
815 $DB->insert_record('role_names', $teacherename);
816 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id
);
817 $DB->insert_record('role_names', $otherrename);
818 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id
), '', 'roleid, name');
820 foreach ($allroles as $role) {
821 // Get localised name from lang pack.
822 $this->assertSame('', $role->name
);
823 $name = role_get_name($role, null, ROLENAME_ORIGINAL
);
824 $this->assertNotEmpty($name);
825 $this->assertNotEquals($role->shortname
, $name);
827 if (isset($renames[$role->id
])) {
828 $this->assertSame($renames[$role->id
], role_get_name($role, $coursecontext));
829 $this->assertSame($renames[$role->id
], role_get_name($role, $coursecontext, ROLENAME_ALIAS
));
830 $this->assertSame($renames[$role->id
], role_get_name($role, $coursecontext, ROLENAME_ALIAS_RAW
));
831 $this->assertSame("{$renames[$role->id]} ($name)", role_get_name($role, $coursecontext, ROLENAME_BOTH
));
833 $this->assertSame($name, role_get_name($role, $coursecontext));
834 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_ALIAS
));
835 $this->assertNull(role_get_name($role, $coursecontext, ROLENAME_ALIAS_RAW
));
836 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_BOTH
));
838 $this->assertSame($name, role_get_name($role));
839 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_ORIGINAL
));
840 $this->assertSame($name, role_get_name($role, null, ROLENAME_ORIGINAL
));
841 $this->assertSame($role->shortname
, role_get_name($role, $coursecontext, ROLENAME_SHORT
));
842 $this->assertSame($role->shortname
, role_get_name($role, null, ROLENAME_SHORT
));
843 $this->assertSame("$name ($role->shortname)", role_get_name($role, $coursecontext, ROLENAME_ORIGINALANDSHORT
));
844 $this->assertSame("$name ($role->shortname)", role_get_name($role, null, ROLENAME_ORIGINALANDSHORT
));
845 $this->assertNull(role_get_name($role, null, ROLENAME_ALIAS_RAW
));
850 * Test tweaking of role name arrays.
852 public function test_role_fix_names() {
855 $this->resetAfterTest();
857 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST
);
858 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST
);
859 $otherid = create_role('Other role', 'other', 'Some other role', '');
860 $anotherid = create_role('Another role', 'another', 'Yet another other role', '');
861 $allroles = $DB->get_records('role');
863 $syscontext = context_system
::instance();
864 $frontcontext = context_course
::instance(SITEID
);
865 $course = $this->getDataGenerator()->create_course();
866 $coursecontext = context_course
::instance($course->id
);
867 $category = $DB->get_record('course_categories', array('id'=>$course->category
), '*', MUST_EXIST
);
868 $categorycontext = context_coursecat
::instance($category->id
);
870 $teacherename = (object)array('roleid'=>$teacher->id
, 'name'=>'Učitel', 'contextid'=>$coursecontext->id
);
871 $DB->insert_record('role_names', $teacherename);
872 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id
);
873 $DB->insert_record('role_names', $otherrename);
874 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id
), '', 'roleid, name');
876 // Make sure all localname contain proper values for each ROLENAME_ constant,
877 // note role_get_name() on frontpage is used to get the original name for future compatibility.
879 unset($roles[$student->id
]); // Remove one role to make sure no role is added or removed.
880 $rolenames = array();
881 foreach ($roles as $role) {
882 $rolenames[$role->id
] = $role->name
;
885 $alltypes = array(ROLENAME_ALIAS
, ROLENAME_ALIAS_RAW
, ROLENAME_BOTH
, ROLENAME_ORIGINAL
, ROLENAME_ORIGINALANDSHORT
, ROLENAME_SHORT
);
886 foreach ($alltypes as $type) {
887 $fixed = role_fix_names($roles, $coursecontext, $type);
888 $this->assertCount(count($roles), $fixed);
889 foreach ($fixed as $roleid => $rolename) {
890 $this->assertInstanceOf('stdClass', $rolename);
891 $role = $allroles[$roleid];
892 $name = role_get_name($role, $coursecontext, $type);
893 $this->assertSame($name, $rolename->localname
);
895 $fixed = role_fix_names($rolenames, $coursecontext, $type);
896 $this->assertCount(count($rolenames), $fixed);
897 foreach ($fixed as $roleid => $rolename) {
898 $role = $allroles[$roleid];
899 $name = role_get_name($role, $coursecontext, $type);
900 $this->assertSame($name, $rolename);
906 * Test role default allows.
908 public function test_get_default_role_archetype_allows() {
909 $archetypes = get_role_archetypes();
910 foreach ($archetypes as $archetype) {
912 $result = get_default_role_archetype_allows('assign', $archetype);
913 $this->assertInternalType('array', $result);
915 $result = get_default_role_archetype_allows('override', $archetype);
916 $this->assertInternalType('array', $result);
918 $result = get_default_role_archetype_allows('switch', $archetype);
919 $this->assertInternalType('array', $result);
921 $result = get_default_role_archetype_allows('view', $archetype);
922 $this->assertInternalType('array', $result);
925 $result = get_default_role_archetype_allows('assign', '');
926 $this->assertSame(array(), $result);
928 $result = get_default_role_archetype_allows('override', '');
929 $this->assertSame(array(), $result);
931 $result = get_default_role_archetype_allows('switch', '');
932 $this->assertSame(array(), $result);
934 $result = get_default_role_archetype_allows('view', '');
935 $this->assertSame(array(), $result);
937 $result = get_default_role_archetype_allows('assign', 'wrongarchetype');
938 $this->assertSame(array(), $result);
939 $this->assertDebuggingCalled();
941 $result = get_default_role_archetype_allows('override', 'wrongarchetype');
942 $this->assertSame(array(), $result);
943 $this->assertDebuggingCalled();
945 $result = get_default_role_archetype_allows('switch', 'wrongarchetype');
946 $this->assertSame(array(), $result);
947 $this->assertDebuggingCalled();
949 $result = get_default_role_archetype_allows('view', 'wrongarchetype');
950 $this->assertSame(array(), $result);
951 $this->assertDebuggingCalled();
955 * Test allowing of role assignments.
957 public function test_core_role_set_assign_allowed() {
960 $this->resetAfterTest();
962 $otherid = create_role('Other role', 'other', 'Some other role', '');
963 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST
);
965 $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id
)));
966 core_role_set_assign_allowed($otherid, $student->id
);
967 $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id
)));
969 // Test event trigger.
970 $allowroleassignevent = \core\event\role_allow_assign_updated
::create(array('context' => context_system
::instance()));
971 $sink = $this->redirectEvents();
972 $allowroleassignevent->trigger();
973 $events = $sink->get_events();
975 $event = array_pop($events);
976 $this->assertInstanceOf('\core\event\role_allow_assign_updated', $event);
978 $baseurl = new moodle_url('/admin/roles/allow.php', array('mode' => $mode));
979 $expectedlegacylog = array(SITEID
, 'role', 'edit allow ' . $mode, str_replace($CFG->wwwroot
. '/', '', $baseurl));
980 $this->assertEventLegacyLogData($expectedlegacylog, $event);
984 * Test allowing of role overrides.
986 public function test_core_role_set_override_allowed() {
989 $this->resetAfterTest();
991 $otherid = create_role('Other role', 'other', 'Some other role', '');
992 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST
);
994 $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id
)));
995 core_role_set_override_allowed($otherid, $student->id
);
996 $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id
)));
998 // Test event trigger.
999 $allowroleassignevent = \core\event\role_allow_override_updated
::create(array('context' => context_system
::instance()));
1000 $sink = $this->redirectEvents();
1001 $allowroleassignevent->trigger();
1002 $events = $sink->get_events();
1004 $event = array_pop($events);
1005 $this->assertInstanceOf('\core\event\role_allow_override_updated', $event);
1007 $baseurl = new moodle_url('/admin/roles/allow.php', array('mode' => $mode));
1008 $expectedlegacylog = array(SITEID
, 'role', 'edit allow ' . $mode, str_replace($CFG->wwwroot
. '/', '', $baseurl));
1009 $this->assertEventLegacyLogData($expectedlegacylog, $event);
1013 * Test allowing of role switching.
1015 public function test_core_role_set_switch_allowed() {
1018 $this->resetAfterTest();
1020 $otherid = create_role('Other role', 'other', 'Some other role', '');
1021 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST
);
1023 $this->assertFalse($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id
)));
1024 core_role_set_switch_allowed($otherid, $student->id
);
1025 $this->assertTrue($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id
)));
1027 // Test event trigger.
1028 $allowroleassignevent = \core\event\role_allow_switch_updated
::create(array('context' => context_system
::instance()));
1029 $sink = $this->redirectEvents();
1030 $allowroleassignevent->trigger();
1031 $events = $sink->get_events();
1033 $event = array_pop($events);
1034 $this->assertInstanceOf('\core\event\role_allow_switch_updated', $event);
1036 $baseurl = new moodle_url('/admin/roles/allow.php', array('mode' => $mode));
1037 $expectedlegacylog = array(SITEID
, 'role', 'edit allow ' . $mode, str_replace($CFG->wwwroot
. '/', '', $baseurl));
1038 $this->assertEventLegacyLogData($expectedlegacylog, $event);
1042 * Test allowing of role switching.
1044 public function test_core_role_set_view_allowed() {
1047 $this->resetAfterTest();
1049 $otherid = create_role('Other role', 'other', 'Some other role', '');
1050 $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST
);
1052 $this->assertFalse($DB->record_exists('role_allow_view', array('roleid' => $otherid, 'allowview' => $student->id
)));
1053 core_role_set_view_allowed($otherid, $student->id
);
1054 $this->assertTrue($DB->record_exists('role_allow_view', array('roleid' => $otherid, 'allowview' => $student->id
)));
1056 // Test event trigger.
1057 $allowroleassignevent = \core\event\role_allow_view_updated
::create(array('context' => context_system
::instance()));
1058 $sink = $this->redirectEvents();
1059 $allowroleassignevent->trigger();
1060 $events = $sink->get_events();
1062 $event = array_pop($events);
1063 $this->assertInstanceOf('\core\event\role_allow_view_updated', $event);
1065 $baseurl = new moodle_url('/admin/roles/allow.php', array('mode' => $mode));
1066 $expectedlegacylog = array(SITEID
, 'role', 'edit allow ' . $mode, str_replace($CFG->wwwroot
. '/', '', $baseurl));
1067 $this->assertEventLegacyLogData($expectedlegacylog, $event);
1071 * Test returning of assignable roles in context.
1073 public function test_get_assignable_roles() {
1076 $this->resetAfterTest();
1078 $course = $this->getDataGenerator()->create_course();
1079 $coursecontext = context_course
::instance($course->id
);
1081 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST
);
1082 $teacher = $this->getDataGenerator()->create_user();
1083 role_assign($teacherrole->id
, $teacher->id
, $coursecontext);
1084 $teacherename = (object)array('roleid'=>$teacherrole->id
, 'name'=>'Učitel', 'contextid'=>$coursecontext->id
);
1085 $DB->insert_record('role_names', $teacherename);
1087 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST
);
1088 $student = $this->getDataGenerator()->create_user();
1089 role_assign($studentrole->id
, $student->id
, $coursecontext);
1091 $contexts = $DB->get_records('context');
1092 $users = $DB->get_records('user');
1093 $allroles = $DB->get_records('role');
1095 // Evaluate all results for all users in all contexts.
1096 foreach ($users as $user) {
1097 $this->setUser($user);
1098 foreach ($contexts as $contextid => $unused) {
1099 $context = context_helper
::instance_by_id($contextid);
1100 $roles = get_assignable_roles($context, ROLENAME_SHORT
);
1101 foreach ($allroles as $roleid => $role) {
1102 if (isset($roles[$roleid])) {
1103 if (is_siteadmin()) {
1104 $this->assertTrue($DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel
, 'roleid'=>$roleid)));
1106 $this->assertTrue(user_can_assign($context, $roleid), "u:$user->id r:$roleid");
1108 $this->assertEquals($role->shortname
, $roles[$roleid]);
1110 $allowed = $DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel
, 'roleid'=>$roleid));
1111 if (is_siteadmin()) {
1112 $this->assertFalse($allowed);
1114 $this->assertFalse($allowed and user_can_assign($context, $roleid), "u:$user->id, r:{$allroles[$roleid]->name}, c:$context->contextlevel");
1121 // Not-logged-in user.
1123 foreach ($contexts as $contextid => $unused) {
1124 $context = context_helper
::instance_by_id($contextid);
1125 $roles = get_assignable_roles($context, ROLENAME_SHORT
);
1126 $this->assertSame(array(), $roles);
1129 // Test current user.
1131 $admin = $DB->get_record('user', array('username'=>'admin'), '*', MUST_EXIST
);
1132 $roles1 = get_assignable_roles($coursecontext, ROLENAME_SHORT
, false, $admin);
1133 $roles2 = get_assignable_roles($coursecontext, ROLENAME_SHORT
, false, $admin->id
);
1134 $this->setAdminUser();
1135 $roles3 = get_assignable_roles($coursecontext, ROLENAME_SHORT
);
1136 $this->assertSame($roles1, $roles3);
1137 $this->assertSame($roles2, $roles3);
1139 // Test parameter defaults.
1140 $this->setAdminUser();
1141 $roles1 = get_assignable_roles($coursecontext);
1142 $roles2 = get_assignable_roles($coursecontext, ROLENAME_ALIAS
, false, $admin);
1143 $this->assertEquals($roles2, $roles1);
1145 // Verify returned names - let's allow all roles everywhere to simplify this a bit.
1146 $alllevels = context_helper
::get_all_levels();
1147 $alllevels = array_keys($alllevels);
1148 foreach ($allroles as $roleid => $role) {
1149 set_role_contextlevels($roleid, $alllevels);
1151 $alltypes = array(ROLENAME_ALIAS
, ROLENAME_ALIAS_RAW
, ROLENAME_BOTH
, ROLENAME_ORIGINAL
, ROLENAME_ORIGINALANDSHORT
, ROLENAME_SHORT
);
1152 foreach ($alltypes as $type) {
1153 $rolenames = role_fix_names($allroles, $coursecontext, $type);
1154 $roles = get_assignable_roles($coursecontext, $type, false, $admin);
1155 foreach ($roles as $roleid => $rolename) {
1156 $this->assertSame($rolenames[$roleid]->localname
, $rolename);
1161 $alltypes = array(ROLENAME_ALIAS
, ROLENAME_ALIAS_RAW
, ROLENAME_BOTH
, ROLENAME_ORIGINAL
, ROLENAME_ORIGINALANDSHORT
, ROLENAME_SHORT
);
1162 foreach ($alltypes as $type) {
1163 $roles = get_assignable_roles($coursecontext, $type, false, $admin);
1164 list($rolenames, $rolecounts, $nameswithcounts) = get_assignable_roles($coursecontext, $type, true, $admin);
1165 $this->assertEquals($roles, $rolenames);
1166 foreach ($rolenames as $roleid => $name) {
1167 if ($roleid == $teacherrole->id
or $roleid == $studentrole->id
) {
1168 $this->assertEquals(1, $rolecounts[$roleid]);
1170 $this->assertEquals(0, $rolecounts[$roleid]);
1172 $this->assertSame("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]);
1178 * Test getting of all switchable roles.
1180 public function test_get_switchable_roles() {
1183 $this->resetAfterTest();
1185 $course = $this->getDataGenerator()->create_course();
1186 $coursecontext = context_course
::instance($course->id
);
1188 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST
);
1189 $teacher = $this->getDataGenerator()->create_user();
1190 role_assign($teacherrole->id
, $teacher->id
, $coursecontext);
1191 $teacherename = (object)array('roleid'=>$teacherrole->id
, 'name'=>'Učitel', 'contextid'=>$coursecontext->id
);
1192 $DB->insert_record('role_names', $teacherename);
1194 $contexts = $DB->get_records('context');
1195 $users = $DB->get_records('user');
1196 $allroles = $DB->get_records('role');
1198 // Evaluate all results for all users in all contexts.
1199 foreach ($users as $user) {
1200 $this->setUser($user);
1201 foreach ($contexts as $contextid => $unused) {
1202 $context = context_helper
::instance_by_id($contextid);
1203 $roles = get_switchable_roles($context);
1204 foreach ($allroles as $roleid => $role) {
1205 if (is_siteadmin()) {
1206 $this->assertTrue(isset($roles[$roleid]));
1208 $parents = $context->get_parent_context_ids(true);
1209 $pcontexts = implode(',' , $parents);
1210 $allowed = $DB->record_exists_sql(
1213 JOIN {role_allow_switch} ras ON ras.allowswitch = r.id
1214 JOIN {role_assignments} ra ON ra.roleid = ras.roleid
1215 WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid
1217 array('userid'=>$user->id
, 'roleid'=>$roleid)
1219 if (isset($roles[$roleid])) {
1220 $this->assertTrue($allowed);
1222 $this->assertFalse($allowed);
1226 if (isset($roles[$roleid])) {
1227 $coursecontext = $context->get_course_context(false);
1228 $this->assertSame(role_get_name($role, $coursecontext), $roles[$roleid]);
1236 * Test getting of all overridable roles.
1238 public function test_get_overridable_roles() {
1241 $this->resetAfterTest();
1243 $course = $this->getDataGenerator()->create_course();
1244 $coursecontext = context_course
::instance($course->id
);
1246 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST
);
1247 $teacher = $this->getDataGenerator()->create_user();
1248 role_assign($teacherrole->id
, $teacher->id
, $coursecontext);
1249 $teacherename = (object)array('roleid'=>$teacherrole->id
, 'name'=>'Učitel', 'contextid'=>$coursecontext->id
);
1250 $DB->insert_record('role_names', $teacherename);
1251 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // Any capability is ok.
1252 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT
, $teacherrole->id
, $coursecontext->id
);
1254 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST
);
1255 $student = $this->getDataGenerator()->create_user();
1256 role_assign($studentrole->id
, $student->id
, $coursecontext);
1258 $contexts = $DB->get_records('context');
1259 $users = $DB->get_records('user');
1260 $allroles = $DB->get_records('role');
1262 // Evaluate all results for all users in all contexts.
1263 foreach ($users as $user) {
1264 $this->setUser($user);
1265 foreach ($contexts as $contextid => $unused) {
1266 $context = context_helper
::instance_by_id($contextid);
1267 $roles = get_overridable_roles($context, ROLENAME_SHORT
);
1268 foreach ($allroles as $roleid => $role) {
1269 $hascap = has_any_capability(array('moodle/role:safeoverride', 'moodle/role:override'), $context);
1270 if (is_siteadmin()) {
1271 $this->assertTrue(isset($roles[$roleid]));
1273 $parents = $context->get_parent_context_ids(true);
1274 $pcontexts = implode(',' , $parents);
1275 $allowed = $DB->record_exists_sql(
1278 JOIN {role_allow_override} rao ON r.id = rao.allowoverride
1279 JOIN {role_assignments} ra ON rao.roleid = ra.roleid
1280 WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid
1282 array('userid'=>$user->id
, 'roleid'=>$roleid)
1284 if (isset($roles[$roleid])) {
1285 $this->assertTrue($hascap);
1286 $this->assertTrue($allowed);
1288 $this->assertFalse($hascap and $allowed);
1292 if (isset($roles[$roleid])) {
1293 $this->assertEquals($role->shortname
, $roles[$roleid]);
1299 // Test parameter defaults.
1300 $this->setAdminUser();
1301 $roles1 = get_overridable_roles($coursecontext);
1302 $roles2 = get_overridable_roles($coursecontext, ROLENAME_ALIAS
, false);
1303 $this->assertEquals($roles2, $roles1);
1305 $alltypes = array(ROLENAME_ALIAS
, ROLENAME_ALIAS_RAW
, ROLENAME_BOTH
, ROLENAME_ORIGINAL
, ROLENAME_ORIGINALANDSHORT
, ROLENAME_SHORT
);
1306 foreach ($alltypes as $type) {
1307 $rolenames = role_fix_names($allroles, $coursecontext, $type);
1308 $roles = get_overridable_roles($coursecontext, $type, false);
1309 foreach ($roles as $roleid => $rolename) {
1310 $this->assertSame($rolenames[$roleid]->localname
, $rolename);
1315 $roles = get_overridable_roles($coursecontext, ROLENAME_ALIAS
, false);
1316 list($rolenames, $rolecounts, $nameswithcounts) = get_overridable_roles($coursecontext, ROLENAME_ALIAS
, true);
1317 $this->assertEquals($roles, $rolenames);
1318 foreach ($rolenames as $roleid => $name) {
1319 if ($roleid == $teacherrole->id
) {
1320 $this->assertEquals(1, $rolecounts[$roleid]);
1322 $this->assertEquals(0, $rolecounts[$roleid]);
1324 $this->assertSame("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]);
1329 * Test getting of all overridable roles.
1331 public function test_get_viewable_roles_course() {
1334 $this->resetAfterTest();
1336 $course = $this->getDataGenerator()->create_course();
1337 $coursecontext = context_course
::instance($course->id
);
1339 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST
);
1340 $teacher = $this->getDataGenerator()->create_user();
1341 role_assign($teacherrole->id
, $teacher->id
, $coursecontext);
1343 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST
);
1344 $studentrolerename = (object) array('roleid' => $studentrole->id
, 'name' => 'Učitel', 'contextid' => $coursecontext->id
);
1345 $DB->insert_record('role_names', $studentrolerename);
1347 // By default teacher can see student.
1348 $this->setUser($teacher);
1349 $viewableroles = get_viewable_roles($coursecontext);
1350 $this->assertContains($studentrolerename->name
, array_values($viewableroles));
1351 // Remove view permission.
1352 $DB->delete_records('role_allow_view', array('roleid' => $teacherrole->id
, 'allowview' => $studentrole->id
));
1353 $viewableroles = get_viewable_roles($coursecontext);
1354 // Teacher can no longer see student role.
1355 $this->assertNotContains($studentrolerename->name
, array_values($viewableroles));
1356 // Allow again teacher to view student.
1357 core_role_set_view_allowed($teacherrole->id
, $studentrole->id
);
1358 // Teacher can now see student role.
1359 $viewableroles = get_viewable_roles($coursecontext);
1360 $this->assertContains($studentrolerename->name
, array_values($viewableroles));
1364 * Test getting of all overridable roles.
1366 public function test_get_viewable_roles_system() {
1369 $this->resetAfterTest();
1371 $context = context_system
::instance();
1373 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST
);
1374 $teacher = $this->getDataGenerator()->create_user();
1375 role_assign($teacherrole->id
, $teacher->id
, $context);
1377 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST
);
1378 $studentrolename = role_get_name($studentrole, $context);
1380 // By default teacher can see student.
1381 $this->setUser($teacher);
1382 $viewableroles = get_viewable_roles($context);
1383 $this->assertContains($studentrolename, array_values($viewableroles));
1384 // Remove view permission.
1385 $DB->delete_records('role_allow_view', array('roleid' => $teacherrole->id
, 'allowview' => $studentrole->id
));
1386 $viewableroles = get_viewable_roles($context);
1387 // Teacher can no longer see student role.
1388 $this->assertNotContains($studentrolename, array_values($viewableroles));
1389 // Allow again teacher to view student.
1390 core_role_set_view_allowed($teacherrole->id
, $studentrole->id
);
1391 // Teacher can now see student role.
1392 $viewableroles = get_viewable_roles($context);
1393 $this->assertContains($studentrolename, array_values($viewableroles));
1397 * Test we have context level defaults.
1399 public function test_get_default_contextlevels() {
1400 $archetypes = get_role_archetypes();
1401 $alllevels = context_helper
::get_all_levels();
1402 foreach ($archetypes as $archetype) {
1403 $defaults = get_default_contextlevels($archetype);
1404 $this->assertInternalType('array', $defaults);
1405 foreach ($defaults as $level) {
1406 $this->assertTrue(isset($alllevels[$level]));
1412 * Test role context level setup.
1414 public function test_set_role_contextlevels() {
1417 $this->resetAfterTest();
1419 $roleid = create_role('New student role', 'student2', 'New student description', 'student');
1421 $this->assertFalse($DB->record_exists('role_context_levels', array('roleid' => $roleid)));
1423 set_role_contextlevels($roleid, array(CONTEXT_COURSE
, CONTEXT_MODULE
));
1424 $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel');
1425 $this->assertCount(2, $levels);
1426 $this->assertTrue(isset($levels[CONTEXT_COURSE
]));
1427 $this->assertTrue(isset($levels[CONTEXT_MODULE
]));
1429 set_role_contextlevels($roleid, array(CONTEXT_COURSE
));
1430 $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel');
1431 $this->assertCount(1, $levels);
1432 $this->assertTrue(isset($levels[CONTEXT_COURSE
]));
1436 * Test getting of role context levels
1438 public function test_get_roles_for_contextlevels() {
1441 $allroles = get_all_roles();
1442 foreach (context_helper
::get_all_levels() as $level => $unused) {
1443 $roles = get_roles_for_contextlevels($level);
1444 foreach ($allroles as $roleid => $unused) {
1445 $exists = $DB->record_exists('role_context_levels', array('contextlevel'=>$level, 'roleid'=>$roleid));
1446 if (in_array($roleid, $roles)) {
1447 $this->assertTrue($exists);
1449 $this->assertFalse($exists);
1456 * Test default enrol roles.
1458 public function test_get_default_enrol_roles() {
1459 $this->resetAfterTest();
1461 $course = $this->getDataGenerator()->create_course();
1462 $coursecontext = context_course
::instance($course->id
);
1464 $id2 = create_role('New student role', 'student2', 'New student description', 'student');
1465 set_role_contextlevels($id2, array(CONTEXT_COURSE
));
1467 $allroles = get_all_roles();
1468 $expected = array($id2=>$allroles[$id2]);
1470 foreach (get_role_archetypes() as $archetype) {
1471 $defaults = get_default_contextlevels($archetype);
1472 if (in_array(CONTEXT_COURSE
, $defaults)) {
1473 $roles = get_archetype_roles($archetype);
1474 foreach ($roles as $role) {
1475 $expected[$role->id
] = $role;
1480 $roles = get_default_enrol_roles($coursecontext);
1481 foreach ($allroles as $role) {
1482 $this->assertEquals(isset($expected[$role->id
]), isset($roles[$role->id
]));
1483 if (isset($roles[$role->id
])) {
1484 $this->assertSame(role_get_name($role, $coursecontext), $roles[$role->id
]);
1490 * Test getting of role users.
1492 public function test_get_role_users() {
1495 $this->resetAfterTest();
1497 $systemcontext = context_system
::instance();
1498 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST
);
1499 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST
);
1500 $noeditteacherrole = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST
);
1501 $course = $this->getDataGenerator()->create_course();
1502 $coursecontext = context_course
::instance($course->id
);
1503 $otherid = create_role('Other role', 'other', 'Some other role', '');
1504 $teacherrename = (object)array('roleid'=>$teacherrole->id
, 'name'=>'Učitel', 'contextid'=>$coursecontext->id
);
1505 $DB->insert_record('role_names', $teacherrename);
1506 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id
);
1507 $DB->insert_record('role_names', $otherrename);
1509 $user1 = $this->getDataGenerator()->create_user(array('firstname'=>'John', 'lastname'=>'Smith'));
1510 role_assign($teacherrole->id
, $user1->id
, $coursecontext->id
);
1511 $user2 = $this->getDataGenerator()->create_user(array('firstname'=>'Jan', 'lastname'=>'Kovar'));
1512 role_assign($teacherrole->id
, $user2->id
, $systemcontext->id
);
1513 $user3 = $this->getDataGenerator()->create_user();
1514 $this->getDataGenerator()->enrol_user($user3->id
, $course->id
, $teacherrole->id
);
1515 $user4 = $this->getDataGenerator()->create_user();
1516 $this->getDataGenerator()->enrol_user($user4->id
, $course->id
, $studentrole->id
);
1517 $this->getDataGenerator()->enrol_user($user4->id
, $course->id
, $noeditteacherrole->id
);
1519 $group = $this->getDataGenerator()->create_group(array('courseid'=>$course->id
));
1520 groups_add_member($group, $user3);
1522 $users = get_role_users($teacherrole->id
, $coursecontext);
1523 $this->assertCount(2, $users);
1524 $this->assertArrayHasKey($user1->id
, $users);
1525 $this->assertEquals($users[$user1->id
]->id
, $user1->id
);
1526 $this->assertEquals($users[$user1->id
]->roleid
, $teacherrole->id
);
1527 $this->assertEquals($users[$user1->id
]->rolename
, $teacherrole->name
);
1528 $this->assertEquals($users[$user1->id
]->roleshortname
, $teacherrole->shortname
);
1529 $this->assertEquals($users[$user1->id
]->rolecoursealias
, $teacherrename->name
);
1530 $this->assertArrayHasKey($user3->id
, $users);
1531 $this->assertEquals($users[$user3->id
]->id
, $user3->id
);
1532 $this->assertEquals($users[$user3->id
]->roleid
, $teacherrole->id
);
1533 $this->assertEquals($users[$user3->id
]->rolename
, $teacherrole->name
);
1534 $this->assertEquals($users[$user3->id
]->roleshortname
, $teacherrole->shortname
);
1535 $this->assertEquals($users[$user3->id
]->rolecoursealias
, $teacherrename->name
);
1537 $users = get_role_users($teacherrole->id
, $coursecontext, true);
1538 $this->assertCount(3, $users);
1540 $users = get_role_users($teacherrole->id
, $coursecontext, true, '', null, null, '', 2, 1);
1541 $this->assertCount(1, $users);
1543 $users = get_role_users($teacherrole->id
, $coursecontext, false, 'u.id, u.email, u.idnumber', 'u.idnumber');
1544 $this->assertCount(2, $users);
1545 $this->assertArrayHasKey($user1->id
, $users);
1546 $this->assertArrayHasKey($user3->id
, $users);
1548 $users = get_role_users($teacherrole->id
, $coursecontext, false, 'u.id, u.email');
1549 $this->assertDebuggingCalled('get_role_users() adding u.lastname, u.firstname to the query result because they were required by $sort but missing in $fields');
1550 $this->assertCount(2, $users);
1551 $this->assertArrayHasKey($user1->id
, $users);
1552 $this->assertObjectHasAttribute('lastname', $users[$user1->id
]);
1553 $this->assertObjectHasAttribute('firstname', $users[$user1->id
]);
1554 $this->assertArrayHasKey($user3->id
, $users);
1555 $this->assertObjectHasAttribute('lastname', $users[$user3->id
]);
1556 $this->assertObjectHasAttribute('firstname', $users[$user3->id
]);
1558 $users = get_role_users($teacherrole->id
, $coursecontext, false, 'u.id AS id_alias');
1559 $this->assertDebuggingCalled('get_role_users() adding u.lastname, u.firstname to the query result because they were required by $sort but missing in $fields');
1560 $this->assertCount(2, $users);
1561 $this->assertArrayHasKey($user1->id
, $users);
1562 $this->assertObjectHasAttribute('id_alias', $users[$user1->id
]);
1563 $this->assertObjectHasAttribute('lastname', $users[$user1->id
]);
1564 $this->assertObjectHasAttribute('firstname', $users[$user1->id
]);
1565 $this->assertArrayHasKey($user3->id
, $users);
1566 $this->assertObjectHasAttribute('id_alias', $users[$user3->id
]);
1567 $this->assertObjectHasAttribute('lastname', $users[$user3->id
]);
1568 $this->assertObjectHasAttribute('firstname', $users[$user3->id
]);
1570 $users = get_role_users($teacherrole->id
, $coursecontext, false, 'u.id, u.email, u.idnumber', 'u.idnumber', null, $group->id
);
1571 $this->assertCount(1, $users);
1572 $this->assertArrayHasKey($user3->id
, $users);
1574 $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'));
1575 $this->assertCount(1, $users);
1576 $this->assertArrayHasKey($user1->id
, $users);
1578 $users = get_role_users(array($noeditteacherrole->id
, $studentrole->id
), $coursecontext, false, 'ra.id', 'ra.id');
1579 $this->assertDebuggingNotCalled();
1580 $users = get_role_users(array($noeditteacherrole->id
, $studentrole->id
), $coursecontext, false, 'ra.userid', 'ra.userid');
1581 $this->assertDebuggingCalled('get_role_users() without specifying one single roleid needs to be called prefixing ' .
1582 'role assignments id (ra.id) as unique field, you can use $fields param for it.');
1583 $users = get_role_users(array($noeditteacherrole->id
, $studentrole->id
), $coursecontext, false);
1584 $this->assertDebuggingCalled('get_role_users() without specifying one single roleid needs to be called prefixing ' .
1585 'role assignments id (ra.id) as unique field, you can use $fields param for it.');
1586 $users = get_role_users(array($noeditteacherrole->id
, $studentrole->id
), $coursecontext,
1587 false, 'u.id, u.firstname', 'u.id, u.firstname');
1588 $this->assertDebuggingCalled('get_role_users() without specifying one single roleid needs to be called prefixing ' .
1589 'role assignments id (ra.id) as unique field, you can use $fields param for it.');
1593 * Test used role query.
1595 public function test_get_roles_used_in_context() {
1598 $this->resetAfterTest();
1600 $systemcontext = context_system
::instance();
1601 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST
);
1602 $course = $this->getDataGenerator()->create_course();
1603 $coursecontext = context_course
::instance($course->id
);
1604 $otherid = create_role('Other role', 'other', 'Some other role', '');
1605 $teacherrename = (object)array('roleid'=>$teacherrole->id
, 'name'=>'Učitel', 'contextid'=>$coursecontext->id
);
1606 $DB->insert_record('role_names', $teacherrename);
1607 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id
);
1608 $DB->insert_record('role_names', $otherrename);
1610 $user1 = $this->getDataGenerator()->create_user();
1611 role_assign($teacherrole->id
, $user1->id
, $coursecontext->id
);
1613 $roles = get_roles_used_in_context($coursecontext);
1614 $this->assertCount(1, $roles);
1615 $role = reset($roles);
1616 $roleid = key($roles);
1617 $this->assertEquals($roleid, $role->id
);
1618 $this->assertEquals($teacherrole->id
, $role->id
);
1619 $this->assertSame($teacherrole->name
, $role->name
);
1620 $this->assertSame($teacherrole->shortname
, $role->shortname
);
1621 $this->assertEquals($teacherrole->sortorder
, $role->sortorder
);
1622 $this->assertSame($teacherrename->name
, $role->coursealias
);
1624 $user2 = $this->getDataGenerator()->create_user();
1625 role_assign($teacherrole->id
, $user2->id
, $systemcontext->id
);
1626 role_assign($otherid, $user2->id
, $systemcontext->id
);
1628 $roles = get_roles_used_in_context($systemcontext);
1629 $this->assertCount(2, $roles);
1633 * Test roles used in course.
1635 public function test_get_user_roles_in_course() {
1638 $this->resetAfterTest();
1640 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST
);
1641 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST
);
1642 $managerrole = $DB->get_record('role', array('shortname' => 'manager'), '*', MUST_EXIST
);
1643 $course = $this->getDataGenerator()->create_course();
1644 $coursecontext = context_course
::instance($course->id
);
1645 $teacherrename = (object)array('roleid'=>$teacherrole->id
, 'name'=>'Učitel', 'contextid'=>$coursecontext->id
);
1646 $DB->insert_record('role_names', $teacherrename);
1648 $roleids = explode(',', $CFG->profileroles
); // Should include teacher and student in new installs.
1649 $this->assertTrue(in_array($teacherrole->id
, $roleids));
1650 $this->assertTrue(in_array($studentrole->id
, $roleids));
1651 $this->assertFalse(in_array($managerrole->id
, $roleids));
1653 $user1 = $this->getDataGenerator()->create_user();
1654 role_assign($teacherrole->id
, $user1->id
, $coursecontext->id
);
1655 role_assign($studentrole->id
, $user1->id
, $coursecontext->id
);
1656 $user2 = $this->getDataGenerator()->create_user();
1657 role_assign($studentrole->id
, $user2->id
, $coursecontext->id
);
1658 $user3 = $this->getDataGenerator()->create_user();
1659 $user4 = $this->getDataGenerator()->create_user();
1660 role_assign($managerrole->id
, $user4->id
, $coursecontext->id
);
1662 $this->setAdminUser();
1664 $roles = get_user_roles_in_course($user1->id
, $course->id
);
1665 $this->assertEquals(1, preg_match_all('/,/', $roles, $matches));
1666 $this->assertTrue(strpos($roles, role_get_name($teacherrole, $coursecontext)) !== false);
1668 $roles = get_user_roles_in_course($user2->id
, $course->id
);
1669 $this->assertEquals(0, preg_match_all('/,/', $roles, $matches));
1670 $this->assertTrue(strpos($roles, role_get_name($studentrole, $coursecontext)) !== false);
1672 $roles = get_user_roles_in_course($user3->id
, $course->id
);
1673 $this->assertSame('', $roles);
1675 // Managers should be able to see a link to their own role type, given they can assign it in the context.
1676 $this->setUser($user4);
1677 $roles = get_user_roles_in_course($user4->id
, $course->id
);
1678 $this->assertNotEmpty($roles);
1679 $this->assertEquals(1, count(explode(',', $roles)));
1680 $this->assertTrue(strpos($roles, role_get_name($managerrole, $coursecontext)) !== false);
1682 // Managers should see 2 roles if viewing a user who has been enrolled as a student and a teacher in the course.
1683 $roles = get_user_roles_in_course($user1->id
, $course->id
);
1684 $this->assertEquals(2, count(explode(',', $roles)));
1685 $this->assertTrue(strpos($roles, role_get_name($studentrole, $coursecontext)) !== false);
1686 $this->assertTrue(strpos($roles, role_get_name($teacherrole, $coursecontext)) !== false);
1688 // Students should not see the manager role if viewing a manager's profile.
1689 $this->setUser($user2);
1690 $roles = get_user_roles_in_course($user4->id
, $course->id
);
1691 $this->assertEmpty($roles); // Should see 0 roles on the manager's profile.
1692 $this->assertFalse(strpos($roles, role_get_name($managerrole, $coursecontext)) !== false);
1696 * Test get_user_roles and get_users_roles
1698 public function test_get_user_roles() {
1701 $this->resetAfterTest();
1703 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST
);
1704 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST
);
1705 $course = $this->getDataGenerator()->create_course();
1706 $coursecontext = context_course
::instance($course->id
);
1707 $teacherrename = (object)array('roleid'=>$teacherrole->id
, 'name'=>'Učitel', 'contextid'=>$coursecontext->id
);
1708 $DB->insert_record('role_names', $teacherrename);
1710 $roleids = explode(',', $CFG->profileroles
); // Should include teacher and student in new installs.
1712 $user1 = $this->getDataGenerator()->create_user();
1713 role_assign($teacherrole->id
, $user1->id
, $coursecontext->id
);
1714 role_assign($studentrole->id
, $user1->id
, $coursecontext->id
);
1715 $user2 = $this->getDataGenerator()->create_user();
1716 role_assign($studentrole->id
, $user2->id
, $coursecontext->id
);
1717 $user3 = $this->getDataGenerator()->create_user();
1719 $u1roles = get_user_roles($coursecontext, $user1->id
);
1721 $u2roles = get_user_roles($coursecontext, $user2->id
);
1723 $allroles = get_users_roles($coursecontext, [], false);
1724 $specificuserroles = get_users_roles($coursecontext, [$user1->id
, $user2->id
]);
1725 $this->assertEquals($u1roles, $allroles[$user1->id
]);
1726 $this->assertEquals($u1roles, $specificuserroles[$user1->id
]);
1727 $this->assertEquals($u2roles, $allroles[$user2->id
]);
1728 $this->assertEquals($u2roles, $specificuserroles[$user2->id
]);
1732 * Test has_capability(), has_any_capability() and has_all_capabilities().
1734 public function test_has_capability_and_friends() {
1737 $this->resetAfterTest();
1739 $course = $this->getDataGenerator()->create_course();
1740 $coursecontext = context_course
::instance($course->id
);
1741 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST
);
1742 $teacher = $this->getDataGenerator()->create_user();
1743 role_assign($teacherrole->id
, $teacher->id
, $coursecontext);
1744 $admin = $DB->get_record('user', array('username'=>'admin'));
1746 // Note: Here are used default capabilities, the full test is in permission evaluation bellow,
1747 // use two capabilities that teacher has and one does not, none of them should be allowed for not-logged-in user.
1749 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupsection')));
1750 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse')));
1751 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/site:approvecourse')));
1753 $sca = array('moodle/backup:backupsection', 'moodle/backup:backupcourse', 'moodle/site:approvecourse');
1754 $sc = array('moodle/backup:backupsection', 'moodle/backup:backupcourse');
1757 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext));
1758 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext));
1759 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext));
1760 $this->assertFalse(has_any_capability($sca, $coursecontext));
1761 $this->assertFalse(has_all_capabilities($sca, $coursecontext));
1763 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $teacher));
1764 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $teacher));
1765 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $teacher));
1766 $this->assertTrue(has_any_capability($sca, $coursecontext, $teacher));
1767 $this->assertTrue(has_all_capabilities($sc, $coursecontext, $teacher));
1768 $this->assertFalse(has_all_capabilities($sca, $coursecontext, $teacher));
1770 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $admin));
1771 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $admin));
1772 $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext, $admin));
1773 $this->assertTrue(has_any_capability($sca, $coursecontext, $admin));
1774 $this->assertTrue(has_all_capabilities($sc, $coursecontext, $admin));
1775 $this->assertTrue(has_all_capabilities($sca, $coursecontext, $admin));
1777 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, $admin, false));
1778 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, $admin, false));
1779 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $admin, false));
1780 $this->assertFalse(has_any_capability($sca, $coursecontext, $admin, false));
1781 $this->assertFalse(has_all_capabilities($sc, $coursecontext, $admin, false));
1782 $this->assertFalse(has_all_capabilities($sca, $coursecontext, $admin, false));
1784 $this->setUser($teacher);
1785 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext));
1786 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext));
1787 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext));
1788 $this->assertTrue(has_any_capability($sca, $coursecontext));
1789 $this->assertTrue(has_all_capabilities($sc, $coursecontext));
1790 $this->assertFalse(has_all_capabilities($sca, $coursecontext));
1792 $this->setAdminUser();
1793 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext));
1794 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext));
1795 $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext));
1796 $this->assertTrue(has_any_capability($sca, $coursecontext));
1797 $this->assertTrue(has_all_capabilities($sc, $coursecontext));
1798 $this->assertTrue(has_all_capabilities($sca, $coursecontext));
1800 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, 0));
1801 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, 0));
1802 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, 0));
1803 $this->assertFalse(has_any_capability($sca, $coursecontext, 0));
1804 $this->assertFalse(has_all_capabilities($sca, $coursecontext, 0));
1808 * Test that the caching in get_role_definitions() and get_role_definitions_uncached()
1809 * works as intended.
1811 public function test_role_definition_caching() {
1814 $this->resetAfterTest();
1816 // Get some role ids.
1817 $authenticatedrole = $DB->get_record('role', array('shortname' => 'user'), '*', MUST_EXIST
);
1818 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST
);
1819 $emptyroleid = create_role('No capabilities', 'empty', 'A role with no capabilties');
1820 $course = $this->getDataGenerator()->create_course();
1821 $coursecontext = context_course
::instance($course->id
);
1823 // Instantiate the cache instance, since that does DB queries (get_config)
1824 // and we don't care about those.
1825 cache
::make('core', 'roledefs');
1827 // One database query is not necessarily one database read, it seems. Find out how many.
1828 $startdbreads = $DB->perf_get_reads();
1829 $rs = $DB->get_recordset('user');
1831 $readsperquery = $DB->perf_get_reads() - $startdbreads;
1833 // Now load some role definitions, and check when it queries the database.
1835 // Load the capabilities for two roles. Should be one query.
1836 $startdbreads = $DB->perf_get_reads();
1837 get_role_definitions([$authenticatedrole->id
, $studentrole->id
]);
1838 $this->assertEquals(1 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1840 // Load the capabilities for same two roles. Should not query the DB.
1841 $startdbreads = $DB->perf_get_reads();
1842 get_role_definitions([$authenticatedrole->id
, $studentrole->id
]);
1843 $this->assertEquals(0 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1845 // Include a third role. Should do one DB query.
1846 $startdbreads = $DB->perf_get_reads();
1847 get_role_definitions([$authenticatedrole->id
, $studentrole->id
, $emptyroleid]);
1848 $this->assertEquals(1 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1850 // Repeat call. No DB queries.
1851 $startdbreads = $DB->perf_get_reads();
1852 get_role_definitions([$authenticatedrole->id
, $studentrole->id
, $emptyroleid]);
1853 $this->assertEquals(0 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1856 role_change_permission($studentrole->id
, $coursecontext, 'moodle/course:tag', CAP_ALLOW
);
1858 // Should now know to do one query.
1859 $startdbreads = $DB->perf_get_reads();
1860 get_role_definitions([$authenticatedrole->id
, $studentrole->id
]);
1861 $this->assertEquals(1 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1863 // Now clear the in-memory cache, and verify that it does not query the DB.
1864 // Cannot use accesslib_clear_all_caches_for_unit_testing since that also
1865 // clears the MUC cache.
1866 global $ACCESSLIB_PRIVATE;
1867 $ACCESSLIB_PRIVATE->cacheroledefs
= array();
1869 // Get all roles. Should not need the DB.
1870 $startdbreads = $DB->perf_get_reads();
1871 get_role_definitions([$authenticatedrole->id
, $studentrole->id
, $emptyroleid]);
1872 $this->assertEquals(0 * $readsperquery, $DB->perf_get_reads() - $startdbreads);
1876 * Tests get_user_capability_course() which checks a capability across all courses.
1878 public function test_get_user_capability_course() {
1881 $this->resetAfterTest();
1883 $generator = $this->getDataGenerator();
1884 $cap = 'moodle/course:view';
1886 // The structure being created here is this:
1888 // All tests work with the single capability 'moodle/course:view'.
1890 // ROLE DEF/OVERRIDE ROLE ASSIGNS
1891 // Role: Allow Prohib Empty Def user u1 u2 u3 u4 u5 u6 u7 u8
1892 // System ALLOW PROHIBIT A E A+E
1903 // Front-page and guest role stuff from the end of this test not included in the diagram.
1905 // Create a role which allows course:view and one that prohibits it, and one neither.
1906 $allowroleid = $generator->create_role();
1907 $prohibitroleid = $generator->create_role();
1908 $emptyroleid = $generator->create_role();
1909 $systemcontext = context_system
::instance();
1910 assign_capability($cap, CAP_ALLOW
, $allowroleid, $systemcontext->id
);
1911 assign_capability($cap, CAP_PROHIBIT
, $prohibitroleid, $systemcontext->id
);
1913 // Create two categories (nested).
1914 $cat1 = $generator->create_category();
1915 $cat2 = $generator->create_category(['parent' => $cat1->id
]);
1917 // Create six courses - two in cat1, two in cat2, and two in default category.
1918 // Shortnames are used for a sorting test. Otherwise they are not significant.
1919 $c1 = $generator->create_course(['category' => $cat1->id
, 'shortname' => 'Z']);
1920 $c2 = $generator->create_course(['category' => $cat1->id
, 'shortname' => 'Y']);
1921 $c3 = $generator->create_course(['category' => $cat2->id
, 'shortname' => 'X']);
1922 $c4 = $generator->create_course(['category' => $cat2->id
]);
1923 $c5 = $generator->create_course();
1924 $c6 = $generator->create_course();
1926 // Category overrides: in cat 1, empty role is allowed; in cat 2, empty role is prevented.
1927 assign_capability($cap, CAP_ALLOW
, $emptyroleid,
1928 context_coursecat
::instance($cat1->id
)->id
);
1929 assign_capability($cap, CAP_PREVENT
, $emptyroleid,
1930 context_coursecat
::instance($cat2->id
)->id
);
1932 // Course overrides: in C5, allow role is prevented; in C6, empty role is prohibited; in
1933 // C3, empty role is allowed.
1934 assign_capability($cap, CAP_PREVENT
, $allowroleid,
1935 context_course
::instance($c5->id
)->id
);
1936 assign_capability($cap, CAP_PROHIBIT
, $emptyroleid,
1937 context_course
::instance($c6->id
)->id
);
1938 assign_capability($cap, CAP_ALLOW
, $emptyroleid,
1939 context_course
::instance($c3->id
)->id
);
1940 assign_capability($cap, CAP_ALLOW
, $prohibitroleid,
1941 context_course
::instance($c2->id
)->id
);
1943 // User 1 has no roles except default user role.
1944 $u1 = $generator->create_user();
1946 // It returns false (annoyingly) if there are no courses.
1947 $this->assertFalse(get_user_capability_course($cap, $u1->id
, true, '', 'id'));
1949 // Final override: in C1, default user role is allowed.
1950 assign_capability($cap, CAP_ALLOW
, $CFG->defaultuserroleid
,
1951 context_course
::instance($c1->id
)->id
);
1953 // Should now get C1 only.
1954 $courses = get_user_capability_course($cap, $u1->id
, true, '', 'id');
1955 $this->assert_course_ids([$c1->id
], $courses);
1957 // User 2 has allow role (system wide).
1958 $u2 = $generator->create_user();
1959 role_assign($allowroleid, $u2->id
, $systemcontext->id
);
1961 // Should get everything except C5.
1962 $courses = get_user_capability_course($cap, $u2->id
, true, '', 'id');
1963 $this->assert_course_ids([SITEID
, $c1->id
, $c2->id
, $c3->id
, $c4->id
, $c6->id
], $courses);
1965 // User 3 has empty role (system wide).
1966 $u3 = $generator->create_user();
1967 role_assign($emptyroleid, $u3->id
, $systemcontext->id
);
1969 // Should get cat 1 courses but not cat2, except C3.
1970 $courses = get_user_capability_course($cap, $u3->id
, true, '', 'id');
1971 $this->assert_course_ids([$c1->id
, $c2->id
, $c3->id
], $courses);
1973 // User 4 has allow and empty role (system wide).
1974 $u4 = $generator->create_user();
1975 role_assign($allowroleid, $u4->id
, $systemcontext->id
);
1976 role_assign($emptyroleid, $u4->id
, $systemcontext->id
);
1978 // Should get everything except C5 and C6.
1979 $courses = get_user_capability_course($cap, $u4->id
, true, '', 'id');
1980 $this->assert_course_ids([SITEID
, $c1->id
, $c2->id
, $c3->id
, $c4->id
], $courses);
1982 // User 5 has allow role in default category only.
1983 $u5 = $generator->create_user();
1984 role_assign($allowroleid, $u5->id
, context_coursecat
::instance($c5->category
)->id
);
1986 // Should get C1 and the default category courses but not C5.
1987 $courses = get_user_capability_course($cap, $u5->id
, true, '', 'id');
1988 $this->assert_course_ids([$c1->id
, $c6->id
], $courses);
1990 // User 6 has a bunch of course roles: prohibit role in C1, empty role in C3, allow role in
1992 $u6 = $generator->create_user();
1993 role_assign($prohibitroleid, $u6->id
, context_course
::instance($c1->id
)->id
);
1994 role_assign($emptyroleid, $u6->id
, context_course
::instance($c3->id
)->id
);
1995 role_assign($allowroleid, $u6->id
, context_course
::instance($c5->id
)->id
);
1997 // Should get C3 only because the allow role is prevented in C5.
1998 $courses = get_user_capability_course($cap, $u6->id
, true, '', 'id');
1999 $this->assert_course_ids([$c3->id
], $courses);
2001 // User 7 has empty role in C2.
2002 $u7 = $generator->create_user();
2003 role_assign($emptyroleid, $u7->id
, context_course
::instance($c2->id
)->id
);
2005 // Should get C1 by the default user role override, and C2 by the cat1 level override.
2006 $courses = get_user_capability_course($cap, $u7->id
, true, '', 'id');
2007 $this->assert_course_ids([$c1->id
, $c2->id
], $courses);
2009 // User 8 has prohibit role as system context, to verify that prohibits can't be overridden.
2010 $u8 = $generator->create_user();
2011 role_assign($prohibitroleid, $u8->id
, context_course
::instance($c2->id
)->id
);
2013 // Should get C1 by the default user role override, no other courses because the prohibit cannot be overridden.
2014 $courses = get_user_capability_course($cap, $u8->id
, true, '', 'id');
2015 $this->assert_course_ids([$c1->id
], $courses);
2017 // Admin user gets everything....
2018 $courses = get_user_capability_course($cap, get_admin()->id
, true, '', 'id');
2019 $this->assert_course_ids([SITEID
, $c1->id
, $c2->id
, $c3->id
, $c4->id
, $c5->id
, $c6->id
],
2022 // Unless you turn off doanything, when it only has the things a user with no role does.
2023 $courses = get_user_capability_course($cap, get_admin()->id
, false, '', 'id');
2024 $this->assert_course_ids([$c1->id
], $courses);
2026 // Using u3 as an example, test the limit feature.
2027 $courses = get_user_capability_course($cap, $u3->id
, true, '', 'id', 2);
2028 $this->assert_course_ids([$c1->id
, $c2->id
], $courses);
2031 $courses = get_user_capability_course($cap, $u3->id
, true, '', 'shortname');
2032 $this->assert_course_ids([$c3->id
, $c2->id
, $c1->id
], $courses);
2034 // Check returned fields - default.
2035 $courses = get_user_capability_course($cap, $u3->id
, true, '', 'id');
2036 $this->assertEquals((object)['id' => $c1->id
], $courses[0]);
2038 // Add a selection of fields, including the context ones with special handling.
2039 $courses = get_user_capability_course($cap, $u3->id
, true, 'shortname, ctxlevel, ctxdepth, ctxinstance', 'id');
2040 $this->assertEquals((object)['id' => $c1->id
, 'shortname' => 'Z', 'ctxlevel' => 50,
2041 'ctxdepth' => 3, 'ctxinstance' => $c1->id
], $courses[0]);
2043 // Test front page role - user 1 has no roles, but if we change the front page role
2044 // definition so that it has our capability, then they should see the front page course.
2046 assign_capability($cap, CAP_ALLOW
, $CFG->defaultfrontpageroleid
, $systemcontext->id
);
2047 $courses = get_user_capability_course($cap, $u1->id
, true, '', 'id');
2048 $this->assert_course_ids([SITEID
, $c1->id
], $courses);
2050 // Check that temporary guest access (in this case, given on course 2 for user 1)
2051 // also is included, if it has this capability.
2052 assign_capability($cap, CAP_ALLOW
, $CFG->guestroleid
, $systemcontext->id
);
2053 $this->setUser($u1);
2054 load_temp_course_role(context_course
::instance($c2->id
), $CFG->guestroleid
);
2055 $courses = get_user_capability_course($cap, $USER->id
, true, '', 'id');
2056 $this->assert_course_ids([SITEID
, $c1->id
, $c2->id
], $courses);
2060 * Extracts an array of course ids to make the above test script shorter.
2062 * @param int[] $expected Array of expected course ids
2063 * @param stdClass[] $courses Array of course objects
2065 protected function assert_course_ids(array $expected, array $courses) {
2066 $courseids = array_map(function($c) {
2069 $this->assertEquals($expected, $courseids);
2073 * Test if course creator future capability lookup works.
2075 public function test_guess_if_creator_will_have_course_capability() {
2076 global $DB, $CFG, $USER;
2078 $this->resetAfterTest();
2080 $category = $this->getDataGenerator()->create_category();
2081 $course = $this->getDataGenerator()->create_course(array('category'=>$category->id
));
2083 $syscontext = context_system
::instance();
2084 $categorycontext = context_coursecat
::instance($category->id
);
2085 $coursecontext = context_course
::instance($course->id
);
2086 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST
);
2087 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST
);
2088 $creatorrole = $DB->get_record('role', array('shortname'=>'coursecreator'), '*', MUST_EXIST
);
2089 $managerrole = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST
);
2091 $this->assertEquals($teacherrole->id
, $CFG->creatornewroleid
);
2093 $creator = $this->getDataGenerator()->create_user();
2094 $manager = $this->getDataGenerator()->create_user();
2095 role_assign($managerrole->id
, $manager->id
, $categorycontext);
2097 $this->assertFalse(has_capability('moodle/course:view', $categorycontext, $creator));
2098 $this->assertFalse(has_capability('moodle/role:assign', $categorycontext, $creator));
2099 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $creator));
2100 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $creator));
2101 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $creator));
2102 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $creator));
2104 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext, $manager));
2105 $this->assertTrue(has_capability('moodle/course:visibility', $categorycontext, $manager));
2106 $this->assertTrue(has_capability('moodle/course:visibility', $coursecontext, $manager));
2107 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $manager->id
));
2108 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $manager->id
));
2110 $this->assertEquals(0, $USER->id
);
2111 $this->assertFalse(has_capability('moodle/course:view', $categorycontext));
2112 $this->assertFalse(has_capability('moodle/role:assign', $categorycontext));
2113 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext));
2114 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext));
2115 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext));
2116 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext));
2118 $this->setUser($manager);
2119 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext));
2120 $this->assertTrue(has_capability('moodle/course:visibility', $categorycontext));
2121 $this->assertTrue(has_capability('moodle/course:visibility', $coursecontext));
2122 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext));
2123 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext));
2125 $this->setAdminUser();
2126 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext));
2127 $this->assertTrue(has_capability('moodle/course:visibility', $categorycontext));
2128 $this->assertTrue(has_capability('moodle/course:visibility', $coursecontext));
2129 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext));
2130 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext));
2133 role_assign($creatorrole->id
, $creator->id
, $categorycontext);
2135 $this->assertFalse(has_capability('moodle/role:assign', $categorycontext, $creator));
2136 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $creator));
2137 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $creator));
2138 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $creator));
2139 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $creator));
2141 $this->setUser($creator);
2142 $this->assertFalse(has_capability('moodle/role:assign', $categorycontext, null));
2143 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, null));
2144 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, null));
2145 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, null));
2146 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, null));
2149 set_config('creatornewroleid', $studentrole->id
);
2151 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $creator));
2152 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $creator));
2153 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $creator));
2154 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $creator));
2156 set_config('creatornewroleid', $teacherrole->id
);
2158 role_change_permission($managerrole->id
, $categorycontext, 'moodle/course:visibility', CAP_PREVENT
);
2159 role_assign($creatorrole->id
, $manager->id
, $categorycontext);
2161 $this->assertTrue(has_capability('moodle/course:view', $categorycontext, $manager));
2162 $this->assertTrue(has_capability('moodle/course:view', $coursecontext, $manager));
2163 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext, $manager));
2164 $this->assertTrue(has_capability('moodle/role:assign', $coursecontext, $manager));
2165 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $manager));
2166 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $manager));
2167 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $manager));
2168 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $manager));
2170 role_change_permission($managerrole->id
, $categorycontext, 'moodle/course:view', CAP_PREVENT
);
2171 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext, $manager));
2172 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $manager));
2173 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $manager));
2174 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $manager));
2175 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $manager));
2177 $this->getDataGenerator()->enrol_user($manager->id
, $course->id
, 0);
2179 $this->assertTrue(has_capability('moodle/role:assign', $categorycontext, $manager));
2180 $this->assertTrue(has_capability('moodle/role:assign', $coursecontext, $manager));
2181 $this->assertTrue(is_enrolled($coursecontext, $manager));
2182 $this->assertFalse(has_capability('moodle/course:visibility', $categorycontext, $manager));
2183 $this->assertFalse(has_capability('moodle/course:visibility', $coursecontext, $manager));
2184 $this->assertTrue(guess_if_creator_will_have_course_capability('moodle/course:visibility', $categorycontext, $manager));
2185 $this->assertFalse(guess_if_creator_will_have_course_capability('moodle/course:visibility', $coursecontext, $manager));
2190 guess_if_creator_will_have_course_capability('moodle/course:visibility', $syscontext, $creator);
2191 $this->fail('Exception expected when non course/category context passed to guess_if_creator_will_have_course_capability()');
2192 } catch (moodle_exception
$e) {
2193 $this->assertInstanceOf('coding_exception', $e);
2198 * Test require_capability() exceptions.
2200 public function test_require_capability() {
2201 $this->resetAfterTest();
2203 $syscontext = context_system
::instance();
2206 $this->assertFalse(has_capability('moodle/site:config', $syscontext));
2208 require_capability('moodle/site:config', $syscontext);
2209 $this->fail('Exception expected from require_capability()');
2210 } catch (moodle_exception
$e) {
2211 $this->assertInstanceOf('required_capability_exception', $e);
2213 $this->setAdminUser();
2214 $this->assertFalse(has_capability('moodle/site:config', $syscontext, 0));
2216 require_capability('moodle/site:config', $syscontext, 0);
2217 $this->fail('Exception expected from require_capability()');
2218 } catch (moodle_exception
$e) {
2219 $this->assertInstanceOf('required_capability_exception', $e);
2221 $this->assertFalse(has_capability('moodle/site:config', $syscontext, null, false));
2223 require_capability('moodle/site:config', $syscontext, null, false);
2224 $this->fail('Exception expected from require_capability()');
2225 } catch (moodle_exception
$e) {
2226 $this->assertInstanceOf('required_capability_exception', $e);
2231 * Test that enrolled users SQL does not return any values for users in
2234 public function test_get_enrolled_sql_different_course() {
2237 $this->resetAfterTest();
2239 $course = $this->getDataGenerator()->create_course();
2240 $context = context_course
::instance($course->id
);
2241 $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST
);
2242 $user = $this->getDataGenerator()->create_user();
2244 // This user should not appear anywhere, we're not interested in that context.
2245 $course2 = $this->getDataGenerator()->create_course();
2246 $this->getDataGenerator()->enrol_user($user->id
, $course2->id
, $student->id
);
2248 $enrolled = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, false);
2249 $active = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, true);
2250 $suspended = get_suspended_userids($context);
2252 $this->assertFalse(isset($enrolled[$user->id
]));
2253 $this->assertFalse(isset($active[$user->id
]));
2254 $this->assertFalse(isset($suspended[$user->id
]));
2255 $this->assertCount(0, $enrolled);
2256 $this->assertCount(0, $active);
2257 $this->assertCount(0, $suspended);
2261 * Test that enrolled users SQL does not return any values for role
2262 * assignments without an enrolment.
2264 public function test_get_enrolled_sql_role_only() {
2267 $this->resetAfterTest();
2269 $course = $this->getDataGenerator()->create_course();
2270 $context = context_course
::instance($course->id
);
2271 $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST
);
2272 $user = $this->getDataGenerator()->create_user();
2274 // Role assignment is not the same as course enrollment.
2275 role_assign($student->id
, $user->id
, $context->id
);
2277 $enrolled = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, false);
2278 $active = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, true);
2279 $suspended = get_suspended_userids($context);
2281 $this->assertFalse(isset($enrolled[$user->id
]));
2282 $this->assertFalse(isset($active[$user->id
]));
2283 $this->assertFalse(isset($suspended[$user->id
]));
2284 $this->assertCount(0, $enrolled);
2285 $this->assertCount(0, $active);
2286 $this->assertCount(0, $suspended);
2290 * Test that multiple enrolments for the same user are counted correctly.
2292 public function test_get_enrolled_sql_multiple_enrolments() {
2295 $this->resetAfterTest();
2297 $course = $this->getDataGenerator()->create_course();
2298 $context = context_course
::instance($course->id
);
2299 $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST
);
2300 $user = $this->getDataGenerator()->create_user();
2302 // Add a suspended enrol.
2303 $selfinstance = $DB->get_record('enrol', array('courseid' => $course->id
, 'enrol' => 'self'));
2304 $selfplugin = enrol_get_plugin('self');
2305 $selfplugin->update_status($selfinstance, ENROL_INSTANCE_ENABLED
);
2306 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, $student->id
, 'self', 0, 0, ENROL_USER_SUSPENDED
);
2308 // Should be enrolled, but not active - user is suspended.
2309 $enrolled = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, false);
2310 $active = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, true);
2311 $suspended = get_suspended_userids($context);
2313 $this->assertTrue(isset($enrolled[$user->id
]));
2314 $this->assertFalse(isset($active[$user->id
]));
2315 $this->assertTrue(isset($suspended[$user->id
]));
2316 $this->assertCount(1, $enrolled);
2317 $this->assertCount(0, $active);
2318 $this->assertCount(1, $suspended);
2320 // Add an active enrol for the user. Any active enrol makes them enrolled.
2321 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, $student->id
);
2323 // User should be active now.
2324 $enrolled = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, false);
2325 $active = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, true);
2326 $suspended = get_suspended_userids($context);
2328 $this->assertTrue(isset($enrolled[$user->id
]));
2329 $this->assertTrue(isset($active[$user->id
]));
2330 $this->assertFalse(isset($suspended[$user->id
]));
2331 $this->assertCount(1, $enrolled);
2332 $this->assertCount(1, $active);
2333 $this->assertCount(0, $suspended);
2338 * Test that enrolled users SQL does not return any values for users
2339 * without a group when $context is not a valid course context.
2341 public function test_get_enrolled_sql_userswithoutgroup() {
2344 $this->resetAfterTest();
2346 $systemcontext = context_system
::instance();
2347 $course = $this->getDataGenerator()->create_course();
2348 $coursecontext = context_course
::instance($course->id
);
2349 $user1 = $this->getDataGenerator()->create_user();
2350 $user2 = $this->getDataGenerator()->create_user();
2352 $this->getDataGenerator()->enrol_user($user1->id
, $course->id
);
2353 $this->getDataGenerator()->enrol_user($user2->id
, $course->id
);
2355 $group = $this->getDataGenerator()->create_group(array('courseid' => $course->id
));
2356 groups_add_member($group, $user1);
2358 $enrolled = get_enrolled_users($coursecontext);
2359 $this->assertCount(2, $enrolled);
2361 // Get users without any group on the course context.
2362 $enrolledwithoutgroup = get_enrolled_users($coursecontext, '', USERSWITHOUTGROUP
);
2363 $this->assertCount(1, $enrolledwithoutgroup);
2364 $this->assertFalse(isset($enrolledwithoutgroup[$user1->id
]));
2366 // Get users without any group on the system context (it should throw an exception).
2367 $this->expectException('coding_exception');
2368 get_enrolled_users($systemcontext, '', USERSWITHOUTGROUP
);
2371 public function get_enrolled_sql_provider() {
2374 // Two users who are enrolled.
2392 // A user who is suspended.
2395 'status' => ENROL_USER_SUSPENDED
,
2397 'suspended' => true,
2414 'status' => ENROL_USER_SUSPENDED
,
2416 'suspended' => true,
2426 // One user who is not yet enrolled.
2429 'timestart' => DAYSECS
,
2432 'suspended' => true,
2442 // One user who is no longer enrolled
2445 'timeend' => -DAYSECS
,
2448 'suspended' => true,
2458 // One user who is not yet enrolled, and one who is no longer enrolled.
2461 'timeend' => -DAYSECS
,
2464 'suspended' => true,
2467 'timestart' => DAYSECS
,
2470 'suspended' => true,
2483 * @dataProvider get_enrolled_sql_provider
2485 public function test_get_enrolled_sql_course($users, $counts) {
2488 $this->resetAfterTest();
2490 $course = $this->getDataGenerator()->create_course();
2491 $context = context_course
::instance($course->id
);
2492 $student = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST
);
2493 $createdusers = array();
2495 foreach ($users as &$userdata) {
2496 $user = $this->getDataGenerator()->create_user();
2497 $userdata['id'] = $user->id
;
2502 if (isset($userdata['timestart'])) {
2503 $timestart = time() +
$userdata['timestart'];
2505 if (isset($userdata['timeend'])) {
2506 $timeend = time() +
$userdata['timeend'];
2508 if (isset($userdata['status'])) {
2509 $status = $userdata['status'];
2512 // Enrol the user in the course.
2513 $this->getDataGenerator()->enrol_user($user->id
, $course->id
, $student->id
, 'manual', $timestart, $timeend, $status);
2516 // After all users have been enroled, check expectations.
2517 $enrolled = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, false);
2518 $active = get_enrolled_users($context, '', 0, 'u.id', null, 0, 0, true);
2519 $suspended = get_suspended_userids($context);
2521 foreach ($users as $userdata) {
2522 if (isset($userdata['enrolled']) && $userdata['enrolled']) {
2523 $this->assertTrue(isset($enrolled[$userdata['id']]));
2525 $this->assertFalse(isset($enrolled[$userdata['id']]));
2528 if (isset($userdata['active']) && $userdata['active']) {
2529 $this->assertTrue(isset($active[$userdata['id']]));
2531 $this->assertFalse(isset($active[$userdata['id']]));
2534 if (isset($userdata['suspended']) && $userdata['suspended']) {
2535 $this->assertTrue(isset($suspended[$userdata['id']]));
2537 $this->assertFalse(isset($suspended[$userdata['id']]));
2541 $this->assertCount($counts['enrolled'], $enrolled);
2542 $this->assertCount($counts['active'], $active);
2543 $this->assertCount($counts['suspended'], $suspended);
2547 * A small functional test of permission evaluations.
2549 public function test_permission_evaluation() {
2550 global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;
2552 $this->resetAfterTest();
2554 $generator = $this->getDataGenerator();
2556 // Fill the site with some real data.
2557 $testcategories = array();
2558 $testcourses = array();
2559 $testpages = array();
2560 $testblocks = array();
2561 $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
2563 $systemcontext = context_system
::instance();
2564 $frontpagecontext = context_course
::instance(SITEID
);
2566 // Add block to system context.
2567 $bi = $generator->create_block('online_users');
2568 context_block
::instance($bi->id
);
2569 $testblocks[] = $bi->id
;
2572 $testusers = array();
2573 for ($i=0; $i<20; $i++
) {
2574 $user = $generator->create_user();
2575 $testusers[$i] = $user->id
;
2576 $usercontext = context_user
::instance($user->id
);
2578 // Add block to user profile.
2579 $bi = $generator->create_block('online_users', array('parentcontextid'=>$usercontext->id
));
2580 $testblocks[] = $bi->id
;
2582 // Deleted user - should be ignored everywhere, can not have context.
2583 $generator->create_user(array('deleted'=>1));
2585 // Add block to frontpage.
2586 $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagecontext->id
));
2587 $frontpageblockcontext = context_block
::instance($bi->id
);
2588 $testblocks[] = $bi->id
;
2590 // Add a resource to frontpage.
2591 $page = $generator->create_module('page', array('course'=>$SITE->id
));
2592 $testpages[] = $page->cmid
;
2593 $frontpagepagecontext = context_module
::instance($page->cmid
);
2595 // Add block to frontpage resource.
2596 $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagepagecontext->id
));
2597 $frontpagepageblockcontext = context_block
::instance($bi->id
);
2598 $testblocks[] = $bi->id
;
2600 // Some nested course categories with courses.
2601 $manualenrol = enrol_get_plugin('manual');
2603 for ($i=0; $i<5; $i++
) {
2604 $cat = $generator->create_category(array('parent'=>$parentcat));
2605 $testcategories[] = $cat->id
;
2606 $catcontext = context_coursecat
::instance($cat->id
);
2607 $parentcat = $cat->id
;
2613 // Add resource to each category.
2614 $bi = $generator->create_block('online_users', array('parentcontextid'=>$catcontext->id
));
2615 context_block
::instance($bi->id
);
2617 // Add a few courses to each category.
2618 for ($j=0; $j<6; $j++
) {
2619 $course = $generator->create_course(array('category'=>$cat->id
));
2620 $testcourses[] = $course->id
;
2621 $coursecontext = context_course
::instance($course->id
);
2626 // Add manual enrol instance.
2627 $manualenrol->add_default_instance($DB->get_record('course', array('id'=>$course->id
)));
2629 // Add block to each course.
2630 $bi = $generator->create_block('online_users', array('parentcontextid'=>$coursecontext->id
));
2631 $testblocks[] = $bi->id
;
2633 // Add a resource to each course.
2634 $page = $generator->create_module('page', array('course'=>$course->id
));
2635 $testpages[] = $page->cmid
;
2636 $modcontext = context_module
::instance($page->cmid
);
2638 // Add block to each module.
2639 $bi = $generator->create_block('online_users', array('parentcontextid'=>$modcontext->id
));
2640 $testblocks[] = $bi->id
;
2644 // Make sure all contexts were created properly.
2645 $count = 1; // System.
2646 $count +
= $DB->count_records('user', array('deleted'=>0));
2647 $count +
= $DB->count_records('course_categories');
2648 $count +
= $DB->count_records('course');
2649 $count +
= $DB->count_records('course_modules');
2650 $count +
= $DB->count_records('block_instances');
2651 $this->assertEquals($count, $DB->count_records('context'));
2652 $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
2653 $this->assertEquals(0, $DB->count_records('context', array('path'=>null)));
2656 // Test context_helper::get_level_name() method.
2658 $levels = context_helper
::get_all_levels();
2659 foreach ($levels as $level => $classname) {
2660 $name = context_helper
::get_level_name($level);
2661 $this->assertNotEmpty($name);
2665 // Test context::instance_by_id(), context_xxx::instance() methods.
2667 $context = context
::instance_by_id($frontpagecontext->id
);
2668 $this->assertSame(CONTEXT_COURSE
, $context->contextlevel
);
2669 $this->assertFalse(context
::instance_by_id(-1, IGNORE_MISSING
));
2671 context
::instance_by_id(-1);
2672 $this->fail('exception expected');
2673 } catch (moodle_exception
$e) {
2674 $this->assertTrue(true);
2676 $this->assertInstanceOf('context_system', context_system
::instance());
2677 $this->assertInstanceOf('context_coursecat', context_coursecat
::instance($testcategories[0]));
2678 $this->assertInstanceOf('context_course', context_course
::instance($testcourses[0]));
2679 $this->assertInstanceOf('context_module', context_module
::instance($testpages[0]));
2680 $this->assertInstanceOf('context_block', context_block
::instance($testblocks[0]));
2682 $this->assertFalse(context_coursecat
::instance(-1, IGNORE_MISSING
));
2683 $this->assertFalse(context_course
::instance(-1, IGNORE_MISSING
));
2684 $this->assertFalse(context_module
::instance(-1, IGNORE_MISSING
));
2685 $this->assertFalse(context_block
::instance(-1, IGNORE_MISSING
));
2687 context_coursecat
::instance(-1);
2688 $this->fail('exception expected');
2689 } catch (moodle_exception
$e) {
2690 $this->assertTrue(true);
2693 context_course
::instance(-1);
2694 $this->fail('exception expected');
2695 } catch (moodle_exception
$e) {
2696 $this->assertTrue(true);
2699 context_module
::instance(-1);
2700 $this->fail('exception expected');
2701 } catch (moodle_exception
$e) {
2702 $this->assertTrue(true);
2705 context_block
::instance(-1);
2706 $this->fail('exception expected');
2707 } catch (moodle_exception
$e) {
2708 $this->assertTrue(true);
2712 // Test $context->get_url(), $context->get_context_name(), $context->get_capabilities() methods.
2714 $testcontexts = array();
2715 $testcontexts[CONTEXT_SYSTEM
] = context_system
::instance();
2716 $testcontexts[CONTEXT_COURSECAT
] = context_coursecat
::instance($testcategories[0]);
2717 $testcontexts[CONTEXT_COURSE
] = context_course
::instance($testcourses[0]);
2718 $testcontexts[CONTEXT_MODULE
] = context_module
::instance($testpages[0]);
2719 $testcontexts[CONTEXT_BLOCK
] = context_block
::instance($testblocks[0]);
2721 foreach ($testcontexts as $context) {
2722 $name = $context->get_context_name(true, true);
2723 $this->assertNotEmpty($name);
2725 $this->assertInstanceOf('moodle_url', $context->get_url());
2727 $caps = $context->get_capabilities();
2728 $this->assertTrue(is_array($caps));
2729 foreach ($caps as $cap) {
2731 $this->assertSame(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask'));
2734 unset($testcontexts);
2736 // Test $context->get_course_context() method.
2738 $this->assertFalse($systemcontext->get_course_context(false));
2740 $systemcontext->get_course_context();
2741 $this->fail('exception expected');
2742 } catch (moodle_exception
$e) {
2743 $this->assertInstanceOf('coding_exception', $e);
2745 $context = context_coursecat
::instance($testcategories[0]);
2746 $this->assertFalse($context->get_course_context(false));
2748 $context->get_course_context();
2749 $this->fail('exception expected');
2750 } catch (moodle_exception
$e) {
2751 $this->assertInstanceOf('coding_exception', $e);
2753 $this->assertEquals($frontpagecontext, $frontpagecontext->get_course_context(true));
2754 $this->assertEquals($frontpagecontext, $frontpagepagecontext->get_course_context(true));
2755 $this->assertEquals($frontpagecontext, $frontpagepageblockcontext->get_course_context(true));
2758 // Test $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() methods.
2760 $userid = reset($testusers);
2761 $usercontext = context_user
::instance($userid);
2762 $this->assertEquals($systemcontext, $usercontext->get_parent_context());
2763 $this->assertEquals(array($systemcontext->id
=>$systemcontext), $usercontext->get_parent_contexts());
2764 $this->assertEquals(array($usercontext->id
=>$usercontext, $systemcontext->id
=>$systemcontext), $usercontext->get_parent_contexts(true));
2766 $this->assertEquals(array(), $systemcontext->get_parent_contexts());
2767 $this->assertEquals(array($systemcontext->id
=>$systemcontext), $systemcontext->get_parent_contexts(true));
2768 $this->assertEquals(array(), $systemcontext->get_parent_context_ids());
2769 $this->assertEquals(array($systemcontext->id
), $systemcontext->get_parent_context_ids(true));
2770 $this->assertEquals(array(), $systemcontext->get_parent_context_paths());
2771 $this->assertEquals(array($systemcontext->id
=> $systemcontext->path
), $systemcontext->get_parent_context_paths(true));
2773 $this->assertEquals($systemcontext, $frontpagecontext->get_parent_context());
2774 $this->assertEquals(array($systemcontext->id
=>$systemcontext), $frontpagecontext->get_parent_contexts());
2775 $this->assertEquals(array($frontpagecontext->id
=>$frontpagecontext, $systemcontext->id
=>$systemcontext), $frontpagecontext->get_parent_contexts(true));
2776 $this->assertEquals(array($systemcontext->id
), $frontpagecontext->get_parent_context_ids());
2777 $this->assertEquals(array($frontpagecontext->id
, $systemcontext->id
), $frontpagecontext->get_parent_context_ids(true));
2778 $this->assertEquals(array($systemcontext->id
=> $systemcontext->path
), $frontpagecontext->get_parent_context_paths());
2779 $expected = array($systemcontext->id
=> $systemcontext->path
, $frontpagecontext->id
=> $frontpagecontext->path
);
2780 $this->assertEquals($expected, $frontpagecontext->get_parent_context_paths(true));
2782 $this->assertFalse($systemcontext->get_parent_context());
2783 $frontpagecontext = context_course
::instance($SITE->id
);
2784 $parent = $systemcontext;
2785 foreach ($testcategories as $catid) {
2786 $catcontext = context_coursecat
::instance($catid);
2787 $this->assertEquals($parent, $catcontext->get_parent_context());
2788 $parent = $catcontext;
2790 $this->assertEquals($frontpagecontext, $frontpagepagecontext->get_parent_context());
2791 $this->assertEquals($frontpagecontext, $frontpageblockcontext->get_parent_context());
2792 $this->assertEquals($frontpagepagecontext, $frontpagepageblockcontext->get_parent_context());
2795 // Test $context->get_child_contexts() method.
2797 $children = $systemcontext->get_child_contexts();
2798 $this->resetDebugging();
2799 $this->assertEquals(count($children)+
1, $DB->count_records('context'));
2801 $context = context_coursecat
::instance($testcategories[3]);
2802 $children = $context->get_child_contexts();
2806 foreach ($children as $child) {
2807 if ($child->contextlevel
== CONTEXT_COURSECAT
) {
2810 if ($child->contextlevel
== CONTEXT_COURSE
) {
2813 if ($child->contextlevel
== CONTEXT_BLOCK
) {
2817 $this->assertCount(8, $children);
2818 $this->assertEquals(1, $countcats);
2819 $this->assertEquals(6, $countcourses);
2820 $this->assertEquals(1, $countblocks);
2822 $context = context_course
::instance($testcourses[2]);
2823 $children = $context->get_child_contexts();
2825 $context = context_module
::instance($testpages[3]);
2826 $children = $context->get_child_contexts();
2827 $this->assertCount(1, $children);
2829 $context = context_block
::instance($testblocks[1]);
2830 $children = $context->get_child_contexts();
2831 $this->assertCount(0, $children);
2835 unset($countcourses);
2836 unset($countblocks);
2839 // Test context_helper::reset_caches() method.
2841 context_helper
::reset_caches();
2842 $this->assertEquals(0, context_inspection
::test_context_cache_size());
2843 context_course
::instance($SITE->id
);
2844 $this->assertEquals(1, context_inspection
::test_context_cache_size());
2847 // Test context preloading.
2849 context_helper
::reset_caches();
2850 $sql = "SELECT ".context_helper
::get_preload_record_columns_sql('c')."
2852 WHERE c.contextlevel <> ".CONTEXT_SYSTEM
;
2853 $records = $DB->get_records_sql($sql);
2854 $firstrecord = reset($records);
2855 $columns = context_helper
::get_preload_record_columns('c');
2856 $firstrecord = (array)$firstrecord;
2857 $this->assertSame(array_keys($firstrecord), array_values($columns));
2858 context_helper
::reset_caches();
2859 foreach ($records as $record) {
2860 context_helper
::preload_from_record($record);
2861 $this->assertEquals(new stdClass(), $record);
2863 $this->assertEquals(count($records), context_inspection
::test_context_cache_size());
2867 context_helper
::reset_caches();
2868 context_helper
::preload_course($SITE->id
);
2869 $numfrontpagemodules = $DB->count_records('course_modules', array('course' => $SITE->id
));
2870 $this->assertEquals(3 +
$numfrontpagemodules, context_inspection
::test_context_cache_size()); // Depends on number of default blocks.
2872 // Test assign_capability(), unassign_capability() functions.
2874 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id
, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2875 $this->assertFalse($rc);
2876 assign_capability('moodle/site:accessallgroups', CAP_ALLOW
, $allroles['teacher'], $frontpagecontext->id
);
2877 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id
, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2878 $this->assertEquals(CAP_ALLOW
, $rc->permission
);
2879 assign_capability('moodle/site:accessallgroups', CAP_PREVENT
, $allroles['teacher'], $frontpagecontext->id
);
2880 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id
, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2881 $this->assertEquals(CAP_ALLOW
, $rc->permission
);
2882 assign_capability('moodle/site:accessallgroups', CAP_PREVENT
, $allroles['teacher'], $frontpagecontext, true);
2883 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id
, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2884 $this->assertEquals(CAP_PREVENT
, $rc->permission
);
2886 assign_capability('moodle/site:accessallgroups', CAP_INHERIT
, $allroles['teacher'], $frontpagecontext);
2887 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id
, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2888 $this->assertFalse($rc);
2889 assign_capability('moodle/site:accessallgroups', CAP_ALLOW
, $allroles['teacher'], $frontpagecontext);
2890 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true);
2891 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id
, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
2892 $this->assertFalse($rc);
2893 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id
, true);
2896 accesslib_clear_all_caches_for_unit_testing(); // Must be done after assign_capability().
2899 // Test role_assign(), role_unassign(), role_unassign_all() functions.
2901 $context = context_course
::instance($testcourses[1]);
2902 $this->assertEquals(0, $DB->count_records('role_assignments', array('contextid'=>$context->id
)));
2903 role_assign($allroles['teacher'], $testusers[1], $context->id
);
2904 role_assign($allroles['teacher'], $testusers[2], $context->id
);
2905 role_assign($allroles['manager'], $testusers[1], $context->id
);
2906 $this->assertEquals(3, $DB->count_records('role_assignments', array('contextid'=>$context->id
)));
2907 role_unassign($allroles['teacher'], $testusers[1], $context->id
);
2908 $this->assertEquals(2, $DB->count_records('role_assignments', array('contextid'=>$context->id
)));
2909 role_unassign_all(array('contextid'=>$context->id
));
2910 $this->assertEquals(0, $DB->count_records('role_assignments', array('contextid'=>$context->id
)));
2913 accesslib_clear_all_caches_for_unit_testing(); // Just in case.
2916 // Test has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends functions.
2918 $adminid = get_admin()->id
;
2919 $guestid = $CFG->siteguest
;
2921 // Enrol some users into some courses.
2922 $course1 = $DB->get_record('course', array('id'=>$testcourses[22]), '*', MUST_EXIST
);
2923 $course2 = $DB->get_record('course', array('id'=>$testcourses[7]), '*', MUST_EXIST
);
2924 $cms = $DB->get_records('course_modules', array('course'=>$course1->id
), 'id');
2926 $blocks = $DB->get_records('block_instances', array('parentcontextid'=>context_module
::instance($cm1->id
)->id
), 'id');
2927 $block1 = reset($blocks);
2928 $instance1 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course1->id
));
2929 $instance2 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course2->id
));
2930 for ($i=0; $i<9; $i++
) {
2931 $manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']);
2933 $manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']);
2934 $manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']);
2936 for ($i=10; $i<15; $i++
) {
2937 $manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']);
2939 $manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']);
2941 // Add tons of role assignments - the more the better.
2942 role_assign($allroles['coursecreator'], $testusers[11], context_coursecat
::instance($testcategories[2]));
2943 role_assign($allroles['manager'], $testusers[12], context_coursecat
::instance($testcategories[1]));
2944 role_assign($allroles['student'], $testusers[9], context_module
::instance($cm1->id
));
2945 role_assign($allroles['teacher'], $testusers[8], context_module
::instance($cm1->id
));
2946 role_assign($allroles['guest'], $testusers[13], context_course
::instance($course1->id
));
2947 role_assign($allroles['teacher'], $testusers[7], context_block
::instance($block1->id
));
2948 role_assign($allroles['manager'], $testusers[9], context_block
::instance($block1->id
));
2949 role_assign($allroles['editingteacher'], $testusers[9], context_course
::instance($course1->id
));
2951 role_assign($allroles['teacher'], $adminid, context_course
::instance($course1->id
));
2952 role_assign($allroles['editingteacher'], $adminid, context_block
::instance($block1->id
));
2954 // Add tons of overrides - the more the better.
2955 assign_capability('moodle/site:accessallgroups', CAP_ALLOW
, $CFG->defaultuserroleid
, $frontpageblockcontext, true);
2956 assign_capability('moodle/site:accessallgroups', CAP_ALLOW
, $CFG->defaultfrontpageroleid
, $frontpageblockcontext, true);
2957 assign_capability('moodle/block:view', CAP_PROHIBIT
, $allroles['guest'], $frontpageblockcontext, true);
2958 assign_capability('block/online_users:viewlist', CAP_PREVENT
, $allroles['user'], $frontpageblockcontext, true);
2959 assign_capability('block/online_users:viewlist', CAP_PREVENT
, $allroles['student'], $frontpageblockcontext, true);
2961 assign_capability('moodle/site:accessallgroups', CAP_PREVENT
, $CFG->defaultuserroleid
, $frontpagepagecontext, true);
2962 assign_capability('moodle/site:accessallgroups', CAP_ALLOW
, $CFG->defaultfrontpageroleid
, $frontpagepagecontext, true);
2963 assign_capability('mod/page:view', CAP_PREVENT
, $allroles['guest'], $frontpagepagecontext, true);
2964 assign_capability('mod/page:view', CAP_ALLOW
, $allroles['user'], $frontpagepagecontext, true);
2965 assign_capability('moodle/page:view', CAP_ALLOW
, $allroles['student'], $frontpagepagecontext, true);
2967 assign_capability('moodle/site:accessallgroups', CAP_ALLOW
, $CFG->defaultuserroleid
, $frontpagecontext, true);
2968 assign_capability('moodle/site:accessallgroups', CAP_ALLOW
, $CFG->defaultfrontpageroleid
, $frontpagecontext, true);
2969 assign_capability('mod/page:view', CAP_ALLOW
, $allroles['guest'], $frontpagecontext, true);
2970 assign_capability('mod/page:view', CAP_PROHIBIT
, $allroles['user'], $frontpagecontext, true);
2972 assign_capability('mod/page:view', CAP_PREVENT
, $allroles['guest'], $systemcontext, true);
2974 // Prepare for prohibit test.
2975 role_assign($allroles['editingteacher'], $testusers[19], context_system
::instance());
2976 role_assign($allroles['teacher'], $testusers[19], context_course
::instance($testcourses[17]));
2977 role_assign($allroles['editingteacher'], $testusers[19], context_course
::instance($testcourses[17]));
2978 assign_capability('moodle/course:update', CAP_PROHIBIT
, $allroles['teacher'], context_course
::instance($testcourses[17]), true);
2980 accesslib_clear_all_caches_for_unit_testing(); /// Must be done after assign_capability().
2982 // Extra tests for guests and not-logged-in users because they can not be verified by cross checking
2983 // with get_users_by_capability() where they are ignored.
2984 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid));
2985 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid));
2986 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid));
2987 $this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid));
2989 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0));
2990 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0));
2991 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0));
2992 $this->assertFalse(has_capability('mod/page:view', $systemcontext, 0));
2994 $this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11]));
2995 $this->assertTrue(has_capability('moodle/course:create', context_coursecat
::instance($testcategories[2]), $testusers[11]));
2996 $this->assertFalse(has_capability('moodle/course:create', context_course
::instance($testcourses[1]), $testusers[11]));
2997 $this->assertTrue(has_capability('moodle/course:create', context_course
::instance($testcourses[19]), $testusers[11]));
2999 $this->assertFalse(has_capability('moodle/course:update', context_course
::instance($testcourses[1]), $testusers[9]));
3000 $this->assertFalse(has_capability('moodle/course:update', context_course
::instance($testcourses[19]), $testusers[9]));
3001 $this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9]));
3004 $this->assertTrue(has_capability('moodle/course:update', context_system
::instance(), $testusers[19]));
3005 $ids = get_users_by_capability(context_system
::instance(), 'moodle/course:update', 'u.id');
3006 $this->assertArrayHasKey($testusers[19], $ids);
3007 $this->assertFalse(has_capability('moodle/course:update', context_course
::instance($testcourses[17]), $testusers[19]));
3008 $ids = get_users_by_capability(context_course
::instance($testcourses[17]), 'moodle/course:update', 'u.id');
3009 $this->assertArrayNotHasKey($testusers[19], $ids);
3011 // Test the list of enrolled users.
3012 $coursecontext = context_course
::instance($course1->id
);
3013 $enrolled = get_enrolled_users($coursecontext);
3014 $this->assertCount(10, $enrolled);
3015 for ($i=0; $i<10; $i++
) {
3016 $this->assertTrue(isset($enrolled[$testusers[$i]]));
3018 $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
3019 $this->assertCount(1, $enrolled);
3020 $this->assertTrue(isset($enrolled[$testusers[9]]));
3024 $userid = $testusers[9];
3025 $USER = $DB->get_record('user', array('id'=>$userid));
3026 load_all_capabilities();
3027 $coursecontext = context_course
::instance($course1->id
);
3028 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
3029 $this->assertFalse(is_role_switched($course1->id
));
3030 role_switch($allroles['student'], $coursecontext);
3031 $this->assertTrue(is_role_switched($course1->id
));
3032 $this->assertEquals($allroles['student'], $USER->access
['rsw'][$coursecontext->path
]);
3033 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
3034 reload_all_capabilities();
3035 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
3036 role_switch(0, $coursecontext);
3037 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
3039 $USER = $DB->get_record('user', array('id'=>$userid));
3040 load_all_capabilities();
3041 $coursecontext = context_course
::instance($course1->id
);
3042 $blockcontext = context_block
::instance($block1->id
);
3043 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
3044 role_switch($allroles['student'], $coursecontext);
3045 $this->assertEquals($allroles['student'], $USER->access
['rsw'][$coursecontext->path
]);
3046 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
3047 reload_all_capabilities();
3048 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
3049 load_all_capabilities();
3050 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
3052 // Temp course role for enrol.
3053 $DB->delete_records('cache_flags', array()); // This prevents problem with dirty contexts immediately resetting the temp role - this is a known problem...
3054 $userid = $testusers[5];
3055 $roleid = $allroles['editingteacher'];
3056 $USER = $DB->get_record('user', array('id'=>$userid));
3057 load_all_capabilities();
3058 $coursecontext = context_course
::instance($course1->id
);
3059 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
3060 $this->assertFalse(isset($USER->access
['ra'][$coursecontext->path
][$roleid]));
3061 load_temp_course_role($coursecontext, $roleid);
3062 $this->assertEquals($USER->access
['ra'][$coursecontext->path
][$roleid], $roleid);
3063 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
3064 remove_temp_course_roles($coursecontext);
3065 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
3066 load_temp_course_role($coursecontext, $roleid);
3067 reload_all_capabilities();
3068 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
3069 $USER = new stdClass();
3072 // Now cross check has_capability() with get_users_by_capability(), each using different code paths,
3073 // they have to be kept in sync, usually only one of them breaks, so we know when something is wrong,
3074 // at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users).
3075 $contexts = $DB->get_records('context', array(), 'id');
3076 $contexts = array_values($contexts);
3077 $capabilities = $DB->get_records('capabilities', array(), 'id');
3078 $capabilities = array_values($capabilities);
3079 $roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']);
3080 $userids = array_values($testusers);
3081 $userids[] = get_admin()->id
;
3083 if (!PHPUNIT_LONGTEST
) {
3084 $contexts = array_slice($contexts, 0, 10);
3085 $capabilities = array_slice($capabilities, 0, 5);
3086 $userids = array_slice($userids, 0, 5);
3089 foreach ($userids as $userid) { // No guest or deleted.
3090 // Each user gets 0-10 random roles.
3091 $rcount = rand(0, 10);
3092 for ($j=0; $j<$rcount; $j++
) {
3093 $roleid = $roles[rand(0, count($roles)-1)];
3094 $contextid = $contexts[rand(0, count($contexts)-1)]->id
;
3095 role_assign($roleid, $userid, $contextid);
3099 $permissions = array(CAP_ALLOW
, CAP_PREVENT
, CAP_INHERIT
, CAP_PREVENT
);
3100 $maxoverrides = count($contexts)*10;
3101 for ($j=0; $j<$maxoverrides; $j++
) {
3102 $roleid = $roles[rand(0, count($roles)-1)];
3103 $contextid = $contexts[rand(0, count($contexts)-1)]->id
;
3104 $permission = $permissions[rand(0, count($permissions)-1)];
3105 $capname = $capabilities[rand(0, count($capabilities)-1)]->name
;
3106 assign_capability($capname, $permission, $roleid, $contextid, true);
3108 unset($permissions);
3111 accesslib_clear_all_caches_for_unit_testing(); // must be done after assign_capability().
3113 // Test time - let's set up some real user, just in case the logic for USER affects the others...
3114 $USER = $DB->get_record('user', array('id'=>$testusers[3]));
3115 load_all_capabilities();
3117 $userids[] = $CFG->siteguest
;
3118 $userids[] = 0; // Not-logged-in user.
3119 $userids[] = -1; // Non-existent user.
3121 foreach ($contexts as $crecord) {
3122 $context = context
::instance_by_id($crecord->id
);
3123 if ($coursecontext = $context->get_course_context(false)) {
3124 $enrolled = get_enrolled_users($context);
3126 $enrolled = array();
3128 foreach ($capabilities as $cap) {
3129 $allowed = get_users_by_capability($context, $cap->name
, 'u.id, u.username');
3131 $enrolledwithcap = get_enrolled_users($context, $cap->name
);
3133 $enrolledwithcap = array();
3135 foreach ($userids as $userid) {
3136 if ($userid == 0 or isguestuser($userid)) {
3138 $CFG->forcelogin
= true;
3139 $this->assertFalse(has_capability($cap->name
, $context, $userid));
3140 unset($CFG->forcelogin
);
3142 if (($cap->captype
=== 'write') or ($cap->riskbitmask
& (RISK_XSS | RISK_CONFIG | RISK_DATALOSS
))) {
3143 $this->assertFalse(has_capability($cap->name
, $context, $userid));
3145 $this->assertFalse(isset($allowed[$userid]));
3147 if (is_siteadmin($userid)) {
3148 $this->assertTrue(has_capability($cap->name
, $context, $userid, true));
3150 $hascap = has_capability($cap->name
, $context, $userid, false);
3151 $this->assertSame($hascap, isset($allowed[$userid]), "Capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
3152 if (isset($enrolled[$userid])) {
3153 $this->assertSame(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
3160 $USER = new stdClass();
3164 unset($capabilities);
3166 // Now let's do all the remaining tests that break our carefully prepared fake site.
3169 // Test $context->mark_dirty() method.
3171 $DB->delete_records('cache_flags', array());
3172 accesslib_clear_all_caches(false);
3173 $systemcontext->mark_dirty();
3174 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
3175 $this->assertTrue(isset($dirty[$systemcontext->path
]));
3176 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts
[$systemcontext->path
]));
3179 // Test $context->reload_if_dirty() method.
3181 $DB->delete_records('cache_flags', array());
3182 accesslib_clear_all_caches(false);
3183 load_all_capabilities();
3184 $context = context_course
::instance($testcourses[2]);
3185 $page = $DB->get_record('page', array('course'=>$testcourses[2]));
3186 $pagecm = get_coursemodule_from_instance('page', $page->id
);
3187 $pagecontext = context_module
::instance($pagecm->id
);
3189 $context->mark_dirty();
3190 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts
[$context->path
]));
3191 $USER->access
['test'] = true;
3192 $context->reload_if_dirty();
3193 $this->assertFalse(isset($USER->access
['test']));
3195 $context->mark_dirty();
3196 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts
[$context->path
]));
3197 $USER->access
['test'] = true;
3198 $pagecontext->reload_if_dirty();
3199 $this->assertFalse(isset($USER->access
['test']));
3202 // Test context_helper::build_all_paths() method.
3204 $oldcontexts = $DB->get_records('context', array(), 'id');
3205 $DB->set_field_select('context', 'path', null, "contextlevel <> ".CONTEXT_SYSTEM
);
3206 $DB->set_field_select('context', 'depth', 0, "contextlevel <> ".CONTEXT_SYSTEM
);
3207 context_helper
::build_all_paths();
3208 $newcontexts = $DB->get_records('context', array(), 'id');
3209 $this->assertEquals($oldcontexts, $newcontexts);
3210 unset($oldcontexts);
3211 unset($newcontexts);
3214 // Test $context->reset_paths() method.
3216 $context = context_course
::instance($testcourses[2]);
3217 $children = $context->get_child_contexts();
3218 $context->reset_paths(false);
3219 $this->assertNull($DB->get_field('context', 'path', array('id'=>$context->id
)));
3220 $this->assertEquals(0, $DB->get_field('context', 'depth', array('id'=>$context->id
)));
3221 foreach ($children as $child) {
3222 $this->assertNull($DB->get_field('context', 'path', array('id'=>$child->id
)));
3223 $this->assertEquals(0, $DB->get_field('context', 'depth', array('id'=>$child->id
)));
3225 $this->assertEquals(count($children)+
1, $DB->count_records('context', array('depth'=>0)));
3226 $this->assertEquals(count($children)+
1, $DB->count_records('context', array('path'=>null)));
3228 $context = context_course
::instance($testcourses[2]);
3229 $context->reset_paths(true);
3230 $context = context_course
::instance($testcourses[2]);
3231 $this->assertSame($context->path
, $DB->get_field('context', 'path', array('id'=>$context->id
)));
3232 $this->assertSame($context->depth
, $DB->get_field('context', 'depth', array('id'=>$context->id
)));
3233 $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
3234 $this->assertEquals(0, $DB->count_records('context', array('path'=>null)));
3237 // Test $context->update_moved() method.
3239 accesslib_clear_all_caches(false);
3240 $DB->delete_records('cache_flags', array());
3241 $course = $DB->get_record('course', array('id'=>$testcourses[0]));
3242 $context = context_course
::instance($course->id
);
3243 $oldpath = $context->path
;
3244 $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
3245 $categorycontext = context_coursecat
::instance($miscid);
3246 $course->category
= $miscid;
3247 $DB->update_record('course', $course);
3248 $context->update_moved($categorycontext);
3250 $context = context_course
::instance($course->id
);
3251 $this->assertEquals($categorycontext, $context->get_parent_context());
3252 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
3253 $this->assertFalse(isset($dirty[$oldpath]));
3254 $this->assertTrue(isset($dirty[$context->path
]));
3257 // Test $context->delete_content() method.
3259 context_helper
::reset_caches();
3260 $context = context_module
::instance($testpages[3]);
3261 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id
)));
3262 $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id
)));
3263 $context->delete_content();
3264 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id
)));
3265 $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id
)));
3268 // Test $context->delete() method.
3270 context_helper
::reset_caches();
3271 $context = context_module
::instance($testpages[4]);
3272 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id
)));
3273 $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id
)));
3274 $bi = $DB->get_record('block_instances', array('parentcontextid'=>$context->id
));
3275 $bicontext = context_block
::instance($bi->id
);
3276 $DB->delete_records('cache_flags', array());
3277 $context->delete(); // Should delete also linked blocks.
3278 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
3279 $this->assertFalse(isset($dirty[$context->path
]));
3280 $this->assertFalse($DB->record_exists('context', array('id'=>$context->id
)));
3281 $this->assertFalse($DB->record_exists('context', array('id'=>$bicontext->id
)));
3282 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_MODULE
, 'instanceid'=>$testpages[4])));
3283 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK
, 'instanceid'=>$bi->id
)));
3284 $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id
)));
3285 context_module
::instance($testpages[4]);
3288 // Test context_helper::delete_instance() method.
3290 context_helper
::reset_caches();
3291 $lastcourse = array_pop($testcourses);
3292 $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE
, 'instanceid'=>$lastcourse)));
3293 $coursecontext = context_course
::instance($lastcourse);
3294 $this->assertEquals(1, context_inspection
::test_context_cache_size());
3295 $this->assertNotEquals(CONTEXT_COURSE
, $coursecontext->instanceid
);
3296 $DB->delete_records('cache_flags', array());
3297 context_helper
::delete_instance(CONTEXT_COURSE
, $lastcourse);
3298 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
3299 $this->assertFalse(isset($dirty[$coursecontext->path
]));
3300 $this->assertEquals(0, context_inspection
::test_context_cache_size());
3301 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE
, 'instanceid'=>$lastcourse)));
3302 context_course
::instance($lastcourse);
3305 // Test context_helper::create_instances() method.
3307 $prevcount = $DB->count_records('context');
3308 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK
));
3309 context_helper
::create_instances(null, true);
3310 $this->assertSame($DB->count_records('context'), $prevcount);
3311 $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
3312 $this->assertEquals(0, $DB->count_records('context', array('path'=>null)));
3314 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK
));
3315 $DB->delete_records('block_instances', array());
3316 $prevcount = $DB->count_records('context');
3317 $DB->delete_records_select('context', 'contextlevel <> '.CONTEXT_SYSTEM
);
3318 context_helper
::create_instances(null, true);
3319 $this->assertSame($prevcount, $DB->count_records('context'));
3320 $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
3321 $this->assertEquals(0, $DB->count_records('context', array('path'=>null)));
3323 // Test context_helper::cleanup_instances() method.
3325 $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
3326 $DB->delete_records('course', array('id'=>$lastcourse));
3327 $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
3328 $DB->delete_records('course_categories', array('id'=>$lastcategory));
3329 $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
3330 $DB->delete_records('user', array('id'=>$lastuser));
3331 $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id
));
3332 $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid
));
3333 context_helper
::cleanup_instances();
3334 $count = 1; // System.
3335 $count +
= $DB->count_records('user', array('deleted'=>0));
3336 $count +
= $DB->count_records('course_categories');
3337 $count +
= $DB->count_records('course');
3338 $count +
= $DB->count_records('course_modules');
3339 $count +
= $DB->count_records('block_instances');
3340 $this->assertEquals($count, $DB->count_records('context'));
3343 // Test context cache size restrictions.
3345 $testusers= array();
3346 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE +
100; $i++
) {
3347 $user = $generator->create_user();
3348 $testusers[$i] = $user->id
;
3350 context_helper
::create_instances(null, true);
3351 context_helper
::reset_caches();
3352 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE +
100; $i++
) {
3353 context_user
::instance($testusers[$i]);
3354 if ($i == CONTEXT_CACHE_MAX_SIZE
- 1) {
3355 $this->assertEquals(CONTEXT_CACHE_MAX_SIZE
, context_inspection
::test_context_cache_size());
3356 } else if ($i == CONTEXT_CACHE_MAX_SIZE
) {
3357 // Once the limit is reached roughly 1/3 of records should be removed from cache.
3358 $this->assertEquals((int)ceil(CONTEXT_CACHE_MAX_SIZE
* (2/3) +
101), context_inspection
::test_context_cache_size());
3361 // We keep the first 100 cached.
3362 $prevsize = context_inspection
::test_context_cache_size();
3363 for ($i=0; $i<100; $i++
) {
3364 context_user
::instance($testusers[$i]);
3365 $this->assertEquals($prevsize, context_inspection
::test_context_cache_size());
3367 context_user
::instance($testusers[102]);
3368 $this->assertEquals($prevsize+
1, context_inspection
::test_context_cache_size());
3373 // Test basic test of legacy functions.
3374 // Note: watch out, the fake site might be pretty borked already.
3376 $this->assertEquals(get_system_context(), context_system
::instance());
3377 $this->assertDebuggingCalled('get_system_context() is deprecated, please use context_system::instance() instead.', DEBUG_DEVELOPER
);
3379 foreach ($DB->get_records('context') as $contextid => $record) {
3380 $context = context
::instance_by_id($contextid);
3381 $this->assertEquals($context, get_context_instance($record->contextlevel
, $record->instanceid
));
3382 $this->assertDebuggingCalled('get_context_instance() is deprecated, please use context_xxxx::instance() instead.', DEBUG_DEVELOPER
);
3385 // Make sure a debugging is thrown.
3386 get_context_instance($record->contextlevel
, $record->instanceid
);
3387 $this->assertDebuggingCalled('get_context_instance() is deprecated, please use context_xxxx::instance() instead.', DEBUG_DEVELOPER
);
3388 get_system_context();
3389 $this->assertDebuggingCalled('get_system_context() is deprecated, please use context_system::instance() instead.', DEBUG_DEVELOPER
);
3393 * Test updating of role capabilities during upgrade
3395 public function test_update_capabilities() {
3398 $this->resetAfterTest(true);
3400 $froncontext = context_course
::instance($SITE->id
);
3401 $student = $DB->get_record('role', array('archetype'=>'student'));
3402 $teacher = $DB->get_record('role', array('archetype'=>'teacher'));
3404 $existingcaps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
3406 $this->assertFalse(isset($existingcaps['moodle/site:restore'])); // Moved to new 'moodle/restore:restorecourse'.
3407 $this->assertTrue(isset($existingcaps['moodle/restore:restorecourse'])); // New cap from 'moodle/site:restore'.
3408 $this->assertTrue(isset($existingcaps['moodle/site:sendmessage'])); // New capability.
3409 $this->assertTrue(isset($existingcaps['moodle/backup:backupcourse']));
3410 $this->assertTrue(isset($existingcaps['moodle/backup:backupsection'])); // Cloned from 'moodle/backup:backupcourse'.
3411 $this->assertTrue(isset($existingcaps['moodle/site:approvecourse'])); // Updated bitmask.
3412 $this->assertTrue(isset($existingcaps['moodle/course:manageactivities']));
3413 $this->assertTrue(isset($existingcaps['mod/page:addinstance'])); // Cloned from core 'moodle/course:manageactivities'.
3415 // Fake state before upgrade.
3416 $DB->set_field('capabilities', 'name', 'moodle/site:restore', array('name'=>'moodle/restore:restorecourse'));
3417 $DB->set_field('role_capabilities', 'capability', 'moodle/site:restore', array('capability'=>'moodle/restore:restorecourse'));
3418 assign_capability('moodle/site:restore', CAP_PROHIBIT
, $teacher->id
, $froncontext->id
, true);
3419 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/site:restore', 'roleid'=>$teacher->id
), 'contextid, permission', 'contextid, permission'));
3421 $DB->delete_records('role_capabilities', array('capability'=>'moodle/site:sendmessage'));
3422 $DB->delete_records('capabilities', array('name'=>'moodle/site:sendmessage'));
3424 $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupsection'));
3425 $DB->delete_records('capabilities', array('name'=>'moodle/backup:backupsection'));
3426 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT
, $student->id
, $froncontext->id
, true);
3427 assign_capability('moodle/backup:backupcourse', CAP_ALLOW
, $teacher->id
, $froncontext->id
, true);
3429 $DB->set_field('capabilities', 'riskbitmask', 0, array('name'=>'moodle/site:approvecourse'));
3431 $DB->delete_records('role_capabilities', array('capability'=>'mod/page:addinstance'));
3432 $DB->delete_records('capabilities', array('name'=>'mod/page:addinstance'));
3433 assign_capability('moodle/course:manageactivities', CAP_PROHIBIT
, $student->id
, $froncontext->id
, true);
3434 assign_capability('moodle/course:manageactivities', CAP_ALLOW
, $teacher->id
, $froncontext->id
, true);
3437 update_capabilities('moodle');
3439 // Only core should be upgraded.
3440 $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
3442 $this->assertFalse(isset($existingcaps['moodle/site:restore']));
3443 $this->assertTrue(isset($caps['moodle/restore:restorecourse']));
3444 $this->assertEquals($existingcaps['moodle/restore:restorecourse'], $caps['moodle/restore:restorecourse']);
3445 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/restore:restorecourse', 'roleid'=>$teacher->id
), 'contextid, permission', 'contextid, permission'));
3446 $this->assertEquals($perms1, $perms2);
3448 $this->assertTrue(isset($caps['moodle/site:sendmessage']));
3449 $this->assertEquals($existingcaps['moodle/site:sendmessage'], $caps['moodle/site:sendmessage']);
3451 $this->assertTrue(isset($caps['moodle/backup:backupsection']));
3452 $this->assertEquals($existingcaps['moodle/backup:backupsection'], $caps['moodle/backup:backupsection']);
3453 $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/backup:backupcourse', 'moodle/backup:backupsection'));
3454 foreach ($roles as $role) {
3455 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse', 'roleid'=>$role->id
), 'contextid, permission', 'contextid, permission'));
3456 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupsection', 'roleid'=>$role->id
), 'contextid, permission', 'contextid, permission'));
3457 $this->assertEquals($perms1, $perms2);
3460 $this->assertTrue(isset($caps['moodle/site:approvecourse']));
3461 $this->assertEquals($existingcaps['moodle/site:approvecourse'], $caps['moodle/site:approvecourse']);
3463 $this->assertFalse(isset($caps['mod/page:addinstance']));
3466 update_capabilities('mod_page');
3467 $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
3468 $this->assertTrue(isset($caps['mod/page:addinstance']));
3469 $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/course:manageactivities', 'mod/page:addinstance'));
3470 foreach ($roles as $role) {
3471 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/course:manageactivities', 'roleid'=>$role->id
), 'contextid, permission', 'contextid, permission'));
3472 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'mod/page:addinstance', 'roleid'=>$role->id
), 'contextid, permission', 'contextid, permission'));
3474 $this->assertEquals($perms1, $perms2);
3478 * Tests reset_role_capabilities function.
3480 public function test_reset_role_capabilities() {
3482 $this->resetAfterTest(true);
3483 $generator = $this->getDataGenerator();
3485 // Create test course and user, enrol one in the other.
3486 $course = $generator->create_course();
3487 $user = $generator->create_user();
3488 $roleid = $DB->get_field('role', 'id', array('shortname' => 'student'), MUST_EXIST
);
3489 $generator->enrol_user($user->id
, $course->id
, $roleid);
3491 // Change student role so it DOES have 'mod/forum:addinstance'.
3492 $systemcontext = context_system
::instance();
3493 assign_capability('mod/forum:addinstance', CAP_ALLOW
, $roleid, $systemcontext->id
);
3495 // Override course so it does NOT allow students 'mod/forum:viewdiscussion'.
3496 $coursecontext = context_course
::instance($course->id
);
3497 assign_capability('mod/forum:viewdiscussion', CAP_PREVENT
, $roleid, $coursecontext->id
);
3499 // Check expected capabilities so far.
3500 $this->assertTrue(has_capability('mod/forum:addinstance', $coursecontext, $user));
3501 $this->assertFalse(has_capability('mod/forum:viewdiscussion', $coursecontext, $user));
3503 // Oops, allowing student to add forums was a mistake, let's reset the role.
3504 reset_role_capabilities($roleid);
3506 // Check new expected capabilities - role capabilities should have been reset,
3507 // while the override at course level should remain.
3508 $this->assertFalse(has_capability('mod/forum:addinstance', $coursecontext, $user));
3509 $this->assertFalse(has_capability('mod/forum:viewdiscussion', $coursecontext, $user));
3513 * Tests count_role_users function.
3515 public function test_count_role_users() {
3517 $this->resetAfterTest(true);
3518 $generator = self
::getDataGenerator();
3519 // Create a course in a category, and some users.
3520 $category = $generator->create_category();
3521 $course = $generator->create_course(array('category' => $category->id
));
3522 $user1 = $generator->create_user();
3523 $user2 = $generator->create_user();
3524 $user3 = $generator->create_user();
3525 $user4 = $generator->create_user();
3526 $user5 = $generator->create_user();
3527 $roleid1 = $DB->get_field('role', 'id', array('shortname' => 'manager'), MUST_EXIST
);
3528 $roleid2 = $DB->get_field('role', 'id', array('shortname' => 'coursecreator'), MUST_EXIST
);
3529 // Enrol two users as managers onto the course, and 1 onto the category.
3530 $generator->enrol_user($user1->id
, $course->id
, $roleid1);
3531 $generator->enrol_user($user2->id
, $course->id
, $roleid1);
3532 $generator->role_assign($roleid1, $user3->id
, context_coursecat
::instance($category->id
));
3533 // Enrol 1 user as a coursecreator onto the course, and another onto the category.
3534 // This is to ensure we do not count users with roles that are not specified.
3535 $generator->enrol_user($user4->id
, $course->id
, $roleid2);
3536 $generator->role_assign($roleid2, $user5->id
, context_coursecat
::instance($category->id
));
3537 // Check that the correct users are found on the course.
3538 $this->assertEquals(2, count_role_users($roleid1, context_course
::instance($course->id
), false));
3539 $this->assertEquals(3, count_role_users($roleid1, context_course
::instance($course->id
), true));
3540 // Check for the category.
3541 $this->assertEquals(1, count_role_users($roleid1, context_coursecat
::instance($category->id
), false));
3542 $this->assertEquals(1, count_role_users($roleid1, context_coursecat
::instance($category->id
), true));
3543 // Have a user with the same role at both the category and course level.
3544 $generator->role_assign($roleid1, $user1->id
, context_coursecat
::instance($category->id
));
3545 // The course level checks should remain the same.
3546 $this->assertEquals(2, count_role_users($roleid1, context_course
::instance($course->id
), false));
3547 $this->assertEquals(3, count_role_users($roleid1, context_course
::instance($course->id
), true));
3551 * Test updating of role capabilities during upgrade
3554 public function test_get_with_capability_sql() {
3557 $this->resetAfterTest();
3559 $course = $this->getDataGenerator()->create_course();
3560 $coursecontext = context_course
::instance($course->id
);
3561 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST
);
3562 $teacher = $this->getDataGenerator()->create_user();
3563 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST
);
3564 $student = $this->getDataGenerator()->create_user();
3565 $guest = $DB->get_record('user', array('username' => 'guest'));
3567 role_assign($teacherrole->id
, $teacher->id
, $coursecontext);
3568 role_assign($studentrole->id
, $student->id
, $coursecontext);
3569 $admin = $DB->get_record('user', array('username' => 'admin'));
3571 // Note: Here are used default capabilities, the full test is in permission evaluation below,
3572 // use two capabilities that teacher has and one does not, none of them should be allowed for not-logged-in user.
3573 $this->assertTrue($DB->record_exists('capabilities', array('name' => 'moodle/backup:backupcourse')));
3574 $this->assertTrue($DB->record_exists('capabilities', array('name' => 'moodle/site:approvecourse')));
3576 list($sql, $params) = get_with_capability_sql($coursecontext, 'moodle/backup:backupcourse');
3577 $users = $DB->get_records_sql($sql, $params);
3579 $this->assertTrue(array_key_exists($teacher->id
, $users));
3580 $this->assertFalse(array_key_exists($admin->id
, $users));
3581 $this->assertFalse(array_key_exists($student->id
, $users));
3582 $this->assertFalse(array_key_exists($guest->id
, $users));
3584 list($sql, $params) = get_with_capability_sql($coursecontext, 'moodle/site:approvecourse');
3585 $users = $DB->get_records_sql($sql, $params);
3587 $this->assertFalse(array_key_exists($teacher->id
, $users));
3588 $this->assertFalse(array_key_exists($admin->id
, $users));
3589 $this->assertFalse(array_key_exists($student->id
, $users));
3590 $this->assertFalse(array_key_exists($guest->id
, $users));
3592 // Test role override.
3593 assign_capability('moodle/site:backupcourse', CAP_PROHIBIT
, $teacherrole->id
, $coursecontext, true);
3594 assign_capability('moodle/site:backupcourse', CAP_ALLOW
, $studentrole->id
, $coursecontext, true);
3596 list($sql, $params) = get_with_capability_sql($coursecontext, 'moodle/site:backupcourse');
3597 $users = $DB->get_records_sql($sql, $params);
3599 $this->assertFalse(array_key_exists($teacher->id
, $users));
3600 $this->assertFalse(array_key_exists($admin->id
, $users));
3601 $this->assertTrue(array_key_exists($student->id
, $users));
3602 $this->assertFalse(array_key_exists($guest->id
, $users));
3606 * Test the get_profile_roles() function.
3608 public function test_get_profile_roles() {
3610 $this->resetAfterTest();
3612 $course = $this->getDataGenerator()->create_course();
3613 $coursecontext = context_course
::instance($course->id
);
3615 // Assign a student role.
3616 $studentrole = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST
);
3617 $user1 = $this->getDataGenerator()->create_user();
3618 role_assign($studentrole->id
, $user1->id
, $coursecontext);
3620 // Assign an editing teacher role.
3621 $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST
);
3622 $user2 = $this->getDataGenerator()->create_user();
3623 role_assign($teacherrole->id
, $user2->id
, $coursecontext);
3625 // Create a custom role that can be assigned at course level, but don't assign it yet.
3626 create_role('Custom role', 'customrole', 'Custom course role');
3627 $customrole = $DB->get_record('role', array('shortname' => 'customrole'), '*', MUST_EXIST
);
3628 set_role_contextlevels($customrole->id
, [CONTEXT_COURSE
]);
3629 core_role_set_assign_allowed($teacherrole->id
, $customrole->id
); // Allow teacher to assign the role in the course.
3631 // Set the site policy 'profileroles' to show student, teacher and non-editing teacher roles (i.e. not the custom role).
3632 $neteacherrole = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST
);
3633 set_config('profileroles', "{$studentrole->id}, {$teacherrole->id}, {$neteacherrole->id}");
3635 // A student in the course (given they can't assign roles) should see those roles which are:
3636 // - listed in the 'profileroles' site policy AND
3637 // - are assigned in the course context (or parent contexts).
3638 // In this case, the non-editing teacher role is not assigned and should not be returned.
3640 $teacherrole->id
=> (object) [
3641 'id' => $teacherrole->id
,
3643 'shortname' => $teacherrole->shortname
,
3644 'sortorder' => $teacherrole->sortorder
,
3645 'coursealias' => null
3647 $studentrole->id
=> (object) [
3648 'id' => $studentrole->id
,
3650 'shortname' => $studentrole->shortname
,
3651 'sortorder' => $studentrole->sortorder
,
3652 'coursealias' => null
3655 $this->setUser($user1);
3656 $this->assertEquals($expected, get_profile_roles($coursecontext));
3658 // An editing teacher should also see only 2 roles at this stage as only 2 roles are assigned: 'teacher' and 'student'.
3659 $this->setUser($user2);
3660 $this->assertEquals($expected, get_profile_roles($coursecontext));
3662 // Assign a custom role in the course.
3663 $user3 = $this->getDataGenerator()->create_user();
3664 role_assign($customrole->id
, $user3->id
, $coursecontext);
3666 // Confirm that the teacher can see the custom role now that it's assigned.
3667 $expectedteacher = [
3668 $teacherrole->id
=> (object) [
3669 'id' => $teacherrole->id
,
3671 'shortname' => $teacherrole->shortname
,
3672 'sortorder' => $teacherrole->sortorder
,
3673 'coursealias' => null
3675 $studentrole->id
=> (object) [
3676 'id' => $studentrole->id
,
3678 'shortname' => $studentrole->shortname
,
3679 'sortorder' => $studentrole->sortorder
,
3680 'coursealias' => null
3682 $customrole->id
=> (object) [
3683 'id' => $customrole->id
,
3684 'name' => 'Custom role',
3685 'shortname' => $customrole->shortname
,
3686 'sortorder' => $customrole->sortorder
,
3687 'coursealias' => null
3690 $this->setUser($user2);
3691 $this->assertEquals($expectedteacher, get_profile_roles($coursecontext));
3693 // And that the student can't, because the role isn't included in the 'profileroles' site policy.
3694 $expectedstudent = [
3695 $teacherrole->id
=> (object) [
3696 'id' => $teacherrole->id
,
3698 'shortname' => $teacherrole->shortname
,
3699 'sortorder' => $teacherrole->sortorder
,
3700 'coursealias' => null
3702 $studentrole->id
=> (object) [
3703 'id' => $studentrole->id
,
3705 'shortname' => $studentrole->shortname
,
3706 'sortorder' => $studentrole->sortorder
,
3707 'coursealias' => null
3710 $this->setUser($user1);
3711 $this->assertEquals($expectedstudent, get_profile_roles($coursecontext));
3713 // If we have no roles listed in the site policy, the teacher should be able to see the assigned roles.
3714 $expectedteacher = [
3715 $studentrole->id
=> (object) [
3716 'id' => $studentrole->id
,
3718 'shortname' => $studentrole->shortname
,
3719 'sortorder' => $studentrole->sortorder
,
3720 'coursealias' => null
3722 $customrole->id
=> (object) [
3723 'id' => $customrole->id
,
3724 'name' => 'Custom role',
3725 'shortname' => $customrole->shortname
,
3726 'sortorder' => $customrole->sortorder
,
3727 'coursealias' => null
3729 $teacherrole->id
=> (object) [
3730 'id' => $teacherrole->id
,
3732 'shortname' => $teacherrole->shortname
,
3733 'sortorder' => $teacherrole->sortorder
,
3734 'coursealias' => null
3737 set_config('profileroles', "");
3738 $this->setUser($user2);
3739 $this->assertEquals($expectedteacher, get_profile_roles($coursecontext));
3744 * Context caching fixture
3746 class context_inspection
extends context_helper
{
3747 public static function test_context_cache_size() {
3748 return self
::$cache_count;