Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Ratings 2.0: Difference between revisions

From MoodleDocs
No edit summary
No edit summary
Line 22: Line 22:


MDL-20514 Allow Aggregate Type in Glossary Activity
MDL-20514 Allow Aggregate Type in Glossary Activity
==Interface==
[[Image:RatingUI.gif]]
When Javascript is enabled ajax submission means the button can be removed. In the future it would be possible to automatically interpret a 1 to 5 rating as a star rating style UI element.
If the user has 'post' permission as returned by modname_rating_permissions() the dropdown box and submission button will be displayed.
If the user has 'view' permissions the text to the left of the dropdown box will be displayed. The displayed text consists of the aggregate of the ratings, 4 out of 5 in the example. The number in brackets is the number of ratings that have been submitted. There have been two ratings submitted in the example.
If the user has 'viewall' permissions they can click on the aggregate summary to view a list of all of the ratings that have been submitted. This is a listing of each user's profile pic, their name and the rating they submitted.


==Database changes==
==Database changes==
Line 393: Line 406:
}
}
</code>
</code>
==Interface==
[[Image:RatingUI.gif]]
When Javascript is enabled ajax submission means the button can be removed. In the future it would be possible to automatically interpret a 1 to 5 rating as a star rating style UI element.
If the user has 'post' permission as returned by modname_rating_permissions() the dropdown box and submission button will be displayed.
If the user has 'view' permissions the text to the left of the dropdown box will be displayed. The displayed text consists of the aggregate of the ratings, 4 out of 5 in the example. The number in brackets is the number of ratings that have been submitted. There have been two ratings submitted in the example.
If the user has 'viewall' permissions they can click on the aggregate summary to view a list of all of the ratings that have been submitted. This is a listing of each user's profile pic, their name and the rating they submitted.

Revision as of 07:24, 18 February 2010

Objectives

Ratings are grades entered away from the gradebook. They can be entered by students and teachers and are aggregated into grades.

The goals of ratings 2.0:

  • Manage ratings centrally
  • Use a consistent approach for all ratings throughout Moodle
  • Easily integrate ratings 2.0 with existing modules
  • Remove duplicate implementations of ratings functionality

Overview

The ratings 2.0 provides APIs to:

  1. Add ratings
  2. Update ratings
  3. Access collected ratings for grade calculation purposes
  4. Delete ratings

Current tracker issues

MDL-21389 Write spec for separate Ratings 2.0

MDL-20514 Allow Aggregate Type in Glossary Activity

Interface

RatingUI.gif

When Javascript is enabled ajax submission means the button can be removed. In the future it would be possible to automatically interpret a 1 to 5 rating as a star rating style UI element.

If the user has 'post' permission as returned by modname_rating_permissions() the dropdown box and submission button will be displayed.

If the user has 'view' permissions the text to the left of the dropdown box will be displayed. The displayed text consists of the aggregate of the ratings, 4 out of 5 in the example. The number in brackets is the number of ratings that have been submitted. There have been two ratings submitted in the example.

If the user has 'viewall' permissions they can click on the aggregate summary to view a list of all of the ratings that have been submitted. This is a listing of each user's profile pic, their name and the rating they submitted.


Database changes

New tables

Ratings

Field Type Default Info
id int(10) auto-incrementing The unique ID for this comment.
contextid int(10) The context id defined in context table - identifies the instance of plugin owning the comment.
itemid int(10) Some plugin specific item id (eg. forum post blog entry)
scaleid int(10) ID of the scale (1-5, 0-100, custom) from which the user selected their rating. Including this allows smarter handling of previously entered ratings should the scales be changed.
rating int(10) The user's rating
userid int(10) The user who submitted the rating
timecreated int(10)
timemodified int(10)

Altered tables

The forum, glossary and data tables need to be altered to contain the required fields specificed in [1]

Removed database tables

The following tables will have their data migrated to the above ratings table and then be removed:

data_ratings

forum_ratings

glossary_ratings

Scales

Course modules will continue to store the scale associated with their ratings. For example the glossary table has a scale column.

Scales are going to be refactored as part of a separate issue. See MDL-17258.

Ratings code changes

lib/ratinglib.php will contain...

class rating

__construct($contextid, $itemid, $scaleid, $userid)

