Skip to content

Commit

Permalink
MDL-49257 grades: introduce calculation freeze
Browse files Browse the repository at this point in the history
In order to prevent changes in the existing grades when we fix bugs
we are introducing the gradebook code versioning. Each course may
"freeze" the code version to the older date. Freezing is usually done
during upgrade or restore and can be removed by the teacher by pressing
the button and accepting potential grade changes. There is no visible
setting and not possible to change the version back manually.

See MDL-50432 and MDL-50522
  • Loading branch information
marinaglancy committed Jun 23, 2015
1 parent f4bfbd5 commit deb3d5e
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 0 deletions.
7 changes: 7 additions & 0 deletions backup/moodle2/backup_stepslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,13 @@ protected function define_structure() {
$gradebook->add_child($grade_settings);
$grade_settings->add_child($grade_setting);

// Add attribute with gradebook calculation freeze date if needed.
$gradebookcalculationfreeze = get_config('core', 'gradebook_calculations_freeze_' . $this->get_courseid());
if ($gradebookcalculationfreeze) {
$gradebook->add_attributes(array('calculations_freeze'));
$gradebook->get_attribute('calculations_freeze')->set_value($gradebookcalculationfreeze);
}

// Define sources

//Include manual, category and the course grade item
Expand Down
27 changes: 27 additions & 0 deletions backup/moodle2/restore_stepslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,18 @@ protected function define_structure() {
}

protected function process_gradebook($data) {
// For non-merge restore types:
// Unset 'gradebook_calculations_freeze_' in the course and replace with the one from the backup.
$target = $this->get_task()->get_target();
if ($target == backup::TARGET_CURRENT_DELETING || $target == backup::TARGET_EXISTING_DELETING) {
set_config('gradebook_calculations_freeze_' . $this->get_courseid(), null);
}
if (!empty($data['calculations_freeze']) && $this->get_task()->get_target() == backup::TARGET_NEW_COURSE) {
if ($target == backup::TARGET_NEW_COURSE || $target == backup::TARGET_CURRENT_DELETING ||
$target == backup::TARGET_EXISTING_DELETING) {
set_config('gradebook_calculations_freeze_' . $this->get_courseid(), $data['calculations_freeze']);
}
}
}

protected function process_grade_item($data) {
Expand Down Expand Up @@ -451,9 +463,24 @@ protected function after_execute() {
}
$rs->close();

// Freeze gradebook calculations if needed.
$this->gradebook_calculation_freeze();

// Restore marks items as needing update. Update everything now.
grade_regrade_final_grades($this->get_courseid());
}

/**
* Freeze gradebook calculation if needed.
*
* This is similar to various upgrade scripts that check if the freeze is needed.
*/
protected function gradebook_calculation_freeze() {
global $CFG;
$gradebookcalculationsfreeze = get_config('core', 'gradebook_calculations_freeze_' . $this->get_courseid());
preg_match('/(\d{8})/', $this->get_task()->get_info()->moodle_release, $matches);
$backupbuild = (int)$matches[1];
}
}

/**
Expand Down
45 changes: 45 additions & 0 deletions grade/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,15 @@ function hide_aggregatesubcats_upgrade_notice($courseid) {
unset_config('show_aggregatesubcats_upgrade_' . $courseid);
}

/**
* Hide warning about changed grades due to bug fixes
*
* @param int $courseid The current course id.
*/
function hide_gradebook_calculations_freeze_notice($courseid) {
unset_config('gradebook_calculations_freeze_' . $courseid);
}

