Skip to content

Commit

Permalink
rating MDL-21657 first commit for rating library
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew Davis committed Mar 16, 2010
1 parent 283cf6e commit a09aeee
Show file tree
Hide file tree
Showing 21 changed files with 917 additions and 33 deletions.
2 changes: 1 addition & 1 deletion admin/settings/mnet.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?php

require_once($CFG->dirroot.'/mnet/lib.php');
// This file defines settingpages and externalpages under the "mnet" category

if ($hassiteconfig) { // speedup for non-admins, add all caps used on this page
Expand Down
36 changes: 36 additions & 0 deletions course/moodleform_mod.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,18 @@ protected function init_features() {
* @param array $default_values passed by reference
*/
function data_preprocessing(&$default_values){
if (empty($default_values['scale'])) {
$default_values['assessed'] = 0;
}

if (empty($default_values['assessed'])){
//$default_values['userating'] = 0;//this was used by glossary to check/uncheck a 'use ratings' checkbox
$default_values['ratingtime'] = 0;
} else {
//$default_values['userating'] = 1;
$default_values['ratingtime']=
($default_values['assesstimestart'] && $default_values['assesstimefinish']) ? 1 : 0;
}
}

/**
Expand Down Expand Up @@ -327,6 +339,30 @@ function standard_coursemodule_elements(){
}
}

if (plugin_supports('mod', $this->_modname, FEATURE_RATINGS, false)) {
$mform->addElement('header', 'modstandardratings', get_string('ratings', 'ratings'));

//$mform->addElement('checkbox', 'assessed', get_string('allowratings', 'ratings') , get_string('ratingsuse', 'ratings'));

$mform->addElement('select', 'assessed', get_string('aggregatetype', 'ratings') , forum_get_aggregate_types());
$mform->setDefault('assessed', 0);
$mform->setHelpButton('assessed', array('assessaggregate', get_string('aggregatetype', 'ratings'), 'forum'));

$mform->addElement('modgrade', 'scale', get_string('grade'), false);
$mform->disabledIf('scale', 'assessed', 'eq', 0);

$mform->addElement('checkbox', 'ratingtime', get_string('ratingtime', 'forum'));
$mform->disabledIf('ratingtime', 'assessed', 'eq', 0);

$mform->addElement('date_time_selector', 'assesstimestart', get_string('from'));
$mform->disabledIf('assesstimestart', 'assessed', 'eq', 0);
$mform->disabledIf('assesstimestart', 'ratingtime');

$mform->addElement('date_time_selector', 'assesstimefinish', get_string('to'));
$mform->disabledIf('assesstimefinish', 'assessed', 'eq', 0);
$mform->disabledIf('assesstimefinish', 'ratingtime');
}

$mform->addElement('header', 'modstandardelshdr', get_string('modstandardels', 'form'));
if ($this->_features->groups) {
$options = array(NOGROUPS => get_string('groupsnone'),
Expand Down
11 changes: 11 additions & 0 deletions lang/en_utf8/ratings.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php
$string['rating'] = 'Rating';
$string['ratings'] = 'Ratings';
$string['aggregatetype'] = 'Aggregate type';
$string['allowratings'] = 'Allow posts to be rated?';
$string['norate'] = 'Rating of items not allowed!';
$string['noviewrate'] = 'You do not have the capability to view post ratings';
$string['noviewanyrate'] = 'You can only look at results for posts that you made';
$string['ratepermissiondenied'] = 'You do not have permission to rate this item';
$string['ratingsuse'] = 'Use ratings';
$string['sessionexpired'] = 'Your session has expired. Please log in again.';
25 changes: 25 additions & 0 deletions lib/db/access.php
Original file line number Diff line number Diff line change
Expand Up @@ -1530,5 +1530,30 @@
'legacy' => array(
'admin' => CAP_ALLOW
)
),
'moodle/ratings:view' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_SYSTEM,
'legacy' => array(
'admin' => CAP_ALLOW
)
),
'moodle/ratings:viewall' => array(

'riskbitmask' => RISK_PERSONAL,
'captype' => 'read',
'contextlevel' => CONTEXT_SYSTEM,
'legacy' => array(
'admin' => CAP_ALLOW
)
),
'moodle/ratings:rate' => array(

'riskbitmask' => RISK_DATALOSS,
'captype' => 'write',
'contextlevel' => CONTEXT_SYSTEM,
'legacy' => array(
'admin' => CAP_ALLOW
)
)
);
17 changes: 16 additions & 1 deletion lib/db/install.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2374,7 +2374,7 @@
<KEY NAME="blogid" TYPE="foreign" FIELDS="blogid" REFTABLE="post" REFFIELDS="id" PREVIOUS="contextid"/>
</KEYS>
</TABLE>
<TABLE NAME="blog_external" COMMENT="External blog links used for RSS copying of blog entries to Moodle user blogs" PREVIOUS="blog_association">
<TABLE NAME="blog_external" COMMENT="External blog links used for RSS copying of blog entries to Moodle user blogs" PREVIOUS="blog_association" NEXT="ratings">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="userid"/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="id" NEXT="name"/>
Expand All @@ -2391,5 +2391,20 @@
<KEY NAME="userid" TYPE="foreign" FIELDS="userid" REFTABLE="user" REFFIELDS="id" PREVIOUS="primary"/>
</KEYS>
</TABLE>
<TABLE NAME="ratings" COMMENT="moodle ratings" PREVIOUS="blog_external">
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="contextid"/>
<FIELD NAME="contextid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="id" NEXT="itemid"/>
<FIELD NAME="itemid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="contextid" NEXT="scaleid"/>
<FIELD NAME="scaleid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="itemid" NEXT="rating"/>
<FIELD NAME="rating" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="scaleid" NEXT="userid"/>
<FIELD NAME="userid" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="rating" NEXT="timecreated"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="userid" NEXT="timemodified"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="false" PREVIOUS="timecreated"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>
</KEYS>
</TABLE>
</TABLES>
</XMLDB>
74 changes: 74 additions & 0 deletions lib/db/upgrade.php
Original file line number Diff line number Diff line change
Expand Up @@ -3051,6 +3051,80 @@ function xmldb_main_upgrade($oldversion) {
upgrade_main_savepoint($result, 2010021800);
}

if ($result && $oldversion < 2010031600) {
//create the ratings table (replaces module specific ratings implementations)
$table = new xmldb_table('ratings');

/// Adding fields to table ratings
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('contextid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);

$table->add_field('itemid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
$table->add_field('scaleid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
$table->add_field('rating', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
$table->add_field('userid', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);

$table->add_field('timecreated', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);
$table->add_field('timemodified', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, null);

/// Adding keys to table ratings
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
$table->add_key('contextid', XMLDB_KEY_FOREIGN, array('contextid'), 'context', array('id'));
$table->add_key('userid', XMLDB_KEY_FOREIGN, array('userid'), 'user', array('id'));

/// Adding indexes to table ratings
$table->add_index('itemid', XMLDB_INDEX_NOTUNIQUE, array('itemid'));

/// Create table for ratings
$dbman->create_table($table);

//migrate ratings out of the modules into the central ratings table

//migrate forumratings
//forum ratings only have a single time column so use it for both time created and modified
$ratingssql = 'select r.id as rid, r.post as itemid, r.rating, r.userid, r.time as timecreated, r.time as timemodified, f.scale, f.id as mid from {forum_ratings} r
inner join {forum_posts} p on p.id=r.post
inner join {forum_discussions} d on d.id=p.discussion
inner join {forum} f on f.id=d.forum';
echo "migrating forum ratings<br>";
$result = $result && upgrade_module_ratings($ratingssql,'forum');

//migrate glossary_ratings
//glossary ratings only have a single time column so use it for both time created and modified
$ratingssql = 'select r.id as rid, r.entryid as itemid, r.rating, r.userid, r.time as timecreated, r.time as timemodified, g.id as mid, g.scale
from {glossary_ratings} r inner join {glossary_entries} ge on ge.id=r.entryid
inner join {glossary} g on g.id=ge.glossaryid';
echo "migrating glossary ratings<br>";
$result = $result && upgrade_module_ratings($ratingssql,'glossary');

//migrate data_ratings
//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
from {data_ratings} r inner join {data_records} re on r.recordid=re.id
inner join {data} d on d.id=re.dataid';
echo "migrating data ratings<br>";
$result = $result && upgrade_module_ratings($ratingssql,'data');

//add assesstimestart and assesstimefinish columns to data
$table = new xmldb_table('data');
$field = new xmldb_field('assesstimestart');
if (!$dbman->field_exists($table, $field)) {
$field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'assessed');
$dbman->add_field($table, $field);
}
$field = new xmldb_field('assesstimefinish');
if (!$dbman->field_exists($table, $field)) {
$field->set_attributes(XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, 0, 'assesstimestart');
$dbman->add_field($table, $field);
}

//todo set permissions based on current value of glossary.assessed

//todo drop forum_ratings, data_ratings and glossary_ratings

upgrade_main_savepoint($result, 2010031600);
}

return $result;
}

Expand Down
44 changes: 44 additions & 0 deletions lib/db/upgradelib.php
Original file line number Diff line number Diff line change
Expand Up @@ -396,3 +396,47 @@ function upgrade_cleanup_unwanted_block_contexts($contextidarray) {

return ($outcome1 && $outcome2 && $outcome4 && $outcome4);
}

function upgrade_module_ratings($ratingssql, $modulename) {
global $DB;
$contextid = null;
$contextarray = array();
$result = true;
$i=0;

$ratings = $DB->get_records_sql($ratingssql);

foreach ($ratings as $old_rating) {
if($i++%500==0) {
upgrade_set_timeout(60);//prevent a timeout
}

//all posts within a given forum will have the same context id so store them in an array
if( !array_key_exists($old_rating->mid, $contextarray) ) {
$sql = 'select cxt.id from {course_modules} cm inner join {modules} m on cm.module=m.id
inner join {context} cxt on cxt.instanceid=cm.id
where m.name=:modulename and cm.instance=:moduleinstanceid and cxt.contextlevel='.CONTEXT_MODULE;
$params = array();
$params['moduleinstanceid'] = $old_rating->mid;
$params['modulename'] = $modulename;
$results = $DB->get_record_sql($sql, $params);
$contextarray[$old_rating->mid] = $results->id;
}
$contextid = $contextarray[$old_rating->mid];

$rating = new stdclass;
$rating->contextid = $contextid;
$rating->scaleid = $old_rating->scale;
$rating->itemid = $old_rating->itemid;
$rating->rating = $old_rating->rating;
$rating->userid = $old_rating->userid;
$rating->timecreated = $old_rating->timecreated;
$rating->timemodified = $old_rating->timemodified;

$result = $result && $DB->insert_record('ratings', $rating);
}

$ratings->close();

return $result;
}
2 changes: 2 additions & 0 deletions lib/moodlelib.php
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,8 @@

define('FEATURE_COMMENT', 'comment');

define('FEATURE_RATINGS', 'ratings');

/** Unspecified module archetype */
define('MOD_ARCHETYPE_OTHER', 0);
/** Resource-like type module */
Expand Down
110 changes: 110 additions & 0 deletions lib/outputrenderers.php
Original file line number Diff line number Diff line change
Expand Up @@ -1229,6 +1229,116 @@ protected function render_pix_icon(pix_icon $icon) {
return html_writer::empty_tag('img', $attributes);
}

/**
* Produces the html that represents this rating in the UI
* @param $page the page object on which this rating will appear
*/
function render_rating(rating $rating) {
global $CFG, $USER, $PAGE;
static $strrate;//holds the string "rate". Its static so we only fetch it once.
static $havesetupjavascript = false;

if( !$havesetupjavascript && !empty($CFG->enableajax) ) {
$PAGE->requires->js_init_call('M.core_ratings.init');
$havesetupjavascript = true;
}

if (empty($strrate)) {
$strrate = get_string("rate", "forum");
}

$strratings = '';

if($rating->settings->permissions[RATING_VIEW] || $rating->settings->permissions[RATING_VIEW_ALL]) {
switch ($rating->settings->aggregationmethod) {
case RATING_AGGREGATE_AVERAGE :
$strratings .= get_string("aggregateavg", "forum");
break;
case RATING_AGGREGATE_COUNT :
$strratings .= get_string("aggregatecount", "forum");
break;
case RATING_AGGREGATE_MAXIMUM :
$strratings .= get_string("aggregatemax", "forum");
break;
case RATING_AGGREGATE_MINIMUM :
$strratings .= get_string("aggregatemin", "forum");
break;
case RATING_AGGREGATE_SUM :
$strratings .= get_string("aggregatesum", "forum");
break;
}

if (empty($strratings)) {
$strratings .= $strrate;
}
$strratings .= ': ';

$scalemax = 0;
$ratingstr = null;

if ( is_array($rating->settings->scale->scaleitems) ) {
$scalemax = $rating->settings->scale->scaleitems[ count($rating->settings->scale->scaleitems)-1 ];
$ratingstr = $rating->settings->scale->scaleitems[$rating->rating];
}
else { //its numeric
$scalemax = $rating->settings->scale->scaleitems;
$ratingstr = round($rating->aggregate,1);
}

$aggstr = "{$ratingstr} / $scalemax ({$rating->count}) ";

if ($rating->settings->permissions[RATING_VIEW_ALL]) {
$link = new moodle_url("/rating/index.php?contextid={$rating->context->id}&itemid={$rating->itemid}&scaleid={$rating->scaleid}");
$action = new popup_action('click', $link, 'ratings', array('height' => 400, 'width' => 600));
$strratings .= $this->action_link($link, $aggstr, $action);
} else if ($rating->settings->permissions[RATING_VIEW_ALL]) {
$strratings .= $aggstr;
}
}

//todo andrew alter the below if to deny guest users the ability to post ratings.
//Petr to define "guest"
$formstart = null;
if($rating->settings->permissions[RATING_POST]) {
//dont use $rating->userid below as it will be null if the user hasnt already rated the item
$formstart = <<<END
<form id="postrating{$rating->itemid}" class="postratingform" method="post" action="rating/rate.php">
<div class="ratingform">
<input type="hidden" class="ratinginput" name="contextid" value="{$rating->context->id}" />
<input type="hidden" class="ratinginput" name="itemid" value="{$rating->itemid}" />
<input type="hidden" class="ratinginput" name="scaleid" value="{$rating->settings->scale->id}" />
<input type="hidden" class="ratinginput" name="returnurl" value="{$rating->settings->returnurl}" />
END;
$strratings = $formstart.$strratings;

//generate an array of values for numeric scales
$scalearray = $rating->settings->scale->scaleitems;
if( !is_array($scalearray) && is_int($scalearray) ) {
$scalearray = array();
for($i=0; $i<=$rating->settings->scale->scaleitems; $i++) {
$scalearray[$i] = $i;
}
}

$scalearray = array(RATING_UNSET_RATING => $strrate.'...') + $scalearray;
$strratings .= html_writer::select($scalearray, 'rating'.$rating->itemid, $rating->rating, false, array('class'=>'postratingmenu ratinginput'));

//output submit button
$strratings .= '<span class="ratingsubmit"><input type="submit" class="postratingmenusubmit" id="postratingsubmit'.$rating->itemid.'" value="'.get_string('rate', 'forum').'" />';

//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);
$strratings .= $this->help_icon_scale(1, $rating->settings->scale);
}
$strratings .= '</span></div></form>';
}

return $strratings;
}

/*
* Centered heading with attached help button (same title text)
* and optional icon attached
Expand Down
5 changes: 5 additions & 0 deletions lib/outputrequirementslib.php
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,11 @@ protected function find_module($name) {
'fullpath' => '/group/module.js',
'requires' => array('node', 'overlay', 'event-mouseenter'));
break;
case 'core_ratings':
$module = array('name' => 'core_ratings',
'fullpath' => '/rating/module.js',
'requires' => array('node', 'event', 'overlay', 'io', 'json'));
break;
}

} else {
Expand Down
Loading

0 comments on commit a09aeee

Please sign in to comment.