Initialize a class instance.

update_rating($rating)

Add rating to database

get_rating()

get the rating

delete_rating()

delete the rating

render_rating($page = null)

Load the rating renderer and use it to output this rating's UI. See Rating Submission for required fields.

static ratings_load_ratings($contextid, $aggregate='AVG', $items, $userid = null)

Returns an result set of ratings including aggregated ratings. $items is an array of objects with an id member variable ie $items[0]->id.

function ratings_load_ratings($contextid, $aggregate='AVG', $items, $userid = null) {

global $DB, $USER;

   if (isnull($userid)) {
       $userid = $USER->id;
   }
   $itemids = array();
   foreach($items as $item) {
       $itemids[] = $item->id;
   }

   list($itemidtest, $params) = $DB->get_in_or_equal(
           $itemids, SQL_PARAMS_NAMED, 'itemid0000');

   $sql = <<<ENDSQL

SELECT r.itemid,

   $aggregate(r.rating) AS aggrrating,
   COUNT(r.rating) AS numratings,
   ur.rating AS usersrating

FROM {ratings} r LEFT JOIN {ratings} ur ON ur.contextid = r.contextid AND

       ur.itemid = r.itemid AND
       ur.userid = :userid

WHERE

   r.contextid = :contextid AND
   r.itemid $itemidtest AND

GROUP BY r.itemid, ur.rating ENDSQL;

   $params['userid'] = $userid;
   $params['contextid'] = $context->id;

   return $DB->get_records_sql($sql, $params);

}

static make_rating_subobjs($posts,$ratings)

Similar to make_context_subobj(). Iterate over forum $posts (forum posts, glossary items etc) and create $post->rating, $post->rating->aggregate and $post->rating->count.

Ratings renderer

Located in mod/ratings/renderer.php the new class core_rating_renderer should extend plugin_renderer_base defined in lib/outputrenderers.php Almost all renderers appear to inherit from plugin_renderer_base rather than core_renderer.

core_rating_renderer::render_rating($rating)

returns rating UI html snippet. Used to include ratings in pages.

Using the rating renderer

The process to render ratings is as follows:

// in mod/forum/discuss.php (for example) $posts = // Some forum/lib.php function call.

//The current scaleid comes from the forum or glossary object and may be changed at any time so supply it each time //Also, a user should only see their own ratings $ratings = Rating->ratings_load_ratings($contextid, $aggregate, $posts/* Optional array of items (forum posts or glossary items) with an 'id' property. If null returns all ratings for the context by the user*/, $userid); //Or, just return all ratings for the given context. $ratings = Rating->ratings_load_ratings($contextid, $aggregate);

//Iterate over the posts and converts the result set into objects //$post->rating, $post->rating->aggregate and $post->rating->count //Similar to make_context_subobj(). $posts = Rating->make_rating_subobjs($posts,$ratings);

foreach ($posts as $postid => $post) {

   $forumoutput->post($post);//access the rating info at $post->rating, $post->rating->aggregate and $post->rating->count

}

$permissions = forum_rating_permission();//implemented by the module. returns array('view'=>true/false,'post'=>true/false) $scaleid = //load scale id from forum or glossary

// in mod/forum/renderer.php, in the post(post, $rating) method:

// ... output most of the post ... starts around line 5813 of mod/forum/lib.php echo $post->rating->render_rating($this->page,$permissions,$scaleid); // ... output the rest.


// and finally in rating/lib.php in the Rating class:

