MDL-50173 ratings: Use proper checks to ensure ratings are viewable.

Mainly to verify groups visibility this new callback has been created.

Note this was originally 2 commits but for amending purposes they have
been squashed.
This commit is contained in:
Ankit Agarwal
2015-09-09 04:42:19 +02:00
committed by Eloy Lafuente (stronk7)
parent a20bcf6598
commit 20ff15e22b
6 changed files with 306 additions and 3 deletions
+47
View File
@@ -1500,6 +1500,53 @@ function data_rating_validate($params) {
return true;
}
/**
* Can the current user see ratings for a given itemid?
*
* @param array $params submitted data
* contextid => int contextid [required]
* component => The component for this module - should always be mod_data [required]
* ratingarea => object the context in which the rated items exists [required]
* itemid => int the ID of the object being rated [required]
* scaleid => int scale id [optional]
* @return bool
* @throws coding_exception
* @throws rating_exception
*/
function mod_data_rating_can_see_item_ratings($params) {
global $DB;
// Check the component is mod_data.
if (!isset($params['component']) || $params['component'] != 'mod_data') {
throw new rating_exception('invalidcomponent');
}
// Check the ratingarea is entry (the only rating area in data).
if (!isset($params['ratingarea']) || $params['ratingarea'] != 'entry') {
throw new rating_exception('invalidratingarea');
}
if (!isset($params['itemid'])) {
throw new rating_exception('invaliditemid');
}
$datasql = "SELECT d.id as dataid, d.course, r.groupid
FROM {data_records} r
JOIN {data} d ON r.dataid = d.id
WHERE r.id = :itemid";
$dataparams = array('itemid' => $params['itemid']);
if (!$info = $DB->get_record_sql($datasql, $dataparams)) {
// Item doesn't exist
throw new rating_exception('invaliditemid');
}
$course = $DB->get_record('course', array('id' => $info->course), '*', MUST_EXIST);
$cm = get_coursemodule_from_instance('data', $info->dataid, $course->id, false, MUST_EXIST);
// Make sure groups allow this user to see the item they're rating.
return groups_group_visible($info->groupid, $course, $cm);
}
/**
* function that takes in the current data, number of items per page,
+101 -2
View File
@@ -35,9 +35,9 @@ require_once($CFG->dirroot . '/mod/data/lib.php');
* @copyright 2013 Adrian Greeve
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class data_lib_testcase extends advanced_testcase {
class mod_data_lib_testcase extends advanced_testcase {
function test_data_delete_record() {
public function test_data_delete_record() {
global $DB;
$this->resetAfterTest();
@@ -231,4 +231,103 @@ class data_lib_testcase extends advanced_testcase {
$this->assertEquals($url, $event->get_url());
$this->assertEventContextNotUsed($event);
}
/**
* Tests for mod_data_rating_can_see_item_ratings().
*
* @throws coding_exception
* @throws rating_exception
*/
public function test_mod_data_rating_can_see_item_ratings() {
global $DB;
$this->resetAfterTest();
// Setup test data.
$course = new stdClass();
$course->groupmode = SEPARATEGROUPS;
$course->groupmodeforce = true;
$course = $this->getDataGenerator()->create_course($course);
$data = $this->getDataGenerator()->create_module('data', array('course' => $course->id));
$cm = get_coursemodule_from_instance('data', $data->id);
$context = context_module::instance($cm->id);
// Create users.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
// Groups and stuff.
$role = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
$this->getDataGenerator()->enrol_user($user1->id, $course->id, $role->id);
$this->getDataGenerator()->enrol_user($user2->id, $course->id, $role->id);
$this->getDataGenerator()->enrol_user($user3->id, $course->id, $role->id);
$this->getDataGenerator()->enrol_user($user4->id, $course->id, $role->id);
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
groups_add_member($group1, $user1);
groups_add_member($group1, $user2);
groups_add_member($group2, $user3);
groups_add_member($group2, $user4);
// Add data.
$field = data_get_field_new('text', $data);
$fielddetail = new stdClass();
$fielddetail->name = 'Name';
$fielddetail->description = 'Some name';
$field->define_field($fielddetail);
$field->insert_field();
$recordid = data_add_record($data, $group1->id);
$datacontent = array();
$datacontent['fieldid'] = $field->field->id;
$datacontent['recordid'] = $recordid;
$datacontent['content'] = 'Asterix';
$DB->insert_record('data_content', $datacontent);
// Now try to access it as various users.
unassign_capability('moodle/site:accessallgroups', $role->id);
$params = array('contextid' => 2,
'component' => 'mod_data',
'ratingarea' => 'entry',
'itemid' => $recordid,
'scaleid' => 2);
$this->setUser($user1);
$this->assertTrue(mod_data_rating_can_see_item_ratings($params));
$this->setUser($user2);
$this->assertTrue(mod_data_rating_can_see_item_ratings($params));
$this->setUser($user3);
$this->assertFalse(mod_data_rating_can_see_item_ratings($params));
$this->setUser($user4);
$this->assertFalse(mod_data_rating_can_see_item_ratings($params));
// Now try with accessallgroups cap and make sure everything is visible.
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $role->id, $context->id);
$this->setUser($user1);
$this->assertTrue(mod_data_rating_can_see_item_ratings($params));
$this->setUser($user2);
$this->assertTrue(mod_data_rating_can_see_item_ratings($params));
$this->setUser($user3);
$this->assertTrue(mod_data_rating_can_see_item_ratings($params));
$this->setUser($user4);
$this->assertTrue(mod_data_rating_can_see_item_ratings($params));
// Change group mode and verify visibility.
$course->groupmode = VISIBLEGROUPS;
$DB->update_record('course', $course);
unassign_capability('moodle/site:accessallgroups', $role->id);
$this->setUser($user1);
$this->assertTrue(mod_data_rating_can_see_item_ratings($params));
$this->setUser($user2);
$this->assertTrue(mod_data_rating_can_see_item_ratings($params));
$this->setUser($user3);
$this->assertTrue(mod_data_rating_can_see_item_ratings($params));
$this->setUser($user4);
$this->assertTrue(mod_data_rating_can_see_item_ratings($params));
}
}
+42
View File
@@ -3664,6 +3664,48 @@ function forum_rating_validate($params) {
return true;
}
/**
* Can the current user see ratings for a given itemid?
*
* @param array $params submitted data
* contextid => int contextid [required]
* component => The component for this module - should always be mod_forum [required]
* ratingarea => object the context in which the rated items exists [required]
* itemid => int the ID of the object being rated [required]
* scaleid => int scale id [optional]
* @return bool
* @throws coding_exception
* @throws rating_exception
*/
function mod_forum_rating_can_see_item_ratings($params) {
global $DB, $USER;
// Check the component is mod_forum.
if (!isset($params['component']) || $params['component'] != 'mod_forum') {
throw new rating_exception('invalidcomponent');
}
// Check the ratingarea is post (the only rating area in forum).
if (!isset($params['ratingarea']) || $params['ratingarea'] != 'post') {
throw new rating_exception('invalidratingarea');
}
if (!isset($params['itemid'])) {
throw new rating_exception('invaliditemid');
}
$post = $DB->get_record('forum_posts', array('id' => $params['itemid']), '*', MUST_EXIST);
$discussion = $DB->get_record('forum_discussions', array('id' => $post->discussion), '*', MUST_EXIST);
$forum = $DB->get_record('forum', array('id' => $discussion->forum), '*', MUST_EXIST);
$course = $DB->get_record('course', array('id' => $forum->course), '*', MUST_EXIST);
$cm = get_coursemodule_from_instance('forum', $forum->id, $course->id , false, MUST_EXIST);
// Perform some final capability checks.
if (!forum_user_can_see_post($forum, $discussion, $post, $USER, $cm)) {
return false;
}
return true;
}
/**
* This function prints the overview of a discussion in the forum listing.
+104
View File
@@ -26,6 +26,7 @@ defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/forum/lib.php');
require_once($CFG->dirroot . '/rating/lib.php');
class mod_forum_lib_testcase extends advanced_testcase {
@@ -1317,4 +1318,107 @@ class mod_forum_lib_testcase extends advanced_testcase {
return $discussion;
}
/**
* Tests for mod_forum_rating_can_see_item_ratings().
*
* @throws coding_exception
* @throws rating_exception
*/
public function test_mod_forum_rating_can_see_item_ratings() {
global $DB;
$this->resetAfterTest();
// Setup test data.
$course = new stdClass();
$course->groupmode = SEPARATEGROUPS;
$course->groupmodeforce = true;
$course = $this->getDataGenerator()->create_course($course);
$forum = $this->getDataGenerator()->create_module('forum', array('course' => $course->id));
$generator = self::getDataGenerator()->get_plugin_generator('mod_forum');
$cm = get_coursemodule_from_instance('forum', $forum->id);
$context = context_module::instance($cm->id);
// Create users.
$user1 = $this->getDataGenerator()->create_user();
$user2 = $this->getDataGenerator()->create_user();
$user3 = $this->getDataGenerator()->create_user();
$user4 = $this->getDataGenerator()->create_user();
// Groups and stuff.
$role = $DB->get_record('role', array('shortname' => 'teacher'), '*', MUST_EXIST);
$this->getDataGenerator()->enrol_user($user1->id, $course->id, $role->id);
$this->getDataGenerator()->enrol_user($user2->id, $course->id, $role->id);
$this->getDataGenerator()->enrol_user($user3->id, $course->id, $role->id);
$this->getDataGenerator()->enrol_user($user4->id, $course->id, $role->id);
$group1 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
$group2 = $this->getDataGenerator()->create_group(array('courseid' => $course->id));
groups_add_member($group1, $user1);
groups_add_member($group1, $user2);
groups_add_member($group2, $user3);
groups_add_member($group2, $user4);
$record = new stdClass();
$record->course = $forum->course;
$record->forum = $forum->id;
$record->userid = $user1->id;
$record->groupid = $group1->id;
$discussion = $generator->create_discussion($record);
// Retrieve the first post.
$post = $DB->get_record('forum_posts', array('discussion' => $discussion->id));
$ratingoptions = new stdClass;
$ratingoptions->context = $context;
$ratingoptions->ratingarea = 'post';
$ratingoptions->component = 'mod_forum';
$ratingoptions->itemid = $post->id;
$ratingoptions->scaleid = 2;
$ratingoptions->userid = $user2->id;
$rating = new rating($ratingoptions);
$rating->update_rating(2);
// Now try to access it as various users.
unassign_capability('moodle/site:accessallgroups', $role->id);
$params = array('contextid' => 2,
'component' => 'mod_forum',
'ratingarea' => 'post',
'itemid' => $post->id,
'scaleid' => 2);
$this->setUser($user1);
$this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
$this->setUser($user2);
$this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
$this->setUser($user3);
$this->assertFalse(mod_forum_rating_can_see_item_ratings($params));
$this->setUser($user4);
$this->assertFalse(mod_forum_rating_can_see_item_ratings($params));
// Now try with accessallgroups cap and make sure everything is visible.
assign_capability('moodle/site:accessallgroups', CAP_ALLOW, $role->id, $context->id);
$this->setUser($user1);
$this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
$this->setUser($user2);
$this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
$this->setUser($user3);
$this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
$this->setUser($user4);
$this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
// Change group mode and verify visibility.
$course->groupmode = VISIBLEGROUPS;
$DB->update_record('course', $course);
unassign_capability('moodle/site:accessallgroups', $role->id);
$this->setUser($user1);
$this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
$this->setUser($user2);
$this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
$this->setUser($user3);
$this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
$this->setUser($user4);
$this->assertTrue(mod_forum_rating_can_see_item_ratings($params));
}
}
+5
View File
@@ -1,6 +1,11 @@
This files describes API changes in /mod/* - activity modules,
information provided here is intended especially for developers.
=== 2.8.8 ===
* Modules using rating component must implement a callback mod_x_rating_can_see_item_ratings(). Refer
to mod_forum_rating_can_see_item_ratings() for example.
=== 2.8 ===
* Constant FEATURE_GROUPMEMBERSONLY is deprecated. Modules should remove this
+7 -1
View File
@@ -55,7 +55,13 @@ if ($popup) {
$PAGE->set_pagelayout('popup');
}
if (!has_capability('moodle/rating:view', $context)) {
$params = array('contextid' => $contextid,
'component' => $component,
'ratingarea' => $ratingarea,
'itemid' => $itemid,
'scaleid' => $scaleid);
if (!has_capability('moodle/rating:view', $context) ||
!component_callback($component, 'rating_can_see_item_ratings', array($params), true)) {
print_error('noviewrate', 'rating');
}