/**
* Print warning about changed grades during upgrade to 2.8.
*
Expand Down Expand Up @@ -547,6 +556,9 @@ function print_natural_aggregation_upgrade_notice($courseid, $context, $thispage

$minmaxtouse = grade_get_setting($courseid, 'minmaxtouse', $CFG->grade_minmaxtouse);

$gradebookcalculationsfreeze = get_config('core', 'gradebook_calculations_freeze_' . $courseid);
$acceptgradebookchanges = optional_param('acceptgradebookchanges', false, PARAM_BOOL) && confirm_sesskey();

// Hide the warning if the user told it to go away.
if ($hidenaturalwarning) {
hide_natural_aggregation_upgrade_notice($courseid);
Expand Down Expand Up @@ -641,6 +653,39 @@ function print_natural_aggregation_upgrade_notice($courseid, $context, $thispage
}
}

if ($gradebookcalculationsfreeze) {
if ($acceptgradebookchanges) {
// Accept potential changes in grades caused by extra credit bug MDL-49257.
hide_gradebook_calculations_freeze_notice($courseid);
$courseitem = grade_item::fetch_course_item($courseid);
$courseitem->force_regrading();
grade_regrade_final_grades($courseid);

$html .= $OUTPUT->notification(get_string('gradebookcalculationsuptodate', 'grades'), 'notifysuccess');
} else {
// Show the warning that there may be extra credit weights problems.
$a = new stdClass();
$a->gradebookversion = $gradebookcalculationsfreeze;
if (preg_match('/(\d{8,})/', $CFG->release, $matches)) {
$a->currentversion = $matches[1];
} else {
$a->currentversion = $CFG->release;
}
$a->url = get_docs_url('Gradebook_calculations_changes');
$message = get_string('gradebookcalculationswarning', 'grades', $a);

$fixmessage = get_string('gradebookcalculationsfixbutton', 'grades');
$urlparams = array('id' => $courseid,
'acceptgradebookchanges' => true,
'sesskey' => sesskey());
$fixurl = new moodle_url($thispage, $urlparams);
$fixbutton = $OUTPUT->single_button($fixurl, $fixmessage, 'get');

$html .= $OUTPUT->notification($message, 'notifywarning');
$html .= $fixbutton;
}
}

if (!empty($html)) {
$html = html_writer::tag('div', $html, array('class' => 'core_grades_notices'));
}
Expand Down
14 changes: 14 additions & 0 deletions grade/tests/behat/behat_grade.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,18 @@ public function i_reset_weights_for_grade_category($gradeitem) {
$steps[] = new Given('I click on "' . $this->escape($linktext) . '" "link"');
return $steps;
}

/**
* Step allowing to test before-the-fix behaviour of the gradebook
*
* @Given /^gradebook calculations for the course "(?P<coursename_string>(?:[^"]|\\")*)" are frozen at version "(?P<version_string>(?:[^"]|\\")*)"$/
* @param string $coursename
* @param string $version
* @return Given
*/
public function gradebook_calculations_for_the_course_are_frozen_at_version($coursename, $version) {
global $DB;
$courseid = $DB->get_field('course', 'id', array('shortname' => $coursename), MUST_EXIST);
set_config('gradebook_calculations_freeze_' . $courseid, $version);
}
}
3 changes: 3 additions & 0 deletions lang/en/grades.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@
$string['gradealreadyupdated'] = '{$a} grades have not been imported because the grades in the import file are older than in the grader report. To proceed with the grade import anyway, use the force import option.';
$string['gradeanalysis'] = 'Grade analysis';
$string['gradebook'] = 'Gradebook';
$string['gradebookcalculationsuptodate'] = 'The calculations in the gradebook are up to date. You may need to reload this page to see changes.';
$string['gradebookcalculationsfixbutton'] = 'Accept the changes and recalculate grades';
$string['gradebookcalculationswarning'] = 'Note: Some errors have been detected in gradebook calculations that affect this course. The errors have been fixed but the fix was not yet applied to this course since it may lead to the changes in existing grades. You can review the changes on <a href="{$a->url}">this documentation page</a>. Look for the changes between versions {$a->gradebookversion} and {$a->currentversion}';
$string['gradebookhiddenerror'] = 'The gradebook is currently set to hide everything from students.';
$string['gradebookhistories'] = 'Grade histories';
$string['gradeboundary'] = 'Letter grade boundary';
Expand Down

0 comments on commit deb3d5e

Please sign in to comment.