<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Definition of the grade_user_report class is defined
*
* @package gradereport_user
* @copyright 2007 Nicolas Connault
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
> use core_user\output\myprofile\tree;
require_once($CFG->dirroot . '/grade/report/lib.php');
>
require_once($CFG->libdir.'/tablelib.php');
< //showhiddenitems values
define("GRADE_REPORT_USER_HIDE_HIDDEN", 0);
define("GRADE_REPORT_USER_HIDE_UNTIL", 1);
define("GRADE_REPORT_USER_SHOW_HIDDEN", 2);
define("GRADE_REPORT_USER_VIEW_SELF", 1);
define("GRADE_REPORT_USER_VIEW_USER", 2);
< /**
< * Class providing an API for the user report building and displaying.
< * @uses grade_report
< * @package gradereport_user
< */
< class grade_report_user extends grade_report {
<
< /**
< * The user.
< * @var object $user
< */
< public $user;
<
< /**
< * A flexitable to hold the data.
< * @var object $table
< */
< public $table;
<
< /**
< * An array of table headers
< * @var array
< */
< public $tableheaders = array();
<
< /**
< * An array of table columns
< * @var array
< */
< public $tablecolumns = array();
<
< /**
< * An array containing rows of data for the table.
< * @var type
< */
< public $tabledata = array();
<
< /**
< * An array containing the grade items data for external usage (web services, ajax, etc...)
< * @var array
< */
< public $gradeitemsdata = array();
<
< /**
< * The grade tree structure
< * @var grade_tree
< */
< public $gtree;
<
< /**
< * Flat structure similar to grade tree
< */
< public $gseq;
<
< /**
< * show student ranks
< */
< public $showrank;
<
< /**
< * show grade percentages
< */
< public $showpercentage;
<
< /**
< * Show range
< */
< public $showrange = true;
<
< /**
< * Show grades in the report, default true
< * @var bool
< */
< public $showgrade = true;
<
< /**
< * Decimal points to use for values in the report, default 2
< * @var int
< */
< public $decimals = 2;
<
< /**
< * The number of decimal places to round range to, default 0
< * @var int
< */
< public $rangedecimals = 0;
<
< /**
< * Show grade feedback in the report, default true
< * @var bool
< */
< public $showfeedback = true;
<
< /**
< * Show grade weighting in the report, default true.
< * @var bool
< */
< public $showweight = true;
<
< /**
< * Show letter grades in the report, default false
< * @var bool
< */
< public $showlettergrade = false;
<
< /**
< * Show the calculated contribution to the course total column.
< * @var bool
< */
< public $showcontributiontocoursetotal = true;
<
< /**
< * Show average grades in the report, default false.
< * @var false
< */
< public $showaverage = false;
<
< public $maxdepth;
< public $evenodd;
<
< public $canviewhidden;
<
< public $switch;
<
< /**
< * Show hidden items even when user does not have required cap
< */
< public $showhiddenitems;
< public $showtotalsifcontainhidden;
<
< public $baseurl;
< public $pbarurl;
<
< /**
< * The modinfo object to be used.
< *
< * @var course_modinfo
< */
< protected $modinfo = null;
<
< /**
< * View as user.
< *
< * When this is set to true, the visibility checks, and capability checks will be
< * applied to the user whose grades are being displayed. This is very useful when
< * a mentor/parent is viewing the report of their mentee because they need to have
< * access to the same information, but not more, not less.
< *
< * @var boolean
< */
< protected $viewasuser = false;
<
< /**
< * An array that collects the aggregationhints for every
< * grade_item. The hints contain grade, grademin, grademax
< * status, weight and parent.
< *
< * @var array
< */
< protected $aggregationhints = array();
<
< /**
< * Constructor. Sets local copies of user preferences and initialises grade_tree.
< * @param int $courseid
< * @param object $gpr grade plugin return tracking object
< * @param string $context
< * @param int $userid The id of the user
< * @param bool $viewasuser Set this to true when the current user is a mentor/parent of the targetted user.
< */
< public function __construct($courseid, $gpr, $context, $userid, $viewasuser = null) {
< global $DB, $CFG;
< parent::__construct($courseid, $gpr, $context);
<
< $this->showrank = grade_get_setting($this->courseid, 'report_user_showrank', $CFG->grade_report_user_showrank);
< $this->showpercentage = grade_get_setting($this->courseid, 'report_user_showpercentage', $CFG->grade_report_user_showpercentage);
< $this->showhiddenitems = grade_get_setting($this->courseid, 'report_user_showhiddenitems', $CFG->grade_report_user_showhiddenitems);
< $this->showtotalsifcontainhidden = array($this->courseid => grade_get_setting($this->courseid, 'report_user_showtotalsifcontainhidden', $CFG->grade_report_user_showtotalsifcontainhidden));
<
< $this->showgrade = grade_get_setting($this->courseid, 'report_user_showgrade', !empty($CFG->grade_report_user_showgrade));
< $this->showrange = grade_get_setting($this->courseid, 'report_user_showrange', !empty($CFG->grade_report_user_showrange));
< $this->showfeedback = grade_get_setting($this->courseid, 'report_user_showfeedback', !empty($CFG->grade_report_user_showfeedback));
<
< $this->showweight = grade_get_setting($this->courseid, 'report_user_showweight',
< !empty($CFG->grade_report_user_showweight));
<
< $this->showcontributiontocoursetotal = grade_get_setting($this->courseid, 'report_user_showcontributiontocoursetotal',
< !empty($CFG->grade_report_user_showcontributiontocoursetotal));
<
< $this->showlettergrade = grade_get_setting($this->courseid, 'report_user_showlettergrade', !empty($CFG->grade_report_user_showlettergrade));
< $this->showaverage = grade_get_setting($this->courseid, 'report_user_showaverage', !empty($CFG->grade_report_user_showaverage));
<
< $this->viewasuser = $viewasuser;
<
< // The default grade decimals is 2
< $defaultdecimals = 2;
< if (property_exists($CFG, 'grade_decimalpoints')) {
< $defaultdecimals = $CFG->grade_decimalpoints;
< }
< $this->decimals = grade_get_setting($this->courseid, 'decimalpoints', $defaultdecimals);
<
< // The default range decimals is 0
< $defaultrangedecimals = 0;
< if (property_exists($CFG, 'grade_report_user_rangedecimals')) {
< $defaultrangedecimals = $CFG->grade_report_user_rangedecimals;
< }
< $this->rangedecimals = grade_get_setting($this->courseid, 'report_user_rangedecimals', $defaultrangedecimals);
<
< $this->switch = grade_get_setting($this->courseid, 'aggregationposition', $CFG->grade_aggregationposition);
<
< // Grab the grade_tree for this course
< $this->gtree = new grade_tree($this->courseid, false, $this->switch, null, !$CFG->enableoutcomes);
<
< // Get the user (for full name).
< $this->user = $DB->get_record('user', array('id' => $userid));
<
< // What user are we viewing this as?
< $coursecontext = context_course::instance($this->courseid);
< if ($viewasuser) {
< $this->modinfo = new course_modinfo($this->course, $this->user->id);
< $this->canviewhidden = has_capability('moodle/grade:viewhidden', $coursecontext, $this->user->id);
< } else {
< $this->modinfo = $this->gtree->modinfo;
< $this->canviewhidden = has_capability('moodle/grade:viewhidden', $coursecontext);
< }
<
< // Determine the number of rows and indentation.
< $this->maxdepth = 1;
< $this->inject_rowspans($this->gtree->top_element);
< $this->maxdepth++; // Need to account for the lead column that spans all children.
< for ($i = 1; $i <= $this->maxdepth; $i++) {
< $this->evenodd[$i] = 0;
< }
<
< $this->tabledata = array();
<
< // base url for sorting by first/last name
< $this->baseurl = $CFG->wwwroot.'/grade/report?id='.$courseid.'&userid='.$userid;
< $this->pbarurl = $this->baseurl;
<
< // no groups on this report - rank is from all course users
< $this->setup_table();
<
< //optionally calculate grade item averages
< $this->calculate_averages();
< }
<
< /**
< * Recurses through a tree of elements setting the rowspan property on each element
< *
< * @param array $element Either the top element or, during recursion, the current element
< * @return int The number of elements processed
< */
< function inject_rowspans(&$element) {
<
< if ($element['depth'] > $this->maxdepth) {
< $this->maxdepth = $element['depth'];
< }
< if (empty($element['children'])) {
< return 1;
< }
< $count = 1;
<
< foreach ($element['children'] as $key=>$child) {
< // If category is hidden then do not include it in the rowspan.
< if ($child['type'] == 'category' && $child['object']->is_hidden() && !$this->canviewhidden
< && ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN
< || ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$child['object']->is_hiddenuntil()))) {
< // Just calculate the rowspans for children of this category, don't add them to the count.
< $this->inject_rowspans($element['children'][$key]);
< } else {
< $count += $this->inject_rowspans($element['children'][$key]);
< }
< }
<
< $element['rowspan'] = $count;
< return $count;
< }
<
<
< /**
< * Prepares the headers and attributes of the flexitable.
< */
< public function setup_table() {
< /*
< * Table has 1-8 columns
< *| All columns except for itemname/description are optional
< */
<
< // setting up table headers
<
< $this->tablecolumns = array('itemname');
< $this->tableheaders = array($this->get_lang_string('gradeitem', 'grades'));
<
< if ($this->showweight) {
< $this->tablecolumns[] = 'weight';
< $this->tableheaders[] = $this->get_lang_string('weightuc', 'grades');
< }
<
< if ($this->showgrade) {
< $this->tablecolumns[] = 'grade';
< $this->tableheaders[] = $this->get_lang_string('grade', 'grades');
< }
<
< if ($this->showrange) {
< $this->tablecolumns[] = 'range';
< $this->tableheaders[] = $this->get_lang_string('range', 'grades');
< }
<
< if ($this->showpercentage) {
< $this->tablecolumns[] = 'percentage';
< $this->tableheaders[] = $this->get_lang_string('percentage', 'grades');
< }
<
< if ($this->showlettergrade) {
< $this->tablecolumns[] = 'lettergrade';
< $this->tableheaders[] = $this->get_lang_string('lettergrade', 'grades');
< }
<
< if ($this->showrank) {
< $this->tablecolumns[] = 'rank';
< $this->tableheaders[] = $this->get_lang_string('rank', 'grades');
< }
<
< if ($this->showaverage) {
< $this->tablecolumns[] = 'average';
< $this->tableheaders[] = $this->get_lang_string('average', 'grades');
< }
<
< if ($this->showfeedback) {
< $this->tablecolumns[] = 'feedback';
< $this->tableheaders[] = $this->get_lang_string('feedback', 'grades');
< }
<
< if ($this->showcontributiontocoursetotal) {
< $this->tablecolumns[] = 'contributiontocoursetotal';
< $this->tableheaders[] = $this->get_lang_string('contributiontocoursetotal', 'grades');
< }
< }
<
< function fill_table() {
< //print "<pre>";
< //print_r($this->gtree->top_element);
< $this->fill_table_recursive($this->gtree->top_element);
< //print_r($this->tabledata);
< //print "</pre>";
< return true;
< }
<
< /**
< * Fill the table with data.
< *
< * @param $element - An array containing the table data for the current row.
< */
< private function fill_table_recursive(&$element) {
< global $DB, $CFG;
<
< $type = $element['type'];
< $depth = $element['depth'];
< $grade_object = $element['object'];
< $eid = $grade_object->id;
< $element['userid'] = $this->user->id;
< $fullname = $this->gtree->get_element_header($element, true, true, true, true, true);
< $data = array();
< $gradeitemdata = array();
< $hidden = '';
< $excluded = '';
< $itemlevel = ($type == 'categoryitem' || $type == 'category' || $type == 'courseitem') ? $depth : ($depth + 1);
< $class = 'level' . $itemlevel . ' level' . ($itemlevel % 2 ? 'odd' : 'even');
< $classfeedback = '';
<
< // If this is a hidden grade category, hide it completely from the user
< if ($type == 'category' && $grade_object->is_hidden() && !$this->canviewhidden && (
< $this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN ||
< ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_object->is_hiddenuntil()))) {
< return false;
< }
<
< if ($type == 'category') {
< $this->evenodd[$depth] = (($this->evenodd[$depth] + 1) % 2);
< }
< $alter = ($this->evenodd[$depth] == 0) ? 'even' : 'odd';
<
< /// Process those items that have scores associated
< if ($type == 'item' or $type == 'categoryitem' or $type == 'courseitem') {
< $header_row = "row_{$eid}_{$this->user->id}";
< $header_cat = "cat_{$grade_object->categoryid}_{$this->user->id}";
<
< if (! $grade_grade = grade_grade::fetch(array('itemid'=>$grade_object->id,'userid'=>$this->user->id))) {
< $grade_grade = new grade_grade();
< $grade_grade->userid = $this->user->id;
< $grade_grade->itemid = $grade_object->id;
< }
<
< $grade_grade->load_grade_item();
<
< /// Hidden Items
< if ($grade_grade->grade_item->is_hidden()) {
< $hidden = ' dimmed_text';
< }
<
< $hide = false;
< // If this is a hidden grade item, hide it completely from the user.
< if ($grade_grade->is_hidden() && !$this->canviewhidden && (
< $this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN ||
< ($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_grade->is_hiddenuntil()))) {
< $hide = true;
< } else if (!empty($grade_object->itemmodule) && !empty($grade_object->iteminstance)) {
< // The grade object can be marked visible but still be hidden if
< // the student cannot see the activity due to conditional access
< // and it's set to be hidden entirely.
< $instances = $this->modinfo->get_instances_of($grade_object->itemmodule);
< if (!empty($instances[$grade_object->iteminstance])) {
< $cm = $instances[$grade_object->iteminstance];
< $gradeitemdata['cmid'] = $cm->id;
< if (!$cm->uservisible) {
< // If there is 'availableinfo' text then it is only greyed
< // out and not entirely hidden.
< if (!$cm->availableinfo) {
< $hide = true;
< }
< }
< }
< }
<
< // Actual Grade - We need to calculate this whether the row is hidden or not.
< $gradeval = $grade_grade->finalgrade;
< $hint = $grade_grade->get_aggregation_hint();
< if (!$this->canviewhidden) {
< /// Virtual Grade (may be calculated excluding hidden items etc).
< $adjustedgrade = $this->blank_hidden_total_and_adjust_bounds($this->courseid,
< $grade_grade->grade_item,
< $gradeval);
<
< $gradeval = $adjustedgrade['grade'];
<
< // We temporarily adjust the view of this grade item - because the min and
< // max are affected by the hidden values in the aggregation.
< $grade_grade->grade_item->grademax = $adjustedgrade['grademax'];
< $grade_grade->grade_item->grademin = $adjustedgrade['grademin'];
< $hint['status'] = $adjustedgrade['aggregationstatus'];
< $hint['weight'] = $adjustedgrade['aggregationweight'];
< } else {
< // The max and min for an aggregation may be different to the grade_item.
< if (!is_null($gradeval)) {
< $grade_grade->grade_item->grademax = $grade_grade->get_grade_max();
< $grade_grade->grade_item->grademin = $grade_grade->get_grade_min();
< }
< }
<
<
< if (!$hide) {
< /// Excluded Item
< /**
< if ($grade_grade->is_excluded()) {
< $fullname .= ' ['.get_string('excluded', 'grades').']';
< $excluded = ' excluded';
< }
< **/
< $canviewall = has_capability('moodle/grade:viewall', $this->context);
< /// Other class information
< $class .= $hidden . $excluded;
< if ($this->switch) { // alter style based on whether aggregation is first or last
< $class .= ($type == 'categoryitem' or $type == 'courseitem') ? " ".$alter."d$depth baggt b2b" : " item b1b";
< } else {
< $class .= ($type == 'categoryitem' or $type == 'courseitem') ? " ".$alter."d$depth baggb" : " item b1b";
< }
< if ($type == 'categoryitem' or $type == 'courseitem') {
< $header_cat = "cat_{$grade_object->iteminstance}_{$this->user->id}";
< }
<
< /// Name
< $data['itemname']['content'] = $fullname;
< $data['itemname']['class'] = $class;
< $data['itemname']['colspan'] = ($this->maxdepth - $depth);
< $data['itemname']['celltype'] = 'th';
< $data['itemname']['id'] = $header_row;
<
< // Basic grade item information.
< $gradeitemdata['id'] = $grade_object->id;
< $gradeitemdata['itemname'] = $grade_object->itemname;
< $gradeitemdata['itemtype'] = $grade_object->itemtype;
< $gradeitemdata['itemmodule'] = $grade_object->itemmodule;
< $gradeitemdata['iteminstance'] = $grade_object->iteminstance;
< $gradeitemdata['itemnumber'] = $grade_object->itemnumber;
< $gradeitemdata['categoryid'] = $grade_object->categoryid;
< $gradeitemdata['outcomeid'] = $grade_object->outcomeid;
< $gradeitemdata['scaleid'] = $grade_object->outcomeid;
< $gradeitemdata['locked'] = $canviewall ? $grade_grade->grade_item->is_locked() : null;
<
< if ($this->showfeedback) {
< // Copy $class before appending itemcenter as feedback should not be centered
< $classfeedback = $class;
< }
< $class .= " itemcenter ";
< if ($this->showweight) {
< $data['weight']['class'] = $class;
< $data['weight']['content'] = '-';
< $data['weight']['headers'] = "$header_cat $header_row weight";
< // has a weight assigned, might be extra credit
<
< // This obliterates the weight because it provides a more informative description.
< if (is_numeric($hint['weight'])) {
< $data['weight']['content'] = format_float($hint['weight'] * 100.0, 2) . ' %';
< $gradeitemdata['weightraw'] = $hint['weight'];
< $gradeitemdata['weightformatted'] = $data['weight']['content'];
< }
< if ($hint['status'] != 'used' && $hint['status'] != 'unknown') {
< $data['weight']['content'] .= '<br>' . get_string('aggregationhint' . $hint['status'], 'grades');
< $gradeitemdata['status'] = $hint['status'];
< }
< }
<
< if ($this->showgrade) {
< $gradeitemdata['graderaw'] = null;
< $gradeitemdata['gradehiddenbydate'] = false;
< $gradeitemdata['gradeneedsupdate'] = $grade_grade->grade_item->needsupdate;
< $gradeitemdata['gradeishidden'] = $grade_grade->is_hidden();
< $gradeitemdata['gradedatesubmitted'] = $grade_grade->get_datesubmitted();
< $gradeitemdata['gradedategraded'] = $grade_grade->get_dategraded();
< $gradeitemdata['gradeislocked'] = $canviewall ? $grade_grade->is_locked() : null;
< $gradeitemdata['gradeisoverridden'] = $canviewall ? $grade_grade->is_overridden() : null;
<
< if ($grade_grade->grade_item->needsupdate) {
< $data['grade']['class'] = $class.' gradingerror';
< $data['grade']['content'] = get_string('error');
< } else if (!empty($CFG->grade_hiddenasdate) and $grade_grade->get_datesubmitted() and !$this->canviewhidden and $grade_grade->is_hidden()
< and !$grade_grade->grade_item->is_category_item() and !$grade_grade->grade_item->is_course_item()) {
< // 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
< $class .= ' datesubmitted';
< $data['grade']['class'] = $class;
< $data['grade']['content'] = get_string('submittedon', 'grades', userdate($grade_grade->get_datesubmitted(), get_string('strftimedatetimeshort')));
< $gradeitemdata['gradehiddenbydate'] = true;
< } else if ($grade_grade->is_hidden()) {
< $data['grade']['class'] = $class.' dimmed_text';
< $data['grade']['content'] = '-';
<
< if ($this->canviewhidden) {
< $gradeitemdata['graderaw'] = $gradeval;
< $data['grade']['content'] = grade_format_gradevalue($gradeval,
< $grade_grade->grade_item,
< true);
< }
< } else {
< $data['grade']['class'] = $class;
< $data['grade']['content'] = grade_format_gradevalue($gradeval,
< $grade_grade->grade_item,
< true);
< $gradeitemdata['graderaw'] = $gradeval;
< }
< $data['grade']['headers'] = "$header_cat $header_row grade";
< $gradeitemdata['gradeformatted'] = $data['grade']['content'];
< }
<
< // Range
< if ($this->showrange) {
< $data['range']['class'] = $class;
< $data['range']['content'] = $grade_grade->grade_item->get_formatted_range(GRADE_DISPLAY_TYPE_REAL, $this->rangedecimals);
< $data['range']['headers'] = "$header_cat $header_row range";
<
< $gradeitemdata['rangeformatted'] = $data['range']['content'];
< $gradeitemdata['grademin'] = $grade_grade->grade_item->grademin;
< $gradeitemdata['grademax'] = $grade_grade->grade_item->grademax;
< }
<
< // Percentage
< if ($this->showpercentage) {
< if ($grade_grade->grade_item->needsupdate) {
< $data['percentage']['class'] = $class.' gradingerror';
< $data['percentage']['content'] = get_string('error');
< } else if ($grade_grade->is_hidden()) {
< $data['percentage']['class'] = $class.' dimmed_text';
< $data['percentage']['content'] = '-';
< if ($this->canviewhidden) {
< $data['percentage']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE);
< }
< } else {
< $data['percentage']['class'] = $class;
< $data['percentage']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE);
< }
< $data['percentage']['headers'] = "$header_cat $header_row percentage";
< $gradeitemdata['percentageformatted'] = $data['percentage']['content'];
< }
<
< // Lettergrade
< if ($this->showlettergrade) {
< if ($grade_grade->grade_item->needsupdate) {
< $data['lettergrade']['class'] = $class.' gradingerror';
< $data['lettergrade']['content'] = get_string('error');
< } else if ($grade_grade->is_hidden()) {
< $data['lettergrade']['class'] = $class.' dimmed_text';
< if (!$this->canviewhidden) {
< $data['lettergrade']['content'] = '-';
< } else {
< $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER);
< }
< } else {
< $data['lettergrade']['class'] = $class;
< $data['lettergrade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_LETTER);
< }
< $data['lettergrade']['headers'] = "$header_cat $header_row lettergrade";
< $gradeitemdata['lettergradeformatted'] = $data['lettergrade']['content'];
< }
<
< // Rank
< if ($this->showrank) {
< $gradeitemdata['rank'] = 0;
< if ($grade_grade->grade_item->needsupdate) {
< $data['rank']['class'] = $class.' gradingerror';
< $data['rank']['content'] = get_string('error');
< } elseif ($grade_grade->is_hidden()) {
< $data['rank']['class'] = $class.' dimmed_text';
< $data['rank']['content'] = '-';
< } else if (is_null($gradeval)) {
< // no grade, no rank
< $data['rank']['class'] = $class;
< $data['rank']['content'] = '-';
<
< } else {
< /// find the number of users with a higher grade
< $sql = "SELECT COUNT(DISTINCT(userid))
< FROM {grade_grades}
< WHERE finalgrade > ?
< AND itemid = ?
< AND hidden = 0";
< $rank = $DB->count_records_sql($sql, array($grade_grade->finalgrade, $grade_grade->grade_item->id)) + 1;
<
< $data['rank']['class'] = $class;
< $numusers = $this->get_numusers(false);
< $data['rank']['content'] = "$rank/$numusers"; // Total course users.
<
< $gradeitemdata['rank'] = $rank;
< $gradeitemdata['numusers'] = $numusers;
< }
< $data['rank']['headers'] = "$header_cat $header_row rank";
< }
<
< // Average
< if ($this->showaverage) {
< $gradeitemdata['averageformatted'] = '';
<
< $data['average']['class'] = $class;
< if (!empty($this->gtree->items[$eid]->avg)) {
< $data['average']['content'] = $this->gtree->items[$eid]->avg;
< $gradeitemdata['averageformatted'] = $this->gtree->items[$eid]->avg;
< } else {
< $data['average']['content'] = '-';
< }
< $data['average']['headers'] = "$header_cat $header_row average";
< }
<
< // Feedback
< if ($this->showfeedback) {
< $gradeitemdata['feedback'] = '';
< $gradeitemdata['feedbackformat'] = $grade_grade->feedbackformat;
<
< if ($grade_grade->feedback) {
< $grade_grade->feedback = file_rewrite_pluginfile_urls(
< $grade_grade->feedback,
< 'pluginfile.php',
< $grade_grade->get_context()->id,
< GRADE_FILE_COMPONENT,
< GRADE_FEEDBACK_FILEAREA,
< $grade_grade->id
< );
< }
<
< if ($grade_grade->overridden > 0 AND ($type == 'categoryitem' OR $type == 'courseitem')) {
< $data['feedback']['class'] = $classfeedback.' feedbacktext';
< $data['feedback']['content'] = get_string('overridden', 'grades').': ' .
< format_text($grade_grade->feedback, $grade_grade->feedbackformat,
< ['context' => $grade_grade->get_context()]);
< $gradeitemdata['feedback'] = $grade_grade->feedback;
< } else if (empty($grade_grade->feedback) or (!$this->canviewhidden and $grade_grade->is_hidden())) {
< $data['feedback']['class'] = $classfeedback.' feedbacktext';
< $data['feedback']['content'] = ' ';
< } else {
< $data['feedback']['class'] = $classfeedback.' feedbacktext';
< $data['feedback']['content'] = format_text($grade_grade->feedback, $grade_grade->feedbackformat,
< ['context' => $grade_grade->get_context()]);
< $gradeitemdata['feedback'] = $grade_grade->feedback;
< }
< $data['feedback']['headers'] = "$header_cat $header_row feedback";
< }
< // Contribution to the course total column.
< if ($this->showcontributiontocoursetotal) {
< $data['contributiontocoursetotal']['class'] = $class;
< $data['contributiontocoursetotal']['content'] = '-';
< $data['contributiontocoursetotal']['headers'] = "$header_cat $header_row contributiontocoursetotal";
<
< }
< $this->gradeitemsdata[] = $gradeitemdata;
< }
< // We collect the aggregation hints whether they are hidden or not.
< if ($this->showcontributiontocoursetotal) {
< $hint['grademax'] = $grade_grade->grade_item->grademax;
< $hint['grademin'] = $grade_grade->grade_item->grademin;
< $hint['grade'] = $gradeval;
< $parent = $grade_object->load_parent_category();
< if ($grade_object->is_category_item()) {
< $parent = $parent->load_parent_category();
< }
< $hint['parent'] = $parent->load_grade_item()->id;
< $this->aggregationhints[$grade_grade->itemid] = $hint;
< }
< }
<
< /// Category
< if ($type == 'category') {
< $data['leader']['class'] = $class.' '.$alter."d$depth b1t b2b b1l";
< $data['leader']['rowspan'] = $element['rowspan'];
<
< if ($this->switch) { // alter style based on whether aggregation is first or last
< $data['itemname']['class'] = $class.' '.$alter."d$depth b1b b1t";
< } else {
< $data['itemname']['class'] = $class.' '.$alter."d$depth b2t";
< }
< $data['itemname']['colspan'] = ($this->maxdepth - $depth + count($this->tablecolumns) - 1);
< $data['itemname']['content'] = $fullname;
< $data['itemname']['celltype'] = 'th';
< $data['itemname']['id'] = "cat_{$grade_object->id}_{$this->user->id}";
< }
<
< /// Add this row to the overall system
< foreach ($data as $key => $celldata) {
< $data[$key]['class'] .= ' column-' . $key;
< }
< $this->tabledata[] = $data;
<
< /// Recursively iterate through all child elements
< if (isset($element['children'])) {
< foreach ($element['children'] as $key=>$child) {
< $this->fill_table_recursive($element['children'][$key]);
< }
< }
<
< // Check we are showing this column, and we are looking at the root of the table.
< // This should be the very last thing this fill_table_recursive function does.
< if ($this->showcontributiontocoursetotal && ($type == 'category' && $depth == 1)) {
< // We should have collected all the hints by now - walk the tree again and build the contributions column.
<
< $this->fill_contributions_column($element);
< }
< }
<
< /**
< * This function is called after the table has been built and the aggregationhints
< * have been collected. We need this info to walk up the list of parents of each
< * grade_item.
< *
< * @param $element - An array containing the table data for the current row.
< */
< public function fill_contributions_column($element) {
<
< // Recursively iterate through all child elements.
< if (isset($element['children'])) {
< foreach ($element['children'] as $key=>$child) {
< $this->fill_contributions_column($element['children'][$key]);
< }
< } else if ($element['type'] == 'item') {
< // This is a grade item (We don't do this for categories or we would double count).
< $grade_object = $element['object'];
< $itemid = $grade_object->id;
<
< // Ignore anything with no hint - e.g. a hidden row.
< if (isset($this->aggregationhints[$itemid])) {
<
< // Normalise the gradeval.
< $gradecat = $grade_object->load_parent_category();
< if ($gradecat->aggregation == GRADE_AGGREGATE_SUM) {
< // Natural aggregation/Sum of grades does not consider the mingrade, cannot traditionnally normalise it.
< $graderange = $this->aggregationhints[$itemid]['grademax'];
<
< if ($graderange != 0) {
< $gradeval = $this->aggregationhints[$itemid]['grade'] / $graderange;
< } else {
< $gradeval = 0;
< }
< } else {
< $gradeval = grade_grade::standardise_score($this->aggregationhints[$itemid]['grade'],
< $this->aggregationhints[$itemid]['grademin'], $this->aggregationhints[$itemid]['grademax'], 0, 1);
< }
<
< // Multiply the normalised value by the weight
< // of all the categories higher in the tree.
< $parent = null;
< do {
< if (!is_null($this->aggregationhints[$itemid]['weight'])) {
< $gradeval *= $this->aggregationhints[$itemid]['weight'];
< } else if (empty($parent)) {
< // If we are in the first loop, and the weight is null, then we cannot calculate the contribution.
< $gradeval = null;
< break;
< }
<
< // The second part of this if is to prevent infinite loops
< // in case of crazy data.
< if (isset($this->aggregationhints[$itemid]['parent']) &&
< $this->aggregationhints[$itemid]['parent'] != $itemid) {
< $parent = $this->aggregationhints[$itemid]['parent'];
< $itemid = $parent;
< } else {
< // We are at the top of the tree.
< $parent = false;
< }
< } while ($parent);
<
< // Finally multiply by the course grademax.
< if (!is_null($gradeval)) {
< // Convert to percent.
< $gradeval *= 100;
< }
<
< // Now we need to loop through the "built" table data and update the
< // contributions column for the current row.
< $header_row = "row_{$grade_object->id}_{$this->user->id}";
< foreach ($this->tabledata as $key => $row) {
< if (isset($row['itemname']) && ($row['itemname']['id'] == $header_row)) {
< // Found it - update the column.
< $content = '-';
< if (!is_null($gradeval)) {
< $decimals = $grade_object->get_decimals();
< $content = format_float($gradeval, $decimals, true) . ' %';
< }
< $this->tabledata[$key]['contributiontocoursetotal']['content'] = $content;
< break;
< }
< }
< }
< }
< }
<
< /**
< * Prints or returns the HTML from the flexitable.
< * @param bool $return Whether or not to return the data instead of printing it directly.
< * @return string
< */
< public function print_table($return=false) {
< $maxspan = $this->maxdepth;
<
< /// Build table structure
< $html = "
< <table cellspacing='0'
< cellpadding='0'
< summary='" . s($this->get_lang_string('tablesummary', 'gradereport_user')) . "'
< class='boxaligncenter generaltable user-grade'>
< <thead>
< <tr>
< <th id='".$this->tablecolumns[0]."' class=\"header column-{$this->tablecolumns[0]}\" colspan='$maxspan'>".$this->tableheaders[0]."</th>\n";
<
< for ($i = 1; $i < count($this->tableheaders); $i++) {
< $html .= "<th id='".$this->tablecolumns[$i]."' class=\"header column-{$this->tablecolumns[$i]}\">".$this->tableheaders[$i]."</th>\n";
< }
<
< $html .= "
< </tr>
< </thead>
< <tbody>\n";
<
< /// Print out the table data
< for ($i = 0; $i < count($this->tabledata); $i++) {
< $html .= "<tr>\n";
< if (isset($this->tabledata[$i]['leader'])) {
< $rowspan = $this->tabledata[$i]['leader']['rowspan'];
< $class = $this->tabledata[$i]['leader']['class'];
< $html .= "<td class='$class' rowspan='$rowspan'></td>\n";
< }
< for ($j = 0; $j < count($this->tablecolumns); $j++) {
< $name = $this->tablecolumns[$j];
< $class = (isset($this->tabledata[$i][$name]['class'])) ? $this->tabledata[$i][$name]['class'] : '';
< $colspan = (isset($this->tabledata[$i][$name]['colspan'])) ? "colspan='".$this->tabledata[$i][$name]['colspan']."'" : '';
< $content = (isset($this->tabledata[$i][$name]['content'])) ? $this->tabledata[$i][$name]['content'] : null;
< $celltype = (isset($this->tabledata[$i][$name]['celltype'])) ? $this->tabledata[$i][$name]['celltype'] : 'td';
< $id = (isset($this->tabledata[$i][$name]['id'])) ? "id='{$this->tabledata[$i][$name]['id']}'" : '';
< $headers = (isset($this->tabledata[$i][$name]['headers'])) ? "headers='{$this->tabledata[$i][$name]['headers']}'" : '';
< if (isset($content)) {
< $html .= "<$celltype $id $headers class='$class' $colspan>$content</$celltype>\n";
< }
< }
< $html .= "</tr>\n";
< }
<
< $html .= "</tbody></table>";
<
< if ($return) {
< return $html;
< } else {
< echo $html;
< }
< }
<
< /**
< * Processes the data sent by the form (grades and feedbacks).
< * @var array $data
< * @return bool Success or Failure (array of errors).
< */
< function process_data($data) {
< }
< function process_action($target, $action) {
< }
<
< /**
< * Builds the grade item averages.
< */
< function calculate_averages() {
< global $USER, $DB, $CFG;
<
< if ($this->showaverage) {
< // This settings are actually grader report settings (not user report)
< // however we're using them as having two separate but identical settings the
< // user would have to keep in sync would be annoying.
< $averagesdisplaytype = $this->get_pref('averagesdisplaytype');
< $averagesdecimalpoints = $this->get_pref('averagesdecimalpoints');
< $meanselection = $this->get_pref('meanselection');
< $shownumberofgrades = $this->get_pref('shownumberofgrades');
<
< $avghtml = '';
< $groupsql = $this->groupsql;
< $groupwheresql = $this->groupwheresql;
< $totalcount = $this->get_numusers(false);
<
< // We want to query both the current context and parent contexts.
< list($relatedctxsql, $relatedctxparams) = $DB->get_in_or_equal($this->context->get_parent_context_ids(true), SQL_PARAMS_NAMED, 'relatedctx');
<
< // Limit to users with a gradeable role ie students.
< list($gradebookrolessql, $gradebookrolesparams) = $DB->get_in_or_equal(explode(',', $this->gradebookroles), SQL_PARAMS_NAMED, 'grbr0');
<
< // Limit to users with an active enrolment.
< $coursecontext = $this->context->get_course_context(true);
< $defaultgradeshowactiveenrol = !empty($CFG->grade_report_showonlyactiveenrol);
< $showonlyactiveenrol = get_user_preferences('grade_report_showonlyactiveenrol', $defaultgradeshowactiveenrol);
< $showonlyactiveenrol = $showonlyactiveenrol || !has_capability('moodle/course:viewsuspendedusers', $coursecontext);
< list($enrolledsql, $enrolledparams) = get_enrolled_sql($this->context, '', 0, $showonlyactiveenrol);
<
< $params = array_merge($this->groupwheresql_params, $gradebookrolesparams, $enrolledparams, $relatedctxparams);
< $params['courseid'] = $this->courseid;
<
< // find sums of all grade items in course
< $sql = "SELECT gg.itemid, SUM(gg.finalgrade) AS sum
< FROM {grade_items} gi
< JOIN {grade_grades} gg ON gg.itemid = gi.id
< JOIN {user} u ON u.id = gg.userid
< JOIN ($enrolledsql) je ON je.id = gg.userid
< JOIN (
< SELECT DISTINCT ra.userid
< FROM {role_assignments} ra
< WHERE ra.roleid $gradebookrolessql
< AND ra.contextid $relatedctxsql
< ) rainner ON rainner.userid = u.id
< $groupsql
< WHERE gi.courseid = :courseid
< AND u.deleted = 0
< AND gg.finalgrade IS NOT NULL
< AND gg.hidden = 0
< $groupwheresql
< GROUP BY gg.itemid";
<
< $sum_array = array();
< $sums = $DB->get_recordset_sql($sql, $params);
< foreach ($sums as $itemid => $csum) {
< $sum_array[$itemid] = $csum->sum;
< }
< $sums->close();
<
< $columncount=0;
<
< // Empty grades must be evaluated as grademin, NOT always 0
< // This query returns a count of ungraded grades (NULL finalgrade OR no matching record in grade_grades table)
< // No join condition when joining grade_items and user to get a grade item row for every user
< // Then left join with grade_grades and look for rows with null final grade (which includes grade items with no grade_grade)
< $sql = "SELECT gi.id, COUNT(u.id) AS count
< FROM {grade_items} gi
< JOIN {user} u ON u.deleted = 0
< JOIN ($enrolledsql) je ON je.id = u.id
< JOIN (
< SELECT DISTINCT ra.userid
< FROM {role_assignments} ra
< WHERE ra.roleid $gradebookrolessql
< AND ra.contextid $relatedctxsql
< ) rainner ON rainner.userid = u.id
< LEFT JOIN {grade_grades} gg
< ON (gg.itemid = gi.id AND gg.userid = u.id AND gg.finalgrade IS NOT NULL AND gg.hidden = 0)
< $groupsql
< WHERE gi.courseid = :courseid
< AND gg.finalgrade IS NULL
< $groupwheresql
< GROUP BY gi.id";
<
< $ungraded_counts = $DB->get_records_sql($sql, $params);
<
< foreach ($this->gtree->items as $itemid=>$unused) {
< if (!empty($this->gtree->items[$itemid]->avg)) {
< continue;
< }
< $item = $this->gtree->items[$itemid];
<
< if ($item->needsupdate) {
< $avghtml .= '<td class="cell c' . $columncount++.'"><span class="gradingerror">'.get_string('error').'</span></td>';
< continue;
< }
<
< if (empty($sum_array[$item->id])) {
< $sum_array[$item->id] = 0;
< }
<
< if (empty($ungraded_counts[$itemid])) {
< $ungraded_count = 0;
< } else {
< $ungraded_count = $ungraded_counts[$itemid]->count;
< }
<
< //do they want the averages to include all grade items
< if ($meanselection == GRADE_REPORT_MEAN_GRADED) {
< $mean_count = $totalcount - $ungraded_count;
< } else { // Bump up the sum by the number of ungraded items * grademin
< $sum_array[$item->id] += ($ungraded_count * $item->grademin);
< $mean_count = $totalcount;
< }
<
< // Determine which display type to use for this average
< if (!empty($USER->gradeediting) && $USER->gradeediting[$this->courseid]) {
< $displaytype = GRADE_DISPLAY_TYPE_REAL;
<
< } else if ($averagesdisplaytype == GRADE_REPORT_PREFERENCE_INHERIT) { // no ==0 here, please resave the report and user preferences
< $displaytype = $item->get_displaytype();
<
< } else {
< $displaytype = $averagesdisplaytype;
< }
<
< // Override grade_item setting if a display preference (not inherit) was set for the averages
< if ($averagesdecimalpoints == GRADE_REPORT_PREFERENCE_INHERIT) {
< $decimalpoints = $item->get_decimals();
< } else {
< $decimalpoints = $averagesdecimalpoints;
< }
<
< if (empty($sum_array[$item->id]) || $mean_count == 0) {
< $this->gtree->items[$itemid]->avg = '-';
< } else {
< $sum = $sum_array[$item->id];
< $avgradeval = $sum/$mean_count;
< $gradehtml = grade_format_gradevalue($avgradeval, $item, true, $displaytype, $decimalpoints);
<
< $numberofgrades = '';
< if ($shownumberofgrades) {
< $numberofgrades = " ($mean_count)";
< }
<
< $this->gtree->items[$itemid]->avg = $gradehtml.$numberofgrades;
< }
< }
< }
< }
<
< /**
< * Trigger the grade_report_viewed event
< *
< * @since Moodle 2.9
< */
< public function viewed() {
< $event = \gradereport_user\event\grade_report_viewed::create(
< array(
< 'context' => $this->context,
< 'courseid' => $this->courseid,
< 'relateduserid' => $this->user->id,
< )
< );
< $event->trigger();
< }
< }
<
function grade_report_user_settings_definition(&$mform) {
global $CFG;
< $options = array(-1 => get_string('default', 'grades'),
> $options = [
> -1 => get_string('default', 'grades'),
0 => get_string('hide'),
< 1 => get_string('show'));
> 1 => get_string('show')
> ];
if (empty($CFG->grade_report_user_showrank)) {
$options[-1] = get_string('defaultprev', 'grades', $options[0]);
} else {
$options[-1] = get_string('defaultprev', 'grades', $options[1]);
}
$mform->addElement('select', 'report_user_showrank', get_string('showrank', 'grades'), $options);
$mform->addHelpButton('report_user_showrank', 'showrank', 'grades');
if (empty($CFG->grade_report_user_showpercentage)) {
$options[-1] = get_string('defaultprev', 'grades', $options[0]);
} else {
$options[-1] = get_string('defaultprev', 'grades', $options[1]);
}
$mform->addElement('select', 'report_user_showpercentage', get_string('showpercentage', 'grades'), $options);
$mform->addHelpButton('report_user_showpercentage', 'showpercentage', 'grades');
if (empty($CFG->grade_report_user_showgrade)) {
$options[-1] = get_string('defaultprev', 'grades', $options[0]);
} else {
$options[-1] = get_string('defaultprev', 'grades', $options[1]);
}
$mform->addElement('select', 'report_user_showgrade', get_string('showgrade', 'grades'), $options);
if (empty($CFG->grade_report_user_showfeedback)) {
$options[-1] = get_string('defaultprev', 'grades', $options[0]);
} else {
$options[-1] = get_string('defaultprev', 'grades', $options[1]);
}
$mform->addElement('select', 'report_user_showfeedback', get_string('showfeedback', 'grades'), $options);
if (empty($CFG->grade_report_user_showweight)) {
$options[-1] = get_string('defaultprev', 'grades', $options[0]);
} else {
$options[-1] = get_string('defaultprev', 'grades', $options[1]);
}
$mform->addElement('select', 'report_user_showweight', get_string('showweight', 'grades'), $options);
if (empty($CFG->grade_report_user_showaverage)) {
$options[-1] = get_string('defaultprev', 'grades', $options[0]);
} else {
$options[-1] = get_string('defaultprev', 'grades', $options[1]);
}
$mform->addElement('select', 'report_user_showaverage', get_string('showaverage', 'grades'), $options);
$mform->addHelpButton('report_user_showaverage', 'showaverage', 'grades');
if (empty($CFG->grade_report_user_showlettergrade)) {
$options[-1] = get_string('defaultprev', 'grades', $options[0]);
} else {
$options[-1] = get_string('defaultprev', 'grades', $options[1]);
}
$mform->addElement('select', 'report_user_showlettergrade', get_string('showlettergrade', 'grades'), $options);
if (empty($CFG->grade_report_user_showcontributiontocoursetotal)) {
$options[-1] = get_string('defaultprev', 'grades', $options[0]);
} else {
$options[-1] = get_string('defaultprev', 'grades', $options[$CFG->grade_report_user_showcontributiontocoursetotal]);
}
$mform->addElement('select', 'report_user_showcontributiontocoursetotal', get_string('showcontributiontocoursetotal', 'grades'), $options);
$mform->addHelpButton('report_user_showcontributiontocoursetotal', 'showcontributiontocoursetotal', 'grades');
if (empty($CFG->grade_report_user_showrange)) {
$options[-1] = get_string('defaultprev', 'grades', $options[0]);
} else {
$options[-1] = get_string('defaultprev', 'grades', $options[1]);
}
$mform->addElement('select', 'report_user_showrange', get_string('showrange', 'grades'), $options);
< $options = array(0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5);
> $options = [
> 0 => 0,
> 1 => 1,
> 2 => 2,
> 3 => 3,
> 4 => 4,
> 5 => 5
> ];
>
if (! empty($CFG->grade_report_user_rangedecimals)) {
$options[-1] = $options[$CFG->grade_report_user_rangedecimals];
}
$mform->addElement('select', 'report_user_rangedecimals', get_string('rangedecimals', 'grades'), $options);
< $options = array(-1 => get_string('default', 'grades'),
> $options = [
> -1 => get_string('default', 'grades'),
0 => get_string('shownohidden', 'grades'),
1 => get_string('showhiddenuntilonly', 'grades'),
< 2 => get_string('showallhidden', 'grades'));
> 2 => get_string('showallhidden', 'grades')
> ];
if (empty($CFG->grade_report_user_showhiddenitems)) {
$options[-1] = get_string('defaultprev', 'grades', $options[0]);
} else {
$options[-1] = get_string('defaultprev', 'grades', $options[$CFG->grade_report_user_showhiddenitems]);
}
$mform->addElement('select', 'report_user_showhiddenitems', get_string('showhiddenitems', 'grades'), $options);
$mform->addHelpButton('report_user_showhiddenitems', 'showhiddenitems', 'grades');
< //showtotalsifcontainhidden
< $options = array(-1 => get_string('default', 'grades'),
> $options = [
> -1 => get_string('default', 'grades'),
GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN => get_string('hide'),
GRADE_REPORT_SHOW_TOTAL_IF_CONTAINS_HIDDEN => get_string('hidetotalshowexhiddenitems', 'grades'),
< GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN => get_string('hidetotalshowinchiddenitems', 'grades') );
> GRADE_REPORT_SHOW_REAL_TOTAL_IF_CONTAINS_HIDDEN => get_string('hidetotalshowinchiddenitems', 'grades')
> ];
if (empty($CFG->grade_report_user_showtotalsifcontainhidden)) {
$options[-1] = get_string('defaultprev', 'grades', $options[0]);
} else {
$options[-1] = get_string('defaultprev', 'grades', $options[$CFG->grade_report_user_showtotalsifcontainhidden]);
}
$mform->addElement('select', 'report_user_showtotalsifcontainhidden', get_string('hidetotalifhiddenitems', 'grades'), $options);
$mform->addHelpButton('report_user_showtotalsifcontainhidden', 'hidetotalifhiddenitems', 'grades');
}
/**
* Profile report callback.
*
* @param object $course The course.
* @param object $user The user.
* @param boolean $viewasuser True when we are viewing this as the targetted user sees it.
*/
< function grade_report_user_profilereport($course, $user, $viewasuser = false) {
< global $OUTPUT;
> function grade_report_user_profilereport(object $course, object $user, bool $viewasuser = false) {
if (!empty($course->showgrades)) {
$context = context_course::instance($course->id);
< /// return tracking object
< $gpr = new grade_plugin_return(array('type'=>'report', 'plugin'=>'user', 'courseid'=>$course->id, 'userid'=>$user->id));
< // Create a report instance
< $report = new grade_report_user($course->id, $gpr, $context, $user->id, $viewasuser);
> // Fetch the return tracking object.
> $gpr = new grade_plugin_return(
> ['type' => 'report', 'plugin' => 'user', 'courseid' => $course->id, 'userid' => $user->id]
> );
> // Create a report instance.
> $report = new gradereport_user\report\user($course->id, $gpr, $context, $user->id, $viewasuser);
< // print the page
< echo '<div class="grade-report-user">'; // css fix to share styles with real report page
> // Print the page.
> // A css fix to share styles with real report page.
> echo '<div class="grade-report-user">';
if ($report->fill_table()) {
echo $report->print_table(true);
}
echo '</div>';
}
}
/**
* Add nodes to myprofile page.
*
< * @param \core_user\output\myprofile\tree $tree Tree object
> * @param tree $tree Tree object
* @param stdClass $user user object
* @param bool $iscurrentuser
< * @param stdClass $course Course object
> * @param null|stdClass $course Course object
*/
< function gradereport_user_myprofile_navigation(core_user\output\myprofile\tree $tree, $user, $iscurrentuser, $course) {
< global $CFG, $USER;
> function gradereport_user_myprofile_navigation(tree $tree, stdClass $user, bool $iscurrentuser, ?stdClass $course) {
if (empty($course)) {
// We want to display these reports under the site context.
$course = get_fast_modinfo(SITEID)->get_course();
}
$usercontext = context_user::instance($user->id);
$anyreport = has_capability('moodle/user:viewuseractivitiesreport', $usercontext);
// Start capability checks.
if ($anyreport || $iscurrentuser) {
// Add grade hardcoded grade report if necessary.
$gradeaccess = false;
$coursecontext = context_course::instance($course->id);
if (has_capability('moodle/grade:viewall', $coursecontext)) {
// Can view all course grades.
$gradeaccess = true;
} else if ($course->showgrades) {
if ($iscurrentuser && has_capability('moodle/grade:view', $coursecontext)) {
// Can view own grades.
$gradeaccess = true;
} else if (has_capability('moodle/grade:viewall', $usercontext)) {
// Can view grades of this user - parent most probably.
$gradeaccess = true;
} else if ($anyreport) {
// Can view grades of this user - parent most probably.
$gradeaccess = true;
}
}
if ($gradeaccess) {
$url = new moodle_url('/course/user.php', array('mode' => 'grade', 'id' => $course->id, 'user' => $user->id));
< $node = new core_user\output\myprofile\node('reports', 'grade', get_string('grade'), null, $url);
> $node = new core_user\output\myprofile\node('reports', 'grade', get_string('grades'), null, $url);
$tree->add_node($node);
}
}
> }
}
>
> /**
> * Returns link to user report for the current element
> *
> * @param context_course $context Course context
> * @param int $courseid Course ID
> * @param array $element An array representing an element in the grade_tree
> * @param grade_plugin_return $gpr A grade_plugin_return object
> * @param string $mode Mode - gradeitem or user
> * @param ?stdClass $templatecontext Template context
> * @return stdClass|null
> */
> function gradereport_user_get_report_link(context_course $context, int $courseid, array $element,
> grade_plugin_return $gpr, string $mode, ?stdClass $templatecontext): ?stdClass {
> global $CFG;
>
> if ($mode == 'user') {
> $reportstring = grade_helper::get_lang_string('userreport_' . $mode, 'gradereport_user');
>
> if (!isset($templatecontext)) {
> $templatecontext = new stdClass();
> }
>
> // FIXME: MDL-52678 This get_capability_info is hacky and we should have an API for inserting grade row links instead.
> $canseeuserreport = false;
> if (get_capability_info('gradereport/' . $CFG->grade_profilereport . ':view')) {
> $canseeuserreport = has_capability('gradereport/' . $CFG->grade_profilereport . ':view', $context);
> }
>
> if ($canseeuserreport) {
> $url = new moodle_url('/grade/report/' . $CFG->grade_profilereport . '/index.php',
> ['userid' => $element['userid'], 'id' => $courseid]);
> $gpr->add_url_params($url);
> $templatecontext->reporturl1 = html_writer::link($url, $reportstring,
> ['class' => 'dropdown-item', 'aria-label' => $reportstring, 'role' => 'menuitem']);
> return $templatecontext;
> }
> }
> return null;