MDL-49324 Grades: Use a progress bar when recalculating gradebook grades
authorDamyon Wiese <damyon@moodle.com>
Fri, 27 Feb 2015 08:33:54 +0000 (16:33 +0800)
committerAndrew Nicols <andrew@nicols.co.uk>
Tue, 23 Feb 2016 00:35:10 +0000 (08:35 +0800)
grade/edit/tree/index.php
grade/export/lib.php
grade/report/grader/index.php
grade/report/outcomes/index.php
grade/report/overview/index.php
grade/report/singleview/index.php
grade/report/user/index.php
grade/report/user/lib.php
lang/en/error.php
lang/en/grades.php
lib/gradelib.php

index 672888a..081ec40 100644 (file)
@@ -63,8 +63,6 @@ if (!is_null($category) && !is_null($aggregationtype) && confirm_sesskey()) {
     $data->aggregation = $aggregationtype;
     grade_category::set_properties($grade_category, $data);
     $grade_category->update();
-
-    grade_regrade_final_grades($courseid);
 }
 
 //first make sure we have proper final grades - we need it for locking changes
@@ -72,8 +70,6 @@ $normalisationmessage = null;
 
 $originalweights = grade_helper::fetch_all_natural_weights_for_course($courseid);
 
-grade_regrade_final_grades($courseid);
-
 $alteredweights = grade_helper::fetch_all_natural_weights_for_course($courseid);
 
 if (array_diff($originalweights, $alteredweights)) {
@@ -236,14 +232,24 @@ if ($data = data_submitted() and confirm_sesskey()) {
 
     $originalweights = grade_helper::fetch_all_natural_weights_for_course($courseid);
 
-    grade_regrade_final_grades($courseid);
-
     $alteredweights = grade_helper::fetch_all_natural_weights_for_course($courseid);
     if (array_diff($originalweights, $alteredweights)) {
         $normalisationmessage = get_string('weightsadjusted', 'grades');
     }
 }
 
+// Do this check just before printing the grade header (and only do it once).
+if (grade_needs_regrade_final_grades($courseid)) {
+    $PAGE->set_heading($course->fullname);
+    echo $OUTPUT->header();
+    echo $OUTPUT->heading(get_string('recalculatinggrades', 'grades'));
+    $progress = new \core\progress\display(true);
+    grade_regrade_final_grades($courseid, null, null, $progress);
+    echo $OUTPUT->continue_button($PAGE->url);
+    echo $OUTPUT->footer();
+    die();
+}
+
 print_grade_page_head($courseid, 'settings', 'setup', get_string('gradebooksetup', 'grades'));
 
 // Print Table of categories and items
index bf7b981..0057ce3 100644 (file)
@@ -699,8 +699,7 @@ class grade_export_update_buffer {
  * @param $courseid int The course being exported
  */
 function export_verify_grades($courseid) {
-    $regraderesult = grade_regrade_final_grades($courseid);
-    if (is_array($regraderesult)) {
-        throw new moodle_exception('gradecantregrade', 'error', '', implode(', ', array_unique($regraderesult)));
+    if (grade_needs_regrade_final_grades($courseid)) {
+        throw new moodle_exception('gradesneedregrading', 'grades', '', implode(', ', array_unique($regraderesult)));
     }
 }
index f15efe2..dcd5b04 100644 (file)
@@ -115,9 +115,6 @@ if (!is_null($toggle) && !empty($toggle_type)) {
     set_user_preferences(array('grade_report_show'.$toggle_type => $toggle));
 }
 
-//first make sure we have proper final grades - this must be done before constructing of the grade tree
-grade_regrade_final_grades($courseid);
-
 // Perform actions
 if (!empty($target) && !empty($action) && confirm_sesskey()) {
     grade_report_grader::do_process_action($target, $action, $courseid);
@@ -125,6 +122,17 @@ if (!empty($target) && !empty($action) && confirm_sesskey()) {
 
 $reportname = get_string('pluginname', 'gradereport_grader');
 
+// Do this check just before printing the grade header (and only do it once).
+if (grade_needs_regrade_final_grades($courseid)) {
+    $PAGE->set_heading($course->fullname);
+    $progress = new \core\progress\display(true);
+    echo $OUTPUT->header();
+    echo $OUTPUT->heading(get_string('recalculatinggrades', 'grades'));
+    grade_regrade_final_grades($courseid, null, null, $progress);
+    echo $OUTPUT->continue_button($PAGE->url);
+    echo $OUTPUT->footer();
+    die();
+}
 // Print header
 print_grade_page_head($COURSE->id, 'report', 'grader', $reportname, false, $buttons);
 
index cc809ab..df3a7c0 100644 (file)
@@ -40,7 +40,16 @@ $context = context_course::instance($course->id);
 require_capability('gradereport/outcomes:view', $context);
 
 // First make sure we have proper final grades.
-grade_regrade_final_grades($courseid);
+if (grade_needs_regrade_final_grades($courseid)) {
+    $PAGE->set_heading($course->fullname);
+    $progress = new \core\progress\display(true);
+    echo $OUTPUT->header();
+    echo $OUTPUT->heading(get_string('recalculatinggrades', 'grades'));
+    grade_regrade_final_grades($courseid, null, null, $progress);
+    echo $OUTPUT->continue_button($PAGE->url);
+    echo $OUTPUT->footer();
+    die();
+}
 
 // Grab all outcomes used in course.
 $report_info = array();
index e46885c..6cb2c61 100644 (file)
@@ -107,8 +107,17 @@ if (!isset($USER->grade_last_report)) {
 }
 $USER->grade_last_report[$course->id] = 'overview';
 
-//first make sure we have proper final grades - this must be done before constructing of the grade tree
-grade_regrade_final_grades($courseid);
+// First make sure we have proper final grades.
+if (grade_needs_regrade_final_grades($courseid)) {
+    $PAGE->set_heading($course->fullname);
+    $progress = new \core\progress\display(true);
+    echo $OUTPUT->header();
+    echo $OUTPUT->heading(get_string('recalculatinggrades', 'grades'));
+    grade_regrade_final_grades($courseid, null, null, $progress);
+    echo $OUTPUT->continue_button($PAGE->url);
+    echo $OUTPUT->footer();
+    die();
+}
 
 if (has_capability('moodle/grade:viewall', $context) && $courseid != SITEID) {
     // Please note this would be extremely slow if we wanted to implement this properly for all teachers.
index be9461b..fed131a 100644 (file)
@@ -78,9 +78,17 @@ if (!isset($USER->grade_last_report)) {
 }
 $USER->grade_last_report[$course->id] = 'singleview';
 
-// First make sure we have proper final grades -
-// this must be done before constructing of the grade tree.
-grade_regrade_final_grades($courseid);
+// First make sure we have proper final grades.
+if (grade_needs_regrade_final_grades($courseid)) {
+    $PAGE->set_heading($course->fullname);
+    $progress = new \core\progress\display(true);
+    echo $OUTPUT->header();
+    echo $OUTPUT->heading(get_string('recalculatinggrades', 'grades'));
+    grade_regrade_final_grades($courseid, null, null, $progress);
+    echo $OUTPUT->continue_button($PAGE->url);
+    echo $OUTPUT->footer();
+    die();
+}
 
 $report = new gradereport_singleview($courseid, $gpr, $context, $itemtype, $itemid);
 
index 149879c..f8578cc 100644 (file)
@@ -79,9 +79,17 @@ if (!isset($USER->grade_last_report)) {
 }
 $USER->grade_last_report[$course->id] = 'user';
 
-
-//first make sure we have proper final grades - this must be done before constructing of the grade tree
-grade_regrade_final_grades($courseid);
+// First make sure we have proper final grades.
+if (grade_needs_regrade_final_grades($courseid)) {
+    $PAGE->set_heading($course->fullname);
+    $progress = new \core\progress\display(true);
+    echo $OUTPUT->header();
+    echo $OUTPUT->heading(get_string('recalculatinggrades', 'grades'));
+    grade_regrade_final_grades($courseid, null, null, $progress);
+    echo $OUTPUT->continue_button($PAGE->url);
+    echo $OUTPUT->footer();
+    die();
+}
 
 if (has_capability('moodle/grade:viewall', $context)) { //Teachers will see all student reports
     $groupmode    = groups_get_course_groupmode($course);   // Groups are being used
index 0f35f82..65f66a6 100644 (file)
@@ -1163,9 +1163,6 @@ function grade_report_user_profilereport($course, $user, $viewasuser = false) {
 
         $context = context_course::instance($course->id);
 
-        //first make sure we have proper final grades - this must be done before constructing of the grade tree
-        grade_regrade_final_grades($course->id);
-
         /// return tracking object
         $gpr = new grade_plugin_return(array('type'=>'report', 'plugin'=>'user', 'courseid'=>$course->id, 'userid'=>$user->id));
         // Create a report instance
index 32aded3..2dc689f 100644 (file)
@@ -254,6 +254,7 @@ $string['filternotinstalled'] = 'Filter {$a} is not currently installed';
 $string['forumblockingtoomanyposts'] = 'You have exceeded the posting threshold set for this forum';
 $string['generalexceptionmessage'] = 'Exception - {$a}';
 $string['gradepubdisable'] = 'Grade publishing disabled';
+$string['gradesneedregrading'] = 'The course grades need to be recalculated';
 $string['gradecantregrade'] = 'An error occurred during grade calculation: {$a}';
 $string['groupalready'] = 'User already belongs to group {$a}';
 $string['groupexistforcourse'] = 'Group "{$a}" already exists for this course';
index 4089b5e..f37a5fe 100644 (file)
@@ -616,6 +616,7 @@ $string['rawpct'] = 'Raw %';
 $string['real'] = 'Real';
 $string['realletter'] = 'Real (letter)';
 $string['realpercentage'] = 'Real (percentage)';
+$string['recalculatinggrades'] = 'Recalculating grades';
 $string['recovergradesdefault'] = 'Recover grades default';
 $string['recovergradesdefault_help'] = 'By default recover old grades when re-enrolling a user in a course.';
 $string['refreshpreview'] = 'Refresh preview';
index 6dfa227..4fc6950 100644 (file)
@@ -325,6 +325,18 @@ function grade_update_outcomes($source, $courseid, $itemtype, $itemmodule, $item
     return false; //grade items not found
 }
 
+/**
+ * Return true if the course needs regrading.
+ *
+ * @param int $courseid The course ID
+ * @return bool true if course grades need updating.
+ */
+function grade_needs_regrade_final_grades($courseid) {
+    $course_item = grade_item::fetch_course_item($courseid);
+    return $course_item->needsupdate;
+}
+
+
 /**
  * Returns grading information for given activity, optionally with user grades
  * Manual, course or category items can not be queried.
@@ -1011,14 +1023,19 @@ function grade_recover_history_grades($userid, $courseid) {
  * @param int $courseid The course ID
  * @param int $userid If specified try to do a quick regrading of the grades of this user only
  * @param object $updated_item Optional grade item to be marked for regrading
+ * @param \core\progress\base $progress If provided, will be used to update progress on this long operation.
  * @return bool true if ok, array of errors if problems found. Grade item id => error message
  */
-function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null) {
+function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null, $progress=null) {
     // This may take a very long time.
     \core_php_time_limit::raise();
 
     $course_item = grade_item::fetch_course_item($courseid);
 
+    if ($progress == null) {
+        $progress = new \core\progress\none();
+    }
+
     if ($userid) {
         // one raw grade updated for one user
         if (empty($updated_item)) {
@@ -1072,6 +1089,18 @@ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null)
         $depends_on[$gid] = $grade_items[$gid]->depends_on();
     }
 
+    $progresstotal = 0;
+    $progresscurrent = 0;
+
+    // This progress total might not be 100% accurate, because more things might get marked as needsupdate
+    // during the process.
+    foreach ($grade_items as $item) {
+        if ($item->needsupdate) {
+            $progresstotal++;
+        }
+    }
+    $progress->start_progress('regrade_course', $progresstotal);
+
     $errors = array();
     $finalids = array();
     $gids     = array_keys($grade_items);
@@ -1088,6 +1117,16 @@ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null)
                 $finalids[] = $gid; // we can make it final - does not need update
                 continue;
             }
+            $thisprogress = $progresstotal;
+            foreach ($grade_items as $item) {
+                if ($item->needsupdate) {
+                    $thisprogress--;
+                }
+            }
+            // Clip between $progresscurrent and $progresstotal.
+            $thisprogress = max(min($thisprogress, $progresstotal), $progresscurrent);
+            $progress->progress($thisprogress);
+            $progresscurrent = $thisprogress;
 
             $doupdate = true;
             foreach ($depends_on[$gid] as $did) {
@@ -1131,6 +1170,7 @@ function grade_regrade_final_grades($courseid, $userid=null, $updated_item=null)
             break; // Found error.
         }
     }
+    $progress->end_progress();
 
     if (count($errors) == 0) {
         if (empty($userid)) {