PageRenderTime 60ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

/lib/tests/accesslib_test.php

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