/** * Create an evidence from a list of parameters. * * Requires no capability because evidence can be added in many situations under any user. * * @param int $userid The user id for which evidence is added. * @param competency|int $competencyorid The competency, or its id for which evidence is added. * @param context|int $contextorid The context in which the evidence took place. * @param int $action The type of action to take on the competency. \core_competency\evidence::ACTION_*. * @param string $descidentifier The strings identifier. * @param string $desccomponent The strings component. * @param mixed $desca Any arguments the string requires. * @param bool $recommend When true, the user competency will be sent for review. * @param string $url The url the evidence may link to. * @param int $grade The grade, or scale ID item. * @param int $actionuserid The ID of the user who took the action of adding the evidence. Null when system. * This should be used when the action was taken by a real person, this will allow * to keep track of all the evidence given by a certain person. * @param string $note A note to attach to the evidence. * @return evidence * @throws coding_exception * @throws invalid_persistent_exception * @throws moodle_exception */ public static function add_evidence($userid, $competencyorid, $contextorid, $action, $descidentifier, $desccomponent, $desca = null, $recommend = false, $url = null, $grade = null, $actionuserid = null, $note = null) { global $DB; static::require_enabled(); // Some clearly important variable assignments right there. $competencyid = $competencyorid; $competency = null; if (is_object($competencyid)) { $competency = $competencyid; $competencyid = $competency->get_id(); } $contextid = $contextorid; $context = $contextorid; if (is_object($contextorid)) { $contextid = $contextorid->id; } else { $context = context::instance_by_id($contextorid); } $setucgrade = false; $ucgrade = null; $ucproficiency = null; $usercompetencycourse = null; // Fetch or create the user competency. $usercompetency = user_competency::get_record(array('userid' => $userid, 'competencyid' => $competencyid)); if (!$usercompetency) { $usercompetency = user_competency::create_relation($userid, $competencyid); $usercompetency->create(); } // What should we be doing? switch ($action) { // Completing a competency. case evidence::ACTION_COMPLETE: // The logic here goes like this: // // if rating outside a course // - set the default grade and proficiency ONLY if there is no current grade // else we are in a course // - set the defautl grade and proficiency in the course ONLY if there is no current grade in the course // - then check the course settings to see if we should push the rating outside the course // - if we should push it // --- push it only if the user_competency (outside the course) has no grade // Done. if ($grade !== null) { throw new coding_exception("The grade MUST NOT be set with a 'completing' evidence."); } // Fetch the default grade to attach to the evidence. if (empty($competency)) { $competency = new competency($competencyid); } list($grade, $proficiency) = $competency->get_default_grade(); // Add user_competency_course record when in a course or module. if (in_array($context->contextlevel, array(CONTEXT_COURSE, CONTEXT_MODULE))) { $coursecontext = $context->get_course_context(); $courseid = $coursecontext->instanceid; $filterparams = array('userid' => $userid, 'competencyid' => $competencyid, 'courseid' => $courseid); // Fetch or create user competency course. $usercompetencycourse = user_competency_course::get_record($filterparams); if (!$usercompetencycourse) { $usercompetencycourse = user_competency_course::create_relation($userid, $competencyid, $courseid); $usercompetencycourse->create(); } // Only update the grade and proficiency if there is not already a grade. if ($usercompetencycourse->get_grade() === null) { // Set grade. $usercompetencycourse->set_grade($grade); // Set proficiency. $usercompetencycourse->set_proficiency($proficiency); } // Check the course settings to see if we should push to user plans. $coursesettings = course_competency_settings::get_by_courseid($courseid); $setucgrade = $coursesettings->get_pushratingstouserplans(); if ($setucgrade) { // Only push to user plans if there is not already a grade. if ($usercompetency->get_grade() !== null) { $setucgrade = false; } else { $ucgrade = $grade; $ucproficiency = $proficiency; } } } else { // When completing the competency we fetch the default grade from the competency. But we only mark // the user competency when a grade has not been set yet. Complete is an action to use with automated systems. if ($usercompetency->get_grade() === null) { $setucgrade = true; $ucgrade = $grade; $ucproficiency = $proficiency; } } break; // We override the grade, even overriding back to not set. // We override the grade, even overriding back to not set. case evidence::ACTION_OVERRIDE: $setucgrade = true; $ucgrade = $grade; if (empty($competency)) { $competency = new competency($competencyid); } if ($ucgrade !== null) { $ucproficiency = $competency->get_proficiency_of_grade($ucgrade); } // Add user_competency_course record when in a course or module. if (in_array($context->contextlevel, array(CONTEXT_COURSE, CONTEXT_MODULE))) { $coursecontext = $context->get_course_context(); $courseid = $coursecontext->instanceid; $filterparams = array('userid' => $userid, 'competencyid' => $competencyid, 'courseid' => $courseid); // Fetch or create user competency course. $usercompetencycourse = user_competency_course::get_record($filterparams); if (!$usercompetencycourse) { $usercompetencycourse = user_competency_course::create_relation($userid, $competencyid, $courseid); $usercompetencycourse->create(); } // Get proficiency. $proficiency = $ucproficiency; if ($proficiency === null) { if (empty($competency)) { $competency = new competency($competencyid); } $proficiency = $competency->get_proficiency_of_grade($grade); } // Set grade. $usercompetencycourse->set_grade($grade); // Set proficiency. $usercompetencycourse->set_proficiency($proficiency); $coursesettings = course_competency_settings::get_by_courseid($courseid); if (!$coursesettings->get_pushratingstouserplans()) { $setucgrade = false; } } break; // Simply logging an evidence. // Simply logging an evidence. case evidence::ACTION_LOG: if ($grade !== null) { throw new coding_exception("The grade MUST NOT be set when 'logging' an evidence."); } break; // Whoops, this is not expected. // Whoops, this is not expected. default: throw new coding_exception('Unexpected action parameter when registering an evidence.'); break; } // Should we recommend? if ($recommend && $usercompetency->get_status() == user_competency::STATUS_IDLE) { $usercompetency->set_status(user_competency::STATUS_WAITING_FOR_REVIEW); } // Setting the grade and proficiency for the user competency. $wascompleted = false; if ($setucgrade == true) { if (!$usercompetency->get_proficiency() && $ucproficiency) { $wascompleted = true; } $usercompetency->set_grade($ucgrade); $usercompetency->set_proficiency($ucproficiency); } // Prepare the evidence. $record = new stdClass(); $record->usercompetencyid = $usercompetency->get_id(); $record->contextid = $contextid; $record->action = $action; $record->descidentifier = $descidentifier; $record->desccomponent = $desccomponent; $record->grade = $grade; $record->actionuserid = $actionuserid; $record->note = $note; $evidence = new evidence(0, $record); $evidence->set_desca($desca); $evidence->set_url($url); // Validate both models, we should not operate on one if the other will not save. if (!$usercompetency->is_valid()) { throw new invalid_persistent_exception($usercompetency->get_errors()); } else { if (!$evidence->is_valid()) { throw new invalid_persistent_exception($evidence->get_errors()); } } // Save the user_competency_course record. if ($usercompetencycourse !== null) { // Validate and update. if (!$usercompetencycourse->is_valid()) { throw new invalid_persistent_exception($usercompetencycourse->get_errors()); } $usercompetencycourse->update(); } // Finally save. Pheww! $usercompetency->update(); $evidence->create(); // Trigger the evidence_created event. \core\event\competency_evidence_created::create_from_evidence($evidence, $usercompetency, $recommend)->trigger(); // The competency was marked as completed, apply the rules. if ($wascompleted) { self::apply_competency_rules_from_usercompetency($usercompetency, $competency); } return $evidence; }
/** * Tests for the user_competency_course data when api::add_evidence() is invoked when * grading a user competency in a course. */ public function test_add_evidence_user_competency_course_grade_in_course() { global $USER; $this->resetAfterTest(true); $dg = $this->getDataGenerator(); // Create a course. $course = $dg->create_course(); $record = array('courseid' => $course->id, 'pushratingstouserplans' => false); $settings = new course_competency_settings(0, (object) $record); $settings->create(); $coursecontext = context_course::instance($course->id); // Create a student and enrol into the course. $student = $dg->create_user(); $studentarch = get_archetype_roles('student'); $studentrole = array_shift($studentarch); $dg->role_assign($studentrole->id, $student->id, $coursecontext->id); $dg->enrol_user($student->id, $course->id, $studentrole->id); // Create a competency for the course. $lpg = $dg->get_plugin_generator('core_competency'); $framework = $lpg->create_framework(); // Do not push ratings from course to user plans. $comp = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id())); $lpg->create_course_competency(array('courseid' => $course->id, 'competencyid' => $comp->get_id())); // Query for user_competency_course data. $filterparams = array('userid' => $student->id, 'competencyid' => $comp->get_id(), 'courseid' => $course->id); // Add evidence that sets a grade to the course. $evidence = api::add_evidence($student->id, $comp, $coursecontext, evidence::ACTION_OVERRIDE, 'commentincontext', 'core', null, false, null, 3, $USER->id); // Get user competency course record. $usercompcourse = \core_competency\user_competency_course::get_record($filterparams); // There should be a user_competency_course object when adding a grade. $this->assertNotEmpty($usercompcourse); $grade = $evidence->get_grade(); $this->assertEquals($grade, $usercompcourse->get_grade()); $this->assertEquals(3, $usercompcourse->get_grade()); $proficiency = $comp->get_proficiency_of_grade($grade); $this->assertEquals($proficiency, $usercompcourse->get_proficiency()); // Confirm that the user competency's grade/proficiency has not been affected by the grade. $usercompetencyparams = ['userid' => $student->id, 'competencyid' => $comp->get_id()]; $usercompetency = \core_competency\user_competency::get_record($usercompetencyparams); $this->assertNotEmpty($usercompetency); $this->assertNotEquals($usercompcourse->get_grade(), $usercompetency->get_grade()); $this->assertNotEquals($usercompcourse->get_proficiency(), $usercompetency->get_proficiency()); }
public function test_who_can_change_settings() { global $CFG, $DB; $this->resetAfterTest(true); $syscontext = context_system::instance(); $dg = $this->getDataGenerator(); $lpg = $dg->get_plugin_generator('core_competency'); $role = create_role('Settings changer role', 'settingschanger', 'Someone who can change course competency settings'); assign_capability('moodle/competency:coursecompetencyconfigure', CAP_ALLOW, $role, $syscontext->id); assign_capability('moodle/competency:competencygrade', CAP_ALLOW, $role, $syscontext->id); assign_capability('moodle/competency:coursecompetencyview', CAP_ALLOW, $role, $syscontext->id); assign_capability('moodle/competency:planview', CAP_ALLOW, $role, $syscontext->id); $gradedrole = create_role('Graded role', 'graded', 'Someone who can be graded'); assign_capability('moodle/competency:coursecompetencygradable', CAP_ALLOW, $gradedrole, $syscontext->id); $c1 = $dg->create_course(); $u1 = $dg->create_user(); $u2 = $dg->create_user(); $u3 = $dg->create_user(); $framework = $lpg->create_framework(); $comp1 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id())); $comp2 = $lpg->create_competency(array('competencyframeworkid' => $framework->get_id())); $lpg->create_course_competency(array('competencyid' => $comp1->get_id(), 'courseid' => $c1->id)); $lpg->create_course_competency(array('competencyid' => $comp2->get_id(), 'courseid' => $c1->id)); // Enrol the user. $dg->enrol_user($u1->id, $c1->id); role_assign($gradedrole, $u1->id, $syscontext->id); // Assign roles. role_assign($role, $u2->id, $syscontext->id); $this->setUser($u2); set_config('pushcourseratingstouserplans', true, 'core_competency'); $coursesettings = course_competency_settings::get_by_courseid($c1->id); $this->assertTrue((bool) $coursesettings->get_pushratingstouserplans()); set_config('pushcourseratingstouserplans', false, 'core_competency'); $coursesettings = course_competency_settings::get_by_courseid($c1->id); $this->assertFalse((bool) $coursesettings->get_pushratingstouserplans()); api::update_course_competency_settings($c1->id, (object) array('pushratingstouserplans' => true)); $coursesettings = course_competency_settings::get_by_courseid($c1->id); $this->assertTrue((bool) $coursesettings->get_pushratingstouserplans()); set_config('pushcourseratingstouserplans', true, 'core_competency'); api::update_course_competency_settings($c1->id, (object) array('pushratingstouserplans' => false)); $coursesettings = course_competency_settings::get_by_courseid($c1->id); $this->assertFalse((bool) $coursesettings->get_pushratingstouserplans()); // Right now the setting is false. api::grade_competency_in_course($c1->id, $u1->id, $comp1->get_id(), 1, 'Note'); $filterparams = array('userid' => $u1->id, 'competencyid' => $comp1->get_id()); $usercompcourse = \core_competency\user_competency_course::get_record($filterparams); $usercomp = \core_competency\user_competency::get_record($filterparams); // No grade in plan - only a grade in the course. $this->assertEmpty($usercomp->get_grade()); $this->assertEquals(1, $usercompcourse->get_grade()); api::update_course_competency_settings($c1->id, (object) array('pushratingstouserplans' => true)); api::grade_competency_in_course($c1->id, $u1->id, $comp1->get_id(), 2, 'Note 2'); $filterparams = array('userid' => $u1->id, 'competencyid' => $comp1->get_id()); $usercompcourse = \core_competency\user_competency_course::get_record($filterparams); $usercomp = \core_competency\user_competency::get_record($filterparams); // Updated grade in plan - updated grade in the course. $this->assertEquals(2, $usercomp->get_grade()); $this->assertEquals(2, $usercompcourse->get_grade()); $this->setUser($u3); $this->setExpectedException('required_capability_exception'); api::update_course_competency_settings($c1->id, (object) array('pushratingstouserplans' => false)); }