Leveraging the grade report lib.php
When I initially built a custom grade report, I looked at the user grade report as an example of how to build/access score averages and percentages of course completed figures.I opened grade/report/user/index.php and tried to determine how it was generating that nice user grade report, this one.
Eventually, I stopped on this line
$report = new grade_report_user($courseid, $gpr, $context, $userid);
This line is creating a new object grade_report_user and is passing in both the course and user id.
I found the grade_report_user class in the grade/report/user/lib.php file. It contains a constructor that seems to do all the work of calculating the grades for each user and course passed into it. In my report, I had to ensure I had created both the $context and $gpr variables to pass into the object constructor. I found both of these statements in the lib.php file and copied them into my custom file.
This is the code from the index.php file in my custom progress report.
$courseid = required_param('id', PARAM_INT);
$context = get_context_instance(CONTEXT_COURSE, $course->id);
$gpr = new grade_plugin_return(array('type'=>'report', 'plugin'=>'progress', 'courseid'=>$courseid, 'userid'=>$rec->userid));
$uObj = new grade_report_user($courseid, $gpr, $context, $rec->userid);
$uObj->setup_table();
$uObj->fill_table();
$tdata = $uObj->tabledata;
The setup_table and fill_table are public functions of the grade_report_user class. Using var_dump() liberally during this process on $context, $uObj, and $tdata was very helpful. The $rec->userid is provided by a query result that I am looping over while creating a grade_report_user object for each user. Like this:
$students = getStudents($courseid); //getStudents is a function I created
foreach($students as $rec){
$courseid = required_param('id', PARAM_INT); // course id
$context = get_context_instance(CONTEXT_COURSE, $course->id);
$gpr = new grade_plugin_return(array('type'=>'report', 'plugin'=>'progress', 'courseid'=>$courseid, 'userid'=>$rec->userid));
$uObj = new grade_report_user($courseid, $gpr, $context, $rec->userid); $uObj->setup_table();
$uObj->fill_table();
$tdata =
$uObj->tabledata;
.
.
.
}
I then created another smaller data structure to hold the two pieces of data for each student that I wanted
foreach($tdata as $i => $td){
//var_dump($tdata);
if($i === 1 ){
//var_dump($i);
$scores['grade'] = $td['percentage']['content'];
}elseif($i === 3){
//var_dump($td);
$scores['percentcomplete'] = $td['percentage']['content'];
}
}
Notice, continued use of var_dump()!
I then simply outputted the result like this:'.$scores['grade'].'
'.$scores['percentcomplete'].'
The end result is a progress report that lists all the course students current grade and % of course completed in a nice tidy summary format - where the score data is IDENTICAL to that of the more detailed user grade report!


great article james, this helped me a lot while trying to do something similar. my customer likes summary type information. moodle reports in so much detail, that it is overwhelming.... thanks for the pointer about using the grade/report/user/lib.php file. I knew there was a class somewhere, but was not sure where to look.
ReplyDeletebravo!
Do you know how moodle put the simbol (-) when no have calification?
ReplyDelete