Merge branch 'MDL-36646_23' of git://github.com/timhunt/moodle into MOODLE_23_STABLE
[moodle.git] / lib / tests / accesslib_test.php
CommitLineData
a3d5830a
PS
1<?php
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
17/**
18 * Full functional accesslib test
19 *
a3d5830a
PS
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
24 */
25
26defined('MOODLE_INTERNAL') || die();
27
28
29/**
30 * Context caching fixture
31 */
32class context_inspection extends context_helper {
33 public static function test_context_cache_size() {
34 return self::$cache_count;
35 }
36}
37
38
39/**
40 * Functional test for accesslib.php
41 *
42 * Note: execution may take many minutes especially on slower servers.
43 */
44class accesslib_testcase extends advanced_testcase {
45
dfa6a346 46 //TODO: add more tests for the remaining accesslib parts such as enrol related api
a3d5830a
PS
47
48 /**
49 * Verify comparison of context instances in phpunit asserts
50 * @return void
51 */
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);
57
58 $user1 = context_user::instance(1);
59 $user2 = context_user::instance(2);
60 $this->assertNotEquals($user1, $user2);
61 }
62
63 /**
dfa6a346
PS
64 * Test resetting works.
65 */
66 public function test_accesslib_clear_all_caches() {
67 global $ACCESSLIB_PRIVATE;
68
69 $this->resetAfterTest();
70
71 $this->setAdminUser();
72 load_all_capabilities();
73
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);
82 }
83
84 /**
85 * Test getting of role access
86 * @return void
87 */
88 public function test_get_role_access() {
89 global $DB;
90
91 $roles = $DB->get_records('role');
92 foreach ($roles as $role) {
93 $access = get_role_access($role->id);
94
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']));
102 }
103
104 // Note: the data is validated in the functional permission evaluation test at the end of this testcase.
105 }
106
107 /**
108 * Test getting of guest role.
109 * @return void
110 */
111 public function test_get_guest_role() {
112 global $CFG;
113
114 $guest = get_guest_role();
115 $this->assertEquals('guest', $guest->archetype);
116 $this->assertEquals('guest', $guest->shortname);
117
118 $this->assertEquals($CFG->guestroleid, $guest->id);
119 }
120
121 /**
122 * Test if user is admin.
123 * @return void
124 */
125 public function test_is_siteadmin() {
126 global $DB;
127
128 $this->resetAfterTest();
129
130 $users = $DB->get_records('user');
131
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));
146 }
147 }
148 }
149
770cee96
ARN
150 /**
151 * Test if user is enrolled in a course
152 * @return void
153 */
154 public function test_is_enrolled() {
155 global $DB;
156
157 // Generate data
158 $user = $this->getDataGenerator()->create_user();
159 $course = $this->getDataGenerator()->create_course();
160 $coursecontext = context_course::instance($course->id);
161 $role = $DB->get_record('role', array('shortname'=>'student'));
162
163 // There should be a manual enrolment as part of the default install
164 $plugin = enrol_get_plugin('manual');
165 $instance = $DB->get_record('enrol', array(
166 'courseid' => $course->id,
167 'enrol' => 'manual',
168 ));
169 $this->assertNotEquals($instance, false);
170
171 // Enrol the user in the course
172 $plugin->enrol_user($instance, $user->id, $role->id);
173
174 // We'll test with the mod/assign:submit capability
175 $capability= 'mod/assign:submit';
176 $this->assertTrue($DB->record_exists('capabilities', array('name' => $capability)));
177
178 // Switch to our user
179 $this->setUser($user);
180
181 // Ensure that the user has the capability first
182 $this->assertTrue(has_capability($capability, $coursecontext, $user->id));
183
184 // We first test whether the user is enrolled on the course as this
185 // seeds the cache, then we test for the capability
186 $this->assertTrue(is_enrolled($coursecontext, $user, '', true));
187 $this->assertTrue(is_enrolled($coursecontext, $user, $capability));
188
189 // Prevent the capability for this user role
190 assign_capability($capability, CAP_PROHIBIT, $role->id, $coursecontext);
191 $coursecontext->mark_dirty();
192 $this->assertFalse(has_capability($capability, $coursecontext, $user->id));
193
194 // Again, we seed the cache first by checking initial enrolment,
195 // and then we test the actual capability
196 $this->assertTrue(is_enrolled($coursecontext, $user, '', true));
197 $this->assertFalse(is_enrolled($coursecontext, $user, $capability));
198
199 // We need variable states to be reset for the next test
200 $this->resetAfterTest(true);
201 }
202
dfa6a346
PS
203 /**
204 * Test logged in test.
205 * @return void
206 */
207 public function test_isloggedin() {
208 global $USER;
209
210 $this->resetAfterTest();
211
212 $USER->id = 0;
213 $this->assertFalse(isloggedin());
214 $USER->id = 1;
215 $this->assertTrue(isloggedin());
216 }
217
218 /**
219 * Test guest user test.
220 * @return void
221 */
222 public function test_isguestuser() {
223 global $DB;
224
225 $this->resetAfterTest();
226
227 $guest = $DB->get_record('user', array('username'=>'guest'));
228 $this->setUser(0);
229 $this->assertFalse(isguestuser());
230 $this->setAdminUser();
231 $this->assertFalse(isguestuser());
232 $this->assertTrue(isguestuser($guest));
233 $this->assertTrue(isguestuser($guest->id));
234 $this->setUser($guest);
235 $this->assertTrue(isguestuser());
236
237 $users = $DB->get_records('user');
238 foreach ($users as $user) {
239 if ($user->username === 'guest') {
240 continue;
241 }
242 $this->assertFalse(isguestuser($user));
243 }
244 }
245
246 /**
247 * Test capability riskiness.
248 * @return void
249 */
250 public function test_is_safe_capability() {
251 global $DB;
252 // Note: there is not much to test, just make sure no notices are throw for the most dangerous cap.
253 $capability = $DB->get_record('capabilities', array('name'=>'moodle/site:config'), '*', MUST_EXIST);
254 $this->assertFalse(is_safe_capability($capability));
255 }
256
257 /**
258 * Test context fetching.
259 * @return void
260 */
261 public function test_get_context_info_array() {
262 $this->resetAfterTest();
263
264 $syscontext = context_system::instance();
265 $user = $this->getDataGenerator()->create_user();
266 $usercontext = context_user::instance($user->id);
267 $course = $this->getDataGenerator()->create_course();
268 $catcontext = context_coursecat::instance($course->category);
269 $coursecontext = context_course::instance($course->id);
270 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
271 $modcontext = context_module::instance($page->cmid);
272 $cm = get_coursemodule_from_instance('page', $page->id);
273 $block1 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$coursecontext->id));
274 $block1context = context_block::instance($block1->id);
275 $block2 = $this->getDataGenerator()->create_block('online_users', array('parentcontextid'=>$modcontext->id));
276 $block2context = context_block::instance($block2->id);
277
278 $result = get_context_info_array($syscontext->id);
279 $this->assertCount(3, $result);
280 $this->assertSame($syscontext, $result[0]);
281 $this->assertSame(null, $result[1]);
282 $this->assertSame(null, $result[2]);
283
284 $result = get_context_info_array($usercontext->id);
285 $this->assertCount(3, $result);
286 $this->assertSame($usercontext, $result[0]);
287 $this->assertSame(null, $result[1]);
288 $this->assertSame(null, $result[2]);
289
290 $result = get_context_info_array($catcontext->id);
291 $this->assertCount(3, $result);
292 $this->assertSame($catcontext, $result[0]);
293 $this->assertSame(null, $result[1]);
294 $this->assertSame(null, $result[2]);
295
296 $result = get_context_info_array($coursecontext->id);
297 $this->assertCount(3, $result);
298 $this->assertSame($coursecontext, $result[0]);
299 $this->assertEquals($course->id, $result[1]->id);
300 $this->assertEquals($course->shortname, $result[1]->shortname);
301 $this->assertSame(null, $result[2]);
302
303 $result = get_context_info_array($block1context->id);
304 $this->assertCount(3, $result);
305 $this->assertSame($block1context, $result[0]);
306 $this->assertEquals($course->id, $result[1]->id);
307 $this->assertEquals($course->shortname, $result[1]->shortname);
308 $this->assertSame(null, $result[2]);
309
310 $result = get_context_info_array($modcontext->id);
311 $this->assertCount(3, $result);
312 $this->assertSame($modcontext, $result[0]);
313 $this->assertEquals($course->id, $result[1]->id);
314 $this->assertEquals($course->shortname, $result[1]->shortname);
315 $this->assertEquals($cm->id, $result[2]->id);
316 $this->assertEquals($cm->groupmembersonly, $result[2]->groupmembersonly);
317
318 $result = get_context_info_array($block2context->id);
319 $this->assertCount(3, $result);
320 $this->assertSame($block2context, $result[0]);
321 $this->assertEquals($course->id, $result[1]->id);
322 $this->assertEquals($course->shortname, $result[1]->shortname);
323 $this->assertEquals($cm->id, $result[2]->id);
324 $this->assertEquals($cm->groupmembersonly, $result[2]->groupmembersonly);
325 }
326
327 /**
328 * Test looking for course contacts.
329 * @return void
330 */
331 public function test_has_coursecontact_role() {
332 global $DB, $CFG;
333
334 $this->resetAfterTest();
335
336 $users = $DB->get_records('user');
337
338 // Nobody is expected to have any course level roles.
339 $this->assertNotEmpty($CFG->coursecontact);
340 foreach($users as $user) {
341 $this->assertFalse(has_coursecontact_role($user->id));
342 }
343
344 $user = $this->getDataGenerator()->create_user();
345 $course = $this->getDataGenerator()->create_course();
346 role_assign($CFG->coursecontact, $user->id, context_course::instance($course->id));
347 $this->assertTrue(has_coursecontact_role($user->id));
348 }
349
350 /**
351 * Test creation of roles.
352 * @return void
353 */
354 public function test_create_role() {
355 global $DB;
356
357 $this->resetAfterTest();
358
359 $id = create_role('New student role', 'student2', 'New student description', 'student');
360 $role = $DB->get_record('role', array('id'=>$id));
361
362 $this->assertNotEmpty($role);
363 $this->assertEquals('New student role', $role->name);
364 $this->assertEquals('student2', $role->shortname);
365 $this->assertEquals('New student description', $role->description);
366 $this->assertEquals('student', $role->archetype);
367 }
368
369 /**
370 * Test adding of capabilities to roles.
371 */
372 public function test_assign_capability() {
373 global $DB;
374
375 $this->resetAfterTest();
376
377 $user = $this->getDataGenerator()->create_user();
378 $syscontext = context_system::instance();
379 $frontcontext = context_course::instance(SITEID);
380 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
381 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability assigned to student by default
382 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')));
383 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse')));
384
385 $this->setUser($user);
386 $result = assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $student->id, $frontcontext->id);
387 $this->assertTrue($result);
388 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
389 $this->assertNotEmpty($permission);
390 $this->assertEquals(CAP_ALLOW, $permission->permission);
391 $this->assertEquals($user->id, $permission->modifierid);
392
393 $this->setUser(0);
394 $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $frontcontext->id, false);
395 $this->assertTrue($result);
396 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
397 $this->assertNotEmpty($permission);
398 $this->assertEquals(CAP_ALLOW, $permission->permission);
399 $this->assertEquals(3, $permission->modifierid);
400
401 $result = assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $frontcontext->id, true);
402 $this->assertTrue($result);
403 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
404 $this->assertNotEmpty($permission);
405 $this->assertEquals(CAP_PROHIBIT, $permission->permission);
406 $this->assertEquals(0, $permission->modifierid);
407
408 $result = assign_capability('moodle/backup:backupcourse', CAP_INHERIT, $student->id, $frontcontext->id);
409 $this->assertTrue($result);
410 $permission = $DB->get_record('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$student->id, 'capability'=>'moodle/backup:backupcourse'));
411 $this->assertEmpty($permission);
412 }
413
414 /**
415 * Test removing of capabilities from roles.
416 */
417 public function test_unassign_capability() {
418 global $DB;
419
420 $this->resetAfterTest();
421
422 $syscontext = context_system::instance();
423 $frontcontext = context_course::instance(SITEID);
424 $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
425 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability assigned to manager by default
426 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $frontcontext->id);
427
428 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
429 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
430
431 $result = unassign_capability('moodle/backup:backupcourse', $manager->id, $syscontext->id);
432 $this->assertTrue($result);
433 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
434 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
435 unassign_capability('moodle/backup:backupcourse', $manager->id, $frontcontext);
436 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
437
438 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $syscontext->id);
439 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $frontcontext->id);
440 $this->assertTrue($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
441
442 $result = unassign_capability('moodle/backup:backupcourse', $manager->id);
443 $this->assertTrue($result);
444 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$syscontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
445 $this->assertFalse($DB->record_exists('role_capabilities', array('contextid'=>$frontcontext->id, 'roleid'=>$manager->id, 'capability'=>'moodle/backup:backupcourse')));
446 }
447
448 /**
449 * Test role assigning
450 */
451 public function test_role_assign() {
452 global $DB, $USER;
453
454 $this->resetAfterTest();
455
456 $user = $this->getDataGenerator()->create_user();
457 $course = $this->getDataGenerator()->create_course();
458 $role = $DB->get_record('role', array('shortname'=>'student'));
459
460 $this->setUser(0);
461 $context = context_system::instance();
462 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
463 role_assign($role->id, $user->id, $context->id);
464 $ras = $DB->get_record('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id));
465 $this->assertNotEmpty($ras);
466 $this->assertSame('', $ras->component);
467 $this->assertSame('0', $ras->itemid);
468 $this->assertEquals($USER->id, $ras->modifierid);
469
470 $this->setAdminUser();
471 $context = context_course::instance($course->id);
472 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
473 role_assign($role->id, $user->id, $context->id, 'enrol_self', 1, 666);
474 $ras = $DB->get_record('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id));
475 $this->assertNotEmpty($ras);
476 $this->assertSame('enrol_self', $ras->component);
477 $this->assertSame('1', $ras->itemid);
478 $this->assertEquals($USER->id, $ras->modifierid);
479 $this->assertEquals(666, $ras->timemodified);
480 }
481
482 /**
483 * Test role unassigning
484 * @return void
485 */
486 public function test_role_unassign() {
487 global $DB;
488
489 $this->resetAfterTest();
490
491 $user = $this->getDataGenerator()->create_user();
492 $course = $this->getDataGenerator()->create_course();
493 $role = $DB->get_record('role', array('shortname'=>'student'));
494
495 $context = context_system::instance();
496 role_assign($role->id, $user->id, $context->id);
497 $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
498 role_unassign($role->id, $user->id, $context->id);
499 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
500
501 role_assign($role->id, $user->id, $context->id, 'enrol_self', 1);
502 $this->assertTrue($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
503 role_unassign($role->id, $user->id, $context->id, 'enrol_self', 1);
504 $this->assertFalse($DB->record_exists('role_assignments', array('userid'=>$user->id, 'roleid'=>$role->id, 'contextid'=>$context->id)));
505 }
506
507 /**
508 * Test role unassigning
509 * @return void
510 */
511 public function test_role_unassign_all() {
512 global $DB;
513
514 $this->resetAfterTest();
515
516 $user = $this->getDataGenerator()->create_user();
517 $course = $this->getDataGenerator()->create_course();
518 $role = $DB->get_record('role', array('shortname'=>'student'));
519 $syscontext = context_system::instance();
520 $coursecontext = context_course::instance($course->id);
521 $page = $this->getDataGenerator()->create_module('page', array('course'=>$course->id));
522 $modcontext = context_module::instance($page->cmid);
523
524 role_assign($role->id, $user->id, $syscontext->id);
525 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
526 $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id)));
527 role_unassign_all(array('userid'=>$user->id, 'roleid'=>$role->id));
528 $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id)));
529
530 role_assign($role->id, $user->id, $syscontext->id);
531 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
532 role_assign($role->id, $user->id, $modcontext->id);
533 $this->assertEquals(3, $DB->count_records('role_assignments', array('userid'=>$user->id)));
534 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id), false);
535 $this->assertEquals(2, $DB->count_records('role_assignments', array('userid'=>$user->id)));
536 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id), true);
537 $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id)));
538 role_unassign_all(array('userid'=>$user->id));
539 $this->assertEquals(0, $DB->count_records('role_assignments', array('userid'=>$user->id)));
540
541 role_assign($role->id, $user->id, $syscontext->id);
542 role_assign($role->id, $user->id, $coursecontext->id, 'enrol_self', 1);
543 role_assign($role->id, $user->id, $coursecontext->id);
544 role_assign($role->id, $user->id, $modcontext->id);
545 $this->assertEquals(4, $DB->count_records('role_assignments', array('userid'=>$user->id)));
546 role_unassign_all(array('userid'=>$user->id, 'contextid'=>$coursecontext->id, 'component'=>'enrol_self'), true, true);
547 $this->assertEquals(1, $DB->count_records('role_assignments', array('userid'=>$user->id)));
548 }
549
550 /**
551 * Test role queries.
552 * @return void
553 */
554 public function test_get_roles_with_capability() {
555 global $DB;
556
557 $this->resetAfterTest();
558
559 $syscontext = context_system::instance();
560 $frontcontext = context_course::instance(SITEID);
561 $manager = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
562 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
563
564 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability is ok
565 $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse'));
566
567 $roles = get_roles_with_capability('moodle/backup:backupcourse');
568 $this->assertEquals(array(), $roles);
569
570 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $manager->id, $syscontext->id);
571 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $manager->id, $frontcontext->id);
572 assign_capability('moodle/backup:backupcourse', CAP_PREVENT, $teacher->id, $frontcontext->id);
573
574 $roles = get_roles_with_capability('moodle/backup:backupcourse');
575 $this->assertEquals(array($teacher->id, $manager->id), array_keys($roles), '', 0, 10, true);
576
577 $roles = get_roles_with_capability('moodle/backup:backupcourse', CAP_ALLOW);
578 $this->assertEquals(array($manager->id), array_keys($roles), '', 0, 10, true);
579
580 $roles = get_roles_with_capability('moodle/backup:backupcourse', NULL, $syscontext);
581 $this->assertEquals(array($manager->id), array_keys($roles), '', 0, 10, true);
582 }
583
584 /**
585 * Test deleting of roles.
586 * @return void
587 */
588 public function test_delete_role() {
589 global $DB;
590
591 $this->resetAfterTest();
592
593 $role = $DB->get_record('role', array('shortname'=>'manager'), '*', MUST_EXIST);
594 $user = $this->getDataGenerator()->create_user();
595 role_assign($role->id, $user->id, context_system::instance());
596 $course = $this->getDataGenerator()->create_course();
597 $rolename = (object)array('roleid'=>$role->id, 'name'=>'Man', 'contextid'=>context_course::instance($course->id)->id);
598 $DB->insert_record('role_names', $rolename);
599
600 $this->assertTrue($DB->record_exists('role_assignments', array('roleid'=>$role->id)));
601 $this->assertTrue($DB->record_exists('role_capabilities', array('roleid'=>$role->id)));
602 $this->assertTrue($DB->record_exists('role_names', array('roleid'=>$role->id)));
603 $this->assertTrue($DB->record_exists('role_context_levels', array('roleid'=>$role->id)));
604 $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$role->id)));
605 $this->assertTrue($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id)));
606 $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$role->id)));
607 $this->assertTrue($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id)));
608
609 $result = delete_role($role->id);
610 $this->assertTrue($result);
611 $this->assertFalse($DB->record_exists('role', array('id'=>$role->id)));
612 $this->assertFalse($DB->record_exists('role_assignments', array('roleid'=>$role->id)));
613 $this->assertFalse($DB->record_exists('role_capabilities', array('roleid'=>$role->id)));
614 $this->assertFalse($DB->record_exists('role_names', array('roleid'=>$role->id)));
615 $this->assertFalse($DB->record_exists('role_context_levels', array('roleid'=>$role->id)));
616 $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$role->id)));
617 $this->assertFalse($DB->record_exists('role_allow_assign', array('allowassign'=>$role->id)));
618 $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$role->id)));
619 $this->assertFalse($DB->record_exists('role_allow_override', array('allowoverride'=>$role->id)));
620 }
621
622 /**
623 * Test fetching of all roles.
624 * @return void
625 */
626 public function test_get_all_roles() {
627 $allroles = get_all_roles();
628 $this->assertEquals('array', gettype($allroles));
629 $this->assertCount(8, $allroles); // there are 8 roles is standard install
630
631 $role = reset($allroles);
632 $role = (array)$role;
633
634 $this->assertEquals(array('id', 'name', 'shortname', 'description', 'sortorder', 'archetype'), array_keys($role), '', 0, 10, true);
635
636 foreach($allroles as $roleid => $role) {
637 $this->assertEquals($role->id, $roleid);
638 }
639 }
640
641 /**
642 * Test getting of all archetypes.
643 * @return void
644 */
645 public function test_get_role_archetypes() {
646 $archetypes = get_role_archetypes();
647 $this->assertCount(8, $archetypes); // there are 8 archetypes in standard install
648 foreach ($archetypes as $k=>$v) {
649 $this->assertSame($k, $v);
650 }
651 }
652
653 /**
654 * Test getting of roles with given archetype.
655 * @return void
656 */
657 public function test_get_archetype_roles() {
658 $this->resetAfterTest();
659
660 // New install should have 1 role for each archetype.
661 $archetypes = get_role_archetypes();
662 foreach ($archetypes as $archetype) {
663 $roles = get_archetype_roles($archetype);
664 $this->assertCount(1, $roles);
665 $role = reset($roles);
666 $this->assertEquals($archetype, $role->archetype);
667 }
668
669 create_role('New student role', 'student2', 'New student description', 'student');
670 $roles = get_archetype_roles('student');
671 $this->assertCount(2, $roles);
672 }
673
674 /**
675 * Test aliased role names
676 * @return void
677 */
678 public function test_role_get_name() {
679 global $DB;
680
681 $this->resetAfterTest();
682
683 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
684 $allroles = $DB->get_records('role');
685 $course = $this->getDataGenerator()->create_course();
686 $coursecontext = context_course::instance($course->id);
687
688 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
689 $DB->insert_record('role_names', $teacherename);
690
691 foreach ($allroles as $role) {
692 $this->assertNotEmpty(role_get_name($role, $coursecontext));
693 if ($role->id == $teacher->id) {
694 $this->assertSame($teacherename->name, role_get_name($role, $coursecontext));
695 }
696 }
697 }
698
699 /**
700 * Test tweaking of role name arrays
a3d5830a
PS
701 * @return void
702 */
dfa6a346
PS
703 public function test_role_fix_names() {
704 global $DB;
705
706 $this->resetAfterTest();
707
708 $teacher = $DB->get_record('role', array('shortname'=>'teacher'), '*', MUST_EXIST);
709 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
710 $otherid = create_role('Other role', 'other', 'Some other role', '');
711 $anotherid = create_role('Another role', 'another', 'Yet another other role', '');
712 $allroles = $DB->get_records('role');
713
714 $syscontext = context_system::instance();
715 $frontcontext = context_course::instance(SITEID);
716 $course = $this->getDataGenerator()->create_course();
717 $coursecontext = context_course::instance($course->id);
718 $category = $DB->get_record('course_categories', array('id'=>$course->category), '*', MUST_EXIST);
719 $categorycontext = context_coursecat::instance($category->id);
720
721 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
722 $DB->insert_record('role_names', $teacherename);
723 $otherrename = (object)array('roleid'=>$otherid, 'name'=>'Ostatní', 'contextid'=>$coursecontext->id);
724 $DB->insert_record('role_names', $otherrename);
725 $renames = $DB->get_records_menu('role_names', array('contextid'=>$coursecontext->id), '', 'roleid,name');
726
727 // Make sure all localname contain proper values for each ROLENAME_ constant,
728 // note role_get_name() on frontpage is used to get the original name for future comatibility.
729 $roles = $allroles;
730 unset($roles[$student->id]); // Remove one roel to make sure no role is added or removed.
731 $rolenames = array();
732 foreach ($roles as $role) {
733 $rolenames[$role->id] = $role->name;
734 }
735
736 /* TODO: unsupported! MDL-8249
737 $fixed = role_fix_names($roles, $coursecontext, ROLENAME_SHORT);
738 $this->assertCount(count($roles), $fixed);
739 foreach($fixed as $rolename) {
740 $this->assertInstanceOf('stdClass', $rolename);
741 $role = $roles[$rolename->id];
742 $this->assertSame($role->shortname, $rolename->localname);
743 }
744 */
745
746 /* TODO: unsupported! MDL-8249
747 $fixed = role_fix_names($roles, $coursecontext, ROLENAME_ORIGINALANDSHORT);
748 $this->assertCount(count($roles), $fixed);
749 foreach($fixed as $rolename) {
750 $this->assertInstanceOf('stdClass', $rolename);
751 $role = $roles[$rolename->id];
752 $this->assertSame("$role->name ($role->shortname)", $rolename->localname);
753 }
754 */
755
756 $fixed = role_fix_names($roles, $coursecontext, ROLENAME_ORIGINAL);
757 $this->assertCount(count($roles), $fixed);
758 foreach($fixed as $roleid=>$rolename) {
759 $this->assertInstanceOf('stdClass', $rolename);
760 $role = $roles[$roleid];
761 $name = role_get_name($role, $frontcontext);
762 $this->assertSame($name, $rolename->localname);
763 }
764 $fixed = role_fix_names($rolenames, $coursecontext, ROLENAME_ORIGINAL);
765 $this->assertCount(count($rolenames), $fixed);
766 foreach($fixed as $roleid=>$rolename) {
767 $role = $roles[$roleid];
768 $name = role_get_name($role, $frontcontext);
769 $this->assertSame($name, $rolename);
770 }
771
772 $fixed = role_fix_names($roles, $coursecontext, ROLENAME_ALIAS);
773 $this->assertCount(count($roles), $fixed);
774 foreach($fixed as $roleid=>$rolename) {
775 $this->assertInstanceOf('stdClass', $rolename);
776 $role = $roles[$roleid];
777 $this->assertSame(role_get_name($role, $coursecontext), $rolename->localname);
778 }
779 $fixed = role_fix_names($rolenames, $coursecontext, ROLENAME_ALIAS);
780 $this->assertCount(count($rolenames), $fixed);
781 foreach($fixed as $roleid=>$rolename) {
782 $role = $roles[$roleid];
783 $this->assertSame(role_get_name($role, $coursecontext), $rolename);
784 }
785
786 /* TODO: buggy! MDL-8249
787 $fixed = role_fix_names($roles, $coursecontext, ROLENAME_BOTH);
788 $this->assertCount(count($roles), $fixed);
789 foreach($fixed as $roleid=>$rolename) {
790 $this->assertInstanceOf('stdClass', $rolename);
791 $role = $roles[$roleid];
792 $name = role_get_name($role, $frontcontext);
793 if (isset($renames[$roleid])) {
794 $this->assertSame("$renames[$roleid] ($name)", $rolename->localname);
795 } else {
796 $this->assertSame(role_get_name($role, $coursecontext), $rolename->localname);
797 }
798 }
799 */
800 $fixed = role_fix_names($rolenames, $coursecontext, ROLENAME_BOTH);
801 $this->assertCount(count($rolenames), $fixed);
802 foreach($fixed as $roleid=>$rolename) {
803 $role = $roles[$roleid];
804 if (isset($renames[$roleid])) {
805 $name = role_get_name($role, $frontcontext);
806 $this->assertSame("$renames[$roleid] ($name)", $rolename);
807 } else {
808 $this->assertSame(role_get_name($role, $coursecontext), $rolename);
809 }
810 }
811
812 $fixed = role_fix_names($roles, $coursecontext, ROLENAME_ALIAS_RAW);
813 $this->assertCount(count($roles), $fixed);
814 foreach($fixed as $roleid=>$rolename) {
815 $this->assertInstanceOf('stdClass', $rolename);
816 if (isset($renames[$roleid])) {
817 $this->assertSame($renames[$roleid], $rolename->localname);
818 } else {
819 $this->assertSame('', $rolename->localname);
820 }
821 }
822 $fixed = role_fix_names($rolenames, $coursecontext, ROLENAME_ALIAS_RAW);
823 $this->assertCount(count($rolenames), $fixed);
824 foreach($fixed as $roleid=>$rolename) {
825 if (isset($renames[$roleid])) {
826 $this->assertSame($renames[$roleid], $rolename);
827 } else {
828 $this->assertSame('', $rolename);
829 }
830 }
831 }
832
833 /**
834 * Test allowing of role assignments.
835 * @return void
836 */
837 public function test_allow_assign() {
838 global $DB;
839
840 $this->resetAfterTest();
841
842 $otherid = create_role('Other role', 'other', 'Some other role', '');
843 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
844
845 $this->assertFalse($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id)));
846 allow_assign($otherid, $student->id);
847 $this->assertTrue($DB->record_exists('role_allow_assign', array('roleid'=>$otherid, 'allowassign'=>$student->id)));
848 }
849
850 /**
851 * Test allowing of role overrides.
852 * @return void
853 */
854 public function test_allow_override() {
855 global $DB;
856
857 $this->resetAfterTest();
858
859 $otherid = create_role('Other role', 'other', 'Some other role', '');
860 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
861
862 $this->assertFalse($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id)));
863 allow_override($otherid, $student->id);
864 $this->assertTrue($DB->record_exists('role_allow_override', array('roleid'=>$otherid, 'allowoverride'=>$student->id)));
865 }
866
867 /**
868 * Test allowing of role switching.
869 * @return void
870 */
871 public function test_allow_switch() {
872 global $DB;
873
874 $this->resetAfterTest();
875
876 $otherid = create_role('Other role', 'other', 'Some other role', '');
877 $student = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
878
879 $this->assertFalse($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id)));
880 allow_switch($otherid, $student->id);
881 $this->assertTrue($DB->record_exists('role_allow_switch', array('roleid'=>$otherid, 'allowswitch'=>$student->id)));
882 }
883
884 /**
885 * Test returning of assignable roles in context.
886 * @return void
887 */
888 public function test_get_assignable_roles() {
889 global $DB;
890
891 $this->resetAfterTest();
892
893 $course = $this->getDataGenerator()->create_course();
894 $coursecontext = context_course::instance($course->id);
895
896 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
897 $teacher = $this->getDataGenerator()->create_user();
898 role_assign($teacherrole->id, $teacher->id, $coursecontext);
899 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
900 $DB->insert_record('role_names', $teacherename);
901
902 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
903 $student = $this->getDataGenerator()->create_user();
904 role_assign($studentrole->id, $student->id, $coursecontext);
905
906 $contexts = $DB->get_records('context');
907 $users = $DB->get_records('user');
908 $allroles = $DB->get_records('role');
909
910 // Evaluate all results for all users in all contexts.
911 foreach($users as $user) {
912 $this->setUser($user);
913 foreach ($contexts as $contextid=>$unused) {
914 $context = context_helper::instance_by_id($contextid);
915 $roles = get_assignable_roles($context, ROLENAME_SHORT);
916 foreach ($allroles as $roleid=>$role) {
917 if (isset($roles[$roleid])) {
918 if (is_siteadmin()) {
919 $this->assertTrue($DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel, 'roleid'=>$roleid)));
920 } else {
921 $this->assertTrue(user_can_assign($context, $roleid), "u:$user->id r:$roleid");
922 }
923 $this->assertEquals($role->shortname, $roles[$roleid]);
924 } else {
925 $allowed = $DB->record_exists('role_context_levels', array('contextlevel'=>$context->contextlevel, 'roleid'=>$roleid));
926 if (is_siteadmin()) {
927 $this->assertFalse($allowed);
928 } else {
929 $this->assertFalse($allowed and user_can_assign($context, $roleid), "u:$user->id, r:{$allroles[$roleid]->name}, c:$context->contextlevel");
930 }
931 }
932 }
933 }
934 }
935
936 // not-logged-in user
937 $this->setUser(0);
938 foreach ($contexts as $contextid=>$unused) {
939 $context = context_helper::instance_by_id($contextid);
940 $roles = get_assignable_roles($context, ROLENAME_SHORT);
941 $this->assertSame(array(), $roles);
942 }
943
944 // Test current user.
945 $this->setUser(0);
946 $admin = $DB->get_record('user', array('username'=>'admin'), '*', MUST_EXIST);
947 $roles1 = get_assignable_roles($coursecontext, ROLENAME_SHORT, false, $admin);
948 $roles2 = get_assignable_roles($coursecontext, ROLENAME_SHORT, false, $admin->id);
949 $this->setAdminUser();
950 $roles3 = get_assignable_roles($coursecontext, ROLENAME_SHORT);
951 $this->assertSame($roles1, $roles3);
952 $this->assertSame($roles2, $roles3);
953
954 // Test parameter defaults.
955 $this->setAdminUser();
956 $roles1 = get_assignable_roles($coursecontext);
957 $roles2 = get_assignable_roles($coursecontext, ROLENAME_ALIAS, false, $admin);
958 $this->assertEquals($roles2, $roles1);
959
960 // Verify returned names - let's allow all roles everywhere to simplify this a bit.
961 $alllevels = context_helper::get_all_levels();
962 $alllevels = array_keys($alllevels);
963 foreach($allroles as $roleid=>$role) {
964 set_role_contextlevels($roleid, $alllevels);
965 }
966 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
967 foreach ($alltypes as $type) {
968 if ($type == ROLENAME_SHORT or $type == ROLENAME_ORIGINALANDSHORT or $type == ROLENAME_BOTH) {
969 // TODO: skip for now, remove after role_fix_names() is fixed and supports all types MDL-8249
970 continue;
971 }
972 $rolenames = role_fix_names($allroles, $coursecontext, $type);
973 $roles = get_assignable_roles($coursecontext, $type, false, $admin);
974 foreach ($roles as $roleid=>$rolename) {
975 $this->assertSame($rolenames[$roleid]->localname, $rolename);
976 }
977 }
978
979 // Verify counts.
980 //TODO: test all types - ROLENAME_SHORT is borked here for example MDL-8249
981 $roles = get_assignable_roles($coursecontext, ROLENAME_ALIAS, false, $admin);
982 list($rolenames, $rolecounts, $nameswithcounts) = get_assignable_roles($coursecontext, ROLENAME_ALIAS, true, $admin);
983 $this->assertEquals($roles, $rolenames);
984 foreach ($rolenames as $roleid=>$name) {
985 if ($roleid == $teacherrole->id or $roleid == $studentrole->id) {
986 $this->assertEquals(1, $rolecounts[$roleid]);
987 } else {
988 $this->assertEquals(0, $rolecounts[$roleid]);
989 }
990 $this->assertEquals("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]);
991 }
992 }
993
994 /**
995 * Test getting of all switchable roles.
996 * @retrun void
997 */
998 public function test_get_switchable_roles() {
999 global $DB;
1000
1001 $this->resetAfterTest();
1002
1003 $course = $this->getDataGenerator()->create_course();
1004 $coursecontext = context_course::instance($course->id);
1005
1006 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1007 $teacher = $this->getDataGenerator()->create_user();
1008 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1009 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1010 $DB->insert_record('role_names', $teacherename);
1011
1012 $contexts = $DB->get_records('context');
1013 $users = $DB->get_records('user');
1014 $allroles = $DB->get_records('role');
1015
1016 // Evaluate all results for all users in all contexts.
1017 foreach($users as $user) {
1018 $this->setUser($user);
1019 foreach ($contexts as $contextid=>$unused) {
1020 $context = context_helper::instance_by_id($contextid);
1021 $roles = get_switchable_roles($context);
1022 foreach ($allroles as $roleid=>$role) {
1023 if (is_siteadmin()) {
1024 $this->assertTrue(isset($roles[$roleid]));
1025 } else {
1026 $parents = $context->get_parent_context_ids(true);
1027 $pcontexts = implode(',' , $parents);
1028 $allowed = $DB->record_exists_sql(
1029 "SELECT r.id
1030 FROM {role} r
1031 JOIN {role_allow_switch} ras ON ras.allowswitch = r.id
1032 JOIN {role_assignments} ra ON ra.roleid = ras.roleid
1033 WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid
1034 ",
1035 array('userid'=>$user->id, 'roleid'=>$roleid)
1036 );
1037 if (isset($roles[$roleid])) {
1038 $this->assertTrue($allowed);
1039 } else {
1040 $this->assertFalse($allowed);
1041 }
1042 }
1043
1044 if (isset($roles[$roleid])) {
1045 $coursecontext = $context->get_course_context(false);
1046 if ($coursecontext) {
1047 $this->assertEquals(role_get_name($role, $coursecontext), $roles[$roleid]);
1048 } else {
1049 // TODO: switch to role_get_name() once it supports all contexts and rolename types MDL-8249
1050 $this->assertEquals($role->name, $roles[$roleid]);
1051 }
1052 }
1053 }
1054 }
1055 }
1056 }
1057
1058 /**
1059 * Test getting of all overridable roles.
1060 * @return void
1061 */
1062 public function test_get_overridable_roles() {
1063 global $DB;
1064
1065 $this->resetAfterTest();
1066
1067 $course = $this->getDataGenerator()->create_course();
1068 $coursecontext = context_course::instance($course->id);
1069
1070 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1071 $teacher = $this->getDataGenerator()->create_user();
1072 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1073 $teacherename = (object)array('roleid'=>$teacher->id, 'name'=>'Učitel', 'contextid'=>$coursecontext->id);
1074 $DB->insert_record('role_names', $teacherename);
1075 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse'))); // any capability is ok
1076 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $teacher->id, $coursecontext->id);
1077
1078 $studentrole = $DB->get_record('role', array('shortname'=>'student'), '*', MUST_EXIST);
1079 $student = $this->getDataGenerator()->create_user();
1080 role_assign($studentrole->id, $student->id, $coursecontext);
1081
1082 $contexts = $DB->get_records('context');
1083 $users = $DB->get_records('user');
1084 $allroles = $DB->get_records('role');
1085
1086 // Evaluate all results for all users in all contexts.
1087 foreach($users as $user) {
1088 $this->setUser($user);
1089 foreach ($contexts as $contextid=>$unused) {
1090 $context = context_helper::instance_by_id($contextid);
1091 $roles = get_overridable_roles($context, ROLENAME_SHORT);
1092 foreach ($allroles as $roleid=>$role) {
1093 $hascap = has_any_capability(array('moodle/role:safeoverride', 'moodle/role:override'), $context);
1094 if (is_siteadmin()) {
1095 $this->assertTrue(isset($roles[$roleid]));
1096 } else {
1097 $parents = $context->get_parent_context_ids(true);
1098 $pcontexts = implode(',' , $parents);
1099 $allowed = $DB->record_exists_sql(
1100 "SELECT r.id
1101 FROM {role} r
1102 JOIN {role_allow_override} rao ON r.id = rao.allowoverride
1103 JOIN {role_assignments} ra ON rao.roleid = ra.roleid
1104 WHERE ra.userid = :userid AND ra.contextid IN ($pcontexts) AND r.id = :roleid
1105 ",
1106 array('userid'=>$user->id, 'roleid'=>$roleid)
1107 );
1108 if (isset($roles[$roleid])) {
1109 $this->assertTrue($hascap);
1110 $this->assertTrue($allowed);
1111 } else {
1112 $this->assertFalse($hascap and $allowed);
1113 }
1114 }
1115
1116 if (isset($roles[$roleid])) {
1117 //TODO: ROLENAME_SHORT borked! MDL-8249
1118 //$this->assertEquals($role->shortname, $roles[$roleid]);
1119 }
1120 }
1121 }
1122 }
1123
1124 // Test parameter defaults.
1125 $this->setAdminUser();
1126 $roles1 = get_overridable_roles($coursecontext);
1127 $roles2 = get_overridable_roles($coursecontext, ROLENAME_ALIAS, false);
1128 $this->assertEquals($roles2, $roles1);
1129
1130 $alltypes = array(ROLENAME_ALIAS, ROLENAME_ALIAS_RAW, ROLENAME_BOTH, ROLENAME_ORIGINAL, ROLENAME_ORIGINALANDSHORT, ROLENAME_SHORT);
1131 foreach ($alltypes as $type) {
1132 if ($type == ROLENAME_SHORT or $type == ROLENAME_ORIGINALANDSHORT or $type == ROLENAME_BOTH) {
1133 // TODO: skip for now, remove after role_fix_names() is fixed and supports all types MDL-8249
1134 continue;
1135 }
1136 $rolenames = role_fix_names($allroles, $coursecontext, $type);
1137 $roles = get_overridable_roles($coursecontext, $type, false);
1138 foreach ($roles as $roleid=>$rolename) {
1139 $this->assertSame($rolenames[$roleid]->localname, $rolename);
1140 }
1141 }
1142
1143 // Verify counts.
1144 $roles = get_overridable_roles($coursecontext, ROLENAME_ALIAS, false);
1145 list($rolenames, $rolecounts, $nameswithcounts) = get_overridable_roles($coursecontext, ROLENAME_ALIAS, true);
1146 $this->assertEquals($roles, $rolenames);
1147 foreach ($rolenames as $roleid=>$name) {
1148 if ($roleid == $teacherrole->id) {
1149 $this->assertEquals(1, $rolecounts[$roleid]);
1150 } else {
1151 $this->assertEquals(0, $rolecounts[$roleid]);
1152 }
1153 $this->assertEquals("$name ($rolecounts[$roleid])", $nameswithcounts[$roleid]);
1154 }
1155 }
1156
1157 /**
1158 * Test we have context level defaults.
1159 * @return void
1160 */
1161 public function test_get_default_contextlevels() {
1162 $archetypes = get_role_archetypes();
1163 $alllevels = context_helper::get_all_levels();
1164 foreach ($archetypes as $archetype) {
1165 $defaults = get_default_contextlevels($archetype);
1166 $this->assertTrue(is_array($defaults));
1167 foreach ($defaults as $level) {
1168 $this->assertTrue(isset($alllevels[$level]));
1169 }
1170 }
1171 }
1172
1173 /**
1174 * Test role context level setup.
1175 * @return void
1176 */
1177 public function test_set_role_contextlevels() {
1178 global $DB;
1179
1180 $this->resetAfterTest();
1181
1182 $roleid = create_role('New student role', 'student2', 'New student description', 'student');
1183
1184 $this->assertFalse($DB->record_exists('role_context_levels', array('roleid' => $roleid)));
1185
1186 set_role_contextlevels($roleid, array(CONTEXT_COURSE, CONTEXT_MODULE));
1187 $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel');
1188 $this->assertCount(2, $levels);
1189 $this->assertTrue(isset($levels[CONTEXT_COURSE]));
1190 $this->assertTrue(isset($levels[CONTEXT_MODULE]));
1191
1192 set_role_contextlevels($roleid, array(CONTEXT_COURSE));
1193 $levels = $DB->get_records('role_context_levels', array('roleid' => $roleid), '', 'contextlevel, contextlevel');
1194 $this->assertCount(1, $levels);
1195 $this->assertTrue(isset($levels[CONTEXT_COURSE]));
1196 }
1197
1198 /**
1199 * Test getting of role context levels
1200 * @return void
1201 */
1202 public function test_get_roles_for_contextlevels() {
1203 global $DB;
1204
1205 $allroles = get_all_roles();
1206 foreach (context_helper::get_all_levels() as $level=>$unused) {
1207 $roles = get_roles_for_contextlevels($level);
1208 foreach ($allroles as $roleid=>$unused) {
1209 $exists = $DB->record_exists('role_context_levels', array('contextlevel'=>$level, 'roleid'=>$roleid));
1210 if (in_array($roleid, $roles)) {
1211 $this->assertTrue($exists);
1212 } else {
1213 $this->assertFalse($exists);
1214 }
1215 }
1216 }
1217 }
1218
1219 /**
1220 * Test default enrol roles.
1221 * @return void
1222 */
1223 public function test_get_default_enrol_roles() {
1224 $this->resetAfterTest();
1225
1226 $course = $this->getDataGenerator()->create_course();
1227 $coursecontext = context_course::instance($course->id);
1228
1229 $id2 = create_role('New student role', 'student2', 'New student description', 'student');
1230 set_role_contextlevels($id2, array(CONTEXT_COURSE));
1231
1232 //TODO: add role name alias MDL-8249
1233
1234 $allroles = get_all_roles();
1235 $expected = array($id2=>$allroles[$id2]);
1236
1237 foreach(get_role_archetypes() as $archetype) {
1238 $defaults = get_default_contextlevels($archetype);
1239 if (in_array(CONTEXT_COURSE, $defaults)) {
1240 $roles = get_archetype_roles($archetype);
1241 foreach($roles as $role) {
1242 $expected[$role->id] = $role;
1243 }
1244 }
1245 }
1246
1247 $roles = get_default_enrol_roles($coursecontext);
1248 foreach ($allroles as $role) {
1249 $this->assertEquals(isset($expected[$role->id]), isset($roles[$role->id]));
1250 if (isset($roles[$role->id])) {
1251 $this->assertEquals(role_get_name($role, $coursecontext), $roles[$role->id]);
1252 }
1253 }
1254 }
1255
1256 /**
1257 * Test has_capability(), has_any_capability() and has_all_capabilities().
1258 */
1259 public function test_has_capability_and_friends() {
1260 global $DB;
1261
1262 $this->resetAfterTest();
1263
1264 $course = $this->getDataGenerator()->create_course();
1265 $coursecontext = context_course::instance($course->id);
1266 $teacherrole = $DB->get_record('role', array('shortname'=>'editingteacher'), '*', MUST_EXIST);
1267 $teacher = $this->getDataGenerator()->create_user();
1268 role_assign($teacherrole->id, $teacher->id, $coursecontext);
1269 $admin = $DB->get_record('user', array('username'=>'admin'));
1270
1271 // Note: Here are used default capabilities, the full test is in permission evaluation bellow,
1272 // use two capabilities that teacher has and one does not, none of them should be allowed for not-logged-in user.
1273
1274 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupsection')));
1275 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/backup:backupcourse')));
1276 $this->assertTrue($DB->record_exists('capabilities', array('name'=>'moodle/site:approvecourse')));
1277
1278 $sca = array('moodle/backup:backupsection', 'moodle/backup:backupcourse', 'moodle/site:approvecourse');
1279 $sc = array('moodle/backup:backupsection', 'moodle/backup:backupcourse');
1280
1281 $this->setUser(0);
1282 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext));
1283 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext));
1284 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext));
1285 $this->assertFalse(has_any_capability($sca, $coursecontext));
1286 $this->assertFalse(has_all_capabilities($sca, $coursecontext));
1287
1288 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $teacher));
1289 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $teacher));
1290 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $teacher));
1291 $this->assertTrue(has_any_capability($sca, $coursecontext, $teacher));
1292 $this->assertTrue(has_all_capabilities($sc, $coursecontext, $teacher));
1293 $this->assertFalse(has_all_capabilities($sca, $coursecontext, $teacher));
1294
1295 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext, $admin));
1296 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext, $admin));
1297 $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext, $admin));
1298 $this->assertTrue(has_any_capability($sca, $coursecontext, $admin));
1299 $this->assertTrue(has_all_capabilities($sc, $coursecontext, $admin));
1300 $this->assertTrue(has_all_capabilities($sca, $coursecontext, $admin));
1301
1302 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, $admin, false));
1303 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, $admin, false));
1304 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, $admin, false));
1305 $this->assertFalse(has_any_capability($sca, $coursecontext, $admin, false));
1306 $this->assertFalse(has_all_capabilities($sc, $coursecontext, $admin, false));
1307 $this->assertFalse(has_all_capabilities($sca, $coursecontext, $admin, false));
1308
1309 $this->setUser($teacher);
1310 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext));
1311 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext));
1312 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext));
1313 $this->assertTrue(has_any_capability($sca, $coursecontext));
1314 $this->assertTrue(has_all_capabilities($sc, $coursecontext));
1315 $this->assertFalse(has_all_capabilities($sca, $coursecontext));
1316
1317 $this->setAdminUser();
1318 $this->assertTrue(has_capability('moodle/backup:backupsection', $coursecontext));
1319 $this->assertTrue(has_capability('moodle/backup:backupcourse', $coursecontext));
1320 $this->assertTrue(has_capability('moodle/site:approvecourse', $coursecontext));
1321 $this->assertTrue(has_any_capability($sca, $coursecontext));
1322 $this->assertTrue(has_all_capabilities($sc, $coursecontext));
1323 $this->assertTrue(has_all_capabilities($sca, $coursecontext));
1324
1325 $this->assertFalse(has_capability('moodle/backup:backupsection', $coursecontext, 0));
1326 $this->assertFalse(has_capability('moodle/backup:backupcourse', $coursecontext, 0));
1327 $this->assertFalse(has_capability('moodle/site:approvecourse', $coursecontext, 0));
1328 $this->assertFalse(has_any_capability($sca, $coursecontext, 0));
1329 $this->assertFalse(has_all_capabilities($sca, $coursecontext, 0));
1330 }
1331
1332 /**
1333 * Test require_capability() exceptions.
1334 * @return void
1335 */
1336 public function test_require_capability() {
1337 $this->resetAfterTest();
1338
1339 $syscontext = context_system::instance();
1340
1341 $this->setUser(0);
1342 $this->assertFalse(has_capability('moodle/site:config', $syscontext));
1343 try {
1344 require_capability('moodle/site:config', $syscontext);
1345 $this->fail('Exception expected from require_capability()');
1346 } catch (Exception $e) {
1347 $this->assertInstanceOf('required_capability_exception', $e);
1348 }
1349 $this->setAdminUser();
1350 $this->assertFalse(has_capability('moodle/site:config', $syscontext, 0));
1351 try {
1352 require_capability('moodle/site:config', $syscontext, 0);
1353 $this->fail('Exception expected from require_capability()');
1354 } catch (Exception $e) {
1355 $this->assertInstanceOf('required_capability_exception', $e);
1356 }
1357 $this->assertFalse(has_capability('moodle/site:config', $syscontext, null, false));
1358 try {
1359 require_capability('moodle/site:config', $syscontext, null, false);
1360 $this->fail('Exception expected from require_capability()');
1361 } catch (Exception $e) {
1362 $this->assertInstanceOf('required_capability_exception', $e);
1363 }
1364
1365
1366 }
1367
1368 /**
1369 * A small functional test of permission evaluations.
1370 * @return void
1371 */
1372 public function test_permission_evaluation() {
a3d5830a
PS
1373 global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE;
1374
1375 $this->resetAfterTest(true);
1376
1377 $generator = $this->getDataGenerator();
1378
1379 // Fill the site with some real data
1380 $testcategories = array();
1381 $testcourses = array();
1382 $testpages = array();
1383 $testblocks = array();
1384 $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id');
1385
1386 $systemcontext = context_system::instance();
1387 $frontpagecontext = context_course::instance(SITEID);
1388
1389 // Add block to system context
1390 $bi = $generator->create_block('online_users');
1391 context_block::instance($bi->id);
1392 $testblocks[] = $bi->id;
1393
1394 // Some users
1395 $testusers = array();
1396 for($i=0; $i<20; $i++) {
1397 $user = $generator->create_user();
1398 $testusers[$i] = $user->id;
1399 $usercontext = context_user::instance($user->id);
1400
1401 // Add block to user profile
1402 $bi = $generator->create_block('online_users', array('parentcontextid'=>$usercontext->id));
1403 $testblocks[] = $bi->id;
1404 }
1405 // Deleted user - should be ignored everywhere, can not have context
1406 $generator->create_user(array('deleted'=>1));
1407
1408 // Add block to frontpage
1409 $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagecontext->id));
1410 $frontpageblockcontext = context_block::instance($bi->id);
1411 $testblocks[] = $bi->id;
1412
1413 // Add a resource to frontpage
1414 $page = $generator->create_module('page', array('course'=>$SITE->id));
1415 $testpages[] = $page->id;
1416 $frontpagepagecontext = context_module::instance($page->cmid);
1417
1418 // Add block to frontpage resource
1419 $bi = $generator->create_block('online_users', array('parentcontextid'=>$frontpagepagecontext->id));
1420 $frontpagepageblockcontext = context_block::instance($bi->id);
1421 $testblocks[] = $bi->id;
1422
1423 // Some nested course categories with courses
1424 $manualenrol = enrol_get_plugin('manual');
1425 $parentcat = 0;
1426 for($i=0; $i<5; $i++) {
1427 $cat = $generator->create_category(array('parent'=>$parentcat));
1428 $testcategories[] = $cat->id;
1429 $catcontext = context_coursecat::instance($cat->id);
1430 $parentcat = $cat->id;
1431
dfa6a346 1432 if ($i >= 4) {
a3d5830a
PS
1433 continue;
1434 }
1435
1436 // Add resource to each category
1437 $bi = $generator->create_block('online_users', array('parentcontextid'=>$catcontext->id));
1438 context_block::instance($bi->id);
1439
1440 // Add a few courses to each category
1441 for($j=0; $j<6; $j++) {
1442 $course = $generator->create_course(array('category'=>$cat->id));
1443 $testcourses[] = $course->id;
1444 $coursecontext = context_course::instance($course->id);
1445
1446 if ($j >= 5) {
1447 continue;
1448 }
1449 // Add manual enrol instance
1450 $manualenrol->add_default_instance($DB->get_record('course', array('id'=>$course->id)));
1451
1452 // Add block to each course
1453 $bi = $generator->create_block('online_users', array('parentcontextid'=>$coursecontext->id));
1454 $testblocks[] = $bi->id;
1455
1456 // Add a resource to each course
1457 $page = $generator->create_module('page', array('course'=>$course->id));
1458 $testpages[] = $page->id;
1459 $modcontext = context_module::instance($page->cmid);
1460
1461 // Add block to each module
1462 $bi = $generator->create_block('online_users', array('parentcontextid'=>$modcontext->id));
1463 $testblocks[] = $bi->id;
1464 }
1465 }
1466
1467 // Make sure all contexts were created properly
1468 $count = 1; //system
1469 $count += $DB->count_records('user', array('deleted'=>0));
1470 $count += $DB->count_records('course_categories');
1471 $count += $DB->count_records('course');
1472 $count += $DB->count_records('course_modules');
1473 $count += $DB->count_records('block_instances');
1474 $this->assertEquals($DB->count_records('context'), $count);
1475 $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
1476 $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
1477
1478
1479 // ====== context_helper::get_level_name() ================================
1480
1481 $levels = context_helper::get_all_levels();
1482 foreach ($levels as $level=>$classname) {
1483 $name = context_helper::get_level_name($level);
1484 $this->assertFalse(empty($name));
1485 }
1486
1487
1488 // ======= context::instance_by_id(), context_xxx::instance();
1489
1490 $context = context::instance_by_id($frontpagecontext->id);
1491 $this->assertSame($context->contextlevel, CONTEXT_COURSE);
1492 $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING));
1493 try {
1494 context::instance_by_id(-1);
1495 $this->fail('exception expected');
1496 } catch (Exception $e) {
1497 $this->assertTrue(true);
1498 }
1499 $this->assertTrue(context_system::instance() instanceof context_system);
1500 $this->assertTrue(context_coursecat::instance($testcategories[0]) instanceof context_coursecat);
1501 $this->assertTrue(context_course::instance($testcourses[0]) instanceof context_course);
1502 $this->assertTrue(context_module::instance($testpages[0]) instanceof context_module);
1503 $this->assertTrue(context_block::instance($testblocks[0]) instanceof context_block);
1504
1505 $this->assertFalse(context_coursecat::instance(-1, IGNORE_MISSING));
1506 $this->assertFalse(context_course::instance(-1, IGNORE_MISSING));
1507 $this->assertFalse(context_module::instance(-1, IGNORE_MISSING));
1508 $this->assertFalse(context_block::instance(-1, IGNORE_MISSING));
1509 try {
1510 context_coursecat::instance(-1);
1511 $this->fail('exception expected');
1512 } catch (Exception $e) {
1513 $this->assertTrue(true);
1514 }
1515 try {
1516 context_course::instance(-1);
1517 $this->fail('exception expected');
1518 } catch (Exception $e) {
1519 $this->assertTrue(true);
1520 }
1521 try {
1522 context_module::instance(-1);
1523 $this->fail('exception expected');
1524 } catch (Exception $e) {
1525 $this->assertTrue(true);
1526 }
1527 try {
1528 context_block::instance(-1);
1529 $this->fail('exception expected');
1530 } catch (Exception $e) {
1531 $this->assertTrue(true);
1532 }
1533
1534
1535 // ======= $context->get_url(), $context->get_context_name(), $context->get_capabilities() =========
1536
1537 $testcontexts = array();
1538 $testcontexts[CONTEXT_SYSTEM] = context_system::instance();
1539 $testcontexts[CONTEXT_COURSECAT] = context_coursecat::instance($testcategories[0]);
1540 $testcontexts[CONTEXT_COURSE] = context_course::instance($testcourses[0]);
1541 $testcontexts[CONTEXT_MODULE] = context_module::instance($testpages[0]);
1542 $testcontexts[CONTEXT_BLOCK] = context_block::instance($testblocks[0]);
1543
1544 foreach ($testcontexts as $context) {
1545 $name = $context->get_context_name(true, true);
1546 $this->assertFalse(empty($name));
1547
1548 $this->assertTrue($context->get_url() instanceof moodle_url);
1549
1550 $caps = $context->get_capabilities();
1551 $this->assertTrue(is_array($caps));
1552 foreach ($caps as $cap) {
1553 $cap = (array)$cap;
1554 $this->assertSame(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask'));
1555 }
1556 }
1557 unset($testcontexts);
1558
1559 // ===== $context->get_course_context() =========================================
1560
1561 $this->assertFalse($systemcontext->get_course_context(false));
1562 try {
1563 $systemcontext->get_course_context();
1564 $this->fail('exception expected');
1565 } catch (Exception $e) {
1566 $this->assertTrue(true);
1567 }
1568 $context = context_coursecat::instance($testcategories[0]);
1569 $this->assertFalse($context->get_course_context(false));
1570 try {
1571 $context->get_course_context();
1572 $this->fail('exception expected');
1573 } catch (Exception $e) {
1574 $this->assertTrue(true);
1575 }
1576 $this->assertSame($frontpagecontext->get_course_context(true), $frontpagecontext);
1577 $this->assertSame($frontpagepagecontext->get_course_context(true), $frontpagecontext);
1578 $this->assertSame($frontpagepageblockcontext->get_course_context(true), $frontpagecontext);
1579
1580
1581 // ======= $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() =======
1582
1583 $userid = reset($testusers);
1584 $usercontext = context_user::instance($userid);
1585 $this->assertSame($usercontext->get_parent_context(), $systemcontext);
1586 $this->assertSame($usercontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
1587 $this->assertSame($usercontext->get_parent_contexts(true), array($usercontext->id=>$usercontext, $systemcontext->id=>$systemcontext));
1588
1589 $this->assertSame($systemcontext->get_parent_contexts(), array());
1590 $this->assertSame($systemcontext->get_parent_contexts(true), array($systemcontext->id=>$systemcontext));
1591 $this->assertSame($systemcontext->get_parent_context_ids(), array());
1592 $this->assertSame($systemcontext->get_parent_context_ids(true), array($systemcontext->id));
1593
1594 $this->assertSame($frontpagecontext->get_parent_context(), $systemcontext);
1595 $this->assertSame($frontpagecontext->get_parent_contexts(), array($systemcontext->id=>$systemcontext));
1596 $this->assertSame($frontpagecontext->get_parent_contexts(true), array($frontpagecontext->id=>$frontpagecontext, $systemcontext->id=>$systemcontext));
1597 $this->assertSame($frontpagecontext->get_parent_context_ids(), array($systemcontext->id));
1598 $this->assertEquals($frontpagecontext->get_parent_context_ids(true), array($frontpagecontext->id, $systemcontext->id));
1599
1600 $this->assertSame($systemcontext->get_parent_context(), false);
1601 $frontpagecontext = context_course::instance($SITE->id);
1602 $parent = $systemcontext;
1603 foreach ($testcategories as $catid) {
1604 $catcontext = context_coursecat::instance($catid);
1605 $this->assertSame($catcontext->get_parent_context(), $parent);
1606 $parent = $catcontext;
1607 }
1608 $this->assertSame($frontpagepagecontext->get_parent_context(), $frontpagecontext);
1609 $this->assertSame($frontpageblockcontext->get_parent_context(), $frontpagecontext);
1610 $this->assertSame($frontpagepageblockcontext->get_parent_context(), $frontpagepagecontext);
1611
1612
1613 // ====== $context->get_child_contexts() ================================
1614
1615 $CFG->debug = 0;
1616 $children = $systemcontext->get_child_contexts();
1617 $CFG->debug = DEBUG_DEVELOPER;
1618 $this->assertEquals(count($children)+1, $DB->count_records('context'));
1619
1620 $context = context_coursecat::instance($testcategories[3]);
1621 $children = $context->get_child_contexts();
1622 $countcats = 0;
1623 $countcourses = 0;
1624 $countblocks = 0;
1625 foreach ($children as $child) {
1626 if ($child->contextlevel == CONTEXT_COURSECAT) {
1627 $countcats++;
1628 }
1629 if ($child->contextlevel == CONTEXT_COURSE) {
1630 $countcourses++;
1631 }
1632 if ($child->contextlevel == CONTEXT_BLOCK) {
1633 $countblocks++;
1634 }
1635 }
1636 $this->assertEquals(count($children), 8);
1637 $this->assertEquals($countcats, 1);
1638 $this->assertEquals($countcourses, 6);
1639 $this->assertEquals($countblocks, 1);
1640
1641 $context = context_course::instance($testcourses[2]);
1642 $children = $context->get_child_contexts();
1643 $this->assertEquals(count($children), 7); // depends on number of default blocks
1644
1645 $context = context_module::instance($testpages[3]);
1646 $children = $context->get_child_contexts();
1647 $this->assertEquals(count($children), 1);
1648
1649 $context = context_block::instance($testblocks[1]);
1650 $children = $context->get_child_contexts();
1651 $this->assertEquals(count($children), 0);
1652
1653 unset($children);
1654 unset($countcats);
1655 unset($countcourses);
1656 unset($countblocks);
1657
1658
1659 // ======= context_helper::reset_caches() ============================
1660
1661 context_helper::reset_caches();
1662 $this->assertEquals(context_inspection::test_context_cache_size(), 0);
1663 context_course::instance($SITE->id);
1664 $this->assertEquals(context_inspection::test_context_cache_size(), 1);
1665
1666
1667 // ======= context preloading ========================================
1668
1669 context_helper::reset_caches();
1670 $sql = "SELECT ".context_helper::get_preload_record_columns_sql('c')."
1671 FROM {context} c
1672 WHERE c.contextlevel <> ".CONTEXT_SYSTEM;
1673 $records = $DB->get_records_sql($sql);
1674 $firstrecord = reset($records);
1675 $columns = context_helper::get_preload_record_columns('c');
1676 $firstrecord = (array)$firstrecord;
1677 $this->assertSame(array_keys($firstrecord), array_values($columns));
1678 context_helper::reset_caches();
1679 foreach ($records as $record) {
1680 context_helper::preload_from_record($record);
1681 $this->assertEquals($record, new stdClass());
1682 }
1683 $this->assertEquals(context_inspection::test_context_cache_size(), count($records));
1684 unset($records);
1685 unset($columns);
1686
1687 context_helper::reset_caches();
1688 context_helper::preload_course($SITE->id);
877b243f
TH
1689 $numfrontpagemodules = $DB->count_records('course_modules', array('course' => $SITE->id));
1690 $this->assertEquals(6 + $numfrontpagemodules, context_inspection::test_context_cache_size()); // depends on number of default blocks
a3d5830a
PS
1691
1692 // ====== assign_capability(), unassign_capability() ====================
1693
1694 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1695 $this->assertFalse($rc);
1696 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext->id);
1697 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1698 $this->assertEquals($rc->permission, CAP_ALLOW);
1699 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext->id);
1700 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1701 $this->assertEquals($rc->permission, CAP_ALLOW);
1702 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext, true);
1703 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1704 $this->assertEquals($rc->permission, CAP_PREVENT);
1705
1706 assign_capability('moodle/site:accessallgroups', CAP_INHERIT, $allroles['teacher'], $frontpagecontext);
1707 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1708 $this->assertFalse($rc);
1709 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext);
1710 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true);
1711 $rc = $DB->get_record('role_capabilities', array('contextid'=>$frontpagecontext->id, 'roleid'=>$allroles['teacher'], 'capability'=>'moodle/site:accessallgroups'));
1712 $this->assertFalse($rc);
1713 unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true);
1714 unset($rc);
1715
1716 accesslib_clear_all_caches(false); // must be done after assign_capability()
1717
1718
1719 // ======= role_assign(), role_unassign(), role_unassign_all() ==============
1720
1721 $context = context_course::instance($testcourses[1]);
1722 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
1723 role_assign($allroles['teacher'], $testusers[1], $context->id);
1724 role_assign($allroles['teacher'], $testusers[2], $context->id);
1725 role_assign($allroles['manager'], $testusers[1], $context->id);
1726 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 3);
1727 role_unassign($allroles['teacher'], $testusers[1], $context->id);
1728 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 2);
1729 role_unassign_all(array('contextid'=>$context->id));
1730 $this->assertEquals($DB->count_records('role_assignments', array('contextid'=>$context->id)), 0);
1731 unset($context);
1732
1733 accesslib_clear_all_caches(false); // just in case
1734
1735
1736 // ====== has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends ========================
1737
1738 $adminid = get_admin()->id;
1739 $guestid = $CFG->siteguest;
1740
1741 // Enrol some users into some courses
1742 $course1 = $DB->get_record('course', array('id'=>$testcourses[22]), '*', MUST_EXIST);
1743 $course2 = $DB->get_record('course', array('id'=>$testcourses[7]), '*', MUST_EXIST);
1744 $cms = $DB->get_records('course_modules', array('course'=>$course1->id), 'id');
1745 $cm1 = reset($cms);
1746 $blocks = $DB->get_records('block_instances', array('parentcontextid'=>context_module::instance($cm1->id)->id), 'id');
1747 $block1 = reset($blocks);
1748 $instance1 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course1->id));
1749 $instance2 = $DB->get_record('enrol', array('enrol'=>'manual', 'courseid'=>$course2->id));
1750 for($i=0; $i<9; $i++) {
1751 $manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']);
1752 }
1753 $manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']);
1754 $manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']);
1755
1756 for($i=10; $i<15; $i++) {
1757 $manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']);
1758 }
1759 $manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']);
1760
1761 // Add tons of role assignments - the more the better
1762 role_assign($allroles['coursecreator'], $testusers[11], context_coursecat::instance($testcategories[2]));
1763 role_assign($allroles['manager'], $testusers[12], context_coursecat::instance($testcategories[1]));
1764 role_assign($allroles['student'], $testusers[9], context_module::instance($cm1->id));
1765 role_assign($allroles['teacher'], $testusers[8], context_module::instance($cm1->id));
1766 role_assign($allroles['guest'], $testusers[13], context_course::instance($course1->id));
1767 role_assign($allroles['teacher'], $testusers[7], context_block::instance($block1->id));
1768 role_assign($allroles['manager'], $testusers[9], context_block::instance($block1->id));
1769 role_assign($allroles['editingteacher'], $testusers[9], context_course::instance($course1->id));
1770
1771 role_assign($allroles['teacher'], $adminid, context_course::instance($course1->id));
1772 role_assign($allroles['editingteacher'], $adminid, context_block::instance($block1->id));
1773
1774 // Add tons of overrides - the more the better
1775 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpageblockcontext, true);
1776 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpageblockcontext, true);
1777 assign_capability('moodle/block:view', CAP_PROHIBIT, $allroles['guest'], $frontpageblockcontext, true);
1778 assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['user'], $frontpageblockcontext, true);
1779 assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['student'], $frontpageblockcontext, true);
1780
1781 assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $CFG->defaultuserroleid, $frontpagepagecontext, true);
1782 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagepagecontext, true);
1783 assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $frontpagepagecontext, true);
1784 assign_capability('mod/page:view', CAP_ALLOW, $allroles['user'], $frontpagepagecontext, true);
1785 assign_capability('moodle/page:view', CAP_ALLOW, $allroles['student'], $frontpagepagecontext, true);
1786
1787 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpagecontext, true);
1788 assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext, true);
1789 assign_capability('mod/page:view', CAP_ALLOW, $allroles['guest'], $frontpagecontext, true);
1790 assign_capability('mod/page:view', CAP_PROHIBIT, $allroles['user'], $frontpagecontext, true);
1791
1792 assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $systemcontext, true);
1793
1794 accesslib_clear_all_caches(false); // must be done after assign_capability()
1795
1796 // Extra tests for guests and not-logged-in users because they can not be verified by cross checking
1797 // with get_users_by_capability() where they are ignored
1798 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid));
1799 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid));
1800 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid));
1801 $this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid));
1802
1803 $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0));
1804 $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0));
1805 $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0));
1806 $this->assertFalse(has_capability('mod/page:view', $systemcontext, 0));
1807
1808 $this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11]));
1809 $this->assertTrue(has_capability('moodle/course:create', context_coursecat::instance($testcategories[2]), $testusers[11]));
1810 $this->assertFalse(has_capability('moodle/course:create', context_course::instance($testcourses[1]), $testusers[11]));
1811 $this->assertTrue(has_capability('moodle/course:create', context_course::instance($testcourses[19]), $testusers[11]));
1812
1813 $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[1]), $testusers[9]));
1814 $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[19]), $testusers[9]));
1815 $this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9]));
1816
1817 // Test the list of enrolled users
1818 $coursecontext = context_course::instance($course1->id);
1819 $enrolled = get_enrolled_users($coursecontext);
1820 $this->assertEquals(count($enrolled), 10);
1821 for($i=0; $i<10; $i++) {
1822 $this->assertTrue(isset($enrolled[$testusers[$i]]));
1823 }
1824 $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update');
1825 $this->assertEquals(count($enrolled), 1);
1826 $this->assertTrue(isset($enrolled[$testusers[9]]));
1827 unset($enrolled);
1828
1829 // role switching
1830 $userid = $testusers[9];
1831 $USER = $DB->get_record('user', array('id'=>$userid));
1832 load_all_capabilities();
1833 $coursecontext = context_course::instance($course1->id);
1834 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
1835 $this->assertFalse(is_role_switched($course1->id));
1836 role_switch($allroles['student'], $coursecontext);
1837 $this->assertTrue(is_role_switched($course1->id));
1838 $this->assertEquals($USER->access['rsw'][$coursecontext->path], $allroles['student']);
1839 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
1840 reload_all_capabilities();
1841 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
1842 role_switch(0, $coursecontext);
1843 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
1844 $userid = $adminid;
1845 $USER = $DB->get_record('user', array('id'=>$userid));
1846 load_all_capabilities();
1847 $coursecontext = context_course::instance($course1->id);
1848 $blockcontext = context_block::instance($block1->id);
1849 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
1850 role_switch($allroles['student'], $coursecontext);
1851 $this->assertEquals($USER->access['rsw'][$coursecontext->path], $allroles['student']);
1852 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
1853 reload_all_capabilities();
1854 $this->assertFalse(has_capability('moodle/course:update', $blockcontext));
1855 load_all_capabilities();
1856 $this->assertTrue(has_capability('moodle/course:update', $blockcontext));
1857
1858 // temp course role for enrol
1859 $DB->delete_records('cache_flags', array()); // this prevents problem with dirty contexts immediately resetting the temp role - this is a known problem...
1860 $userid = $testusers[5];
1861 $roleid = $allroles['editingteacher'];
1862 $USER = $DB->get_record('user', array('id'=>$userid));
1863 load_all_capabilities();
1864 $coursecontext = context_course::instance($course1->id);
1865 $this->assertFalse(has_capability('moodle/course:update', $coursecontext));
1866 $this->assertFalse(isset($USER->access['ra'][$coursecontext->path][$roleid]));
1867 load_temp_course_role($coursecontext, $roleid);
1868 $this->assertEquals($USER->access['ra'][$coursecontext->path][$roleid], $roleid);
1869 $this->assertTrue(has_capability('moodle/course:update', $coursecontext));
1870 remove_temp_course_roles($coursecontext);
1871 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
1872 load_temp_course_role($coursecontext, $roleid);
1873 reload_all_capabilities();
1874 $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid));
1875 $USER = new stdClass();
1876 $USER->id = 0;
1877
1878 // Now cross check has_capability() with get_users_by_capability(), each using different code paths,
1879 // they have to be kept in sync, usually only one of them breaks, so we know when something is wrong,
1880 // at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users)
1881 $contexts = $DB->get_records('context', array(), 'id');
1882 $contexts = array_values($contexts);
1883 $capabilities = $DB->get_records('capabilities', array(), 'id');
1884 $capabilities = array_values($capabilities);
1885 $roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']);
7514f9c2
PS
1886 $userids = array_values($testusers);
1887 $userids[] = get_admin()->id;
a3d5830a 1888
7514f9c2
PS
1889 if (!PHPUNIT_LONGTEST) {
1890 $contexts = array_slice($contexts, 0, 10);
1891 $capabilities = array_slice($capabilities, 0, 5);
1892 $userids = array_slice($userids, 0, 5);
1893 }
1894
1895 // Random time!
1896 //srand(666);
1897 foreach($userids as $userid) { // no guest or deleted
1898 // each user gets 0-10 random roles
1899 $rcount = rand(0, 10);
1900 for($j=0; $j<$rcount; $j++) {
a3d5830a
PS
1901 $roleid = $roles[rand(0, count($roles)-1)];
1902 $contextid = $contexts[rand(0, count($contexts)-1)]->id;
7514f9c2 1903 role_assign($roleid, $userid, $contextid);
a3d5830a 1904 }
a3d5830a
PS
1905 }
1906
7514f9c2
PS
1907 $permissions = array(CAP_ALLOW, CAP_PREVENT, CAP_INHERIT, CAP_PREVENT);
1908 $maxoverrides = count($contexts)*10;
1909 for($j=0; $j<$maxoverrides; $j++) {
1910 $roleid = $roles[rand(0, count($roles)-1)];
1911 $contextid = $contexts[rand(0, count($contexts)-1)]->id;
1912 $permission = $permissions[rand(0,count($permissions)-1)];
1913 $capname = $capabilities[rand(0, count($capabilities)-1)]->name;
1914 assign_capability($capname, $permission, $roleid, $contextid, true);
1915 }
1916 unset($permissions);
1917 unset($roles);
1918
1919 accesslib_clear_all_caches(false); // must be done after assign_capability()
1920
1921 // Test time - let's set up some real user, just in case the logic for USER affects the others...
1922 $USER = $DB->get_record('user', array('id'=>$testusers[3]));
1923 load_all_capabilities();
1924
1925 $userids[] = $CFG->siteguest;
1926 $userids[] = 0; // not-logged-in user
1927 $userids[] = -1; // non-existent user
1928
a3d5830a
PS
1929 foreach ($contexts as $crecord) {
1930 $context = context::instance_by_id($crecord->id);
1931 if ($coursecontext = $context->get_course_context(false)) {
1932 $enrolled = get_enrolled_users($context);
1933 } else {
1934 $enrolled = array();
1935 }
1936 foreach ($capabilities as $cap) {
1937 $allowed = get_users_by_capability($context, $cap->name, 'u.id, u.username');
1938 if ($enrolled) {
1939 $enrolledwithcap = get_enrolled_users($context, $cap->name);
1940 } else {
1941 $enrolledwithcap = array();
1942 }
7514f9c2 1943 foreach ($userids as $userid) {
a3d5830a
PS
1944 if ($userid == 0 or isguestuser($userid)) {
1945 if ($userid == 0) {
1946 $CFG->forcelogin = true;
1947 $this->assertFalse(has_capability($cap->name, $context, $userid));
1948 unset($CFG->forcelogin);
1949 }
1950 if (($cap->captype === 'write') or ($cap->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS))) {
1951 $this->assertFalse(has_capability($cap->name, $context, $userid));
1952 }
1953 $this->assertFalse(isset($allowed[$userid]));
1954 } else {
1955 if (is_siteadmin($userid)) {
1956 $this->assertTrue(has_capability($cap->name, $context, $userid, true));
1957 }
1958 $hascap = has_capability($cap->name, $context, $userid, false);
1959 $this->assertSame($hascap, isset($allowed[$userid]), "Capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
1960 if (isset($enrolled[$userid])) {
1961 $this->assertSame(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:$userid, context:$context->id, $cap->name, hascap: ".(int)$hascap." ");
1962 }
1963 }
1964 }
1965 }
1966 }
1967 // Back to nobody
1968 $USER = new stdClass();
1969 $USER->id = 0;
1970 unset($contexts);
7514f9c2 1971 unset($userids);
a3d5830a
PS
1972 unset($capabilities);
1973
1974 // Now let's do all the remaining tests that break our carefully prepared fake site
1975
1976
1977
1978 // ======= $context->mark_dirty() =======================================
1979
1980 $DB->delete_records('cache_flags', array());
1981 accesslib_clear_all_caches(false);
1982 $systemcontext->mark_dirty();
1983 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
1984 $this->assertTrue(isset($dirty[$systemcontext->path]));
1985 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$systemcontext->path]));
1986
1987
1988 // ======= $context->reload_if_dirty(); =================================
1989
1990 $DB->delete_records('cache_flags', array());
1991 accesslib_clear_all_caches(false);
1992 load_all_capabilities();
1993 $context = context_course::instance($testcourses[2]);
1994 $page = $DB->get_record('page', array('course'=>$testcourses[2]));
877b243f
TH
1995 $pagecm = get_coursemodule_from_instance('page', $page->id);
1996 $pagecontext = context_module::instance($pagecm->id);
a3d5830a
PS
1997
1998 $context->mark_dirty();
1999 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
2000 $USER->access['test'] = true;
2001 $context->reload_if_dirty();
2002 $this->assertFalse(isset($USER->access['test']));
2003
2004 $context->mark_dirty();
2005 $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path]));
2006 $USER->access['test'] = true;
2007 $pagecontext->reload_if_dirty();
2008 $this->assertFalse(isset($USER->access['test']));
2009
2010
2011 // ======= context_helper::build_all_paths() ============================
2012
2013 $oldcontexts = $DB->get_records('context', array(), 'id');
2014 $DB->set_field_select('context', 'path', NULL, "contextlevel <> ".CONTEXT_SYSTEM);
2015 $DB->set_field_select('context', 'depth', 0, "contextlevel <> ".CONTEXT_SYSTEM);
2016 context_helper::build_all_paths();
2017 $newcontexts = $DB->get_records('context', array(), 'id');
2018 $this->assertEquals($oldcontexts, $newcontexts);
2019 unset($oldcontexts);
2020 unset($newcontexts);
2021
2022
2023 // ======= $context->reset_paths() ======================================
2024
2025 $context = context_course::instance($testcourses[2]);
2026 $children = $context->get_child_contexts();
2027 $context->reset_paths(false);
2028 $this->assertSame($DB->get_field('context', 'path', array('id'=>$context->id)), NULL);
2029 $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), 0);
2030 foreach ($children as $child) {
2031 $this->assertSame($DB->get_field('context', 'path', array('id'=>$child->id)), NULL);
2032 $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$child->id)), 0);
2033 }
2034 $this->assertEquals(count($children)+1, $DB->count_records('context', array('depth'=>0)));
2035 $this->assertEquals(count($children)+1, $DB->count_records('context', array('path'=>NULL)));
2036
2037 $context = context_course::instance($testcourses[2]);
2038 $context->reset_paths(true);
2039 $context = context_course::instance($testcourses[2]);
2040 $this->assertEquals($DB->get_field('context', 'path', array('id'=>$context->id)), $context->path);
2041 $this->assertEquals($DB->get_field('context', 'depth', array('id'=>$context->id)), $context->depth);
2042 $this->assertEquals(0, $DB->count_records('context', array('depth'=>0)));
2043 $this->assertEquals(0, $DB->count_records('context', array('path'=>NULL)));
2044
2045
2046 // ====== $context->update_moved(); ======================================
2047
2048 accesslib_clear_all_caches(false);
2049 $DB->delete_records('cache_flags', array());
2050 $course = $DB->get_record('course', array('id'=>$testcourses[0]));
2051 $context = context_course::instance($course->id);
2052 $oldpath = $context->path;
2053 $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
2054 $categorycontext = context_coursecat::instance($miscid);
2055 $course->category = $miscid;
2056 $DB->update_record('course', $course);
2057 $context->update_moved($categorycontext);
2058
2059 $context = context_course::instance($course->id);
2060 $this->assertEquals($context->get_parent_context(), $categorycontext);
2061 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2062 $this->assertTrue(isset($dirty[$oldpath]));
2063 $this->assertTrue(isset($dirty[$context->path]));
2064
2065
2066 // ====== $context->delete_content() =====================================
2067
2068 context_helper::reset_caches();
2069 $context = context_module::instance($testpages[3]);
2070 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
2071 $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2072 $context->delete_content();
2073 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
2074 $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2075
2076
2077 // ====== $context->delete() =============================
2078
2079 context_helper::reset_caches();
2080 $context = context_module::instance($testpages[4]);
2081 $this->assertTrue($DB->record_exists('context', array('id'=>$context->id)));
2082 $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2083 $bi = $DB->get_record('block_instances', array('parentcontextid'=>$context->id));
2084 $bicontext = context_block::instance($bi->id);
2085 $DB->delete_records('cache_flags', array());
2086 $context->delete(); // should delete also linked blocks
2087 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2088 $this->assertTrue(isset($dirty[$context->path]));
2089 $this->assertFalse($DB->record_exists('context', array('id'=>$context->id)));
2090 $this->assertFalse($DB->record_exists('context', array('id'=>$bicontext->id)));
2091 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_MODULE, 'instanceid'=>$testpages[4])));
2092 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK, 'instanceid'=>$bi->id)));
2093 $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid'=>$context->id)));
2094 context_module::instance($testpages[4]);
2095
2096
2097 // ====== context_helper::delete_instance() =============================
2098
2099 context_helper::reset_caches();
2100 $lastcourse = array_pop($testcourses);
2101 $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
2102 $coursecontext = context_course::instance($lastcourse);
2103 $this->assertEquals(context_inspection::test_context_cache_size(), 1);
2104 $this->assertFalse($coursecontext->instanceid == CONTEXT_COURSE);
2105 $DB->delete_records('cache_flags', array());
2106 context_helper::delete_instance(CONTEXT_COURSE, $lastcourse);
2107 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2108 $this->assertTrue(isset($dirty[$coursecontext->path]));
2109 $this->assertEquals(context_inspection::test_context_cache_size(), 0);
2110 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$lastcourse)));
2111 context_course::instance($lastcourse);
2112
2113
2114 // ======= context_helper::create_instances() ==========================
2115
2116 $prevcount = $DB->count_records('context');
2117 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
2118 context_helper::create_instances(null, true);
2119 $this->assertSame($DB->count_records('context'), $prevcount);
2120 $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
2121 $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
2122
2123 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
2124 $DB->delete_records('block_instances', array());
2125 $prevcount = $DB->count_records('context');
2126 $DB->delete_records_select('context', 'contextlevel <> '.CONTEXT_SYSTEM);
2127 context_helper::create_instances(null, true);
2128 $this->assertSame($DB->count_records('context'), $prevcount);
2129 $this->assertEquals($DB->count_records('context', array('depth'=>0)), 0);
2130 $this->assertEquals($DB->count_records('context', array('path'=>NULL)), 0);
2131
2132
2133 // ======= context_helper::cleanup_instances() ==========================
2134
2135 $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
2136 $DB->delete_records('course', array('id'=>$lastcourse));
2137 $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
2138 $DB->delete_records('course_categories', array('id'=>$lastcategory));
2139 $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
2140 $DB->delete_records('user', array('id'=>$lastuser));
2141 $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
2142 $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
2143 context_helper::cleanup_instances();
2144 $count = 1; //system
2145 $count += $DB->count_records('user', array('deleted'=>0));
2146 $count += $DB->count_records('course_categories');
2147 $count += $DB->count_records('course');
2148 $count += $DB->count_records('course_modules');
2149 $count += $DB->count_records('block_instances');
2150 $this->assertEquals($DB->count_records('context'), $count);
2151
2152
2153 // ======= context cache size restrictions ==============================
2154
2155 $testusers= array();
2156 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
2157 $user = $generator->create_user();
2158 $testusers[$i] = $user->id;
2159 }
2160 context_helper::create_instances(null, true);
2161 context_helper::reset_caches();
2162 for ($i=0; $i<CONTEXT_CACHE_MAX_SIZE + 100; $i++) {
2163 context_user::instance($testusers[$i]);
2164 if ($i == CONTEXT_CACHE_MAX_SIZE - 1) {
2165 $this->assertEquals(context_inspection::test_context_cache_size(), CONTEXT_CACHE_MAX_SIZE);
2166 } else if ($i == CONTEXT_CACHE_MAX_SIZE) {
2167 // once the limit is reached roughly 1/3 of records should be removed from cache
2168 $this->assertEquals(context_inspection::test_context_cache_size(), (int)(CONTEXT_CACHE_MAX_SIZE * (2/3) +102));
2169 }
2170 }
2171 // We keep the first 100 cached
2172 $prevsize = context_inspection::test_context_cache_size();
2173 for ($i=0; $i<100; $i++) {
2174 context_user::instance($testusers[$i]);
2175 $this->assertEquals(context_inspection::test_context_cache_size(), $prevsize);
2176 }
2177 context_user::instance($testusers[102]);
2178 $this->assertEquals(context_inspection::test_context_cache_size(), $prevsize+1);
2179 unset($testusers);
2180
2181
2182
2183 // =================================================================
2184 // ======= basic test of legacy functions ==========================
2185 // =================================================================
2186 // note: watch out, the fake site might be pretty borked already
2187
2188 $this->assertSame(get_system_context(), context_system::instance());
2189
2190 foreach ($DB->get_records('context') as $contextid=>$record) {
2191 $context = context::instance_by_id($contextid);
2192 $this->assertSame(get_context_instance_by_id($contextid), $context);
2193 $this->assertSame(get_context_instance($record->contextlevel, $record->instanceid), $context);
2194 $this->assertSame(get_parent_contexts($context), $context->get_parent_context_ids());
2195 if ($context->id == SYSCONTEXTID) {
2196 $this->assertSame(get_parent_contextid($context), false);
2197 } else {
2198 $this->assertSame(get_parent_contextid($context), $context->get_parent_context()->id);
2199 }
2200 }
2201
2202 $CFG->debug = 0;
2203 $children = get_child_contexts($systemcontext);
2204 $CFG->debug = DEBUG_DEVELOPER;
2205 $this->assertEquals(count($children), $DB->count_records('context')-1);
2206 unset($children);
2207
2208 $DB->delete_records('context', array('contextlevel'=>CONTEXT_BLOCK));
2209 create_contexts();
2210 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_BLOCK)));
2211
2212 $DB->set_field('context', 'depth', 0, array('contextlevel'=>CONTEXT_BLOCK));
2213 build_context_path();
2214 $this->assertFalse($DB->record_exists('context', array('depth'=>0)));
2215
2216 $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}");
2217 $DB->delete_records('course', array('id'=>$lastcourse));
2218 $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}");
2219 $DB->delete_records('course_categories', array('id'=>$lastcategory));
2220 $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0");
2221 $DB->delete_records('user', array('id'=>$lastuser));
2222 $DB->delete_records('block_instances', array('parentcontextid'=>$frontpagepagecontext->id));
2223 $DB->delete_records('course_modules', array('id'=>$frontpagepagecontext->instanceid));
2224 cleanup_contexts();
2225 $count = 1; //system
2226 $count += $DB->count_records('user', array('deleted'=>0));
2227 $count += $DB->count_records('course_categories');
2228 $count += $DB->count_records('course');
2229 $count += $DB->count_records('course_modules');
2230 $count += $DB->count_records('block_instances');
2231 $this->assertEquals($DB->count_records('context'), $count);
2232
2233 context_helper::reset_caches();
2234 preload_course_contexts($SITE->id);
877b243f
TH
2235 $this->assertEquals(1 + $DB->count_records('course_modules', array('course' => $SITE->id)),
2236 context_inspection::test_context_cache_size());
a3d5830a
PS
2237
2238 context_helper::reset_caches();
2239 list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx');
2240 $sql = "SELECT c.id $select FROM {course_categories} c $join";
2241 $records = $DB->get_records_sql($sql);
2242 foreach ($records as $record) {
2243 context_instance_preload($record);
2244 $record = (array)$record;
2245 $this->assertEquals(1, count($record)); // only id left
2246 }
2247 $this->assertEquals(count($records), context_inspection::test_context_cache_size());
2248
2249 accesslib_clear_all_caches(true);
2250 $DB->delete_records('cache_flags', array());
2251 mark_context_dirty($systemcontext->path);
2252 $dirty = get_cache_flags('accesslib/dirtycontexts', time()-2);
2253 $this->assertTrue(isset($dirty[$systemcontext->path]));
2254
2255 accesslib_clear_all_caches(false);
2256 $DB->delete_records('cache_flags', array());
2257 $course = $DB->get_record('course', array('id'=>$testcourses[2]));
2258 $context = get_context_instance(CONTEXT_COURSE, $course->id);
2259 $oldpath = $context->path;
2260 $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}");
2261 $categorycontext = context_coursecat::instance($miscid);
2262 $course->category = $miscid;
2263 $DB->update_record('course', $course);
2264 context_moved($context, $categorycontext);
2265 $context = get_context_instance(CONTEXT_COURSE, $course->id);
2266 $this->assertEquals($context->get_parent_context(), $categorycontext);
2267
2268 $this->assertTrue($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
2269 delete_context(CONTEXT_COURSE, $testcourses[2]);
2270 $this->assertFalse($DB->record_exists('context', array('contextlevel'=>CONTEXT_COURSE, 'instanceid'=>$testcourses[2])));
2271
2272 $name = get_contextlevel_name(CONTEXT_COURSE);
2273 $this->assertFalse(empty($name));
2274
2275 $context = get_context_instance(CONTEXT_COURSE, $testcourses[2]);
2276 $name = print_context_name($context);
2277 $this->assertFalse(empty($name));
2278
2279 $url = get_context_url($coursecontext);
2280 $this->assertFalse($url instanceof modole_url);
2281
877b243f
TH
2282 $pagecm = get_coursemodule_from_instance('page', $testpages[7]);
2283 $context = get_context_instance(CONTEXT_MODULE, $pagecm->id);
a3d5830a
PS
2284 $coursecontext = get_course_context($context);
2285 $this->assertEquals($coursecontext->contextlevel, CONTEXT_COURSE);
877b243f 2286 $this->assertEquals(get_courseid_from_context($context), $pagecm->course);
a3d5830a
PS
2287
2288 $caps = fetch_context_capabilities($systemcontext);
2289 $this->assertTrue(is_array($caps));
2290 unset($caps);
2291 }
9a251f18 2292
dfa6a346
PS
2293 /**
2294 * Test updating of role capabilities during upgrade
2295 * @return void
2296 */
9a251f18
PS
2297 public function test_update_capabilities() {
2298 global $DB, $SITE;
2299
2300 $this->resetAfterTest(true);
2301
2302 $froncontext = context_course::instance($SITE->id);
2303 $student = $DB->get_record('role', array('archetype'=>'student'));
2304 $teacher = $DB->get_record('role', array('archetype'=>'teacher'));
2305
2306 $existingcaps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
2307
2308 $this->assertFalse(isset($existingcaps['moodle/site:restore'])); // moved to new 'moodle/restore:restorecourse'
2309 $this->assertTrue(isset($existingcaps['moodle/restore:restorecourse'])); // new cap from 'moodle/site:restore'
2310 $this->assertTrue(isset($existingcaps['moodle/site:sendmessage'])); // new capability
2311 $this->assertTrue(isset($existingcaps['moodle/backup:backupcourse']));
2312 $this->assertTrue(isset($existingcaps['moodle/backup:backupsection'])); // cloned from 'moodle/backup:backupcourse'
2313 $this->assertTrue(isset($existingcaps['moodle/site:approvecourse'])); // updated bitmask
2314 $this->assertTrue(isset($existingcaps['moodle/course:manageactivities']));
2315 $this->assertTrue(isset($existingcaps['mod/page:addinstance'])); // cloned from core 'moodle/course:manageactivities'
2316
2317 // fake state before upgrade
2318 $DB->set_field('capabilities', 'name', 'moodle/site:restore', array('name'=>'moodle/restore:restorecourse'));
2319 $DB->set_field('role_capabilities', 'capability', 'moodle/site:restore', array('capability'=>'moodle/restore:restorecourse'));
2320 assign_capability('moodle/site:restore', CAP_PROHIBIT, $teacher->id, $froncontext->id, true);
2321 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/site:restore', 'roleid'=>$teacher->id), 'contextid, permission', 'contextid, permission'));
2322
2323 $DB->delete_records('role_capabilities', array('capability'=>'moodle/site:sendmessage'));
2324 $DB->delete_records('capabilities', array('name'=>'moodle/site:sendmessage'));
2325
2326 $DB->delete_records('role_capabilities', array('capability'=>'moodle/backup:backupsection'));
2327 $DB->delete_records('capabilities', array('name'=>'moodle/backup:backupsection'));
2328 assign_capability('moodle/backup:backupcourse', CAP_PROHIBIT, $student->id, $froncontext->id, true);
2329 assign_capability('moodle/backup:backupcourse', CAP_ALLOW, $teacher->id, $froncontext->id, true);
2330
2331 $DB->set_field('capabilities', 'riskbitmask', 0, array('name'=>'moodle/site:approvecourse'));
2332
2333 $DB->delete_records('role_capabilities', array('capability'=>'mod/page:addinstance'));
2334 $DB->delete_records('capabilities', array('name'=>'mod/page:addinstance'));
2335 assign_capability('moodle/course:manageactivities', CAP_PROHIBIT, $student->id, $froncontext->id, true);
2336 assign_capability('moodle/course:manageactivities', CAP_ALLOW, $teacher->id, $froncontext->id, true);
2337
2338 // execute core
2339 update_capabilities('moodle');
2340
2341 // only core should be upgraded
2342 $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
2343
2344 $this->assertFalse(isset($existingcaps['moodle/site:restore']));
2345 $this->assertTrue(isset($caps['moodle/restore:restorecourse']));
2346 $this->assertEquals($existingcaps['moodle/restore:restorecourse'], $caps['moodle/restore:restorecourse']);
2347 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/restore:restorecourse', 'roleid'=>$teacher->id), 'contextid, permission', 'contextid, permission'));
2348 $this->assertEquals($perms1, $perms2);
2349
2350 $this->assertTrue(isset($caps['moodle/site:sendmessage']));
2351 $this->assertEquals($existingcaps['moodle/site:sendmessage'], $caps['moodle/site:sendmessage']);
2352
2353 $this->assertTrue(isset($caps['moodle/backup:backupsection']));
2354 $this->assertEquals($existingcaps['moodle/backup:backupsection'], $caps['moodle/backup:backupsection']);
2355 $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/backup:backupcourse', 'moodle/backup:backupsection'));
2356 foreach ($roles as $role) {
2357 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupcourse', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2358 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/backup:backupsection', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2359 $this->assertEquals($perms1, $perms2);
2360 }
2361
2362 $this->assertTrue(isset($caps['moodle/site:approvecourse']));
2363 $this->assertEquals($existingcaps['moodle/site:approvecourse'], $caps['moodle/site:approvecourse']);
2364
2365 $this->assertFalse(isset($caps['mod/page:addinstance']));
2366
2367 // execute plugin
2368 update_capabilities('mod_page');
2369 $caps = $DB->get_records('capabilities', array(), 'id', 'name, captype, contextlevel, component, riskbitmask');
2370 $this->assertTrue(isset($caps['mod/page:addinstance']));
2371 $roles = $DB->get_records_sql('SELECT DISTINCT roleid AS id FROM {role_capabilities} WHERE capability=? OR capability=?', array('moodle/course:manageactivities', 'mod/page:addinstance'));
2372 foreach ($roles as $role) {
2373 $perms1 = array_values($DB->get_records('role_capabilities', array('capability'=>'moodle/course:manageactivities', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2374 $perms2 = array_values($DB->get_records('role_capabilities', array('capability'=>'mod/page:addinstance', 'roleid'=>$role->id), 'contextid, permission', 'contextid, permission'));
2375 }
2376 $this->assertEquals($perms1, $perms2);
2377 }
a3d5830a
PS
2378}
2379