From d251b259375aba05fa3fc385f61b5fd5ed60efe5 Mon Sep 17 00:00:00 2001 From: Andrew Davis Date: Fri, 23 Apr 2010 09:44:19 +0000 Subject: [PATCH] rating MDL-21657 updated version of ratings including checks for both new system capabilities and old per module capabilities --- lib/outputrenderers.php | 177 ++++++++++++++++---------------- mod/data/db/upgrade.php | 25 +++-- mod/data/lib.php | 221 +++++++++++++++------------------------- mod/data/view.php | 18 ++++ mod/forum/lib.php | 18 ++++ mod/glossary/lib.php | 52 ++++++---- mod/glossary/view.php | 10 +- rating/lib.php | 32 +++++- rating/module.js | 13 ++- rating/rate.php | 13 ++- rating/rate_ajax.php | 54 +++++++--- 11 files changed, 352 insertions(+), 281 deletions(-) diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 0731dc5bf22..101d9f9ce37 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -1268,70 +1268,78 @@ class core_renderer extends renderer_base { $strrate = get_string("rate", "rating"); $ratinghtml = ''; //the string we'll return - //if the item doesnt belong to the current user - if ($rating->itemuserid!=$USER->id ) { - if ($rating->settings->permissions->canview || $rating->settings->permissions->canviewall) { - $aggregatelabel = ''; - switch ($rating->settings->aggregationmethod) { - case RATING_AGGREGATE_AVERAGE : - $aggregatelabel .= get_string("aggregateavg", "forum"); - break; - case RATING_AGGREGATE_COUNT : - $aggregatelabel .= get_string("aggregatecount", "forum"); - break; - case RATING_AGGREGATE_MAXIMUM : - $aggregatelabel .= get_string("aggregatemax", "forum"); - break; - case RATING_AGGREGATE_MINIMUM : - $aggregatelabel .= get_string("aggregatemin", "forum"); - break; - case RATING_AGGREGATE_SUM : - $aggregatelabel .= get_string("aggregatesum", "forum"); - break; - } + //permissions check - can they view the aggregate? + if ( ($rating->itemuserid==$USER->id + && $rating->settings->permissions->view && $rating->settings->pluginpermissions->view) + || ($rating->itemuserid!=$USER->id + && $rating->settings->permissions->viewany && $rating->settings->pluginpermissions->viewany) ) { - //$scalemax = 0;//no longer displaying scale max - $aggregatestr = ''; - - if ($rating->rating) { //this will prevent the user seeing the aggregate until they have submitted a rating - if (is_array($rating->settings->scale->scaleitems)) { - //$scalemax = $rating->settings->scale->scaleitems[ count($rating->settings->scale->scaleitems) ]; - $aggregatestr .= $rating->settings->scale->scaleitems[round($rating->aggregate)];//round aggregate as we're using it as an index - } - else { //its numeric - //$scalemax = $rating->settings->scale->scaleitems; - $aggregatestr .= round($rating->aggregate,1); - } - } - - $countstr = null; - if ($rating->count>0) { - $countstr = "({$rating->count})"; - } else { - $countstr = ""; - } - - //$aggregatehtml = "{$ratingstr} / $scalemax ({$rating->count}) "; - $aggregatehtml = "$aggregatelabel: {$aggregatestr} $countstr "; - - if ($rating->settings->permissions->canviewall) { - $url = "/rating/index.php?contextid={$rating->context->id}&itemid={$rating->itemid}&scaleid={$rating->settings->scale->id}"; - $nonpopuplink = new moodle_url($url); - $popuplink = new moodle_url("$url&popup=1"); - - $action = new popup_action('click', $popuplink, 'ratings', array('height' => 400, 'width' => 600)); - $ratinghtml .= $this->action_link($nonpopuplink, $aggregatehtml, $action); - } else if ($rating->settings->permissions->canview) { - $ratinghtml .= $aggregatehtml; - } + $aggregatelabel = ''; + switch ($rating->settings->aggregationmethod) { + case RATING_AGGREGATE_AVERAGE : + $aggregatelabel .= get_string("aggregateavg", "forum"); + break; + case RATING_AGGREGATE_COUNT : + $aggregatelabel .= get_string("aggregatecount", "forum"); + break; + case RATING_AGGREGATE_MAXIMUM : + $aggregatelabel .= get_string("aggregatemax", "forum"); + break; + case RATING_AGGREGATE_MINIMUM : + $aggregatelabel .= get_string("aggregatemin", "forum"); + break; + case RATING_AGGREGATE_SUM : + $aggregatelabel .= get_string("aggregatesum", "forum"); + break; } - $formstart = null; - //if the item doesnt belong to the current user, the user has permission to rate - //and we're not outside of a defined assessable period - //if( $rating->itemuserid!=$USER->id && $rating->settings->permissions->canrate && $inassessablewindow) { - if ($rating->itemuserid!=$USER->id && $rating->settings->permissions->canrate && $inassessablewindow) { - $formstart = <<aggregate) { + if (is_array($rating->settings->scale->scaleitems)) { + //$scalemax = $rating->settings->scale->scaleitems[ count($rating->settings->scale->scaleitems) ]; + $aggregatestr .= $rating->settings->scale->scaleitems[round($rating->aggregate)];//round aggregate as we're using it as an index + } + else { //its numeric + //$scalemax = $rating->settings->scale->scaleitems; + $aggregatestr .= round($rating->aggregate,1); + } + } else { + $aggregatestr = ' - '; + } + + $countstr = null; + if ($rating->count>0) { + $countstr = "({$rating->count})"; + } else { + $countstr = ""; + } + + //$aggregatehtml = "{$ratingstr} / $scalemax ({$rating->count}) "; + $aggregatehtml = "{$aggregatestr} $countstr "; + + if ($rating->settings->permissions->viewall && $rating->settings->pluginpermissions->viewall) { + $url = "/rating/index.php?contextid={$rating->context->id}&itemid={$rating->itemid}&scaleid={$rating->settings->scale->id}"; + $nonpopuplink = new moodle_url($url); + $popuplink = new moodle_url("$url&popup=1"); + + $action = new popup_action('click', $popuplink, 'ratings', array('height' => 400, 'width' => 600)); + $ratinghtml .= $aggregatelabel.': '.$this->action_link($nonpopuplink, $aggregatehtml, $action); + } else { + $ratinghtml .= "{$aggregatelabel}: $aggregatehtml"; + } + } + + $formstart = null; + //if the item doesnt belong to the current user, the user has permission to rate + //and we're within the assessable period + if ($rating->itemuserid!=$USER->id + && $rating->settings->permissions->rate + && $rating->settings->pluginpermissions->rate + && $inassessablewindow) { + + $formstart = <<
@@ -1341,35 +1349,34 @@ class core_renderer extends renderer_base { END; - if (empty($ratinghtml)) { - $ratinghtml .= $strrate.': '; - } + if (empty($ratinghtml)) { + $ratinghtml .= $strrate.': '; + } - $ratinghtml = $formstart.$ratinghtml; + $ratinghtml = $formstart.$ratinghtml; - //generate an array of values for numeric scales - $scalearray = $rating->settings->scale->scaleitems; - if (!is_array($scalearray)) { //almost certainly a numerical scale - $intscalearray = intval($scalearray);//just in case theyve passed "5" instead of 5 - if( is_int($intscalearray) && $intscalearray>0 ){ - $scalearray = array(); - for($i=0; $i<=$rating->settings->scale->scaleitems; $i++) { - $scalearray[$i] = $i; - } + //generate an array of values for numeric scales + $scalearray = $rating->settings->scale->scaleitems; + if (!is_array($scalearray)) { //almost certainly a numerical scale + $intscalearray = intval($scalearray);//just in case theyve passed "5" instead of 5 + if( is_int($intscalearray) && $intscalearray>0 ){ + $scalearray = array(); + for($i=0; $i<=$rating->settings->scale->scaleitems; $i++) { + $scalearray[$i] = $i; } } - - $scalearray = array(RATING_UNSET_RATING => $strrate.'...') + $scalearray; - $ratinghtml .= html_writer::select($scalearray, 'rating', $rating->rating, false, array('class'=>'postratingmenu ratinginput','id'=>'menurating'.$rating->itemid)); - - //output submit button - $ratinghtml .= ''; - - if (is_array($rating->settings->scale->scaleitems)) { - $ratinghtml .= $this->help_icon_scale($rating->settings->scale->courseid, $rating->settings->scale); - } - $ratinghtml .= '
'; } + + $scalearray = array(RATING_UNSET_RATING => $strrate.'...') + $scalearray; + $ratinghtml .= html_writer::select($scalearray, 'rating', $rating->rating, false, array('class'=>'postratingmenu ratinginput','id'=>'menurating'.$rating->itemid)); + + //output submit button + $ratinghtml .= ''; + + if (is_array($rating->settings->scale->scaleitems)) { + $ratinghtml .= $this->help_icon_scale($rating->settings->scale->courseid, $rating->settings->scale); + } + $ratinghtml .= ''; } return $ratinghtml; diff --git a/mod/data/db/upgrade.php b/mod/data/db/upgrade.php index e20d4a74471..e371e423be8 100644 --- a/mod/data/db/upgrade.php +++ b/mod/data/db/upgrade.php @@ -254,22 +254,29 @@ function xmldb_data_upgrade($oldversion) { upgrade_mod_savepoint($result, 2010031602, 'data'); } - /*leave this commented out until the data module is switched to the new rating system MDL-21657 - * if($result && $oldversion < 2010041300) { - //migrate data_ratings to the central rating table + if($result && $oldversion < 2010042300) { + //migrate data ratings to the central rating table require_once($CFG->dirroot . '/lib/db/upgradelib.php'); //data ratings didnt store time created and modified so Im using the times from the record the rating was attached to - $ratingssql = 'SELECT r.id AS rid, r.recordid AS itemid, r.rating, r.userid, re.timecreated, re.timemodified, d.scale, d.id AS mid + $sql = "INSERT INTO {rating} (contextid, scaleid, itemid, rating, userid, timecreated, timemodified) +SELECT cxt.id, d.scale, r.recordid AS itemid, r.rating, r.userid, re.timecreated AS timecreated, re.timemodified AS timemodified FROM {data_ratings} r JOIN {data_records} re ON r.recordid=re.id -JOIN {data} d ON d.id=re.dataid'; - $result = $result && upgrade_module_ratings($ratingssql,'data'); +JOIN {data} d ON d.id=re.dataid +JOIN {course_modules} cm ON cm.instance=d.id +JOIN {context} cxt ON cxt.instanceid=cm.id +JOIN {modules} m ON m.id=cm.module +WHERE m.name = :modname AND cxt.contextlevel = :contextlevel"; + $params['modname'] = 'data'; + $params['contextlevel'] = CONTEXT_MODULE; - //todo drop data_ratings + $DB->execute($sql, $params); - upgrade_mod_savepoint($result, 2010041300, 'data'); - }*/ + //todo andrew drop data_ratings + + upgrade_mod_savepoint($result, 2010042300, 'data'); + } return $result; } diff --git a/mod/data/lib.php b/mod/data/lib.php index c3b32e06340..e8b4cc23f68 100755 --- a/mod/data/lib.php +++ b/mod/data/lib.php @@ -862,6 +862,11 @@ function data_update_instance($data) { $data->assessed = 0; } + if (empty($data->ratingtime) or empty($data->assessed)) { + $data->assesstimestart = 0; + $data->assesstimefinish = 0; + } + if (empty($data->notification)) { $data->notification = 0; } @@ -995,20 +1000,22 @@ function data_user_complete($course, $user, $mod, $data) { * @return array array of grades, false if none */ function data_get_user_grades($data, $userid=0) { - global $DB; + global $CFG; - $user = $userid ? "AND u.id = :userid" : ""; - $params = array('userid'=>$userid, 'dataid'=>$data->id); + require_once($CFG->dirroot.'/rating/lib.php'); + $rm = new rating_manager(); - $sql = "SELECT u.id, u.id AS userid, avg(drt.rating) AS rawgrade - FROM {user} u, {data_records} dr, - {data_ratings} drt - WHERE u.id = dr.userid AND dr.id = drt.recordid - AND drt.userid != u.id AND dr.dataid = :dataid - $user - GROUP BY u.id"; + $ratingoptions = new stdclass(); + $ratingoptions->modulename = 'data'; + $ratingoptions->moduleid = $data->id; - return $DB->get_records_sql($sql, $params); + $ratingoptions->userid = $userid; + $ratingoptions->aggregationmethod = $data->assessed; + $ratingoptions->scaleid = $data->scale; + $ratingoptions->itemtable = 'data_records'; + $ratingoptions->itemtableusercolumn = 'userid'; + + return $rm->get_user_grades($ratingoptions); } /** @@ -1128,7 +1135,7 @@ function data_grade_item_delete($data) { */ function data_get_participants($dataid) { // Returns the users with data in one data -// (users with records in data_records, data_comments and data_ratings) +// (users with records in data_records, data_comments and ratings) global $DB; $records = $DB->get_records_sql("SELECT DISTINCT u.id, u.id @@ -1140,8 +1147,8 @@ function data_get_participants($dataid) { WHERE r.dataid = ? AND u.id = r.userid AND r.id = c.itemid AND c.commentarea='database_entry'", array($dataid)); $ratings = $DB->get_records_sql("SELECT DISTINCT u.id, u.id - FROM {user} u, {data_records} r, {data_ratings} a - WHERE r.dataid = ? AND u.id = r.userid AND r.id = a.recordid", array($dataid)); + FROM {user} u, {data_records} r, {ratings} a + WHERE r.dataid = ? AND u.id = r.userid AND r.id = a.itemid", array($dataid)); $participants = array(); @@ -1312,9 +1319,9 @@ function data_print_template($template, $records, $data, $search='', $page=0, $r } /********************************** - * Printing Ratings Form * + * Printing Comments Form * *********************************/ - if (($template == 'singletemplate') && ($data->comments)) { //prints ratings options + if (($template == 'singletemplate') && ($data->comments)) { if (!empty($CFG->usecomments)) { require_once($CFG->dirroot . '/comment/lib.php'); list($context, $course, $cm) = get_context_info_array($context->id); @@ -1334,6 +1341,24 @@ function data_print_template($template, $records, $data, $search='', $page=0, $r } } +/** + * Return rating related permissions + * @param string $options the context id + * @return array an associative array of the user's rating permissions + */ +function data_rating_permissions($options) { + $contextid = $options; + $context = get_context_instance_by_id($contextid); + + if (!$context) { + print_error('invalidcontext'); + return null; + } else { + $ret = new stdclass(); + return array('view'=>has_capability('mod/data:viewrating',$context), 'viewany'=>has_capability('mod/data:viewanyrating',$context), 'viewall'=>has_capability('mod/data:viewallratings',$context), 'rate'=>has_capability('mod/data:rate',$context)); + } +} + /** * function that takes in the current data, number of items per page, @@ -1528,7 +1553,7 @@ function data_print_preference_form($data, $perpage, $search, $sort='', $order=' * @return void Output echo'd */ function data_print_ratings($data, $record) { - global $USER, $DB, $OUTPUT; + /*global $USER, $DB, $OUTPUT; $cm = get_coursemodule_from_instance('data', $data->id); $context = get_context_instance(CONTEXT_MODULE, $cm->id); @@ -1564,129 +1589,13 @@ function data_print_ratings($data, $record) { echo ''; echo ''; } - } -} - -/** - * Print the multiple ratings on a post given to the current user by others. - * Scale is an array of ratings - * - * @staticvar string $strrate - * @param int $recordid - * @param array $scale - * @param bool $link - */ -function data_print_ratings_mean($recordid, $scale, $link=true) { + }*/ global $OUTPUT; - static $strrate; - - $mean = data_get_ratings_mean($recordid, $scale); - - if ($mean !== "") { - - if (empty($strratings)) { - $strratings = get_string("ratings", "data"); - } - - echo "$strratings: "; - if ($link) { - $link = new moodle_url("/mod/data/report.php?id=$recordid"); - $action = new popup_action('click', $link, 'ratings', array('height' => 400, 'width' => 600)); - echo $OUTPUT->action_link($link, $mean, $action); - } else { - echo "$mean "; - } + if( !empty($record->rating) ){ + echo $OUTPUT->render($record->rating); } } -/** - * Return the mean rating of a post given to the current user by others. - * Scale is an array of possible ratings in the scale - * Ratings is an optional simple array of actual ratings (just integers) - * - * @param int $recordid - * @param array $scale - * @param array $ratings - */ -function data_get_ratings_mean($recordid, $scale, $ratings=NULL) { - global $DB; - - if (!$ratings) { - $ratings = array(); - if ($rates = $DB->get_records("data_ratings", array("recordid"=>$recordid))) { - foreach ($rates as $rate) { - $ratings[] = $rate->rating; - } - } - } - - $count = count($ratings); - - if ($count == 0) { - return ""; - - } else if ($count == 1) { - return $scale[$ratings[0]]; - - } else { - $total = 0; - foreach ($ratings as $rating) { - $total += $rating; - } - $mean = round( ((float)$total/(float)$count) + 0.001); // Little fudge factor so that 0.5 goes UP - - if (isset($scale[$mean])) { - return $scale[$mean]." ($count)"; - } else { - return "$mean ($count)"; // Should never happen, hopefully - } - } -} - - -/** - * Print the menu of ratings as part of a larger form. - * If the post has already been - set that value. - * Scale is an array of ratings - * - * @global object - * @staticvar string $strrate - * @param int $recordid - * @param int $userid - * @param array $scale - */ -function data_print_rating_menu($recordid, $userid, $scale) { - global $DB, $OUTPUT; - - static $strrate; - - if (!$rating = $DB->get_record("data_ratings", array("userid"=>$userid, "recordid"=>$recordid))) { - $rating->rating = -999; - } - - if (empty($strrate)) { - $strrate = get_string("rate", "data"); - } - echo html_writer::select($scale, $recordid, $rating->rating, array(-999=>"$strrate...")); -} - -/** - * Returns a list of ratings for a particular post - sorted. - * - * @global object - * @param int $recordid - * @param string $sort - * @return array - */ -function data_get_ratings($recordid, $sort="u.firstname ASC") { - global $DB; - - return $DB->get_records_sql("SELECT u.*, r.rating - FROM {data_ratings} r, {user} u - WHERE r.recordid = ? AND r.userid = u.id - ORDER BY $sort", array($recordid)); -} - /** * For Participantion Reports * @@ -2464,6 +2373,7 @@ function data_reset_gradebook($courseid, $type='') { function data_reset_userdata($data) { global $CFG, $DB; require_once($CFG->libdir.'/filelib.php'); + require_once($CFG->dirroot.'/rating/lib.php'); $componentstr = get_string('modulenameplural', 'data'); $status = array(); @@ -2477,9 +2387,12 @@ function data_reset_userdata($data) { FROM {data} d WHERE d.course=?"; + $rm = new rating_manager(); + $ratingdeloptions = new stdclass(); + // delete entries if requested if (!empty($data->reset_data)) { - $DB->delete_records_select('data_ratings', "recordid IN ($allrecordssql)", array($data->courseid)); + //$DB->delete_records_select('data_ratings', "recordid IN ($allrecordssql)", array($data->courseid)); $DB->delete_records_select('comments', "itemid IN ($allrecordssql) AND commentarea='database_entry'", array($data->courseid)); $DB->delete_records_select('data_content', "recordid IN ($allrecordssql)", array($data->courseid)); $DB->delete_records_select('data_records', "dataid IN ($alldatassql)", array($data->courseid)); @@ -2487,6 +2400,14 @@ function data_reset_userdata($data) { if ($datas = $DB->get_records_sql($alldatassql, array($data->courseid))) { foreach ($datas as $dataid=>$unused) { fulldelete("$CFG->dataroot/$data->courseid/moddata/data/$dataid"); + + if (!$cm = get_coursemodule_from_instance('data', $dataid)) { + continue; + } + $datacontext = get_context_instance(CONTEXT_MODULE, $cm->id); + + $ratingdeloptions->contextid = $datacontext->id; + $rm->delete_ratings($ratingdeloptions); } } @@ -2512,7 +2433,16 @@ function data_reset_userdata($data) { foreach ($rs as $record) { if (array_key_exists($record->userid, $notenrolled) or !$record->userexists or $record->userdeleted or !is_enrolled($course_context, $record->userid)) { - $DB->delete_records('data_ratings', array('recordid'=>$record->id)); + //delete ratings + //$DB->delete_records('data_ratings', array('recordid'=>$record->id)); + if (!$cm = get_coursemodule_from_instance('data', $record->dataid)) { + continue; + } + $datacontext = get_context_instance(CONTEXT_MODULE, $cm->id); + $ratingdeloptions->contextid = $datacontext->id; + $ratingdeloptions->itemid = $record->id; + $rm->delete_ratings($ratingdeloptions); + $DB->delete_records('comments', array('itemid'=>$record->id, 'commentarea'=>'database_entry')); $DB->delete_records('data_content', array('recordid'=>$record->id)); $DB->delete_records('data_records', array('id'=>$record->id)); @@ -2537,7 +2467,18 @@ function data_reset_userdata($data) { // remove all ratings if (!empty($data->reset_data_ratings)) { - $DB->delete_records_select('data_ratings', "recordid IN ($allrecordssql)", array($data->courseid)); + //$DB->delete_records_select('data_ratings', "recordid IN ($allrecordssql)", array($data->courseid)); + if ($datas = $DB->get_records_sql($alldatassql, array($data->courseid))) { + foreach ($datas as $dataid=>$unused) { + if (!$cm = get_coursemodule_from_instance('data', $dataid)) { + continue; + } + $datacontext = get_context_instance(CONTEXT_MODULE, $cm->id); + + $ratingdeloptions->contextid = $datacontext->id; + $rm->delete_ratings($ratingdeloptions); + } + } if (empty($data->reset_gradebook_grades)) { // remove all grades from gradebook @@ -2584,7 +2525,7 @@ function data_supports($feature) { case FEATURE_COMPLETION_TRACKS_VIEWS: return true; case FEATURE_GRADE_HAS_GRADE: return true; case FEATURE_GRADE_OUTCOMES: return true; - case FEATURE_RATE: return false; + case FEATURE_RATE: return true; default: return null; } diff --git a/mod/data/view.php b/mod/data/view.php index 21ec53d0b0d..12972259e13 100755 --- a/mod/data/view.php +++ b/mod/data/view.php @@ -639,6 +639,24 @@ data_generate_default_template($data, 'singletemplate', 0, false, false); } + //data_print_template() only adds ratings for singletemplate which is why we're attaching them here + //attach ratings to data records + require_once($CFG->dirroot.'/rating/lib.php'); + $ratingoptions = new stdclass(); + $ratingoptions->context = $cm->context; + $ratingoptions->items = $records; + $ratingoptions->aggregate = $data->assessed;//the aggregation method + $ratingoptions->scaleid = $data->scale; + $ratingoptions->userid = $USER->id; + $ratingoptions->returnurl = $CFG->wwwroot.'/mod/data/'.$baseurl; + $ratingoptions->assesstimestart = $data->assesstimestart; + $ratingoptions->assesstimefinish = $data->assesstimefinish; + $ratingoptions->plugintype = 'mod'; + $ratingoptions->pluginname = 'data'; + + $rm = new rating_manager(); + $records = $rm->get_ratings($ratingoptions); + data_print_template('singletemplate', $records, $data, $search, $page); echo $OUTPUT->paging_bar($totalcount, $page, $nowperpage, $baseurl); diff --git a/mod/forum/lib.php b/mod/forum/lib.php index a4f2325a0c9..b5e2b61fecc 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -3392,6 +3392,22 @@ function forum_print_post($post, $discussion, $forum, &$cm, $course, $ownpost=fa } } +/** + * Return rating related permissions + * @param string $options the context id + * @return array an associative array of the user's rating permissions + */ +function forum_rating_permissions($contextid) { + $context = get_context_instance_by_id($contextid); + + if (!$context) { + print_error('invalidcontext'); + return null; + } else { + return array('view'=>has_capability('mod/forum:viewrating',$context), 'viewany'=>has_capability('mod/forum:viewanyrating',$context), 'viewall'=>has_capability('mod/forum:viewallratings',$context), 'rate'=>has_capability('mod/forum:rate',$context)); + } +} + /** * This function prints the overview of a discussion in the forum listing. @@ -5237,6 +5253,8 @@ function forum_print_discussion($course, $cm, $forum, $discussion, $post, $mode, } $ratingoptions->assesstimestart = $forum->assesstimestart; $ratingoptions->assesstimefinish = $forum->assesstimefinish; + $ratingoptions->plugintype = 'mod'; + $ratingoptions->pluginname = 'forum'; $rm = new rating_manager(); $posts = $rm->get_ratings($ratingoptions); diff --git a/mod/glossary/lib.php b/mod/glossary/lib.php index 710fa2ece9b..b4d41785702 100644 --- a/mod/glossary/lib.php +++ b/mod/glossary/lib.php @@ -457,6 +457,23 @@ function glossary_get_user_grades($glossary, $userid=0) { return $rm->get_user_grades($ratingoptions); } +/** + * Return rating related permissions + * @param string $options the context id + * @return array an associative array of the user's rating permissions + */ +function glossary_rating_permissions($options) { + $contextid = $options; + $context = get_context_instance_by_id($contextid); + + if (!$context) { + print_error('invalidcontext'); + return null; + } else { + return array('view'=>has_capability('mod/glossary:viewrating',$context), 'viewany'=>has_capability('mod/glossary:viewanyrating',$context), 'viewall'=>has_capability('mod/glossary:viewallratings',$context), 'rate'=>has_capability('mod/glossary:rate',$context)); + } +} + /** * Update activity grades * @@ -2097,21 +2114,6 @@ function glossary_full_tag($tag,$level=0,$endline=true,$content) { return $st.$co.$et; } -/** - * Returns a list of ratings for a particular entry - sorted. - * - * @global object - * @param int $entryid - * @param string $sort - */ -function glossary_get_ratings($entryid, $sort="u.firstname ASC") { - global $DB; - return $DB->get_records_sql("SELECT u.*, r.rating, r.time - FROM {glossary_ratings} r, {user} u - WHERE r.entryid = ? AND r.userid = u.id - ORDER BY $sort", array($entryid)); -} - /** * How many unrated entries are in the given glossary for a given user? * @@ -2365,6 +2367,7 @@ function glossary_reset_gradebook($courseid, $type='') { */ function glossary_reset_userdata($data) { global $CFG, $DB; + require_once($CFG->dirroot.'/rating/lib.php'); $componentstr = get_string('modulenameplural', 'glossary'); $status = array(); @@ -2382,11 +2385,14 @@ function glossary_reset_userdata($data) { $fs = get_file_storage(); + $rm = new rating_manager(); + $ratingdeloptions = new stdclass(); + // delete entries if requested if (!empty($data->reset_glossary_all) or (!empty($data->reset_glossary_types) and in_array('main', $data->reset_glossary_types) and in_array('secondary', $data->reset_glossary_types))) { - $DB->delete_records_select('glossary_ratings', "entryid IN ($allentriessql)", $params); + //$DB->delete_records_select('glossary_ratings', "entryid IN ($allentriessql)", $params); // TODO: delete comments //$DB->delete_records_select('comments', "entryid IN ($allentriessql)", array()); $DB->delete_records_select('glossary_entries', "glossaryid IN ($allglossariessql)", $params); @@ -2399,6 +2405,10 @@ function glossary_reset_userdata($data) { } $context = get_context_instance(CONTEXT_MODULE, $cm->id); $fs->delete_area_files($context->id, 'glossary_attachment'); + + //delete ratings + $ratingdeloptions->contextid = $context->id; + $rm->delete_ratings($ratingdeloptions); } } @@ -2417,7 +2427,7 @@ function glossary_reset_userdata($data) { $secondaryglossariessql = "$allglossariessql AND g.mainglossary=0"; if (in_array('main', $data->reset_glossary_types)) { - $DB->delete_records_select('glossary_ratings', "entryid IN ($mainentriessql)", $params); + //$DB->delete_records_select('glossary_ratings', "entryid IN ($mainentriessql)", $params); $DB->delete_records_select('glossary_comments', "entryid IN ($mainentriessql)", $params); $DB->delete_records_select('glossary_entries', "glossaryid IN ($mainglossariessql)", $params); @@ -2428,6 +2438,10 @@ function glossary_reset_userdata($data) { } $context = get_context_instance(CONTEXT_MODULE, $cm->id); $fs->delete_area_files($context->id, 'glossary_attachment'); + + //delete ratings + $ratingdeloptions->contextid = $context->id; + $rm->delete_ratings($ratingdeloptions); } } @@ -2454,6 +2468,10 @@ function glossary_reset_userdata($data) { } $context = get_context_instance(CONTEXT_MODULE, $cm->id); $fs->delete_area_files($context->id, 'glossary_attachment'); + + //delete ratings + $ratingdeloptions->contextid = $context->id; + $rm->delete_ratings($ratingdeloptions); } } diff --git a/mod/glossary/view.php b/mod/glossary/view.php index 9490d90682b..00cc8831b35 100644 --- a/mod/glossary/view.php +++ b/mod/glossary/view.php @@ -400,20 +400,18 @@ if ($allentries) { //load ratings - require_once('../../rating/lib.php'); + require_once($CFG->dirroot.'/rating/lib.php'); $ratingoptions = new stdclass(); $ratingoptions->context = $cm->context; $ratingoptions->items = $allentries; $ratingoptions->aggregate = $glossary->assessed;//the aggregation method $ratingoptions->scaleid = $glossary->scale; $ratingoptions->userid = $USER->id; - //if (!empty($_SERVER['HTTP_REFERER'])) { -// $ratingoptions->returnurl = $_SERVER['HTTP_REFERER']; - // } else { - $ratingoptions->returnurl = $CFG->wwwroot.'/mod/glossary/view.php?id='.$cm->id; - //} + $ratingoptions->returnurl = $CFG->wwwroot.'/mod/glossary/view.php?id='.$cm->id; $ratingoptions->assesstimestart = $glossary->assesstimestart; $ratingoptions->assesstimefinish = $glossary->assesstimefinish; + $ratingoptions->plugintype = 'mod'; + $ratingoptions->pluginname = 'glossary'; $rm = new rating_manager(); $allentries = $rm->get_ratings($ratingoptions); diff --git a/rating/lib.php b/rating/lib.php index f0cff2e2430..a9ec6c7c1f1 100644 --- a/rating/lib.php +++ b/rating/lib.php @@ -234,6 +234,8 @@ class rating_manager { * returnurl => string the url to return the user to after submitting a rating. Can be left null for ajax requests [optional] * assesstimestart => int only allow rating of items created after this timestamp [optional] * assesstimefinish => int only allow rating of items created before this timestamp [optional] + * plugintype => string plugin type ie 'mod' Used to find the permissions callback [optional] + * pluginname => string plugin name ie 'forum' Used to find the permissions callback [optional] * @return array the array of items with their ratings attached at $items[0]->rating */ public function get_ratings($options) { @@ -333,10 +335,23 @@ class rating_manager { $settings->assesstimefinish = $options->assesstimefinish; } + //check site capabilities $settings->permissions = new stdclass(); - $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); + $settings->permissions->view = has_capability('moodle/rating:view',$options->context);//can view the aggregate of ratings of their own items + $settings->permissions->viewany = has_capability('moodle/rating:viewany',$options->context);//can view the aggregate of ratings of other people's items + $settings->permissions->viewall = has_capability('moodle/rating:viewall',$options->context);//can view individual ratings + $settings->permissions->rate = has_capability('moodle/rating:rate',$options->context);//can submit ratings + + //check module capabilities (mostly for backwards compatability with old modules that previously implemented their own ratings) + $plugintype = !empty($options->plugintype) ? $options->plugintype : null; + $pluginname = !empty($options->pluginname) ? $options->pluginname : null; + $pluginpermissionsarray = $this->get_plugin_permissions_array($options->context->id, $plugintype, $pluginname); + + $settings->pluginpermissions = new stdclass(); + $settings->pluginpermissions->view = $pluginpermissionsarray['view']; + $settings->pluginpermissions->viewany = $pluginpermissionsarray['viewany']; + $settings->pluginpermissions->viewall = $pluginpermissionsarray['viewall']; + $settings->pluginpermissions->rate = $pluginpermissionsarray['rate']; $rating = null; $ratingoptions = new stdclass(); @@ -534,4 +549,15 @@ class rating_manager { } return $aggregatestr; } + + public function get_plugin_permissions_array($contextid, $plugintype=null, $pluginname=null) { + $pluginpermissionsarray = null; + $defaultpluginpermissions = array('rate'=>true,'view'=>true,'viewany'=>true,'viewall'=>true);//all true == rely on system level permissions if no plugin callback is defined + if ($plugintype && $pluginname) { + $pluginpermissionsarray = plugin_callback($plugintype, $pluginname, 'rating', 'permissions', array($contextid), $defaultpluginpermissions); + } else { + $pluginpermissionsarray = $defaultpluginpermissions; + } + return $pluginpermissionsarray; + } }//end rating_manager class definition \ No newline at end of file diff --git a/rating/module.js b/rating/module.js index 258b4f1b90b..7c47c5c0002 100644 --- a/rating/module.js +++ b/rating/module.js @@ -37,13 +37,16 @@ M.core_rating={ var responseobj = this.Y.JSON.parse(outcome.responseText); var itemid = responseobj.itemid; - var node = this.Y.one('#ratingaggregate'+itemid); - node.set('innerHTML',responseobj.aggregate); + //if the user has access to the aggregate + if (responseobj.aggregate) { + var node = this.Y.one('#ratingaggregate'+itemid); + node.set('innerHTML',responseobj.aggregate); - var node = this.Y.one('#ratingcount'+itemid); - node.set('innerHTML',"("+responseobj.count+")"); + var node = this.Y.one('#ratingcount'+itemid); + node.set('innerHTML',"("+responseobj.count+")"); + } } catch(e) { - //todo put up an overlay or similar rather than an alert + //should put up an overlay or similar rather than an alert alert(e.message+" "+outcome.responseText); } if(outcome.success){ diff --git a/rating/rate.php b/rating/rate.php index 37742848ae7..000c64632e3 100644 --- a/rating/rate.php +++ b/rating/rate.php @@ -40,7 +40,18 @@ $result = new stdClass; list($context, $course, $cm) = get_context_info_array($contextid); require_login($course, false, $cm); -if( !has_capability('moodle/rating:rate',$context) ) { +//check the module rating permissions +$pluginrateallowed = true; +$pluginpermissionsarray = null; +if ($context->contextlevel==CONTEXT_MODULE) { + $plugintype = 'mod'; + $pluginname = $cm->modname; + $rm = new rating_manager(); + $pluginpermissionsarray = $rm->get_plugin_permissions_array($context->id, $plugintype, $pluginname); + $pluginrateallowed = $pluginpermissionsarray['rate']; +} + +if (!$pluginrateallowed || !has_capability('moodle/rating:rate',$context)) { echo $OUTPUT->header(); echo get_string('ratepermissiondenied', 'ratings'); echo $OUTPUT->footer(); diff --git a/rating/rate_ajax.php b/rating/rate_ajax.php index 99f12a8fb70..400dced351d 100644 --- a/rating/rate_ajax.php +++ b/rating/rate_ajax.php @@ -47,7 +47,19 @@ if( !isloggedin() ){ list($context, $course, $cm) = get_context_info_array($contextid); require_login($course, false, $cm); -if( !has_capability('moodle/rating:rate',$context) ) { +//check the module rating permissions +//doing this check here rather than within rating_manager::get_ratings so we can return a json error response +$pluginrateallowed = true; +$pluginpermissionsarray = null; +if ($context->contextlevel==CONTEXT_MODULE) { + $plugintype = 'mod'; + $pluginname = $cm->modname; + $rm = new rating_manager(); + $pluginpermissionsarray = $rm->get_plugin_permissions_array($context->id, $plugintype, $pluginname); + $pluginrateallowed = $pluginpermissionsarray['rate']; +} + +if (!$pluginrateallowed || !has_capability('moodle/rating:rate',$context)) { $result->error = get_string('ratepermissiondenied', 'ratings'); echo json_encode($result); die(); @@ -71,20 +83,27 @@ $rating = new rating($ratingoptions); $rating->update_rating($userrating); -//todo add a setting to turn grade updating off for those who don't want them in gradebook -//note that this needs to be done in both rate.php and rate_ajax.php +//Future possible enhancement: add a setting to turn grade updating off for those who don't want them in gradebook +//note that this would need to be done in both rate.php and rate_ajax.php if(true){ - //tell the module that its grades have changed - if ( $modinstance = $DB->get_record($cm->modname, array('id' => $cm->instance)) ) { - $modinstance->cmidnumber = $cm->id; //MDL-12961 - $functionname = $cm->modname.'_update_grades'; - require_once("../mod/{$cm->modname}/lib.php"); - if(function_exists($functionname)) { - $functionname($modinstance, $rateduserid); + if ($context->contextlevel==CONTEXT_MODULE) { + //tell the module that its grades have changed + if ( $modinstance = $DB->get_record($cm->modname, array('id' => $cm->instance)) ) { + $modinstance->cmidnumber = $cm->id; //MDL-12961 + $functionname = $cm->modname.'_update_grades'; + require_once("../mod/{$cm->modname}/lib.php"); + if(function_exists($functionname)) { + $functionname($modinstance, $rateduserid); + } } } } +//object to return to client as json +$result = new stdClass; +$result->success = true; + + //need to retrieve the updated item to get its new aggregate value $item = new stdclass(); $item->id = $rating->itemid; @@ -109,9 +128,14 @@ if($rating->scaleid < 0 ) { //if its a scale (not numeric) $aggregatetoreturn = $scalearray[$aggregatetoreturn-1]; } -$result = new stdClass; -$result->success = true; -$result->aggregate = $aggregatetoreturn; -$result->count = $items[0]->rating->count; -$result->itemid = $rating->itemid; +//See if the user has permission to see the rating aggregate +//we could do this check as "if $userid==$rateduserid" but going to the database to determine item owner id seems more secure +//if we accept the item owner user id from the http request a user could alter the URL and erroneously get access to the rating aggregate +if (($userid==$items[0]->rating->itemuserid && has_capability('moodle/rating:view',$context) && $pluginpermissionsarray['view']) + || ($userid!=$items[0]->rating->itemuserid && has_capability('moodle/rating:viewany',$context) && $pluginpermissionsarray['viewany'])) { + $result->aggregate = $aggregatetoreturn; + $result->count = $items[0]->rating->count; + $result->itemid = $rating->itemid; +} + echo json_encode($result); \ No newline at end of file