Merge branch 'MDL-40255_M25' of git://github.com/lazydaisy/moodle into MOODLE_25_STABLE
[moodle.git] / lib / tests / accesslib_test.php
blob03a40c6e946c22ee95b8042df423f9da9edd2254
1 <?php
2 // This file is part of Moodle - http://moodle.org/
3 //
4 // Moodle is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // Moodle is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // You should have received a copy of the GNU General Public License
15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17 /**
18 * Full functional accesslib test
20 * @package core
21 * @category phpunit
22 * @copyright 2011 Petr Skoda {@link http://skodak.org}
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26 defined('MOODLE_INTERNAL') || die();
29 /**
30 * Context caching fixture
32 class context_inspection extends context_helper {
33 public static function test_context_cache_size() {
34 return self::$cache_count;
39 /**
40 * Functional test for accesslib.php
42 * Note: execution may take many minutes especially on slower servers.
44 class accesslib_testcase extends advanced_testcase {
46 //TODO: add more tests for the remaining accesslib parts such as enrol related api
48 /**
49 * Verify comparison of context instances in phpunit asserts
50 * @return void
52 public function test_context_comparisons() {
53 $frontpagecontext1 = context_course::instance(SITEID);
54 context_helper::reset_caches();
55 $frontpagecontext2 = context_course::instance(SITEID);
56 $this->assertEquals($frontpagecontext1, $frontpagecontext2);
58 $user1 = context_user::instance(1);
59 $user2 = context_user::instance(2);
60 $this->assertNotEquals($user1, $user2);
63 /**
64 * Test resetting works.
66 public function test_accesslib_clear_all_caches() {
67 global $ACCESSLIB_PRIVATE;
69 $this->resetAfterTest();
71 $this->setAdminUser();
72 load_all_capabilities();
74 $this->assertNotEmpty($ACCESSLIB_PRIVATE->rolepermissions);
75 $this->assertNotEmpty($ACCESSLIB_PRIVATE->rolepermissions);
76 $this->assertNotEmpty($ACCESSLIB_PRIVATE->accessdatabyuser);
77 accesslib_clear_all_caches(true);
78 $this->assertEmpty($ACCESSLIB_PRIVATE->rolepermissions);
79 $this->assertEmpty($ACCESSLIB_PRIVATE->rolepermissions);
80 $this->assertEmpty($ACCESSLIB_PRIVATE->dirtycontexts);
81 $this->assertEmpty($ACCESSLIB_PRIVATE->accessdatabyuser);
84 /**
85 * Test getting of role access
86 * @return void
88 public function test_get_role_access() {
89 global $DB;
91 $roles = $DB->get_records('role');
92 foreach ($roles as $role) {
93 $access = get_role_access($role->id);
95 $this->assertTrue(is_array($access));
96 $this->assertTrue(is_array($access['ra']));
97 $this->assertTrue(is_array($access['rdef']));
98 $this->assertTrue(isset($access['rdef_count']));
99 $this->assertTrue(is_array($access['loaded']));
100 $this->assertTrue(isset($access['time']));
101 $this->assertTrue(is_array($access['rsw']));
104 // Note: the data is validated in the functional permission evaluation test at the end of this testcase.
108 * Test getting of guest role.
109 * @return void
111 public function test_get_guest_role() {
112 global $CFG;
114 $guest = get_guest_role();
115 $this->assertEquals('guest', $guest->archetype);
116 $this->assertEquals('guest', $guest->shortname);
118 $this->assertEquals($CFG->guestroleid, $guest->id);
122 * Test if user is admin.
123 * @return void
125 public function test_is_siteadmin() {
126 global $DB, $CFG;
128 $this->resetAfterTest();
130 $users = $DB->get_records('user');
132 foreach ($users as $user) {
133 $this->setUser(0);
134 if ($user->username === 'admin') {
135 $this->assertTrue(is_siteadmin($user));
136 $this->assertTrue(is_siteadmin($user->id));
137 $this->setUser($user);
138 $this->assertTrue(is_siteadmin());
139 $this->assertTrue(is_siteadmin(null));
140 } else {
141 $this->assertFalse(is_siteadmin($user));
142 $this->assertFalse(is_siteadmin($user->id));
143 $this->setUser($user);
144 $this->assertFalse(is_siteadmin());
145 $this->assertFalse(is_siteadmin(null));
149 // Change the site admin list and check that it still works with
150 // multiple admins. We do this with userids only (not real user
151 // accounts) because it makes the test simpler.
152 $before = $CFG->siteadmins;
153 set_config('siteadmins', '666,667,668');
154 $this->assertTrue(is_siteadmin(666));
155 $this->assertTrue(is_siteadmin(667));
156 $this->assertTrue(is_siteadmin(668));
157 $this->assertFalse(is_siteadmin(669));
158 set_config('siteadmins', '13');
159 $this->assertTrue(is_siteadmin(13));
160 $this->assertFalse(is_siteadmin(666));
161 set_config('siteadmins', $before);
165 * Test if user is enrolled in a course
166 * @return void
168 public function test_is_enrolled() {
169 global $DB;
171 // Generate data
172 $user = $this->getDataGenerator()->create_user();
173 $course = $this->getDataGenerator()->create_course();
174 $coursecontext = context_course::instance($course->id);
175 $role = $DB->get_record('role', array('shortname'=>'student'));
177 // There should be a manual enrolment as part of the default install
178 $plugin = enrol_get_plugin('manual');
179 $instance = $DB->get_record('enrol', array(
180 'courseid' => $course->id,
181 'enrol' => 'manual',
183 $this->assertNotEquals($instance, false);
185 // Enrol the user in the course
186 $plugin->enrol_user($instance, $user->id, $role->id);
188 // We'll test with the mod/assign:submit capability
189 $capability= 'mod/assign:submit';
190 $this->assertTrue($DB->record_exists('capabilities', array('name' => $capability)));
192 // Switch to our user
193 $this->setUser($user);
195 // Ensure that the user has the capability first
196 $this->assertTrue(has_capability($capability, $coursecontext, $user->id));
198 // We first test whether the user is enrolled on the course as this
199 // seeds the cache, then we test for the capability
200 $this->assertTrue(is_enrolled($coursecontext, $user, '', true));
201 $this->assertTrue(is_enrolled($coursecontext, $user, $capability));
203 // Prevent the capability for this user role
204 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
205 $coursecontext->mark_dirty();
206 $this->assertFalse(has_capability($capability, $coursecontext, $user->id));
208 // Again, we seed the cache first by checking initial enrolment,
209 // and then we test the actual capability
210 $this->assertTrue(is_enrolled($coursecontext, $user, '', true));
211 $this->assertFalse(is_enrolled($coursecontext, $user, $capability));
213 // We need variable states to be reset for the next test
214 $this->resetAfterTest(true);
218 * Test logged in test.
219 * @return void
221 public function test_isloggedin() {
222 global $USER;
224 $this->resetAfterTest();
226 $USER->id = 0;
227 $this->assertFalse(isloggedin());
228 $USER->id = 1;
229 $this->assertTrue(isloggedin());
233 * Test guest user test.
234 * @return void
236 public function test_isguestuser() {
237 global $DB;
239 $this->resetAfterTest();
241 $guest = $DB->get_record('user', array('username'=>'guest'));
242 $this->setUser(0);
243 $this->assertFalse(isguestuser());
244 $this->setAdminUser();
245 $this->assertFalse(isguestuser());
246 $this->assertTrue(isguestuser($guest));
247 $this->assertTrue(isguestuser($guest->id));
248 $this->setUser($guest);
249 $this->assertTrue(isguestuser());
251 $users = $DB->get_records('user');
252 foreach ($users as $user) {
253 if ($user->username === 'guest') {
254 continue;
256 $this->assertFalse(isguestuser($user));
261 * Test capability riskiness.
262 * @return void
264 public function test_is_safe_capability() {
265 global $DB;
266 // Note: there is not much to test, just make sure no notices are throw for the most dangerous cap.
267 $capability = $DB->get_record('capabilities', array('name'=>'moodle/site:config'), '*', MUST_EXIST);
268 $this->assertFalse(is_safe_capability($capability));
272 * Test context fetching.
273 * @return void
275 public function test_get_context_info_array() {
276 $this->resetAfterTest();
278 $syscontext = context_system::instance();
279 $user = $this->getDataGenerator()->create_user();
280 $usercontext = context_user::instance($user->id);
281 $course = $this->getDataGenerator()->create_course();
282 $catcontext = context_coursecat::instance($course->category);
283 $coursecontext = context_course::instance($course->id);
284 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
285 $modcontext = context_module::instance($page->cmid);
286 $cm = get_coursemodule_from_instance('page', $page->id);
287 $block1 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$coursecontext->id));
288 $block1context = context_block::instance($block1->id);
289 $block2 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$modcontext->id));
290 $block2context = context_block::instance($block2->id);
292 $result = get_context_info_array($syscontext->id);
293 $this->assertCount(3, $result);
294 $this->assertSame($syscontext, $result[0]);
295 $this->assertSame(null, $result[1]);
296 $this->assertSame(null, $result[2]);
298 $result = get_context_info_array($usercontext->id);
299 $this->assertCount(3, $result);
300 $this->assertSame($usercontext, $result[0]);
301 $this->assertSame(null, $result[1]);
302 $this->assertSame(null, $result[2]);
304 $result = get_context_info_array($catcontext->id);
305 $this->assertCount(3, $result);
306 $this->assertSame($catcontext, $result[0]);
307 $this->assertSame(null, $result[1]);
308 $this->assertSame(null, $result[2]);
310 $result = get_context_info_array($coursecontext->id);
311 $this->assertCount(3, $result);
312 $this->assertSame($coursecontext, $result[0]);
313 $this->assertEquals($course->id, $result[1]->id);
314 $this->assertEquals($course->shortname, $result[1]->shortname);
315 $this->assertSame(null, $result[2]);
317 $result = get_context_info_array($block1context->id);
318 $this->assertCount(3, $result);
319 $this->assertSame($block1context, $result[0]);
320 $this->assertEquals($course->id, $result[1]->id);
321 $this->assertEquals($course->shortname, $result[1]->shortname);
322 $this->assertSame(null, $result[2]);
324 $result = get_context_info_array($modcontext->id);
325 $this->assertCount(3, $result);
326 $this->assertSame($modcontext, $result[0]);
327 $this->assertEquals($course->id, $result[1]->id);
328 $this->assertEquals($course->shortname, $result[1]->shortname);
329 $this->assertEquals($cm->id, $result[2]->id);
330 $this->assertEquals($cm->groupmembersonly, $result[2]->groupmembersonly);
332 $result = get_context_info_array($block2context->id);
333 $this->assertCount(3, $result);
334 $this->assertSame($block2context, $result[0]);
335 $this->assertEquals($course->id, $result[1]->id);
336 $this->assertEquals($course->shortname, $result[1]->shortname);
337 $this->assertEquals($cm->id, $result[2]->id);
338 $this->assertEquals($cm->groupmembersonly, $result[2]->groupmembersonly);
342 * Test looking for course contacts.
343 * @return void
345 public function test_has_coursecontact_role() {
346 global $DB, $CFG;
348 $this->resetAfterTest();
350 $users = $DB->get_records('user');
352 // Nobody is expected to have any course level roles.
353 $this->assertNotEmpty($CFG->coursecontact);
354 foreach($users as $user) {
355 $this->assertFalse(has_coursecontact_role($user->id));
358 $user = $this->getDataGenerator()->create_user();
359 $course = $this->getDataGenerator()->create_course();
360 role_assign($CFG->coursecontact, $user->id, context_course::instance($course->id));
361 $this->assertTrue(has_coursecontact_role($user->id));
365 * Test creation of roles.
366 * @return void
368 public function test_create_role() {
369 global $DB;
371 $this->resetAfterTest();
373 $id = create_role('New student role', 'student2', 'New student description', 'student');
374 $role = $DB->get_record('role', array('id'=>$id));
376 $this->assertNotEmpty($role);
377 $this->assertEquals('New student role', $role->name);
378 $this->assertEquals('student2', $role->shortname);
379 $this->assertEquals('New student description', $role->description);
380 $this->assertEquals('student', $role->archetype);
384 * Test adding of capabilities to roles.
386 public function test_assign_capability() {
387 global $DB;
389 $this->resetAfterTest();
391 $user = $this->getDataGenerator()->create_user();
392 $syscontext = context_system::instance();
393 $frontcontext = context_course::instance(SITEID);
394 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
395 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability assigned to student by default
396 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')));
397 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')));
399 $this->setUser($user);
400 $result = assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $frontcontext->id);
401 $this->assertTrue($result);
402 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
403 $this->assertNotEmpty($permission);
404 $this->assertEquals(CAP_ALLOW, $permission->permission);
405 $this->assertEquals($user->id, $permission->modifierid);
407 $this->setUser(0);
408 $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $frontcontext->id, false);
409 $this->assertTrue($result);
410 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
411 $this->assertNotEmpty($permission);
412 $this->assertEquals(CAP_ALLOW, $permission->permission);
413 $this->assertEquals(3, $permission->modifierid);
415 $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $frontcontext->id, true);
416 $this->assertTrue($result);
417 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
418 $this->assertNotEmpty($permission);
419 $this->assertEquals(CAP_PROHIBIT, $permission->permission);
420 $this->assertEquals(0, $permission->modifierid);
422 $result = assign_capability('moodle/backup:backupcourse', CAP_INHERIT, $student->id, $frontcontext->id);
423 $this->assertTrue($result);
424 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
425 $this->assertEmpty($permission);
429 * Test removing of capabilities from roles.
431 public function test_unassign_capability() {
432 global $DB;
434 $this->resetAfterTest();
436 $syscontext = context_system::instance();
437 $frontcontext = context_course::instance(SITEID);
438 $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
439 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability assigned to manager by default
440 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $frontcontext->id);
442 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
443 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
445 $result = unassign_capability('moodle/backup:backupcourse', $manager->id, $syscontext->id);
446 $this->assertTrue($result);
447 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
448 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
449 unassign_capability('moodle/backup:backupcourse', $manager->id, $frontcontext);
450 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
452 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $syscontext->id);
453 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $frontcontext->id);
454 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
456 $result = unassign_capability('moodle/backup:backupcourse', $manager->id);
457 $this->assertTrue($result);
458 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
459 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
463 * Test role assigning
465 public function test_role_assign() {
466 global $DB, $USER;
468 $this->resetAfterTest();
470 $user = $this->getDataGenerator()->create_user();
471 $course = $this->getDataGenerator()->create_course();
472 $role = $DB->get_record('role', array('shortname'=>'student'));
474 $this->setUser(0);
475 $context = context_system::instance();
476 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
477 role_assign($role->id, $user->id, $context->id);
478 $ras = $DB->get_record('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id));
479 $this->assertNotEmpty($ras);
480 $this->assertSame('', $ras->component);
481 $this->assertSame('0', $ras->itemid);
482 $this->assertEquals($USER->id, $ras->modifierid);
484 $this->setAdminUser();
485 $context = context_course::instance($course->id);
486 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
487 role_assign($role->id, $user->id, $context->id, 'enrol_self', 1, 666);
488 $ras = $DB->get_record('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id));
489 $this->assertNotEmpty($ras);
490 $this->assertSame('enrol_self', $ras->component);
491 $this->assertSame('1', $ras->itemid);
492 $this->assertEquals($USER->id, $ras->modifierid);
493 $this->assertEquals(666, $ras->timemodified);
497 * Test role unassigning
498 * @return void
500 public function test_role_unassign() {
501 global $DB;
503 $this->resetAfterTest();
505 $user = $this->getDataGenerator()->create_user();
506 $course = $this->getDataGenerator()->create_course();
507 $role = $DB->get_record('role', array('shortname'=>'student'));
509 $context = context_system::instance();
510 role_assign($role->id, $user->id, $context->id);
511 $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
512 role_unassign($role->id, $user->id, $context->id);
513 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
515 role_assign($role->id, $user->id, $context->id, 'enrol_self', 1);
516 $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
517 role_unassign($role->id, $user->id, $context->id, 'enrol_self', 1);
518 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
522 * Test role unassigning
523 * @return void
525 public function test_role_unassign_all() {
526 global $DB;
528 $this->resetAfterTest();
530 $user = $this->getDataGenerator()->create_user();
531 $course = $this->getDataGenerator()->create_course();
532 $role = $DB->get_record('role', array('shortname'=>'student'));
533 $syscontext = context_system::instance();
534 $coursecontext = context_course::instance($course->id);
535 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
536 $modcontext = context_module::instance($page->cmid);
538 role_assign($role->id, $user->id, $syscontext->id);
539 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
540 $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id)));
541 role_unassign_all(array('userid'=>$user->id, 'roleid'=>$role->id));
542 $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id)));
544 role_assign($role->id, $user->id, $syscontext->id);
545 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
546 role_assign($role->id, $user->id, $modcontext->id);
547 $this->assertEquals(3, $DB->count_records('role_assignments', array('userid'=>$user->id)));
548 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id), false);
549 $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id)));
550 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id), true);
551 $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id)));
552 role_unassign_all(array('userid'=>$user->id));
553 $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id)));
555 role_assign($role->id, $user->id, $syscontext->id);
556 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
557 role_assign($role->id, $user->id, $coursecontext->id);
558 role_assign($role->id, $user->id, $modcontext->id);
559 $this->assertEquals(4, $DB->count_records('role_assignments', array('userid'=>$user->id)));
560 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id, 'component'=>'enrol_self'), true, true);
561 $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id)));
565 * Test role queries.
566 * @return void
568 public function test_get_roles_with_capability() {
569 global $DB;
571 $this->resetAfterTest();
573 $syscontext = context_system::instance();
574 $frontcontext = context_course::instance(SITEID);
575 $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
576 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
578 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability is ok
579 $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse'));
581 $roles = get_roles_with_capability('moodle/backup:backupcourse');
582 $this->assertEquals(array(), $roles);
584 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $syscontext->id);
585 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $manager->id, $frontcontext->id);
586 assign_capability('moodle/backup:backupcourse', CAP_PREVENT, $teacher->id, $frontcontext->id);
588 $roles = get_roles_with_capability('moodle/backup:backupcourse');
589 $this->assertEquals(array($teacher->id, $manager->id), array_keys($roles), '', 0, 10, true);
591 $roles = get_roles_with_capability('moodle/backup:backupcourse', CAP_ALLOW);
592 $this->assertEquals(array($manager->id), array_keys($roles), '', 0, 10, true);
594 $roles = get_roles_with_capability('moodle/backup:backupcourse', NULL, $syscontext);
595 $this->assertEquals(array($manager->id), array_keys($roles), '', 0, 10, true);
599 * Test deleting of roles.
600 * @return void
602 public function test_delete_role() {
603 global $DB;
605 $this->resetAfterTest();
607 $role = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
608 $user = $this->getDataGenerator()->create_user();
609 role_assign($role->id, $user->id, context_system::instance());
610 $course = $this->getDataGenerator()->create_course();
611 $rolename = (object)array('roleid'=>$role->id, 'name'=>'Man', 'contextid'=>context_course::instance($course->id)->id);
612 $DB->insert_record('role_names', $rolename);
614 $this->assertTrue($DB->record_exists('role_assignments', array('roleid'=>$role->id)));
615 $this->assertTrue($DB->record_exists('role_capabilities', array('roleid'=>$role->id)));
616 $this->assertTrue($DB->record_exists('role_names', array('roleid'=>$role->id)));
617 $this->assertTrue($DB->record_exists('role_context_levels', array('roleid'=>$role->id)));
618 $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$role->id)));
619 $this->assertTrue($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id)));
620 $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$role->id)));
621 $this->assertTrue($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id)));
623 $result = delete_role($role->id);
624 $this->assertTrue($result);
625 $this->assertFalse($DB->record_exists('role', array('id'=>$role->id)));
626 $this->assertFalse($DB->record_exists('role_assignments', array('roleid'=>$role->id)));
627 $this->assertFalse($DB->record_exists('role_capabilities', array('roleid'=>$role->id)));
628 $this->assertFalse($DB->record_exists('role_names', array('roleid'=>$role->id)));
629 $this->assertFalse($DB->record_exists('role_context_levels', array('roleid'=>$role->id)));
630 $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$role->id)));
631 $this->assertFalse($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id)));
632 $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$role->id)));
633 $this->assertFalse($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id)));
637 * Test fetching of all roles.
638 * @return void
640 public function test_get_all_roles() {
641 global $DB;
643 $this->resetAfterTest();
645 $allroles = get_all_roles();
646 $this->assertEquals('array', gettype($allroles));
647 $this->assertCount(8, $allroles); // there are 8 roles is standard install
649 $role = reset($allroles);
650 $role = (array)$role;
652 $this->assertEquals(array('id', 'name', 'shortname', 'description', 'sortorder', 'archetype'), array_keys($role), '', 0, 10, true);
654 foreach($allroles as $roleid => $role) {
655 $this->assertEquals($role->id, $roleid);
658 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
659 $course = $this->getDataGenerator()->create_course();
660 $coursecontext = context_course::instance($course->id);
661 $otherid = create_role('Other role', 'other', 'Some other role', '');
662 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
663 $DB->insert_record('role_names', $teacherename);
664 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
665 $DB->insert_record('role_names', $otherrename);
666 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id), '', 'roleid,name');
668 $allroles = get_all_roles($coursecontext);
669 $this->assertEquals('array', gettype($allroles));
670 $this->assertCount(9, $allroles);
671 $role = reset($allroles);
672 $role = (array)$role;
674 $this->assertEquals(array('id', 'name', 'shortname', 'description', 'sortorder', 'archetype', 'coursealias'), array_keys($role), '', 0, 10, true);
676 foreach($allroles as $roleid => $role) {
677 $this->assertEquals($role->id, $roleid);
678 if (isset($renames[$roleid])) {
679 $this->assertSame($renames[$roleid], $role->coursealias);
680 } else {
681 $this->assertSame(null, $role->coursealias);
687 * Test getting of all archetypes.
688 * @return void
690 public function test_get_role_archetypes() {
691 $archetypes = get_role_archetypes();
692 $this->assertCount(8, $archetypes); // there are 8 archetypes in standard install
693 foreach ($archetypes as $k=>$v) {
694 $this->assertSame($k, $v);
699 * Test getting of roles with given archetype.
700 * @return void
702 public function test_get_archetype_roles() {
703 $this->resetAfterTest();
705 // New install should have 1 role for each archetype.
706 $archetypes = get_role_archetypes();
707 foreach ($archetypes as $archetype) {
708 $roles = get_archetype_roles($archetype);
709 $this->assertCount(1, $roles);
710 $role = reset($roles);
711 $this->assertEquals($archetype, $role->archetype);
714 create_role('New student role', 'student2', 'New student description', 'student');
715 $roles = get_archetype_roles('student');
716 $this->assertCount(2, $roles);
720 * Test aliased role names
721 * @return void
723 public function test_role_get_name() {
724 global $DB;
726 $this->resetAfterTest();
728 $allroles = $DB->get_records('role');
729 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
730 $course = $this->getDataGenerator()->create_course();
731 $coursecontext = context_course::instance($course->id);
732 $otherid = create_role('Other role', 'other', 'Some other role', '');
733 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
734 $DB->insert_record('role_names', $teacherename);
735 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
736 $DB->insert_record('role_names', $otherrename);
737 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id), '', 'roleid,name');
739 foreach ($allroles as $role) {
740 // Get localised name from lang pack.
741 $this->assertSame('', $role->name);
742 $name = role_get_name($role, null, ROLENAME_ORIGINAL);
743 $this->assertNotEmpty($name);
744 $this->assertNotEquals($role->shortname, $name);
746 if (isset($renames[$role->id])) {
747 $this->assertSame($renames[$role->id], role_get_name($role, $coursecontext));
748 $this->assertSame($renames[$role->id], role_get_name($role, $coursecontext, ROLENAME_ALIAS));
749 $this->assertSame($renames[$role->id], role_get_name($role, $coursecontext, ROLENAME_ALIAS_RAW));
750 $this->assertSame("{$renames[$role->id]} ($name)", role_get_name($role, $coursecontext, ROLENAME_BOTH));
751 } else {
752 $this->assertSame($name, role_get_name($role, $coursecontext));
753 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_ALIAS));
754 $this->assertSame(null, role_get_name($role, $coursecontext, ROLENAME_ALIAS_RAW));
755 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_BOTH));
757 $this->assertSame($name, role_get_name($role));
758 $this->assertSame($name, role_get_name($role, $coursecontext, ROLENAME_ORIGINAL));
759 $this->assertSame($name, role_get_name($role, null, ROLENAME_ORIGINAL));
760 $this->assertSame($role->shortname, role_get_name($role, $coursecontext, ROLENAME_SHORT));
761 $this->assertSame($role->shortname, role_get_name($role, null, ROLENAME_SHORT));
762 $this->assertSame("$name ($role->shortname)", role_get_name($role, $coursecontext, ROLENAME_ORIGINALANDSHORT));
763 $this->assertSame("$name ($role->shortname)", role_get_name($role, null, ROLENAME_ORIGINALANDSHORT));
764 $this->assertSame(null, role_get_name($role, null, ROLENAME_ALIAS_RAW));
769 * Test tweaking of role name arrays
770 * @return void
772 public function test_role_fix_names() {
773 global $DB;
775 $this->resetAfterTest();
777 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
778 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
779 $otherid = create_role('Other role', 'other', 'Some other role', '');
780 $anotherid = create_role('Another role', 'another', 'Yet another other role', '');
781 $allroles = $DB->get_records('role');
783 $syscontext = context_system::instance();
784 $frontcontext = context_course::instance(SITEID);
785 $course = $this->getDataGenerator()->create_course();
786 $coursecontext = context_course::instance($course->id);
787 $category = $DB->get_record('course_categories', array('id'=>$course->category), '*', MUST_EXIST);
788 $categorycontext = context_coursecat::instance($category->id);
790 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
791 $DB->insert_record('role_names', $teacherename);
792 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
793 $DB->insert_record('role_names', $otherrename);
794 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id), '', 'roleid,name');
796 // Make sure all localname contain proper values for each ROLENAME_ constant,
797 // note role_get_name() on frontpage is used to get the original name for future comatibility.
798 $roles = $allroles;
799 unset($roles[$student->id]); // Remove one roel to make sure no role is added or removed.
800 $rolenames = array();
801 foreach ($roles as $role) {
802 $rolenames[$role->id] = $role->name;
805 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
806 foreach ($alltypes as $type) {
807 $fixed = role_fix_names($roles, $coursecontext, $type);
808 $this->assertCount(count($roles), $fixed);
809 foreach($fixed as $roleid=>$rolename) {
810 $this->assertInstanceOf('stdClass', $rolename);
811 $role = $allroles[$roleid];
812 $name = role_get_name($role, $coursecontext, $type);
813 $this->assertSame($name, $rolename->localname);
815 $fixed = role_fix_names($rolenames, $coursecontext, $type);
816 $this->assertCount(count($rolenames), $fixed);
817 foreach($fixed as $roleid=>$rolename) {
818 $role = $allroles[$roleid];
819 $name = role_get_name($role, $coursecontext, $type);
820 $this->assertSame($name, $rolename);
826 * Test allowing of role assignments.
827 * @return void
829 public function test_allow_assign() {
830 global $DB;
832 $this->resetAfterTest();
834 $otherid = create_role('Other role', 'other', 'Some other role', '');
835 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
837 $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id)));
838 allow_assign($otherid, $student->id);
839 $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id)));
843 * Test allowing of role overrides.
844 * @return void
846 public function test_allow_override() {
847 global $DB;
849 $this->resetAfterTest();
851 $otherid = create_role('Other role', 'other', 'Some other role', '');
852 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
854 $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id)));
855 allow_override($otherid, $student->id);
856 $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id)));
860 * Test allowing of role switching.
861 * @return void
863 public function test_allow_switch() {
864 global $DB;
866 $this->resetAfterTest();
868 $otherid = create_role('Other role', 'other', 'Some other role', '');
869 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
871 $this->assertFalse($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id)));
872 allow_switch($otherid, $student->id);
873 $this->assertTrue($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id)));
877 * Test returning of assignable roles in context.
878 * @return void
880 public function test_get_assignable_roles() {
881 global $DB;
883 $this->resetAfterTest();
885 $course = $this->getDataGenerator()->create_course();
886 $coursecontext = context_course::instance($course->id);
888 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
889 $teacher = $this->getDataGenerator()->create_user();
890 role_assign($teacherrole->id, $teacher->id, $coursecontext);
891 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
892 $DB->insert_record('role_names', $teacherename);
894 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
895 $student = $this->getDataGenerator()->create_user();
896 role_assign($studentrole->id, $student->id, $coursecontext);
898 $contexts = $DB->get_records('context');
899 $users = $DB->get_records('user');
900 $allroles = $DB->get_records('role');
902 // Evaluate all results for all users in all contexts.
903 foreach($users as $user) {
904 $this->setUser($user);
905 foreach ($contexts as $contextid=>$unused) {
906 $context = context_helper::instance_by_id($contextid);
907 $roles = get_assignable_roles($context, ROLENAME_SHORT);
908 foreach ($allroles as $roleid=>$role) {
909 if (isset($roles[$roleid])) {
910 if (is_siteadmin()) {
911 $this->assertTrue($DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel, 'roleid'=>$roleid)));
912 } else {
913 $this->assertTrue(user_can_assign($context, $roleid), "u:$user->id r:$roleid");
915 $this->assertEquals($role->shortname, $roles[$roleid]);
916 } else {
917 $allowed = $DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel, 'roleid'=>$roleid));
918 if (is_siteadmin()) {
919 $this->assertFalse($allowed);
920 } else {
921 $this->assertFalse($allowed and user_can_assign($context, $roleid), "u:$user->id, r:{$allroles[$roleid]->name}, c:$context->contextlevel");
928 // not-logged-in user
929 $this->setUser(0);
930 foreach ($contexts as $contextid=>$unused) {
931 $context = context_helper::instance_by_id($contextid);
932 $roles = get_assignable_roles($context, ROLENAME_SHORT);
933 $this->assertSame(array(), $roles);
936 // Test current user.
937 $this->setUser(0);
938 $admin = $DB->get_record('user', array('username'=>'admin'), '*', MUST_EXIST);
939 $roles1 = get_assignable_roles($coursecontext, ROLENAME_SHORT, false, $admin);
940 $roles2 = get_assignable_roles($coursecontext, ROLENAME_SHORT, false, $admin->id);
941 $this->setAdminUser();
942 $roles3 = get_assignable_roles($coursecontext, ROLENAME_SHORT);
943 $this->assertSame($roles1, $roles3);
944 $this->assertSame($roles2, $roles3);
946 // Test parameter defaults.
947 $this->setAdminUser();
948 $roles1 = get_assignable_roles($coursecontext);
949 $roles2 = get_assignable_roles($coursecontext, ROLENAME_ALIAS, false, $admin);
950 $this->assertEquals($roles2, $roles1);
952 // Verify returned names - let's allow all roles everywhere to simplify this a bit.
953 $alllevels = context_helper::get_all_levels();
954 $alllevels = array_keys($alllevels);
955 foreach($allroles as $roleid=>$role) {
956 set_role_contextlevels($roleid, $alllevels);
958 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
959 foreach ($alltypes as $type) {
960 $rolenames = role_fix_names($allroles, $coursecontext, $type);
961 $roles = get_assignable_roles($coursecontext, $type, false, $admin);
962 foreach ($roles as $roleid=>$rolename) {
963 $this->assertSame($rolenames[$roleid]->localname, $rolename);
967 // Verify counts.
968 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
969 foreach ($alltypes as $type) {
970 $roles = get_assignable_roles($coursecontext, $type, false, $admin);
971 list($rolenames, $rolecounts, $nameswithcounts) = get_assignable_roles($coursecontext, $type, true, $admin);
972 $this->assertEquals($roles, $rolenames);
973 foreach ($rolenames as $roleid=>$name) {
974 if ($roleid == $teacherrole->id or $roleid == $studentrole->id) {
975 $this->assertEquals(1, $rolecounts[$roleid]);
976 } else {
977 $this->assertEquals(0, $rolecounts[$roleid]);
979 $this->assertEquals("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]);
985 * Test getting of all switchable roles.
986 * @retrun void
988 public function test_get_switchable_roles() {
989 global $DB;
991 $this->resetAfterTest();
993 $course = $this->getDataGenerator()->create_course();
994 $coursecontext = context_course::instance($course->id);
996 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
997 $teacher = $this->getDataGenerator()->create_user();
998 role_assign($teacherrole->id, $teacher->id, $coursecontext);
999 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1000 $DB->insert_record('role_names', $teacherename);
1002 $contexts = $DB->get_records('context');
1003 $users = $DB->get_records('user');
1004 $allroles = $DB->get_records('role');
1006 // Evaluate all results for all users in all contexts.
1007 foreach($users as $user) {
1008 $this->setUser($user);
1009 foreach ($contexts as $contextid=>$unused) {
1010 $context = context_helper::instance_by_id($contextid);
1011 $roles = get_switchable_roles($context);
1012 foreach ($allroles as $roleid=>$role) {
1013 if (is_siteadmin()) {
1014 $this->assertTrue(isset($roles[$roleid]));
1015 } else {
1016 $parents = $context->get_parent_context_ids(true);
1017 $pcontexts = implode(',' , $parents);
1018 $allowed = $DB->record_exists_sql(
1019 "SELECT r.id
1020 FROM {role} r
1021 JOIN {role_allow_switch} ras ON ras.allowswitch = r.id
1022 JOIN {role_assignments} ra ON ra.roleid = ras.roleid
1023 WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid
1025 array('userid'=>$user->id, 'roleid'=>$roleid)
1027 if (isset($roles[$roleid])) {
1028 $this->assertTrue($allowed);
1029 } else {
1030 $this->assertFalse($allowed);
1034 if (isset($roles[$roleid])) {
1035 $coursecontext = $context->get_course_context(false);
1036 $this->assertEquals(role_get_name($role, $coursecontext), $roles[$roleid]);
1044 * Test getting of all overridable roles.
1045 * @return void
1047 public function test_get_overridable_roles() {
1048 global $DB;
1050 $this->resetAfterTest();
1052 $course = $this->getDataGenerator()->create_course();
1053 $coursecontext = context_course::instance($course->id);
1055 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1056 $teacher = $this->getDataGenerator()->create_user();
1057 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1058 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1059 $DB->insert_record('role_names', $teacherename);
1060 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability is ok
1061 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $teacher->id, $coursecontext->id);
1063 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1064 $student = $this->getDataGenerator()->create_user();
1065 role_assign($studentrole->id, $student->id, $coursecontext);
1067 $contexts = $DB->get_records('context');
1068 $users = $DB->get_records('user');
1069 $allroles = $DB->get_records('role');
1071 // Evaluate all results for all users in all contexts.
1072 foreach($users as $user) {
1073 $this->setUser($user);
1074 foreach ($contexts as $contextid=>$unused) {
1075 $context = context_helper::instance_by_id($contextid);
1076 $roles = get_overridable_roles($context, ROLENAME_SHORT);
1077 foreach ($allroles as $roleid=>$role) {
1078 $hascap = has_any_capability(array('moodle/role:safeoverride', 'moodle/role:override'), $context);
1079 if (is_siteadmin()) {
1080 $this->assertTrue(isset($roles[$roleid]));
1081 } else {
1082 $parents = $context->get_parent_context_ids(true);
1083 $pcontexts = implode(',' , $parents);
1084 $allowed = $DB->record_exists_sql(
1085 "SELECT r.id
1086 FROM {role} r
1087 JOIN {role_allow_override} rao ON r.id = rao.allowoverride
1088 JOIN {role_assignments} ra ON rao.roleid = ra.roleid
1089 WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid
1091 array('userid'=>$user->id, 'roleid'=>$roleid)
1093 if (isset($roles[$roleid])) {
1094 $this->assertTrue($hascap);
1095 $this->assertTrue($allowed);
1096 } else {
1097 $this->assertFalse($hascap and $allowed);
1101 if (isset($roles[$roleid])) {
1102 $this->assertEquals($role->shortname, $roles[$roleid]);
1108 // Test parameter defaults.
1109 $this->setAdminUser();
1110 $roles1 = get_overridable_roles($coursecontext);
1111 $roles2 = get_overridable_roles($coursecontext, ROLENAME_ALIAS, false);
1112 $this->assertEquals($roles2, $roles1);
1114 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
1115 foreach ($alltypes as $type) {
1116 $rolenames = role_fix_names($allroles, $coursecontext, $type);
1117 $roles = get_overridable_roles($coursecontext, $type, false);
1118 foreach ($roles as $roleid=>$rolename) {
1119 $this->assertSame($rolenames[$roleid]->localname, $rolename);
1123 // Verify counts.
1124 $roles = get_overridable_roles($coursecontext, ROLENAME_ALIAS, false);
1125 list($rolenames, $rolecounts, $nameswithcounts) = get_overridable_roles($coursecontext, ROLENAME_ALIAS, true);
1126 $this->assertEquals($roles, $rolenames);
1127 foreach ($rolenames as $roleid=>$name) {
1128 if ($roleid == $teacherrole->id) {
1129 $this->assertEquals(1, $rolecounts[$roleid]);
1130 } else {
1131 $this->assertEquals(0, $rolecounts[$roleid]);
1133 $this->assertEquals("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]);
1138 * Test we have context level defaults.
1139 * @return void
1141 public function test_get_default_contextlevels() {
1142 $archetypes = get_role_archetypes();
1143 $alllevels = context_helper::get_all_levels();
1144 foreach ($archetypes as $archetype) {
1145 $defaults = get_default_contextlevels($archetype);
1146 $this->assertTrue(is_array($defaults));
1147 foreach ($defaults as $level) {
1148 $this->assertTrue(isset($alllevels[$level]));
1154 * Test role context level setup.
1155 * @return void
1157 public function test_set_role_contextlevels() {
1158 global $DB;
1160 $this->resetAfterTest();
1162 $roleid = create_role('New student role', 'student2', 'New student description', 'student');
1164 $this->assertFalse($DB->record_exists('role_context_levels', array('roleid' => $roleid)));
1166 set_role_contextlevels($roleid, array(CONTEXT_COURSE, CONTEXT_MODULE));
1167 $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel');
1168 $this->assertCount(2, $levels);
1169 $this->assertTrue(isset($levels[CONTEXT_COURSE]));
1170 $this->assertTrue(isset($levels[CONTEXT_MODULE]));
1172 set_role_contextlevels($roleid, array(CONTEXT_COURSE));
1173 $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel');
1174 $this->assertCount(1, $levels);
1175 $this->assertTrue(isset($levels[CONTEXT_COURSE]));
1179 * Test getting of role context levels
1180 * @return void
1182 public function test_get_roles_for_contextlevels() {
1183 global $DB;
1185 $allroles = get_all_roles();
1186 foreach (context_helper::get_all_levels() as $level=>$unused) {
1187 $roles = get_roles_for_contextlevels($level);
1188 foreach ($allroles as $roleid=>$unused) {
1189 $exists = $DB->record_exists('role_context_levels', array('contextlevel'=>$level, 'roleid'=>$roleid));
1190 if (in_array($roleid, $roles)) {
1191 $this->assertTrue($exists);
1192 } else {
1193 $this->assertFalse($exists);
1200 * Test default enrol roles.
1201 * @return void
1203 public function test_get_default_enrol_roles() {
1204 $this->resetAfterTest();
1206 $course = $this->getDataGenerator()->create_course();
1207 $coursecontext = context_course::instance($course->id);
1209 $id2 = create_role('New student role', 'student2', 'New student description', 'student');
1210 set_role_contextlevels($id2, array(CONTEXT_COURSE));
1212 $allroles = get_all_roles();
1213 $expected = array($id2=>$allroles[$id2]);
1215 foreach(get_role_archetypes() as $archetype) {
1216 $defaults = get_default_contextlevels($archetype);
1217 if (in_array(CONTEXT_COURSE, $defaults)) {
1218 $roles = get_archetype_roles($archetype);
1219 foreach($roles as $role) {
1220 $expected[$role->id] = $role;
1225 $roles = get_default_enrol_roles($coursecontext);
1226 foreach ($allroles as $role) {
1227 $this->assertEquals(isset($expected[$role->id]), isset($roles[$role->id]));
1228 if (isset($roles[$role->id])) {
1229 $this->assertEquals(role_get_name($role, $coursecontext), $roles[$role->id]);
1235 * Test getting of role users.
1236 * @return void
1238 public function test_get_role_users() {
1239 global $DB;
1241 $this->resetAfterTest();
1243 $systemcontext = context_system::instance();
1244 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1245 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1246 $course = $this->getDataGenerator()->create_course();
1247 $coursecontext = context_course::instance($course->id);
1248 $otherid = create_role('Other role', 'other', 'Some other role', '');
1249 $teacherrename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1250 $DB->insert_record('role_names', $teacherrename);
1251 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
1252 $DB->insert_record('role_names', $otherrename);
1254 $user1 = $this->getDataGenerator()->create_user(array('firstname'=>'John', 'lastname'=>'Smith'));
1255 role_assign($teacherrole->id, $user1->id, $coursecontext->id);
1256 $user2 = $this->getDataGenerator()->create_user(array('firstname'=>'Jan', 'lastname'=>'Kovar'));
1257 role_assign($teacherrole->id, $user2->id, $systemcontext->id);
1258 $user3 = $this->getDataGenerator()->create_user();
1259 $this->getDataGenerator()->enrol_user($user3->id, $course->id, $teacherrole->id);
1260 $user4 = $this->getDataGenerator()->create_user();
1261 $this->getDataGenerator()->enrol_user($user4->id, $course->id, $studentrole->id);
1263 $group = $this->getDataGenerator()->create_group(array('courseid'=>$course->id));
1264 groups_add_member($group, $user3);
1266 $users = get_role_users($teacherrole->id, $coursecontext);
1267 $this->assertCount(2, $users);
1268 $this->assertArrayHasKey($user1->id, $users);
1269 $this->assertEquals($users[$user1->id]->id, $user1->id);
1270 $this->assertEquals($users[$user1->id]->roleid, $teacherrole->id);
1271 $this->assertEquals($users[$user1->id]->rolename, $teacherrole->name);
1272 $this->assertEquals($users[$user1->id]->roleshortname, $teacherrole->shortname);
1273 $this->assertEquals($users[$user1->id]->rolecoursealias, $teacherrename->name);
1274 $this->assertArrayHasKey($user3->id, $users);
1275 $this->assertEquals($users[$user3->id]->id, $user3->id);
1276 $this->assertEquals($users[$user3->id]->roleid, $teacherrole->id);
1277 $this->assertEquals($users[$user3->id]->rolename, $teacherrole->name);
1278 $this->assertEquals($users[$user3->id]->roleshortname, $teacherrole->shortname);
1279 $this->assertEquals($users[$user3->id]->rolecoursealias, $teacherrename->name);
1281 $users = get_role_users($teacherrole->id, $coursecontext, true);
1282 $this->assertCount(3, $users);
1284 $users = get_role_users($teacherrole->id, $coursecontext, true, '', null, null, '', 2, 1);
1285 $this->assertCount(1, $users);
1287 $users = get_role_users($teacherrole->id, $coursecontext, false, 'u.id, u.email, u.idnumber', 'u.idnumber');
1288 $this->assertCount(2, $users);
1289 $this->assertArrayHasKey($user1->id, $users);
1290 $this->assertArrayHasKey($user3->id, $users);
1292 $users = get_role_users($teacherrole->id, $coursecontext, false, 'u.id, u.email, u.idnumber', 'u.idnumber', null, $group->id);
1293 $this->assertCount(1, $users);
1294 $this->assertArrayHasKey($user3->id, $users);
1296 $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'));
1297 $this->assertCount(1, $users);
1298 $this->assertArrayHasKey($user1->id, $users);
1302 * Test used role query.
1303 * @return void
1305 public function test_get_roles_used_in_context() {
1306 global $DB;
1308 $this->resetAfterTest();
1310 $systemcontext = context_system::instance();
1311 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1312 $course = $this->getDataGenerator()->create_course();
1313 $coursecontext = context_course::instance($course->id);
1314 $otherid = create_role('Other role', 'other', 'Some other role', '');
1315 $teacherrename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1316 $DB->insert_record('role_names', $teacherrename);
1317 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
1318 $DB->insert_record('role_names', $otherrename);
1320 $user1 = $this->getDataGenerator()->create_user();
1321 role_assign($teacherrole->id, $user1->id, $coursecontext->id);
1323 $roles = get_roles_used_in_context($coursecontext);
1324 $this->assertCount(1, $roles);
1325 $role = reset($roles);
1326 $roleid = key($roles);
1327 $this->assertEquals($roleid, $role->id);
1328 $this->assertEquals($teacherrole->id, $role->id);
1329 $this->assertEquals($teacherrole->name, $role->name);
1330 $this->assertEquals($teacherrole->shortname, $role->shortname);
1331 $this->assertEquals($teacherrole->sortorder, $role->sortorder);
1332 $this->assertEquals($teacherrename->name, $role->coursealias);
1334 $user2 = $this->getDataGenerator()->create_user();
1335 role_assign($teacherrole->id, $user2->id, $systemcontext->id);
1336 role_assign($otherid, $user2->id, $systemcontext->id);
1338 $roles = get_roles_used_in_context($systemcontext);
1339 $this->assertCount(2, $roles);
1343 * Test roles used in course.
1344 * @return void
1346 public function test_get_user_roles_in_course() {
1347 global $DB, $CFG;
1349 $this->resetAfterTest();
1351 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1352 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1353 $course = $this->getDataGenerator()->create_course();
1354 $coursecontext = context_course::instance($course->id);
1355 $teacherrename = (object)array('roleid'=>$teacherrole->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1356 $DB->insert_record('role_names', $teacherrename);
1358 $roleids = explode(',', $CFG->profileroles); // should include teacher and student in new installs
1359 $this->assertTrue(in_array($teacherrole->id, $roleids));
1360 $this->assertTrue(in_array($studentrole->id, $roleids));
1362 $user1 = $this->getDataGenerator()->create_user();
1363 role_assign($teacherrole->id, $user1->id, $coursecontext->id);
1364 role_assign($studentrole->id, $user1->id, $coursecontext->id);
1365 $user2 = $this->getDataGenerator()->create_user();
1366 role_assign($studentrole->id, $user2->id, $coursecontext->id);
1367 $user3 = $this->getDataGenerator()->create_user();
1369 $roles = get_user_roles_in_course($user1->id, $course->id);
1370 $this->assertEquals(1, preg_match_all('/,/', $roles, $matches));
1371 $this->assertTrue(strpos($roles, role_get_name($teacherrole, $coursecontext)) !== false);
1373 $roles = get_user_roles_in_course($user2->id, $course->id);
1374 $this->assertEquals(0, preg_match_all('/,/', $roles, $matches));
1375 $this->assertTrue(strpos($roles, role_get_name($studentrole, $coursecontext)) !== false);
1377 $roles = get_user_roles_in_course($user3->id, $course->id);
1378 $this->assertSame('', $roles);
1382 * Test has_capability(), has_any_capability() and has_all_capabilities().
1384 public function test_has_capability_and_friends() {
1385 global $DB;
1387 $this->resetAfterTest();
1389 $course = $this->getDataGenerator()->create_course();
1390 $coursecontext = context_course::instance($course->id);
1391 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1392 $teacher = $this->getDataGenerator()->create_user();
1393 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1394 $admin = $DB->get_record('user', array('username'=>'admin'));
1396 // Note: Here are used default capabilities, the full test is in permission evaluation bellow,
1397 // use two capabilities that teacher has and one does not, none of them should be allowed for not-logged-in user.
1399 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupsection')));
1400 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse')));
1401 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/site:approvecourse')));
1403 $sca = array('moodle/backup:backupsection', 'moodle/backup:backupcourse', 'moodle/site:approvecourse');
1404 $sc = array('moodle/backup:backupsection', 'moodle/backup:backupcourse');
1406 $this->setUser(0);
1407 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext));
1408 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext));
1409 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext));
1410 $this->assertFalse(has_any_capability($sca, $coursecontext));
1411 $this->assertFalse(has_all_capabilities($sca, $coursecontext));
1413 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $teacher));
1414 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $teacher));
1415 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $teacher));
1416 $this->assertTrue(has_any_capability($sca, $coursecontext, $teacher));
1417 $this->assertTrue(has_all_capabilities($sc, $coursecontext, $teacher));
1418 $this->assertFalse(has_all_capabilities($sca, $coursecontext, $teacher));
1420 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $admin));
1421 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $admin));
1422 $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext, $admin));
1423 $this->assertTrue(has_any_capability($sca, $coursecontext, $admin));
1424 $this->assertTrue(has_all_capabilities($sc, $coursecontext, $admin));
1425 $this->assertTrue(has_all_capabilities($sca, $coursecontext, $admin));
1427 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, $admin, false));
1428 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, $admin, false));
1429 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $admin, false));
1430 $this->assertFalse(has_any_capability($sca, $coursecontext, $admin, false));
1431 $this->assertFalse(has_all_capabilities($sc, $coursecontext, $admin, false));
1432 $this->assertFalse(has_all_capabilities($sca, $coursecontext, $admin, false));
1434 $this->setUser($teacher);
1435 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext));
1436 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext));
1437 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext));
1438 $this->assertTrue(has_any_capability($sca, $coursecontext));
1439 $this->assertTrue(has_all_capabilities($sc, $coursecontext));
1440 $this->assertFalse(has_all_capabilities($sca, $coursecontext));
1442 $this->setAdminUser();
1443 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext));
1444 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext));
1445 $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext));
1446 $this->assertTrue(has_any_capability($sca, $coursecontext));
1447 $this->assertTrue(has_all_capabilities($sc, $coursecontext));
1448 $this->assertTrue(has_all_capabilities($sca, $coursecontext));
1450 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, 0));
1451 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, 0));
1452 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, 0));
1453 $this->assertFalse(has_any_capability($sca, $coursecontext, 0));
1454 $this->assertFalse(has_all_capabilities($sca, $coursecontext, 0));
1458 * Test require_capability() exceptions.
1459 * @return void
1461 public function test_require_capability() {
1462 $this->resetAfterTest();
1464 $syscontext = context_system::instance();
1466 $this->setUser(0);
1467 $this->assertFalse(has_capability('moodle/site:config', $syscontext));
1468 try {
1469 require_capability('moodle/site:config', $syscontext);
1470 $this->fail('Exception expected from require_capability()');
1471 } catch (Exception $e) {
1472 $this->assertInstanceOf('required_capability_exception', $e);
1474 $this->setAdminUser();
1475 $this->assertFalse(has_capability('moodle/site:config', $syscontext, 0));
1476 try {
1477 require_capability('moodle/site:config', $syscontext, 0);
1478 $this->fail('Exception expected from require_capability()');
1479 } catch (Exception $e) {
1480 $this->assertInstanceOf('required_capability_exception', $e);
1482 $this->assertFalse(has_capability('moodle/site:config', $syscontext, null, false));
1483 try {
1484 require_capability('moodle/site:config', $syscontext, null, false);
1485 $this->fail('Exception expected from require_capability()');
1486 } catch (Exception $e) {
1487 $this->assertInstanceOf('required_capability_exception', $e);
1494 * A small functional test of permission evaluations.
1495 * @return void
1497 public function test_permission_evaluation() {
1498 global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;
1500 $this->resetAfterTest(true);
1502 $generator = $this->getDataGenerator();
1504 // Fill the site with some real data
1505 $testcategories = array();
1506 $testcourses = array();
1507 $testpages = array();
1508 $testblocks = array();
1509 $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
1511 $systemcontext = context_system::instance();
1512 $frontpagecontext = context_course::instance(SITEID);
1514 // Add block to system context
1515 $bi = $generator->create_block('online_users');
1516 context_block::instance($bi->id);
1517 $testblocks[] = $bi->id;
1519 // Some users
1520 $testusers = array();
1521 for($i=0; $i<20; $i++) {
1522 $user = $generator->create_user();
1523 $testusers[$i] = $user->id;
1524 $usercontext = context_user::instance($user->id);
1526 // Add block to user profile
1527 $bi = $generator->create_block('online_users', array('parentcontextid'=>$usercontext->id));
1528 $testblocks[] = $bi->id;
1530 // Deleted user - should be ignored everywhere, can not have context
1531 $generator->create_user(array('deleted'=>1));
1533 // Add block to frontpage
1534 $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagecontext->id));
1535 $frontpageblockcontext = context_block::instance($bi->id);
1536 $testblocks[] = $bi->id;
1538 // Add a resource to frontpage
1539 $page = $generator->create_module('page', array('course'=>$SITE->id));
1540 $testpages[] = $page->id;
1541 $frontpagepagecontext = context_module::instance($page->cmid);
1543 // Add block to frontpage resource
1544 $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagepagecontext->id));
1545 $frontpagepageblockcontext = context_block::instance($bi->id);
1546 $testblocks[] = $bi->id;
1548 // Some nested course categories with courses
1549 $manualenrol = enrol_get_plugin('manual');
1550 $parentcat = 0;
1551 for($i=0; $i<5; $i++) {
1552 $cat = $generator->create_category(array('parent'=>$parentcat));
1553 $testcategories[] = $cat->id;
1554 $catcontext = context_coursecat::instance($cat->id);
1555 $parentcat = $cat->id;
1557 if ($i >= 4) {
1558 continue;
1561 // Add resource to each category
1562 $bi = $generator->create_block('online_users', array('parentcontextid'=>$catcontext->id));
1563 context_block::instance($bi->id);
1565 // Add a few courses to each category
1566 for($j=0; $j<6; $j++) {
1567 $course = $generator->create_course(array('category'=>$cat->id));
1568 $testcourses[] = $course->id;
1569 $coursecontext = context_course::instance($course->id);
1571 if ($j >= 5) {
1572 continue;
1574 // Add manual enrol instance
1575 $manualenrol->add_default_instance($DB->get_record('course', array('id'=>$course->id)));
1577 // Add block to each course
1578 $bi = $generator->create_block('online_users', array('parentcontextid'=>$coursecontext->id));
1579 $testblocks[] = $bi->id;
1581 // Add a resource to each course
1582 $page = $generator->create_module('page', array('course'=>$course->id));
1583 $testpages[] = $page->id;
1584 $modcontext = context_module::instance($page->cmid);
1586 // Add block to each module
1587 $bi = $generator->create_block('online_users', array('parentcontextid'=>$modcontext->id));
1588 $testblocks[] = $bi->id;
1592 // Make sure all contexts were created properly
1593 $count = 1; //system
1594 $count += $DB->count_records('user', array('deleted'=>0));
1595 $count += $DB->count_records('course_categories');
1596 $count += $DB->count_records('course');
1597 $count += $DB->count_records('course_modules');
1598 $count += $DB->count_records('block_instances');
1599 $this->assertEquals($DB->count_records('context'), $count);
1600 $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
1601 $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
1604 // ====== context_helper::get_level_name() ================================
1606 $levels = context_helper::get_all_levels();
1607 foreach ($levels as $level=>$classname) {
1608 $name = context_helper::get_level_name($level);
1609 $this->assertFalse(empty($name));
1613 // ======= context::instance_by_id(), context_xxx::instance();
1615 $context = context::instance_by_id($frontpagecontext->id);
1616 $this->assertSame($context->contextlevel, CONTEXT_COURSE);
1617 $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING));
1618 try {
1619 context::instance_by_id(-1);
1620 $this->fail('exception expected');
1621 } catch (Exception $e) {
1622 $this->assertTrue(true);
1624 $this->assertTrue(context_system::instance() instanceof context_system);
1625 $this->assertTrue(context_coursecat::instance($testcategories[0]) instanceof context_coursecat);
1626 $this->assertTrue(context_course::instance($testcourses[0]) instanceof context_course);
1627 $this->assertTrue(context_module::instance($testpages[0]) instanceof context_module);
1628 $this->assertTrue(context_block::instance($testblocks[0]) instanceof context_block);
1630 $this->assertFalse(context_coursecat::instance(-1, IGNORE_MISSING));
1631 $this->assertFalse(context_course::instance(-1, IGNORE_MISSING));
1632 $this->assertFalse(context_module::instance(-1, IGNORE_MISSING));
1633 $this->assertFalse(context_block::instance(-1, IGNORE_MISSING));
1634 try {
1635 context_coursecat::instance(-1);
1636 $this->fail('exception expected');
1637 } catch (Exception $e) {
1638 $this->assertTrue(true);
1640 try {
1641 context_course::instance(-1);
1642 $this->fail('exception expected');
1643 } catch (Exception $e) {
1644 $this->assertTrue(true);
1646 try {
1647 context_module::instance(-1);
1648 $this->fail('exception expected');
1649 } catch (Exception $e) {
1650 $this->assertTrue(true);
1652 try {
1653 context_block::instance(-1);
1654 $this->fail('exception expected');
1655 } catch (Exception $e) {
1656 $this->assertTrue(true);
1660 // ======= $context->get_url(), $context->get_context_name(), $context->get_capabilities() =========
1662 $testcontexts = array();
1663 $testcontexts[CONTEXT_SYSTEM] = context_system::instance();
1664 $testcontexts[CONTEXT_COURSECAT] = context_coursecat::instance($testcategories[0]);
1665 $testcontexts[CONTEXT_COURSE] = context_course::instance($testcourses[0]);
1666 $testcontexts[CONTEXT_MODULE] = context_module::instance($testpages[0]);
1667 $testcontexts[CONTEXT_BLOCK] = context_block::instance($testblocks[0]);
1669 foreach ($testcontexts as $context) {
1670 $name = $context->get_context_name(true, true);
1671 $this->assertFalse(empty($name));
1673 $this->assertTrue($context->get_url() instanceof moodle_url);
1675 $caps = $context->get_capabilities();
1676 $this->assertTrue(is_array($caps));
1677 foreach ($caps as $cap) {
1678 $cap = (array)$cap;
1679 $this->assertSame(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask'));
1682 unset($testcontexts);
1684 // ===== $context->get_course_context() =========================================
1686 $this->assertFalse($systemcontext->get_course_context(false));
1687 try {
1688 $systemcontext->get_course_context();
1689 $this->fail('exception expected');
1690 } catch (Exception $e) {
1691 $this->assertTrue(true);
1693 $context = context_coursecat::instance($testcategories[0]);
1694 $this->assertFalse($context->get_course_context(false));
1695 try {
1696 $context->get_course_context();
1697 $this->fail('exception expected');
1698 } catch (Exception $e) {
1699 $this->assertTrue(true);
1701 $this->assertSame($frontpagecontext->get_course_context(true), $frontpagecontext);
1702 $this->assertSame($frontpagepagecontext->get_course_context(true), $frontpagecontext);
1703 $this->assertSame($frontpagepageblockcontext->get_course_context(true), $frontpagecontext);
1706 // ======= $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() =======
1708 $userid = reset($testusers);
1709 $usercontext = context_user::instance($userid);
1710 $this->assertSame($usercontext->get_parent_context(), $systemcontext);
1711 $this->assertSame($usercontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
1712 $this->assertSame($usercontext->get_parent_contexts(true), array($usercontext->id=>$usercontext, $systemcontext->id=>$systemcontext));
1714 $this->assertSame($systemcontext->get_parent_contexts(), array());
1715 $this->assertSame($systemcontext->get_parent_contexts(true), array($systemcontext->id=>$systemcontext));
1716 $this->assertSame($systemcontext->get_parent_context_ids(), array());
1717 $this->assertSame($systemcontext->get_parent_context_ids(true), array($systemcontext->id));
1719 $this->assertSame($frontpagecontext->get_parent_context(), $systemcontext);
1720 $this->assertSame($frontpagecontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
1721 $this->assertSame($frontpagecontext->get_parent_contexts(true), array($frontpagecontext->id=>$frontpagecontext, $systemcontext->id=>$systemcontext));
1722 $this->assertSame($frontpagecontext->get_parent_context_ids(), array($systemcontext->id));
1723 $this->assertEquals($frontpagecontext->get_parent_context_ids(true), array($frontpagecontext->id, $systemcontext->id));
1725 $this->assertSame($systemcontext->get_parent_context(), false);
1726 $frontpagecontext = context_course::instance($SITE->id);
1727 $parent = $systemcontext;
1728 foreach ($testcategories as $catid) {
1729 $catcontext = context_coursecat::instance($catid);
1730 $this->assertSame($catcontext->get_parent_context(), $parent);
1731 $parent = $catcontext;
1733 $this->assertSame($frontpagepagecontext->get_parent_context(), $frontpagecontext);
1734 $this->assertSame($frontpageblockcontext->get_parent_context(), $frontpagecontext);
1735 $this->assertSame($frontpagepageblockcontext->get_parent_context(), $frontpagepagecontext);
1738 // ====== $context->get_child_contexts() ================================
1740 $children = $systemcontext->get_child_contexts();
1741 $this->resetDebugging();
1742 $this->assertEquals(count($children)+1, $DB->count_records('context'));
1744 $context = context_coursecat::instance($testcategories[3]);
1745 $children = $context->get_child_contexts();
1746 $countcats = 0;
1747 $countcourses = 0;
1748 $countblocks = 0;
1749 foreach ($children as $child) {
1750 if ($child->contextlevel == CONTEXT_COURSECAT) {
1751 $countcats++;
1753 if ($child->contextlevel == CONTEXT_COURSE) {
1754 $countcourses++;
1756 if ($child->contextlevel == CONTEXT_BLOCK) {
1757 $countblocks++;
1760 $this->assertEquals(count($children), 8);
1761 $this->assertEquals($countcats, 1);
1762 $this->assertEquals($countcourses, 6);
1763 $this->assertEquals($countblocks, 1);
1765 $context = context_course::instance($testcourses[2]);
1766 $children = $context->get_child_contexts();
1767 $this->assertEquals(count($children), 7); // depends on number of default blocks
1769 $context = context_module::instance($testpages[3]);
1770 $children = $context->get_child_contexts();
1771 $this->assertEquals(count($children), 1);
1773 $context = context_block::instance($testblocks[1]);
1774 $children = $context->get_child_contexts();
1775 $this->assertEquals(count($children), 0);
1777 unset($children);
1778 unset($countcats);
1779 unset($countcourses);
1780 unset($countblocks);
1783 // ======= context_helper::reset_caches() ============================
1785 context_helper::reset_caches();
1786 $this->assertEquals(context_inspection::test_context_cache_size(), 0);
1787 context_course::instance($SITE->id);
1788 $this->assertEquals(context_inspection::test_context_cache_size(), 1);
1791 // ======= context preloading ========================================
1793 context_helper::reset_caches();
1794 $sql = "SELECT ".context_helper::get_preload_record_columns_sql('c')."
1795 FROM {context} c
1796 WHERE c.contextlevel <> ".CONTEXT_SYSTEM;
1797 $records = $DB->get_records_sql($sql);
1798 $firstrecord = reset($records);
1799 $columns = context_helper::get_preload_record_columns('c');
1800 $firstrecord = (array)$firstrecord;
1801 $this->assertSame(array_keys($firstrecord), array_values($columns));
1802 context_helper::reset_caches();
1803 foreach ($records as $record) {
1804 context_helper::preload_from_record($record);
1805 $this->assertEquals($record, new stdClass());
1807 $this->assertEquals(context_inspection::test_context_cache_size(), count($records));
1808 unset($records);
1809 unset($columns);
1811 context_helper::reset_caches();
1812 context_helper::preload_course($SITE->id);
1813 $numfrontpagemodules = $DB->count_records('course_modules', array('course' => $SITE->id));
1814 $this->assertEquals(6 + $numfrontpagemodules, context_inspection::test_context_cache_size()); // depends on number of default blocks
1816 // ====== assign_capability(), unassign_capability() ====================
1818 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1819 $this->assertFalse($rc);
1820 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext->id);
1821 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1822 $this->assertEquals($rc->permission, CAP_ALLOW);
1823 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext->id);
1824 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1825 $this->assertEquals($rc->permission, CAP_ALLOW);
1826 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext, true);
1827 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1828 $this->assertEquals($rc->permission, CAP_PREVENT);
1830 assign_capability('moodle/site:accessallgroups', CAP_INHERIT, $allroles['teacher'], $frontpagecontext);
1831 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1832 $this->assertFalse($rc);
1833 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext);
1834 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true);
1835 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1836 $this->assertFalse($rc);
1837 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true);
1838 unset($rc);
1840 accesslib_clear_all_caches(false); // must be done after assign_capability()
1843 // ======= role_assign(), role_unassign(), role_unassign_all() ==============
1845 $context = context_course::instance($testcourses[1]);
1846 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
1847 role_assign($allroles['teacher'], $testusers[1], $context->id);
1848 role_assign($allroles['teacher'], $testusers[2], $context->id);
1849 role_assign($allroles['manager'], $testusers[1], $context->id);
1850 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 3);
1851 role_unassign($allroles['teacher'], $testusers[1], $context->id);
1852 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 2);
1853 role_unassign_all(array('contextid'=>$context->id));
1854 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
1855 unset($context);
1857 accesslib_clear_all_caches(false); // just in case
1860 // ====== has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends ========================
1862 $adminid = get_admin()->id;
1863 $guestid = $CFG->siteguest;
1865 // Enrol some users into some courses
1866 $course1 = $DB->get_record('course', array('id'=>$testcourses[22]), '*', MUST_EXIST);
1867 $course2 = $DB->get_record('course', array('id'=>$testcourses[7]), '*', MUST_EXIST);
1868 $cms = $DB->get_records('course_modules', array('course'=>$course1->id), 'id');
1869 $cm1 = reset($cms);
1870 $blocks = $DB->get_records('block_instances', array('parentcontextid'=>context_module::instance($cm1->id)->id), 'id');
1871 $block1 = reset($blocks);
1872 $instance1 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course1->id));
1873 $instance2 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course2->id));
1874 for($i=0; $i<9; $i++) {
1875 $manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']);
1877 $manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']);
1878 $manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']);
1880 for($i=10; $i<15; $i++) {
1881 $manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']);
1883 $manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']);
1885 // Add tons of role assignments - the more the better
1886 role_assign($allroles['coursecreator'], $testusers[11], context_coursecat::instance($testcategories[2]));
1887 role_assign($allroles['manager'], $testusers[12], context_coursecat::instance($testcategories[1]));
1888 role_assign($allroles['student'], $testusers[9], context_module::instance($cm1->id));
1889 role_assign($allroles['teacher'], $testusers[8], context_module::instance($cm1->id));
1890 role_assign($allroles['guest'], $testusers[13], context_course::instance($course1->id));
1891 role_assign($allroles['teacher'], $testusers[7], context_block::instance($block1->id));
1892 role_assign($allroles['manager'], $testusers[9], context_block::instance($block1->id));
1893 role_assign($allroles['editingteacher'], $testusers[9], context_course::instance($course1->id));
1895 role_assign($allroles['teacher'], $adminid, context_course::instance($course1->id));
1896 role_assign($allroles['editingteacher'], $adminid, context_block::instance($block1->id));
1898 // Add tons of overrides - the more the better
1899 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpageblockcontext, true);
1900 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpageblockcontext, true);
1901 assign_capability('moodle/block:view', CAP_PROHIBIT, $allroles['guest'], $frontpageblockcontext, true);
1902 assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['user'], $frontpageblockcontext, true);
1903 assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['student'], $frontpageblockcontext, true);
1905 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $CFG->defaultuserroleid, $frontpagepagecontext, true);
1906 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagepagecontext, true);
1907 assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $frontpagepagecontext, true);
1908 assign_capability('mod/page:view', CAP_ALLOW, $allroles['user'], $frontpagepagecontext, true);
1909 assign_capability('moodle/page:view', CAP_ALLOW, $allroles['student'], $frontpagepagecontext, true);
1911 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpagecontext, true);
1912 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext, true);
1913 assign_capability('mod/page:view', CAP_ALLOW, $allroles['guest'], $frontpagecontext, true);
1914 assign_capability('mod/page:view', CAP_PROHIBIT, $allroles['user'], $frontpagecontext, true);
1916 assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $systemcontext, true);
1918 accesslib_clear_all_caches(false); // must be done after assign_capability()
1920 // Extra tests for guests and not-logged-in users because they can not be verified by cross checking
1921 // with get_users_by_capability() where they are ignored
1922 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid));
1923 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid));
1924 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid));
1925 $this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid));
1927 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0));
1928 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0));
1929 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0));
1930 $this->assertFalse(has_capability('mod/page:view', $systemcontext, 0));
1932 $this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11]));
1933 $this->assertTrue(has_capability('moodle/course:create', context_coursecat::instance($testcategories[2]), $testusers[11]));
1934 $this->assertFalse(has_capability('moodle/course:create', context_course::instance($testcourses[1]), $testusers[11]));
1935 $this->assertTrue(has_capability('moodle/course:create', context_course::instance($testcourses[19]), $testusers[11]));
1937 $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[1]), $testusers[9]));
1938 $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[19]), $testusers[9]));
1939 $this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9]));
1941 // Test the list of enrolled users
1942 $coursecontext = context_course::instance($course1->id);
1943 $enrolled = get_enrolled_users($coursecontext);
1944 $this->assertEquals(count($enrolled), 10);
1945 for($i=0; $i<10; $i++) {
1946 $this->assertTrue(isset($enrolled[$testusers[$i]]));
1948 $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
1949 $this->assertEquals(count($enrolled), 1);
1950 $this->assertTrue(isset($enrolled[$testusers[9]]));
1951 unset($enrolled);
1953 // role switching
1954 $userid = $testusers[9];
1955 $USER = $DB->get_record('user', array('id'=>$userid));
1956 load_all_capabilities();
1957 $coursecontext = context_course::instance($course1->id);
1958 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
1959 $this->assertFalse(is_role_switched($course1->id));
1960 role_switch($allroles['student'], $coursecontext);
1961 $this->assertTrue(is_role_switched($course1->id));
1962 $this->assertEquals($USER->access['rsw'][$coursecontext->path], $allroles['student']);
1963 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
1964 reload_all_capabilities();
1965 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
1966 role_switch(0, $coursecontext);
1967 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
1968 $userid = $adminid;
1969 $USER = $DB->get_record('user', array('id'=>$userid));
1970 load_all_capabilities();
1971 $coursecontext = context_course::instance($course1->id);
1972 $blockcontext = context_block::instance($block1->id);
1973 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
1974 role_switch($allroles['student'], $coursecontext);
1975 $this->assertEquals($USER->access['rsw'][$coursecontext->path], $allroles['student']);
1976 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
1977 reload_all_capabilities();
1978 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
1979 load_all_capabilities();
1980 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
1982 // temp course role for enrol
1983 $DB->delete_records('cache_flags', array()); // this prevents problem with dirty contexts immediately resetting the temp role - this is a known problem...
1984 $userid = $testusers[5];
1985 $roleid = $allroles['editingteacher'];
1986 $USER = $DB->get_record('user', array('id'=>$userid));
1987 load_all_capabilities();
1988 $coursecontext = context_course::instance($course1->id);
1989 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
1990 $this->assertFalse(isset($USER->access['ra'][$coursecontext->path][$roleid]));
1991 load_temp_course_role($coursecontext, $roleid);
1992 $this->assertEquals($USER->access['ra'][$coursecontext->path][$roleid], $roleid);
1993 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
1994 remove_temp_course_roles($coursecontext);
1995 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
1996 load_temp_course_role($coursecontext, $roleid);
1997 reload_all_capabilities();
1998 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
1999 $USER = new stdClass();
2000 $USER->id = 0;
2002 // Now cross check has_capability() with get_users_by_capability(), each using different code paths,
2003 // they have to be kept in sync, usually only one of them breaks, so we know when something is wrong,
2004 // at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users)
2005 $contexts = $DB->get_records('context', array(), 'id');
2006 $contexts = array_values($contexts);
2007 $capabilities = $DB->get_records('capabilities', array(), 'id');
2008 $capabilities = array_values($capabilities);
2009 $roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']);
2010 $userids = array_values($testusers);
2011 $userids[] = get_admin()->id;
2013 if (!PHPUNIT_LONGTEST) {
2014 $contexts = array_slice($contexts, 0, 10);
2015 $capabilities = array_slice($capabilities, 0, 5);
2016 $userids = array_slice($userids, 0, 5);
2019 // Random time!
2020 //srand(666);
2021 foreach($userids as $userid) { // no guest or deleted
2022 // each user gets 0-10 random roles
2023 $rcount = rand(0, 10);
2024 for($j=0; $j<$rcount; $j++) {
2025 $roleid = $roles[rand(0, count($roles)-1)];
2026 $contextid = $contexts[rand(0, count($contexts)-1)]->id;
2027 role_assign($roleid, $userid, $contextid);
2031 $permissions = array(CAP_ALLOW, CAP_PREVENT, CAP_INHERIT, CAP_PREVENT);
2032 $maxoverrides = count($contexts)*10;
2033 for($j=0; $j<$maxoverrides; $j++) {
2034 $roleid = $roles[rand(0, count($roles)-1)];
2035 $contextid = $contexts[rand(0, count($contexts)-1)]->id;
2036 $permission = $permissions[rand(0,count($permissions)-1)];
2037 $capname = $capabilities[rand(0, count($capabilities)-1)]->name;
2038 assign_capability($capname, $permission, $roleid, $contextid, true);
2040 unset($permissions);
2041 unset($roles);
2043 accesslib_clear_all_caches(false); // must be done after assign_capability()
2045 // Test time - let's set up some real user, just in case the logic for USER affects the others...
2046 $USER = $DB->get_record('user', array('id'=>$testusers[3]));
2047 load_all_capabilities();
2049 $userids[] = $CFG->siteguest;
2050 $userids[] = 0; // not-logged-in user
2051 $userids[] = -1; // non-existent user
2053 foreach ($contexts as $crecord) {
2054 $context = context::instance_by_id($crecord->id);
2055 if ($coursecontext = $context->get_course_context(false)) {
2056 $enrolled = get_enrolled_users($context);
2057 } else {
2058 $enrolled = array();
2060 foreach ($capabilities as $cap) {
2061 $allowed = get_users_by_capability($context, $cap->name, 'u.id, u.username');
2062 if ($enrolled) {
2063 $enrolledwithcap = get_enrolled_users($context, $cap->name);
2064 } else {
2065 $enrolledwithcap = array();
2067 foreach ($userids as $userid) {
2068 if ($userid == 0 or isguestuser($userid)) {
2069 if ($userid == 0) {
2070 $CFG->forcelogin = true;
2071 $this->assertFalse(has_capability($cap->name, $context, $userid));
2072 unset($CFG->forcelogin);
2074 if (($cap->captype === 'write') or ($cap->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))) {
2075 $this->assertFalse(has_capability($cap->name, $context, $userid));
2077 $this->assertFalse(isset($allowed[$userid]));
2078 } else {
2079 if (is_siteadmin($userid)) {
2080 $this->assertTrue(has_capability($cap->name, $context, $userid, true));
2082 $hascap = has_capability($cap->name, $context, $userid, false);
2083 $this->assertSame($hascap, isset($allowed[$userid]), "Capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
2084 if (isset($enrolled[$userid])) {
2085 $this->assertSame(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
2091 // Back to nobody
2092 $USER = new stdClass();
2093 $USER->id = 0;
2094 unset($contexts);
2095 unset($userids);
2096 unset($capabilities);
2098 // Now let's do all the remaining tests that break our carefully prepared fake site
2102 // ======= $context->mark_dirty() =======================================
2104 $DB->delete_records('cache_flags', array());
2105 accesslib_clear_all_caches(false);
2106 $systemcontext->mark_dirty();
2107 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2108 $this->assertTrue(isset($dirty[$systemcontext->path]));
2109 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$systemcontext->path]));
2112 // ======= $context->reload_if_dirty(); =================================
2114 $DB->delete_records('cache_flags', array());
2115 accesslib_clear_all_caches(false);
2116 load_all_capabilities();
2117 $context = context_course::instance($testcourses[2]);
2118 $page = $DB->get_record('page', array('course'=>$testcourses[2]));
2119 $pagecm = get_coursemodule_from_instance('page', $page->id);
2120 $pagecontext = context_module::instance($pagecm->id);
2122 $context->mark_dirty();
2123 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
2124 $USER->access['test'] = true;
2125 $context->reload_if_dirty();
2126 $this->assertFalse(isset($USER->access['test']));
2128 $context->mark_dirty();
2129 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
2130 $USER->access['test'] = true;
2131 $pagecontext->reload_if_dirty();
2132 $this->assertFalse(isset($USER->access['test']));
2135 // ======= context_helper::build_all_paths() ============================
2137 $oldcontexts = $DB->get_records('context', array(), 'id');
2138 $DB->set_field_select('context', 'path', NULL, "contextlevel <> ".CONTEXT_SYSTEM);
2139 $DB->set_field_select('context', 'depth', 0, "contextlevel <> ".CONTEXT_SYSTEM);
2140 context_helper::build_all_paths();
2141 $newcontexts = $DB->get_records('context', array(), 'id');
2142 $this->assertEquals($oldcontexts, $newcontexts);
2143 unset($oldcontexts);
2144 unset($newcontexts);
2147 // ======= $context->reset_paths() ======================================
2149 $context = context_course::instance($testcourses[2]);
2150 $children = $context->get_child_contexts();
2151 $context->reset_paths(false);
2152 $this->assertSame($DB->get_field('context', 'path', array('id'=>$context->id)), NULL);
2153 $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), 0);
2154 foreach ($children as $child) {
2155 $this->assertSame($DB->get_field('context', 'path', array('id'=>$child->id)), NULL);
2156 $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$child->id)), 0);
2158 $this->assertEquals(count($children)+1, $DB->count_records('context', array('depth'=>0)));
2159 $this->assertEquals(count($children)+1, $DB->count_records('context', array('path'=>NULL)));
2161 $context = context_course::instance($testcourses[2]);
2162 $context->reset_paths(true);
2163 $context = context_course::instance($testcourses[2]);
2164 $this->assertEquals($DB->get_field('context', 'path', array('id'=>$context->id)), $context->path);
2165 $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), $context->depth);
2166 $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
2167 $this->assertEquals(0, $DB->count_records('context', array('path'=>NULL)));
2170 // ====== $context->update_moved(); ======================================
2172 accesslib_clear_all_caches(false);
2173 $DB->delete_records('cache_flags', array());
2174 $course = $DB->get_record('course', array('id'=>$testcourses[0]));
2175 $context = context_course::instance($course->id);
2176 $oldpath = $context->path;
2177 $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
2178 $categorycontext = context_coursecat::instance($miscid);
2179 $course->category = $miscid;
2180 $DB->update_record('course', $course);
2181 $context->update_moved($categorycontext);
2183 $context = context_course::instance($course->id);
2184 $this->assertEquals($context->get_parent_context(), $categorycontext);
2185 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2186 $this->assertTrue(isset($dirty[$oldpath]));
2187 $this->assertTrue(isset($dirty[$context->path]));
2190 // ====== $context->delete_content() =====================================
2192 context_helper::reset_caches();
2193 $context = context_module::instance($testpages[3]);
2194 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
2195 $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2196 $context->delete_content();
2197 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
2198 $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2201 // ====== $context->delete() =============================
2203 context_helper::reset_caches();
2204 $context = context_module::instance($testpages[4]);
2205 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
2206 $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2207 $bi = $DB->get_record('block_instances', array('parentcontextid'=>$context->id));
2208 $bicontext = context_block::instance($bi->id);
2209 $DB->delete_records('cache_flags', array());
2210 $context->delete(); // should delete also linked blocks
2211 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2212 $this->assertTrue(isset($dirty[$context->path]));
2213 $this->assertFalse($DB->record_exists('context', array('id'=>$context->id)));
2214 $this->assertFalse($DB->record_exists('context', array('id'=>$bicontext->id)));
2215 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_MODULE, 'instanceid'=>$testpages[4])));
2216 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK, 'instanceid'=>$bi->id)));
2217 $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2218 context_module::instance($testpages[4]);
2221 // ====== context_helper::delete_instance() =============================
2223 context_helper::reset_caches();
2224 $lastcourse = array_pop($testcourses);
2225 $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
2226 $coursecontext = context_course::instance($lastcourse);
2227 $this->assertEquals(context_inspection::test_context_cache_size(), 1);
2228 $this->assertFalse($coursecontext->instanceid == CONTEXT_COURSE);
2229 $DB->delete_records('cache_flags', array());
2230 context_helper::delete_instance(CONTEXT_COURSE, $lastcourse);
2231 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2232 $this->assertTrue(isset($dirty[$coursecontext->path]));
2233 $this->assertEquals(context_inspection::test_context_cache_size(), 0);
2234 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
2235 context_course::instance($lastcourse);
2238 // ======= context_helper::create_instances() ==========================
2240 $prevcount = $DB->count_records('context');
2241 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
2242 context_helper::create_instances(null, true);
2243 $this->assertSame($DB->count_records('context'), $prevcount);
2244 $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
2245 $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
2247 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
2248 $DB->delete_records('block_instances', array());
2249 $prevcount = $DB->count_records('context');
2250 $DB->delete_records_select('context', 'contextlevel <> '.CONTEXT_SYSTEM);
2251 context_helper::create_instances(null, true);
2252 $this->assertSame($DB->count_records('context'), $prevcount);
2253 $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
2254 $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
2257 // ======= context_helper::cleanup_instances() ==========================
2259 $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
2260 $DB->delete_records('course', array('id'=>$lastcourse));
2261 $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
2262 $DB->delete_records('course_categories', array('id'=>$lastcategory));
2263 $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
2264 $DB->delete_records('user', array('id'=>$lastuser));
2265 $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
2266 $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
2267 context_helper::cleanup_instances();
2268 $count = 1; //system
2269 $count += $DB->count_records('user', array('deleted'=>0));
2270 $count += $DB->count_records('course_categories');
2271 $count += $DB->count_records('course');
2272 $count += $DB->count_records('course_modules');
2273 $count += $DB->count_records('block_instances');
2274 $this->assertEquals($DB->count_records('context'), $count);
2277 // ======= context cache size restrictions ==============================
2279 $testusers= array();
2280 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
2281 $user = $generator->create_user();
2282 $testusers[$i] = $user->id;
2284 context_helper::create_instances(null, true);
2285 context_helper::reset_caches();
2286 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
2287 context_user::instance($testusers[$i]);
2288 if ($i == CONTEXT_CACHE_MAX_SIZE - 1) {
2289 $this->assertEquals(context_inspection::test_context_cache_size(), CONTEXT_CACHE_MAX_SIZE);
2290 } else if ($i == CONTEXT_CACHE_MAX_SIZE) {
2291 // once the limit is reached roughly 1/3 of records should be removed from cache
2292 $this->assertEquals(context_inspection::test_context_cache_size(), (int)(CONTEXT_CACHE_MAX_SIZE * (2/3) +102));
2295 // We keep the first 100 cached
2296 $prevsize = context_inspection::test_context_cache_size();
2297 for ($i=0; $i<100; $i++) {
2298 context_user::instance($testusers[$i]);
2299 $this->assertEquals(context_inspection::test_context_cache_size(), $prevsize);
2301 context_user::instance($testusers[102]);
2302 $this->assertEquals(context_inspection::test_context_cache_size(), $prevsize+1);
2303 unset($testusers);
2307 // =================================================================
2308 // ======= basic test of legacy functions ==========================
2309 // =================================================================
2310 // note: watch out, the fake site might be pretty borked already
2312 $this->assertSame(get_system_context(), context_system::instance());
2314 foreach ($DB->get_records('context') as $contextid=>$record) {
2315 $context = context::instance_by_id($contextid);
2316 $this->assertSame(context::instance_by_id($contextid, IGNORE_MISSING), $context);
2317 $this->assertSame(get_context_instance($record->contextlevel, $record->instanceid), $context);
2318 $this->assertSame(get_parent_contexts($context), $context->get_parent_context_ids());
2319 if ($context->id == SYSCONTEXTID) {
2320 $this->assertSame(get_parent_contextid($context), false);
2321 } else {
2322 $this->assertSame(get_parent_contextid($context), $context->get_parent_context()->id);
2326 $children = get_child_contexts($systemcontext);
2327 $this->resetDebugging();
2328 $this->assertEquals(count($children), $DB->count_records('context')-1);
2329 unset($children);
2331 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
2332 create_contexts();
2333 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK)));
2335 $DB->set_field('context', 'depth', 0, array('contextlevel'=>CONTEXT_BLOCK));
2336 build_context_path();
2337 $this->assertFalse($DB->record_exists('context', array('depth'=>0)));
2339 $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
2340 $DB->delete_records('course', array('id'=>$lastcourse));
2341 $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
2342 $DB->delete_records('course_categories', array('id'=>$lastcategory));
2343 $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
2344 $DB->delete_records('user', array('id'=>$lastuser));
2345 $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
2346 $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
2347 cleanup_contexts();
2348 $count = 1; //system
2349 $count += $DB->count_records('user', array('deleted'=>0));
2350 $count += $DB->count_records('course_categories');
2351 $count += $DB->count_records('course');
2352 $count += $DB->count_records('course_modules');
2353 $count += $DB->count_records('block_instances');
2354 $this->assertEquals($DB->count_records('context'), $count);
2356 context_helper::reset_caches();
2357 preload_course_contexts($SITE->id);
2358 $this->assertEquals(1 + $DB->count_records('course_modules', array('course' => $SITE->id)),
2359 context_inspection::test_context_cache_size());
2361 context_helper::reset_caches();
2362 list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx');
2363 $sql = "SELECT c.id $select FROM {course_categories} c $join";
2364 $records = $DB->get_records_sql($sql);
2365 foreach ($records as $record) {
2366 context_instance_preload($record);
2367 $record = (array)$record;
2368 $this->assertEquals(1, count($record)); // only id left
2370 $this->assertEquals(count($records), context_inspection::test_context_cache_size());
2372 accesslib_clear_all_caches(true);
2373 $DB->delete_records('cache_flags', array());
2374 mark_context_dirty($systemcontext->path);
2375 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2376 $this->assertTrue(isset($dirty[$systemcontext->path]));
2378 accesslib_clear_all_caches(false);
2379 $DB->delete_records('cache_flags', array());
2380 $course = $DB->get_record('course', array('id'=>$testcourses[2]));
2381 $context = context_course::instance($course->id);
2382 $oldpath = $context->path;
2383 $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
2384 $categorycontext = context_coursecat::instance($miscid);
2385 $course->category = $miscid;
2386 $DB->update_record('course', $course);
2387 context_moved($context, $categorycontext);
2388 $context = context_course::instance($course->id);
2389 $this->assertEquals($context->get_parent_context(), $categorycontext);
2391 $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
2392 delete_context(CONTEXT_COURSE, $testcourses[2]);
2393 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
2395 $name = get_contextlevel_name(CONTEXT_COURSE);
2396 $this->assertFalse(empty($name));
2398 $context = context_course::instance($testcourses[2]);
2399 $name = print_context_name($context);
2400 $this->assertFalse(empty($name));
2402 $url = get_context_url($coursecontext);
2403 $this->assertFalse($url instanceof modole_url);
2405 $pagecm = get_coursemodule_from_instance('page', $testpages[7]);
2406 $context = context_module::instance($pagecm->id);
2407 $coursecontext = get_course_context($context);
2408 $this->assertEquals($coursecontext->contextlevel, CONTEXT_COURSE);
2409 $this->assertEquals(get_courseid_from_context($context), $pagecm->course);
2411 $caps = fetch_context_capabilities($systemcontext);
2412 $this->assertTrue(is_array($caps));
2413 unset($caps);
2417 * Test updating of role capabilities during upgrade
2418 * @return void
2420 public function test_update_capabilities() {
2421 global $DB, $SITE;
2423 $this->resetAfterTest(true);
2425 $froncontext = context_course::instance($SITE->id);
2426 $student = $DB->get_record('role', array('archetype'=>'student'));
2427 $teacher = $DB->get_record('role', array('archetype'=>'teacher'));
2429 $existingcaps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
2431 $this->assertFalse(isset($existingcaps['moodle/site:restore'])); // moved to new 'moodle/restore:restorecourse'
2432 $this->assertTrue(isset($existingcaps['moodle/restore:restorecourse'])); // new cap from 'moodle/site:restore'
2433 $this->assertTrue(isset($existingcaps['moodle/site:sendmessage'])); // new capability
2434 $this->assertTrue(isset($existingcaps['moodle/backup:backupcourse']));
2435 $this->assertTrue(isset($existingcaps['moodle/backup:backupsection'])); // cloned from 'moodle/backup:backupcourse'
2436 $this->assertTrue(isset($existingcaps['moodle/site:approvecourse'])); // updated bitmask
2437 $this->assertTrue(isset($existingcaps['moodle/course:manageactivities']));
2438 $this->assertTrue(isset($existingcaps['mod/page:addinstance'])); // cloned from core 'moodle/course:manageactivities'
2440 // fake state before upgrade
2441 $DB->set_field('capabilities', 'name', 'moodle/site:restore', array('name'=>'moodle/restore:restorecourse'));
2442 $DB->set_field('role_capabilities', 'capability', 'moodle/site:restore', array('capability'=>'moodle/restore:restorecourse'));
2443 assign_capability('moodle/site:restore', CAP_PROHIBIT, $teacher->id, $froncontext->id, true);
2444 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/site:restore', 'roleid'=>$teacher->id), 'contextid, permission', 'contextid, permission'));
2446 $DB->delete_records('role_capabilities', array('capability'=>'moodle/site:sendmessage'));
2447 $DB->delete_records('capabilities', array('name'=>'moodle/site:sendmessage'));
2449 $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupsection'));
2450 $DB->delete_records('capabilities', array('name'=>'moodle/backup:backupsection'));
2451 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $froncontext->id, true);
2452 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $teacher->id, $froncontext->id, true);
2454 $DB->set_field('capabilities', 'riskbitmask', 0, array('name'=>'moodle/site:approvecourse'));
2456 $DB->delete_records('role_capabilities', array('capability'=>'mod/page:addinstance'));
2457 $DB->delete_records('capabilities', array('name'=>'mod/page:addinstance'));
2458 assign_capability('moodle/course:manageactivities', CAP_PROHIBIT, $student->id, $froncontext->id, true);
2459 assign_capability('moodle/course:manageactivities', CAP_ALLOW, $teacher->id, $froncontext->id, true);
2461 // execute core
2462 update_capabilities('moodle');
2464 // only core should be upgraded
2465 $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
2467 $this->assertFalse(isset($existingcaps['moodle/site:restore']));
2468 $this->assertTrue(isset($caps['moodle/restore:restorecourse']));
2469 $this->assertEquals($existingcaps['moodle/restore:restorecourse'], $caps['moodle/restore:restorecourse']);
2470 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/restore:restorecourse', 'roleid'=>$teacher->id), 'contextid, permission', 'contextid, permission'));
2471 $this->assertEquals($perms1, $perms2);
2473 $this->assertTrue(isset($caps['moodle/site:sendmessage']));
2474 $this->assertEquals($existingcaps['moodle/site:sendmessage'], $caps['moodle/site:sendmessage']);
2476 $this->assertTrue(isset($caps['moodle/backup:backupsection']));
2477 $this->assertEquals($existingcaps['moodle/backup:backupsection'], $caps['moodle/backup:backupsection']);
2478 $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/backup:backupcourse', 'moodle/backup:backupsection'));
2479 foreach ($roles as $role) {
2480 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2481 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupsection', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2482 $this->assertEquals($perms1, $perms2);
2485 $this->assertTrue(isset($caps['moodle/site:approvecourse']));
2486 $this->assertEquals($existingcaps['moodle/site:approvecourse'], $caps['moodle/site:approvecourse']);
2488 $this->assertFalse(isset($caps['mod/page:addinstance']));
2490 // execute plugin
2491 update_capabilities('mod_page');
2492 $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
2493 $this->assertTrue(isset($caps['mod/page:addinstance']));
2494 $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/course:manageactivities', 'mod/page:addinstance'));
2495 foreach ($roles as $role) {
2496 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/course:manageactivities', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2497 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'mod/page:addinstance', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2499 $this->assertEquals($perms1, $perms2);