public function Rating::render_rating($page = null, $permissions=null,$scaleid) {

   if (is_null($page) {
       global $PAGE;
       $page = $PAGE;
   }
   $ratingoutput = $page->get_renderer('core', 'rating');
   return $ratingoutput->render_rating($this,$permissions,$scaleid);

}

Ratings Aggregation

Forums currently support multiple forms of rating aggregation such as average, maximum, sum etc. These options should be available everywhere that ratings are available.

They are calculated within ratings_load_ratings()

Ratings Settings

Settings for ratings are stored by the module. Each module table, for example forum, must contain the following columns.

Field Type Default Info
aggregation int(10) The aggregation method to apply. Currently this is stored in the assessed column in the table "forum".
allcanrate int(10) Allow anyone to rate items. Currently this is stored in the assessed column in the table "glossary".
assesstimestart int(10) From when can users submit ratings
assesstimefinish int(10) When must users submit ratings by
scale int(10) What scale to use

Where is the "Restrict ratings to posts with dates in this range:" flag stored?

Settings interface

moodleform_mod::standard_coursemodule_elements()

Adds elements to an instance of moodle form. The ratings elements should appear in a separate block from Common Module Settings.

It will determine whether to include ratings settings by calling plugin_supports() found in lib/moodlelib.php like this... if (plugin_supports('mod', $mod, FEATURE_MOD_RATINGS, false)) {

   //include ratings elements

}

mod/%modulename%/lib.php defines a function called %modulename%_supports() that lists the elements that the module supports.

FEATURE_MOD_RATINGS will have to be added to lib/moodlelib.php

Rating Submission

lib/rating.php will be the target for posted ratings. Currently each module implements their own ratings submission. For example mod/glossary/rate.php within the glossary module.

The supplied fields should consist of

Field Type Default Info
contextid PARAM_INT The context id defined in context table - identifies the instance of plugin owning the comment.
itemid PARAM_INT Some plugin specific item id (eg. forum post blog entry)
scaleid PARAM_INT ID of the scale (1-5, 0-100, custom) from which the user selected their rating. Including this allows smarter handling of scales being changed.
rating PARAM_INT for example, in user profile, you can comment user's description or interests, but they share the same itemid(==userid), we need comment_area to separate them
userid PARAM_INT who wrote this comment
returnurl PARAM_LOCALURL Null for ajax requests. If not null the url to which the user should be redirected after recording the rating

The process to record a rating is as follows:

$permissions = forum_rating_permission(); if($permissions['post']) { $rating = N; //the actual rating from the user $ratingObj = new Rating($contextid, $scaleid, $userid, array($itemid)); $ratingObj->set_rating($rating); //redirect to return url if supplied }

//within the class Rating function Rating::set_rating($rating) { $ratings = rating_system::load_ratings($scaleid, $userid, $contextid, array($itemid)); if( !$ratings || sizeof($ratings)==0) { $data->contextid = $this->contextid; $data->scaleid = $this->scaleid; $data->userid = $this->userid; $data->rating = $rating; $DB->insert_record($this->table, $data); } else { $data->id = $this->id; $data->rating = $rating; $DB->update_record($this->table, $data); }

}

Ajax submission

Ajax submission of ratings must be possible for sites with ajax enabled. ForumNG (http://moodle.org/mod/data/view.php?d=13&rid=2927) written by Sam Marshall contains an ajax implementation of the rating UI elements that may be useful to reference.

Check if ajax is enabled like this... if (empty($CFG->enableajax)) {

   //no ajax

} else {

   //add ajax stuff

}

Permissions

Permission could be handled in one of two ways.

Module callback

This allows modules to individually control ratings so, for example, the user may be able to rate forum posts but not glossary items.

modname_rating_permissions()

Modules can implement a function named modname_rating_permissions to control post and view permission. This is called prior to rendering a set of ratings. It is also called by lib/rating.php when it receives and ajax rating submission.

This function will return an array: array('view'=>true, 'viewall'=>true, post'=>true)

This example shows how this would work for the forum module function forum_rating_permissions() { $context = get_context_instance(CONTEXT_MODULE, $this->cm->id); return array('view'=>has_capability('mod/forum:viewrating',$context), 'viewall'=>has_capability('mod/forum:viewanyrating',$context), 'post'=>has_capability('mod/forum:rate',$context)); }

Centralized ratings permissions

Control the ratings related permissions within the ratings module itself. This would allow less fine grained control but makes adding ratings to new areas of Moodle much less invasive.

As each module currently has its own ratings permissions migrating to single set of rating permissions could be tricky. What should happen if a user has viewall permissions in the forums but not in the glossary for example.

Rating::get_ratings_permissions()

static function get_rating_permissions() { $context = get_context_instance(CONTEXT_MODULE, $this->cm->id); return array('view'=>has_capability('moodle/site:ratingview',$context), 'viewall'=>has_capability('moodle/site:ratingviewall',$context), 'post'=>has_capability('moodle/site:ratingrate',$context)); }