/** * Loads some data to be used by the different tests * @param int $s1grade Student 1 grade * @param int $s2grade Student 2 grade * @return array Course and users instances */ private function load_data($s1grade, $s2grade) { global $DB; $course = $this->getDataGenerator()->create_course(array('groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1)); $studentrole = $DB->get_record('role', array('shortname' => 'student')); $student1 = $this->getDataGenerator()->create_user(); $this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id); $student2 = $this->getDataGenerator()->create_user(); $this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id); $teacherrole = $DB->get_record('role', array('shortname' => 'teacher')); $teacher = $this->getDataGenerator()->create_user(); $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); $context = context_course::instance($course->id); assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $context); accesslib_clear_all_caches_for_unit_testing(); $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); groups_add_member($group1->id, $student1->id); groups_add_member($group1->id, $teacher->id); groups_add_member($group2->id, $student2->id); $assignment = $this->getDataGenerator()->create_module('assign', array('name' => "Test assign", 'course' => $course->id)); $modcontext = get_coursemodule_from_instance('assign', $assignment->id, $course->id); $assignment->cmidnumber = $modcontext->id; $student1grade = array('userid' => $student1->id, 'rawgrade' => $s1grade); $student2grade = array('userid' => $student2->id, 'rawgrade' => $s2grade); $studentgrades = array($student1->id => $student1grade, $student2->id => $student2grade); assign_grade_item_update($assignment, $studentgrades); return array($course, $teacher, $student1, $student2, $assignment); }
/** * Test user_get_user_details_courses */ public function test_user_get_user_details_courses() { global $DB; $this->resetAfterTest(); // Create user and modify user profile. $user1 = $this->getDataGenerator()->create_user(); $user2 = $this->getDataGenerator()->create_user(); $course1 = $this->getDataGenerator()->create_course(); $coursecontext = context_course::instance($course1->id); $teacherrole = $DB->get_record('role', array('shortname' => 'teacher')); $this->getDataGenerator()->enrol_user($user1->id, $course1->id); $this->getDataGenerator()->enrol_user($user2->id, $course1->id); role_assign($teacherrole->id, $user1->id, $coursecontext->id); role_assign($teacherrole->id, $user2->id, $coursecontext->id); accesslib_clear_all_caches_for_unit_testing(); // Get user2 details as a user with super system capabilities. $result = user_get_user_details_courses($user2); $this->assertEquals($user2->id, $result['id']); $this->assertEquals(fullname($user2), $result['fullname']); $this->assertEquals($course1->id, $result['enrolledcourses'][0]['id']); $this->setUser($user1); // Get user2 details as a user who can only see this user in a course. $result = user_get_user_details_courses($user2); $this->assertEquals($user2->id, $result['id']); $this->assertEquals(fullname($user2), $result['fullname']); $this->assertEquals($course1->id, $result['enrolledcourses'][0]['id']); }
/** * Unassign a capability to $USER * * @param string $capability capability name * @param int $contextid * @param int $roleid */ public static function unassignUserCapability($capability, $contextid, $roleid) { global $USER; unassign_capability($capability, $roleid, $contextid); accesslib_clear_all_caches_for_unit_testing(); }
protected function assign_capability($capability, $permission = CAP_ALLOW, $contextid = null) { if ($contextid === null) { $contextid = context_system::instance(); } if (is_object($contextid)) { $contextid = $contextid->id; } assign_capability($capability, $permission, $this->get_roleid($contextid), $contextid, true); accesslib_clear_all_caches_for_unit_testing(); }
/** * Create a role with capabilities and permissions. * * @param string|array $caps Capability names. * @param int $perm Constant CAP_* to apply to the capabilities. * @return int The new role ID. */ protected function create_role_with_caps($caps, $perm) { $caps = (array) $caps; $dg = $this->getDataGenerator(); $roleid = $dg->create_role(); foreach ($caps as $cap) { assign_capability($cap, $perm, $roleid, context_system::instance()->id, true); } accesslib_clear_all_caches_for_unit_testing(); return $roleid; }
/** * Test load_users method. */ public function test_load_users() { global $DB; $this->setAdminUser(); $this->resetAfterTest(true); $roleteacher = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST); // Create a course, users and groups. $course = $this->getDataGenerator()->create_course(); $coursecontext = context_course::instance($course->id); $group = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); $teacher = $this->getDataGenerator()->create_user(); $user1 = $this->getDataGenerator()->create_user(); $user2 = $this->getDataGenerator()->create_user(); $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $roleteacher->id); $this->getDataGenerator()->enrol_user($user1->id, $course->id); $this->getDataGenerator()->enrol_user($user2->id, $course->id); $this->getDataGenerator()->create_group_member(array('groupid' => $group->id, 'userid' => $teacher->id)); $this->getDataGenerator()->create_group_member(array('groupid' => $group->id, 'userid' => $user1->id)); $this->getDataGenerator()->create_group_member(array('groupid' => $group->id, 'userid' => $user2->id)); // Perform a regrade before creating the report. grade_regrade_final_grades($course->id); $screentest = new gradereport_singleview_screen_testable($course->id, 0, $group->id); $groupusers = $screentest->test_load_users(); $this->assertCount(2, $groupusers); // Now, let's suspend the enrolment of a user. Should return only one user. $this->getDataGenerator()->enrol_user($user2->id, $course->id, $roleteacher->id, 'manual', 0, 0, ENROL_USER_SUSPENDED); $users = $screentest->test_load_users(); $this->assertCount(1, $users); // Change the viewsuspendedusers capabilities and set the user preference to display suspended users. assign_capability('moodle/course:viewsuspendedusers', CAP_ALLOW, $roleteacher->id, $coursecontext, true); set_user_preference('grade_report_showonlyactiveenrol', false, $teacher); accesslib_clear_all_caches_for_unit_testing(); $this->setUser($teacher); $screentest = new gradereport_singleview_screen_testable($course->id, 0, $group->id); $users = $screentest->test_load_users(); $this->assertCount(2, $users); // Change the capability again, now the user can't see the suspended enrolments. assign_capability('moodle/course:viewsuspendedusers', CAP_PROHIBIT, $roleteacher->id, $coursecontext, true); set_user_preference('grade_report_showonlyactiveenrol', false, $teacher); accesslib_clear_all_caches_for_unit_testing(); $users = $screentest->test_load_users(); $this->assertCount(1, $users); // Now, activate the user enrolment again. We shall get 2 users now. $this->getDataGenerator()->enrol_user($user2->id, $course->id, $roleteacher->id, 'manual', 0, 0, ENROL_USER_ACTIVE); $users = $screentest->test_load_users(); $this->assertCount(2, $users); }
public function setUp() { global $CFG; parent::setUp(); foreach ($this->testtables as $dir => $tables) { $this->create_test_tables($tables, $dir); // Create tables } $this->switch_to_test_db(); // Switch to test DB for all the execution // Nasty hack, recreate the system context record (the accesslib API does not allow to create it easily) $this->create_system_context_record(); // Reset all caches accesslib_clear_all_caches_for_unit_testing(); $this->syscontext = get_context_instance(CONTEXT_SYSTEM); $this->fill_records(); // Ignore any frontpageroleid, that would require to crete more contexts $this->originaldefaultfrontpageroleid = $CFG->defaultfrontpageroleid; $CFG->defaultfrontpageroleid = null; }
/** * Test get_calendar_events */ public function test_get_calendar_events() { global $DB, $USER; $this->resetAfterTest(true); $this->setAdminUser(); // Create a few stuff to test with. $user = $this->getDataGenerator()->create_user(); $course = $this->getDataGenerator()->create_course(); $record = new stdClass(); $record->courseid = $course->id; $group = $this->getDataGenerator()->create_group($record); $beforecount = $DB->count_records('event'); // Let's create a few events. $siteevent = $this->create_calendar_event('site', $USER->id, 'site'); $record = new stdClass(); $record->courseid = $course->id; $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 2, time(), $record); $userevent = $this->create_calendar_event('user', $USER->id); $record = new stdClass(); $record->courseid = $course->id; $record->groupid = $group->id; $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record); $paramevents = array('eventids' => array($siteevent->id), 'courseids' => array($course->id), 'groupids' => array($group->id)); $options = array('siteevents' => true, 'userevents' => true); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); // Check to see if we got all events. $this->assertEquals(5, count($events['events'])); $this->assertEquals(0, count($events['warnings'])); $options = array('siteevents' => true, 'userevents' => true, 'timeend' => time() + 7 * WEEKSECS); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(5, count($events['events'])); $this->assertEquals(0, count($events['warnings'])); // Let's play around with caps. $this->setUser($user); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(2, count($events['events'])); // site, user. $this->assertEquals(2, count($events['warnings'])); // course, group. $role = $DB->get_record('role', array('shortname' => 'student')); $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(4, count($events['events'])); // site, user, both course events. $this->assertEquals(1, count($events['warnings'])); // group. $options = array('siteevents' => true, 'userevents' => true, 'timeend' => time() + HOURSECS); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(3, count($events['events'])); // site, user, one course event. $this->assertEquals(1, count($events['warnings'])); // group. groups_add_member($group, $user); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(4, count($events['events'])); // site, user, group, one course event. $this->assertEquals(0, count($events['warnings'])); $paramevents = array('courseids' => array($course->id), 'groupids' => array($group->id)); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(4, count($events['events'])); // site, user, group, one course event. $this->assertEquals(0, count($events['warnings'])); $paramevents = array('groupids' => array($group->id, 23)); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(3, count($events['events'])); // site, user, group. $this->assertEquals(1, count($events['warnings'])); $paramevents = array('courseids' => array(23)); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(2, count($events['events'])); // site, user. $this->assertEquals(1, count($events['warnings'])); $paramevents = array(); $options = array('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7 * WEEKSECS); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(0, count($events['events'])); // nothing returned. $this->assertEquals(0, count($events['warnings'])); $paramevents = array('eventids' => array($siteevent->id, $groupevent->id)); $options = array('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7 * WEEKSECS); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(2, count($events['events'])); // site, group. $this->assertEquals(0, count($events['warnings'])); $paramevents = array('eventids' => array($siteevent->id)); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(1, count($events['events'])); // site. $this->assertEquals(0, count($events['warnings'])); // Try getting a course event by its id. $paramevents = array('eventids' => array($courseevent->id)); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(1, count($events['events'])); $this->assertEquals(0, count($events['warnings'])); // Now, create an activity event. $this->setAdminUser(); $nexttime = time() + DAYSECS; $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'duedate' => $nexttime)); $this->setUser($user); $paramevents = array('courseids' => array($course->id)); $options = array('siteevents' => true, 'userevents' => true, 'timeend' => time() + WEEKSECS); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertCount(5, $events['events']); // Hide the assignment. set_coursemodule_visible($assign->cmid, 0); // Empty all the caches that may be affected by this change. accesslib_clear_all_caches_for_unit_testing(); course_modinfo::clear_instance_cache(); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); // Expect one less. $this->assertCount(4, $events['events']); }
/** * Testing can_edit_submission */ public function test_can_edit_submission() { global $PAGE, $DB; $this->create_extra_users(); $this->setAdminUser(); // Create assignment (onlinetext). $assign = $this->create_instance(array('assignsubmission_onlinetext_enabled' => 1, 'submissiondrafts' => 1)); $PAGE->set_url(new moodle_url('/mod/assign/view.php', array('id' => $assign->get_course_module()->id))); // Check student can edit their own submission. $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->students[0]->id)); // Check student cannot edit others submission. $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->students[1]->id)); // Check teacher cannot (by default) edit a students submission. $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id)); // Add the required capability to edit a student submission. $roleid = create_role('Dummy role', 'dummyrole', 'dummy role description'); assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id); role_assign($roleid, $this->teachers[0]->id, $assign->get_context()->id); accesslib_clear_all_caches_for_unit_testing(); // Retest - should now have access. $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->teachers[0]->id)); // Force create an assignment with SEPARATEGROUPS. $data = new stdClass(); $data->courseid = $this->course->id; $data->name = 'Grouping'; $groupingid = groups_create_grouping($data); groups_assign_grouping($groupingid, $this->groups[0]->id); groups_assign_grouping($groupingid, $this->groups[1]->id); $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS)); // Add the capability to the new assignment for extra students 0 and 1. assign_capability('mod/assign:editothersubmission', CAP_ALLOW, $roleid, $assign->get_context()->id); role_assign($roleid, $this->extrastudents[0]->id, $assign->get_context()->id); role_assign($roleid, $this->extrastudents[1]->id, $assign->get_context()->id); accesslib_clear_all_caches_for_unit_testing(); // Verify the extra student does not have the capability to edit a submission not in their group. $this->assertFalse($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[1]->id)); // Verify the extra student does have the capability to edit a submission in their group. $this->assertTrue($assign->can_edit_submission($this->students[0]->id, $this->extrastudents[0]->id)); }
/** * Test view_book */ public function test_view_book() { global $DB; $this->resetAfterTest(true); $this->setAdminUser(); // Setup test data. $course = $this->getDataGenerator()->create_course(); $book = $this->getDataGenerator()->create_module('book', array('course' => $course->id)); $bookgenerator = $this->getDataGenerator()->get_plugin_generator('mod_book'); $chapter = $bookgenerator->create_chapter(array('bookid' => $book->id)); $chapterhidden = $bookgenerator->create_chapter(array('bookid' => $book->id, 'hidden' => 1)); $context = context_module::instance($book->cmid); $cm = get_coursemodule_from_instance('book', $book->id); // Test invalid instance id. try { mod_book_external::view_book(0); $this->fail('Exception expected due to invalid mod_book instance id.'); } catch (moodle_exception $e) { $this->assertEquals('invalidrecord', $e->errorcode); } // Test not-enrolled user. $user = self::getDataGenerator()->create_user(); $this->setUser($user); try { mod_book_external::view_book($book->id, 0); $this->fail('Exception expected due to not enrolled user.'); } catch (moodle_exception $e) { $this->assertEquals('requireloginerror', $e->errorcode); } // Test user with full capabilities. $studentrole = $DB->get_record('role', array('shortname' => 'student')); $this->getDataGenerator()->enrol_user($user->id, $course->id, $studentrole->id); // Trigger and capture the event. $sink = $this->redirectEvents(); $result = mod_book_external::view_book($book->id, 0); $result = external_api::clean_returnvalue(mod_book_external::view_book_returns(), $result); $events = $sink->get_events(); $this->assertCount(2, $events); $event = array_shift($events); // Checking that the event contains the expected values. $this->assertInstanceOf('\mod_book\event\course_module_viewed', $event); $this->assertEquals($context, $event->get_context()); $moodleurl = new \moodle_url('/mod/book/view.php', array('id' => $cm->id)); $this->assertEquals($moodleurl, $event->get_url()); $this->assertEventContextNotUsed($event); $this->assertNotEmpty($event->get_name()); $event = array_shift($events); $this->assertInstanceOf('\mod_book\event\chapter_viewed', $event); $this->assertEquals($chapter->id, $event->objectid); $result = mod_book_external::view_book($book->id, $chapter->id); $result = external_api::clean_returnvalue(mod_book_external::view_book_returns(), $result); $events = $sink->get_events(); // We expect a total of 3 events. $this->assertCount(3, $events); // Try to view a hidden chapter. try { mod_book_external::view_book($book->id, $chapterhidden->id); $this->fail('Exception expected due to missing capability.'); } catch (moodle_exception $e) { $this->assertEquals('errorchapter', $e->errorcode); } // Test user with no capabilities. // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles. assign_capability('mod/book:read', CAP_PROHIBIT, $studentrole->id, $context->id); accesslib_clear_all_caches_for_unit_testing(); try { mod_book_external::view_book($book->id, 0); $this->fail('Exception expected due to missing capability.'); } catch (moodle_exception $e) { $this->assertEquals('nopermissions', $e->errorcode); } }
public function get_enrolled_users_with_capability_setup($capability) { global $USER, $DB; $this->resetAfterTest(true); $return = new stdClass(); // Create the course and fetch its context. $return->course = self::getDataGenerator()->create_course(); $context = context_course::instance($return->course->id); // Create one teacher, and two students. $return->teacher = self::getDataGenerator()->create_user(); $return->student1 = self::getDataGenerator()->create_user(); $return->student2 = self::getDataGenerator()->create_user(); // Create a new student role based on the student archetype but with the capability prohibitted. $fakestudentroleid = create_role('Fake student role', 'fakestudent', 'Fake student role', 'student'); assign_capability($capability, CAP_PROHIBIT, $fakestudentroleid, $context->id); // Enrol all of the users in the course. // * 'teacher' is an editing teacher. // * 'student1' is a standard student. // * 'student2' is a student with the capability prohibitted. $editingteacherroleid = $DB->get_field('role', 'id', array('shortname' => 'editingteacher')); $studentroleid = $DB->get_field('role', 'id', array('shortname' => 'student')); $this->getDataGenerator()->enrol_user($return->teacher->id, $return->course->id, $editingteacherroleid); $this->getDataGenerator()->enrol_user($return->student1->id, $return->course->id, $studentroleid); $this->getDataGenerator()->enrol_user($return->student2->id, $return->course->id, $fakestudentroleid); // Log in as the teacher. $this->setUser($return->teacher); // Clear caches. accesslib_clear_all_caches_for_unit_testing(); return $return; }
/** * Test submit_answers */ public function test_submit_answers() { global $DB; // Test user with full capabilities. $this->setUser($this->student); // Build our questions and responses array. $realquestions = array(); $questions = survey_get_questions($this->survey); $i = 5; foreach ($questions as $q) { if ($q->type >= 0) { if ($q->multi) { $subquestions = survey_get_subquestions($q); foreach ($subquestions as $sq) { $realquestions[] = array('key' => 'q' . $sq->id, 'value' => $i % 5 + 1); $i++; } } else { $realquestions[] = array('key' => 'q' . $q->id, 'value' => $i % 5 + 1); $i++; } } } $result = mod_survey_external::submit_answers($this->survey->id, $realquestions); $result = external_api::clean_returnvalue(mod_survey_external::submit_answers_returns(), $result); $this->assertTrue($result['status']); $this->assertCount(0, $result['warnings']); $dbanswers = $DB->get_records_menu('survey_answers', array('survey' => $this->survey->id), '', 'question, answer1'); foreach ($realquestions as $q) { $id = str_replace('q', '', $q['key']); $this->assertEquals($q['value'], $dbanswers[$id]); } // Submit again, we expect an error here. try { mod_survey_external::submit_answers($this->survey->id, $realquestions); $this->fail('Exception expected due to answers already submitted.'); } catch (moodle_exception $e) { $this->assertEquals('alreadysubmitted', $e->errorcode); } // Test user with no capabilities. // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles. assign_capability('mod/survey:participate', CAP_PROHIBIT, $this->studentrole->id, $this->context->id); accesslib_clear_all_caches_for_unit_testing(); try { mod_survey_external::submit_answers($this->survey->id, $realquestions); $this->fail('Exception expected due to missing capability.'); } catch (moodle_exception $e) { $this->assertEquals('nopermissions', $e->errorcode); } // Test not-enrolled user. $usernotenrolled = self::getDataGenerator()->create_user(); $this->setUser($usernotenrolled); try { mod_survey_external::submit_answers($this->survey->id, $realquestions); $this->fail('Exception expected due to not enrolled user.'); } catch (moodle_exception $e) { $this->assertEquals('requireloginerror', $e->errorcode); } }
/** * Test validate_attempt */ public function test_validate_attempt() { global $DB; // Create a new quiz with one attempt started. list($quiz, $context, $quizobj, $attempt, $attemptobj) = $this->create_quiz_with_questions(true); $this->setUser($this->student); // Invalid attempt. try { $params = array('attemptid' => -1, 'page' => 0); testable_mod_quiz_external::validate_attempt($params); $this->fail('Exception expected due to invalid attempt id.'); } catch (dml_missing_record_exception $e) { $this->assertEquals('invalidrecord', $e->errorcode); } // Test OK case. $params = array('attemptid' => $attempt->id, 'page' => 0); $result = testable_mod_quiz_external::validate_attempt($params); $this->assertEquals($attempt->id, $result[0]->get_attempt()->id); $this->assertEquals([], $result[1]); // Test with preflight data. $quiz->password = '******'; $DB->update_record('quiz', $quiz); try { $params = array('attemptid' => $attempt->id, 'page' => 0, 'preflightdata' => array(array("name" => "quizpassword", "value" => 'bad'))); testable_mod_quiz_external::validate_attempt($params); $this->fail('Exception expected due to invalid passwod.'); } catch (moodle_exception $e) { $this->assertEquals(get_string('passworderror', 'quizaccess_password'), $e->errorcode); } // Now, try everything correct. $params['preflightdata'][0]['value'] = 'abc'; $result = testable_mod_quiz_external::validate_attempt($params); $this->assertEquals($attempt->id, $result[0]->get_attempt()->id); $this->assertEquals([], $result[1]); // Page out of range. $DB->update_record('quiz', $quiz); $params['page'] = 4; try { testable_mod_quiz_external::validate_attempt($params); $this->fail('Exception expected due to page out of range.'); } catch (moodle_quiz_exception $e) { $this->assertEquals('Invalid page number', $e->errorcode); } $params['page'] = 0; // Try to open attempt in closed quiz. $quiz->timeopen = time() - WEEKSECS; $quiz->timeclose = time() - DAYSECS; $DB->update_record('quiz', $quiz); // This should work, ommit access rules. testable_mod_quiz_external::validate_attempt($params, false); // Get a generic error because prior to checking the dates the attempt is closed. try { testable_mod_quiz_external::validate_attempt($params); $this->fail('Exception expected due to passed dates.'); } catch (moodle_quiz_exception $e) { $this->assertEquals('attempterror', $e->errorcode); } // Finish the attempt. $attemptobj = quiz_attempt::create($attempt->id); $attemptobj->process_finish(time(), false); try { testable_mod_quiz_external::validate_attempt($params, false); $this->fail('Exception expected due to attempt finished.'); } catch (moodle_quiz_exception $e) { $this->assertEquals('attemptalreadyclosed', $e->errorcode); } // Test user with no capabilities. // We need a explicit prohibit since this capability is only defined in authenticated user and guest roles. assign_capability('mod/quiz:attempt', CAP_PROHIBIT, $this->studentrole->id, $context->id); // Empty all the caches that may be affected by this change. accesslib_clear_all_caches_for_unit_testing(); course_modinfo::clear_instance_cache(); try { testable_mod_quiz_external::validate_attempt($params); $this->fail('Exception expected due to missing permissions.'); } catch (required_capability_exception $e) { $this->assertEquals('nopermissions', $e->errorcode); } // Now try with a different user. $this->setUser($this->teacher); $params['page'] = 0; try { testable_mod_quiz_external::validate_attempt($params); $this->fail('Exception expected due to not your attempt.'); } catch (moodle_quiz_exception $e) { $this->assertEquals('notyourattempt', $e->errorcode); } }
function test_get_switchable_roles() { global $USER; $tablenames = array('role', 'role_capabilities', 'role_assignments', 'role_allow_switch', 'capabilities', 'context', 'role_names'); $this->create_test_tables($tablenames, 'lib'); $this->switch_to_test_db(); $this->switch_to_test_cfg(); // Ensure SYSCONTEXTID is set. get_context_instance(CONTEXT_SYSTEM); $contexts = $this->load_test_data('context', array('contextlevel', 'instanceid', 'path', 'depth'), array('sys' => array(CONTEXT_SYSTEM, 0, '/' . SYSCONTEXTID, 1), 'cat' => array(CONTEXT_COURSECAT, 66, '/' . SYSCONTEXTID . '/' . (SYSCONTEXTID + 1), 2), 'cou' => array(CONTEXT_COURSE, 666, '/' . SYSCONTEXTID . '/' . (SYSCONTEXTID + 1) . '/' . (SYSCONTEXTID + 2), 3), 'fp' => array(CONTEXT_COURSE, SITEID, '/' . SYSCONTEXTID . '/' . SITEID, 2))); $this->testdb->set_field('context', 'id', SYSCONTEXTID, array('id' => $contexts['sys']->id)); $this->testdb->set_field('context', 'id', SYSCONTEXTID + 1, array('id' => $contexts['cat']->id)); $this->testdb->set_field('context', 'id', SYSCONTEXTID + 2, array('id' => $contexts['cou']->id)); $syscontext = $contexts['sys']; $syscontext->id = SYSCONTEXTID; $context = $contexts['cou']; $context->id = SYSCONTEXTID + 2; $roles = $this->load_test_data('role', array('name', 'shortname', 'description', 'sortorder'), array('r1' => array('r1', 'r1', 'not null', 2), 'r2' => array('r2', 'r2', 'not null', 3), 'funny' => array('funny', 'funny', 'not null', 4))); $r1id = $roles['r1']->id; $r2id = $roles['r2']->id; $funnyid = $roles['funny']->id; // strange role // Note that get_switchable_roles requires at least one capability for // each role. I am not really clear why it was implemented that way // but this makes the test work. $roles = $this->load_test_data('role_capabilities', array('roleid', 'capability'), array(array($r1id, 'moodle/say:hello'), array($r2id, 'moodle/say:hello'), array($funnyid, 'moodle/say:hello'))); $this->load_test_data('role_assignments', array('userid', 'contextid', 'roleid'), array(array(2, SYSCONTEXTID + 1, $r1id), array(3, SYSCONTEXTID + 2, $r2id))); $this->load_test_data('role_allow_switch', array('roleid', 'allowswitch'), array(array($r1id, $r2id), array($r2id, $r1id), array($r2id, $r2id), array($r2id, $funnyid))); // r1 should be able to switch to r2, but this user only has r1 in $context, not $syscontext. $this->switch_global_user_id(2); accesslib_clear_all_caches_for_unit_testing(); $this->assert(new ArraysHaveSameValuesExpectation(array()), array_keys(get_switchable_roles($syscontext))); $this->assert(new ArraysHaveSameValuesExpectation(array($r2id)), array_keys(get_switchable_roles($context))); $this->revert_global_user_id(); // The table says r2 should be able to switch to all of r1, r2 and funny; // this used to be restricted further beyond the switch table (for example // to prevent you switching to roles with doanything) but is not any more // (for example because doanything does not exist). $this->switch_global_user_id(3); accesslib_clear_all_caches_for_unit_testing(); $this->assert(new ArraysHaveSameValuesExpectation(array()), array_keys(get_switchable_roles($syscontext))); $this->assert(new ArraysHaveSameValuesExpectation(array($r2id, $r1id, $funnyid)), array_keys(get_switchable_roles($context))); }
public function setUp() { parent::setUp(); // Make sure accesslib has cached a sensible system context object // before we switch to the test DB. $this->syscontext = get_context_instance(CONTEXT_SYSTEM); // Create the table we need and switch to test DB. $this->create_test_tables(array('filter_active', 'filter_config', 'context', 'course', 'course_categories', 'course_modules', 'modules', 'course_sections', 'course_modules_availability', 'grade_items', 'cache_text'), 'lib'); $this->create_test_tables(array('label'), 'mod/label'); $this->switch_to_test_db(); // Nasty hack, recreate the system context record (the accesslib API does not allow to create it easily) $this->create_system_context_record(); // Reset all caches accesslib_clear_all_caches_for_unit_testing(); $this->syscontext = get_context_instance(CONTEXT_SYSTEM); // Make the category $cat = new stdClass(); $cat->name = 'testcategory'; $cat->parent = 0; $cat->depth = 1; $cat->sortorder = 100; $cat->timemodified = time(); $catid = $this->testdb->insert_record('course_categories', $cat); $this->testdb->set_field('course_categories', 'path', '/' . $catid, array('id' => $catid)); $this->catcontext = context_coursecat::instance($catid); // Make the course $course = (object) array('shortname' => 'TEST101'); $courseid = $this->testdb->insert_record('course', $course); $this->coursecontext = context_course::instance($courseid); // Set up section $section = (object) array('course' => $courseid); $section->id = $this->testdb->insert_record('course_sections', $section); // Make course-modules $mod = (object) array('name' => 'label', 'visible' => 1); $mod->id = $this->testdb->insert_record('modules', $mod); $label1 = (object) array('course' => $courseid, 'intro' => 'Intro 1', 'name' => 'Label 1'); $label1->id = $this->testdb->insert_record('label', $label1); $cm1 = (object) array('course' => $courseid, 'section' => $section->id, 'module' => $mod->id, 'instance' => $label1->id); $cm1->id = $this->testdb->insert_record('course_modules', $cm1); $this->activity1context = context_module::instance($cm1->id); $label2 = (object) array('course' => $courseid, 'intro' => 'Intro 2', 'name' => 'Label 2'); $label2->id = $this->testdb->insert_record('label', $label2); $cm2 = (object) array('course' => $courseid, 'section' => $section->id, 'module' => $mod->id, 'instance' => $label2->id); $cm2->id = $this->testdb->insert_record('course_modules', $cm2); $this->testdb->set_field('course_sections', 'sequence', "{$cm1->id},{$cm2->id}", array('id' => $section->id)); $this->activity2context = context_module::instance($cm2->id); }
/** * Tests grade_report_user::inject_rowspans() * * inject_rowspans() returns the count of the number of elements, sets maxdepth on the * report object and sets the rowspan property on any element that has children. */ public function test_inject_rowspans() { global $CFG, $USER, $DB; parent::setUp(); $this->resetAfterTest(true); $CFG->enableavailability = 1; $CFG->enablecompletion = 1; // Create a course. $course = $this->getDataGenerator()->create_course(); $coursecategory = grade_category::fetch_course_category($course->id); $coursecontext = context_course::instance($course->id); // Create and enrol test users. $student = $this->getDataGenerator()->create_user(array('username' => 'Student Sam')); $role = $DB->get_record('role', array('shortname' => 'student'), '*', MUST_EXIST); $this->getDataGenerator()->enrol_user($student->id, $course->id, $role->id); $teacher = $this->getDataGenerator()->create_user(array('username' => 'Teacher T')); $role = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST); $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $role->id); // An array so we can test with both users in a loop. $users = array($student, $teacher); // Make the student the current user. $this->setUser($student); // Test an empty course. $report = $this->create_report($course, $student, $coursecontext); // a lead column that spans all children + course grade item = 2 $this->assertEquals(2, $report->inject_rowspans($report->gtree->top_element)); $this->assertEquals(2, $report->gtree->top_element['rowspan']); $this->assertEquals(2, $report->maxdepth); // Only elements with children should have rowspan set. if (array_key_exists('rowspan', $report->gtree->top_element['children'][1])) { $this->fail('Elements without children should not have rowspan set'); } // Add 2 activities. $data1 = $this->getDataGenerator()->create_module('data', array('assessed' => 1, 'scale' => 100, 'course' => $course->id)); $forum1 = $this->getDataGenerator()->create_module('forum', array('assessed' => 1, 'scale' => 100, 'course' => $course->id)); $forum1cm = get_coursemodule_from_id('forum', $forum1->cmid); // Switch the stdClass instance for a grade item instance so grade_item::set_parent() is available. $forum1 = grade_item::fetch(array('itemtype' => 'mod', 'itemmodule' => 'forum', 'iteminstance' => $forum1->id, 'courseid' => $course->id)); $report = $this->create_report($course, $student, $coursecontext); // Lead column + course + (2 x activity) = 4 $this->assertEquals(4, $report->inject_rowspans($report->gtree->top_element)); $this->assertEquals(4, $report->gtree->top_element['rowspan']); // Lead column + 1 level (course + 2 activities) = 2 $this->assertEquals(2, $report->maxdepth); // Only elements with children should have rowspan set. if (array_key_exists('rowspan', $report->gtree->top_element['children'][1])) { $this->fail('Elements without children should not have rowspan set'); } // Hide the forum activity. set_coursemodule_visible($forum1cm->id, 0); foreach ($users as $user) { $this->setUser($user); $message = 'Testing with ' . $user->username; accesslib_clear_all_caches_for_unit_testing(); $report = $this->create_report($course, $user, $coursecontext); // Lead column + course + (2 x activity) = 4 (element count isn't affected by hiding) $this->assertEquals(4, $report->inject_rowspans($report->gtree->top_element), $message); $this->assertEquals(4, $report->gtree->top_element['rowspan'], $message); // Lead column -> 1 level containing the course + 2 activities = 2 $this->assertEquals(2, $report->maxdepth, $message); } // Unhide the forum activity. set_coursemodule_visible($forum1cm->id, 1); // Create a category and put the forum in it. $params = new stdClass(); $params->courseid = $course->id; $params->fullname = 'unittestcategory'; $params->parent = $coursecategory->id; $gradecategory = new grade_category($params, false); $gradecategory->insert(); $forum1->set_parent($gradecategory->id); $report = $this->create_report($course, $student, $coursecontext); // Lead column + course + (category + category grade item) + (2 x activity) = 6 $this->assertEquals(6, $report->inject_rowspans($report->gtree->top_element)); $this->assertEquals(6, $report->gtree->top_element['rowspan']); // Lead column -> the category -> the forum activity = 3 $this->assertEquals(3, $report->maxdepth); // Check rowspan on the category. The category itself + category grade item + forum = 3 $this->assertEquals(3, $report->gtree->top_element['children'][4]['rowspan']); // check the forum doesn't have rowspan set if (array_key_exists('rowspan', $report->gtree->top_element['children'][4]['children'][3])) { $this->fail('The forum has no children so should not have rowspan set'); } // Conditional activity tests. $DB->insert_record('course_modules_availability', (object) array('coursemoduleid' => $forum1cm->id, 'gradeitemid' => 37, 'grademin' => 5.5)); $cm = (object) array('id' => $forum1cm->id); $test = new condition_info($cm, CONDITION_MISSING_EVERYTHING); $fullcm = $test->get_full_course_module(); foreach ($users as $user) { $this->setUser($user); $message = 'Testing with ' . $user->username; accesslib_clear_all_caches_for_unit_testing(); $report = $this->create_report($course, $user, $coursecontext); // Lead column + course + (category + category grade item) + (2 x activity) = 6 $this->assertEquals(6, $report->inject_rowspans($report->gtree->top_element), $message); $this->assertEquals(6, $report->gtree->top_element['rowspan'], $message); // Lead column -> the category -> the forum activity = 3 $this->assertEquals(3, $report->maxdepth, $message); } }
/** * Testing get_shared_group_members */ public function test_get_shared_group_members() { $this->create_extra_users(); $this->setAdminUser(); // Force create an assignment with SEPARATEGROUPS. $data = new stdClass(); $data->courseid = $this->course->id; $data->name = 'Grouping'; $groupingid = groups_create_grouping($data); groups_assign_grouping($groupingid, $this->groups[0]->id); groups_assign_grouping($groupingid, $this->groups[1]->id); $assign = $this->create_instance(array('groupingid' => $groupingid, 'groupmode' => SEPARATEGROUPS)); $cm = $assign->get_course_module(); // Add the capability to access allgroups. $roleid = create_role('Access all groups role', 'accessallgroupsrole', ''); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $roleid, $assign->get_context()->id); role_assign($roleid, $this->extrastudents[3]->id, $assign->get_context()->id); accesslib_clear_all_caches_for_unit_testing(); // Get shared group members for students 0 and 1. $groupmembers = array(); $groupmembers[0] = $assign->get_shared_group_members($cm, $this->students[0]->id); $groupmembers[1] = $assign->get_shared_group_members($cm, $this->students[1]->id); // They should share groups with extrastudents 0 and 1. $this->assertTrue(in_array($this->extrastudents[0]->id, $groupmembers[0])); $this->assertFalse(in_array($this->extrastudents[0]->id, $groupmembers[1])); $this->assertTrue(in_array($this->extrastudents[1]->id, $groupmembers[1])); $this->assertFalse(in_array($this->extrastudents[1]->id, $groupmembers[0])); // Lists of group members for students and extrastudents should be the same. $this->assertEquals($groupmembers[0], $assign->get_shared_group_members($cm, $this->extrastudents[0]->id)); $this->assertEquals($groupmembers[1], $assign->get_shared_group_members($cm, $this->extrastudents[1]->id)); // Get all group members for extrastudent 3 wich can access all groups. $allgroupmembers = $assign->get_shared_group_members($cm, $this->extrastudents[3]->id); // Extrastudent 3 should see students 0 and 1, extrastudent 0 and 1. $this->assertTrue(in_array($this->students[0]->id, $allgroupmembers)); $this->assertTrue(in_array($this->students[1]->id, $allgroupmembers)); $this->assertTrue(in_array($this->extrastudents[0]->id, $allgroupmembers)); $this->assertTrue(in_array($this->extrastudents[1]->id, $allgroupmembers)); }
/** * Validate that the listing respects the local/elisprogram:track_enrol_userset_user * capability as long as the appropriate userset and track are associated to * one another and the target user is in the userset */ public function test_availableusersrespectsindirectusersetpermissions() { global $DB, $USER; $this->load_csv_data(); set_config('siteguest', ''); set_config('siteadmins', ''); accesslib_clear_all_caches_for_unit_testing(); // Create a test user to be in the userset. $usersetmember = new user(array('idnumber' => 'usersetmember', 'username' => 'usersetmember', 'firstname' => 'usersetmember', 'lastname' => 'usersetmember', 'email' => '*****@*****.**', 'country' => 'CA')); $usersetmember->save(); // Our test userset. $userset = new userset(array('name' => 'userset')); $userset->save(); // Assign the test user to the test userset. $clusterassignment = new clusterassignment(array('userid' => $usersetmember->id, 'clusterid' => $userset->id)); $clusterassignment->save(); // Assign the userset to our track. $clustertrack = new clustertrack(array('clusterid' => $userset->id, 'trackid' => 1)); $clustertrack->save(); // Set up a db record for the active user for permissions reasons. // (i.e. so they are not treated as an admin). $activeuser = new user(array('idnumber' => 'activeuser', 'username' => 'activeuser', 'firstname' => 'activeuser', 'lastname' => 'activeuser', 'email' => '*****@*****.**', 'country' => 'CA')); $activeuser->save(); // Set up our test role. $roleid = create_role('testrole', 'testrole', 'testrole'); $syscontext = context_system::instance(); assign_capability('local/elisprogram:track_enrol_userset_user', CAP_ALLOW, $roleid, $syscontext->id); // Perform the role necessary assignment. $moodleuser = $DB->get_record('user', array('username' => 'activeuser')); // Make sure all the contexts are created, so that we can find the children. $contextclass = \local_eliscore\context\helper::get_class_for_level(CONTEXT_ELIS_USERSET); $instance = $contextclass::instance($userset->id); role_assign($roleid, $moodleuser->id, $instance->id); // Assume the role of the user with the role assignment. $USER = $moodleuser; $usersrecset = usertrack::get_available_users(1); $users = array(); foreach ($usersrecset as $key => $user) { $users[$key] = $user; } unset($usersrecset); $this->assertEquals(1, count($users)); // Validate user. $this->assertArrayHasKey($usersetmember->id, $users); $user = $users[$usersetmember->id]; $this->assertEquals($usersetmember->username, 'usersetmember'); // Validate count. $count = usertrack::count_available_users(1); $this->assertEquals(1, $count); }
/** * Test update_grades() */ public function test_update_grades() { global $DB; $this->resetAfterTest(true); $assignmentname = 'The assignment'; $student1rawgrade = 10; $student2rawgrade = 20; list($course, $assignment, $student1, $student2, $teacher, $parent) = $this->load_test_data($assignmentname, $student1rawgrade, $student2rawgrade); $assigmentcm = get_coursemodule_from_id('assign', $assignment->id, 0, false, MUST_EXIST); $this->setUser($teacher); // Teacher updating grade item information. $changedmax = 93; $result = core_grades_external::update_grades('test', $course->id, 'mod_assign', $assigmentcm->id, 0, array(), array('grademax' => $changedmax)); $result = external_api::clean_returnvalue(core_grades_external::update_grades_returns(), $result); $this->assertTrue($result == GRADE_UPDATE_OK); $grades = grade_get_grades($course->id, 'mod', 'assign', $assignment->id); $this->assertTrue($grades->items[0]->grademax == $changedmax); // Teacher updating 1 student grade. $student1grade = 23; $result = core_grades_external::update_grades('test', $course->id, 'mod_assign', $assigmentcm->id, 0, array(array('studentid' => $student1->id, 'grade' => $student1grade))); $result = external_api::clean_returnvalue(core_grades_external::update_grades_returns(), $result); $this->assertTrue($result == GRADE_UPDATE_OK); $grades = grade_get_grades($course->id, 'mod', 'assign', $assignment->id, array($student1->id)); $this->assertTrue($grades->items[0]->grades[$student1->id]->grade == $student1grade); // Teacher updating multiple student grades. $student1grade = 11; $student2grade = 13; $result = core_grades_external::update_grades('test', $course->id, 'mod_assign', $assigmentcm->id, 0, array(array('studentid' => $student1->id, 'grade' => $student1grade), array('studentid' => $student2->id, 'grade' => $student2grade))); $result = external_api::clean_returnvalue(core_grades_external::update_grades_returns(), $result); $this->assertTrue($result == GRADE_UPDATE_OK); $grades = grade_get_grades($course->id, 'mod', 'assign', $assignment->id, array($student1->id, $student2->id)); $this->assertTrue($grades->items[0]->grades[$student1->id]->grade == $student1grade); $this->assertTrue($grades->items[0]->grades[$student2->id]->grade == $student2grade); // Student attempting to update their own grade (should fail). $this->setUser($student1); try { $student1grade = 17; $result = core_grades_external::update_grades('test', $course->id, 'mod_assign', $assigmentcm->id, 0, array(array('studentid' => $student1->id, 'grade' => $student1grade))); $this->fail('moodle_exception expected'); } catch (moodle_exception $ex) { $this->assertTrue(true); } // Parent attempting to update their child's grade (should fail). $this->setUser($parent); try { $student1grade = 13; $result = core_grades_external::update_grades('test', $course->id, 'mod_assign', $assigmentcm->id, 0, array(array('studentid' => $student1->id, 'grade' => $student1grade))); $this->fail('moodle_exception expected'); } catch (moodle_exception $ex) { $this->assertTrue(true); } // Student trying to hide a grade item (should fail). $this->setUser($student1); try { $result = core_grades_external::update_grades('test', $course->id, 'mod_assign', $assigmentcm->id, 0, array(), array('hidden' => 1)); $this->fail('moodle_exception expected'); } catch (moodle_exception $ex) { $this->assertTrue(true); } // Give the student role 'moodle/grade:hide' and they should now be able to hide the grade item. $studentrole = $DB->get_record('role', array('shortname' => 'student')); $coursecontext = context_course::instance($course->id); assign_capability('moodle/grade:hide', CAP_ALLOW, $studentrole->id, $coursecontext->id); accesslib_clear_all_caches_for_unit_testing(); // Check the activity isn't already hidden. $grades = grade_get_grades($course->id, 'mod', 'assign', $assignment->id); $this->assertTrue($grades->items[0]->hidden == 0); $result = core_grades_external::update_grades('test', $course->id, 'mod_assign', $assigmentcm->id, 0, array(), array('hidden' => 1)); $result = external_api::clean_returnvalue(core_grades_external::update_grades_returns(), $result); $this->assertTrue($result == GRADE_UPDATE_OK); $grades = grade_get_grades($course->id, 'mod', 'assign', $assignment->id); $this->assertTrue($grades->items[0]->hidden == 1); }
/** * Create a a course, assignment module instance, student and teacher and enrol them in * the course. * * @param array $params parameters to be provided to the assignment module creation * @return array containing the course, assignment module, student and teacher */ private function create_assign_with_student_and_teacher($params = array()) { global $DB; $course = $this->getDataGenerator()->create_course(); $params = array_merge(array('course' => $course->id, 'name' => 'assignment', 'intro' => 'assignment intro text'), $params); // Create a course and assignment and users. $assign = $this->getDataGenerator()->create_module('assign', $params); $cm = get_coursemodule_from_instance('assign', $assign->id); $context = context_module::instance($cm->id); $student = $this->getDataGenerator()->create_user(); $studentrole = $DB->get_record('role', array('shortname' => 'student')); $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); $teacher = $this->getDataGenerator()->create_user(); $teacherrole = $DB->get_record('role', array('shortname' => 'teacher')); $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); assign_capability('mod/assign:view', CAP_ALLOW, $teacherrole->id, $context->id, true); assign_capability('mod/assign:viewgrades', CAP_ALLOW, $teacherrole->id, $context->id, true); assign_capability('mod/assign:grade', CAP_ALLOW, $teacherrole->id, $context->id, true); accesslib_clear_all_caches_for_unit_testing(); return array('course' => $course, 'assign' => $assign, 'student' => $student, 'teacher' => $teacher); }
/** * A small functional test of permission evaluations. */ public function test_permission_evaluation() { global $USER, $SITE, $CFG, $DB, $ACCESSLIB_PRIVATE; $this->resetAfterTest(); $generator = $this->getDataGenerator(); // Fill the site with some real data. $testcategories = array(); $testcourses = array(); $testpages = array(); $testblocks = array(); $allroles = $DB->get_records_menu('role', array(), 'id', 'archetype, id'); $systemcontext = context_system::instance(); $frontpagecontext = context_course::instance(SITEID); // Add block to system context. $bi = $generator->create_block('online_users'); context_block::instance($bi->id); $testblocks[] = $bi->id; // Some users. $testusers = array(); for ($i = 0; $i < 20; $i++) { $user = $generator->create_user(); $testusers[$i] = $user->id; $usercontext = context_user::instance($user->id); // Add block to user profile. $bi = $generator->create_block('online_users', array('parentcontextid' => $usercontext->id)); $testblocks[] = $bi->id; } // Deleted user - should be ignored everywhere, can not have context. $generator->create_user(array('deleted' => 1)); // Add block to frontpage. $bi = $generator->create_block('online_users', array('parentcontextid' => $frontpagecontext->id)); $frontpageblockcontext = context_block::instance($bi->id); $testblocks[] = $bi->id; // Add a resource to frontpage. $page = $generator->create_module('page', array('course' => $SITE->id)); $testpages[] = $page->id; $frontpagepagecontext = context_module::instance($page->cmid); // Add block to frontpage resource. $bi = $generator->create_block('online_users', array('parentcontextid' => $frontpagepagecontext->id)); $frontpagepageblockcontext = context_block::instance($bi->id); $testblocks[] = $bi->id; // Some nested course categories with courses. $manualenrol = enrol_get_plugin('manual'); $parentcat = 0; for ($i = 0; $i < 5; $i++) { $cat = $generator->create_category(array('parent' => $parentcat)); $testcategories[] = $cat->id; $catcontext = context_coursecat::instance($cat->id); $parentcat = $cat->id; if ($i >= 4) { continue; } // Add resource to each category. $bi = $generator->create_block('online_users', array('parentcontextid' => $catcontext->id)); context_block::instance($bi->id); // Add a few courses to each category. for ($j = 0; $j < 6; $j++) { $course = $generator->create_course(array('category' => $cat->id)); $testcourses[] = $course->id; $coursecontext = context_course::instance($course->id); if ($j >= 5) { continue; } // Add manual enrol instance. $manualenrol->add_default_instance($DB->get_record('course', array('id' => $course->id))); // Add block to each course. $bi = $generator->create_block('online_users', array('parentcontextid' => $coursecontext->id)); $testblocks[] = $bi->id; // Add a resource to each course. $page = $generator->create_module('page', array('course' => $course->id)); $testpages[] = $page->id; $modcontext = context_module::instance($page->cmid); // Add block to each module. $bi = $generator->create_block('online_users', array('parentcontextid' => $modcontext->id)); $testblocks[] = $bi->id; } } // Make sure all contexts were created properly. $count = 1; // System. $count += $DB->count_records('user', array('deleted' => 0)); $count += $DB->count_records('course_categories'); $count += $DB->count_records('course'); $count += $DB->count_records('course_modules'); $count += $DB->count_records('block_instances'); $this->assertEquals($count, $DB->count_records('context')); $this->assertEquals(0, $DB->count_records('context', array('depth' => 0))); $this->assertEquals(0, $DB->count_records('context', array('path' => null))); // Test context_helper::get_level_name() method. $levels = context_helper::get_all_levels(); foreach ($levels as $level => $classname) { $name = context_helper::get_level_name($level); $this->assertNotEmpty($name); } // Test context::instance_by_id(), context_xxx::instance() methods. $context = context::instance_by_id($frontpagecontext->id); $this->assertSame(CONTEXT_COURSE, $context->contextlevel); $this->assertFalse(context::instance_by_id(-1, IGNORE_MISSING)); try { context::instance_by_id(-1); $this->fail('exception expected'); } catch (moodle_exception $e) { $this->assertTrue(true); } $this->assertInstanceOf('context_system', context_system::instance()); $this->assertInstanceOf('context_coursecat', context_coursecat::instance($testcategories[0])); $this->assertInstanceOf('context_course', context_course::instance($testcourses[0])); $this->assertInstanceOf('context_module', context_module::instance($testpages[0])); $this->assertInstanceOf('context_block', context_block::instance($testblocks[0])); $this->assertFalse(context_coursecat::instance(-1, IGNORE_MISSING)); $this->assertFalse(context_course::instance(-1, IGNORE_MISSING)); $this->assertFalse(context_module::instance(-1, IGNORE_MISSING)); $this->assertFalse(context_block::instance(-1, IGNORE_MISSING)); try { context_coursecat::instance(-1); $this->fail('exception expected'); } catch (moodle_exception $e) { $this->assertTrue(true); } try { context_course::instance(-1); $this->fail('exception expected'); } catch (moodle_exception $e) { $this->assertTrue(true); } try { context_module::instance(-1); $this->fail('exception expected'); } catch (moodle_exception $e) { $this->assertTrue(true); } try { context_block::instance(-1); $this->fail('exception expected'); } catch (moodle_exception $e) { $this->assertTrue(true); } // Test $context->get_url(), $context->get_context_name(), $context->get_capabilities() methods. $testcontexts = array(); $testcontexts[CONTEXT_SYSTEM] = context_system::instance(); $testcontexts[CONTEXT_COURSECAT] = context_coursecat::instance($testcategories[0]); $testcontexts[CONTEXT_COURSE] = context_course::instance($testcourses[0]); $testcontexts[CONTEXT_MODULE] = context_module::instance($testpages[0]); $testcontexts[CONTEXT_BLOCK] = context_block::instance($testblocks[0]); foreach ($testcontexts as $context) { $name = $context->get_context_name(true, true); $this->assertNotEmpty($name); $this->assertInstanceOf('moodle_url', $context->get_url()); $caps = $context->get_capabilities(); $this->assertTrue(is_array($caps)); foreach ($caps as $cap) { $cap = (array) $cap; $this->assertSame(array_keys($cap), array('id', 'name', 'captype', 'contextlevel', 'component', 'riskbitmask')); } } unset($testcontexts); // Test $context->get_course_context() method. $this->assertFalse($systemcontext->get_course_context(false)); try { $systemcontext->get_course_context(); $this->fail('exception expected'); } catch (moodle_exception $e) { $this->assertInstanceOf('coding_exception', $e); } $context = context_coursecat::instance($testcategories[0]); $this->assertFalse($context->get_course_context(false)); try { $context->get_course_context(); $this->fail('exception expected'); } catch (moodle_exception $e) { $this->assertInstanceOf('coding_exception', $e); } $this->assertEquals($frontpagecontext, $frontpagecontext->get_course_context(true)); $this->assertEquals($frontpagecontext, $frontpagepagecontext->get_course_context(true)); $this->assertEquals($frontpagecontext, $frontpagepageblockcontext->get_course_context(true)); // Test $context->get_parent_context(), $context->get_parent_contexts(), $context->get_parent_context_ids() methods. $userid = reset($testusers); $usercontext = context_user::instance($userid); $this->assertEquals($systemcontext, $usercontext->get_parent_context()); $this->assertEquals(array($systemcontext->id => $systemcontext), $usercontext->get_parent_contexts()); $this->assertEquals(array($usercontext->id => $usercontext, $systemcontext->id => $systemcontext), $usercontext->get_parent_contexts(true)); $this->assertEquals(array(), $systemcontext->get_parent_contexts()); $this->assertEquals(array($systemcontext->id => $systemcontext), $systemcontext->get_parent_contexts(true)); $this->assertEquals(array(), $systemcontext->get_parent_context_ids()); $this->assertEquals(array($systemcontext->id), $systemcontext->get_parent_context_ids(true)); $this->assertEquals($systemcontext, $frontpagecontext->get_parent_context()); $this->assertEquals(array($systemcontext->id => $systemcontext), $frontpagecontext->get_parent_contexts()); $this->assertEquals(array($frontpagecontext->id => $frontpagecontext, $systemcontext->id => $systemcontext), $frontpagecontext->get_parent_contexts(true)); $this->assertEquals(array($systemcontext->id), $frontpagecontext->get_parent_context_ids()); $this->assertEquals(array($frontpagecontext->id, $systemcontext->id), $frontpagecontext->get_parent_context_ids(true)); $this->assertFalse($systemcontext->get_parent_context()); $frontpagecontext = context_course::instance($SITE->id); $parent = $systemcontext; foreach ($testcategories as $catid) { $catcontext = context_coursecat::instance($catid); $this->assertEquals($parent, $catcontext->get_parent_context()); $parent = $catcontext; } $this->assertEquals($frontpagecontext, $frontpagepagecontext->get_parent_context()); $this->assertEquals($frontpagecontext, $frontpageblockcontext->get_parent_context()); $this->assertEquals($frontpagepagecontext, $frontpagepageblockcontext->get_parent_context()); // Test $context->get_child_contexts() method. $children = $systemcontext->get_child_contexts(); $this->resetDebugging(); $this->assertEquals(count($children) + 1, $DB->count_records('context')); $context = context_coursecat::instance($testcategories[3]); $children = $context->get_child_contexts(); $countcats = 0; $countcourses = 0; $countblocks = 0; foreach ($children as $child) { if ($child->contextlevel == CONTEXT_COURSECAT) { $countcats++; } if ($child->contextlevel == CONTEXT_COURSE) { $countcourses++; } if ($child->contextlevel == CONTEXT_BLOCK) { $countblocks++; } } $this->assertCount(8, $children); $this->assertEquals(1, $countcats); $this->assertEquals(6, $countcourses); $this->assertEquals(1, $countblocks); $context = context_course::instance($testcourses[2]); $children = $context->get_child_contexts(); $this->assertCount(7, $children); // Depends on number of default blocks. $context = context_module::instance($testpages[3]); $children = $context->get_child_contexts(); $this->assertCount(1, $children); $context = context_block::instance($testblocks[1]); $children = $context->get_child_contexts(); $this->assertCount(0, $children); unset($children); unset($countcats); unset($countcourses); unset($countblocks); // Test context_helper::reset_caches() method. context_helper::reset_caches(); $this->assertEquals(0, context_inspection::test_context_cache_size()); context_course::instance($SITE->id); $this->assertEquals(1, context_inspection::test_context_cache_size()); // Test context preloading. context_helper::reset_caches(); $sql = "SELECT " . context_helper::get_preload_record_columns_sql('c') . "\n FROM {context} c\n WHERE c.contextlevel <> " . CONTEXT_SYSTEM; $records = $DB->get_records_sql($sql); $firstrecord = reset($records); $columns = context_helper::get_preload_record_columns('c'); $firstrecord = (array) $firstrecord; $this->assertSame(array_keys($firstrecord), array_values($columns)); context_helper::reset_caches(); foreach ($records as $record) { context_helper::preload_from_record($record); $this->assertEquals(new stdClass(), $record); } $this->assertEquals(count($records), context_inspection::test_context_cache_size()); unset($records); unset($columns); context_helper::reset_caches(); context_helper::preload_course($SITE->id); $numfrontpagemodules = $DB->count_records('course_modules', array('course' => $SITE->id)); $this->assertEquals(6 + $numfrontpagemodules, context_inspection::test_context_cache_size()); // Depends on number of default blocks. // Test assign_capability(), unassign_capability() functions. $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertFalse($rc); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext->id); $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertEquals(CAP_ALLOW, $rc->permission); assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext->id); $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertEquals(CAP_ALLOW, $rc->permission); assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $allroles['teacher'], $frontpagecontext, true); $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertEquals(CAP_PREVENT, $rc->permission); assign_capability('moodle/site:accessallgroups', CAP_INHERIT, $allroles['teacher'], $frontpagecontext); $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertFalse($rc); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $allroles['teacher'], $frontpagecontext); unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext, true); $rc = $DB->get_record('role_capabilities', array('contextid' => $frontpagecontext->id, 'roleid' => $allroles['teacher'], 'capability' => 'moodle/site:accessallgroups')); $this->assertFalse($rc); unassign_capability('moodle/site:accessallgroups', $allroles['teacher'], $frontpagecontext->id, true); unset($rc); accesslib_clear_all_caches_for_unit_testing(); // Must be done after assign_capability(). // Test role_assign(), role_unassign(), role_unassign_all() functions. $context = context_course::instance($testcourses[1]); $this->assertEquals(0, $DB->count_records('role_assignments', array('contextid' => $context->id))); role_assign($allroles['teacher'], $testusers[1], $context->id); role_assign($allroles['teacher'], $testusers[2], $context->id); role_assign($allroles['manager'], $testusers[1], $context->id); $this->assertEquals(3, $DB->count_records('role_assignments', array('contextid' => $context->id))); role_unassign($allroles['teacher'], $testusers[1], $context->id); $this->assertEquals(2, $DB->count_records('role_assignments', array('contextid' => $context->id))); role_unassign_all(array('contextid' => $context->id)); $this->assertEquals(0, $DB->count_records('role_assignments', array('contextid' => $context->id))); unset($context); accesslib_clear_all_caches_for_unit_testing(); // Just in case. // Test has_capability(), get_users_by_capability(), role_switch(), reload_all_capabilities() and friends functions. $adminid = get_admin()->id; $guestid = $CFG->siteguest; // Enrol some users into some courses. $course1 = $DB->get_record('course', array('id' => $testcourses[22]), '*', MUST_EXIST); $course2 = $DB->get_record('course', array('id' => $testcourses[7]), '*', MUST_EXIST); $cms = $DB->get_records('course_modules', array('course' => $course1->id), 'id'); $cm1 = reset($cms); $blocks = $DB->get_records('block_instances', array('parentcontextid' => context_module::instance($cm1->id)->id), 'id'); $block1 = reset($blocks); $instance1 = $DB->get_record('enrol', array('enrol' => 'manual', 'courseid' => $course1->id)); $instance2 = $DB->get_record('enrol', array('enrol' => 'manual', 'courseid' => $course2->id)); for ($i = 0; $i < 9; $i++) { $manualenrol->enrol_user($instance1, $testusers[$i], $allroles['student']); } $manualenrol->enrol_user($instance1, $testusers[8], $allroles['teacher']); $manualenrol->enrol_user($instance1, $testusers[9], $allroles['editingteacher']); for ($i = 10; $i < 15; $i++) { $manualenrol->enrol_user($instance2, $testusers[$i], $allroles['student']); } $manualenrol->enrol_user($instance2, $testusers[15], $allroles['editingteacher']); // Add tons of role assignments - the more the better. role_assign($allroles['coursecreator'], $testusers[11], context_coursecat::instance($testcategories[2])); role_assign($allroles['manager'], $testusers[12], context_coursecat::instance($testcategories[1])); role_assign($allroles['student'], $testusers[9], context_module::instance($cm1->id)); role_assign($allroles['teacher'], $testusers[8], context_module::instance($cm1->id)); role_assign($allroles['guest'], $testusers[13], context_course::instance($course1->id)); role_assign($allroles['teacher'], $testusers[7], context_block::instance($block1->id)); role_assign($allroles['manager'], $testusers[9], context_block::instance($block1->id)); role_assign($allroles['editingteacher'], $testusers[9], context_course::instance($course1->id)); role_assign($allroles['teacher'], $adminid, context_course::instance($course1->id)); role_assign($allroles['editingteacher'], $adminid, context_block::instance($block1->id)); // Add tons of overrides - the more the better. assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpageblockcontext, true); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpageblockcontext, true); assign_capability('moodle/block:view', CAP_PROHIBIT, $allroles['guest'], $frontpageblockcontext, true); assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['user'], $frontpageblockcontext, true); assign_capability('block/online_users:viewlist', CAP_PREVENT, $allroles['student'], $frontpageblockcontext, true); assign_capability('moodle/site:accessallgroups', CAP_PREVENT, $CFG->defaultuserroleid, $frontpagepagecontext, true); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagepagecontext, true); assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $frontpagepagecontext, true); assign_capability('mod/page:view', CAP_ALLOW, $allroles['user'], $frontpagepagecontext, true); assign_capability('moodle/page:view', CAP_ALLOW, $allroles['student'], $frontpagepagecontext, true); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultuserroleid, $frontpagecontext, true); assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $CFG->defaultfrontpageroleid, $frontpagecontext, true); assign_capability('mod/page:view', CAP_ALLOW, $allroles['guest'], $frontpagecontext, true); assign_capability('mod/page:view', CAP_PROHIBIT, $allroles['user'], $frontpagecontext, true); assign_capability('mod/page:view', CAP_PREVENT, $allroles['guest'], $systemcontext, true); accesslib_clear_all_caches_for_unit_testing(); /// Must be done after assign_capability(). // Extra tests for guests and not-logged-in users because they can not be verified by cross checking // with get_users_by_capability() where they are ignored. $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, $guestid)); $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, $guestid)); $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, $guestid)); $this->assertFalse(has_capability('mod/page:view', $systemcontext, $guestid)); $this->assertFalse(has_capability('moodle/block:view', $frontpageblockcontext, 0)); $this->assertFalse(has_capability('mod/page:view', $frontpagepagecontext, 0)); $this->assertTrue(has_capability('mod/page:view', $frontpagecontext, 0)); $this->assertFalse(has_capability('mod/page:view', $systemcontext, 0)); $this->assertFalse(has_capability('moodle/course:create', $systemcontext, $testusers[11])); $this->assertTrue(has_capability('moodle/course:create', context_coursecat::instance($testcategories[2]), $testusers[11])); $this->assertFalse(has_capability('moodle/course:create', context_course::instance($testcourses[1]), $testusers[11])); $this->assertTrue(has_capability('moodle/course:create', context_course::instance($testcourses[19]), $testusers[11])); $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[1]), $testusers[9])); $this->assertFalse(has_capability('moodle/course:update', context_course::instance($testcourses[19]), $testusers[9])); $this->assertFalse(has_capability('moodle/course:update', $systemcontext, $testusers[9])); // Test the list of enrolled users. $coursecontext = context_course::instance($course1->id); $enrolled = get_enrolled_users($coursecontext); $this->assertCount(10, $enrolled); for ($i = 0; $i < 10; $i++) { $this->assertTrue(isset($enrolled[$testusers[$i]])); } $enrolled = get_enrolled_users($coursecontext, 'moodle/course:update'); $this->assertCount(1, $enrolled); $this->assertTrue(isset($enrolled[$testusers[9]])); unset($enrolled); // Role switching. $userid = $testusers[9]; $USER = $DB->get_record('user', array('id' => $userid)); load_all_capabilities(); $coursecontext = context_course::instance($course1->id); $this->assertTrue(has_capability('moodle/course:update', $coursecontext)); $this->assertFalse(is_role_switched($course1->id)); role_switch($allroles['student'], $coursecontext); $this->assertTrue(is_role_switched($course1->id)); $this->assertEquals($allroles['student'], $USER->access['rsw'][$coursecontext->path]); $this->assertFalse(has_capability('moodle/course:update', $coursecontext)); reload_all_capabilities(); $this->assertFalse(has_capability('moodle/course:update', $coursecontext)); role_switch(0, $coursecontext); $this->assertTrue(has_capability('moodle/course:update', $coursecontext)); $userid = $adminid; $USER = $DB->get_record('user', array('id' => $userid)); load_all_capabilities(); $coursecontext = context_course::instance($course1->id); $blockcontext = context_block::instance($block1->id); $this->assertTrue(has_capability('moodle/course:update', $blockcontext)); role_switch($allroles['student'], $coursecontext); $this->assertEquals($allroles['student'], $USER->access['rsw'][$coursecontext->path]); $this->assertFalse(has_capability('moodle/course:update', $blockcontext)); reload_all_capabilities(); $this->assertFalse(has_capability('moodle/course:update', $blockcontext)); load_all_capabilities(); $this->assertTrue(has_capability('moodle/course:update', $blockcontext)); // Temp course role for enrol. $DB->delete_records('cache_flags', array()); // This prevents problem with dirty contexts immediately resetting the temp role - this is a known problem... $userid = $testusers[5]; $roleid = $allroles['editingteacher']; $USER = $DB->get_record('user', array('id' => $userid)); load_all_capabilities(); $coursecontext = context_course::instance($course1->id); $this->assertFalse(has_capability('moodle/course:update', $coursecontext)); $this->assertFalse(isset($USER->access['ra'][$coursecontext->path][$roleid])); load_temp_course_role($coursecontext, $roleid); $this->assertEquals($USER->access['ra'][$coursecontext->path][$roleid], $roleid); $this->assertTrue(has_capability('moodle/course:update', $coursecontext)); remove_temp_course_roles($coursecontext); $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid)); load_temp_course_role($coursecontext, $roleid); reload_all_capabilities(); $this->assertFalse(has_capability('moodle/course:update', $coursecontext, $userid)); $USER = new stdClass(); $USER->id = 0; // Now cross check has_capability() with get_users_by_capability(), each using different code paths, // they have to be kept in sync, usually only one of them breaks, so we know when something is wrong, // at the same time validate extra restrictions (guest read only no risks, admin exception, non existent and deleted users). $contexts = $DB->get_records('context', array(), 'id'); $contexts = array_values($contexts); $capabilities = $DB->get_records('capabilities', array(), 'id'); $capabilities = array_values($capabilities); $roles = array($allroles['guest'], $allroles['user'], $allroles['teacher'], $allroles['editingteacher'], $allroles['coursecreator'], $allroles['manager']); $userids = array_values($testusers); $userids[] = get_admin()->id; if (!PHPUNIT_LONGTEST) { $contexts = array_slice($contexts, 0, 10); $capabilities = array_slice($capabilities, 0, 5); $userids = array_slice($userids, 0, 5); } foreach ($userids as $userid) { // No guest or deleted. // Each user gets 0-10 random roles. $rcount = rand(0, 10); for ($j = 0; $j < $rcount; $j++) { $roleid = $roles[rand(0, count($roles) - 1)]; $contextid = $contexts[rand(0, count($contexts) - 1)]->id; role_assign($roleid, $userid, $contextid); } } $permissions = array(CAP_ALLOW, CAP_PREVENT, CAP_INHERIT, CAP_PREVENT); $maxoverrides = count($contexts) * 10; for ($j = 0; $j < $maxoverrides; $j++) { $roleid = $roles[rand(0, count($roles) - 1)]; $contextid = $contexts[rand(0, count($contexts) - 1)]->id; $permission = $permissions[rand(0, count($permissions) - 1)]; $capname = $capabilities[rand(0, count($capabilities) - 1)]->name; assign_capability($capname, $permission, $roleid, $contextid, true); } unset($permissions); unset($roles); accesslib_clear_all_caches_for_unit_testing(); // must be done after assign_capability(). // Test time - let's set up some real user, just in case the logic for USER affects the others... $USER = $DB->get_record('user', array('id' => $testusers[3])); load_all_capabilities(); $userids[] = $CFG->siteguest; $userids[] = 0; // Not-logged-in user. $userids[] = -1; // Non-existent user. foreach ($contexts as $crecord) { $context = context::instance_by_id($crecord->id); if ($coursecontext = $context->get_course_context(false)) { $enrolled = get_enrolled_users($context); } else { $enrolled = array(); } foreach ($capabilities as $cap) { $allowed = get_users_by_capability($context, $cap->name, 'u.id, u.username'); if ($enrolled) { $enrolledwithcap = get_enrolled_users($context, $cap->name); } else { $enrolledwithcap = array(); } foreach ($userids as $userid) { if ($userid == 0 or isguestuser($userid)) { if ($userid == 0) { $CFG->forcelogin = true; $this->assertFalse(has_capability($cap->name, $context, $userid)); unset($CFG->forcelogin); } if ($cap->captype === 'write' or $cap->riskbitmask & (RISK_XSS | RISK_CONFIG | RISK_DATALOSS)) { $this->assertFalse(has_capability($cap->name, $context, $userid)); } $this->assertFalse(isset($allowed[$userid])); } else { if (is_siteadmin($userid)) { $this->assertTrue(has_capability($cap->name, $context, $userid, true)); } $hascap = has_capability($cap->name, $context, $userid, false); $this->assertSame($hascap, isset($allowed[$userid]), "Capability result mismatch user:{$userid}, context:{$context->id}, {$cap->name}, hascap: " . (int) $hascap . " "); if (isset($enrolled[$userid])) { $this->assertSame(isset($allowed[$userid]), isset($enrolledwithcap[$userid]), "Enrolment with capability result mismatch user:{$userid}, context:{$context->id}, {$cap->name}, hascap: " . (int) $hascap . " "); } } } } } // Back to nobody. $USER = new stdClass(); $USER->id = 0; unset($contexts); unset($userids); unset($capabilities); // Now let's do all the remaining tests that break our carefully prepared fake site. // Test $context->mark_dirty() method. $DB->delete_records('cache_flags', array()); accesslib_clear_all_caches(false); $systemcontext->mark_dirty(); $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2); $this->assertTrue(isset($dirty[$systemcontext->path])); $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$systemcontext->path])); // Test $context->reload_if_dirty() method. $DB->delete_records('cache_flags', array()); accesslib_clear_all_caches(false); load_all_capabilities(); $context = context_course::instance($testcourses[2]); $page = $DB->get_record('page', array('course' => $testcourses[2])); $pagecm = get_coursemodule_from_instance('page', $page->id); $pagecontext = context_module::instance($pagecm->id); $context->mark_dirty(); $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path])); $USER->access['test'] = true; $context->reload_if_dirty(); $this->assertFalse(isset($USER->access['test'])); $context->mark_dirty(); $this->assertTrue(isset($ACCESSLIB_PRIVATE->dirtycontexts[$context->path])); $USER->access['test'] = true; $pagecontext->reload_if_dirty(); $this->assertFalse(isset($USER->access['test'])); // Test context_helper::build_all_paths() method. $oldcontexts = $DB->get_records('context', array(), 'id'); $DB->set_field_select('context', 'path', null, "contextlevel <> " . CONTEXT_SYSTEM); $DB->set_field_select('context', 'depth', 0, "contextlevel <> " . CONTEXT_SYSTEM); context_helper::build_all_paths(); $newcontexts = $DB->get_records('context', array(), 'id'); $this->assertEquals($oldcontexts, $newcontexts); unset($oldcontexts); unset($newcontexts); // Test $context->reset_paths() method. $context = context_course::instance($testcourses[2]); $children = $context->get_child_contexts(); $context->reset_paths(false); $this->assertNull($DB->get_field('context', 'path', array('id' => $context->id))); $this->assertEquals(0, $DB->get_field('context', 'depth', array('id' => $context->id))); foreach ($children as $child) { $this->assertNull($DB->get_field('context', 'path', array('id' => $child->id))); $this->assertEquals(0, $DB->get_field('context', 'depth', array('id' => $child->id))); } $this->assertEquals(count($children) + 1, $DB->count_records('context', array('depth' => 0))); $this->assertEquals(count($children) + 1, $DB->count_records('context', array('path' => null))); $context = context_course::instance($testcourses[2]); $context->reset_paths(true); $context = context_course::instance($testcourses[2]); $this->assertSame($context->path, $DB->get_field('context', 'path', array('id' => $context->id))); $this->assertSame($context->depth, $DB->get_field('context', 'depth', array('id' => $context->id))); $this->assertEquals(0, $DB->count_records('context', array('depth' => 0))); $this->assertEquals(0, $DB->count_records('context', array('path' => null))); // Test $context->update_moved() method. accesslib_clear_all_caches(false); $DB->delete_records('cache_flags', array()); $course = $DB->get_record('course', array('id' => $testcourses[0])); $context = context_course::instance($course->id); $oldpath = $context->path; $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}"); $categorycontext = context_coursecat::instance($miscid); $course->category = $miscid; $DB->update_record('course', $course); $context->update_moved($categorycontext); $context = context_course::instance($course->id); $this->assertEquals($categorycontext, $context->get_parent_context()); $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2); $this->assertTrue(isset($dirty[$oldpath])); $this->assertTrue(isset($dirty[$context->path])); // Test $context->delete_content() method. context_helper::reset_caches(); $context = context_module::instance($testpages[3]); $this->assertTrue($DB->record_exists('context', array('id' => $context->id))); $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid' => $context->id))); $context->delete_content(); $this->assertTrue($DB->record_exists('context', array('id' => $context->id))); $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid' => $context->id))); // Test $context->delete() method. context_helper::reset_caches(); $context = context_module::instance($testpages[4]); $this->assertTrue($DB->record_exists('context', array('id' => $context->id))); $this->assertEquals(1, $DB->count_records('block_instances', array('parentcontextid' => $context->id))); $bi = $DB->get_record('block_instances', array('parentcontextid' => $context->id)); $bicontext = context_block::instance($bi->id); $DB->delete_records('cache_flags', array()); $context->delete(); // Should delete also linked blocks. $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2); $this->assertTrue(isset($dirty[$context->path])); $this->assertFalse($DB->record_exists('context', array('id' => $context->id))); $this->assertFalse($DB->record_exists('context', array('id' => $bicontext->id))); $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_MODULE, 'instanceid' => $testpages[4]))); $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_BLOCK, 'instanceid' => $bi->id))); $this->assertEquals(0, $DB->count_records('block_instances', array('parentcontextid' => $context->id))); context_module::instance($testpages[4]); // Test context_helper::delete_instance() method. context_helper::reset_caches(); $lastcourse = array_pop($testcourses); $this->assertTrue($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $lastcourse))); $coursecontext = context_course::instance($lastcourse); $this->assertEquals(1, context_inspection::test_context_cache_size()); $this->assertNotEquals(CONTEXT_COURSE, $coursecontext->instanceid); $DB->delete_records('cache_flags', array()); context_helper::delete_instance(CONTEXT_COURSE, $lastcourse); $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2); $this->assertTrue(isset($dirty[$coursecontext->path])); $this->assertEquals(0, context_inspection::test_context_cache_size()); $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $lastcourse))); context_course::instance($lastcourse); // Test context_helper::create_instances() method. $prevcount = $DB->count_records('context'); $DB->delete_records('context', array('contextlevel' => CONTEXT_BLOCK)); context_helper::create_instances(null, true); $this->assertSame($DB->count_records('context'), $prevcount); $this->assertEquals(0, $DB->count_records('context', array('depth' => 0))); $this->assertEquals(0, $DB->count_records('context', array('path' => null))); $DB->delete_records('context', array('contextlevel' => CONTEXT_BLOCK)); $DB->delete_records('block_instances', array()); $prevcount = $DB->count_records('context'); $DB->delete_records_select('context', 'contextlevel <> ' . CONTEXT_SYSTEM); context_helper::create_instances(null, true); $this->assertSame($prevcount, $DB->count_records('context')); $this->assertEquals(0, $DB->count_records('context', array('depth' => 0))); $this->assertEquals(0, $DB->count_records('context', array('path' => null))); // Test context_helper::cleanup_instances() method. $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}"); $DB->delete_records('course', array('id' => $lastcourse)); $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}"); $DB->delete_records('course_categories', array('id' => $lastcategory)); $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0"); $DB->delete_records('user', array('id' => $lastuser)); $DB->delete_records('block_instances', array('parentcontextid' => $frontpagepagecontext->id)); $DB->delete_records('course_modules', array('id' => $frontpagepagecontext->instanceid)); context_helper::cleanup_instances(); $count = 1; // System. $count += $DB->count_records('user', array('deleted' => 0)); $count += $DB->count_records('course_categories'); $count += $DB->count_records('course'); $count += $DB->count_records('course_modules'); $count += $DB->count_records('block_instances'); $this->assertEquals($count, $DB->count_records('context')); // Test context cache size restrictions. $testusers = array(); for ($i = 0; $i < CONTEXT_CACHE_MAX_SIZE + 100; $i++) { $user = $generator->create_user(); $testusers[$i] = $user->id; } context_helper::create_instances(null, true); context_helper::reset_caches(); for ($i = 0; $i < CONTEXT_CACHE_MAX_SIZE + 100; $i++) { context_user::instance($testusers[$i]); if ($i == CONTEXT_CACHE_MAX_SIZE - 1) { $this->assertEquals(CONTEXT_CACHE_MAX_SIZE, context_inspection::test_context_cache_size()); } else { if ($i == CONTEXT_CACHE_MAX_SIZE) { // Once the limit is reached roughly 1/3 of records should be removed from cache. $this->assertEquals((int) ceil(CONTEXT_CACHE_MAX_SIZE * (2 / 3) + 101), context_inspection::test_context_cache_size()); } } } // We keep the first 100 cached. $prevsize = context_inspection::test_context_cache_size(); for ($i = 0; $i < 100; $i++) { context_user::instance($testusers[$i]); $this->assertEquals($prevsize, context_inspection::test_context_cache_size()); } context_user::instance($testusers[102]); $this->assertEquals($prevsize + 1, context_inspection::test_context_cache_size()); unset($testusers); // Test basic test of legacy functions. // Note: watch out, the fake site might be pretty borked already. $this->assertEquals(get_system_context(), context_system::instance()); foreach ($DB->get_records('context') as $contextid => $record) { $context = context::instance_by_id($contextid); $this->assertEquals($context, get_context_instance_by_id($contextid, IGNORE_MISSING)); $this->assertEquals($context, get_context_instance($record->contextlevel, $record->instanceid)); $this->assertEquals($context->get_parent_context_ids(), get_parent_contexts($context)); if ($context->id == SYSCONTEXTID) { $this->assertFalse(get_parent_contextid($context)); } else { $this->assertSame($context->get_parent_context()->id, get_parent_contextid($context)); } } $children = get_child_contexts($systemcontext); // Using assertEquals here as assertSame fails for some reason... $this->assertEquals($children, $systemcontext->get_child_contexts()); $this->assertEquals(count($children), $DB->count_records('context') - 1); $this->resetDebugging(); unset($children); // Make sure a debugging is thrown. get_context_instance($record->contextlevel, $record->instanceid); $this->assertDebuggingCalled('get_context_instance() is deprecated, please use context_xxxx::instance() instead.', DEBUG_DEVELOPER); get_context_instance_by_id($record->id); $this->assertDebuggingCalled('get_context_instance_by_id() is deprecated, please use context::instance_by_id($id) instead.', DEBUG_DEVELOPER); get_system_context(); $this->assertDebuggingCalled('get_system_context() is deprecated, please use context_system::instance() instead.', DEBUG_DEVELOPER); get_parent_contexts($context); $this->assertDebuggingCalled('get_parent_contexts() is deprecated, please use $context->get_parent_context_ids() instead.', DEBUG_DEVELOPER); get_parent_contextid($context); $this->assertDebuggingCalled('get_parent_contextid() is deprecated, please use $context->get_parent_context() instead.', DEBUG_DEVELOPER); get_child_contexts($frontpagecontext); $this->assertDebuggingCalled('get_child_contexts() is deprecated, please use $context->get_child_contexts() instead.', DEBUG_DEVELOPER); $DB->delete_records('context', array('contextlevel' => CONTEXT_BLOCK)); create_contexts(); $this->assertDebuggingCalled('create_contexts() is deprecated, please use context_helper::create_instances() instead.', DEBUG_DEVELOPER); $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_BLOCK))); $DB->set_field('context', 'depth', 0, array('contextlevel' => CONTEXT_BLOCK)); build_context_path(); $this->assertDebuggingCalled('build_context_path() is deprecated, please use context_helper::build_all_paths() instead.', DEBUG_DEVELOPER); $this->assertFalse($DB->record_exists('context', array('depth' => 0))); $lastcourse = $DB->get_field_sql("SELECT MAX(id) FROM {course}"); $DB->delete_records('course', array('id' => $lastcourse)); $lastcategory = $DB->get_field_sql("SELECT MAX(id) FROM {course_categories}"); $DB->delete_records('course_categories', array('id' => $lastcategory)); $lastuser = $DB->get_field_sql("SELECT MAX(id) FROM {user} WHERE deleted=0"); $DB->delete_records('user', array('id' => $lastuser)); $DB->delete_records('block_instances', array('parentcontextid' => $frontpagepagecontext->id)); $DB->delete_records('course_modules', array('id' => $frontpagepagecontext->instanceid)); cleanup_contexts(); $this->assertDebuggingCalled('cleanup_contexts() is deprecated, please use context_helper::cleanup_instances() instead.', DEBUG_DEVELOPER); $count = 1; // System. $count += $DB->count_records('user', array('deleted' => 0)); $count += $DB->count_records('course_categories'); $count += $DB->count_records('course'); $count += $DB->count_records('course_modules'); $count += $DB->count_records('block_instances'); $this->assertEquals($count, $DB->count_records('context')); // Test legacy rebuild_contexts(). $context = context_course::instance($testcourses[2]); rebuild_contexts(array($context)); $this->assertDebuggingCalled('rebuild_contexts() is deprecated, please use $context->reset_paths(true) instead.', DEBUG_DEVELOPER); $context = context_course::instance($testcourses[2]); $this->assertSame($context->path, $DB->get_field('context', 'path', array('id' => $context->id))); $this->assertSame($context->depth, $DB->get_field('context', 'depth', array('id' => $context->id))); $this->assertEquals(0, $DB->count_records('context', array('depth' => 0))); $this->assertEquals(0, $DB->count_records('context', array('path' => null))); context_helper::reset_caches(); preload_course_contexts($SITE->id); $this->assertDebuggingCalled('preload_course_contexts() is deprecated, please use context_helper::preload_course() instead.', DEBUG_DEVELOPER); $this->assertEquals(1 + $DB->count_records('course_modules', array('course' => $SITE->id)), context_inspection::test_context_cache_size()); context_helper::reset_caches(); list($select, $join) = context_instance_preload_sql('c.id', CONTEXT_COURSECAT, 'ctx'); $this->assertDebuggingCalled('context_instance_preload_sql() is deprecated, please use context_helper::get_preload_record_columns_sql() instead.', DEBUG_DEVELOPER); $this->assertEquals(', ' . context_helper::get_preload_record_columns_sql('ctx'), $select); $this->assertEquals('LEFT JOIN {context} ctx ON (ctx.instanceid = c.id AND ctx.contextlevel = ' . CONTEXT_COURSECAT . ')', $join); $sql = "SELECT c.id {$select} FROM {course_categories} c {$join}"; $records = $DB->get_records_sql($sql); foreach ($records as $record) { context_instance_preload($record); $this->assertDebuggingCalled('context_instance_preload() is deprecated, please use context_helper::preload_from_record() instead.', DEBUG_DEVELOPER); $record = (array) $record; $this->assertEquals(1, count($record)); // Only id left. } $this->assertEquals(count($records), context_inspection::test_context_cache_size()); accesslib_clear_all_caches(true); $DB->delete_records('cache_flags', array()); mark_context_dirty($systemcontext->path); $this->assertDebuggingCalled('mark_context_dirty() is deprecated, please use $context->mark_dirty() instead.', DEBUG_DEVELOPER); $dirty = get_cache_flags('accesslib/dirtycontexts', time() - 2); $this->assertTrue(isset($dirty[$systemcontext->path])); accesslib_clear_all_caches(false); $DB->delete_records('cache_flags', array()); $course = $DB->get_record('course', array('id' => $testcourses[2])); $context = context_course::instance($course->id); $oldpath = $context->path; $miscid = $DB->get_field_sql("SELECT MIN(id) FROM {course_categories}"); $categorycontext = context_coursecat::instance($miscid); $course->category = $miscid; $DB->update_record('course', $course); context_moved($context, $categorycontext); $this->assertDebuggingCalled('context_moved() is deprecated, please use context::update_moved() instead.', DEBUG_DEVELOPER); $context = context_course::instance($course->id); $this->assertEquals($categorycontext, $context->get_parent_context()); $this->assertTrue($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $testcourses[2]))); delete_context(CONTEXT_COURSE, $testcourses[2]); $this->assertDebuggingCalled('delete_context() is deprecated, please use context_helper::delete_instance() instead.', DEBUG_DEVELOPER); $this->assertFalse($DB->record_exists('context', array('contextlevel' => CONTEXT_COURSE, 'instanceid' => $testcourses[2]))); delete_context(CONTEXT_COURSE, $testcourses[2], false); $this->assertDebuggingCalled('delete_context() is deprecated, please use $context->delete_content() instead.', DEBUG_DEVELOPER); $name = get_contextlevel_name(CONTEXT_COURSE); $this->assertDebuggingCalled('get_contextlevel_name() is deprecated, please use context_helper::get_level_name() instead.', DEBUG_DEVELOPER); $this->assertFalse(empty($name)); $context = context_course::instance($testcourses[2]); $name = print_context_name($context); $this->assertDebuggingCalled('print_context_name() is deprecated, please use $context->get_context_name() instead.', DEBUG_DEVELOPER); $this->assertFalse(empty($name)); $url1 = get_context_url($coursecontext); $this->assertDebuggingCalled('get_context_url() is deprecated, please use $context->get_url() instead.', DEBUG_DEVELOPER); $url2 = $coursecontext->get_url(); $this->assertEquals($url1, $url2); $this->assertInstanceOf('moodle_url', $url2); $pagecm = get_coursemodule_from_instance('page', $testpages[7]); $context = context_module::instance($pagecm->id); $coursecontext1 = get_course_context($context); $this->assertDebuggingCalled('get_course_context() is deprecated, please use $context->get_course_context(true) instead.', DEBUG_DEVELOPER); $coursecontext2 = $context->get_course_context(true); $this->assertEquals($coursecontext1, $coursecontext2); $this->assertEquals(CONTEXT_COURSE, $coursecontext2->contextlevel); $this->assertEquals($pagecm->course, get_courseid_from_context($context)); $this->assertDebuggingCalled('get_courseid_from_context() is deprecated, please use $context->get_course_context(false) instead.', DEBUG_DEVELOPER); $caps = fetch_context_capabilities($systemcontext); $this->assertDebuggingCalled('fetch_context_capabilities() is deprecated, please use $context->get_capabilities() instead.', DEBUG_DEVELOPER); $this->assertEquals($caps, $systemcontext->get_capabilities()); unset($caps); }
/** * Test get_course_completion_status */ public function test_get_course_completion_status() { global $DB, $CFG, $COMPLETION_CRITERIA_TYPES; require_once $CFG->dirroot . '/completion/criteria/completion_criteria_self.php'; require_once $CFG->dirroot . '/completion/criteria/completion_criteria_date.php'; require_once $CFG->dirroot . '/completion/criteria/completion_criteria_unenrol.php'; require_once $CFG->dirroot . '/completion/criteria/completion_criteria_activity.php'; require_once $CFG->dirroot . '/completion/criteria/completion_criteria_duration.php'; require_once $CFG->dirroot . '/completion/criteria/completion_criteria_grade.php'; require_once $CFG->dirroot . '/completion/criteria/completion_criteria_role.php'; require_once $CFG->dirroot . '/completion/criteria/completion_criteria_course.php'; $this->resetAfterTest(true); $CFG->enablecompletion = true; $student = $this->getDataGenerator()->create_user(); $teacher = $this->getDataGenerator()->create_user(); $course = $this->getDataGenerator()->create_course(array('enablecompletion' => 1, 'groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1)); $data = $this->getDataGenerator()->create_module('data', array('course' => $course->id), array('completion' => 1)); $forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id), array('completion' => 1)); $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id)); $cmdata = get_coursemodule_from_id('data', $data->cmid); $cmforum = get_coursemodule_from_id('forum', $forum->cmid); $studentrole = $DB->get_record('role', array('shortname' => 'student')); $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher')); $this->getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id); $this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id); $group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); $group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id)); // Teacher and student in different groups initially. groups_add_member($group1->id, $student->id); groups_add_member($group2->id, $teacher->id); // Set completion rules. $completion = new completion_info($course); // Loop through each criteria type and run its update_config() method. $criteriadata = new stdClass(); $criteriadata->id = $course->id; $criteriadata->criteria_activity = array(); // Some activities. $criteriadata->criteria_activity[$cmdata->id] = 1; $criteriadata->criteria_activity[$cmforum->id] = 1; // In a week criteria date value. $criteriadata->criteria_date_value = time() + WEEKSECS; // Self completion. $criteriadata->criteria_self = 1; foreach ($COMPLETION_CRITERIA_TYPES as $type) { $class = 'completion_criteria_' . $type; $criterion = new $class(); $criterion->update_config($criteriadata); } // Handle overall aggregation. $aggdata = array('course' => $course->id, 'criteriatype' => null); $aggregation = new completion_aggregation($aggdata); $aggregation->setMethod(COMPLETION_AGGREGATION_ALL); $aggregation->save(); $aggdata['criteriatype'] = COMPLETION_CRITERIA_TYPE_ACTIVITY; $aggregation = new completion_aggregation($aggdata); $aggregation->setMethod(COMPLETION_AGGREGATION_ALL); $aggregation->save(); $this->setUser($student); $result = core_completion_external::get_course_completion_status($course->id, $student->id); // We need to execute the return values cleaning process to simulate the web service server. $studentresult = external_api::clean_returnvalue(core_completion_external::get_course_completion_status_returns(), $result); // 3 different criteria. $this->assertCount(3, $studentresult['completionstatus']['completions']); $this->assertEquals(COMPLETION_AGGREGATION_ALL, $studentresult['completionstatus']['aggregation']); $this->assertFalse($studentresult['completionstatus']['completed']); $this->assertEquals('No', $studentresult['completionstatus']['completions'][0]['status']); $this->assertEquals('No', $studentresult['completionstatus']['completions'][1]['status']); $this->assertEquals('No', $studentresult['completionstatus']['completions'][2]['status']); // Teacher should see students status, they are in different groups but the teacher can access all groups. $this->setUser($teacher); $result = core_completion_external::get_course_completion_status($course->id, $student->id); // We need to execute the return values cleaning process to simulate the web service server. $teacherresult = external_api::clean_returnvalue(core_completion_external::get_course_completion_status_returns(), $result); $this->assertEquals($studentresult, $teacherresult); // Change teacher role capabilities (disable access al goups). $context = context_course::instance($course->id); assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $context); accesslib_clear_all_caches_for_unit_testing(); try { $result = core_completion_external::get_course_completion_status($course->id, $student->id); $this->fail('Exception expected due to groups permissions.'); } catch (moodle_exception $e) { $this->assertEquals('accessdenied', $e->errorcode); } // Now add the teacher in the same group. groups_add_member($group1->id, $teacher->id); $result = core_completion_external::get_course_completion_status($course->id, $student->id); // We need to execute the return values cleaning process to simulate the web service server. $teacherresult = external_api::clean_returnvalue(core_completion_external::get_course_completion_status_returns(), $result); $this->assertEquals($studentresult, $teacherresult); }
/** * @expectedException require_login_exception * @expectedExceptionMessage Activity is hidden */ public function test_view_glossary_without_permission() { $this->resetAfterTest(true); // Generate all the things. $c1 = $this->getDataGenerator()->create_course(); $g1 = $this->getDataGenerator()->create_module('glossary', array('course' => $c1->id)); $u1 = $this->getDataGenerator()->create_user(); $this->getDataGenerator()->enrol_user($u1->id, $c1->id); $ctx = context_module::instance($g1->cmid); // Revoke permission. $roles = get_archetype_roles('user'); $role = array_shift($roles); assign_capability('mod/glossary:view', CAP_PROHIBIT, $role->id, $ctx, true); accesslib_clear_all_caches_for_unit_testing(); // Assertion. $this->setUser($u1); mod_glossary_external::view_glossary($g1->id, 'letter'); }
public function test_message_get_providers_for_user_more() { global $DB; $this->resetAfterTest(); // Create a course. $course = $this->getDataGenerator()->create_course(); $coursecontext = context_course::instance($course->id); // It would probably be better to use a quiz instance as it has capability controlled messages // however mod_quiz doesn't have a data generator. // Instead we're going to use backup notifications and give and take away the capability at various levels. $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id)); $modulecontext = context_module::instance($assign->cmid); // Create and enrol a teacher. $teacherrole = $DB->get_record('role', array('shortname' => 'editingteacher'), '*', MUST_EXIST); $teacher = $this->getDataGenerator()->create_user(); role_assign($teacherrole->id, $teacher->id, $coursecontext); $enrolplugin = enrol_get_plugin('manual'); $enrolplugin->add_instance($course); $enrolinstances = enrol_get_instances($course->id, false); foreach ($enrolinstances as $enrolinstance) { if ($enrolinstance->enrol === 'manual') { break; } } $enrolplugin->enrol_user($enrolinstance, $teacher->id); // Make the teacher the current user. $this->setUser($teacher); // Teacher shouldn't have the required capability so they shouldn't be able to see the backup message. $this->assertFalse(has_capability('moodle/site:config', $modulecontext)); $providers = message_get_providers_for_user($teacher->id); $this->assertFalse($this->message_type_present('moodle', 'backup', $providers)); // Give the user the required capability in an activity module. // They should now be able to see the backup message. assign_capability('moodle/site:config', CAP_ALLOW, $teacherrole->id, $modulecontext->id, true); accesslib_clear_all_caches_for_unit_testing(); $modulecontext = context_module::instance($assign->cmid); $this->assertTrue(has_capability('moodle/site:config', $modulecontext)); $providers = message_get_providers_for_user($teacher->id); $this->assertTrue($this->message_type_present('moodle', 'backup', $providers)); // Prohibit the capability for the user at the course level. // This overrules the CAP_ALLOW at the module level. // They should not be able to see the backup message. assign_capability('moodle/site:config', CAP_PROHIBIT, $teacherrole->id, $coursecontext->id, true); accesslib_clear_all_caches_for_unit_testing(); $modulecontext = context_module::instance($assign->cmid); $this->assertFalse(has_capability('moodle/site:config', $modulecontext)); $providers = message_get_providers_for_user($teacher->id); // Actually, handling PROHIBITs would be too expensive. We do not // care if users with PROHIBITs see a few more preferences than they should. // $this->assertFalse($this->message_type_present('moodle', 'backup', $providers)); }
/** * Commenting on a plan. */ public function test_comment_add_plan() { $this->resetAfterTest(); $dg = $this->getDataGenerator(); $lpg = $dg->get_plugin_generator('core_competency'); $u1 = $dg->create_user(); $u2 = $dg->create_user(); $u3 = $dg->create_user(); $userroleid = $dg->create_role(); $reviewerroleid = $dg->create_role(); assign_capability('moodle/competency:planviewowndraft', CAP_ALLOW, $userroleid, context_system::instance()->id, true); assign_capability('moodle/competency:planviewown', CAP_ALLOW, $userroleid, context_system::instance()->id, true); assign_capability('moodle/competency:planviewdraft', CAP_ALLOW, $reviewerroleid, context_system::instance()->id, true); assign_capability('moodle/competency:planmanage', CAP_ALLOW, $reviewerroleid, context_system::instance()->id, true); assign_capability('moodle/competency:plancomment', CAP_ALLOW, $reviewerroleid, context_system::instance()->id, true); $dg->role_assign($userroleid, $u1->id, context_user::instance($u1->id)); $dg->role_assign($reviewerroleid, $u2->id, context_user::instance($u1->id)); $dg->role_assign($reviewerroleid, $u3->id, context_system::instance()); accesslib_clear_all_caches_for_unit_testing(); $p1 = $lpg->create_plan(array('userid' => $u1->id)); // Post a comment in own plan, no reviewer. Nobody is messaged. $this->setUser($u1); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(0, $messages); // Post a comment in plan as someone else, no reviewer. The owner is messages. $this->setUser($u3); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(1, $messages); $message = array_pop($messages); $this->assertEquals(core_user::get_noreply_user()->id, $message->useridfrom); $this->assertEquals($u1->id, $message->useridto); // Post a comment in a plan with reviewer. The reviewer is messaged. $p1->set_reviewerid($u2->id); $p1->update(); $this->setUser($u1); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(1, $messages); $message = array_pop($messages); $this->assertEquals(core_user::get_noreply_user()->id, $message->useridfrom); $this->assertEquals($u2->id, $message->useridto); // Post a comment as reviewer in a plan being reviewed. The owner is messaged. $p1->set_reviewerid($u2->id); $p1->update(); $this->setUser($u2); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(1, $messages); $message = array_pop($messages); $this->assertEquals(core_user::get_noreply_user()->id, $message->useridfrom); $this->assertEquals($u1->id, $message->useridto); // Post a comment as someone else in a plan being reviewed. The owner and reviewer are messaged. $p1->set_reviewerid($u2->id); $p1->update(); $this->setUser($u3); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(2, $messages); $message1 = array_shift($messages); $message2 = array_shift($messages); $this->assertEquals(core_user::get_noreply_user()->id, $message1->useridfrom); $this->assertEquals($u1->id, $message1->useridto); $this->assertEquals(core_user::get_noreply_user()->id, $message2->useridfrom); $this->assertEquals($u2->id, $message2->useridto); $p1->set_reviewerid(null); $p1->update(); // Test message content. $this->setUser($u3); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('Hello world!'); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(1, $messages); $message = array_pop($messages); $expectedurlname = $p1->get_name(); $expectedurl = url::plan($p1->get_id()); $this->assertTrue(strpos($message->fullmessage, 'Hello world!') !== false); $this->assertTrue(strpos($message->fullmessagehtml, 'Hello world!') !== false); $this->assertEquals(FORMAT_MOODLE, $message->fullmessageformat); $this->assertEquals($expectedurl->out(false), $message->contexturl); $this->assertEquals($expectedurlname, $message->contexturlname); // Test message content as HTML. $this->setUser($u3); $comment = $p1->get_comment_object(); $sink = $this->redirectMessages(); $comment->add('<em>Hello world!</em>', FORMAT_HTML); $messages = $sink->get_messages(); $sink->close(); $this->assertCount(1, $messages); $message = array_pop($messages); $expectedurlname = $p1->get_name(); $expectedurl = url::plan($p1->get_id()); $this->assertTrue(strpos($message->fullmessage, '<em>Hello world!</em>') !== false); $this->assertTrue(strpos($message->fullmessagehtml, '<em>Hello world!</em>') !== false); $this->assertEquals(FORMAT_HTML, $message->fullmessageformat); $this->assertEquals($expectedurl->out(false), $message->contexturl); $this->assertEquals($expectedurlname, $message->contexturlname); }
/** * Test get_calendar_events */ public function test_get_calendar_events() { global $DB, $USER; $this->resetAfterTest(true); $this->setAdminUser(); // Create a few stuff to test with. $user = $this->getDataGenerator()->create_user(); $course = $this->getDataGenerator()->create_course(); $record = new stdClass(); $record->courseid = $course->id; $group = $this->getDataGenerator()->create_group($record); $beforecount = $DB->count_records('event'); // Let's create a few events. $siteevent = $this->create_calendar_event('site', $USER->id, 'site'); // This event will have description with an inline fake image. $draftidfile = file_get_unused_draft_itemid(); $usercontext = context_course::instance($course->id); $filerecord = array('contextid' => $usercontext->id, 'component' => 'user', 'filearea' => 'draft', 'itemid' => $draftidfile, 'filepath' => '/', 'filename' => 'fakeimage.png'); $fs = get_file_storage(); $fs->create_file_from_string($filerecord, 'img contents'); $record = new stdClass(); $record->courseid = $course->id; $record->description = array('format' => FORMAT_HTML, 'text' => 'Text with img <img src="@@PLUGINFILE@@/fakeimage.png">', 'itemid' => $draftidfile); $courseevent = $this->create_calendar_event('course', $USER->id, 'course', 2, time(), $record); $userevent = $this->create_calendar_event('user', $USER->id); $record = new stdClass(); $record->courseid = $course->id; $record->groupid = $group->id; $groupevent = $this->create_calendar_event('group', $USER->id, 'group', 0, time(), $record); $paramevents = array('eventids' => array($siteevent->id), 'courseids' => array($course->id), 'groupids' => array($group->id)); $options = array('siteevents' => true, 'userevents' => true); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); // Check to see if we got all events. $this->assertEquals(5, count($events['events'])); $this->assertEquals(0, count($events['warnings'])); $options = array('siteevents' => true, 'userevents' => true, 'timeend' => time() + 7 * WEEKSECS); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(5, count($events['events'])); $this->assertEquals(0, count($events['warnings'])); // Expect the same URL in the description of two different events (because they are repeated). $coursecontext = context_course::instance($course->id); $expectedurl = "webservice/pluginfile.php/{$coursecontext->id}/calendar/event_description/{$courseevent->id}/fakeimage.png"; $withdescription = 0; foreach ($events['events'] as $event) { if (!empty($event['description'])) { $withdescription++; $this->assertContains($expectedurl, $event['description']); } } $this->assertEquals(2, $withdescription); // Let's play around with caps. $this->setUser($user); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(2, count($events['events'])); // site, user. $this->assertEquals(2, count($events['warnings'])); // course, group. $role = $DB->get_record('role', array('shortname' => 'student')); $this->getDataGenerator()->enrol_user($user->id, $course->id, $role->id); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(4, count($events['events'])); // site, user, both course events. $this->assertEquals(1, count($events['warnings'])); // group. $options = array('siteevents' => true, 'userevents' => true, 'timeend' => time() + HOURSECS); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(3, count($events['events'])); // site, user, one course event. $this->assertEquals(1, count($events['warnings'])); // group. groups_add_member($group, $user); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(4, count($events['events'])); // site, user, group, one course event. $this->assertEquals(0, count($events['warnings'])); $paramevents = array('courseids' => array($course->id), 'groupids' => array($group->id)); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(4, count($events['events'])); // site, user, group, one course event. $this->assertEquals(0, count($events['warnings'])); $paramevents = array('groupids' => array($group->id, 23)); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(3, count($events['events'])); // site, user, group. $this->assertEquals(1, count($events['warnings'])); $paramevents = array('courseids' => array(23)); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(2, count($events['events'])); // site, user. $this->assertEquals(1, count($events['warnings'])); $paramevents = array(); $options = array('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7 * WEEKSECS); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(0, count($events['events'])); // nothing returned. $this->assertEquals(0, count($events['warnings'])); $paramevents = array('eventids' => array($siteevent->id, $groupevent->id)); $options = array('siteevents' => false, 'userevents' => false, 'timeend' => time() + 7 * WEEKSECS); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(2, count($events['events'])); // site, group. $this->assertEquals(0, count($events['warnings'])); $paramevents = array('eventids' => array($siteevent->id)); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(1, count($events['events'])); // site. $this->assertEquals(0, count($events['warnings'])); // Try getting a course event by its id. $paramevents = array('eventids' => array($courseevent->id)); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertEquals(1, count($events['events'])); $this->assertEquals(0, count($events['warnings'])); // Now, create an activity event. $this->setAdminUser(); $nexttime = time() + DAYSECS; $assign = $this->getDataGenerator()->create_module('assign', array('course' => $course->id, 'duedate' => $nexttime)); $this->setUser($user); $paramevents = array('courseids' => array($course->id)); $options = array('siteevents' => true, 'userevents' => true, 'timeend' => time() + WEEKSECS); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); $this->assertCount(5, $events['events']); // Hide the assignment. set_coursemodule_visible($assign->cmid, 0); // Empty all the caches that may be affected by this change. accesslib_clear_all_caches_for_unit_testing(); course_modinfo::clear_instance_cache(); $events = core_calendar_external::get_calendar_events($paramevents, $options); $events = external_api::clean_returnvalue(core_calendar_external::get_calendar_events_returns(), $events); // Expect one less. $this->assertCount(4, $events['events']); }
/** * Test get_page_contents without the viewpage capability. */ public function test_get_page_contents_without_viewpage_capability() { // Prohibit capability = mod/wiki:viewpage on the course for students. $contextcourse = context_course::instance($this->course->id); assign_capability('mod/wiki:viewpage', CAP_PROHIBIT, $this->studentrole->id, $contextcourse->id); accesslib_clear_all_caches_for_unit_testing(); $this->setUser($this->student); $this->setExpectedException('moodle_exception'); mod_wiki_external::get_page_contents($this->firstpage->id); }
/** * Check that the user has not forgotten to clean anything up, and if they * have, display a rude message and clean it up for them. */ private function automatic_clean_up() { global $DB, $CFG; $cleanmore = false; // Drop any test tables that were created. foreach ($this->tables as $tablename => $notused) { $this->drop_test_table($tablename); } // Switch back to the real DB if necessary. if ($DB !== $this->realdb) { $this->revert_to_real_db(); $cleanmore = true; } // Switch back to the real CFG if necessary. if (isset($CFG->testcfg)) { $this->revert_to_real_cfg(); $cleanmore = true; } // revert_global_user_id if necessary. if (!is_null($this->realuserid)) { $this->revert_global_user_id(); $cleanmore = true; } if ($cleanmore) { accesslib_clear_all_caches_for_unit_testing(); $course = 'reset'; get_fast_modinfo($course); } }
/** * Setup the DB fixture data */ public function setup() { parent::setUp(); $tables = array('block_instance', 'cache_flags', 'capabilities', 'context', 'context_temp', 'course', 'course_modules', 'course_categories', 'course_sections', 'files', 'files_cleanup', 'grade_items', 'grade_categories', 'groups', 'groups_members', 'modules', 'role', 'role_names', 'role_context_levels', 'role_assignments', 'role_capabilities', 'user'); $this->create_test_tables($tables, 'lib'); $this->create_test_table('forum', 'mod/forum'); $this->switch_to_test_db(); global $DB, $CFG; // Insert needed capabilities $DB->insert_record('capabilities', array('id' => 45, 'name' => 'moodle/course:update', 'cattype' => 'write', 'contextlevel' => 50, 'component' => 'moodle', 'riskbitmask' => 4)); $DB->insert_record('capabilities', array('id' => 14, 'name' => 'moodle/site:backup', 'cattype' => 'write', 'contextlevel' => 50, 'component' => 'moodle', 'riskbitmask' => 28)); $DB->insert_record('capabilities', array('id' => 17, 'name' => 'moodle/site:restore', 'cattype' => 'write', 'contextlevel' => 50, 'component' => 'moodle', 'riskbitmask' => 28)); $DB->insert_record('capabilities', array('id' => 52, 'name' => 'moodle/course:managefiles', 'cattype' => 'write', 'contextlevel' => 50, 'component' => 'moodle', 'riskbitmask' => 4)); $DB->insert_record('capabilities', array('id' => 73, 'name' => 'moodle/user:editownprofile', 'cattype' => 'write', 'contextlevel' => 10, 'component' => 'moodle', 'riskbitmask' => 16)); // Insert system context $DB->insert_record('context', array('id' => 1, 'contextlevel' => 10, 'instanceid' => 0, 'path' => '/1', 'depth' => 1)); $DB->insert_record('context', array('id' => 2, 'contextlevel' => 50, 'instanceid' => 1, 'path' => '/1/2', 'depth' => 2)); // Insert site course $DB->insert_record('course', array('category' => 0, 'sortorder' => 1, 'fullname' => 'Test site', 'shortname' => 'test', 'format' => 'site', 'modinfo' => 'a:0:{}')); // User and capability stuff (stolen from testaccesslib.php) $syscontext = get_system_context(false); $adminrole = create_role(get_string('administrator'), 'admin', get_string('administratordescription'), 'moodle/legacy:admin'); /// Now is the correct moment to install capabilities - after creation of legacy roles, but before assigning of roles assign_capability('moodle/site:doanything', CAP_ALLOW, $adminrole, $syscontext->id); update_capabilities('moodle'); update_capabilities('mod/forum'); $contexts = $this->load_test_data('context', array('contextlevel', 'instanceid', 'path', 'depth'), array(1 => array(40, 666, '', 2))); $contexts[0] = $syscontext; $contexts[1]->path = $contexts[0]->path . '/' . $contexts[1]->id; $this->testdb->set_field('context', 'path', $contexts[1]->path, array('id' => $contexts[1]->id)); $users = $this->load_test_data('user', array('username', 'confirmed', 'deleted'), array('a' => array('a', 1, 0))); $admin = $this->testdb->get_record('role', array('shortname' => 'admin')); $ras = $this->load_test_data('role_assignments', array('userid', 'roleid', 'contextid'), array('a' => array($users['a']->id, $admin->id, $contexts[0]->id))); $this->switch_global_user_id(1); accesslib_clear_all_caches_for_unit_testing(); // Create a coursecat $newcategory = new stdClass(); $newcategory->name = 'test category'; $newcategory->sortorder = 999; if (!($newcategory->id = $DB->insert_record('course_categories', $newcategory))) { print_error('cannotcreatecategory', '', '', format_string($newcategory->name)); } $newcategory->context = get_context_instance(CONTEXT_COURSECAT, $newcategory->id); mark_context_dirty($newcategory->context->path); fix_course_sortorder(); // Required to build course_categories.depth and .path. $this->coursecat = $DB->get_record('course_categories', array('id' => $newcategory->id)); // Create a course $coursedata = new stdClass(); $coursedata->category = $newcategory->id; $coursedata->shortname = 'testcourse'; $coursedata->fullname = 'Test Course'; try { $this->course = create_course($coursedata); } catch (moodle_exception $e) { // Most likely the result of an aborted unit test: the test course was not correctly deleted $this->course = $DB->get_record('course', array('shortname' => $coursedata->shortname)); } // Create a user $this->user = new stdClass(); $this->user->username = '******'; $this->user->password = '******'; $this->user->firstname = 'TestUser'; $this->user->lastname = 'TestUser'; $this->user->email = '*****@*****.**'; try { $this->user->id = create_user($this->user); } catch (moodle_exception $e) { // Most likely the result of an aborted unit test: the test user was not correctly deleted $this->user->id = $DB->get_field('user', 'id', array('username' => $this->user->username)); } // Assign user to course // role_assign(5, $this->user->id, 0, get_context_instance(CONTEXT_COURSE, $this->course->id)->id); // Create a module $module = new stdClass(); $module->intro = 'Forum used for testing filelib API'; $module->type = 'general'; $module->forcesubscribe = 1; $module->format = 1; $module->name = 'Test Forum'; $module->module = $DB->get_field('modules', 'id', array('name' => 'forum')); $module->modulename = 'forum'; $module->add = 'forum'; $module->cmidnumber = ''; $module->course = $this->course->id; $module->instance = forum_add_instance($module, ''); $this->section = get_course_section(1, $this->course->id); $module->section = $this->section->id; $module->coursemodule = add_course_module($module); add_mod_to_section($module); $module->cmidnumber = set_coursemodule_idnumber($module->coursemodule, ''); rebuild_course_cache($this->course->id); $this->module = $DB->get_record('forum', array('id' => $module->instance)); $this->module->instance = $module->instance; // Update local copy of course $this->course = $DB->get_record('course', array('id' => $this->course->id)); }
public function test_list_user_competencies_to_review() { $dg = $this->getDataGenerator(); $this->resetAfterTest(); $ccg = $dg->get_plugin_generator('core_competency'); $sysctx = context_system::instance(); $this->setAdminUser(); $reviewer = $dg->create_user(); $roleallow = $dg->create_role(); $roleprohibit = $dg->create_role(); assign_capability('moodle/competency:usercompetencyreview', CAP_ALLOW, $roleallow, $sysctx->id); assign_capability('moodle/competency:usercompetencyreview', CAP_PROHIBIT, $roleprohibit, $sysctx->id); role_assign($roleallow, $reviewer->id, $sysctx->id); accesslib_clear_all_caches_for_unit_testing(); $u1 = $dg->create_user(); $u2 = $dg->create_user(); $f1 = $ccg->create_framework(); $c1 = $ccg->create_competency(['competencyframeworkid' => $f1->get_id()]); $c2 = $ccg->create_competency(['competencyframeworkid' => $f1->get_id()]); $c3 = $ccg->create_competency(['competencyframeworkid' => $f1->get_id()]); $uc1a = $ccg->create_user_competency(['userid' => $u1->id, 'competencyid' => $c1->get_id(), 'status' => user_competency::STATUS_IDLE]); $uc1b = $ccg->create_user_competency(['userid' => $u1->id, 'competencyid' => $c2->get_id(), 'status' => user_competency::STATUS_WAITING_FOR_REVIEW]); $uc1c = $ccg->create_user_competency(['userid' => $u1->id, 'competencyid' => $c3->get_id(), 'status' => user_competency::STATUS_IN_REVIEW, 'reviewerid' => $reviewer->id]); $uc2a = $ccg->create_user_competency(['userid' => $u2->id, 'competencyid' => $c1->get_id(), 'status' => user_competency::STATUS_WAITING_FOR_REVIEW]); $uc2b = $ccg->create_user_competency(['userid' => $u2->id, 'competencyid' => $c2->get_id(), 'status' => user_competency::STATUS_IDLE]); $uc2c = $ccg->create_user_competency(['userid' => $u2->id, 'competencyid' => $c3->get_id(), 'status' => user_competency::STATUS_IN_REVIEW]); // The reviewer can review all plans waiting for review, or in review where they are the reviewer. $this->setUser($reviewer); $result = api::list_user_competencies_to_review(); $this->assertEquals(3, $result['count']); $this->assertEquals($uc2a->get_id(), $result['competencies'][0]->usercompetency->get_id()); $this->assertEquals($uc1b->get_id(), $result['competencies'][1]->usercompetency->get_id()); $this->assertEquals($uc1c->get_id(), $result['competencies'][2]->usercompetency->get_id()); // The reviewer cannot view the plans when they do not have the permission in the user's context. role_assign($roleprohibit, $reviewer->id, context_user::instance($u2->id)->id); accesslib_clear_all_caches_for_unit_testing(); $result = api::list_user_competencies_to_review(); $this->assertEquals(2, $result['count']); $this->assertEquals($uc1b->get_id(), $result['competencies'][0]->usercompetency->get_id()); $this->assertEquals($uc1c->get_id(), $result['competencies'][1]->usercompetency->get_id()); }