MDL-75362 gradereport_user: CiBot

This commit is contained in:
Mathew May 2022-09-13 11:01:31 +02:00
parent fdeda7f222
commit 547bf73ea7
15 changed files with 547 additions and 282 deletions

View File

@ -2959,12 +2959,12 @@ abstract class grade_helper {
}
$pluginstr = get_string('pluginname', 'gradereport_'.$plugin);
$url = new moodle_url('/grade/report/'.$plugin.'/index.php', array('id'=>$courseid));
$url = new moodle_url('/grade/report/'.$plugin.'/index.php', array('id' => $courseid));
$gradereports[$plugin] = new grade_plugin_info($plugin, $url, $pluginstr);
// Add link to preferences tab if such a page exists
if (file_exists($plugindir.'/preferences.php')) {
$url = new moodle_url('/grade/report/'.$plugin.'/preferences.php', array('id'=>$courseid));
$url = new moodle_url('/grade/report/'.$plugin.'/preferences.php', array('id' => $courseid));
$gradepreferences[$plugin] = new grade_plugin_info($plugin, $url,
get_string('preferences', 'grades') . ': ' . $pluginstr);
}

View File

@ -40,7 +40,7 @@ class grade_report_viewed extends \core\event\grade_report_viewed {
* Initialise the event data.
* @return void
*/
protected function init() {
protected function init(): void {
parent::init();
$this->data['edulevel'] = self::LEVEL_PARTICIPATING;
}
@ -50,7 +50,7 @@ class grade_report_viewed extends \core\event\grade_report_viewed {
*
* @return string
*/
public static function get_name() {
public static function get_name(): string {
return get_string('eventgradereportviewed', 'gradereport_user');
}

View File

@ -20,6 +20,7 @@ use external_api;
use context_course;
use core_user;
use external_description;
use external_format_value;
use external_function_parameters;
use external_multiple_structure;
use external_single_structure;
@ -29,6 +30,7 @@ use grade_plugin_return;
use graded_users_iterator;
use moodle_exception;
use stdClass;
use gradereport_user\report\user as user_report;
defined('MOODLE_INTERNAL') || die;
@ -132,7 +134,7 @@ class user extends external_api {
* Get the report data
* @param stdClass $course course object
* @param stdClass $context context object
* @param stdClass $user user object (it can be null for all the users)
* @param null|stdClass $user user object (it can be null for all the users)
* @param int $userid the user to retrieve data from, 0 for all
* @param int $groupid the group id to filter
* @param bool $tabledata whether to get the table data (true) or the gradeitemdata
@ -142,7 +144,7 @@ class user extends external_api {
protected static function get_report_data(
stdClass $course,
stdClass $context,
stdClass $user,
?stdClass $user,
int $userid,
int $groupid,
bool $tabledata = true
@ -173,7 +175,7 @@ class user extends external_api {
// Just one user.
if ($user) {
$report = new gradereport_user\report\user($course->id, $gpr, $context, $userid);
$report = new user_report($course->id, $gpr, $context, $userid);
$report->fill_table();
$gradeuserdata = [
@ -201,7 +203,7 @@ class user extends external_api {
while ($userdata = $gui->next_user()) {
$currentuser = $userdata->user;
$report = new gradereport_user\report\user($course->id, $gpr, $context, $currentuser->id);
$report = new user_report($course->id, $gpr, $context, $currentuser->id);
$report->fill_table();
$gradeuserdata = [
@ -415,7 +417,7 @@ class user extends external_api {
}
// Create a report instance. We don't need the gpr second parameter.
$report = new gradereport_user\report\user($course->id, null, $context, $userid);
$report = new user_report($course->id, null, $context, $userid);
$report->viewed();
return [
@ -430,7 +432,7 @@ class user extends external_api {
* @return external_description
* @since Moodle 2.9
*/
public static function view_grade_report_returns() {
public static function view_grade_report_returns(): external_description {
return new external_single_structure(
[
'status' => new external_value(PARAM_BOOL, 'status: true if success'),

View File

@ -59,7 +59,7 @@ class provider implements
/**
* Store all user preferences for the plugin.
*
* @param int $userid The userid of the user whose data is to be exported.
* @param int $userid The userid of the user whose data is to be exported.
*/
public static function export_user_preferences(int $userid) {
$prefvalue = get_user_preferences('gradereport_user_view_user', null, $userid);

View File

@ -49,25 +49,25 @@ class user extends grade_report {
* An array of table headers
* @var array
*/
public $tableheaders = array();
public $tableheaders = [];
/**
* An array of table columns
* @var array
*/
public $tablecolumns = array();
public $tablecolumns = [];
/**
* An array containing rows of data for the table.
* @var type
* @var array
*/
public $tabledata = array();
public $tabledata = [];
/**
* An array containing the grade items data for external usage (web services, ajax, etc...)
* @var array
*/
public $gradeitemsdata = array();
public $gradeitemsdata = [];
/**
* The grade tree structure
@ -77,21 +77,25 @@ class user extends grade_report {
/**
* Flat structure similar to grade tree
* @var void
*/
public $gseq;
/**
* show student ranks
* @var void
*/
public $showrank;
/**
* show grade percentages
* @var void
*/
public $showpercentage;
/**
* Show range
* @var bool
*/
public $showrange = true;
@ -143,20 +147,42 @@ class user extends grade_report {
*/
public $showaverage = false;
/**
* @var int
*/
public $maxdepth;
/**
* @var void
*/
public $evenodd;
/**
* @var bool
*/
public $canviewhidden;
/**
* @var string|null
*/
public $switch;
/**
* Show hidden items even when user does not have required cap
* @var void
*/
public $showhiddenitems;
/**
* @var array
*/
public $showtotalsifcontainhidden;
/**
* @var string
*/
public $baseurl;
/**
* @var string
*/
public $pbarurl;
/**
@ -185,32 +211,52 @@ class user extends grade_report {
*
* @var array
*/
protected $aggregationhints = array();
protected $aggregationhints = [];
/**
* Constructor. Sets local copies of user preferences and initialises grade_tree.
* @param int $courseid
* @param object $gpr grade plugin return tracking object
* @param null|object $gpr grade plugin return tracking object
* @param object $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(int $courseid, object $gpr, object $context, int $userid, bool $viewasuser = null) {
public function __construct(int $courseid, ?object $gpr, object $context, int $userid, bool $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->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 = [$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->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));
@ -218,19 +264,27 @@ class user extends grade_report {
$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->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
// 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
// The default range decimals is 0.
$defaultrangedecimals = 0;
if (property_exists($CFG, 'grade_report_user_rangedecimals')) {
$defaultrangedecimals = $CFG->grade_report_user_rangedecimals;
@ -243,7 +297,7 @@ class user extends grade_report {
$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));
$this->user = $DB->get_record('user', ['id' => $userid]);
// What user are we viewing this as?
$coursecontext = context_course::instance($this->courseid);
@ -263,10 +317,10 @@ class user extends grade_report {
$this->evenodd[$i] = 0;
}
$this->tabledata = array();
$this->tabledata = [];
// The base url for sorting by first/last name.
$this->baseurl = $CFG->wwwroot.'/grade/report?id='.$courseid.'&userid='.$userid;
$this->baseurl = new \moodle_url('/grade/report', ['id' => $courseid, 'userid' => $userid]);
$this->pbarurl = $this->baseurl;
// There no groups on this report - rank is from all course users.
@ -282,7 +336,7 @@ class user extends grade_report {
* @param array $element Either the top element or, during recursion, the current element
* @return int The number of elements processed
*/
function inject_rowspans(array &$element): int {
public function inject_rowspans(array &$element): int {
if ($element['depth'] > $this->maxdepth) {
$this->maxdepth = $element['depth'];
@ -292,7 +346,7 @@ class user extends grade_report {
}
$count = 1;
foreach ($element['children'] as $key=>$child) {
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
@ -320,8 +374,8 @@ class user extends grade_report {
// Setting up table headers.
$this->tablecolumns = array('itemname');
$this->tableheaders = array($this->get_lang_string('gradeitem', 'grades'));
$this->tablecolumns = ['itemname'];
$this->tableheaders = [$this->get_lang_string('gradeitem', 'grades')];
if ($this->showweight) {
$this->tablecolumns[] = 'weight';
@ -369,7 +423,12 @@ class user extends grade_report {
}
}
function fill_table() {
/**
* Provide an entry point to build the table.
*
* @return bool
*/
public function fill_table():bool {
$this->fill_table_recursive($this->gtree->top_element);
return true;
}
@ -377,15 +436,15 @@ class user extends grade_report {
/**
* Fill the table with data.
*
* @param $element - An array containing the table data for the current row.
* @param array $element - The table data for the current row.
*/
private function fill_table_recursive(array &$element) {
global $DB, $CFG, $OUTPUT;
$type = $element['type'];
$depth = $element['depth'];
$grade_object = $element['object'];
$eid = $grade_object->id;
$gradeobject = $element['object'];
$eid = $gradeobject->id;
$element['userid'] = $this->user->id;
$fullname = $this->gtree->get_element_header($element, true, true, true, true, true);
$data = [];
@ -397,9 +456,9 @@ class user extends grade_report {
$classfeedback = '';
// If this is a hidden grade category, hide it completely from the user.
if ($type == 'category' && $grade_object->is_hidden() && !$this->canviewhidden && (
if ($type == 'category' && $gradeobject->is_hidden() && !$this->canviewhidden && (
$this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN ||
($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_object->is_hiddenuntil()))) {
($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$gradeobject->is_hiddenuntil()))) {
return false;
}
@ -409,36 +468,36 @@ class user extends grade_report {
$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 ($type == 'item' || $type == 'categoryitem' || $type == 'courseitem') {
$headerrow = "row_{$eid}_{$this->user->id}";
$headercat = "cat_{$gradeobject->categoryid}_{$this->user->id}";
if (! $grade_grade = grade_grade::fetch(['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;
if (! $gradegrade = grade_grade::fetch(['itemid' => $gradeobject->id, 'userid' => $this->user->id])) {
$gradegrade = new grade_grade();
$gradegrade->userid = $this->user->id;
$gradegrade->itemid = $gradeobject->id;
}
$grade_grade->load_grade_item();
$gradegrade->load_grade_item();
// Hidden Items.
if ($grade_grade->grade_item->is_hidden()) {
if ($gradegrade->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 && (
if ($gradegrade->is_hidden() && !$this->canviewhidden && (
$this->showhiddenitems == GRADE_REPORT_USER_HIDE_HIDDEN ||
($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$grade_grade->is_hiddenuntil()))) {
($this->showhiddenitems == GRADE_REPORT_USER_HIDE_UNTIL && !$gradegrade->is_hiddenuntil()))) {
$hide = true;
} else if (!empty($grade_object->itemmodule) && !empty($grade_object->iteminstance)) {
} else if (!empty($gradeobject->itemmodule) && !empty($gradeobject->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];
$instances = $this->modinfo->get_instances_of($gradeobject->itemmodule);
if (!empty($instances[$gradeobject->iteminstance])) {
$cm = $instances[$gradeobject->iteminstance];
$gradeitemdata['cmid'] = $cm->id;
if (!$cm->uservisible) {
// If there is 'availableinfo' text then it is only greyed
@ -451,42 +510,42 @@ class user extends grade_report {
}
// Actual Grade - We need to calculate this whether the row is hidden or not.
$gradeval = $grade_grade->finalgrade;
$hint = $grade_grade->get_aggregation_hint();
$gradeval = $gradegrade->finalgrade;
$hint = $gradegrade->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,
$gradegrade->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'];
$gradegrade->grade_item->grademax = $adjustedgrade['grademax'];
$gradegrade->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();
$gradegrade->grade_item->grademax = $gradegrade->get_grade_max();
$gradegrade->grade_item->grademin = $gradegrade->get_grade_min();
}
}
if (!$hide) {
$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";
// Alter style based on whether aggregation is first or last.
if ($this->switch) {
$class .= ($type == 'categoryitem' || $type == 'courseitem') ? " ".$alter."d$depth baggt b2b" : " item b1b";
} else {
$class .= ($type == 'categoryitem' or $type == 'courseitem') ? " ".$alter."d$depth baggb" : " item b1b";
$class .= ($type == 'categoryitem' || $type == 'courseitem') ? " ".$alter."d$depth baggb" : " item b1b";
}
if ($type == 'categoryitem' or $type == 'courseitem') {
$header_cat = "cat_{$grade_object->iteminstance}_{$this->user->id}";
if ($type == 'categoryitem' || $type == 'courseitem') {
$headercat = "cat_{$gradeobject->iteminstance}_{$this->user->id}";
}
// Name.
@ -494,20 +553,20 @@ class user extends grade_report {
$data['itemname']['class'] = $class;
$data['itemname']['colspan'] = ($this->maxdepth - $depth);
$data['itemname']['celltype'] = 'th';
$data['itemname']['id'] = $header_row;
$data['itemname']['id'] = $headerrow;
// 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['idnumber'] = $grade_object->idnumber;
$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;
$gradeitemdata['id'] = $gradeobject->id;
$gradeitemdata['itemname'] = $gradeobject->itemname;
$gradeitemdata['itemtype'] = $gradeobject->itemtype;
$gradeitemdata['itemmodule'] = $gradeobject->itemmodule;
$gradeitemdata['iteminstance'] = $gradeobject->iteminstance;
$gradeitemdata['itemnumber'] = $gradeobject->itemnumber;
$gradeitemdata['idnumber'] = $gradeobject->idnumber;
$gradeitemdata['categoryid'] = $gradeobject->categoryid;
$gradeitemdata['outcomeid'] = $gradeobject->outcomeid;
$gradeitemdata['scaleid'] = $gradeobject->outcomeid;
$gradeitemdata['locked'] = $canviewall ? $gradegrade->grade_item->is_locked() : null;
if ($this->showfeedback) {
// Copy $class before appending itemcenter as feedback should not be centered.
@ -517,7 +576,7 @@ class user extends grade_report {
if ($this->showweight) {
$data['weight']['class'] = $class;
$data['weight']['content'] = '-';
$data['weight']['headers'] = "$header_cat $header_row weight";
$data['weight']['headers'] = "$headercat $headerrow weight";
// Has a weight assigned, might be extra credit.
// This obliterates the weight because it provides a more informative description.
@ -535,118 +594,163 @@ class user extends grade_report {
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;
$gradeitemdata['gradeneedsupdate'] = $gradegrade->grade_item->needsupdate;
$gradeitemdata['gradeishidden'] = $gradegrade->is_hidden();
$gradeitemdata['gradedatesubmitted'] = $gradegrade->get_datesubmitted();
$gradeitemdata['gradedategraded'] = $gradegrade->get_dategraded();
$gradeitemdata['gradeislocked'] = $canviewall ? $gradegrade->is_locked() : null;
$gradeitemdata['gradeisoverridden'] = $canviewall ? $gradegrade->is_overridden() : null;
if ($grade_grade->grade_item->needsupdate) {
if ($gradegrade->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.
} else if (
!empty($CFG->grade_hiddenasdate)
&& $gradegrade->get_datesubmitted()
&& !$this->canviewhidden
&& $gradegrade->is_hidden()
&& !$gradegrade->grade_item->is_category_item()
&& !$gradegrade->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')));
$data['grade']['content'] = get_string(
'submittedon',
'grades',
userdate(
$gradegrade->get_datesubmitted(),
get_string('strftimedatetimeshort')
)
);
$gradeitemdata['gradehiddenbydate'] = true;
} else if ($grade_grade->is_hidden()) {
} else if ($gradegrade->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,
$gradegrade->grade_item,
true);
}
} else {
$gradestatusclass = '';
$gradepassicon = '';
$ispassinggrade = $grade_grade->is_passed($grade_grade->grade_item);
$ispassinggrade = $gradegrade->is_passed($gradegrade->grade_item);
if (!is_null($ispassinggrade)) {
$gradestatusclass = $ispassinggrade ? 'gradepass' : 'gradefail';
if ($ispassinggrade) {
$gradepassicon = $OUTPUT->pix_icon('i/valid', get_string('pass', 'grades'), null,
array('class' => 'inline'));
$gradepassicon = $OUTPUT->pix_icon(
'i/valid',
get_string('pass', 'grades'),
null,
['class' => 'inline']
);
} else {
$gradepassicon = $OUTPUT->pix_icon('i/invalid', get_string('fail', 'grades'), null,
array('class' => 'inline'));
$gradepassicon = $OUTPUT->pix_icon(
'i/invalid',
get_string('fail', 'grades'),
null,
['class' => 'inline']
);
}
}
$data['grade']['class'] = "{$class} {$gradestatusclass}";
$data['grade']['content'] = $gradepassicon . grade_format_gradevalue($gradeval,
$grade_grade->grade_item, true);
$gradegrade->grade_item, true);
$gradeitemdata['graderaw'] = $gradeval;
}
$data['grade']['headers'] = "$header_cat $header_row grade";
$data['grade']['headers'] = "$headercat $headerrow 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";
$data['range']['content'] = $gradegrade->grade_item->get_formatted_range(
GRADE_DISPLAY_TYPE_REAL,
$this->rangedecimals
);
$data['range']['headers'] = "$headercat $headerrow range";
$gradeitemdata['rangeformatted'] = $data['range']['content'];
$gradeitemdata['grademin'] = $grade_grade->grade_item->grademin;
$gradeitemdata['grademax'] = $grade_grade->grade_item->grademax;
$gradeitemdata['grademin'] = $gradegrade->grade_item->grademin;
$gradeitemdata['grademax'] = $gradegrade->grade_item->grademax;
}
// Percentage.
if ($this->showpercentage) {
if ($grade_grade->grade_item->needsupdate) {
if ($gradegrade->grade_item->needsupdate) {
$data['percentage']['class'] = $class.' gradingerror';
$data['percentage']['content'] = get_string('error');
} else if ($grade_grade->is_hidden()) {
} else if ($gradegrade->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);
$data['percentage']['content'] = grade_format_gradevalue(
$gradeval,
$gradegrade->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']['content'] = grade_format_gradevalue(
$gradeval,
$gradegrade->grade_item,
true,
GRADE_DISPLAY_TYPE_PERCENTAGE
);
}
$data['percentage']['headers'] = "$header_cat $header_row percentage";
$data['percentage']['headers'] = "$headercat $headerrow percentage";
$gradeitemdata['percentageformatted'] = $data['percentage']['content'];
}
// Lettergrade.
if ($this->showlettergrade) {
if ($grade_grade->grade_item->needsupdate) {
if ($gradegrade->grade_item->needsupdate) {
$data['lettergrade']['class'] = $class.' gradingerror';
$data['lettergrade']['content'] = get_string('error');
} else if ($grade_grade->is_hidden()) {
} else if ($gradegrade->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);
$data['lettergrade']['content'] = grade_format_gradevalue(
$gradeval,
$gradegrade->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']['content'] = grade_format_gradevalue(
$gradeval,
$gradegrade->grade_item,
true,
GRADE_DISPLAY_TYPE_LETTER
);
}
$data['lettergrade']['headers'] = "$header_cat $header_row lettergrade";
$data['lettergrade']['headers'] = "$headercat $headerrow lettergrade";
$gradeitemdata['lettergradeformatted'] = $data['lettergrade']['content'];
}
// Rank.
if ($this->showrank) {
$gradeitemdata['rank'] = 0;
if ($grade_grade->grade_item->needsupdate) {
if ($gradegrade->grade_item->needsupdate) {
$data['rank']['class'] = $class.' gradingerror';
$data['rank']['content'] = get_string('error');
} elseif ($grade_grade->is_hidden()) {
} else if ($gradegrade->is_hidden()) {
$data['rank']['class'] = $class.' dimmed_text';
$data['rank']['content'] = '-';
} else if (is_null($gradeval)) {
// no grade, no rank
// No grade, o rank.
$data['rank']['class'] = $class;
$data['rank']['content'] = '-';
@ -657,7 +761,7 @@ class user extends grade_report {
WHERE finalgrade > ?
AND itemid = ?
AND hidden = 0";
$rank = $DB->count_records_sql($sql, array($grade_grade->finalgrade, $grade_grade->grade_item->id)) + 1;
$rank = $DB->count_records_sql($sql, [$gradegrade->finalgrade, $gradegrade->grade_item->id]) + 1;
$data['rank']['class'] = $class;
$numusers = $this->get_numusers(false);
@ -666,7 +770,7 @@ class user extends grade_report {
$gradeitemdata['rank'] = $rank;
$gradeitemdata['numusers'] = $numusers;
}
$data['rank']['headers'] = "$header_cat $header_row rank";
$data['rank']['headers'] = "$headercat $headerrow rank";
}
// Average.
@ -680,62 +784,62 @@ class user extends grade_report {
} else {
$data['average']['content'] = '-';
}
$data['average']['headers'] = "$header_cat $header_row average";
$data['average']['headers'] = "$headercat $headerrow average";
}
// Feedback.
if ($this->showfeedback) {
$gradeitemdata['feedback'] = '';
$gradeitemdata['feedbackformat'] = $grade_grade->feedbackformat;
$gradeitemdata['feedbackformat'] = $gradegrade->feedbackformat;
if ($grade_grade->feedback) {
$grade_grade->feedback = file_rewrite_pluginfile_urls(
$grade_grade->feedback,
if ($gradegrade->feedback) {
$gradegrade->feedback = file_rewrite_pluginfile_urls(
$gradegrade->feedback,
'pluginfile.php',
$grade_grade->get_context()->id,
$gradegrade->get_context()->id,
GRADE_FILE_COMPONENT,
GRADE_FEEDBACK_FILEAREA,
$grade_grade->id
$gradegrade->id
);
}
if ($grade_grade->overridden > 0 AND ($type == 'categoryitem' OR $type == 'courseitem')) {
if ($gradegrade->overridden > 0 && ($type == 'categoryitem' || $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())) {
format_text($gradegrade->feedback, $gradegrade->feedbackformat,
['context' => $gradegrade->get_context()]);
$gradeitemdata['feedback'] = $gradegrade->feedback;
} else if (empty($gradegrade->feedback) || (!$this->canviewhidden && $gradegrade->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']['content'] = format_text($gradegrade->feedback, $gradegrade->feedbackformat,
['context' => $gradegrade->get_context()]);
$gradeitemdata['feedback'] = $gradegrade->feedback;
}
$data['feedback']['headers'] = "$header_cat $header_row feedback";
$data['feedback']['headers'] = "$headercat $headerrow 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";
$data['contributiontocoursetotal']['headers'] = "$headercat $headerrow 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['grademax'] = $gradegrade->grade_item->grademax;
$hint['grademin'] = $gradegrade->grade_item->grademin;
$hint['grade'] = $gradeval;
$parent = $grade_object->load_parent_category();
if ($grade_object->is_category_item()) {
$parent = $gradeobject->load_parent_category();
if ($gradeobject->is_category_item()) {
$parent = $parent->load_parent_category();
}
$hint['parent'] = $parent->load_grade_item()->id;
$this->aggregationhints[$grade_grade->itemid] = $hint;
$this->aggregationhints[$gradegrade->itemid] = $hint;
}
}
@ -753,7 +857,7 @@ class user extends grade_report {
$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}";
$data['itemname']['id'] = "cat_{$gradeobject->id}_{$this->user->id}";
}
// Add this row to the overall system.
@ -764,7 +868,7 @@ class user extends grade_report {
// Recursively iterate through all child elements.
if (isset($element['children'])) {
foreach ($element['children'] as $key=>$child) {
foreach ($element['children'] as $key => $child) {
$this->fill_table_recursive($element['children'][$key]);
}
}
@ -782,25 +886,25 @@ class user extends grade_report {
* 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.
* @param array $element - An array containing the table data for the current row.
*/
public function fill_contributions_column(array $element) {
// Recursively iterate through all child elements.
if (isset($element['children'])) {
foreach ($element['children'] as $key=>$child) {
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;
$gradeobject = $element['object'];
$itemid = $gradeobject->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();
$gradecat = $gradeobject->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'];
@ -811,8 +915,13 @@ class user extends grade_report {
$gradeval = 0;
}
} else {
$gradeval = grade_grade::standardise_score($this->aggregationhints[$itemid]['grade'],
$this->aggregationhints[$itemid]['grademin'], $this->aggregationhints[$itemid]['grademax'], 0, 1);
$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
@ -847,13 +956,13 @@ class user extends grade_report {
// 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}";
$headerrow = "row_{$gradeobject->id}_{$this->user->id}";
foreach ($this->tabledata as $key => $row) {
if (isset($row['itemname']) && ($row['itemname']['id'] == $header_row)) {
if (isset($row['itemname']) && ($row['itemname']['id'] == $headerrow)) {
// Found it - update the column.
$content = '-';
if (!is_null($gradeval)) {
$decimals = $grade_object->get_decimals();
$decimals = $gradeobject->get_decimals();
$content = format_float($gradeval, $decimals, true) . ' %';
}
$this->tabledata[$key]['contributiontocoursetotal']['content'] = $content;
@ -902,11 +1011,13 @@ class user extends grade_report {
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']."'" : '';
$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']}'" : '';
$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";
}
@ -925,18 +1036,27 @@ class user extends grade_report {
/**
* Processes the data sent by the form (grades and feedbacks).
* @var array $data
* @return bool Success or Failure (array of errors).
*
* @param array $data Take in some data to provide to the base function.
* @return void Success or Failure (array of errors).
*/
function process_data($data) {
public function process_data($data): void {
}
function process_action($target, $action) {
/**
* Stub function.
*
* @param string $target
* @param string $action
* @return void
*/
public function process_action($target, $action): void {
}
/**
* Builds the grade item averages.
*/
function calculate_averages() {
private function calculate_averages() {
global $USER, $DB, $CFG;
if ($this->showaverage) {
@ -954,16 +1074,25 @@ class user extends grade_report {
$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');
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');
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);
$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);
@ -989,19 +1118,20 @@ class user extends grade_report {
$groupwheresql
GROUP BY gg.itemid";
$sum_array = array();
$sumarray = [];
$sums = $DB->get_recordset_sql($sql, $params);
foreach ($sums as $itemid => $csum) {
$sum_array[$itemid] = $csum->sum;
$sumarray[$itemid] = $csum->sum;
}
$sums->close();
$columncount=0;
$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).
// Then left join with grade_grades and look for rows with null final grade.
// This will include 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
@ -1020,36 +1150,37 @@ class user extends grade_report {
$groupwheresql
GROUP BY gi.id";
$ungraded_counts = $DB->get_records_sql($sql, $params);
$ungradedcounts = $DB->get_records_sql($sql, $params);
foreach ($this->gtree->items as $itemid=>$unused) {
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>';
$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($sumarray[$item->id])) {
$sumarray[$item->id] = 0;
}
if (empty($ungraded_counts[$itemid])) {
$ungraded_count = 0;
if (empty($ungradedcounts[$itemid])) {
$ungradedcount = 0;
} else {
$ungraded_count = $ungraded_counts[$itemid]->count;
$ungradedcount = $ungradedcounts[$itemid]->count;
}
// Do they want the averages to include all grade items.
if ($meanselection == GRADE_REPORT_MEAN_GRADED) {
$mean_count = $totalcount - $ungraded_count;
$meancount = $totalcount - $ungradedcount;
} else {
// Bump up the sum by the number of ungraded items * grademin.
$sum_array[$item->id] += ($ungraded_count * $item->grademin);
$mean_count = $totalcount;
$sumarray[$item->id] += ($ungradedcount * $item->grademin);
$meancount = $totalcount;
}
// Determine which display type to use for this average.
@ -1071,16 +1202,16 @@ class user extends grade_report {
$decimalpoints = $averagesdecimalpoints;
}
if (empty($sum_array[$item->id]) || $mean_count == 0) {
if (empty($sumarray[$item->id]) || $meancount == 0) {
$this->gtree->items[$itemid]->avg = '-';
} else {
$sum = $sum_array[$item->id];
$avgradeval = $sum/$mean_count;
$sum = $sumarray[$item->id];
$avgradeval = $sum / $meancount;
$gradehtml = grade_format_gradevalue($avgradeval, $item, true, $displaytype, $decimalpoints);
$numberofgrades = '';
if ($shownumberofgrades) {
$numberofgrades = " ($mean_count)";
$numberofgrades = " ($meancount)";
}
$this->gtree->items[$itemid]->avg = $gradehtml.$numberofgrades;
@ -1096,11 +1227,11 @@ class user extends grade_report {
*/
public function viewed() {
$event = \gradereport_user\event\grade_report_viewed::create(
array(
[
'context' => $this->context,
'courseid' => $this->courseid,
'relateduserid' => $this->user->id,
)
]
);
$event->trigger();
}

View File

@ -21,6 +21,9 @@
* @copyright 2015 Juan Leyva <juan@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die;
$functions = [
'gradereport_user_get_grades_table' => [
'classname' => 'gradereport_user\\external\\user',

View File

@ -22,6 +22,8 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* @param int $oldversion the version we are upgrading from
* @return bool result

View File

@ -31,7 +31,7 @@ $courseid = required_param('id', PARAM_INT);
$userid = optional_param('userid', $USER->id, PARAM_INT);
$userview = optional_param('userview', 0, PARAM_INT);
$PAGE->set_url(new moodle_url('/grade/report/user/index.php', ['id'=>$courseid]));
$PAGE->set_url(new moodle_url('/grade/report/user/index.php', ['id' => $courseid]));
if ($userview == 0) {
$userview = get_user_preferences('gradereport_user_view_user', GRADE_REPORT_USER_VIEW_USER);
@ -51,9 +51,8 @@ require_capability('gradereport/user:view', $context);
if (empty($userid)) {
require_capability('moodle/grade:viewall', $context);
} else {
if (!$DB->get_record('user', ['id'=>$userid, 'deleted'=>0]) or isguestuser($userid)) {
if (!$DB->get_record('user', ['id' => $userid, 'deleted' => 0]) || isguestuser($userid)) {
throw new \moodle_exception('invaliduser');
}
}
@ -62,12 +61,10 @@ $access = false;
if (has_capability('moodle/grade:viewall', $context)) {
// User can view all course grades.
$access = true;
} else if ($userid == $USER->id and has_capability('moodle/grade:view', $context) and $course->showgrades) {
} else if ($userid == $USER->id && has_capability('moodle/grade:view', $context) && $course->showgrades) {
// User can view own grades.
$access = true;
} else if (has_capability('moodle/grade:viewall', context_user::instance($userid)) and $course->showgrades) {
} else if (has_capability('moodle/grade:viewall', context_user::instance($userid)) && $course->showgrades) {
// User can view grades of this user, The user is an parent most probably.
$access = true;
}
@ -78,7 +75,7 @@ if (!$access) {
}
// Initialise the grade tracking object.
$gpr = new grade_plugin_return(['type'=>'report', 'plugin'=>'user', 'courseid'=>$courseid, 'userid'=>$userid]);
$gpr = new grade_plugin_return(['type' => 'report', 'plugin' => 'user', 'courseid' => $courseid, 'userid' => $userid]);
// Infer the users previously selected report via session tracking.
if (!isset($USER->grade_last_report)) {
@ -97,12 +94,12 @@ if (has_capability('moodle/grade:viewall', $context)) {
// To make some other functions work better later.
if (!$currentgroup) {
$currentgroup = NULL;
$currentgroup = null;
}
$isseparategroups = ($course->groupmode == SEPARATEGROUPS and !has_capability('moodle/site:accessallgroups', $context));
$isseparategroups = ($course->groupmode == SEPARATEGROUPS && !has_capability('moodle/site:accessallgroups', $context));
if ($isseparategroups and (!$currentgroup)) {
if ($isseparategroups && (!$currentgroup)) {
// No separate group access, The user can view only themselves.
$userid = $USER->id;
$user_selector = false;
@ -128,7 +125,7 @@ if (has_capability('moodle/grade:viewall', $context)) {
$gui->init();
// Add tabs.
print_grade_page_head($courseid, 'report', 'user');
groups_print_course_menu($course, $gpr->get_return_url('index.php?id='.$courseid, ['userid'=>0]));
groups_print_course_menu($course, $gpr->get_return_url('index.php?id='.$courseid, ['userid' => 0]));
if ($user_selector) {
echo $renderer->graded_users_selector('user', $course, $userid, $currentgroup, true);
@ -140,7 +137,13 @@ if (has_capability('moodle/grade:viewall', $context)) {
$user = $userdata->user;
$report = new gradereport_user\report\user($courseid, $gpr, $context, $user->id, $viewasuser);
$studentnamelink = html_writer::link(new moodle_url('/user/view.php', ['id' => $report->user->id, 'course' => $courseid]), fullname($report->user));
$studentnamelink = html_writer::link(
new moodle_url(
'/user/view.php',
['id' => $report->user->id, 'course' => $courseid]
),
fullname($report->user)
);
echo $OUTPUT->heading($studentnamelink);
if ($report->fill_table()) {
@ -153,11 +156,17 @@ if (has_capability('moodle/grade:viewall', $context)) {
// Only show one user's report.
$report = new gradereport_user\report\user($courseid, $gpr, $context, $userid, $viewasuser);
$studentnamelink = html_writer::link(new moodle_url('/user/view.php', ['id' => $report->user->id, 'course' => $courseid]), fullname($report->user));
$studentnamelink = html_writer::link(
new moodle_url(
'/user/view.php',
['id' => $report->user->id, 'course' => $courseid]
),
fullname($report->user)
);
print_grade_page_head($courseid, 'report', 'user', get_string('pluginname', 'gradereport_user') . ' - ' . $studentnamelink,
false, false, true, null, null, $report->user);
groups_print_course_menu($course, $gpr->get_return_url('index.php?id='.$courseid, ['userid'=>0]));
groups_print_course_menu($course, $gpr->get_return_url('index.php?id='.$courseid, ['userid' => 0]));
if ($user_selector) {
$showallusersoptions = true;
@ -166,7 +175,7 @@ if (has_capability('moodle/grade:viewall', $context)) {
echo $renderer->view_user_selector($userid, $userview);
if ($currentgroup and !groups_is_member($currentgroup, $userid)) {
if ($currentgroup && !groups_is_member($currentgroup, $userid)) {
echo $OUTPUT->notification(get_string('groupusernotmember', 'error'));
} else {
if ($report->fill_table()) {
@ -175,8 +184,7 @@ if (has_capability('moodle/grade:viewall', $context)) {
}
}
} else {
//Students will see just their own report.
// Students will see just their own report.
// Create a report instance.
$report = new gradereport_user\report\user($courseid, $gpr, $context, $userid);

View File

@ -22,6 +22,8 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
$string['eventgradereportviewed'] = 'Grade user report viewed';
$string['pluginname'] = 'User report';
$string['user:view'] = 'View your own grade report';

View File

@ -119,12 +119,12 @@ function grade_report_user_settings_definition(&$mform) {
$mform->addElement('select', 'report_user_showrange', get_string('showrange', 'grades'), $options);
$options = [
0=>0,
1=>1,
2=>2,
3=>3,
4=>4,
5=>5
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5
];
if (!empty($CFG->grade_report_user_rangedecimals)) {
@ -179,7 +179,9 @@ function grade_report_user_profilereport(object $course, object $user, bool $vie
$context = context_course::instance($course->id);
// Fetch the return tracking object.
$gpr = new grade_plugin_return(array('type'=>'report', 'plugin'=>'user', 'courseid'=>$course->id, 'userid'=>$user->id));
$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);

View File

@ -33,12 +33,22 @@
*/
class gradereport_user_renderer extends plugin_renderer_base {
public function graded_users_selector($report, $course, $userid, $groupid, $includeall) {
global $USER;
/**
* Small rendering function that helps with outputting the relevant user selector.
*
* @param string $report
* @param stdClass $course
* @param int $userid
* @param int $groupid
* @param bool $includeall
* @return string The raw HTML to render.
* @throws coding_exception
*/
public function graded_users_selector(string $report, stdClass $course, int $userid, int $groupid, bool $includeall): string {
$select = grade_get_graded_users_select($report, $course, $userid, $groupid, $includeall);
$output = html_writer::tag('div', $this->output->render($select), array('id'=>'graded_users_selector'));
$output .= html_writer::tag('p', '', array('style'=>'page-break-after: always;'));
$output = html_writer::tag('div', $this->output->render($select), ['id' => 'graded_users_selector']);
$output .= html_writer::tag('p', '', ['style' => 'page-break-after: always;']);
return $output;
}
@ -50,20 +60,22 @@ class gradereport_user_renderer extends plugin_renderer_base {
* @param int $userview The current view user setting constant
* @return string
*/
public function view_user_selector($userid, $userview) {
public function view_user_selector(int $userid, int $userview): string {
global $USER;
$url = $this->page->url;
if ($userid != $USER->id) {
$url->param('userid', $userid);
}
$options = array(GRADE_REPORT_USER_VIEW_USER => get_string('otheruser', 'gradereport_user'),
GRADE_REPORT_USER_VIEW_SELF => get_string('myself', 'gradereport_user'));
$options = [
GRADE_REPORT_USER_VIEW_USER => get_string('otheruser', 'gradereport_user'),
GRADE_REPORT_USER_VIEW_SELF => get_string('myself', 'gradereport_user')
];
$select = new single_select($url, 'userview', $options, $userview, null);
$select->label = get_string('viewas', 'gradereport_user');
$output = html_writer::tag('div', $this->output->render($select), array('class' => 'view_users_selector'));
$output = html_writer::tag('div', $this->output->render($select), ['class' => 'view_users_selector']);
return $output;
}

View File

@ -26,31 +26,129 @@ defined('MOODLE_INTERNAL') || die;
if ($ADMIN->fulltree) {
$settings->add(new admin_setting_configcheckbox('grade_report_user_showrank', get_string('showrank', 'grades'), get_string('showrank_help', 'grades'), 0));
$settings->add(new admin_setting_configcheckbox('grade_report_user_showpercentage', get_string('showpercentage', 'grades'), get_string('showpercentage_help', 'grades'), 1));
$settings->add(new admin_setting_configcheckbox('grade_report_user_showgrade', get_string('showgrade', 'grades'), get_string('showgrade_help', 'grades'), 1));
$settings->add(new admin_setting_configcheckbox('grade_report_user_showfeedback', get_string('showfeedback', 'grades'), get_string('showfeedback_help', 'grades'), 1));
$settings->add(new admin_setting_configcheckbox('grade_report_user_showrange', get_string('showrange', 'grades'), get_string('showrange_help', 'grades'), 1));
$settings->add(
new admin_setting_configcheckbox(
'grade_report_user_showrank',
get_string('showrank', 'grades'),
get_string('showrank_help', 'grades'),
0
)
);
$settings->add(new admin_setting_configcheckbox('grade_report_user_showweight',
get_string('showweight', 'grades'), get_string('showweight_help', 'grades'), 1));
$settings->add(
new admin_setting_configcheckbox(
'grade_report_user_showpercentage',
get_string('showpercentage', 'grades'),
get_string('showpercentage_help', 'grades'),
1
)
);
$settings->add(new admin_setting_configcheckbox('grade_report_user_showaverage', get_string('showaverage', 'grades'), get_string('showaverage_help', 'grades'), 0));
$settings->add(new admin_setting_configcheckbox('grade_report_user_showlettergrade', get_string('showlettergrade', 'grades'), get_string('showlettergrade_help', 'grades'), 0));
$settings->add(new admin_setting_configselect('grade_report_user_rangedecimals', get_string('rangedecimals', 'grades'),
get_string('rangedecimals_help', 'grades'), 0,array(0=>0, 1=>1, 2=>2, 3=>3, 4=>4, 5=>5)));
$settings->add(
new admin_setting_configcheckbox(
'grade_report_user_showgrade',
get_string('showgrade', 'grades'),
get_string('showgrade_help', 'grades'),
1
)
);
$options = array(0 => get_string('shownohidden', 'grades'),
1 => get_string('showhiddenuntilonly', 'grades'),
2 => get_string('showallhidden', 'grades'));
$settings->add(new admin_setting_configselect('grade_report_user_showhiddenitems', get_string('showhiddenitems', 'grades'), get_string('showhiddenitems_help', 'grades'), 1, $options));
$settings->add(
new admin_setting_configcheckbox(
'grade_report_user_showfeedback',
get_string('showfeedback', 'grades'),
get_string('showfeedback_help', 'grades'),
1
)
);
$settings->add(new admin_setting_configselect('grade_report_user_showtotalsifcontainhidden', get_string('hidetotalifhiddenitems', 'grades'),
get_string('hidetotalifhiddenitems_help', 'grades'), GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN,
array(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'))));
$settings->add(
new admin_setting_configcheckbox(
'grade_report_user_showrange',
get_string('showrange', 'grades'),
get_string('showrange_help', 'grades'),
1
)
);
$settings->add(new admin_setting_configcheckbox('grade_report_user_showcontributiontocoursetotal',
get_string('showcontributiontocoursetotal', 'grades'), get_string('showcontributiontocoursetotal_help', 'grades'), 1));
$settings->add(
new admin_setting_configcheckbox(
'grade_report_user_showweight',
get_string('showweight', 'grades'),
get_string('showweight_help', 'grades'),
1
)
);
$settings->add(
new admin_setting_configcheckbox(
'grade_report_user_showaverage',
get_string('showaverage', 'grades'),
get_string('showaverage_help', 'grades'),
0
)
);
$settings->add(
new admin_setting_configcheckbox(
'grade_report_user_showlettergrade',
get_string('showlettergrade', 'grades'),
get_string('showlettergrade_help', 'grades'),
0
)
);
$settings->add(
new admin_setting_configselect(
'grade_report_user_rangedecimals',
get_string('rangedecimals', 'grades'),
get_string('rangedecimals_help', 'grades'),
0,
[
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5
]
)
);
$options = [
0 => get_string('shownohidden', 'grades'),
1 => get_string('showhiddenuntilonly', 'grades'),
2 => get_string('showallhidden', 'grades')
];
$settings->add(
new admin_setting_configselect(
'grade_report_user_showhiddenitems',
get_string('showhiddenitems', 'grades'),
get_string('showhiddenitems_help', 'grades'),
1,
$options
)
);
$settings->add(
new admin_setting_configselect(
'grade_report_user_showtotalsifcontainhidden',
get_string('hidetotalifhiddenitems', 'grades'),
get_string('hidetotalifhiddenitems_help', 'grades'),
GRADE_REPORT_HIDE_TOTAL_IF_CONTAINS_HIDDEN,
[
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')
]
)
);
$settings->add(
new admin_setting_configcheckbox(
'grade_report_user_showcontributiontocoursetotal', get_string('showcontributiontocoursetotal', 'grades'),
get_string('showcontributiontocoursetotal_help', 'grades'),
1
)
);
}

View File

@ -17,14 +17,13 @@
namespace gradereport_user;
use externallib_advanced_testcase;
use gradereport_user_external;
use gradereport_user\external\user as user_external;
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/webservice/tests/helpers.php');
require_once($CFG->dirroot . '/grade/report/user/externallib.php');
/**
* User grade report functions unit tests
@ -40,21 +39,21 @@ class externallib_test extends externallib_advanced_testcase {
* Loads some data to be used by the different tests
* @param int $s1grade Student 1 grade
* @param int $s2grade Student 2 grade
* @return array Course and users instances
* @return array Course and users instances
*/
private function load_data($s1grade, $s2grade) {
private function load_data(int $s1grade, int $s2grade): array {
global $DB;
$course = $this->getDataGenerator()->create_course(array('groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1));
$course = $this->getDataGenerator()->create_course(['groupmode' => SEPARATEGROUPS, 'groupmodeforce' => 1]);
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
$student1 = $this->getDataGenerator()->create_user(array('idnumber' => 'testidnumber'));
$studentrole = $DB->get_record('role', ['shortname' => 'student']);
$student1 = $this->getDataGenerator()->create_user(['idnumber' => 'testidnumber']);
$this->getDataGenerator()->enrol_user($student1->id, $course->id, $studentrole->id);
$student2 = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($student2->id, $course->id, $studentrole->id);
$teacherrole = $DB->get_record('role', array('shortname' => 'teacher'));
$teacherrole = $DB->get_record('role', ['shortname' => 'teacher']);
$teacher = $this->getDataGenerator()->create_user();
$this->getDataGenerator()->enrol_user($teacher->id, $course->id, $teacherrole->id);
@ -62,22 +61,28 @@ class externallib_test extends externallib_advanced_testcase {
assign_capability('moodle/site:accessallgroups', CAP_PROHIBIT, $teacherrole->id, $context);
accesslib_clear_all_caches_for_unit_testing();
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
$group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
groups_add_member($group1->id, $student1->id);
groups_add_member($group1->id, $teacher->id);
groups_add_member($group2->id, $student2->id);
$assignment = $this->getDataGenerator()->create_module('assign', array('name' => "Test assign", 'course' => $course->id));
$assignment = $this->getDataGenerator()->create_module('assign', ['name' => "Test assign", 'course' => $course->id]);
$modcontext = get_coursemodule_from_instance('assign', $assignment->id, $course->id);
$assignment->cmidnumber = $modcontext->id;
$student1grade = array('userid' => $student1->id, 'rawgrade' => $s1grade, 'idnumber' => 'testidnumber1');
$student2grade = array('userid' => $student2->id, 'rawgrade' => $s2grade, 'idnumber' => 'testidnumber2');
$studentgrades = array($student1->id => $student1grade, $student2->id => $student2grade);
$student1grade = ['userid' => $student1->id, 'rawgrade' => $s1grade, 'idnumber' => 'testidnumber1'];
$student2grade = ['userid' => $student2->id, 'rawgrade' => $s2grade, 'idnumber' => 'testidnumber2'];
$studentgrades = [$student1->id => $student1grade, $student2->id => $student2grade];
assign_grade_item_update($assignment, $studentgrades);
return array($course, $teacher, $student1, $student2, $assignment);
return [
$course,
$teacher,
$student1,
$student2,
$assignment
];
}
/**
@ -95,8 +100,8 @@ class externallib_test extends externallib_advanced_testcase {
// A teacher must see all student grades (in their group only).
$this->setUser($teacher);
$studentgrades = gradereport_user_external::get_grades_table($course->id);
$studentgrades = \external_api::clean_returnvalue(gradereport_user_external::get_grades_table_returns(), $studentgrades);
$studentgrades = user_external::get_grades_table($course->id);
$studentgrades = \external_api::clean_returnvalue(user_external::get_grades_table_returns(), $studentgrades);
// No warnings returned.
$this->assertCount(0, $studentgrades['warnings']);
@ -105,7 +110,7 @@ class externallib_test extends externallib_advanced_testcase {
$this->assertCount(1, $studentgrades['tables']);
// Read returned grades.
$studentreturnedgrades = array();
$studentreturnedgrades = [];
$studentreturnedgrades[$studentgrades['tables'][0]['userid']] =
(int) $studentgrades['tables'][0]['tabledata'][1]['grade']['content'];
@ -127,8 +132,8 @@ class externallib_test extends externallib_advanced_testcase {
// A user can see his own grades.
$this->setUser($student1);
$studentgrade = gradereport_user_external::get_grades_table($course->id, $student1->id);
$studentgrade = \external_api::clean_returnvalue(gradereport_user_external::get_grades_table_returns(), $studentgrade);
$studentgrade = user_external::get_grades_table($course->id, $student1->id);
$studentgrade = \external_api::clean_returnvalue(user_external::get_grades_table_returns(), $studentgrade);
// No warnings returned.
$this->assertTrue(count($studentgrade['warnings']) == 0);
@ -155,7 +160,7 @@ class externallib_test extends externallib_advanced_testcase {
$this->setUser($student2);
try {
$studentgrade = gradereport_user_external::get_grades_table($course->id, $student1->id);
$studentgrade = user_external::get_grades_table($course->id, $student1->id);
$this->fail('Exception expected due to not perissions to view other user grades.');
} catch (\moodle_exception $e) {
$this->assertEquals('notingroup', $e->errorcode);
@ -178,8 +183,8 @@ class externallib_test extends externallib_advanced_testcase {
$sink = $this->redirectEvents();
$this->setUser($student1);
$result = gradereport_user_external::view_grade_report($course->id);
$result = \external_api::clean_returnvalue(gradereport_user_external::view_grade_report_returns(), $result);
$result = user_external::view_grade_report($course->id);
$result = \external_api::clean_returnvalue(user_external::view_grade_report_returns(), $result);
$events = $sink->get_events();
$this->assertCount(1, $events);
$event = reset($events);
@ -190,8 +195,8 @@ class externallib_test extends externallib_advanced_testcase {
$this->assertEquals($USER->id, $event->get_data()['relateduserid']);
$this->setUser($teacher);
$result = gradereport_user_external::view_grade_report($course->id, $student1->id);
$result = \external_api::clean_returnvalue(gradereport_user_external::view_grade_report_returns(), $result);
$result = user_external::view_grade_report($course->id, $student1->id);
$result = \external_api::clean_returnvalue(user_external::view_grade_report_returns(), $result);
$events = $sink->get_events();
$event = reset($events);
$sink->close();
@ -203,7 +208,7 @@ class externallib_test extends externallib_advanced_testcase {
$this->setUser($student2);
try {
$studentgrade = gradereport_user_external::view_grade_report($course->id, $student1->id);
$studentgrade = user_external::view_grade_report($course->id, $student1->id);
$this->fail('Exception expected due to not permissions to view other user grades.');
} catch (\moodle_exception $e) {
$this->assertEquals('nopermissiontoviewgrades', $e->errorcode);
@ -235,8 +240,8 @@ class externallib_test extends externallib_advanced_testcase {
grade_set_setting($course->id, 'report_user_showlettergrade', 1);
grade_set_setting($course->id, 'report_user_showaverage', 1);
$studentgrades = gradereport_user_external::get_grade_items($course->id);
$studentgrades = \external_api::clean_returnvalue(gradereport_user_external::get_grade_items_returns(), $studentgrades);
$studentgrades = user_external::get_grade_items($course->id);
$studentgrades = \external_api::clean_returnvalue(user_external::get_grade_items_returns(), $studentgrades);
// No warnings returned.
$this->assertCount(0, $studentgrades['warnings']);
@ -299,8 +304,8 @@ class externallib_test extends externallib_advanced_testcase {
$gradegrade->set_overridden(true);
$gradegrade->set_locked(1);
$studentgrades = gradereport_user_external::get_grade_items($course->id);
$studentgrades = \external_api::clean_returnvalue(gradereport_user_external::get_grade_items_returns(), $studentgrades);
$studentgrades = user_external::get_grade_items($course->id);
$studentgrades = \external_api::clean_returnvalue(user_external::get_grade_items_returns(), $studentgrades);
// No warnings returned.
$this->assertCount(0, $studentgrades['warnings']);
@ -332,8 +337,8 @@ class externallib_test extends externallib_advanced_testcase {
$this->setUser($student1);
$studentgrades = gradereport_user_external::get_grade_items($course->id, $student1->id);
$studentgrades = \external_api::clean_returnvalue(gradereport_user_external::get_grade_items_returns(), $studentgrades);
$studentgrades = user_external::get_grade_items($course->id, $student1->id);
$studentgrades = \external_api::clean_returnvalue(user_external::get_grade_items_returns(), $studentgrades);
// No warnings returned.
$this->assertCount(0, $studentgrades['warnings']);
@ -375,11 +380,13 @@ class externallib_test extends externallib_advanced_testcase {
$studentgrades['usergrades'][0]['gradeitems'][0]['idnumber']);
// Hide one grade for the user.
$gradegrade = new \grade_grade(array('userid' => $student1->id,
'itemid' => $studentgrades['usergrades'][0]['gradeitems'][0]['id']), true);
$gradegrade = new \grade_grade([
'userid' => $student1->id,
'itemid' => $studentgrades['usergrades'][0]['gradeitems'][0]['id']
], true);
$gradegrade->set_hidden(1);
$studentgrades = gradereport_user_external::get_grade_items($course->id, $student1->id);
$studentgrades = \external_api::clean_returnvalue(gradereport_user_external::get_grade_items_returns(), $studentgrades);
$studentgrades = user_external::get_grade_items($course->id, $student1->id);
$studentgrades = \external_api::clean_returnvalue(user_external::get_grade_items_returns(), $studentgrades);
// Check we get only the course final grade.
$this->assertCount(1, $studentgrades['usergrades']);

View File

@ -26,9 +26,7 @@ namespace gradereport_user\privacy;
defined('MOODLE_INTERNAL') || die();
use core_privacy\local\metadata\collection;
use core_privacy\local\request\writer;
use gradereport_user\privacy\provider;
/**
* Unit tests for the gradereport_user implementation of the privacy API.

View File

@ -17,7 +17,7 @@
namespace core_grades;
use grade_plugin_return;
use grade_report_user;
use gradereport_user\report\user as user_report;
defined('MOODLE_INTERNAL') || die();
@ -176,7 +176,7 @@ class reportuserlib_test extends \advanced_testcase {
private function create_report($course, $user, $coursecontext) {
$gpr = new grade_plugin_return(array('type' => 'report', 'plugin'=>'user', 'courseid' => $course->id, 'userid' => $user->id));
$report = new grade_report_user($course->id, $gpr, $coursecontext, $user->id);
$report = new user_report($course->id, $gpr, $coursecontext, $user->id);
return $report;
}