Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

509 lines (419 sloc) 20.682 kb
<?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/>.
/**
* File in which the user_report class is defined.
* @package gradebook
*/
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);
/**
* Class providing an API for the user report building and displaying.
* @uses grade_report
* @package gradebook
*/
class grade_report_user extends grade_report {
/**
* The user.
* @var object $user
*/
var $user;
/**
* A flexitable to hold the data.
* @var object $table
*/
var $table;
var $gtree;
/**
* Flat structure similar to grade tree
*/
var $gseq;
/**
* show student ranks
*/
var $showrank;
/**
* show grade percentages
*/
var $showpercentage;
/**
* Show range
*/
var $showrange;
var $tableheaders;
var $tablecolumns;
var $maxdepth;
var $evenodd;
var $tabledata;
var $canviewhidden;
var $switch;
/**
* Show hidden items even when user does not have required cap
*/
var $showhiddenitems;
/**
* 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
*/
function grade_report_user($courseid, $gpr, $context, $userid) {
global $CFG;
parent::grade_report($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 = grade_get_setting($this->courseid, 'report_user_showtotalsifcontainhidden', $CFG->grade_report_user_showtotalsifcontainhidden);
//comment this out to hide the range column on the user report. Control of this via a setting was added to 2.0 (MDL-20617)
$this->showrange = true;
$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, false, !$CFG->enableoutcomes);
// 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();
$this->canviewhidden = has_capability('moodle/grade:viewhidden', get_context_instance(CONTEXT_COURSE, $this->courseid));
// get the user (for full name)
$this->user = get_record('user', 'id', $userid);
// base url for sorting by first/last name
$this->baseurl = $CFG->wwwroot.'/grade/report?id='.$courseid.'&amp;userid='.$userid;
$this->pbarurl = $this->baseurl;
// no groups on this report - rank is from all course users
$this->setup_table();
}
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) {
$count += $this->inject_rowspans($element['children'][$key]);
}
$element['rowspan'] = $count;
return $count;
}
/**
* Prepares the headers and attributes of the flexitable.
*/
function setup_table() {
global $CFG;
/*
* Table has 5-6 columns
*| itemname/description | final grade | percentage final grade | rank (optional) | feedback |
*/
// setting up table headers
$this->tablecolumns = array('itemname', 'grade');
$this->tableheaders = array($this->get_lang_string('gradeitem', 'grades'),
$this->get_lang_string('grade'));
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->showrank) {
// TODO: this is broken if hidden grades present!!
$this->tablecolumns[] = 'rank';
$this->tableheaders[] = $this->get_lang_string('rank', 'grades');
}
$this->tablecolumns[] = 'feedback';
$this->tableheaders[] = $this->get_lang_string('feedback', '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;
}
function fill_table_recursive(&$element) {
global $CFG;
$type = $element['type'];
$depth = $element['depth'];
$grade_object = $element['object'];
$eid = $grade_object->id;
$fullname = $this->gtree->get_element_header($element, true, true, true);
$data = array();
$hidden = '';
$excluded = '';
$class = '';
// 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') {
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 = ' hidden';
}
// 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()))) {
// return false;
} else {
/// Excluded Item
if ($grade_grade->is_excluded()) {
$fullname .= ' ['.get_string('excluded', 'grades').']';
$excluded = ' excluded';
}
/// 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";
}
/// Name
$data['itemname']['content'] = $fullname;
$data['itemname']['class'] = $class;
$data['itemname']['colspan'] = ($this->maxdepth - $depth);
/// Actual Grade
$gradeval = $grade_grade->finalgrade;
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')));
} elseif ($grade_grade->is_hidden()) {
$data['grade']['class'] = $class.' hidden';
$data['grade']['content'] = '-';
} else {
$data['grade']['class'] = $class;
$gradeval = $this->blank_hidden_total($this->courseid, $grade_grade->grade_item, $gradeval);
$data['grade']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true);
}
/// Percentage
if ($this->showpercentage) {
if ($grade_grade->grade_item->needsupdate) {
$data['percentage']['class'] = $class.' gradingerror';
$data['percentage']['content'] = get_string('error');
} elseif ($grade_grade->is_hidden()) {
$data['percentage']['class'] = $class.' hidden';
$data['percentage']['content'] = '-';
} else {
$data['percentage']['class'] = $class;
$data['percentage']['content'] = grade_format_gradevalue($gradeval, $grade_grade->grade_item, true, GRADE_DISPLAY_TYPE_PERCENTAGE);
}
}
/// Rank
if ($this->showrank) {
// TODO: this is broken if hidden grades present!!
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.' hidden';
$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 {$CFG->prefix}grade_grades
WHERE finalgrade > {$gradeval}
AND itemid = {$grade_grade->grade_item->id}";
$rank = count_records_sql($sql) + 1;
$data['rank']['class'] = $class;
$data['rank']['content'] = "$rank/".$this->get_numusers(false); // total course users
}
}
/// Feedback
if (empty($grade_grade->feedback) or (!$this->canviewhidden and $grade_grade->is_hidden())) {
$data['feedback']['class'] = $class.' feedbacktext';
$data['feedback']['content'] = '&nbsp;';
} else {
$data['feedback']['class'] = $class.' feedbacktext';
$data['feedback']['content'] = format_text($grade_grade->feedback, $grade_grade->feedbackformat);
}
/// Range
if ($this->showrange) {
$data['range']['class'] = $class;
$data['range']['content'] = $grade_grade->grade_item->get_formatted_range();
}
}
}
/// 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;
}
/// Add this row to the overall system
$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]);
}
}
}
/**
* 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
*/
function print_table($return=false) {
$maxspan = $this->maxdepth;
/// Build table structure
$html = "
<table cellspacing='0' cellpadding='0' class='boxaligncenter generaltable user-grade'>
<thead>
<tr>
<th class=\"header\" colspan='$maxspan'>".$this->tableheaders[0]."</th>\n";
for ($i = 1; $i < count($this->tableheaders); $i++) {
$html .= "<th class=\"header\">".$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;
if (isset($content)) {
$html .= "<td class='$class' $colspan>$content</td>\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 grade_report_user_settings_definition(&$mform) {
global $CFG;
$options = array(-1 => get_string('default', 'grades'),
0 => get_string('hide'),
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->setHelpButton('report_user_showrank', array('showrank', get_string('showrank', 'grades'), 'grade'));
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->setHelpButton('report_user_showpercentage', array('showpercentage', get_string('showpercentage', 'grades'), 'grade'));
$options = array(-1 => get_string('default', 'grades'),
0 => get_string('shownohidden', 'grades'),
1 => get_string('showhiddenuntilonly', '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->setHelpButton('report_user_showhiddenitems', array('showhiddenitems', get_string('showhiddenitems', 'grades'), 'grade'));
//showtotalsifcontainhidden
$options = array(-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') );
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->setHelpButton('report_user_showtotalsifcontainhidden', array('hidetotalifhiddenitems', get_string('hidetotalifhiddenitems', 'grades'), 'grade'));
}
function grade_report_user_profilereport($course, $user) {
if (!empty($course->showgrades)) {
$context = get_context_instance(CONTEXT_COURSE, $course->id);
//first make sure we have proper final grades - this must be done before constructing of the grade tree
grade_regrade_final_grades($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);
// print the page
echo '<div class="grade-report-user">'; // css fix to share styles with real report page
print_heading(get_string('modulename', 'gradereport_user'). ' - '.fullname($report->user));
if ($report->fill_table()) {
echo $report->print_table(true);
}
echo '</div>';
}
}
?>
Jump to Line
Something went wrong with that request. Please try again.