Merge branch 'MDL-26914-lang-grand-parents' of git://github.com/mudrd8mz/moodle
[moodle.git] / grade / report / user / lib.php
CommitLineData
e060e33d 1<?php
2
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.
14//
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/>.
8ad36f4c 17
f7998fbc 18/**
19 * File in which the user_report class is defined.
20 * @package gradebook
21 */
22
23require_once($CFG->dirroot . '/grade/report/lib.php');
24require_once($CFG->libdir.'/tablelib.php');
25
a83507f2
AD
26//showhiddenitems values
27define("GRADE_REPORT_USER_HIDE_HIDDEN", 0);
28define("GRADE_REPORT_USER_HIDE_UNTIL", 1);
29define("GRADE_REPORT_USER_SHOW_HIDDEN", 2);
30
f7998fbc 31/**
32 * Class providing an API for the user report building and displaying.
33 * @uses grade_report
34 * @package gradebook
35 */
36class grade_report_user extends grade_report {
37
38 /**
39 * The user.
40 * @var object $user
41 */
5c75a0a3 42 public $user;
f7998fbc 43
44 /**
45 * A flexitable to hold the data.
46 * @var object $table
47 */
5c75a0a3 48 public $table;
f7998fbc 49
a071dbb6 50 /**
51 * An array of table headers
52 * @var array
53 */
54 public $tableheaders = array();
55
56 /**
57 * An array of table columns
58 * @var array
59 */
60 public $tablecolumns = array();
61
62 /**
63 * An array containing rows of data for the table.
64 * @var type
65 */
66 public $tabledata = array();
67
68 /**
69 * The grade tree structure
70 * @var grade_tree
71 */
72 public $gtree;
653a8648 73
e0724506 74 /**
75 * Flat structure similar to grade tree
76 */
5c75a0a3 77 public $gseq;
e0724506 78
26ed0305 79 /**
80 * show student ranks
81 */
5c75a0a3 82 public $showrank;
26ed0305 83
699da6b5 84 /**
85 * show grade percentages
86 */
87 public $showpercentage;
88
5528217e 89 /**
90 * Show range
91 */
a071dbb6 92 public $showrange = true;
5528217e 93
a071dbb6 94 /**
95 * Show grades in the report, default true
96 * @var bool
97 */
98 public $showgrade = true;
5528217e 99
a071dbb6 100 /**
101 * Decimal points to use for values in the report, default 2
102 * @var int
103 */
104 public $decimals = 2;
5528217e 105
a071dbb6 106 /**
107 * The number of decimal places to round range to, default 0
108 * @var int
109 */
110 public $rangedecimals = 0;
5528217e 111
a071dbb6 112 /**
113 * Show grade feedback in the report, default true
114 * @var bool
115 */
116 public $showfeedback = true;
117
118 /**
119 * Show grade weighting in the report, default false
120 * @var bool
121 */
122 public $showweight = false;
123
124 /**
125 * Show letter grades in the report, default false
126 * @var bool
127 */
128 public $showlettergrade = false;
129
130 /**
131 * Show average grades in the report, default false.
132 * @var false
133 */
134 public $showaverage = false;
135
136 public $maxdepth;
137 public $evenodd;
138
139 public $canviewhidden;
140
141 public $switch;
5528217e 142
26ed0305 143 /**
144 * Show hidden items even when user does not have required cap
145 */
5c75a0a3 146 public $showhiddenitems;
a071dbb6 147 public $showtotalsifcontainhidden;
148
149 public $baseurl;
150 public $pbarurl;
26ed0305 151
f7998fbc 152 /**
153 * Constructor. Sets local copies of user preferences and initialises grade_tree.
154 * @param int $courseid
d30c4481 155 * @param object $gpr grade plugin return tracking object
f7998fbc 156 * @param string $context
157 * @param int $userid The id of the user
158 */
5c75a0a3 159 public function __construct($courseid, $gpr, $context, $userid) {
a071dbb6 160 global $DB, $CFG;
5c75a0a3 161 parent::__construct($courseid, $gpr, $context);
f7998fbc 162
597f50e6 163 $this->showrank = grade_get_setting($this->courseid, 'report_user_showrank', $CFG->grade_report_user_showrank);
699da6b5 164 $this->showpercentage = grade_get_setting($this->courseid, 'report_user_showpercentage', $CFG->grade_report_user_showpercentage);
597f50e6 165 $this->showhiddenitems = grade_get_setting($this->courseid, 'report_user_showhiddenitems', $CFG->grade_report_user_showhiddenitems);
61541a5a 166 $this->showtotalsifcontainhidden = grade_get_setting($this->courseid, 'report_user_showtotalsifcontainhidden', $CFG->grade_report_user_showtotalsifcontainhidden);
653a8648 167
a071dbb6 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));
174
175 // The default grade decimals is 2
176 $defaultdecimals = 2;
177 if (property_exists($CFG, 'grade_decimalpoints')) {
178 $defaultdecimals = $CFG->grade_decimalpoints;
179 }
180 $this->decimals = grade_get_setting($this->courseid, 'decimalpoints', $defaultdecimals);
181
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;
186 }
187 $this->rangedecimals = grade_get_setting($this->courseid, 'report_user_rangedecimals', $defaultrangedecimals);
188
5528217e 189 $this->switch = grade_get_setting($this->courseid, 'aggregationposition', $CFG->grade_aggregationposition);
190
191 // Grab the grade_tree for this course
4d27bc79 192 $this->gtree = new grade_tree($this->courseid, false, $this->switch, null, !$CFG->enableoutcomes);
26ed0305 193
5528217e 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;
200 }
201
202 $this->tabledata = array();
e0724506 203
5528217e 204 $this->canviewhidden = has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $this->courseid));
4faf5f99 205
f7998fbc 206 // get the user (for full name)
5c75a0a3 207 $this->user = $DB->get_record('user', array('id' => $userid));
f7998fbc 208
209 // base url for sorting by first/last name
210 $this->baseurl = $CFG->wwwroot.'/grade/report?id='.$courseid.'&amp;userid='.$userid;
90d3960c 211 $this->pbarurl = $this->baseurl;
f7998fbc 212
d1214909 213 // no groups on this report - rank is from all course users
90d3960c 214 $this->setup_table();
a071dbb6 215
216 //optionally calculate grade item averages
217 $this->calculate_averages();
f7998fbc 218 }
219
5528217e 220 function inject_rowspans(&$element) {
221 if ($element['depth'] > $this->maxdepth) {
222 $this->maxdepth = $element['depth'];
223 }
224 if (empty($element['children'])) {
225 return 1;
226 }
227 $count = 1;
228 foreach ($element['children'] as $key=>$child) {
229 $count += $this->inject_rowspans($element['children'][$key]);
230 }
231 $element['rowspan'] = $count;
232 return $count;
233 }
234
235
f7998fbc 236 /**
237 * Prepares the headers and attributes of the flexitable.
238 */
5c75a0a3 239 public function setup_table() {
f7998fbc 240 /*
a071dbb6 241 * Table has 1-8 columns
242 *| All columns except for itemname/description are optional
d1214909 243 */
f7998fbc 244
245 // setting up table headers
a071dbb6 246
247 $this->tablecolumns = array('itemname');
248 $this->tableheaders = array($this->get_lang_string('gradeitem', 'grades'));
249
250 if ($this->showweight) {
251 $this->tablecolumns[] = 'weight';
252 $this->tableheaders[] = $this->get_lang_string('weightuc', 'grades');
253 }
254
255 if ($this->showgrade) {
256 $this->tablecolumns[] = 'grade';
257 $this->tableheaders[] = $this->get_lang_string('grade', 'grades');
258 }
699da6b5 259
5528217e 260 if ($this->showrange) {
261 $this->tablecolumns[] = 'range';
262 $this->tableheaders[] = $this->get_lang_string('range', 'grades');
263 }
264
699da6b5 265 if ($this->showpercentage) {
5528217e 266 $this->tablecolumns[] = 'percentage';
267 $this->tableheaders[] = $this->get_lang_string('percentage', 'grades');
699da6b5 268 }
269
a071dbb6 270 if ($this->showlettergrade) {
271 $this->tablecolumns[] = 'lettergrade';
272 $this->tableheaders[] = $this->get_lang_string('lettergrade', 'grades');
273 }
274
26ed0305 275 if ($this->showrank) {
5528217e 276 $this->tablecolumns[] = 'rank';
277 $this->tableheaders[] = $this->get_lang_string('rank', 'grades');
02973505 278 }
f7998fbc 279
a071dbb6 280 if ($this->showaverage) {
281 $this->tablecolumns[] = 'average';
282 $this->tableheaders[] = $this->get_lang_string('average', 'grades');
283 }
f7998fbc 284
a071dbb6 285 if ($this->showfeedback) {
286 $this->tablecolumns[] = 'feedback';
287 $this->tableheaders[] = $this->get_lang_string('feedback', 'grades');
288 }
5528217e 289 }
f7998fbc 290
5528217e 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;
f7998fbc 298 }
299
5528217e 300 private function fill_table_recursive(&$element) {
a071dbb6 301 global $DB, $CFG;
f7998fbc 302
5528217e 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 = '';
f7998fbc 312
a83507f2 313 // If this is a hidden grade category, hide it completely from the user
9e322c8c 314 if ($type == 'category' && $grade_object->is_hidden() && !$this->canviewhidden && (
a83507f2
AD
315 $this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN ||
316 ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_object->is_hiddenuntil()))) {
653a8648 317 return false;
318 }
6391ebe7 319
5528217e 320 if ($type == 'category') {
321 $this->evenodd[$depth] = (($this->evenodd[$depth] + 1) % 2);
b89a70ce 322 }
5528217e 323 $alter = ($this->evenodd[$depth] == 0) ? 'even' : 'odd';
6391ebe7 324
5528217e 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;
d297269d 331 }
6391ebe7 332
5528217e 333 $grade_grade->load_grade_item();
f7998fbc 334
5528217e 335 /// Hidden Items
336 if ($grade_grade->grade_item->is_hidden()) {
337 $hidden = ' hidden';
ced5ee59 338 }
339
a83507f2 340 // If this is a hidden grade item, hide it completely from the user.
653a8648 341 if ($grade_grade->is_hidden() && !$this->canviewhidden && (
a83507f2
AD
342 $this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN ||
343 ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_grade->is_hiddenuntil()))) {
653a8648 344 // return false;
345 } else {
1762a264
AD
346 /// Excluded Item
347 if ($grade_grade->is_excluded()) {
348 $fullname .= ' ['.get_string('excluded', 'grades').']';
349 $excluded = ' excluded';
350 }
653a8648 351
1762a264
AD
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";
358 }
f7998fbc 359
1762a264
AD
360 /// Name
361 $data['itemname']['content'] = $fullname;
362 $data['itemname']['class'] = $class;
363 $data['itemname']['colspan'] = ($this->maxdepth - $depth);
e0724506 364
1762a264
AD
365 /// Actual Grade
366 $gradeval = $grade_grade->finalgrade;
a071dbb6 367
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).'%';
375 }
699da6b5 376 }
6391ebe7 377
a071dbb6 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')));
388
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);
396 }
397 }
398
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);
403 }
404
405 // Percentage
1762a264
AD
406 if ($this->showpercentage) {
407 if ($grade_grade->grade_item->needsupdate) {
408 $data['percentage']['class'] = $class.' gradingerror';
409 $data['percentage']['content'] = get_string('error');
a071dbb6 410 } else if ($grade_grade->is_hidden()) {
411 $data['percentage']['class'] = $class.' hidden';
412 $data['percentage']['content'] = '-';
1762a264
AD
413 } else {
414 $data['percentage']['class'] = $class;
415 $data['percentage']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE);
416 }
417 }
418
a071dbb6 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);
430 }
431 } else {
432 $data['lettergrade']['class'] = $class;
433 $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER);
434 }
435 }
436
437 // Rank
1762a264 438 if ($this->showrank) {
1762a264
AD
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;
653a8648 448 $data['rank']['content'] = '-';
26ed0305 449
1762a264
AD
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 > ?
a071dbb6 455 AND itemid = ?
456 AND hidden = 0";
1762a264
AD
457 $rank = $DB->count_records_sql($sql, array($grade_grade->finalgrade, $grade_grade->grade_item->id)) + 1;
458
459 $data['rank']['class'] = $class;
460 $data['rank']['content'] = "$rank/".$this->get_numusers(false); // total course users
461 }
02973505 462 }
f7998fbc 463
a071dbb6 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'] = '-';
471 }
1762a264 472 }
6391ebe7 473
a071dbb6 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);
485 }
1762a264 486 }
5528217e 487 }
f7998fbc 488 }
e0724506 489
5528217e 490 /// Category
491 if ($type == 'category') {
492 $data['leader']['class'] = $class.' '.$alter."d$depth b1t b2b b1l";
493 $data['leader']['rowspan'] = $element['rowspan'];
494
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";
499 }
500 $data['itemname']['colspan'] = ($this->maxdepth - $depth + count($this->tablecolumns) - 1);
501 $data['itemname']['content'] = $fullname;
502 }
503
504 /// Add this row to the overall system
505 $this->tabledata[] = $data;
506
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]);
511 }
512 }
f7998fbc 513 }
514
515 /**
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
519 */
5c75a0a3 520 public function print_table($return=false) {
5528217e 521 $maxspan = $this->maxdepth;
522
523 /// Build table structure
524 $html = "
81f4918e 525 <table cellspacing='0' cellpadding='0' class='boxaligncenter generaltable user-grade'>
5528217e 526 <thead>
527 <tr>
528 <th class=\"header\" colspan='$maxspan'>".$this->tableheaders[0]."</th>\n";
529
530 for ($i = 1; $i < count($this->tableheaders); $i++) {
531 $html .= "<th class=\"header\">".$this->tableheaders[$i]."</th>\n";
532 }
533
534 $html .= "
535 </tr>
536 </thead>
537 <tbody>\n";
538
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";
546 }
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";
554 }
555 }
556 $html .= "</tr>\n";
557 }
558
559 $html .= "</tbody></table>";
560
f7998fbc 561 if ($return) {
562 return $html;
563 } else {
564 echo $html;
565 }
566 }
567
568 /**
569 * Processes the data sent by the form (grades and feedbacks).
570 * @var array $data
571 * @return bool Success or Failure (array of errors).
572 */
653a8648 573 function process_data($data) {
5c75a0a3 574 }
653a8648 575 function process_action($target, $action) {
f7998fbc 576 }
a071dbb6 577
578 /**
579 * Builds the grade item averages.
580 *
581 */
582 function calculate_averages() {
583 global $USER, $DB;
584
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');
593
594 $avghtml = '';
595 $avgcssclass = 'avg';
596
597 $straverage = get_string('overallaverage', 'grades');
598
599 $groupsql = $this->groupsql;
600 $groupwheresql = $this->groupwheresql;
601 //$groupwheresqlparams = ;
602
603 if ($shownumberofgrades) {
604 $straverage .= ' (' . get_string('submissions', 'grades') . ') ';
605 }
606
607 $totalcount = $this->get_numusers(false);
608
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');
611
612 //limit to users with an active enrolment
613 list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context);
614
615 $params = array_merge($this->groupwheresql_params, $gradebookrolesparams, $enrolledparams);
616 $params['courseid'] = $this->courseid;
617
618 // find sums of all grade items in course
619 $sql = "SELECT gg.itemid, SUM(gg.finalgrade) AS sum
620 FROM {grade_items} gi
a1e26b5e
SH
621 JOIN {grade_grades} gg
622 ON gg.itemid = gi.id
623 JOIN ($enrolledsql) je
624 ON je.id = gg.userid
625 JOIN {role_assignments} ra
626 ON ra.userid = gg.userid
a071dbb6 627 $groupsql
628 WHERE gi.courseid = :courseid
629 AND ra.roleid $gradebookrolessql
630 AND ra.contextid ".get_related_contexts_string($this->context)."
631 AND gg.finalgrade IS NOT NULL
632 AND gg.hidden = 0
633 $groupwheresql
634 GROUP BY gg.itemid";
635
636 $sum_array = array();
cc65dc36
EL
637 $sums = $DB->get_recordset_sql($sql, $params);
638 foreach ($sums as $itemid => $csum) {
639 $sum_array[$itemid] = $csum->sum;
a071dbb6 640 }
cc65dc36 641 $sums->close();
a071dbb6 642
643 $columncount=0;
644
645 // Empty grades must be evaluated as grademin, NOT always 0
646 // This query returns a count of ungraded grades (NULL finalgrade OR no matching record in grade_grades table)
647 // No join condition when joining grade_items and user to get a grade item row for every user
648 // Then left join with grade_grades and look for rows with null final grade (which includes grade items with no grade_grade)
649 $sql = "SELECT gi.id, COUNT(u.id) AS count
650 FROM {grade_items} gi
651 JOIN {user} u
a1e26b5e
SH
652 JOIN ($enrolledsql) je
653 ON je.id = u.id
654 JOIN {role_assignments} ra
655 ON ra.userid = u.id
656 LEFT JOIN {grade_grades} gg
657 ON (gg.itemid = gi.id AND gg.userid = u.id AND gg.finalgrade IS NOT NULL AND gg.hidden = 0)
a071dbb6 658 $groupsql
659 WHERE gi.courseid = :courseid
660 AND ra.roleid $gradebookrolessql
661 AND ra.contextid ".get_related_contexts_string($this->context)."
662 AND gg.finalgrade IS NULL
663 $groupwheresql
664 GROUP BY gi.id";
665
666 $ungraded_counts = $DB->get_records_sql($sql, $params);
667
668 foreach ($this->gtree->items as $itemid=>$unused) {
669 if (!empty($this->gtree->items[$itemid]->avg)) {
670 continue;
671 }
672 $item = $this->gtree->items[$itemid];
673
674 if ($item->needsupdate) {
675 $avghtml .= '<td class="cell c' . $columncount++.'"><span class="gradingerror">'.get_string('error').'</span></td>';
676 continue;
677 }
678
679 if (empty($sum_array[$item->id])) {
680 $sum_array[$item->id] = 0;
681 }
682
683 if (empty($ungraded_counts[$itemid])) {
684 $ungraded_count = 0;
685 } else {
686 $ungraded_count = $ungraded_counts[$itemid]->count;
687 }
688
689 //do they want the averages to include all grade items
690 if ($meanselection == GRADE_REPORT_MEAN_GRADED) {
691 $mean_count = $totalcount - $ungraded_count;
692 } else { // Bump up the sum by the number of ungraded items * grademin
693 $sum_array[$item->id] += ($ungraded_count * $item->grademin);
694 $mean_count = $totalcount;
695 }
696
697 $decimalpoints = $item->get_decimals();
698
699 // Determine which display type to use for this average
700 if (!empty($USER->gradeediting) && $USER->gradeediting[$this->courseid]) {
701 $displaytype = GRADE_DISPLAY_TYPE_REAL;
702
703 } else if ($averagesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave the report and user preferences
704 $displaytype = $item->get_displaytype();
705
706 } else {
707 $displaytype = $averagesdisplaytype;
708 }
709
710 // Override grade_item setting if a display preference (not inherit) was set for the averages
711 if ($averagesdecimalpoints == GRADE_REPORT_PREFERENCE_INHERIT) {
712 $decimalpoints = $item->get_decimals();
713
714 } else {
715 $decimalpoints = $averagesdecimalpoints;
716 }
717
718 if (empty($sum_array[$item->id]) || $mean_count == 0) {
719 $this->gtree->items[$itemid]->avg = '-';
720 } else {
721 $sum = $sum_array[$item->id];
722 $avgradeval = $sum/$mean_count;
723 $gradehtml = grade_format_gradevalue($avgradeval, $item, true, $displaytype, $decimalpoints);
724
725 $numberofgrades = '';
726 if ($shownumberofgrades) {
727 $numberofgrades = " ($mean_count)";
728 }
729
730 $this->gtree->items[$itemid]->avg = $gradehtml.$numberofgrades;
731 }
732 }
733 }
734 }
26ed0305 735}
736
737function grade_report_user_settings_definition(&$mform) {
738 global $CFG;
739
740 $options = array(-1 => get_string('default', 'grades'),
741 0 => get_string('hide'),
742 1 => get_string('show'));
743
cd52d909 744 if (empty($CFG->grade_report_user_showrank)) {
26ed0305 745 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
746 } else {
747 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
748 }
749
750 $mform->addElement('select', 'report_user_showrank', get_string('showrank', 'grades'), $options);
1cc3165e 751 $mform->addHelpButton('report_user_showrank', 'showrank', 'grades');
26ed0305 752
699da6b5 753 if (empty($CFG->grade_report_user_showpercentage)) {
aea45e7e 754 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
5528217e 755 } else {
756 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
699da6b5 757 }
758
759 $mform->addElement('select', 'report_user_showpercentage', get_string('showpercentage', 'grades'), $options);
ff268dcb 760 $mform->addHelpButton('report_user_showpercentage', 'showpercentage', 'grades');
699da6b5 761
a071dbb6 762 if (empty($CFG->grade_report_user_showgrade)) {
763 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
764 } else {
765 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
766 }
767
768 $mform->addElement('select', 'report_user_showgrade', get_string('showgrade', 'grades'), $options);
769
770 if (empty($CFG->grade_report_user_showfeedback)) {
771 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
772 } else {
773 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
774 }
775
776 $mform->addElement('select', 'report_user_showfeedback', get_string('showfeedback', 'grades'), $options);
777
778 if (empty($CFG->grade_report_user_showweight)) {
779 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
780 } else {
781 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
782 }
783
784 $mform->addElement('select', 'report_user_showweight', get_string('showweight', 'grades'), $options);
785
786 if (empty($CFG->grade_report_user_showaverage)) {
787 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
788 } else {
789 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
790 }
791
792 $mform->addElement('select', 'report_user_showaverage', get_string('showaverage', 'grades'), $options);
793 $mform->addHelpButton('report_user_showaverage', 'showaverage', 'grades');
794
795 if (empty($CFG->grade_report_user_showlettergrade)) {
796 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
797 } else {
798 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
799 }
800
801 $mform->addElement('select', 'report_user_showlettergrade', get_string('showlettergrade', 'grades'), $options);
802
803 if (empty($CFG->grade_report_user_showrange)) {
804 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
805 } else {
806 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
807 }
808
809 $mform->addElement('select', 'report_user_showrange', get_string('showrange', 'grades'), $options);
810
811 $options = array(0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5);
812 if (! empty($CFG->grade_report_user_rangedecimals)) {
813 $options[-1] = $options[$CFG->grade_report_user_rangedecimals];
814 }
815 $mform->addElement('select', 'report_user_rangedecimals', get_string('rangedecimals', 'grades'), $options);
816
26ed0305 817 $options = array(-1 => get_string('default', 'grades'),
d69ef28b 818 0 => get_string('shownohidden', 'grades'),
597f50e6 819 1 => get_string('showhiddenuntilonly', 'grades'),
d69ef28b 820 2 => get_string('showallhidden', 'grades'));
26ed0305 821
cd52d909 822 if (empty($CFG->grade_report_user_showhiddenitems)) {
26ed0305 823 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
824 } else {
d69ef28b 825 $options[-1] = get_string('defaultprev', 'grades', $options[$CFG->grade_report_user_showhiddenitems]);
26ed0305 826 }
827
828 $mform->addElement('select', 'report_user_showhiddenitems', get_string('showhiddenitems', 'grades'), $options);
69e3e962 829 $mform->addHelpButton('report_user_showhiddenitems', 'showhiddenitems', 'grades');
61541a5a
AD
830
831 //showtotalsifcontainhidden
832 $options = array(-1 => get_string('default', 'grades'),
833 GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN => get_string('hide'),
834 GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN => get_string('hidetotalshowexhiddenitems', 'grades'),
835 GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN => get_string('hidetotalshowinchiddenitems', 'grades') );
836
837 if (empty($CFG->grade_report_user_showtotalsifcontainhidden)) {
838 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
839 } else {
840 $options[-1] = get_string('defaultprev', 'grades', $options[$CFG->grade_report_user_showtotalsifcontainhidden]);
841 }
842
843 $mform->addElement('select', 'report_user_showtotalsifcontainhidden', get_string('hidetotalifhiddenitems', 'grades'), $options);
0459cc4d 844 $mform->addHelpButton('report_user_showtotalsifcontainhidden', 'hidetotalifhiddenitems', 'grades');
0a784551 845}
846
847function grade_report_user_profilereport($course, $user) {
91152a35 848 global $OUTPUT;
0a784551 849 if (!empty($course->showgrades)) {
850
851 $context = get_context_instance(CONTEXT_COURSE, $course->id);
852
853 //first make sure we have proper final grades - this must be done before constructing of the grade tree
854 grade_regrade_final_grades($course->id);
855
856 /// return tracking object
857 $gpr = new grade_plugin_return(array('type'=>'report', 'plugin'=>'user', 'courseid'=>$course->id, 'userid'=>$user->id));
858 // Create a report instance
859 $report = new grade_report_user($course->id, $gpr, $context, $user->id);
f7998fbc 860
0a784551 861 // print the page
862 echo '<div class="grade-report-user">'; // css fix to share styles with real report page
b5e7b2bf 863 echo $OUTPUT->heading(get_string('pluginname', 'gradereport_user'). ' - '.fullname($report->user));
0a784551 864
865 if ($report->fill_table()) {
866 echo $report->print_table(true);
867 }
868 echo '</div>';
869 }
f7998fbc 870}
0a784551 871
6c3ef410 872