[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 /** 18 * Definition of the grade_user_report class is defined 19 * 20 * @package gradereport_user 21 * @copyright 2007 Nicolas Connault 22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 */ 24 25 require_once($CFG->dirroot . '/grade/report/lib.php'); 26 require_once($CFG->libdir.'/tablelib.php'); 27 28 //showhiddenitems values 29 define("GRADE_REPORT_USER_HIDE_HIDDEN", 0); 30 define("GRADE_REPORT_USER_HIDE_UNTIL", 1); 31 define("GRADE_REPORT_USER_SHOW_HIDDEN", 2); 32 33 /** 34 * Class providing an API for the user report building and displaying. 35 * @uses grade_report 36 * @package gradereport_user 37 */ 38 class grade_report_user extends grade_report { 39 40 /** 41 * The user. 42 * @var object $user 43 */ 44 public $user; 45 46 /** 47 * A flexitable to hold the data. 48 * @var object $table 49 */ 50 public $table; 51 52 /** 53 * An array of table headers 54 * @var array 55 */ 56 public $tableheaders = array(); 57 58 /** 59 * An array of table columns 60 * @var array 61 */ 62 public $tablecolumns = array(); 63 64 /** 65 * An array containing rows of data for the table. 66 * @var type 67 */ 68 public $tabledata = array(); 69 70 /** 71 * The grade tree structure 72 * @var grade_tree 73 */ 74 public $gtree; 75 76 /** 77 * Flat structure similar to grade tree 78 */ 79 public $gseq; 80 81 /** 82 * show student ranks 83 */ 84 public $showrank; 85 86 /** 87 * show grade percentages 88 */ 89 public $showpercentage; 90 91 /** 92 * Show range 93 */ 94 public $showrange = true; 95 96 /** 97 * Show grades in the report, default true 98 * @var bool 99 */ 100 public $showgrade = true; 101 102 /** 103 * Decimal points to use for values in the report, default 2 104 * @var int 105 */ 106 public $decimals = 2; 107 108 /** 109 * The number of decimal places to round range to, default 0 110 * @var int 111 */ 112 public $rangedecimals = 0; 113 114 /** 115 * Show grade feedback in the report, default true 116 * @var bool 117 */ 118 public $showfeedback = true; 119 120 /** 121 * Show grade weighting in the report, default true. 122 * @var bool 123 */ 124 public $showweight = true; 125 126 /** 127 * Show letter grades in the report, default false 128 * @var bool 129 */ 130 public $showlettergrade = false; 131 132 /** 133 * Show the calculated contribution to the course total column. 134 * @var bool 135 */ 136 public $showcontributiontocoursetotal = true; 137 138 /** 139 * Show average grades in the report, default false. 140 * @var false 141 */ 142 public $showaverage = false; 143 144 public $maxdepth; 145 public $evenodd; 146 147 public $canviewhidden; 148 149 public $switch; 150 151 /** 152 * Show hidden items even when user does not have required cap 153 */ 154 public $showhiddenitems; 155 public $showtotalsifcontainhidden; 156 157 public $baseurl; 158 public $pbarurl; 159 160 /** 161 * The modinfo object to be used. 162 * 163 * @var course_modinfo 164 */ 165 protected $modinfo = null; 166 167 /** 168 * View as user. 169 * 170 * When this is set to true, the visibility checks, and capability checks will be 171 * applied to the user whose grades are being displayed. This is very useful when 172 * a mentor/parent is viewing the report of their mentee because they need to have 173 * access to the same information, but not more, not less. 174 * 175 * @var boolean 176 */ 177 protected $viewasuser = false; 178 179 /** 180 * An array that collects the aggregationhints for every 181 * grade_item. The hints contain grade, grademin, grademax 182 * status, weight and parent. 183 * 184 * @var array 185 */ 186 protected $aggregationhints = array(); 187 188 /** 189 * Constructor. Sets local copies of user preferences and initialises grade_tree. 190 * @param int $courseid 191 * @param object $gpr grade plugin return tracking object 192 * @param string $context 193 * @param int $userid The id of the user 194 * @param bool $viewasuser Set this to true when the current user is a mentor/parent of the targetted user. 195 */ 196 public function __construct($courseid, $gpr, $context, $userid, $viewasuser = null) { 197 global $DB, $CFG; 198 parent::__construct($courseid, $gpr, $context); 199 200 $this->showrank = grade_get_setting($this->courseid, 'report_user_showrank', $CFG->grade_report_user_showrank); 201 $this->showpercentage = grade_get_setting($this->courseid, 'report_user_showpercentage', $CFG->grade_report_user_showpercentage); 202 $this->showhiddenitems = grade_get_setting($this->courseid, 'report_user_showhiddenitems', $CFG->grade_report_user_showhiddenitems); 203 $this->showtotalsifcontainhidden = array($this->courseid => grade_get_setting($this->courseid, 'report_user_showtotalsifcontainhidden', $CFG->grade_report_user_showtotalsifcontainhidden)); 204 205 $this->showgrade = grade_get_setting($this->courseid, 'report_user_showgrade', !empty($CFG->grade_report_user_showgrade)); 206 $this->showrange = grade_get_setting($this->courseid, 'report_user_showrange', !empty($CFG->grade_report_user_showrange)); 207 $this->showfeedback = grade_get_setting($this->courseid, 'report_user_showfeedback', !empty($CFG->grade_report_user_showfeedback)); 208 209 $this->showweight = grade_get_setting($this->courseid, 'report_user_showweight', 210 !empty($CFG->grade_report_user_showweight)); 211 212 $this->showcontributiontocoursetotal = grade_get_setting($this->courseid, 'report_user_showcontributiontocoursetotal', 213 !empty($CFG->grade_report_user_showcontributiontocoursetotal)); 214 215 $this->showlettergrade = grade_get_setting($this->courseid, 'report_user_showlettergrade', !empty($CFG->grade_report_user_showlettergrade)); 216 $this->showaverage = grade_get_setting($this->courseid, 'report_user_showaverage', !empty($CFG->grade_report_user_showaverage)); 217 218 $this->viewasuser = $viewasuser; 219 220 // The default grade decimals is 2 221 $defaultdecimals = 2; 222 if (property_exists($CFG, 'grade_decimalpoints')) { 223 $defaultdecimals = $CFG->grade_decimalpoints; 224 } 225 $this->decimals = grade_get_setting($this->courseid, 'decimalpoints', $defaultdecimals); 226 227 // The default range decimals is 0 228 $defaultrangedecimals = 0; 229 if (property_exists($CFG, 'grade_report_user_rangedecimals')) { 230 $defaultrangedecimals = $CFG->grade_report_user_rangedecimals; 231 } 232 $this->rangedecimals = grade_get_setting($this->courseid, 'report_user_rangedecimals', $defaultrangedecimals); 233 234 $this->switch = grade_get_setting($this->courseid, 'aggregationposition', $CFG->grade_aggregationposition); 235 236 // Grab the grade_tree for this course 237 $this->gtree = new grade_tree($this->courseid, false, $this->switch, null, !$CFG->enableoutcomes); 238 239 // Get the user (for full name). 240 $this->user = $DB->get_record('user', array('id' => $userid)); 241 242 // What user are we viewing this as? 243 $coursecontext = context_course::instance($this->courseid); 244 if ($viewasuser) { 245 $this->modinfo = new course_modinfo($this->course, $this->user->id); 246 $this->canviewhidden = has_capability('moodle/grade:viewhidden', $coursecontext, $this->user->id); 247 } else { 248 $this->modinfo = $this->gtree->modinfo; 249 $this->canviewhidden = has_capability('moodle/grade:viewhidden', $coursecontext); 250 } 251 252 // Determine the number of rows and indentation. 253 $this->maxdepth = 1; 254 $this->inject_rowspans($this->gtree->top_element); 255 $this->maxdepth++; // Need to account for the lead column that spans all children. 256 for ($i = 1; $i <= $this->maxdepth; $i++) { 257 $this->evenodd[$i] = 0; 258 } 259 260 $this->tabledata = array(); 261 262 // base url for sorting by first/last name 263 $this->baseurl = $CFG->wwwroot.'/grade/report?id='.$courseid.'&userid='.$userid; 264 $this->pbarurl = $this->baseurl; 265 266 // no groups on this report - rank is from all course users 267 $this->setup_table(); 268 269 //optionally calculate grade item averages 270 $this->calculate_averages(); 271 } 272 273 /** 274 * Recurses through a tree of elements setting the rowspan property on each element 275 * 276 * @param array $element Either the top element or, during recursion, the current element 277 * @return int The number of elements processed 278 */ 279 function inject_rowspans(&$element) { 280 281 if ($element['depth'] > $this->maxdepth) { 282 $this->maxdepth = $element['depth']; 283 } 284 if (empty($element['children'])) { 285 return 1; 286 } 287 $count = 1; 288 289 foreach ($element['children'] as $key=>$child) { 290 // If category is hidden then do not include it in the rowspan. 291 if ($child['type'] == 'category' && $child['object']->is_hidden() && !$this->canviewhidden 292 && ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN 293 || ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$child['object']->is_hiddenuntil()))) { 294 // Just calculate the rowspans for children of this category, don't add them to the count. 295 $this->inject_rowspans($element['children'][$key]); 296 } else { 297 $count += $this->inject_rowspans($element['children'][$key]); 298 } 299 } 300 301 $element['rowspan'] = $count; 302 return $count; 303 } 304 305 306 /** 307 * Prepares the headers and attributes of the flexitable. 308 */ 309 public function setup_table() { 310 /* 311 * Table has 1-8 columns 312 *| All columns except for itemname/description are optional 313 */ 314 315 // setting up table headers 316 317 $this->tablecolumns = array('itemname'); 318 $this->tableheaders = array($this->get_lang_string('gradeitem', 'grades')); 319 320 if ($this->showweight) { 321 $this->tablecolumns[] = 'weight'; 322 $this->tableheaders[] = $this->get_lang_string('weightuc', 'grades'); 323 } 324 325 if ($this->showgrade) { 326 $this->tablecolumns[] = 'grade'; 327 $this->tableheaders[] = $this->get_lang_string('grade', 'grades'); 328 } 329 330 if ($this->showrange) { 331 $this->tablecolumns[] = 'range'; 332 $this->tableheaders[] = $this->get_lang_string('range', 'grades'); 333 } 334 335 if ($this->showpercentage) { 336 $this->tablecolumns[] = 'percentage'; 337 $this->tableheaders[] = $this->get_lang_string('percentage', 'grades'); 338 } 339 340 if ($this->showlettergrade) { 341 $this->tablecolumns[] = 'lettergrade'; 342 $this->tableheaders[] = $this->get_lang_string('lettergrade', 'grades'); 343 } 344 345 if ($this->showrank) { 346 $this->tablecolumns[] = 'rank'; 347 $this->tableheaders[] = $this->get_lang_string('rank', 'grades'); 348 } 349 350 if ($this->showaverage) { 351 $this->tablecolumns[] = 'average'; 352 $this->tableheaders[] = $this->get_lang_string('average', 'grades'); 353 } 354 355 if ($this->showfeedback) { 356 $this->tablecolumns[] = 'feedback'; 357 $this->tableheaders[] = $this->get_lang_string('feedback', 'grades'); 358 } 359 360 if ($this->showcontributiontocoursetotal) { 361 $this->tablecolumns[] = 'contributiontocoursetotal'; 362 $this->tableheaders[] = $this->get_lang_string('contributiontocoursetotal', 'grades'); 363 } 364 } 365 366 function fill_table() { 367 //print "<pre>"; 368 //print_r($this->gtree->top_element); 369 $this->fill_table_recursive($this->gtree->top_element); 370 //print_r($this->tabledata); 371 //print "</pre>"; 372 return true; 373 } 374 375 /** 376 * Fill the table with data. 377 * 378 * @param $element - An array containing the table data for the current row. 379 */ 380 private function fill_table_recursive(&$element) { 381 global $DB, $CFG; 382 383 $type = $element['type']; 384 $depth = $element['depth']; 385 $grade_object = $element['object']; 386 $eid = $grade_object->id; 387 $element['userid'] = $this->user->id; 388 $fullname = $this->gtree->get_element_header($element, true, true, true, true, true); 389 $data = array(); 390 $hidden = ''; 391 $excluded = ''; 392 $itemlevel = ($type == 'categoryitem' || $type == 'category' || $type == 'courseitem') ? $depth : ($depth + 1); 393 $class = 'level' . $itemlevel . ' level' . ($itemlevel % 2 ? 'odd' : 'even'); 394 $classfeedback = ''; 395 396 // If this is a hidden grade category, hide it completely from the user 397 if ($type == 'category' && $grade_object->is_hidden() && !$this->canviewhidden && ( 398 $this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN || 399 ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_object->is_hiddenuntil()))) { 400 return false; 401 } 402 403 if ($type == 'category') { 404 $this->evenodd[$depth] = (($this->evenodd[$depth] + 1) % 2); 405 } 406 $alter = ($this->evenodd[$depth] == 0) ? 'even' : 'odd'; 407 408 /// Process those items that have scores associated 409 if ($type == 'item' or $type == 'categoryitem' or $type == 'courseitem') { 410 $header_row = "row_{$eid}_{$this->user->id}"; 411 $header_cat = "cat_{$grade_object->categoryid}_{$this->user->id}"; 412 413 if (! $grade_grade = grade_grade::fetch(array('itemid'=>$grade_object->id,'userid'=>$this->user->id))) { 414 $grade_grade = new grade_grade(); 415 $grade_grade->userid = $this->user->id; 416 $grade_grade->itemid = $grade_object->id; 417 } 418 419 $grade_grade->load_grade_item(); 420 421 /// Hidden Items 422 if ($grade_grade->grade_item->is_hidden()) { 423 $hidden = ' dimmed_text'; 424 } 425 426 $hide = false; 427 // If this is a hidden grade item, hide it completely from the user. 428 if ($grade_grade->is_hidden() && !$this->canviewhidden && ( 429 $this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN || 430 ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_grade->is_hiddenuntil()))) { 431 $hide = true; 432 } else if (!empty($grade_object->itemmodule) && !empty($grade_object->iteminstance)) { 433 // The grade object can be marked visible but still be hidden if 434 // the student cannot see the activity due to conditional access 435 // and it's set to be hidden entirely. 436 $instances = $this->modinfo->get_instances_of($grade_object->itemmodule); 437 if (!empty($instances[$grade_object->iteminstance])) { 438 $cm = $instances[$grade_object->iteminstance]; 439 if (!$cm->uservisible) { 440 // If there is 'availableinfo' text then it is only greyed 441 // out and not entirely hidden. 442 if (!$cm->availableinfo) { 443 $hide = true; 444 } 445 } 446 } 447 } 448 449 // Actual Grade - We need to calculate this whether the row is hidden or not. 450 $gradeval = $grade_grade->finalgrade; 451 $hint = $grade_grade->get_aggregation_hint(); 452 if (!$this->canviewhidden) { 453 /// Virtual Grade (may be calculated excluding hidden items etc). 454 $adjustedgrade = $this->blank_hidden_total_and_adjust_bounds($this->courseid, 455 $grade_grade->grade_item, 456 $gradeval); 457 458 $gradeval = $adjustedgrade['grade']; 459 460 // We temporarily adjust the view of this grade item - because the min and 461 // max are affected by the hidden values in the aggregation. 462 $grade_grade->grade_item->grademax = $adjustedgrade['grademax']; 463 $grade_grade->grade_item->grademin = $adjustedgrade['grademin']; 464 $hint['status'] = $adjustedgrade['aggregationstatus']; 465 $hint['weight'] = $adjustedgrade['aggregationweight']; 466 } else { 467 // The max and min for an aggregation may be different to the grade_item. 468 if (!is_null($gradeval)) { 469 $grade_grade->grade_item->grademax = $grade_grade->get_grade_max(); 470 $grade_grade->grade_item->grademin = $grade_grade->get_grade_min(); 471 } 472 } 473 474 475 if (!$hide) { 476 /// Excluded Item 477 /** 478 if ($grade_grade->is_excluded()) { 479 $fullname .= ' ['.get_string('excluded', 'grades').']'; 480 $excluded = ' excluded'; 481 } 482 **/ 483 484 /// Other class information 485 $class .= $hidden . $excluded; 486 if ($this->switch) { // alter style based on whether aggregation is first or last 487 $class .= ($type == 'categoryitem' or $type == 'courseitem') ? " ".$alter."d$depth baggt b2b" : " item b1b"; 488 } else { 489 $class .= ($type == 'categoryitem' or $type == 'courseitem') ? " ".$alter."d$depth baggb" : " item b1b"; 490 } 491 if ($type == 'categoryitem' or $type == 'courseitem') { 492 $header_cat = "cat_{$grade_object->iteminstance}_{$this->user->id}"; 493 } 494 495 /// Name 496 $data['itemname']['content'] = $fullname; 497 $data['itemname']['class'] = $class; 498 $data['itemname']['colspan'] = ($this->maxdepth - $depth); 499 $data['itemname']['celltype'] = 'th'; 500 $data['itemname']['id'] = $header_row; 501 502 if ($this->showfeedback) { 503 // Copy $class before appending itemcenter as feedback should not be centered 504 $classfeedback = $class; 505 } 506 $class .= " itemcenter "; 507 if ($this->showweight) { 508 $data['weight']['class'] = $class; 509 $data['weight']['content'] = '-'; 510 $data['weight']['headers'] = "$header_cat $header_row weight"; 511 // has a weight assigned, might be extra credit 512 513 // This obliterates the weight because it provides a more informative description. 514 if (is_numeric($hint['weight'])) { 515 $data['weight']['content'] = format_float($hint['weight'] * 100.0, 2) . ' %'; 516 } 517 if ($hint['status'] != 'used' && $hint['status'] != 'unknown') { 518 $data['weight']['content'] .= '<br>' . get_string('aggregationhint' . $hint['status'], 'grades'); 519 } 520 } 521 522 if ($this->showgrade) { 523 if ($grade_grade->grade_item->needsupdate) { 524 $data['grade']['class'] = $class.' gradingerror'; 525 $data['grade']['content'] = get_string('error'); 526 } else if (!empty($CFG->grade_hiddenasdate) and $grade_grade->get_datesubmitted() and !$this->canviewhidden and $grade_grade->is_hidden() 527 and !$grade_grade->grade_item->is_category_item() and !$grade_grade->grade_item->is_course_item()) { 528 // 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 529 $class .= ' datesubmitted'; 530 $data['grade']['class'] = $class; 531 $data['grade']['content'] = get_string('submittedon', 'grades', userdate($grade_grade->get_datesubmitted(), get_string('strftimedatetimeshort'))); 532 533 } else if ($grade_grade->is_hidden()) { 534 $data['grade']['class'] = $class.' dimmed_text'; 535 $data['grade']['content'] = '-'; 536 if ($this->canviewhidden) { 537 $data['grade']['content'] = grade_format_gradevalue($gradeval, 538 $grade_grade->grade_item, 539 true); 540 } 541 } else { 542 $data['grade']['class'] = $class; 543 $data['grade']['content'] = grade_format_gradevalue($gradeval, 544 $grade_grade->grade_item, 545 true); 546 } 547 $data['grade']['headers'] = "$header_cat $header_row grade"; 548 } 549 550 // Range 551 if ($this->showrange) { 552 $data['range']['class'] = $class; 553 $data['range']['content'] = $grade_grade->grade_item->get_formatted_range(GRADE_DISPLAY_TYPE_REAL, $this->rangedecimals); 554 $data['range']['headers'] = "$header_cat $header_row range"; 555 } 556 557 // Percentage 558 if ($this->showpercentage) { 559 if ($grade_grade->grade_item->needsupdate) { 560 $data['percentage']['class'] = $class.' gradingerror'; 561 $data['percentage']['content'] = get_string('error'); 562 } else if ($grade_grade->is_hidden()) { 563 $data['percentage']['class'] = $class.' dimmed_text'; 564 $data['percentage']['content'] = '-'; 565 if ($this->canviewhidden) { 566 $data['percentage']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE); 567 } 568 } else { 569 $data['percentage']['class'] = $class; 570 $data['percentage']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE); 571 } 572 $data['percentage']['headers'] = "$header_cat $header_row percentage"; 573 } 574 575 // Lettergrade 576 if ($this->showlettergrade) { 577 if ($grade_grade->grade_item->needsupdate) { 578 $data['lettergrade']['class'] = $class.' gradingerror'; 579 $data['lettergrade']['content'] = get_string('error'); 580 } else if ($grade_grade->is_hidden()) { 581 $data['lettergrade']['class'] = $class.' dimmed_text'; 582 if (!$this->canviewhidden) { 583 $data['lettergrade']['content'] = '-'; 584 } else { 585 $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER); 586 } 587 } else { 588 $data['lettergrade']['class'] = $class; 589 $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER); 590 } 591 $data['lettergrade']['headers'] = "$header_cat $header_row lettergrade"; 592 } 593 594 // Rank 595 if ($this->showrank) { 596 if ($grade_grade->grade_item->needsupdate) { 597 $data['rank']['class'] = $class.' gradingerror'; 598 $data['rank']['content'] = get_string('error'); 599 } elseif ($grade_grade->is_hidden()) { 600 $data['rank']['class'] = $class.' dimmed_text'; 601 $data['rank']['content'] = '-'; 602 } else if (is_null($gradeval)) { 603 // no grade, no rank 604 $data['rank']['class'] = $class; 605 $data['rank']['content'] = '-'; 606 607 } else { 608 /// find the number of users with a higher grade 609 $sql = "SELECT COUNT(DISTINCT(userid)) 610 FROM {grade_grades} 611 WHERE finalgrade > ? 612 AND itemid = ? 613 AND hidden = 0"; 614 $rank = $DB->count_records_sql($sql, array($grade_grade->finalgrade, $grade_grade->grade_item->id)) + 1; 615 616 $data['rank']['class'] = $class; 617 $data['rank']['content'] = "$rank/".$this->get_numusers(false); // total course users 618 } 619 $data['rank']['headers'] = "$header_cat $header_row rank"; 620 } 621 622 // Average 623 if ($this->showaverage) { 624 $data['average']['class'] = $class; 625 if (!empty($this->gtree->items[$eid]->avg)) { 626 $data['average']['content'] = $this->gtree->items[$eid]->avg; 627 } else { 628 $data['average']['content'] = '-'; 629 } 630 $data['average']['headers'] = "$header_cat $header_row average"; 631 } 632 633 // Feedback 634 if ($this->showfeedback) { 635 if ($grade_grade->overridden > 0 AND ($type == 'categoryitem' OR $type == 'courseitem')) { 636 $data['feedback']['class'] = $classfeedback.' feedbacktext'; 637 $data['feedback']['content'] = get_string('overridden', 'grades').': ' . format_text($grade_grade->feedback, $grade_grade->feedbackformat); 638 } else if (empty($grade_grade->feedback) or (!$this->canviewhidden and $grade_grade->is_hidden())) { 639 $data['feedback']['class'] = $classfeedback.' feedbacktext'; 640 $data['feedback']['content'] = ' '; 641 } else { 642 $data['feedback']['class'] = $classfeedback.' feedbacktext'; 643 $data['feedback']['content'] = format_text($grade_grade->feedback, $grade_grade->feedbackformat); 644 } 645 $data['feedback']['headers'] = "$header_cat $header_row feedback"; 646 } 647 // Contribution to the course total column. 648 if ($this->showcontributiontocoursetotal) { 649 $data['contributiontocoursetotal']['class'] = $class; 650 $data['contributiontocoursetotal']['content'] = '-'; 651 $data['contributiontocoursetotal']['headers'] = "$header_cat $header_row contributiontocoursetotal"; 652 653 } 654 } 655 // We collect the aggregation hints whether they are hidden or not. 656 if ($this->showcontributiontocoursetotal) { 657 $hint['grademax'] = $grade_grade->grade_item->grademax; 658 $hint['grademin'] = $grade_grade->grade_item->grademin; 659 $hint['grade'] = $gradeval; 660 $parent = $grade_object->load_parent_category(); 661 if ($grade_object->is_category_item()) { 662 $parent = $parent->load_parent_category(); 663 } 664 $hint['parent'] = $parent->load_grade_item()->id; 665 $this->aggregationhints[$grade_grade->itemid] = $hint; 666 } 667 } 668 669 /// Category 670 if ($type == 'category') { 671 $data['leader']['class'] = $class.' '.$alter."d$depth b1t b2b b1l"; 672 $data['leader']['rowspan'] = $element['rowspan']; 673 674 if ($this->switch) { // alter style based on whether aggregation is first or last 675 $data['itemname']['class'] = $class.' '.$alter."d$depth b1b b1t"; 676 } else { 677 $data['itemname']['class'] = $class.' '.$alter."d$depth b2t"; 678 } 679 $data['itemname']['colspan'] = ($this->maxdepth - $depth + count($this->tablecolumns) - 1); 680 $data['itemname']['content'] = $fullname; 681 $data['itemname']['celltype'] = 'th'; 682 $data['itemname']['id'] = "cat_{$grade_object->id}_{$this->user->id}"; 683 } 684 685 /// Add this row to the overall system 686 foreach ($data as $key => $celldata) { 687 $data[$key]['class'] .= ' column-' . $key; 688 } 689 $this->tabledata[] = $data; 690 691 /// Recursively iterate through all child elements 692 if (isset($element['children'])) { 693 foreach ($element['children'] as $key=>$child) { 694 $this->fill_table_recursive($element['children'][$key]); 695 } 696 } 697 698 // Check we are showing this column, and we are looking at the root of the table. 699 // This should be the very last thing this fill_table_recursive function does. 700 if ($this->showcontributiontocoursetotal && ($type == 'category' && $depth == 1)) { 701 // We should have collected all the hints by now - walk the tree again and build the contributions column. 702 703 $this->fill_contributions_column($element); 704 } 705 } 706 707 /** 708 * This function is called after the table has been built and the aggregationhints 709 * have been collected. We need this info to walk up the list of parents of each 710 * grade_item. 711 * 712 * @param $element - An array containing the table data for the current row. 713 */ 714 public function fill_contributions_column($element) { 715 716 // Recursively iterate through all child elements. 717 if (isset($element['children'])) { 718 foreach ($element['children'] as $key=>$child) { 719 $this->fill_contributions_column($element['children'][$key]); 720 } 721 } else if ($element['type'] == 'item') { 722 // This is a grade item (We don't do this for categories or we would double count). 723 $grade_object = $element['object']; 724 $itemid = $grade_object->id; 725 726 // Ignore anything with no hint - e.g. a hidden row. 727 if (isset($this->aggregationhints[$itemid])) { 728 729 // Normalise the gradeval. 730 $gradecat = $grade_object->load_parent_category(); 731 if ($gradecat->aggregation == GRADE_AGGREGATE_SUM) { 732 // Natural aggregation/Sum of grades does not consider the mingrade, cannot traditionnally normalise it. 733 $graderange = $this->aggregationhints[$itemid]['grademax']; 734 735 if ($graderange != 0) { 736 $gradeval = $this->aggregationhints[$itemid]['grade'] / $graderange; 737 } else { 738 $gradeval = 0; 739 } 740 } else { 741 $gradeval = grade_grade::standardise_score($this->aggregationhints[$itemid]['grade'], 742 $this->aggregationhints[$itemid]['grademin'], $this->aggregationhints[$itemid]['grademax'], 0, 1); 743 } 744 745 // Multiply the normalised value by the weight 746 // of all the categories higher in the tree. 747 $parent = null; 748 do { 749 if (!is_null($this->aggregationhints[$itemid]['weight'])) { 750 $gradeval *= $this->aggregationhints[$itemid]['weight']; 751 } else if (empty($parent)) { 752 // If we are in the first loop, and the weight is null, then we cannot calculate the contribution. 753 $gradeval = null; 754 break; 755 } 756 757 // The second part of this if is to prevent infinite loops 758 // in case of crazy data. 759 if (isset($this->aggregationhints[$itemid]['parent']) && 760 $this->aggregationhints[$itemid]['parent'] != $itemid) { 761 $parent = $this->aggregationhints[$itemid]['parent']; 762 $itemid = $parent; 763 } else { 764 // We are at the top of the tree. 765 $parent = false; 766 } 767 } while ($parent); 768 769 // Finally multiply by the course grademax. 770 if (!is_null($gradeval)) { 771 // Convert to percent. 772 $gradeval *= 100; 773 } 774 775 // Now we need to loop through the "built" table data and update the 776 // contributions column for the current row. 777 $header_row = "row_{$grade_object->id}_{$this->user->id}"; 778 foreach ($this->tabledata as $key => $row) { 779 if (isset($row['itemname']) && ($row['itemname']['id'] == $header_row)) { 780 // Found it - update the column. 781 $content = '-'; 782 if (!is_null($gradeval)) { 783 $decimals = $grade_object->get_decimals(); 784 $content = format_float($gradeval, $decimals, true) . ' %'; 785 } 786 $this->tabledata[$key]['contributiontocoursetotal']['content'] = $content; 787 break; 788 } 789 } 790 } 791 } 792 } 793 794 /** 795 * Prints or returns the HTML from the flexitable. 796 * @param bool $return Whether or not to return the data instead of printing it directly. 797 * @return string 798 */ 799 public function print_table($return=false) { 800 $maxspan = $this->maxdepth; 801 802 /// Build table structure 803 $html = " 804 <table cellspacing='0' 805 cellpadding='0' 806 summary='" . s($this->get_lang_string('tablesummary', 'gradereport_user')) . "' 807 class='boxaligncenter generaltable user-grade'> 808 <thead> 809 <tr> 810 <th id='".$this->tablecolumns[0]."' class=\"header column-{$this->tablecolumns[0]}\" colspan='$maxspan'>".$this->tableheaders[0]."</th>\n"; 811 812 for ($i = 1; $i < count($this->tableheaders); $i++) { 813 $html .= "<th id='".$this->tablecolumns[$i]."' class=\"header column-{$this->tablecolumns[$i]}\">".$this->tableheaders[$i]."</th>\n"; 814 } 815 816 $html .= " 817 </tr> 818 </thead> 819 <tbody>\n"; 820 821 /// Print out the table data 822 for ($i = 0; $i < count($this->tabledata); $i++) { 823 $html .= "<tr>\n"; 824 if (isset($this->tabledata[$i]['leader'])) { 825 $rowspan = $this->tabledata[$i]['leader']['rowspan']; 826 $class = $this->tabledata[$i]['leader']['class']; 827 $html .= "<td class='$class' rowspan='$rowspan'></td>\n"; 828 } 829 for ($j = 0; $j < count($this->tablecolumns); $j++) { 830 $name = $this->tablecolumns[$j]; 831 $class = (isset($this->tabledata[$i][$name]['class'])) ? $this->tabledata[$i][$name]['class'] : ''; 832 $colspan = (isset($this->tabledata[$i][$name]['colspan'])) ? "colspan='".$this->tabledata[$i][$name]['colspan']."'" : ''; 833 $content = (isset($this->tabledata[$i][$name]['content'])) ? $this->tabledata[$i][$name]['content'] : null; 834 $celltype = (isset($this->tabledata[$i][$name]['celltype'])) ? $this->tabledata[$i][$name]['celltype'] : 'td'; 835 $id = (isset($this->tabledata[$i][$name]['id'])) ? "id='{$this->tabledata[$i][$name]['id']}'" : ''; 836 $headers = (isset($this->tabledata[$i][$name]['headers'])) ? "headers='{$this->tabledata[$i][$name]['headers']}'" : ''; 837 if (isset($content)) { 838 $html .= "<$celltype $id $headers class='$class' $colspan>$content</$celltype>\n"; 839 } 840 } 841 $html .= "</tr>\n"; 842 } 843 844 $html .= "</tbody></table>"; 845 846 if ($return) { 847 return $html; 848 } else { 849 echo $html; 850 } 851 } 852 853 /** 854 * Processes the data sent by the form (grades and feedbacks). 855 * @var array $data 856 * @return bool Success or Failure (array of errors). 857 */ 858 function process_data($data) { 859 } 860 function process_action($target, $action) { 861 } 862 863 /** 864 * Builds the grade item averages. 865 */ 866 function calculate_averages() { 867 global $USER, $DB, $CFG; 868 869 if ($this->showaverage) { 870 // This settings are actually grader report settings (not user report) 871 // however we're using them as having two separate but identical settings the 872 // user would have to keep in sync would be annoying. 873 $averagesdisplaytype = $this->get_pref('averagesdisplaytype'); 874 $averagesdecimalpoints = $this->get_pref('averagesdecimalpoints'); 875 $meanselection = $this->get_pref('meanselection'); 876 $shownumberofgrades = $this->get_pref('shownumberofgrades'); 877 878 $avghtml = ''; 879 $groupsql = $this->groupsql; 880 $groupwheresql = $this->groupwheresql; 881 $totalcount = $this->get_numusers(false); 882 883 // We want to query both the current context and parent contexts. 884 list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($this->context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relatedctx'); 885 886 // Limit to users with a gradeable role ie students. 887 list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0'); 888 889 // Limit to users with an active enrolment. 890 $coursecontext = $this->context->get_course_context(true); 891 $defaultgradeshowactiveenrol = !empty($CFG->grade_report_showonlyactiveenrol); 892 $showonlyactiveenrol = get_user_preferences('grade_report_showonlyactiveenrol', $defaultgradeshowactiveenrol); 893 $showonlyactiveenrol = $showonlyactiveenrol || !has_capability('moodle/course:viewsuspendedusers', $coursecontext); 894 list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context, '', 0, $showonlyactiveenrol); 895 896 $params = array_merge($this->groupwheresql_params, $gradebookrolesparams, $enrolledparams, $relatedctxparams); 897 $params['courseid'] = $this->courseid; 898 899 // find sums of all grade items in course 900 $sql = "SELECT gg.itemid, SUM(gg.finalgrade) AS sum 901 FROM {grade_items} gi 902 JOIN {grade_grades} gg ON gg.itemid = gi.id 903 JOIN {user} u ON u.id = gg.userid 904 JOIN ($enrolledsql) je ON je.id = gg.userid 905 JOIN ( 906 SELECT DISTINCT ra.userid 907 FROM {role_assignments} ra 908 WHERE ra.roleid $gradebookrolessql 909 AND ra.contextid $relatedctxsql 910 ) rainner ON rainner.userid = u.id 911 $groupsql 912 WHERE gi.courseid = :courseid 913 AND u.deleted = 0 914 AND gg.finalgrade IS NOT NULL 915 AND gg.hidden = 0 916 $groupwheresql 917 GROUP BY gg.itemid"; 918 919 $sum_array = array(); 920 $sums = $DB->get_recordset_sql($sql, $params); 921 foreach ($sums as $itemid => $csum) { 922 $sum_array[$itemid] = $csum->sum; 923 } 924 $sums->close(); 925 926 $columncount=0; 927 928 // Empty grades must be evaluated as grademin, NOT always 0 929 // This query returns a count of ungraded grades (NULL finalgrade OR no matching record in grade_grades table) 930 // No join condition when joining grade_items and user to get a grade item row for every user 931 // Then left join with grade_grades and look for rows with null final grade (which includes grade items with no grade_grade) 932 $sql = "SELECT gi.id, COUNT(u.id) AS count 933 FROM {grade_items} gi 934 JOIN {user} u ON u.deleted = 0 935 JOIN ($enrolledsql) je ON je.id = u.id 936 JOIN ( 937 SELECT DISTINCT ra.userid 938 FROM {role_assignments} ra 939 WHERE ra.roleid $gradebookrolessql 940 AND ra.contextid $relatedctxsql 941 ) rainner ON rainner.userid = u.id 942 LEFT JOIN {grade_grades} gg 943 ON (gg.itemid = gi.id AND gg.userid = u.id AND gg.finalgrade IS NOT NULL AND gg.hidden = 0) 944 $groupsql 945 WHERE gi.courseid = :courseid 946 AND gg.finalgrade IS NULL 947 $groupwheresql 948 GROUP BY gi.id"; 949 950 $ungraded_counts = $DB->get_records_sql($sql, $params); 951 952 foreach ($this->gtree->items as $itemid=>$unused) { 953 if (!empty($this->gtree->items[$itemid]->avg)) { 954 continue; 955 } 956 $item = $this->gtree->items[$itemid]; 957 958 if ($item->needsupdate) { 959 $avghtml .= '<td class="cell c' . $columncount++.'"><span class="gradingerror">'.get_string('error').'</span></td>'; 960 continue; 961 } 962 963 if (empty($sum_array[$item->id])) { 964 $sum_array[$item->id] = 0; 965 } 966 967 if (empty($ungraded_counts[$itemid])) { 968 $ungraded_count = 0; 969 } else { 970 $ungraded_count = $ungraded_counts[$itemid]->count; 971 } 972 973 //do they want the averages to include all grade items 974 if ($meanselection == GRADE_REPORT_MEAN_GRADED) { 975 $mean_count = $totalcount - $ungraded_count; 976 } else { // Bump up the sum by the number of ungraded items * grademin 977 $sum_array[$item->id] += ($ungraded_count * $item->grademin); 978 $mean_count = $totalcount; 979 } 980 981 // Determine which display type to use for this average 982 if (!empty($USER->gradeediting) && $USER->gradeediting[$this->courseid]) { 983 $displaytype = GRADE_DISPLAY_TYPE_REAL; 984 985 } else if ($averagesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave the report and user preferences 986 $displaytype = $item->get_displaytype(); 987 988 } else { 989 $displaytype = $averagesdisplaytype; 990 } 991 992 // Override grade_item setting if a display preference (not inherit) was set for the averages 993 if ($averagesdecimalpoints == GRADE_REPORT_PREFERENCE_INHERIT) { 994 $decimalpoints = $item->get_decimals(); 995 } else { 996 $decimalpoints = $averagesdecimalpoints; 997 } 998 999 if (empty($sum_array[$item->id]) || $mean_count == 0) { 1000 $this->gtree->items[$itemid]->avg = '-'; 1001 } else { 1002 $sum = $sum_array[$item->id]; 1003 $avgradeval = $sum/$mean_count; 1004 $gradehtml = grade_format_gradevalue($avgradeval, $item, true, $displaytype, $decimalpoints); 1005 1006 $numberofgrades = ''; 1007 if ($shownumberofgrades) { 1008 $numberofgrades = " ($mean_count)"; 1009 } 1010 1011 $this->gtree->items[$itemid]->avg = $gradehtml.$numberofgrades; 1012 } 1013 } 1014 } 1015 } 1016 1017 /** 1018 * Trigger the grade_report_viewed event 1019 * 1020 * @since Moodle 2.9 1021 */ 1022 public function viewed() { 1023 $event = \gradereport_user\event\grade_report_viewed::create( 1024 array( 1025 'context' => $this->context, 1026 'courseid' => $this->courseid, 1027 'relateduserid' => $this->user->id, 1028 ) 1029 ); 1030 $event->trigger(); 1031 } 1032 } 1033 1034 function grade_report_user_settings_definition(&$mform) { 1035 global $CFG; 1036 1037 $options = array(-1 => get_string('default', 'grades'), 1038 0 => get_string('hide'), 1039 1 => get_string('show')); 1040 1041 if (empty($CFG->grade_report_user_showrank)) { 1042 $options[-1] = get_string('defaultprev', 'grades', $options[0]); 1043 } else { 1044 $options[-1] = get_string('defaultprev', 'grades', $options[1]); 1045 } 1046 1047 $mform->addElement('select', 'report_user_showrank', get_string('showrank', 'grades'), $options); 1048 $mform->addHelpButton('report_user_showrank', 'showrank', 'grades'); 1049 1050 if (empty($CFG->grade_report_user_showpercentage)) { 1051 $options[-1] = get_string('defaultprev', 'grades', $options[0]); 1052 } else { 1053 $options[-1] = get_string('defaultprev', 'grades', $options[1]); 1054 } 1055 1056 $mform->addElement('select', 'report_user_showpercentage', get_string('showpercentage', 'grades'), $options); 1057 $mform->addHelpButton('report_user_showpercentage', 'showpercentage', 'grades'); 1058 1059 if (empty($CFG->grade_report_user_showgrade)) { 1060 $options[-1] = get_string('defaultprev', 'grades', $options[0]); 1061 } else { 1062 $options[-1] = get_string('defaultprev', 'grades', $options[1]); 1063 } 1064 1065 $mform->addElement('select', 'report_user_showgrade', get_string('showgrade', 'grades'), $options); 1066 1067 if (empty($CFG->grade_report_user_showfeedback)) { 1068 $options[-1] = get_string('defaultprev', 'grades', $options[0]); 1069 } else { 1070 $options[-1] = get_string('defaultprev', 'grades', $options[1]); 1071 } 1072 1073 $mform->addElement('select', 'report_user_showfeedback', get_string('showfeedback', 'grades'), $options); 1074 1075 if (empty($CFG->grade_report_user_showweight)) { 1076 $options[-1] = get_string('defaultprev', 'grades', $options[0]); 1077 } else { 1078 $options[-1] = get_string('defaultprev', 'grades', $options[1]); 1079 } 1080 1081 $mform->addElement('select', 'report_user_showweight', get_string('showweight', 'grades'), $options); 1082 1083 if (empty($CFG->grade_report_user_showaverage)) { 1084 $options[-1] = get_string('defaultprev', 'grades', $options[0]); 1085 } else { 1086 $options[-1] = get_string('defaultprev', 'grades', $options[1]); 1087 } 1088 1089 $mform->addElement('select', 'report_user_showaverage', get_string('showaverage', 'grades'), $options); 1090 $mform->addHelpButton('report_user_showaverage', 'showaverage', 'grades'); 1091 1092 if (empty($CFG->grade_report_user_showlettergrade)) { 1093 $options[-1] = get_string('defaultprev', 'grades', $options[0]); 1094 } else { 1095 $options[-1] = get_string('defaultprev', 'grades', $options[1]); 1096 } 1097 1098 $mform->addElement('select', 'report_user_showlettergrade', get_string('showlettergrade', 'grades'), $options); 1099 if (empty($CFG->grade_report_user_showcontributiontocoursetotal)) { 1100 $options[-1] = get_string('defaultprev', 'grades', $options[0]); 1101 } else { 1102 $options[-1] = get_string('defaultprev', 'grades', $options[$CFG->grade_report_user_showcontributiontocoursetotal]); 1103 } 1104 1105 $mform->addElement('select', 'report_user_showcontributiontocoursetotal', get_string('showcontributiontocoursetotal', 'grades'), $options); 1106 $mform->addHelpButton('report_user_showcontributiontocoursetotal', 'showcontributiontocoursetotal', 'grades'); 1107 1108 if (empty($CFG->grade_report_user_showrange)) { 1109 $options[-1] = get_string('defaultprev', 'grades', $options[0]); 1110 } else { 1111 $options[-1] = get_string('defaultprev', 'grades', $options[1]); 1112 } 1113 1114 $mform->addElement('select', 'report_user_showrange', get_string('showrange', 'grades'), $options); 1115 1116 $options = array(0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5); 1117 if (! empty($CFG->grade_report_user_rangedecimals)) { 1118 $options[-1] = $options[$CFG->grade_report_user_rangedecimals]; 1119 } 1120 $mform->addElement('select', 'report_user_rangedecimals', get_string('rangedecimals', 'grades'), $options); 1121 1122 $options = array(-1 => get_string('default', 'grades'), 1123 0 => get_string('shownohidden', 'grades'), 1124 1 => get_string('showhiddenuntilonly', 'grades'), 1125 2 => get_string('showallhidden', 'grades')); 1126 1127 if (empty($CFG->grade_report_user_showhiddenitems)) { 1128 $options[-1] = get_string('defaultprev', 'grades', $options[0]); 1129 } else { 1130 $options[-1] = get_string('defaultprev', 'grades', $options[$CFG->grade_report_user_showhiddenitems]); 1131 } 1132 1133 $mform->addElement('select', 'report_user_showhiddenitems', get_string('showhiddenitems', 'grades'), $options); 1134 $mform->addHelpButton('report_user_showhiddenitems', 'showhiddenitems', 'grades'); 1135 1136 //showtotalsifcontainhidden 1137 $options = array(-1 => get_string('default', 'grades'), 1138 GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN => get_string('hide'), 1139 GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN => get_string('hidetotalshowexhiddenitems', 'grades'), 1140 GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN => get_string('hidetotalshowinchiddenitems', 'grades') ); 1141 1142 if (empty($CFG->grade_report_user_showtotalsifcontainhidden)) { 1143 $options[-1] = get_string('defaultprev', 'grades', $options[0]); 1144 } else { 1145 $options[-1] = get_string('defaultprev', 'grades', $options[$CFG->grade_report_user_showtotalsifcontainhidden]); 1146 } 1147 1148 $mform->addElement('select', 'report_user_showtotalsifcontainhidden', get_string('hidetotalifhiddenitems', 'grades'), $options); 1149 $mform->addHelpButton('report_user_showtotalsifcontainhidden', 'hidetotalifhiddenitems', 'grades'); 1150 1151 } 1152 1153 /** 1154 * Profile report callback. 1155 * 1156 * @param object $course The course. 1157 * @param object $user The user. 1158 * @param boolean $viewasuser True when we are viewing this as the targetted user sees it. 1159 */ 1160 function grade_report_user_profilereport($course, $user, $viewasuser = false) { 1161 global $OUTPUT; 1162 if (!empty($course->showgrades)) { 1163 1164 $context = context_course::instance($course->id); 1165 1166 /// return tracking object 1167 $gpr = new grade_plugin_return(array('type'=>'report', 'plugin'=>'user', 'courseid'=>$course->id, 'userid'=>$user->id)); 1168 // Create a report instance 1169 $report = new grade_report_user($course->id, $gpr, $context, $user->id, $viewasuser); 1170 1171 // print the page 1172 echo '<div class="grade-report-user">'; // css fix to share styles with real report page 1173 if ($report->fill_table()) { 1174 echo $report->print_table(true); 1175 } 1176 echo '</div>'; 1177 } 1178 } 1179 1180 /** 1181 * Add nodes to myprofile page. 1182 * 1183 * @param \core_user\output\myprofile\tree $tree Tree object 1184 * @param stdClass $user user object 1185 * @param bool $iscurrentuser 1186 * @param stdClass $course Course object 1187 */ 1188 function gradereport_user_myprofile_navigation(core_user\output\myprofile\tree $tree, $user, $iscurrentuser, $course) { 1189 global $CFG, $USER; 1190 if (empty($course)) { 1191 // We want to display these reports under the site context. 1192 $course = get_fast_modinfo(SITEID)->get_course(); 1193 } 1194 $usercontext = context_user::instance($user->id); 1195 $anyreport = has_capability('moodle/user:viewuseractivitiesreport', $usercontext); 1196 1197 // Start capability checks. 1198 if ($anyreport || ($course->showreports && $user->id == $USER->id)) { 1199 // Add grade hardcoded grade report if necessary. 1200 $gradeaccess = false; 1201 $coursecontext = context_course::instance($course->id); 1202 if (has_capability('moodle/grade:viewall', $coursecontext)) { 1203 // Can view all course grades. 1204 $gradeaccess = true; 1205 } else if ($course->showgrades) { 1206 if ($iscurrentuser && has_capability('moodle/grade:view', $coursecontext)) { 1207 // Can view own grades. 1208 $gradeaccess = true; 1209 } else if (has_capability('moodle/grade:viewall', $usercontext)) { 1210 // Can view grades of this user - parent most probably. 1211 $gradeaccess = true; 1212 } else if ($anyreport) { 1213 // Can view grades of this user - parent most probably. 1214 $gradeaccess = true; 1215 } 1216 } 1217 if ($gradeaccess) { 1218 $url = new moodle_url('/course/user.php', array('mode' => 'grade', 'id' => $course->id, 'user' => $user->id)); 1219 $node = new core_user\output\myprofile\node('reports', 'grade', get_string('grade'), null, $url); 1220 $tree->add_node($node); 1221 } 1222 } 1223 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |