MDL-27703 gradebook: altered an sql query in the user report. join with no on clause...
[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;
c97933ff 307 $element['userid'] = $this->user->id;
5528217e 308 $fullname = $this->gtree->get_element_header($element, true, true, true);
309 $data = array();
310 $hidden = '';
311 $excluded = '';
312 $class = '';
f7998fbc 313
a83507f2 314 // If this is a hidden grade category, hide it completely from the user
9e322c8c 315 if ($type == 'category' && $grade_object->is_hidden() && !$this->canviewhidden && (
a83507f2
AD
316 $this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN ||
317 ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_object->is_hiddenuntil()))) {
653a8648 318 return false;
319 }
6391ebe7 320
5528217e 321 if ($type == 'category') {
322 $this->evenodd[$depth] = (($this->evenodd[$depth] + 1) % 2);
b89a70ce 323 }
5528217e 324 $alter = ($this->evenodd[$depth] == 0) ? 'even' : 'odd';
6391ebe7 325
5528217e 326 /// Process those items that have scores associated
327 if ($type == 'item' or $type == 'categoryitem' or $type == 'courseitem') {
328 if (! $grade_grade = grade_grade::fetch(array('itemid'=>$grade_object->id,'userid'=>$this->user->id))) {
329 $grade_grade = new grade_grade();
330 $grade_grade->userid = $this->user->id;
331 $grade_grade->itemid = $grade_object->id;
d297269d 332 }
6391ebe7 333
5528217e 334 $grade_grade->load_grade_item();
f7998fbc 335
5528217e 336 /// Hidden Items
337 if ($grade_grade->grade_item->is_hidden()) {
338 $hidden = ' hidden';
ced5ee59 339 }
340
a83507f2 341 // If this is a hidden grade item, hide it completely from the user.
653a8648 342 if ($grade_grade->is_hidden() && !$this->canviewhidden && (
a83507f2
AD
343 $this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN ||
344 ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_grade->is_hiddenuntil()))) {
653a8648 345 // return false;
346 } else {
1762a264
AD
347 /// Excluded Item
348 if ($grade_grade->is_excluded()) {
349 $fullname .= ' ['.get_string('excluded', 'grades').']';
350 $excluded = ' excluded';
351 }
653a8648 352
1762a264
AD
353 /// Other class information
354 $class = "$hidden $excluded";
355 if ($this->switch) { // alter style based on whether aggregation is first or last
356 $class .= ($type == 'categoryitem' or $type == 'courseitem') ? " ".$alter."d$depth baggt b2b" : " item b1b";
357 } else {
358 $class .= ($type == 'categoryitem' or $type == 'courseitem') ? " ".$alter."d$depth baggb" : " item b1b";
359 }
f7998fbc 360
1762a264
AD
361 /// Name
362 $data['itemname']['content'] = $fullname;
363 $data['itemname']['class'] = $class;
364 $data['itemname']['colspan'] = ($this->maxdepth - $depth);
e0724506 365
1762a264
AD
366 /// Actual Grade
367 $gradeval = $grade_grade->finalgrade;
a071dbb6 368
369 $class .= " itemcenter ";
370 if ($this->showweight) {
371 $data['weight']['class'] = $class;
372 $data['weight']['content'] = '-';
373 // has a weight assigned, might be extra credit
374 if ($grade_object->aggregationcoef > 0 && $type <> 'courseitem') {
375 $data['weight']['content'] = number_format($grade_object->aggregationcoef,2).'%';
376 }
699da6b5 377 }
6391ebe7 378
a071dbb6 379 if ($this->showgrade) {
380 if ($grade_grade->grade_item->needsupdate) {
381 $data['grade']['class'] = $class.' gradingerror';
382 $data['grade']['content'] = get_string('error');
383 } else if (!empty($CFG->grade_hiddenasdate) and $grade_grade->get_datesubmitted() and !$this->canviewhidden and $grade_grade->is_hidden()
384 and !$grade_grade->grade_item->is_category_item() and !$grade_grade->grade_item->is_course_item()) {
385 // 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
386 $class .= ' datesubmitted';
387 $data['grade']['class'] = $class;
388 $data['grade']['content'] = get_string('submittedon', 'grades', userdate($grade_grade->get_datesubmitted(), get_string('strftimedatetimeshort')));
389
390 } elseif ($grade_grade->is_hidden()) {
391 $data['grade']['class'] = $class.' hidden';
392 $data['grade']['content'] = '-';
393 } else {
394 $data['grade']['class'] = $class;
395 $gradeval = $this->blank_hidden_total($this->courseid, $grade_grade->grade_item, $gradeval);
396 $data['grade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true);
397 }
398 }
399
400 // Range
401 if ($this->showrange) {
402 $data['range']['class'] = $class;
403 $data['range']['content'] = $grade_grade->grade_item->get_formatted_range(GRADE_DISPLAY_TYPE_REAL, $this->rangedecimals);
404 }
405
406 // Percentage
1762a264
AD
407 if ($this->showpercentage) {
408 if ($grade_grade->grade_item->needsupdate) {
409 $data['percentage']['class'] = $class.' gradingerror';
410 $data['percentage']['content'] = get_string('error');
a071dbb6 411 } else if ($grade_grade->is_hidden()) {
412 $data['percentage']['class'] = $class.' hidden';
413 $data['percentage']['content'] = '-';
1762a264
AD
414 } else {
415 $data['percentage']['class'] = $class;
416 $data['percentage']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE);
417 }
418 }
419
a071dbb6 420 // Lettergrade
421 if ($this->showlettergrade) {
422 if ($grade_grade->grade_item->needsupdate) {
423 $data['lettergrade']['class'] = $class.' gradingerror';
424 $data['lettergrade']['content'] = get_string('error');
425 } else if ($grade_grade->is_hidden()) {
426 $data['lettergrade']['class'] = $class.' hidden';
427 if (!$this->canviewhidden) {
428 $data['lettergrade']['content'] = '-';
429 } else {
430 $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER);
431 }
432 } else {
433 $data['lettergrade']['class'] = $class;
434 $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER);
435 }
436 }
437
438 // Rank
1762a264 439 if ($this->showrank) {
1762a264
AD
440 if ($grade_grade->grade_item->needsupdate) {
441 $data['rank']['class'] = $class.' gradingerror';
442 $data['rank']['content'] = get_string('error');
443 } elseif ($grade_grade->is_hidden()) {
444 $data['rank']['class'] = $class.' hidden';
445 $data['rank']['content'] = '-';
446 } else if (is_null($gradeval)) {
447 // no grade, no rank
448 $data['rank']['class'] = $class;
653a8648 449 $data['rank']['content'] = '-';
26ed0305 450
1762a264
AD
451 } else {
452 /// find the number of users with a higher grade
453 $sql = "SELECT COUNT(DISTINCT(userid))
454 FROM {grade_grades}
455 WHERE finalgrade > ?
a071dbb6 456 AND itemid = ?
457 AND hidden = 0";
1762a264
AD
458 $rank = $DB->count_records_sql($sql, array($grade_grade->finalgrade, $grade_grade->grade_item->id)) + 1;
459
460 $data['rank']['class'] = $class;
461 $data['rank']['content'] = "$rank/".$this->get_numusers(false); // total course users
462 }
02973505 463 }
f7998fbc 464
a071dbb6 465 // Average
466 if ($this->showaverage) {
467 $data['average']['class'] = $class;
468 if (!empty($this->gtree->items[$eid]->avg)) {
469 $data['average']['content'] = $this->gtree->items[$eid]->avg;
470 } else {
471 $data['average']['content'] = '-';
472 }
1762a264 473 }
6391ebe7 474
a071dbb6 475 // Feedback
476 if ($this->showfeedback) {
477 if ($grade_grade->overridden > 0 AND ($type == 'categoryitem' OR $type == 'courseitem')) {
478 $data['feedback']['class'] = $class.' feedbacktext';
479 $data['feedback']['content'] = get_string('overridden', 'grades').': ' . format_text($grade_grade->feedback, $grade_grade->feedbackformat);
480 } else if (empty($grade_grade->feedback) or (!$this->canviewhidden and $grade_grade->is_hidden())) {
481 $data['feedback']['class'] = $class.' feedbacktext';
482 $data['feedback']['content'] = '&nbsp;';
483 } else {
484 $data['feedback']['class'] = $class.' feedbacktext';
485 $data['feedback']['content'] = format_text($grade_grade->feedback, $grade_grade->feedbackformat);
486 }
1762a264 487 }
5528217e 488 }
f7998fbc 489 }
e0724506 490
5528217e 491 /// Category
492 if ($type == 'category') {
493 $data['leader']['class'] = $class.' '.$alter."d$depth b1t b2b b1l";
494 $data['leader']['rowspan'] = $element['rowspan'];
495
496 if ($this->switch) { // alter style based on whether aggregation is first or last
497 $data['itemname']['class'] = $class.' '.$alter."d$depth b1b b1t";
498 } else {
499 $data['itemname']['class'] = $class.' '.$alter."d$depth b2t";
500 }
501 $data['itemname']['colspan'] = ($this->maxdepth - $depth + count($this->tablecolumns) - 1);
502 $data['itemname']['content'] = $fullname;
503 }
504
505 /// Add this row to the overall system
506 $this->tabledata[] = $data;
507
508 /// Recursively iterate through all child elements
509 if (isset($element['children'])) {
510 foreach ($element['children'] as $key=>$child) {
511 $this->fill_table_recursive($element['children'][$key]);
512 }
513 }
f7998fbc 514 }
515
516 /**
517 * Prints or returns the HTML from the flexitable.
518 * @param bool $return Whether or not to return the data instead of printing it directly.
519 * @return string
520 */
5c75a0a3 521 public function print_table($return=false) {
5528217e 522 $maxspan = $this->maxdepth;
523
524 /// Build table structure
525 $html = "
81f4918e 526 <table cellspacing='0' cellpadding='0' class='boxaligncenter generaltable user-grade'>
5528217e 527 <thead>
528 <tr>
529 <th class=\"header\" colspan='$maxspan'>".$this->tableheaders[0]."</th>\n";
530
531 for ($i = 1; $i < count($this->tableheaders); $i++) {
532 $html .= "<th class=\"header\">".$this->tableheaders[$i]."</th>\n";
533 }
534
535 $html .= "
536 </tr>
537 </thead>
538 <tbody>\n";
539
540 /// Print out the table data
541 for ($i = 0; $i < count($this->tabledata); $i++) {
542 $html .= "<tr>\n";
543 if (isset($this->tabledata[$i]['leader'])) {
544 $rowspan = $this->tabledata[$i]['leader']['rowspan'];
545 $class = $this->tabledata[$i]['leader']['class'];
546 $html .= "<td class='$class' rowspan='$rowspan'></td>\n";
547 }
548 for ($j = 0; $j < count($this->tablecolumns); $j++) {
549 $name = $this->tablecolumns[$j];
550 $class = (isset($this->tabledata[$i][$name]['class'])) ? $this->tabledata[$i][$name]['class'] : '';
551 $colspan = (isset($this->tabledata[$i][$name]['colspan'])) ? "colspan='".$this->tabledata[$i][$name]['colspan']."'" : '';
552 $content = (isset($this->tabledata[$i][$name]['content'])) ? $this->tabledata[$i][$name]['content'] : null;
553 if (isset($content)) {
554 $html .= "<td class='$class' $colspan>$content</td>\n";
555 }
556 }
557 $html .= "</tr>\n";
558 }
559
560 $html .= "</tbody></table>";
561
f7998fbc 562 if ($return) {
563 return $html;
564 } else {
565 echo $html;
566 }
567 }
568
569 /**
570 * Processes the data sent by the form (grades and feedbacks).
571 * @var array $data
572 * @return bool Success or Failure (array of errors).
573 */
653a8648 574 function process_data($data) {
5c75a0a3 575 }
653a8648 576 function process_action($target, $action) {
f7998fbc 577 }
a071dbb6 578
579 /**
580 * Builds the grade item averages.
581 *
582 */
583 function calculate_averages() {
584 global $USER, $DB;
585
586 if ($this->showaverage) {
587 // this settings are actually grader report settings (not user report)
588 // however we're using them as having two separate but identical settings the
589 // user would have to keep in sync would be annoying
590 $averagesdisplaytype = $this->get_pref('averagesdisplaytype');
591 $averagesdecimalpoints = $this->get_pref('averagesdecimalpoints');
592 $meanselection = $this->get_pref('meanselection');
593 $shownumberofgrades = $this->get_pref('shownumberofgrades');
594
595 $avghtml = '';
596 $avgcssclass = 'avg';
597
598 $straverage = get_string('overallaverage', 'grades');
599
600 $groupsql = $this->groupsql;
601 $groupwheresql = $this->groupwheresql;
602 //$groupwheresqlparams = ;
603
604 if ($shownumberofgrades) {
605 $straverage .= ' (' . get_string('submissions', 'grades') . ') ';
606 }
607
608 $totalcount = $this->get_numusers(false);
609
610 //limit to users with a gradeable role ie students
611 list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
612
613 //limit to users with an active enrolment
614 list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context);
615
616 $params = array_merge($this->groupwheresql_params, $gradebookrolesparams, $enrolledparams);
617 $params['courseid'] = $this->courseid;
618
619 // find sums of all grade items in course
620 $sql = "SELECT gg.itemid, SUM(gg.finalgrade) AS sum
621 FROM {grade_items} gi
656d17c2
AD
622 JOIN {grade_grades} gg ON gg.itemid = gi.id
623 JOIN {user} u ON u.id = gg.userid
624 JOIN ($enrolledsql) je ON je.id = gg.userid
625 JOIN (
626 SELECT DISTINCT ra.userid
627 FROM {role_assignments} ra
628 WHERE ra.roleid $gradebookrolessql
629 AND ra.contextid " . get_related_contexts_string($this->context) . "
630 ) rainner ON rainner.userid = u.id
a071dbb6 631 $groupsql
632 WHERE gi.courseid = :courseid
656d17c2
AD
633 AND u.deleted = 0
634 AND gg.finalgrade IS NOT NULL
635 AND gg.hidden = 0
636 $groupwheresql
a071dbb6 637 GROUP BY gg.itemid";
638
639 $sum_array = array();
cc65dc36
EL
640 $sums = $DB->get_recordset_sql($sql, $params);
641 foreach ($sums as $itemid => $csum) {
642 $sum_array[$itemid] = $csum->sum;
a071dbb6 643 }
cc65dc36 644 $sums->close();
a071dbb6 645
646 $columncount=0;
647
648 // Empty grades must be evaluated as grademin, NOT always 0
649 // This query returns a count of ungraded grades (NULL finalgrade OR no matching record in grade_grades table)
650 // No join condition when joining grade_items and user to get a grade item row for every user
651 // Then left join with grade_grades and look for rows with null final grade (which includes grade items with no grade_grade)
652 $sql = "SELECT gi.id, COUNT(u.id) AS count
653 FROM {grade_items} gi
d3e30347 654 JOIN {user} u ON u.deleted = 0
656d17c2
AD
655 JOIN ($enrolledsql) je ON je.id = u.id
656 JOIN (
657 SELECT DISTINCT ra.userid
658 FROM {role_assignments} ra
659 WHERE ra.roleid $gradebookrolessql
660 AND ra.contextid " . get_related_contexts_string($this->context) . "
661 ) rainner ON rainner.userid = u.id
a1e26b5e 662 LEFT JOIN {grade_grades} gg
d3e30347 663 ON (gg.itemid = gi.id AND gg.userid = u.id AND gg.finalgrade IS NOT NULL AND gg.hidden = 0)
a071dbb6 664 $groupsql
656d17c2 665 WHERE gi.courseid = :courseid
656d17c2
AD
666 AND gg.finalgrade IS NULL
667 $groupwheresql
668 GROUP BY gi.id";
a071dbb6 669
670 $ungraded_counts = $DB->get_records_sql($sql, $params);
671
672 foreach ($this->gtree->items as $itemid=>$unused) {
673 if (!empty($this->gtree->items[$itemid]->avg)) {
674 continue;
675 }
676 $item = $this->gtree->items[$itemid];
677
678 if ($item->needsupdate) {
679 $avghtml .= '<td class="cell c' . $columncount++.'"><span class="gradingerror">'.get_string('error').'</span></td>';
680 continue;
681 }
682
683 if (empty($sum_array[$item->id])) {
684 $sum_array[$item->id] = 0;
685 }
686
687 if (empty($ungraded_counts[$itemid])) {
688 $ungraded_count = 0;
689 } else {
690 $ungraded_count = $ungraded_counts[$itemid]->count;
691 }
692
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;
699 }
700
701 $decimalpoints = $item->get_decimals();
702
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;
706
707 } else if ($averagesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave the report and user preferences
708 $displaytype = $item->get_displaytype();
709
710 } else {
711 $displaytype = $averagesdisplaytype;
712 }
713
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();
717
718 } else {
719 $decimalpoints = $averagesdecimalpoints;
720 }
721
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);
728
729 $numberofgrades = '';
730 if ($shownumberofgrades) {
731 $numberofgrades = " ($mean_count)";
732 }
733
734 $this->gtree->items[$itemid]->avg = $gradehtml.$numberofgrades;
735 }
736 }
737 }
738 }
26ed0305 739}
740
741function grade_report_user_settings_definition(&$mform) {
742 global $CFG;
743
744 $options = array(-1 => get_string('default', 'grades'),
745 0 => get_string('hide'),
746 1 => get_string('show'));
747
cd52d909 748 if (empty($CFG->grade_report_user_showrank)) {
26ed0305 749 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
750 } else {
751 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
752 }
753
754 $mform->addElement('select', 'report_user_showrank', get_string('showrank', 'grades'), $options);
1cc3165e 755 $mform->addHelpButton('report_user_showrank', 'showrank', 'grades');
26ed0305 756
699da6b5 757 if (empty($CFG->grade_report_user_showpercentage)) {
aea45e7e 758 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
5528217e 759 } else {
760 $options[-1] = get_string('defaultprev', 'grades', $options[1]);
699da6b5 761 }
762
763 $mform->addElement('select', 'report_user_showpercentage', get_string('showpercentage', 'grades'), $options);
ff268dcb 764 $mform->addHelpButton('report_user_showpercentage', 'showpercentage', 'grades');
699da6b5 765
a071dbb6 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]);
770 }
771
772 $mform->addElement('select', 'report_user_showgrade', get_string('showgrade', 'grades'), $options);
773
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]);
778 }
779
780 $mform->addElement('select', 'report_user_showfeedback', get_string('showfeedback', 'grades'), $options);
781
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]);
786 }
787
788 $mform->addElement('select', 'report_user_showweight', get_string('showweight', 'grades'), $options);
789
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]);
794 }
795
796 $mform->addElement('select', 'report_user_showaverage', get_string('showaverage', 'grades'), $options);
797 $mform->addHelpButton('report_user_showaverage', 'showaverage', 'grades');
798
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]);
803 }
804
805 $mform->addElement('select', 'report_user_showlettergrade', get_string('showlettergrade', 'grades'), $options);
806
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]);
811 }
812
813 $mform->addElement('select', 'report_user_showrange', get_string('showrange', 'grades'), $options);
814
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];
818 }
819 $mform->addElement('select', 'report_user_rangedecimals', get_string('rangedecimals', 'grades'), $options);
820
26ed0305 821 $options = array(-1 => get_string('default', 'grades'),
d69ef28b 822 0 => get_string('shownohidden', 'grades'),
597f50e6 823 1 => get_string('showhiddenuntilonly', 'grades'),
d69ef28b 824 2 => get_string('showallhidden', 'grades'));
26ed0305 825
cd52d909 826 if (empty($CFG->grade_report_user_showhiddenitems)) {
26ed0305 827 $options[-1] = get_string('defaultprev', 'grades', $options[0]);
828 } else {
d69ef28b 829 $options[-1] = get_string('defaultprev', 'grades', $options[$CFG->grade_report_user_showhiddenitems]);
26ed0305 830 }
831
832 $mform->addElement('select', 'report_user_showhiddenitems', get_string('showhiddenitems', 'grades'), $options);
69e3e962 833 $mform->addHelpButton('report_user_showhiddenitems', 'showhiddenitems', 'grades');
61541a5a
AD
834
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') );
840
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]);
845 }
846
847 $mform->addElement('select', 'report_user_showtotalsifcontainhidden', get_string('hidetotalifhiddenitems', 'grades'), $options);
0459cc4d 848 $mform->addHelpButton('report_user_showtotalsifcontainhidden', 'hidetotalifhiddenitems', 'grades');
0a784551 849}
850
851function grade_report_user_profilereport($course, $user) {
91152a35 852 global $OUTPUT;
0a784551 853 if (!empty($course->showgrades)) {
854
855 $context = get_context_instance(CONTEXT_COURSE, $course->id);
856
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);
859
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);
f7998fbc 864
0a784551 865 // print the page
866 echo '<div class="grade-report-user">'; // css fix to share styles with real report page
b5e7b2bf 867 echo $OUTPUT->heading(get_string('pluginname', 'gradereport_user'). ' - '.fullname($report->user));
0a784551 868
869 if ($report->fill_table()) {
870 echo $report->print_table(true);
871 }
872 echo '</div>';
873 }
f7998fbc 874}
0a784551 875
6c3ef410 876