Skip to content

Commit

Permalink
rating MDL-21657 started making ratings API more like comments and sp…
Browse files Browse the repository at this point in the history
…lit rate.php into rate.php and rate_ajax.php
  • Loading branch information
Andrew Davis committed Mar 19, 2010
1 parent 1c5517a commit b1721f6
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 91 deletions.
7 changes: 4 additions & 3 deletions lib/outputrenderers.php
Original file line number Diff line number Diff line change
Expand Up @@ -1237,7 +1237,10 @@ function render_rating(rating $rating) {
global $CFG, $USER;
static $havesetupjavascript = false;

if( !$havesetupjavascript && !empty($CFG->enableajax) ) {
$useajax = !empty($CFG->enableajax);

//include required Javascript
if( !$havesetupjavascript && $useajax ) {
$this->page->requires->js_init_call('M.core_ratings.init');
$havesetupjavascript = true;
}
Expand Down Expand Up @@ -1325,8 +1328,6 @@ function render_rating(rating $rating) {
//output submit button
$strratings .= '<span class="ratingsubmit"><input type="submit" class="postratingmenusubmit" id="postratingsubmit'.$rating->itemid.'" value="'.s(get_string('rate', 'rating')).'" />';

//ajax code is included by rating::load_ratings()

if ( is_array($rating->settings->scale) ) {
//todo andrew where can we get the course id from?
//$strratings .= $this->help_icon_scale($course->id, $scale);
Expand Down
6 changes: 5 additions & 1 deletion rating/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@
echo $OUTPUT->header();

//if (!$ratings = forum_get_ratings($post->id, $sqlsort)) {
$ratings = rating::load_ratings_for_item($context, $itemid, $sort);
$ratingoptions = new stdclass();
$ratingoptions->context = $context;
$ratingoptions->itemid = $itemid;
$ratingoptions->sort = $sort;
$ratings = rating::load_ratings_for_item($ratingoptions);
if (!$ratings) {
//print_error('noresult', 'forum', '', format_string($post->subject));
print_error('noresult');
Expand Down
116 changes: 69 additions & 47 deletions rating/lib.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,16 +75,18 @@ class rating implements renderable {

/**
* Constructor.
* @param context $context the current context object
* @param int $itemid the id of the associated item (forum post, glossary item etc)
* @param int $scaleid the scale to use
* @param int $userid the user submitting the rating
* @param object $options {
* context => context context to use for the rating [required]
* itemid => int the id of the associated item (forum post, glossary item etc) [required]
* scaleid => int The scale in use when the rating was submitted [required]
* userid => int The id of the user who submitted the rating [required]
* }
*/
public function __construct($context, $itemid, $scaleid, $userid) {
$this->context = $context;
$this->itemid = $itemid;
$this->scaleid = $scaleid;
$this->userid = $userid;
public function __construct($options) {
$this->context = $options->context;
$this->itemid = $options->itemid;
$this->scaleid = $options->scaleid;
$this->userid = $options->userid;
}

/**
Expand All @@ -102,7 +104,13 @@ public function update_rating($rating) {
$item->id = $this->itemid;
$items = array($item);

$items = rating::load_ratings($this->context, $items, null, $this->scaleid, $this->userid);
$ratingoptions = new stdclass();
$ratingoptions->context = $this->context;
$ratingoptions->items = $items;
$ratingoptions->aggregate = RATING_AGGREGATE_AVERAGE;//we dont actually care what aggregation is applied
$ratingoptions->scaleid = $this->scaleid;
$ratingoptions->userid = $this->userid;
$items = rating::load_ratings($ratingoptions);
if( !isset($items[0]->rating) || !isset($items[0]->rating->id) ) {
$data->contextid = $this->context->id;
$data->rating = $rating;
Expand Down Expand Up @@ -172,13 +180,15 @@ public static function get_aggregation_method($aggregate) {

/**
* Static method that returns an array of ratings for a given item (forum post, glossary entry etc)
* This returns all users ratings for a single item
* @param context $context the context in which the rating exists
* @param int $itemid The id of the forum posts, glossary items or whatever
* @param string SQL sort by clause
* This returns all users ratings for a single item
* @param object $options {
* context => context the context in which the ratings exists [required]
* itemid => int the id of the associated item (forum post, glossary item etc) [required]
* sort => string SQL sort by clause [optional]
* }
* @return array an array of ratings
*/
public static function load_ratings_for_item($context, $itemid, $sort) {
public static function load_ratings_for_item($options) {
global $DB;

$userfields = user_picture::fields('u','uid');
Expand All @@ -188,41 +198,42 @@ public static function load_ratings_for_item($context, $itemid, $sort) {
LEFT JOIN {user} u ON r.userid = u.id
WHERE r.contextid = :contextid AND
r.itemid = :itemid
$sort";
{$options->sort}";

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

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

/**
* Static method that adds rating objects to an array of items (forum posts, glossary entries etc)
* Rating objects are available at $item->rating
* @param context $context the current context object
* @param array $items an array of items such as forum posts or glossary items. They must have an 'id' member ie $items[0]->id
* @param int $aggregate what aggregation method should be applied. AVG, MAX etc
* @param int $scaleid the scale from which the user can select a rating
* @param int $userid the id of the current user
* @param string $returnurl the url to return the user to after submitting a rating. Can be left null for ajax requests.
* @param object $options {
* context => context the context in which the ratings exists [required]
* items => array an array of items such as forum posts or glossary items. They must have an 'id' member ie $items[0]->id[required]
* aggregate => int what aggregation method should be applied. RATING_AGGREGATE_AVERAGE, RATING_AGGREGATE_MAXIMUM etc [required]
* scaleid => int the scale from which the user can select a rating [required]
* userid => int the id of the current user [optional]
* returnurl => string the url to return the user to after submitting a rating. Can be left null for ajax requests [optional]
* @return array the array of items with their ratings attached at $items[0]->rating
*/
public static function load_ratings($context, $items, $aggregate=RATING_AGGREGATE_AVERAGE, $scaleid=RATING_DEFAULT_SCALE, $userid = null, $returnurl = null) {
public static function load_ratings($options) {
global $DB, $USER, $PAGE, $CFG;

if(empty($items)) {
return $items;
if(empty($options->items)) {
return $options->items;
}

if (is_null($userid)) {
if (is_null($options->userid)) {
$userid = $USER->id;
}

$aggregatestr = rating::get_aggregation_method($aggregate);
$aggregatestr = rating::get_aggregation_method($options->aggregate);

//create an array of item ids
$itemids = array();
foreach($items as $item) {
foreach($options->items as $item) {
$itemids[] = $item->id;
}

Expand All @@ -244,8 +255,8 @@ public static function load_ratings($context, $items, $aggregate=RATING_AGGREGAT
GROUP BY r.itemid, ur.rating
ORDER BY r.itemid";

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

$ratingsrecords = $DB->get_records_sql($sql, $params);

Expand All @@ -255,8 +266,8 @@ public static function load_ratings($context, $items, $aggregate=RATING_AGGREGAT

//we could look for a scale id on each item to allow each item to use a different scale

if($scaleid < 0 ) { //if its a scale (not numeric)
$scalerecord = $DB->get_record('scale', array('id' => -$scaleid));
if($options->scaleid < 0 ) { //if its a scale (not numeric)
$scalerecord = $DB->get_record('scale', array('id' => -$options->scaleid));
if ($scalerecord) {
$scaleobj->scaleitems = explode(',', $scalerecord->scale);
$scaleobj->id = $scalerecord->id;
Expand All @@ -266,33 +277,41 @@ public static function load_ratings($context, $items, $aggregate=RATING_AGGREGAT
}
}
else { //its numeric
$scaleobj->scaleitems = $scaleid;
$scaleobj->id = $scaleid;
$scaleobj->scaleitems = $options->scaleid;
$scaleobj->id = $options->scaleid;
$scaleobj->name = null;

$scalemax = $scaleid;
$scalemax = $options->scaleid;
}

//should $settings and $settings->permissions be declared as proper classes?
$settings = new stdclass(); //settings that are common to all ratings objects in this context
$settings->scale = $scaleobj; //the scale to use now
$settings->aggregationmethod = $aggregate;
$settings->returnurl = $returnurl;
$settings->aggregationmethod = $options->aggregate;
if( !empty($options->returnurl) ) {
$settings->returnurl = $options->returnurl;
}

$settings->permissions = new stdclass();
$settings->permissions->canview = has_capability('moodle/rating:view',$context);
$settings->permissions->canviewall = has_capability('moodle/rating:viewall',$context);
$settings->permissions->canrate = has_capability('moodle/rating:rate',$context);
$settings->permissions->canview = has_capability('moodle/rating:view',$options->context);
$settings->permissions->canviewall = has_capability('moodle/rating:viewall',$options->context);
$settings->permissions->canrate = has_capability('moodle/rating:rate',$options->context);

$rating = null;
foreach($items as $item) {
$ratingoptions = new stdclass();
$ratingoptions->context = $options->context;//context is common to all ratings in the set
foreach($options->items as $item) {
$rating = null;
//match the item with its corresponding rating
foreach($ratingsrecords as $rec) {
if( $item->id==$rec->itemid ) {
//Note: rec->scaleid = the id of scale at the time the rating was submitted
//may be different from the current scale id
$rating = new rating($context, $item->id, $rec->scaleid, $rec->userid);
$ratingoptions->itemid = $item->id;
$ratingoptions->scaleid = $rec->scaleid;
$ratingoptions->userid = $rec->userid;

$rating = new rating($ratingoptions);
$rating->id = $rec->id; //unset($rec->id);
$rating->aggregate = $rec->aggrrating; //unset($rec->aggrrating);
$rating->count = $rec->numratings; //unset($rec->numratings);
Expand All @@ -302,8 +321,11 @@ public static function load_ratings($context, $items, $aggregate=RATING_AGGREGAT
}
//if there are no ratings for this item
if( !$rating ) {
$scaleid = $userid = null;
$rating = new rating($context, $item->id, $scaleid, $userid);
$ratingoptions->itemid = $item->id;
$ratingoptions->scaleid = null;
$ratingoptions->userid = null;

$rating = new rating($ratingoptions);
$rating->id = null;
$rating->aggregate = null;
$rating->count = 0;
Expand All @@ -325,6 +347,6 @@ public static function load_ratings($context, $items, $aggregate=RATING_AGGREGAT
$rating->rating = $scalemax;
}
}
return $items;
return $options->items;
}
} //end rating class definition
2 changes: 1 addition & 1 deletion rating/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ M.core_ratings={
}

this.Y.io.queue.stop();
this.transaction.push({transaction:this.Y.io.queue(M.cfg.wwwroot+'/rating/rate.php', {
this.transaction.push({transaction:this.Y.io.queue(M.cfg.wwwroot+'/rating/rate_ajax.php', {
method : 'POST',
data : build_querystring(thedata),
on : {
Expand Down
53 changes: 14 additions & 39 deletions rating/rate.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,9 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.

/**
* This page receives rating submissions
* This page receives non-ajax rating submissions
*
* This page can be the target for either ajax or non-ajax rating submissions.
* If a return url is supplied the request is presumed to be a non-ajax request so a page
* is returned.
* If there is no return url the request is presumed to be ajax so a json response is returned.
* It is similar to rate_ajax.php. Unlike rate_ajax.php a return url is required.
*
* @package moodlecore
* @copyright 2010 Andrew Davis
Expand All @@ -35,29 +32,17 @@
$itemid = required_param('itemid', PARAM_INT);
$scaleid = required_param('scaleid', PARAM_INT);
$userrating = required_param('rating', PARAM_INT);
$returnurl = optional_param('returnurl', null, PARAM_LOCALURL);//will only be supplied for non-ajax requests
$returnurl = required_param('returnurl', null, PARAM_LOCALURL);//required for non-ajax requests

$result = new stdClass;

if( !isloggedin() && !$returnurl ){ //session has expired and its an ajax request
$result->error = get_string('sessionerroruser', 'error');
echo json_encode($result);
die();
}

list($context, $course, $cm) = get_context_info_array($contextid);
require_login($course, false, $cm);

if( !has_capability('moodle/rating:rate',$context) ) {
if( $returnurl ) { //if its a non-ajax request
echo $OUTPUT->header();
echo get_string('ratepermissiondenied', 'ratings');
echo $OUTPUT->footer();
}
else {
$result->error = get_string('ratepermissiondenied', 'ratings');
echo json_encode($result);
}
echo $OUTPUT->header();
echo get_string('ratepermissiondenied', 'ratings');
echo $OUTPUT->footer();
die();
}

Expand All @@ -71,24 +56,14 @@

//todo how can we validate the forum post,glossary entry or whatever id?
//how do we know where to look for the item? how we we work from module to forum_posts, glossary_entries etc?
//if ($rating_context->contextlevel == CONTEXT_COURSE) {
// $courseid = $rating_context->instanceid;
// $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST);
//if ($rating_context->contextlevel == CONTEXT_MODULE) {
// $cm = get_coursemodule_from_id(false, $rating_context->instanceid, 0, false, MUST_EXIST);
// $courseid = $cm->course;
//}
$rating = new Rating($context, $itemid, $scaleid, $userid);
$ratingoptions = new stdclass;
$ratingoptions->context = $context;
$ratingoptions->itemid = $itemid;
$ratingoptions->scaleid = $scaleid;
$ratingoptions->userid = $userid;
$rating = new rating($ratingoptions);

$rating->update_rating($userrating);

//if its a non-ajax request
if($returnurl) {
redirect($CFG->wwwroot.'/'.$returnurl);
}
else { //this is an ajax request
$result = new stdClass;
$result->success = true;
echo json_encode($result);
die();
}
redirect($CFG->wwwroot.'/'.$returnurl);
Loading

0 comments on commit b1721f6

Please sign in to comment.