Merge branch 'MDL-56567-master' of https://github.com/matthewhilton/moodle
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
/**
|
||||
* Course competency override grade element.
|
||||
*
|
||||
* @package tool_lp
|
||||
* @copyright 2022 Matthew Hilton <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
require_once($CFG->libdir . '/form/advcheckbox.php');
|
||||
|
||||
/**
|
||||
* Course competency override grade element.
|
||||
*
|
||||
* @package tool_lp
|
||||
* @copyright 2022 Matthew Hilton <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class tool_lp_course_competency_overridegrade_form_element extends MoodleQuickForm_advcheckbox {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $elementname Element name
|
||||
* @param mixed $elementlabel Label(s) for an element
|
||||
* @param array $options Options to control the element's display
|
||||
*/
|
||||
public function __construct($elementname=null, $elementlabel=null, $options=[]) {
|
||||
if ($elementname == null) {
|
||||
// This is broken quickforms messing with the constructors.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($options['cmid'])) {
|
||||
$cmid = $options['cmid'];
|
||||
|
||||
$current = \core_competency\api::list_course_module_competencies_in_course_module($cmid);
|
||||
|
||||
// Note: We just pick the override grade value set on the first course_module_competency.
|
||||
// Because in the UI we force them to be the same for all.
|
||||
if (!empty($current)) {
|
||||
$one = array_pop($current);
|
||||
$this->setValue($one->get('overridegrade'));
|
||||
}
|
||||
}
|
||||
|
||||
parent::__construct($elementname, $elementlabel);
|
||||
}
|
||||
}
|
||||
@@ -165,6 +165,7 @@ $string['nouserevidence'] = 'No evidence of prior learning has been added yet.';
|
||||
$string['nouserplans'] = 'No learning plans have been created yet.';
|
||||
$string['oneplanwascreated'] = 'A learning plan was created';
|
||||
$string['outcome'] = 'Outcome';
|
||||
$string['overridegrade'] = 'Override existing competency grade when completed.';
|
||||
$string['path'] = 'Path:';
|
||||
$string['parentcompetency'] = 'Parent';
|
||||
$string['parentcompetency_edit'] = 'Edit parent';
|
||||
|
||||
+10
-1
@@ -161,6 +161,12 @@ function tool_lp_coursemodule_standard_elements($formwrapper, $mform) {
|
||||
'tool_lp_course_competency_rule_form_element');
|
||||
// Reuse the same options.
|
||||
$mform->addElement('course_competency_rule', 'competency_rule', get_string('uponcoursemodulecompletion', 'tool_lp'), $options);
|
||||
|
||||
$overrideelementfile = "$CFG->dirroot/$CFG->admin/tool/lp/classes/course_competency_overridegrade_form_element.php";
|
||||
MoodleQuickForm::registerElementType('course_competency_overridegrade', $overrideelementfile,
|
||||
'tool_lp_course_competency_overridegrade_form_element');
|
||||
$mform->addElement('course_competency_overridegrade', 'override_grade', get_string('overridegrade', 'tool_lp'), $options);
|
||||
$mform->hideIf('override_grade', 'competency_rule', 'noteq', \core_competency\competency::OUTCOME_COMPLETE + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -201,10 +207,13 @@ function tool_lp_coursemodule_edit_post_actions($data, $course) {
|
||||
}
|
||||
|
||||
if (isset($data->competency_rule)) {
|
||||
$overridegrade = isset($data->override_grade) ? $data->override_grade : false;
|
||||
|
||||
// Now update the rules for each course_module_competency.
|
||||
$current = \core_competency\api::list_course_module_competencies_in_course_module($data->coursemodule);
|
||||
foreach ($current as $coursemodulecompetency) {
|
||||
\core_competency\api::set_course_module_competency_ruleoutcome($coursemodulecompetency, $data->competency_rule);
|
||||
\core_competency\api::set_course_module_competency_ruleoutcome($coursemodulecompetency, $data->competency_rule,
|
||||
$overridegrade);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1843,10 +1843,10 @@ class backup_activity_competencies_structure_step extends backup_structure_step
|
||||
$wrapper->add_child($competencies);
|
||||
|
||||
$competency = new backup_nested_element('competency', null, array('idnumber', 'ruleoutcome',
|
||||
'sortorder', 'frameworkidnumber'));
|
||||
'sortorder', 'frameworkidnumber', 'overridegrade'));
|
||||
$competencies->add_child($competency);
|
||||
|
||||
$sql = 'SELECT c.idnumber, cmc.ruleoutcome, cmc.sortorder, f.idnumber AS frameworkidnumber
|
||||
$sql = 'SELECT c.idnumber, cmc.ruleoutcome, cmc.overridegrade, cmc.sortorder, f.idnumber AS frameworkidnumber
|
||||
FROM {' . \core_competency\course_module_competency::TABLE . '} cmc
|
||||
JOIN {' . \core_competency\competency::TABLE . '} c ON c.id = cmc.competencyid
|
||||
JOIN {' . \core_competency\competency_framework::TABLE . '} f ON f.id = c.competencyframeworkid
|
||||
|
||||
@@ -3738,6 +3738,7 @@ class restore_activity_competencies_structure_step extends restore_structure_ste
|
||||
// Sortorder is ignored by precaution, anyway we should walk through the records in the right order.
|
||||
$record = (object) $params;
|
||||
$record->ruleoutcome = $data->ruleoutcome;
|
||||
$record->overridegrade = $data->overridegrade;
|
||||
$coursemodulecompetency = new \core_competency\course_module_competency(0, $record);
|
||||
$coursemodulecompetency->create();
|
||||
}
|
||||
|
||||
+27
-12
@@ -1582,9 +1582,11 @@ class api {
|
||||
*
|
||||
* @param int|course_module_competency $coursemodulecompetencyorid The course_module_competency, or its ID.
|
||||
* @param int $ruleoutcome The value of ruleoutcome.
|
||||
* @param bool $overridegrade If true, will override existing grades in related competencies.
|
||||
* @return bool True on success.
|
||||
*/
|
||||
public static function set_course_module_competency_ruleoutcome($coursemodulecompetencyorid, $ruleoutcome) {
|
||||
public static function set_course_module_competency_ruleoutcome($coursemodulecompetencyorid, $ruleoutcome,
|
||||
$overridegrade = false) {
|
||||
static::require_enabled();
|
||||
$coursemodulecompetency = $coursemodulecompetencyorid;
|
||||
if (!is_object($coursemodulecompetency)) {
|
||||
@@ -1599,6 +1601,8 @@ class api {
|
||||
require_capability('moodle/competency:coursecompetencymanage', $context);
|
||||
|
||||
$coursemodulecompetency->set('ruleoutcome', $ruleoutcome);
|
||||
$coursemodulecompetency->set('overridegrade', $overridegrade);
|
||||
|
||||
return $coursemodulecompetency->update();
|
||||
}
|
||||
|
||||
@@ -4279,7 +4283,7 @@ class api {
|
||||
*/
|
||||
public static function add_evidence($userid, $competencyorid, $contextorid, $action, $descidentifier, $desccomponent,
|
||||
$desca = null, $recommend = false, $url = null, $grade = null, $actionuserid = null,
|
||||
$note = null) {
|
||||
$note = null, $overridegrade = false) {
|
||||
global $DB;
|
||||
static::require_enabled();
|
||||
|
||||
@@ -4350,8 +4354,8 @@ class api {
|
||||
$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) {
|
||||
// Only update the grade and proficiency if there is not already a grade or the override option is enabled.
|
||||
if ($usercompetencycourse->get('grade') === null || $overridegrade) {
|
||||
// Set grade.
|
||||
$usercompetencycourse->set('grade', $grade);
|
||||
// Set proficiency.
|
||||
@@ -4363,8 +4367,8 @@ class api {
|
||||
$setucgrade = $coursesettings->get('pushratingstouserplans');
|
||||
|
||||
if ($setucgrade) {
|
||||
// Only push to user plans if there is not already a grade.
|
||||
if ($usercompetency->get('grade') !== null) {
|
||||
// Only push to user plans if there is not already a grade or the override option is enabled.
|
||||
if ($usercompetency->get('grade') !== null && !$overridegrade) {
|
||||
$setucgrade = false;
|
||||
} else {
|
||||
$ucgrade = $grade;
|
||||
@@ -4374,8 +4378,9 @@ class api {
|
||||
} 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) {
|
||||
// the user competency when a grade has not been set yet or if override option is enabled.
|
||||
// Complete is an action to use with automated systems.
|
||||
if ($usercompetency->get('grade') === null || $overridegrade) {
|
||||
$setucgrade = true;
|
||||
$ucgrade = $grade;
|
||||
$ucproficiency = $proficiency;
|
||||
@@ -4498,7 +4503,7 @@ class api {
|
||||
|
||||
// The competency was marked as completed, apply the rules.
|
||||
if ($wascompleted) {
|
||||
self::apply_competency_rules_from_usercompetency($usercompetency, $competency);
|
||||
self::apply_competency_rules_from_usercompetency($usercompetency, $competency, $overridegrade);
|
||||
}
|
||||
|
||||
return $evidence;
|
||||
@@ -4557,7 +4562,7 @@ class api {
|
||||
* @return void
|
||||
*/
|
||||
protected static function apply_competency_rules_from_usercompetency(user_competency $usercompetency,
|
||||
competency $competency = null) {
|
||||
competency $competency = null, $overridegrade = false) {
|
||||
|
||||
// Perform some basic checks.
|
||||
if (!$usercompetency->get('proficiency')) {
|
||||
@@ -4624,7 +4629,12 @@ class api {
|
||||
'evidence_competencyrule',
|
||||
'core_competency',
|
||||
null,
|
||||
$recommend
|
||||
$recommend,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$overridegrade
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4659,6 +4669,7 @@ class api {
|
||||
$action = null;
|
||||
$recommend = false;
|
||||
$strdesc = 'evidence_coursemodulecompleted';
|
||||
$overridegrade = $coursemodulecompetency->get('overridegrade');
|
||||
|
||||
if ($outcome == course_module_competency::OUTCOME_NONE) {
|
||||
continue;
|
||||
@@ -4686,7 +4697,11 @@ class api {
|
||||
'core_competency',
|
||||
$cmname,
|
||||
$recommend,
|
||||
$url
|
||||
$url,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
$overridegrade
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,10 @@ class course_module_competency extends persistent {
|
||||
'default' => self::OUTCOME_EVIDENCE,
|
||||
'type' => PARAM_INT,
|
||||
),
|
||||
'overridegrade' => array(
|
||||
'default' => false,
|
||||
'type' => PARAM_BOOL
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
<?php
|
||||
// This file is part of Moodle - http://moodle.org/
|
||||
//
|
||||
// Moodle is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// Moodle is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace core_competency;
|
||||
|
||||
/**
|
||||
* Competency ruleoutcome override grade tests
|
||||
*
|
||||
* @package core_competency
|
||||
* @copyright 2022 Matthew Hilton <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class competency_override_test extends \advanced_testcase {
|
||||
|
||||
public function setUp(): void {
|
||||
$this->resetAfterTest(true);
|
||||
$this->setAdminUser();
|
||||
$dg = $this->getDataGenerator();
|
||||
$lpg = $dg->get_plugin_generator('core_competency');
|
||||
|
||||
// Create user in course.
|
||||
$c1 = $dg->create_course((object) ['enablecompletion' => true]);
|
||||
$u1 = $dg->create_user();
|
||||
$dg->enrol_user($u1->id, $c1->id);
|
||||
|
||||
// Create framework with three values.
|
||||
$scale = $dg->create_scale(["scale" => "not,partially,fully"]);
|
||||
$scaleconfiguration = json_encode([
|
||||
['scaleid' => $scale->id],
|
||||
['id' => 1, 'scaledefault' => 1, 'proficient' => 1]
|
||||
]);
|
||||
$framework = $lpg->create_framework([
|
||||
'scaleid' => $scale->id,
|
||||
'scaleconfiguration' => $scaleconfiguration
|
||||
]);
|
||||
|
||||
$plan = $lpg->create_plan(['userid' => $u1->id]);
|
||||
|
||||
$comp1 = $lpg->create_competency([
|
||||
'competencyframeworkid' => $framework->get('id'),
|
||||
'scaleid' => $scale->id,
|
||||
'scaleconfiguration' => $scaleconfiguration
|
||||
]);
|
||||
|
||||
$comp2 = $lpg->create_competency([
|
||||
'competencyframeworkid' => $framework->get('id'),
|
||||
'scaleid' => $scale->id,
|
||||
'scaleconfiguration' => $scaleconfiguration
|
||||
]);
|
||||
|
||||
api::add_competency_to_plan($plan->get('id'), $comp1->get('id'));
|
||||
api::add_competency_to_plan($plan->get('id'), $comp2->get('id'));
|
||||
|
||||
$lpg->create_course_competency([
|
||||
'courseid' => $c1->id,
|
||||
'competencyid' => $comp1->get('id'),
|
||||
'ruleoutcome' => \core_competency\course_competency::OUTCOME_COMPLETE,
|
||||
]);
|
||||
|
||||
$lpg->create_course_competency([
|
||||
'courseid' => $c1->id,
|
||||
'competencyid' => $comp2->get('id'),
|
||||
'ruleoutcome' => \core_competency\course_competency::OUTCOME_COMPLETE,
|
||||
]);
|
||||
|
||||
$label = $dg->create_module('label', ['course' => $c1, 'completion' => COMPLETION_VIEWED, 'completionview' => 1]);
|
||||
$cm = get_coursemodule_from_instance('label', $label->id);
|
||||
$completion = new \completion_info($c1);
|
||||
$this->assertEquals(COMPLETION_ENABLED, $completion->is_enabled($cm));
|
||||
|
||||
// Link course module with the competency and setup a rule to complete the competency when the module is completed.
|
||||
api::add_competency_to_course_module($cm, $comp1->get('id'));
|
||||
api::add_competency_to_course_module($cm, $comp2->get('id'));
|
||||
|
||||
$coursemodulecomps = api::list_course_module_competencies_in_course_module($cm);
|
||||
$this->assertCount(2, $coursemodulecomps);
|
||||
api::set_course_module_competency_ruleoutcome($coursemodulecomps[0], \core_competency\course_competency::OUTCOME_COMPLETE);
|
||||
api::set_course_module_competency_ruleoutcome($coursemodulecomps[1], \core_competency\course_competency::OUTCOME_COMPLETE);
|
||||
|
||||
$this->course = $c1;
|
||||
$this->user = $u1;
|
||||
$this->scale = $scale;
|
||||
$this->framework = $framework;
|
||||
$this->plan = $plan;
|
||||
$this->comp1 = $comp1;
|
||||
$this->comp2 = $comp2;
|
||||
$this->cm = $cm;
|
||||
$this->completion = new \completion_info($c1);
|
||||
$this->context = \context_course::instance($this->course->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test ruleoutcome overridegrade is correctly applied when coursemodule completion is processed.
|
||||
*
|
||||
* @covers \core_competency\api::set_course_module_competency_ruleoutcome
|
||||
*/
|
||||
public function test_ruleoutcome_overridegrade(): void {
|
||||
// Initially the competency (and hence all the child competencies) should not be complete for the user.
|
||||
[$coursecomp, $plancomp, $usercomp] = $this->get_related_competencies($this->comp1->get('id'));
|
||||
$this->assertEquals(0, $plancomp->usercompetency->get('grade'));
|
||||
$this->assertEquals(0, $usercomp->get('grade'));
|
||||
$this->assertEquals(0, $coursecomp->get('grade'));
|
||||
|
||||
[$coursecomp2, $plancomp2, $usercomp2] = $this->get_related_competencies($this->comp2->get('id'));
|
||||
$this->assertEquals(0, $plancomp2->usercompetency->get('grade'));
|
||||
$this->assertEquals(0, $usercomp2->get('grade'));
|
||||
$this->assertEquals(0, $coursecomp2->get('grade'));
|
||||
|
||||
// Update the course module completion state to complete and trigger a competency update.
|
||||
$data = $this->completion->get_data($this->cm, false, $this->user->id);
|
||||
$data->completionstate = COMPLETION_COMPLETE;
|
||||
$data->timemodified = time();
|
||||
$this->completion->internal_set_data($this->cm, $data);
|
||||
|
||||
// Comptency should now be complete for user, plan, and course now that the course module is completed.
|
||||
[$coursecomp, $plancomp, $usercomp] = $this->get_related_competencies($this->comp1->get('id'));
|
||||
$this->assertEquals(1, $plancomp->usercompetency->get('grade'));
|
||||
$this->assertEquals(1, $usercomp->get('grade'));
|
||||
$this->assertEquals(1, $coursecomp->get('grade'));
|
||||
|
||||
[$coursecomp2, $plancomp2, $usercomp2] = $this->get_related_competencies($this->comp2->get('id'));
|
||||
$this->assertEquals(1, $plancomp2->usercompetency->get('grade'));
|
||||
$this->assertEquals(1, $usercomp2->get('grade'));
|
||||
$this->assertEquals(1, $coursecomp2->get('grade'));
|
||||
|
||||
// Change the competency completion for the user by adding evidence.
|
||||
api::add_evidence($this->user->id, $this->comp1, $this->context,
|
||||
evidence::ACTION_OVERRIDE, 'commentincontext', 'core', null, false, null, 2);
|
||||
api::add_evidence($this->user->id, $this->comp2, $this->context,
|
||||
evidence::ACTION_OVERRIDE, 'commentincontext', 'core', null, false, null, 2);
|
||||
|
||||
// After adding evidence, the competencies should now reflect the new grade value.
|
||||
[$coursecomp, $plancomp, $usercomp] = $this->get_related_competencies($this->comp1->get('id'));
|
||||
$this->assertEquals(2, $plancomp->usercompetency->get('grade'));
|
||||
$this->assertEquals(2, $usercomp->get('grade'));
|
||||
$this->assertEquals(2, $coursecomp->get('grade'));
|
||||
|
||||
[$coursecomp2, $plancomp2, $usercomp2] = $this->get_related_competencies($this->comp2->get('id'));
|
||||
$this->assertEquals(2, $plancomp2->usercompetency->get('grade'));
|
||||
$this->assertEquals(2, $usercomp2->get('grade'));
|
||||
$this->assertEquals(2, $coursecomp2->get('grade'));
|
||||
|
||||
// Update the course module competency to incomplete. This will not change the competency status.
|
||||
$data = $this->completion->get_data($this->cm, false, $this->user->id);
|
||||
$data->completionstate = COMPLETION_INCOMPLETE;
|
||||
$data->timemodified = time();
|
||||
$this->completion->internal_set_data($this->cm, $data);
|
||||
|
||||
[$coursecomp, $plancomp, $usercomp] = $this->get_related_competencies($this->comp1->get('id'));
|
||||
$this->assertEquals(2, $plancomp->usercompetency->get('grade'));
|
||||
$this->assertEquals(2, $usercomp->get('grade'));
|
||||
$this->assertEquals(2, $coursecomp->get('grade'));
|
||||
|
||||
[$coursecomp2, $plancomp2, $usercomp2] = $this->get_related_competencies($this->comp2->get('id'));
|
||||
$this->assertEquals(2, $plancomp2->usercompetency->get('grade'));
|
||||
$this->assertEquals(2, $usercomp2->get('grade'));
|
||||
$this->assertEquals(2, $coursecomp2->get('grade'));
|
||||
|
||||
// Re-complete the course module, so that it attempts to re-complete the competencies.
|
||||
$data = $this->completion->get_data($this->cm, false, $this->user->id);
|
||||
$data->completionstate = COMPLETION_COMPLETE;
|
||||
$data->timemodified = time();
|
||||
$this->completion->internal_set_data($this->cm, $data);
|
||||
|
||||
// By default, this will not override the existing grade, so it should remain the same as before.
|
||||
[$coursecomp, $plancomp, $usercomp] = $this->get_related_competencies($this->comp1->get('id'));
|
||||
$this->assertEquals(2, $plancomp->usercompetency->get('grade'));
|
||||
$this->assertEquals(2, $usercomp->get('grade'));
|
||||
$this->assertEquals(2, $coursecomp->get('grade'));
|
||||
|
||||
[$coursecomp2, $plancomp2, $usercomp2] = $this->get_related_competencies($this->comp2->get('id'));
|
||||
$this->assertEquals(2, $plancomp2->usercompetency->get('grade'));
|
||||
$this->assertEquals(2, $usercomp2->get('grade'));
|
||||
$this->assertEquals(2, $coursecomp2->get('grade'));
|
||||
|
||||
// Update the completion rule for only competency 1 to $overridegrade = true.
|
||||
$coursemodulecomps = api::list_course_module_competencies_in_course_module($this->cm);
|
||||
api::set_course_module_competency_ruleoutcome($coursemodulecomps[0], \core_competency\course_competency::OUTCOME_COMPLETE,
|
||||
true);
|
||||
|
||||
// Mark as incomplete then re-complete the course module.
|
||||
$data = $this->completion->get_data($this->cm, false, $this->user->id);
|
||||
$data->completionstate = COMPLETION_INCOMPLETE;
|
||||
$data->timemodified = time();
|
||||
$this->completion->internal_set_data($this->cm, $data);
|
||||
|
||||
$data = $this->completion->get_data($this->cm, false, $this->user->id);
|
||||
$data->completionstate = COMPLETION_COMPLETE;
|
||||
$data->timemodified = time();
|
||||
$this->completion->internal_set_data($this->cm, $data);
|
||||
|
||||
// Because the rule is now set to override existing grades, the grade should have now updated as per the ruleoutcome.
|
||||
// However the second competency didn't have this rule set, so it will not be overriden.
|
||||
[$coursecomp, $plancomp, $usercomp] = $this->get_related_competencies($this->comp1->get('id'));
|
||||
$this->assertEquals(1, $plancomp->usercompetency->get('grade'));
|
||||
$this->assertEquals(1, $usercomp->get('grade'));
|
||||
$this->assertEquals(1, $coursecomp->get('grade'));
|
||||
|
||||
[$coursecomp2, $plancomp2, $usercomp2] = $this->get_related_competencies($this->comp2->get('id'));
|
||||
$this->assertEquals(2, $plancomp2->usercompetency->get('grade'));
|
||||
$this->assertEquals(2, $usercomp2->get('grade'));
|
||||
$this->assertEquals(2, $coursecomp2->get('grade'));
|
||||
|
||||
// If competency 2 is changed now to override and re-completed, it will update the same as competency 1.
|
||||
api::set_course_module_competency_ruleoutcome($coursemodulecomps[1], \core_competency\course_competency::OUTCOME_COMPLETE,
|
||||
true);
|
||||
|
||||
$data = $this->completion->get_data($this->cm, false, $this->user->id);
|
||||
$data->completionstate = COMPLETION_INCOMPLETE;
|
||||
$data->timemodified = time();
|
||||
$this->completion->internal_set_data($this->cm, $data);
|
||||
|
||||
$data = $this->completion->get_data($this->cm, false, $this->user->id);
|
||||
$data->completionstate = COMPLETION_COMPLETE;
|
||||
$data->timemodified = time();
|
||||
$this->completion->internal_set_data($this->cm, $data);
|
||||
|
||||
// Now both the competencies have $overridegrade = true,
|
||||
// they should both reflect the ruleoutcome after the completion above was processed.
|
||||
[$coursecomp, $plancomp, $usercomp] = $this->get_related_competencies($this->comp1->get('id'));
|
||||
$this->assertEquals(1, $plancomp->usercompetency->get('grade'));
|
||||
$this->assertEquals(1, $usercomp->get('grade'));
|
||||
$this->assertEquals(1, $coursecomp->get('grade'));
|
||||
|
||||
[$coursecomp2, $plancomp2, $usercomp2] = $this->get_related_competencies($this->comp2->get('id'));
|
||||
$this->assertEquals(1, $plancomp2->usercompetency->get('grade'));
|
||||
$this->assertEquals(1, $usercomp2->get('grade'));
|
||||
$this->assertEquals(1, $coursecomp2->get('grade'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test competency backup and restore correctly restores the ruleoutcome overridegrade value.
|
||||
*
|
||||
* @covers \core_competency\api::set_course_module_competency_ruleoutcome
|
||||
*/
|
||||
public function test_override_backup_restore(): void {
|
||||
global $CFG;
|
||||
require_once($CFG->dirroot . '/course/externallib.php');
|
||||
|
||||
// Set one to override grade and another to not override grade.
|
||||
$coursemodulecomps = api::list_course_module_competencies_in_course_module($this->cm);
|
||||
api::set_course_module_competency_ruleoutcome($coursemodulecomps[0], \core_competency\course_competency::OUTCOME_COMPLETE,
|
||||
false);
|
||||
api::set_course_module_competency_ruleoutcome($coursemodulecomps[1], \core_competency\course_competency::OUTCOME_COMPLETE,
|
||||
true);
|
||||
|
||||
// Duplicate the course (backup and restore).
|
||||
$duplicated = \core_course_external::duplicate_course($this->course->id, 'test', 'test', $this->course->category);
|
||||
|
||||
// Get the new course modules.
|
||||
$newcoursemodules = get_coursemodules_in_course('label', $duplicated['id']);
|
||||
$this->assertCount(1, $newcoursemodules);
|
||||
$cm = array_pop($newcoursemodules);
|
||||
|
||||
// Get the comeptencies for this cm.
|
||||
$newcoursemodulecomps = api::list_course_module_competencies_in_course_module($cm);
|
||||
$this->assertCount(2, $newcoursemodulecomps);
|
||||
|
||||
// Ensure the override grade settings are restored properly.
|
||||
$this->assertEquals($coursemodulecomps[0]->get('overridegrade'), $newcoursemodulecomps[0]->get('overridegrade'));
|
||||
$this->assertEquals($coursemodulecomps[1]->get('overridegrade'), $newcoursemodulecomps[1]->get('overridegrade'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the course, user and plan competency for the given competency ID
|
||||
*
|
||||
* @param int $compid ID of the competency.
|
||||
* @return array array containing the three related competencies
|
||||
*/
|
||||
private function get_related_competencies(int $compid): array {
|
||||
$coursecomp = api::get_user_competency_in_course($this->course->id, $this->user->id, $compid);
|
||||
$usercomp = api::get_user_competency($this->user->id, $compid);
|
||||
$plancomp = api::get_plan_competency($this->plan, $compid);
|
||||
return [$coursecomp, $plancomp, $usercomp];
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="lib/db" VERSION="20220825" COMMENT="XMLDB file for core Moodle tables"
|
||||
<XMLDB PATH="lib/db" VERSION="20221009" COMMENT="XMLDB file for core Moodle tables"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
@@ -3889,6 +3889,7 @@
|
||||
<FIELD NAME="sortorder" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The field used to naturally sort this link."/>
|
||||
<FIELD NAME="competencyid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="The course competency this activity is linked to."/>
|
||||
<FIELD NAME="ruleoutcome" TYPE="int" LENGTH="2" NOTNULL="true" SEQUENCE="false" COMMENT="The outcome when an activity is completed."/>
|
||||
<FIELD NAME="overridegrade" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false" COMMENT="Enables the ability to override an existing competencys grade."/>
|
||||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
|
||||
|
||||
@@ -2925,5 +2925,17 @@ privatefiles,moodle|/user/files.php';
|
||||
upgrade_main_savepoint(true, 2022092200.01);
|
||||
}
|
||||
|
||||
if ($oldversion < 2022101400.01) {
|
||||
$table = new xmldb_table('competency_modulecomp');
|
||||
$field = new xmldb_field('overridegrade', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '0', 'ruleoutcome');
|
||||
|
||||
if (!$dbman->field_exists($table, $field)) {
|
||||
$dbman->add_field($table, $field);
|
||||
}
|
||||
|
||||
// Main savepoint reached.
|
||||
upgrade_main_savepoint(true, 2022101400.01);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2022101400.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2022101400.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
$release = '4.1dev+ (Build: 20221014)'; // Human-friendly version name
|
||||
|
||||
Reference in New Issue
Block a user