diff --git a/grade/lib.php b/grade/lib.php index 1da3b5f2cbc..13254d1746b 100644 --- a/grade/lib.php +++ b/grade/lib.php @@ -705,6 +705,11 @@ class grade_seq { */ var $items; + /** + * 1D array of elements + */ + var $elements; + /** * Course context */ @@ -727,7 +732,11 @@ class grade_seq { // get course grade tree $top_element = grade_category::fetch_course_tree($courseid, true); - $this->items = grade_seq::flatten($top_element, $category_grade_last, $nooutcomes); + $this->elements = grade_seq::flatten($top_element, $category_grade_last, $nooutcomes); + + foreach ($this->elements as $key=>$unused) { + $this->items[$key] =& $this->elements[$key]['object']; + } } /** @@ -758,10 +767,10 @@ class grade_seq { $result = array(); foreach ($children as $child) { if ($child['type'] == 'category') { - $result = array_merge($result, grade_seq::flatten($child, $category_grade_last, $nooutcomes)); + $result = $result + grade_seq::flatten($child, $category_grade_last, $nooutcomes); } else { $child['eid'] = 'i'.$child['object']->id; - $result[] = $child; + $result[$child['object']->id] = $child; } } @@ -809,7 +818,7 @@ class grade_seq { } // it is a category or item - foreach ($this->items as $element) { + foreach ($this->elements as $element) { if ($element['eid'] == $eid) { return $element; } diff --git a/grade/report/user/lib.php b/grade/report/user/lib.php index f7ee0e784cd..339ebdc522a 100644 --- a/grade/report/user/lib.php +++ b/grade/report/user/lib.php @@ -124,103 +124,104 @@ class grade_report_user extends grade_report { function fill_table() { global $CFG; $numusers = $this->get_numusers(false); // total course users + $items =& $this->gseq->items; + $grades = array(); - foreach ($this->gseq->items as $element) { - $grade_item = $element['object']; - $decimalpoints = $grade_item->get_decimals(); - $data = array(); + $viewhidden = has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $this->courseid)); + foreach ($items as $key=>$unused) { + $grade_item =& $items[$key]; $grade_grade = new grade_grade(array('itemid'=>$grade_item->id, 'userid'=>$this->user->id)); - $grade_grade->grade_item =& $grade_item; + $grades[$key] = $grade_grade; + $grades[$key]->grade_item =& $grade_item; + } + + $hiding_affected = grade_grade::get_hiding_affected($grades, $items); + + foreach ($items as $key=>$unused) { + $grade_item =& $items[$key]; + $grade_grade =& $grades[$key]; + + $data = array(); // TODO: indicate items that "needsupdate" - missing final calculation /// prints grade item name if ($grade_item->is_course_item() or $grade_item->is_category_item()) { - $data[] = ''.$grade_item->get_name().''; + $data[] = '
'.$grade_item->get_name().'
'; } else { - $data[] = $this->get_module_link($grade_item->get_name(), $grade_item->itemmodule, $grade_item->iteminstance);; + $data[] = '
'.$this->get_module_link($grade_item->get_name(), $grade_item->itemmodule, $grade_item->iteminstance).'
'; } /// prints category $cat = $grade_item->get_parent_category(); - $data[] = $cat->fullname; - + $data[] = $cat->get_name(); /// prints the grade - $displaytype = $grade_item->get_displaytype(); - if ($grade_grade->is_excluded()) { $excluded = get_string('excluded', 'grades').' '; } else { $excluded = ''; } - if ((int) $grade_grade->finalgrade < 1) { - $data[] = '-'; - } elseif ($grade_grade->is_hidden() && !has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $grade_item->courseid))) { - $data[] = get_string('gradedon', 'grades', userdate($grade_grade->timemodified)); - } elseif ($grade_item->scaleid) { - if ($scale = get_record('scale', 'id', $grade_item->scaleid)) { - $scales = explode(",", $scale->scale); - // reindex because scale is off 1 - $data[] = $excluded.$scales[$grade_grade->finalgrade-1]; + if (is_null($grade_grade->finalgrade)) { + $data[] = $excluded . '-'; + + } else if (($grade_grade->is_hidden() or in_array($grade_item->id, $hiding_affected)) and !$viewhidden) { + // TODO: optinally do not show anything for hidden grades + // $data[] = '-'; + if ($grade_grade->is_hidden()) { + $data[] = $excluded . '
'.get_string('gradedon', 'grades', userdate($grade_grade->timemodified, get_string('strftimedatetimeshort'))).'
'; + } else { + $data[] = $excluded . '-'; } + } else { - $data[] = $excluded . grade_format_gradevalue($grade_grade->finalgrade, $grade_item, true, $displaytype, $decimalpoints); + $data[] = $excluded . grade_format_gradevalue($grade_grade->finalgrade, $grade_item, true); } /// prints percentage - if ($grade_grade->is_hidden() && !has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $grade_item->courseid))) { - if ((int) $grade_grade->finalgrade < 1) { - $data[] = '-'; - } else { - $data[] = get_string('gradedon', 'grades', userdate($grade_grade->timemodified)); - } + if (is_null($grade_grade->finalgrade)) { + $data[] = '-'; + + } else if (($grade_grade->is_hidden() or in_array($grade_item->id, $hiding_affected)) and !$viewhidden) { + $data[] = '-'; + } else { - if ($grade_item->gradetype == GRADE_TYPE_VALUE) { - // processing numeric grade - if ($grade_grade->finalgrade) { - $percentage = format_float(($grade_grade->finalgrade / $grade_item->grademax) * 100, $decimalpoints).'%'; - } else { - $percentage = '-'; - } - - } else if ($grade_item->gradetype == GRADE_TYPE_SCALE) { - // processing scale grade - $scale = get_record('scale', 'id', $grade_item->scaleid); - $scalevals = explode(",", $scale->scale); - $percentage = format_float(($grade_grade->finalgrade) / count($scalevals) * 100, $decimalpoints).'%'; - - } else { - // text grade - $percentage = '-'; - } - - $data[] = $percentage; + $data[] = grade_format_gradevalue($grade_grade->finalgrade, $grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE); } + /// prints rank - if ($grade_grade->finalgrade) { + if (is_null($grade_grade->finalgrade)) { + // no grade, no rank + $data[] = '-'; + + } else if (($grade_grade->is_hidden() or in_array($grade_item->id, $hiding_affected)) and !$viewhidden) { + $data[] = '-'; + + } else { /// find the number of users with a higher grade $sql = "SELECT COUNT(DISTINCT(userid)) - FROM {$CFG->prefix}grade_grades - WHERE finalgrade > $grade_grade->finalgrade - AND itemid = $grade_item->id"; + FROM {$CFG->prefix}grade_grades + WHERE finalgrade > {$grade_grade->finalgrade} + AND itemid = {$grade_item->id}"; $rank = count_records_sql($sql) + 1; $data[] = "$rank/$numusers"; - } else { - // no grade, no rank - $data[] = "-"; } /// prints notes - if (!empty($grade_grade->feedback)) { - $data[] = format_text($grade_grade->feedback, $grade_grade->feedbackformat); - } else { + if (empty($grade_grade->feedback)) { $data[] = ' '; + + } else if (($grade_grade->is_hidden() or in_array($grade_item->id, $hiding_affected)) and !$viewhidden) { + $data[] = ' '; + + } else { + $data[] = format_text($grade_grade->feedback, $grade_grade->feedbackformat); } + $this->table->add_data($data); } diff --git a/lib/grade/grade_grade.php b/lib/grade/grade_grade.php index a97e3c9887e..2d35722aa32 100644 --- a/lib/grade/grade_grade.php +++ b/lib/grade/grade_grade.php @@ -471,5 +471,57 @@ class grade_grade extends grade_object { $standardised_value = $factor * $diff + $target_min; return $standardised_value; } + + /** + * Return array of grade item ids that are either hidden or indirectly depend + * on hidden grades, excluded grades are not returned. + * @static + * @param array $grades all course grades of one user + * @param array $items $grade_items array of grade items, & used for better internal caching + * @return array + */ + function get_hiding_affected($grade_grades, &$grade_items) { + if (count($grade_grades) !== count($grade_items)) { + error("Incorrent size of arrays in params of grade_grade::get_hiding_affected()!"); + } + + $dependson = array(); + foreach($grade_items as $key=>$unused) { + $grade_item =& $grade_items[$key]; // reference for improved caching inside grade_item + $dependson[$grade_item->id] = $grade_item->depends_on(); + } + + $todo = array(); + $hiding = array(); + foreach($grade_grades as $grade_grade) { + if ($grade_grade->is_hidden() and !$grade_grade->is_excluded() and !is_null($grade_grade->finalgrade)) { + $hiding[] = $grade_grade->itemid; + } else { + $todo[] = $grade_grade->itemid; + } + } + + $max = count($grade_items); + for($i=0; $i<$max; $i++) { + $found = false; + foreach($todo as $key=>$do) { + if (empty($dependson[$do])) { + unset($todo[$key]); + continue; + + } else if (array_intersect($dependson[$do], $hiding)) { + // this item depends on hidden grade indirectly + $hiding[] = $do; + unset($todo[$key]); + $found = true; + } + } + if (!$found) { + break; + } + } + + return $hiding; + } } ?> diff --git a/theme/standard/styles_fonts.css b/theme/standard/styles_fonts.css index 4f4f2f79b31..2eb5094e0e3 100644 --- a/theme/standard/styles_fonts.css +++ b/theme/standard/styles_fonts.css @@ -509,6 +509,14 @@ body#grade-index .grades .header { font-weight: bold; } +.grade-report-user .gradeddate { + font-size: 0.7em; +} + +.grade-report-user .catname { + font-weight: bold; +} + /*** *** Login ***/