Development:Gradebook Report Tutorial: Difference between revisions
(Adding "see also" section) |
|||
Line 39: | Line 39: | ||
grade/report/[newreport]/index.php | grade/report/[newreport]/index.php | ||
6.Create a language file for your report. Include at least the modulename, and optionally the strings for different capabilities. | 6.Create a language file for your report. Include at least the modulename, and optionally the strings for different capabilities. | ||
lang/en_utf8/gradereport_[newreport].php | grade/report/[newreport]/lang/en_utf8/gradereport_[newreport].php | ||
Example from user report here: | Example from user report here: |
Revision as of 12:22, 10 August 2007
Introduction
One of the great features of the new gradebook implementation in Moodle 1.9 is the support for plug-in reports. A few reports are already included in the release, but it is fast and easy to create new reports of any kind.
This page is a small tutorial on how to create a new report for the Moodle gradebook. The first section highlights the basic setup steps, the bare minimum to get your plug-in detected and usable. The second section gives an example of a possible implementation, although you are free to develop outside of these suggestions.
Bare minimum
These steps all involve creating new files, but in all cases they can be copy-pasted from existing reports, to make your life easier.
1. Create a new folder under grade/report
grade/report/[newreport]
2. Create a /db sub-folder under the new report folder
grade/report/[newreport]/db
3. Create an access.php file in the db folder with the following content. You should change the capabilities as needed.
grade/report/[newreport]/db/access.php <?php $gradereport_[newreport]_capabilities = array( 'gradereport/[newreport]:view' => array( 'riskbitmask' => RISK_PERSONAL, 'captype' => 'read', 'contextlevel' => CONTEXT_COURSE, 'legacy' => array( 'student' => CAP_ALLOW, 'teacher' => CAP_ALLOW, 'editingteacher' => CAP_ALLOW, 'admin' => CAP_ALLOW ) ), ); ?>
4. Create a version.php file with the current dates:
grade/report/[newreport]/version.php <?php $plugin->version = 2007081000; $plugin->requires = 2007081000; ?>
5.Create an index.php
grade/report/[newreport]/index.php
6.Create a language file for your report. Include at least the modulename, and optionally the strings for different capabilities.
grade/report/[newreport]/lang/en_utf8/gradereport_[newreport].php Example from user report here: $string['modulename'] = 'User report'; $string['user:view'] = 'View your own grade report';
You do not need to create a new link to your report, it will be automatically detected and added to the gradebook plugin drop-down menu, if you've followed all these steps!
This is all you need to do to create a new report! Now, of course, you'll want the code to actually DO something, usually fetch and display some data. The next section discusses one easy approach using flexitable.
Extending the grade_report class
You are free to develop that class any way you want, but by using the existing methods set up in grade_report, you can avoid tedious repetition of code. We use flexitable for simple reports, as you can see in the user report (grade_report_user class). The rest of this tutorial will follow the path of flexitable.
New file
- Create a lib.php file (or copy it from other report).
grade/report/[newreport]/lib.php
- The lib.php contains an extension of the grade_report class, and should be named
grade_report_[newreport]
Grade_report class variables
The grade_report class makes the following variables available to your new class, if you use its constructor in your child class' constructor:
courseid : Required by constructor gpr : Grade plugin return tracking object, required by constructor context : Required by constructor gtree : The grade_tree must be instantiated in child classes: not all reports need the whole tree prefs : Array of user preferences related to this report. Methods are given to get and set these easily gradebookroles : The roles for this report, pulled out of $CFG->gradebookroles baseurl : Base url for sorting by first/last name (not needed by all reports) pbarurl : Base url for paging page : Current page (for paging). Must be given to constructor if paging is required. lang_strings : Array of cached language strings (using get_string() all the time takes a long time!). A method is provided to replace get_string() and use this cache currentgroup : The current group being displayed. group_selector : A HTML select element used to select the current group. groupsql : An SQL fragment used to add linking information to the group tables. groupwheresql : An SQL constraint to append to the queries used by this object to build the report.
Grade_report class methods
The grade_report class has the following methods which you can use, provided the right steps have been taken to initialise the object first:
get_pref() : Given the name of a user preference (without grade_report_ prefix), locally saves then returns the value of that preference. If the preference has already been fetched before, the saved value is returned. If the preference is not set at the User level, the $CFG equivalent is given (site default). set_pref() : Uses set_user_preferences() to update the value of a user preference. If 'default' is given as the value, the preference will be removed in favour of a higher-level preference ($CFG->$pref_name usually) process_data() : Abstract method, needs to be implemented by child classes if they want to handle user form submissions on the report process_action() : Abstract method, needs to be implemented by child classes if they want to handle user actions on the report get_grade_clean() : format grade using lang specific decimal point and thousand separator the result is suitable for printing on html page format_grade() : Given a user input grade, format it to standard format i.e. no thousand separator, and . as decimal point get_lang_string() : First checks the cached language strings, then returns match if found, or uses get_string(). Use this for any lang_strings in the grades.php file. grade_to_percentage() : Computes then returns the percentage value of the grade value within the given range. get_grade_letters() : Fetches and returns an array of grade letters indexed by their grade boundaries, as stored in preferences. get_numusers() : Fetches and returns a count of all the users that will be shown on this page. setup_groups() : Sets up this object's group variables, mainly to restrict the selection of users to display. get_sort_arrow() : Returns an arrow icon inside an <a> tag, for the purpose of sorting a column. get_module_link() : Builds and returns a HTML link to the grade or view page of the module given. If no itemmodule is given, only the name of the category/item is returned, no link.
Report child class
Assuming you are using flexitable, your child class needs the following variable and methods:
$table : The flexitable that will hold the data
- grade_report_[newreport]() : Constructor. You can set up anything here, but you must call the parent constructor with the 3 required params:
parent::grade_report($COURSE->id, $gpr, $context); The $gpr and $context variables are normally set up in grade/report/[newreport]/index.php
- setup_table() : Prepares the headers and attributes of the flexitable. Example used for the very simple overview report:
// setting up table headers $tablecolumns = array('coursename', 'grade', 'rank'); $tableheaders = array($this->get_lang_string('coursename', 'grades'), $this->get_lang_string('grade'), $this->get_lang_string('rank', 'grades')); $this->table = new flexible_table('grade-report-overview-'.$this->user->id); $this->table->define_columns($tablecolumns); $this->table->define_headers($tableheaders); $this->table->define_baseurl($this->baseurl); $this->table->set_attribute('cellspacing', '0'); $this->table->set_attribute('id', 'overview-grade'); $this->table->set_attribute('class', 'boxaligncenter generaltable'); $this->table->setup();
- fill_table() : After setup_table(), gathers and enters the data in the table. Again, from the overview report:
global $CFG; $numusers = $this->get_numusers(); if ($courses = get_courses('all', null, 'c.id, c.shortname')) { foreach ($courses as $course) { // Get course grade_item $grade_item_id = get_field('grade_items', 'id', 'itemtype', 'course', 'courseid', $course->id); // Get the grade $finalgrade = get_field('grade_grades', 'finalgrade', 'itemid', $grade_item_id, 'userid', $this->user->id); /// prints rank if ($finalgrade) { /// find the number of users with a higher grade $sql = "SELECT COUNT(DISTINCT(userid)) FROM {$CFG->prefix}grade_grades WHERE finalgrade > $finalgrade AND itemid = $grade_item_id"; $rank = count_records_sql($sql) + 1; $rankdata = "$rank/$numusers"; } else { // no grade, no rank $rankdata = "-"; } $this->table->add_data(array($course->shortname, $finalgrade, $rankdata)); } return true; } else { notify(get_string('nocourses', 'grades')); return false; }
- print_table() : Just does what its name says...
ob_start(); $this->table->print_html(); $html = ob_get_clean(); if ($return) { return $html; } else { echo $html; }
- process_data() and process_action() : You can implement these two methods if you need to handle data and actions.
Set up the index.php file. Here is the simple example from the overview report.
require '../../config.php'; $courseid = required_param('id', PARAM_INT); /// basic access checks if (!$course = get_record('course', 'id', $courseid)) { print_error('nocourseid'); } require_login($course); $context = get_context_instance(CONTEXT_COURSE, $course->id); /// find all accessible reports if ($reports = get_list_of_plugins('grade/report', 'CVS')) { // Get all installed reports foreach ($reports as $key => $plugin) { // Remove ones we can't see if (!has_capability('gradereport/'.$plugin.':view', $context)) { unset($reports[$key]); } } } if (empty($reports)) { error('No reports accessible', $CFG->wwwroot.'/course/view.php:id='.$course->id); // TODO: localize } if (!isset($USER->grade_last_report)) { $USER->grade_last_report = array(); } if (!empty($USER->grade_last_report[$course->id])) { $last = $USER->grade_last_report[$course->id]; } else { $last = null; } if (!in_array($last, $reports)) { $last = null; } if (empty($last)) { if (in_array('grader', $reports)) { $last = 'grader'; } else if (in_array('user', $reports)) { $last = 'user'; } else { $last = reset($reports); } } //redirect to last or guessed report redirect($CFG->wwwroot.'/grade/report/'.$last.'/index.php?id='.$course->id);
Conclusion
This short tutorial doesn't explain how to actually create a useful report. That part is essentially up to you, and there are no hard rules about how to do it. Instead, this tutorial explains how to setup a "stub" report, a basic framework with a set of tools and variables you can use to create a fully functional and essential report for your Moodle needs. Please share your report-building experiences and tribulations with the Moodle community through the forum.
See also
- Gradebook Development ideas forum discussion
- Using Moodle New gradebook for Moodle forum discussion
- Development:Grades