Merge branch 'wip-MDL-27145-master' of git://github.com/samhemelryk/moodle
[moodle.git] / grade / report / user / lib.php
blob22791e1d666e99984a28602ce8395f559923ffed
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 /**
19 * File in which the user_report class is defined.
20 * @package gradebook
23 require_once($CFG->dirroot . '/grade/report/lib.php');
24 require_once($CFG->libdir.'/tablelib.php');
26 //showhiddenitems values
27 define("GRADE_REPORT_USER_HIDE_HIDDEN", 0);
28 define("GRADE_REPORT_USER_HIDE_UNTIL", 1);
29 define("GRADE_REPORT_USER_SHOW_HIDDEN", 2);
31 /**
32 * Class providing an API for the user report building and displaying.
33 * @uses grade_report
34 * @package gradebook
36 class grade_report_user extends grade_report {
38 /**
39 * The user.
40 * @var object $user
42 public $user;
44 /**
45 * A flexitable to hold the data.
46 * @var object $table
48 public $table;
50 /**
51 * An array of table headers
52 * @var array
54 public $tableheaders = array();
56 /**
57 * An array of table columns
58 * @var array
60 public $tablecolumns = array();
62 /**
63 * An array containing rows of data for the table.
64 * @var type
66 public $tabledata = array();
68 /**
69 * The grade tree structure
70 * @var grade_tree
72 public $gtree;
74 /**
75 * Flat structure similar to grade tree
77 public $gseq;
79 /**
80 * show student ranks
82 public $showrank;
84 /**
85 * show grade percentages
87 public $showpercentage;
89 /**
90 * Show range
92 public $showrange = true;
94 /**
95 * Show grades in the report, default true
96 * @var bool
98 public $showgrade = true;
101 * Decimal points to use for values in the report, default 2
102 * @var int
104 public $decimals = 2;
107 * The number of decimal places to round range to, default 0
108 * @var int
110 public $rangedecimals = 0;
113 * Show grade feedback in the report, default true
114 * @var bool
116 public $showfeedback = true;
119 * Show grade weighting in the report, default false
120 * @var bool
122 public $showweight = false;
125 * Show letter grades in the report, default false
126 * @var bool
128 public $showlettergrade = false;
131 * Show average grades in the report, default false.
132 * @var false
134 public $showaverage = false;
136 public $maxdepth;
137 public $evenodd;
139 public $canviewhidden;
141 public $switch;
144 * Show hidden items even when user does not have required cap
146 public $showhiddenitems;
147 public $showtotalsifcontainhidden;
149 public $baseurl;
150 public $pbarurl;
153 * Constructor. Sets local copies of user preferences and initialises grade_tree.
154 * @param int $courseid
155 * @param object $gpr grade plugin return tracking object
156 * @param string $context
157 * @param int $userid The id of the user
159 public function __construct($courseid, $gpr, $context, $userid) {
160 global $DB, $CFG;
161 parent::__construct($courseid, $gpr, $context);
163 $this->showrank = grade_get_setting($this->courseid, 'report_user_showrank', $CFG->grade_report_user_showrank);
164 $this->showpercentage = grade_get_setting($this->courseid, 'report_user_showpercentage', $CFG->grade_report_user_showpercentage);
165 $this->showhiddenitems = grade_get_setting($this->courseid, 'report_user_showhiddenitems', $CFG->grade_report_user_showhiddenitems);
166 $this->showtotalsifcontainhidden = grade_get_setting($this->courseid, 'report_user_showtotalsifcontainhidden', $CFG->grade_report_user_showtotalsifcontainhidden);
168 $this->showgrade = grade_get_setting($this->courseid, 'report_user_showgrade', !empty($CFG->grade_report_user_showgrade));
169 $this->showrange = grade_get_setting($this->courseid, 'report_user_showrange', !empty($CFG->grade_report_user_showrange));
170 $this->showfeedback = grade_get_setting($this->courseid, 'report_user_showfeedback', !empty($CFG->grade_report_user_showfeedback));
171 $this->showweight = grade_get_setting($this->courseid, 'report_user_showweight', !empty($CFG->grade_report_user_showweight));
172 $this->showlettergrade = grade_get_setting($this->courseid, 'report_user_showlettergrade', !empty($CFG->grade_report_user_showlettergrade));
173 $this->showaverage = grade_get_setting($this->courseid, 'report_user_showaverage', !empty($CFG->grade_report_user_showaverage));
175 // The default grade decimals is 2
176 $defaultdecimals = 2;
177 if (property_exists($CFG, 'grade_decimalpoints')) {
178 $defaultdecimals = $CFG->grade_decimalpoints;
180 $this->decimals = grade_get_setting($this->courseid, 'decimalpoints', $defaultdecimals);
182 // The default range decimals is 0
183 $defaultrangedecimals = 0;
184 if (property_exists($CFG, 'grade_report_user_rangedecimals')) {
185 $defaultrangedecimals = $CFG->grade_report_user_rangedecimals;
187 $this->rangedecimals = grade_get_setting($this->courseid, 'report_user_rangedecimals', $defaultrangedecimals);
189 $this->switch = grade_get_setting($this->courseid, 'aggregationposition', $CFG->grade_aggregationposition);
191 // Grab the grade_tree for this course
192 $this->gtree = new grade_tree($this->courseid, false, $this->switch, null, !$CFG->enableoutcomes);
194 // Determine the number of rows and indentation
195 $this->maxdepth = 1;
196 $this->inject_rowspans($this->gtree->top_element);
197 $this->maxdepth++; // Need to account for the lead column that spans all children
198 for ($i = 1; $i <= $this->maxdepth; $i++) {
199 $this->evenodd[$i] = 0;
202 $this->tabledata = array();
204 $this->canviewhidden = has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $this->courseid));
206 // get the user (for full name)
207 $this->user = $DB->get_record('user', array('id' => $userid));
209 // base url for sorting by first/last name
210 $this->baseurl = $CFG->wwwroot.'/grade/report?id='.$courseid.'&amp;userid='.$userid;
211 $this->pbarurl = $this->baseurl;
213 // no groups on this report - rank is from all course users
214 $this->setup_table();
216 //optionally calculate grade item averages
217 $this->calculate_averages();
220 function inject_rowspans(&$element) {
221 if ($element['depth'] > $this->maxdepth) {
222 $this->maxdepth = $element['depth'];
224 if (empty($element['children'])) {
225 return 1;
227 $count = 1;
228 foreach ($element['children'] as $key=>$child) {
229 $count += $this->inject_rowspans($element['children'][$key]);
231 $element['rowspan'] = $count;
232 return $count;
237 * Prepares the headers and attributes of the flexitable.
239 public function setup_table() {
241 * Table has 1-8 columns
242 *| All columns except for itemname/description are optional
245 // setting up table headers
247 $this->tablecolumns = array('itemname');
248 $this->tableheaders = array($this->get_lang_string('gradeitem', 'grades'));
250 if ($this->showweight) {
251 $this->tablecolumns[] = 'weight';
252 $this->tableheaders[] = $this->get_lang_string('weightuc', 'grades');
255 if ($this->showgrade) {
256 $this->tablecolumns[] = 'grade';
257 $this->tableheaders[] = $this->get_lang_string('grade', 'grades');
260 if ($this->showrange) {
261 $this->tablecolumns[] = 'range';
262 $this->tableheaders[] = $this->get_lang_string('range', 'grades');
265 if ($this->showpercentage) {
266 $this->tablecolumns[] = 'percentage';
267 $this->tableheaders[] = $this->get_lang_string('percentage', 'grades');
270 if ($this->showlettergrade) {
271 $this->tablecolumns[] = 'lettergrade';
272 $this->tableheaders[] = $this->get_lang_string('lettergrade', 'grades');
275 if ($this->showrank) {
276 $this->tablecolumns[] = 'rank';
277 $this->tableheaders[] = $this->get_lang_string('rank', 'grades');
280 if ($this->showaverage) {
281 $this->tablecolumns[] = 'average';
282 $this->tableheaders[] = $this->get_lang_string('average', 'grades');
285 if ($this->showfeedback) {
286 $this->tablecolumns[] = 'feedback';
287 $this->tableheaders[] = $this->get_lang_string('feedback', 'grades');
291 function fill_table() {
292 //print "<pre>";
293 //print_r($this->gtree->top_element);
294 $this->fill_table_recursive($this->gtree->top_element);
295 //print_r($this->tabledata);
296 //print "</pre>";
297 return true;
300 private function fill_table_recursive(&$element) {
301 global $DB, $CFG;
303 $type = $element['type'];
304 $depth = $element['depth'];
305 $grade_object = $element['object'];
306 $eid = $grade_object->id;
307 $fullname = $this->gtree->get_element_header($element, true, true, true);
308 $data = array();
309 $hidden = '';
310 $excluded = '';
311 $class = '';
313 // If this is a hidden grade category, hide it completely from the user
314 if ($type == 'category' && $grade_object->is_hidden() && !$this->canviewhidden && (
315 $this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN ||
316 ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_object->is_hiddenuntil()))) {
317 return false;
320 if ($type == 'category') {
321 $this->evenodd[$depth] = (($this->evenodd[$depth] + 1) % 2);
323 $alter = ($this->evenodd[$depth] == 0) ? 'even' : 'odd';
325 /// Process those items that have scores associated
326 if ($type == 'item' or $type == 'categoryitem' or $type == 'courseitem') {
327 if (! $grade_grade = grade_grade::fetch(array('itemid'=>$grade_object->id,'userid'=>$this->user->id))) {
328 $grade_grade = new grade_grade();
329 $grade_grade->userid = $this->user->id;
330 $grade_grade->itemid = $grade_object->id;
333 $grade_grade->load_grade_item();
335 /// Hidden Items
336 if ($grade_grade->grade_item->is_hidden()) {
337 $hidden = ' hidden';
340 // If this is a hidden grade item, hide it completely from the user.
341 if ($grade_grade->is_hidden() && !$this->canviewhidden && (
342 $this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN ||
343 ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_grade->is_hiddenuntil()))) {
344 // return false;
345 } else {
346 /// Excluded Item
347 if ($grade_grade->is_excluded()) {
348 $fullname .= ' ['.get_string('excluded', 'grades').']';
349 $excluded = ' excluded';
352 /// Other class information
353 $class = "$hidden $excluded";
354 if ($this->switch) { // alter style based on whether aggregation is first or last
355 $class .= ($type == 'categoryitem' or $type == 'courseitem') ? " ".$alter."d$depth baggt b2b" : " item b1b";
356 } else {
357 $class .= ($type == 'categoryitem' or $type == 'courseitem') ? " ".$alter."d$depth baggb" : " item b1b";
360 /// Name
361 $data['itemname']['content'] = $fullname;
362 $data['itemname']['class'] = $class;
363 $data['itemname']['colspan'] = ($this->maxdepth - $depth);
365 /// Actual Grade
366 $gradeval = $grade_grade->finalgrade;
368 $class .= " itemcenter ";
369 if ($this->showweight) {
370 $data['weight']['class'] = $class;
371 $data['weight']['content'] = '-';
372 // has a weight assigned, might be extra credit
373 if ($grade_object->aggregationcoef > 0 && $type <> 'courseitem') {
374 $data['weight']['content'] = number_format($grade_object->aggregationcoef,2).'%';
378 if ($this->showgrade) {
379 if ($grade_grade->grade_item->needsupdate) {
380 $data['grade']['class'] = $class.' gradingerror';
381 $data['grade']['content'] = get_string('error');
382 } else if (!empty($CFG->grade_hiddenasdate) and $grade_grade->get_datesubmitted() and !$this->canviewhidden and $grade_grade->is_hidden()
383 and !$grade_grade->grade_item->is_category_item() and !$grade_grade->grade_item->is_course_item()) {
384 // the problem here is that we do not have the time when grade value was modified, 'timemodified' is general modification date for grade_grades records
385 $class .= ' datesubmitted';
386 $data['grade']['class'] = $class;
387 $data['grade']['content'] = get_string('submittedon', 'grades', userdate($grade_grade->get_datesubmitted(), get_string('strftimedatetimeshort')));
389 } elseif ($grade_grade->is_hidden()) {
390 $data['grade']['class'] = $class.' hidden';
391 $data['grade']['content'] = '-';
392 } else {
393 $data['grade']['class'] = $class;
394 $gradeval = $this->blank_hidden_total($this->courseid, $grade_grade->grade_item, $gradeval);
395 $data['grade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true);
399 // Range
400 if ($this->showrange) {
401 $data['range']['class'] = $class;
402 $data['range']['content'] = $grade_grade->grade_item->get_formatted_range(GRADE_DISPLAY_TYPE_REAL, $this->rangedecimals);
405 // Percentage
406 if ($this->showpercentage) {
407 if ($grade_grade->grade_item->needsupdate) {
408 $data['percentage']['class'] = $class.' gradingerror';
409 $data['percentage']['content'] = get_string('error');
410 } else if ($grade_grade->is_hidden()) {
411 $data['percentage']['class'] = $class.' hidden';
412 $data['percentage']['content'] = '-';
413 } else {
414 $data['percentage']['class'] = $class;
415 $data['percentage']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE);
419 // Lettergrade
420 if ($this->showlettergrade) {
421 if ($grade_grade->grade_item->needsupdate) {
422 $data['lettergrade']['class'] = $class.' gradingerror';
423 $data['lettergrade']['content'] = get_string('error');
424 } else if ($grade_grade->is_hidden()) {
425 $data['lettergrade']['class'] = $class.' hidden';
426 if (!$this->canviewhidden) {
427 $data['lettergrade']['content'] = '-';
428 } else {
429 $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER);
431 } else {
432 $data['lettergrade']['class'] = $class;
433 $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER);
437 // Rank
438 if ($this->showrank) {
439 if ($grade_grade->grade_item->needsupdate) {
440 $data['rank']['class'] = $class.' gradingerror';
441 $data['rank']['content'] = get_string('error');
442 } elseif ($grade_grade->is_hidden()) {
443 $data['rank']['class'] = $class.' hidden';
444 $data['rank']['content'] = '-';
445 } else if (is_null($gradeval)) {
446 // no grade, no rank
447 $data['rank']['class'] = $class;
448 $data['rank']['content'] = '-';
450 } else {
451 /// find the number of users with a higher grade
452 $sql = "SELECT COUNT(DISTINCT(userid))
453 FROM {grade_grades}
454 WHERE finalgrade > ?
455 AND itemid = ?
456 AND hidden = 0";
457 $rank = $DB->count_records_sql($sql, array($grade_grade->finalgrade, $grade_grade->grade_item->id)) + 1;
459 $data['rank']['class'] = $class;
460 $data['rank']['content'] = "$rank/".$this->get_numusers(false); // total course users
464 // Average
465 if ($this->showaverage) {
466 $data['average']['class'] = $class;
467 if (!empty($this->gtree->items[$eid]->avg)) {
468 $data['average']['content'] = $this->gtree->items[$eid]->avg;
469 } else {
470 $data['average']['content'] = '-';
474 // Feedback
475 if ($this->showfeedback) {
476 if ($grade_grade->overridden > 0 AND ($type == 'categoryitem' OR $type == 'courseitem')) {
477 $data['feedback']['class'] = $class.' feedbacktext';
478 $data['feedback']['content'] = get_string('overridden', 'grades').': ' . format_text($grade_grade->feedback, $grade_grade->feedbackformat);
479 } else if (empty($grade_grade->feedback) or (!$this->canviewhidden and $grade_grade->is_hidden())) {
480 $data['feedback']['class'] = $class.' feedbacktext';
481 $data['feedback']['content'] = '&nbsp;';
482 } else {
483 $data['feedback']['class'] = $class.' feedbacktext';
484 $data['feedback']['content'] = format_text($grade_grade->feedback, $grade_grade->feedbackformat);
490 /// Category
491 if ($type == 'category') {
492 $data['leader']['class'] = $class.' '.$alter."d$depth b1t b2b b1l";
493 $data['leader']['rowspan'] = $element['rowspan'];
495 if ($this->switch) { // alter style based on whether aggregation is first or last
496 $data['itemname']['class'] = $class.' '.$alter."d$depth b1b b1t";
497 } else {
498 $data['itemname']['class'] = $class.' '.$alter."d$depth b2t";
500 $data['itemname']['colspan'] = ($this->maxdepth - $depth + count($this->tablecolumns) - 1);
501 $data['itemname']['content'] = $fullname;
504 /// Add this row to the overall system
505 $this->tabledata[] = $data;
507 /// Recursively iterate through all child elements
508 if (isset($element['children'])) {
509 foreach ($element['children'] as $key=>$child) {
510 $this->fill_table_recursive($element['children'][$key]);
516 * Prints or returns the HTML from the flexitable.
517 * @param bool $return Whether or not to return the data instead of printing it directly.
518 * @return string
520 public function print_table($return=false) {
521 $maxspan = $this->maxdepth;
523 /// Build table structure
524 $html = "
525 <table cellspacing='0' cellpadding='0' class='boxaligncenter generaltable user-grade'>
526 <thead>
527 <tr>
528 <th class=\"header\" colspan='$maxspan'>".$this->tableheaders[0]."</th>\n";
530 for ($i = 1; $i < count($this->tableheaders); $i++) {
531 $html .= "<th class=\"header\">".$this->tableheaders[$i]."</th>\n";
534 $html .= "
535 </tr>
536 </thead>
537 <tbody>\n";
539 /// Print out the table data
540 for ($i = 0; $i < count($this->tabledata); $i++) {
541 $html .= "<tr>\n";
542 if (isset($this->tabledata[$i]['leader'])) {
543 $rowspan = $this->tabledata[$i]['leader']['rowspan'];
544 $class = $this->tabledata[$i]['leader']['class'];
545 $html .= "<td class='$class' rowspan='$rowspan'></td>\n";
547 for ($j = 0; $j < count($this->tablecolumns); $j++) {
548 $name = $this->tablecolumns[$j];
549 $class = (isset($this->tabledata[$i][$name]['class'])) ? $this->tabledata[$i][$name]['class'] : '';
550 $colspan = (isset($this->tabledata[$i][$name]['colspan'])) ? "colspan='".$this->tabledata[$i][$name]['colspan']."'" : '';
551 $content = (isset($this->tabledata[$i][$name]['content'])) ? $this->tabledata[$i][$name]['content'] : null;
552 if (isset($content)) {
553 $html .= "<td class='$class' $colspan>$content</td>\n";
556 $html .= "</tr>\n";
559 $html .= "</tbody></table>";
561 if ($return) {
562 return $html;
563 } else {
564 echo $html;
569 * Processes the data sent by the form (grades and feedbacks).
570 * @var array $data
571 * @return bool Success or Failure (array of errors).
573 function process_data($data) {
575 function process_action($target, $action) {
579 * Builds the grade item averages.
582 function calculate_averages() {
583 global $USER, $DB;
585 if ($this->showaverage) {
586 // this settings are actually grader report settings (not user report)
587 // however we're using them as having two separate but identical settings the
588 // user would have to keep in sync would be annoying
589 $averagesdisplaytype = $this->get_pref('averagesdisplaytype');
590 $averagesdecimalpoints = $this->get_pref('averagesdecimalpoints');
591 $meanselection = $this->get_pref('meanselection');
592 $shownumberofgrades = $this->get_pref('shownumberofgrades');
594 $avghtml = '';
595 $avgcssclass = 'avg';
597 $straverage = get_string('overallaverage', 'grades');
599 $groupsql = $this->groupsql;
600 $groupwheresql = $this->groupwheresql;
601 //$groupwheresqlparams = ;
603 if ($shownumberofgrades) {
604 $straverage .= ' (' . get_string('submissions', 'grades') . ') ';
607 $totalcount = $this->get_numusers(false);
609 //limit to users with a gradeable role ie students
610 list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
612 //limit to users with an active enrolment
613 list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context);
615 $params = array_merge($this->groupwheresql_params, $gradebookrolesparams, $enrolledparams);
616 $params['courseid'] = $this->courseid;
618 // find sums of all grade items in course
619 $sql = "SELECT gg.itemid, SUM(gg.finalgrade) AS sum
620 FROM {grade_items} gi
621 JOIN {grade_grades} gg ON gg.itemid = gi.id
622 JOIN {user} u ON u.id = gg.userid
623 JOIN ($enrolledsql) je ON je.id = gg.userid
624 JOIN (
625 SELECT DISTINCT ra.userid
626 FROM {role_assignments} ra
627 WHERE ra.roleid $gradebookrolessql
628 AND ra.contextid " . get_related_contexts_string($this->context) . "
629 ) rainner ON rainner.userid = u.id
630 $groupsql
631 WHERE gi.courseid = :courseid
632 AND u.deleted = 0
633 AND gg.finalgrade IS NOT NULL
634 AND gg.hidden = 0
635 $groupwheresql
636 GROUP BY gg.itemid";
638 $sum_array = array();
639 $sums = $DB->get_recordset_sql($sql, $params);
640 foreach ($sums as $itemid => $csum) {
641 $sum_array[$itemid] = $csum->sum;
643 $sums->close();
645 $columncount=0;
647 // Empty grades must be evaluated as grademin, NOT always 0
648 // This query returns a count of ungraded grades (NULL finalgrade OR no matching record in grade_grades table)
649 // No join condition when joining grade_items and user to get a grade item row for every user
650 // Then left join with grade_grades and look for rows with null final grade (which includes grade items with no grade_grade)
651 $sql = "SELECT gi.id, COUNT(u.id) AS count
652 FROM {grade_items} gi
653 JOIN {user} u
654 JOIN ($enrolledsql) je ON je.id = u.id
655 JOIN (
656 SELECT DISTINCT ra.userid
657 FROM {role_assignments} ra
658 WHERE ra.roleid $gradebookrolessql
659 AND ra.contextid " . get_related_contexts_string($this->context) . "
660 ) rainner ON rainner.userid = u.id
661 LEFT JOIN {grade_grades} gg
662 ON (gg.itemid = gi.id AND gg.userid = u.id AND gg.finalgrade IS NOT NULL AND gg.hidden = 0)
663 $groupsql
664 WHERE gi.courseid = :courseid
665 AND u.deleted = 0
666 AND gg.finalgrade IS NULL
667 $groupwheresql
668 GROUP BY gi.id";
670 $ungraded_counts = $DB->get_records_sql($sql, $params);
672 foreach ($this->gtree->items as $itemid=>$unused) {
673 if (!empty($this->gtree->items[$itemid]->avg)) {
674 continue;
676 $item = $this->gtree->items[$itemid];
678 if ($item->needsupdate) {
679 $avghtml .= '<td class="cell c' . $columncount++.'"><span class="gradingerror">'.get_string('error').'</span></td>';
680 continue;
683 if (empty($sum_array[$item->id])) {
684 $sum_array[$item->id] = 0;
687 if (empty($ungraded_counts[$itemid])) {
688 $ungraded_count = 0;
689 } else {
690 $ungraded_count = $ungraded_counts[$itemid]->count;
693 //do they want the averages to include all grade items
694 if ($meanselection == GRADE_REPORT_MEAN_GRADED) {
695 $mean_count = $totalcount - $ungraded_count;
696 } else { // Bump up the sum by the number of ungraded items * grademin
697 $sum_array[$item->id] += ($ungraded_count * $item->grademin);
698 $mean_count = $totalcount;
701 $decimalpoints = $item->get_decimals();
703 // Determine which display type to use for this average
704 if (!empty($USER->gradeediting) && $USER->gradeediting[$this->courseid]) {
705 $displaytype = GRADE_DISPLAY_TYPE_REAL;
707 } else if ($averagesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave the report and user preferences
708 $displaytype = $item->get_displaytype();
710 } else {
711 $displaytype = $averagesdisplaytype;
714 // Override grade_item setting if a display preference (not inherit) was set for the averages
715 if ($averagesdecimalpoints == GRADE_REPORT_PREFERENCE_INHERIT) {
716 $decimalpoints = $item->get_decimals();
718 } else {
719 $decimalpoints = $averagesdecimalpoints;
722 if (empty($sum_array[$item->id]) || $mean_count == 0) {
723 $this->gtree->items[$itemid]->avg = '-';
724 } else {
725 $sum = $sum_array[$item->id];
726 $avgradeval = $sum/$mean_count;
727 $gradehtml = grade_format_gradevalue($avgradeval, $item, true, $displaytype, $decimalpoints);
729 $numberofgrades = '';
730 if ($shownumberofgrades) {
731 $numberofgrades = " ($mean_count)";
734 $this->gtree->items[$itemid]->avg = $gradehtml.$numberofgrades;
741 function grade_report_user_settings_definition(&$mform) {
742 global $CFG;
744 $options = array(-1 => get_string('default', 'grades'),
745 0 => get_string('hide'),
746 1 => get_string('show'));
748 if (empty($CFG->grade_report_user_showrank)) {
749 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
750 } else {
751 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
754 $mform->addElement('select', 'report_user_showrank', get_string('showrank', 'grades'), $options);
755 $mform->addHelpButton('report_user_showrank', 'showrank', 'grades');
757 if (empty($CFG->grade_report_user_showpercentage)) {
758 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
759 } else {
760 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
763 $mform->addElement('select', 'report_user_showpercentage', get_string('showpercentage', 'grades'), $options);
764 $mform->addHelpButton('report_user_showpercentage', 'showpercentage', 'grades');
766 if (empty($CFG->grade_report_user_showgrade)) {
767 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
768 } else {
769 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
772 $mform->addElement('select', 'report_user_showgrade', get_string('showgrade', 'grades'), $options);
774 if (empty($CFG->grade_report_user_showfeedback)) {
775 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
776 } else {
777 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
780 $mform->addElement('select', 'report_user_showfeedback', get_string('showfeedback', 'grades'), $options);
782 if (empty($CFG->grade_report_user_showweight)) {
783 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
784 } else {
785 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
788 $mform->addElement('select', 'report_user_showweight', get_string('showweight', 'grades'), $options);
790 if (empty($CFG->grade_report_user_showaverage)) {
791 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
792 } else {
793 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
796 $mform->addElement('select', 'report_user_showaverage', get_string('showaverage', 'grades'), $options);
797 $mform->addHelpButton('report_user_showaverage', 'showaverage', 'grades');
799 if (empty($CFG->grade_report_user_showlettergrade)) {
800 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
801 } else {
802 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
805 $mform->addElement('select', 'report_user_showlettergrade', get_string('showlettergrade', 'grades'), $options);
807 if (empty($CFG->grade_report_user_showrange)) {
808 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
809 } else {
810 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
813 $mform->addElement('select', 'report_user_showrange', get_string('showrange', 'grades'), $options);
815 $options = array(0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5);
816 if (! empty($CFG->grade_report_user_rangedecimals)) {
817 $options[-1] = $options[$CFG->grade_report_user_rangedecimals];
819 $mform->addElement('select', 'report_user_rangedecimals', get_string('rangedecimals', 'grades'), $options);
821 $options = array(-1 => get_string('default', 'grades'),
822 0 => get_string('shownohidden', 'grades'),
823 1 => get_string('showhiddenuntilonly', 'grades'),
824 2 => get_string('showallhidden', 'grades'));
826 if (empty($CFG->grade_report_user_showhiddenitems)) {
827 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
828 } else {
829 $options[-1] = get_string('defaultprev', 'grades', $options[$CFG->grade_report_user_showhiddenitems]);
832 $mform->addElement('select', 'report_user_showhiddenitems', get_string('showhiddenitems', 'grades'), $options);
833 $mform->addHelpButton('report_user_showhiddenitems', 'showhiddenitems', 'grades');
835 //showtotalsifcontainhidden
836 $options = array(-1 => get_string('default', 'grades'),
837 GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN => get_string('hide'),
838 GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN => get_string('hidetotalshowexhiddenitems', 'grades'),
839 GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN => get_string('hidetotalshowinchiddenitems', 'grades') );
841 if (empty($CFG->grade_report_user_showtotalsifcontainhidden)) {
842 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
843 } else {
844 $options[-1] = get_string('defaultprev', 'grades', $options[$CFG->grade_report_user_showtotalsifcontainhidden]);
847 $mform->addElement('select', 'report_user_showtotalsifcontainhidden', get_string('hidetotalifhiddenitems', 'grades'), $options);
848 $mform->addHelpButton('report_user_showtotalsifcontainhidden', 'hidetotalifhiddenitems', 'grades');
851 function grade_report_user_profilereport($course, $user) {
852 global $OUTPUT;
853 if (!empty($course->showgrades)) {
855 $context = get_context_instance(CONTEXT_COURSE, $course->id);
857 //first make sure we have proper final grades - this must be done before constructing of the grade tree
858 grade_regrade_final_grades($course->id);
860 /// return tracking object
861 $gpr = new grade_plugin_return(array('type'=>'report', 'plugin'=>'user', 'courseid'=>$course->id, 'userid'=>$user->id));
862 // Create a report instance
863 $report = new grade_report_user($course->id, $gpr, $context, $user->id);
865 // print the page
866 echo '<div class="grade-report-user">'; // css fix to share styles with real report page
867 echo $OUTPUT->heading(get_string('pluginname', 'gradereport_user'). ' - '.fullname($report->user));
869 if ($report->fill_table()) {
870 echo $report->print_table(true);
872 echo '</div>';