diff --git a/grade/report/user/lib.php b/grade/report/user/lib.php index 7a146942e1f..ce59ea7a87a 100644 --- a/grade/report/user/lib.php +++ b/grade/report/user/lib.php @@ -350,6 +350,14 @@ class grade_report_user extends grade_report { return true; } + /** + * Fill the table with data. + * + * @param $element - An array containing the table data for the current row. + * @param $aggregationhints - An array that collects the aggregationhints for every + * grade_item. The hints contain grade, grademin, grademax + * status, weight and parent. + */ private function fill_table_recursive(&$element, &$aggregationhints = array()) { global $DB, $CFG; @@ -660,6 +668,8 @@ class grade_report_user extends grade_report { } } + // Check we are showing this column, and we are looking at the root of the table. + // This should be the very last thing this fill_table_recursive function does. if ($this->showcontributiontocoursetotal && ($type == 'category' && $depth == 1)) { // We should have collected all the hints by now - walk the tree again and build the contributions column. @@ -667,6 +677,16 @@ class grade_report_user extends grade_report { } } + /** + * This function is called after the table has been built and the aggregationhints + * have been collected. We need this info to walk up the list of parents of each + * grade_item. + * + * @param $element - An array containing the table data for the current row. + * @param $aggregationhints - An array that collects the aggregationhints for every + * grade_item. The hints contain grade, grademin, grademax + * status, weight and parent. + */ public function fill_contributions_column($element, $aggregationhints) { /// Recursively iterate through all child elements @@ -675,33 +695,46 @@ class grade_report_user extends grade_report { $this->fill_contributions_column($element['children'][$key], $aggregationhints); } } else if ($element['type'] == 'item') { + // This is a grade item (We don't do this for categories or we would double count). $grade_object = $element['object']; $itemid = $grade_object->id; + + // Ignore anything with no hint - e.g. a hidden row. if (isset($aggregationhints[$itemid])) { + // Normalise the gradeval. $graderange = $aggregationhints[$itemid]['grademax'] - $aggregationhints[$itemid]['grademin']; $gradeval = ($aggregationhints[$itemid]['grade'] - $aggregationhints[$itemid]['grademin']) / $graderange; + // Multiply the normalised value by the weight + // of all the categories higher in the tree. $parent = $aggregationhints[$itemid]['parent']; do { if (!is_null($aggregationhints[$itemid]['weight'])) { $gradeval *= $aggregationhints[$itemid]['weight']; } + // The second part of this if is to prevent infinite loops + // in case of crazy data. if (isset($aggregationhints[$itemid]['parent']) && $aggregationhints[$itemid]['parent'] != $itemid) { $parent = $aggregationhints[$itemid]['parent']; $itemid = $parent; } else { + // We are at the top of the tree $parent = false; } } while ($parent); + // Finally multiply by the course grademax. $gradeval *= $aggregationhints[$itemid]['grademax']; + // Now we need to loop through the "built" table data and update the + // contributions column for the current row. $header_row = "row_{$grade_object->id}_{$this->user->id}"; foreach ($this->tabledata as $key => $row) { if (isset($row['itemname']) && ($row['itemname']['id'] == $header_row)) { + // Found it - update the column. $decimals = $grade_object->get_decimals(); $this->tabledata[$key]['contributiontocoursetotal']['content'] = format_float($gradeval, $decimals, true); break; diff --git a/lib/grade/grade_category.php b/lib/grade/grade_category.php index 6ff24c1ccf2..d95e123cea0 100644 --- a/lib/grade/grade_category.php +++ b/lib/grade/grade_category.php @@ -599,6 +599,8 @@ class grade_category extends grade_object { unset($grade_values[$this->grade_item->id]); // Make sure a grade_grade exists for every grade_item. + // We need to do this so we can set the aggregationstatus + // with a set_field call instead of checking if each one exists and creating/updating. foreach ($items as $itemid => $gradeitem) { $gradegrade = new grade_grade(array('itemid' => $gradeitem->id, 'userid' => $userid, @@ -630,6 +632,7 @@ class grade_category extends grade_object { // If null, it means no grade. if ($this->aggregateonlygraded) { unset($grade_values[$itemid]); + // Mark this item as dropped because it has no grade. $novalue[$itemid] = 0; continue; } @@ -657,6 +660,8 @@ class grade_category extends grade_object { if (!$this->aggregateonlygraded) { $grade_values[$itemid] = 0; } else { + // We are specifically marking these items that get dropped + // because they are empty. $novalue[$itemid] = 0; } } @@ -726,9 +731,11 @@ class grade_category extends grade_object { * @param int $userid The user we have aggregated the grades for. * @param array $usedweights An array with keys for each of the grade_item columns included in the aggregation. The value are the relative weight. * @param array $novalue An array with keys for each of the grade_item columns skipped because - * they had no value in the aggregation + * they had no value in the aggregation. * @param array $dropped An array with keys for each of the grade_item columns dropped - * because of any drop lowest/highest settings in the aggregation + * because of any drop lowest/highest settings in the aggregation. + * @param array $extracredit An array with keys for each of the grade_item columns + * considered extra credit by the aggregation. */ private function set_usedinaggregation($userid, $usedweights, $novalue, $dropped, $extracredit) { global $DB; diff --git a/lib/grade/grade_grade.php b/lib/grade/grade_grade.php index b0601996247..430fbbbe704 100644 --- a/lib/grade/grade_grade.php +++ b/lib/grade/grade_grade.php @@ -672,6 +672,9 @@ class grade_grade extends grade_object { * unknown => list of item ids that may be affected by hiding (with the calculated grade as the value) * altered => list of item ids that are definitely affected by hiding (with the calculated grade as the value) * alteredgrademax => for each item in altered or unknown, the new value of the grademax + * alteredgrademin => for each item in altered or unknown, the new value of the grademin + * alteredgradestatus => for each item with a modified status - the value of the new status + * alteredgradeweight => for each item with a modified weight - the value of the new weight */ public static function get_hiding_affected(&$grade_grades, &$grade_items) { global $CFG;