MDL-78449 choice: Support groups in get_choice_results WS
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
issueNumber: MDL-78449
|
||||
notes:
|
||||
mod_choice:
|
||||
- message: >
|
||||
The WebService `mod_choice_get_choice_results` has a new parameter
|
||||
`groupid` that allows specifying the group to get the results for. The
|
||||
default behaviour hasn't changed: if a choice has groups and the
|
||||
parameter isn't specified the WebService will return the results for the
|
||||
active group.
|
||||
type: changed
|
||||
@@ -0,0 +1,9 @@
|
||||
issueNumber: MDL-78449
|
||||
notes:
|
||||
mod_choice:
|
||||
- message: >
|
||||
The function `choice_get_response_data` has a new parameter that allows
|
||||
specifying the group to get the results for. The default behaviour
|
||||
hasn't changed: if a choice has groups and the parameter isn't used, the
|
||||
function will return the results for the active group.
|
||||
type: changed
|
||||
@@ -54,20 +54,32 @@ class mod_choice_external extends external_api {
|
||||
* @since Moodle 3.0
|
||||
*/
|
||||
public static function get_choice_results_parameters() {
|
||||
return new external_function_parameters (array('choiceid' => new external_value(PARAM_INT, 'choice instance id')));
|
||||
return new external_function_parameters ([
|
||||
'choiceid' => new external_value(PARAM_INT, 'choice instance id'),
|
||||
'groupid' => new external_value(
|
||||
PARAM_INT,
|
||||
'Group ID. 0 for all participants, empty for active group.',
|
||||
VALUE_DEFAULT,
|
||||
null,
|
||||
),
|
||||
]);
|
||||
}
|
||||
/**
|
||||
* Returns user's results for a specific choice
|
||||
* and a list of those users that did not answered yet.
|
||||
*
|
||||
* @param int $choiceid the choice instance id
|
||||
* @param int $groupid The group to use, 0 for all participants, null to calculate active group.
|
||||
* @return array of responses details
|
||||
* @since Moodle 3.0
|
||||
*/
|
||||
public static function get_choice_results($choiceid) {
|
||||
global $USER, $PAGE;
|
||||
public static function get_choice_results($choiceid, ?int $groupid = null) {
|
||||
global $PAGE;
|
||||
|
||||
$params = self::validate_parameters(self::get_choice_results_parameters(), array('choiceid' => $choiceid));
|
||||
$params = self::validate_parameters(self::get_choice_results_parameters(), [
|
||||
'choiceid' => $choiceid,
|
||||
'groupid' => $groupid,
|
||||
]);
|
||||
|
||||
if (!$choice = choice_get_choice($params['choiceid'])) {
|
||||
throw new moodle_exception("invalidcoursemodule", "error");
|
||||
@@ -77,10 +89,21 @@ class mod_choice_external extends external_api {
|
||||
$context = context_module::instance($cm->id);
|
||||
self::validate_context($context);
|
||||
|
||||
$groupmode = groups_get_activity_groupmode($cm);
|
||||
if ($groupmode = groups_get_activity_groupmode($cm)) {
|
||||
if (is_null($groupid)) {
|
||||
$groupid = groups_get_activity_group($cm);
|
||||
}
|
||||
|
||||
if (!groups_group_visible($groupid, $course, $cm)) {
|
||||
throw new moodle_exception('notingroup');
|
||||
}
|
||||
} else {
|
||||
$groupid = 0;
|
||||
}
|
||||
|
||||
// Check if we have to include responses from inactive users.
|
||||
$onlyactive = $choice->includeinactive ? false : true;
|
||||
$users = choice_get_response_data($choice, $cm, $groupmode, $onlyactive);
|
||||
$users = choice_get_response_data($choice, $cm, $groupmode, $onlyactive, $groupid);
|
||||
// Show those who haven't answered the question.
|
||||
if (!empty($choice->showunanswered)) {
|
||||
$choice->option[0] = get_string('notanswered', 'choice');
|
||||
|
||||
+10
-5
@@ -782,6 +782,8 @@ function choice_reset_userdata($data) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get response data for a choice and group.
|
||||
*
|
||||
* @global object
|
||||
* @global object
|
||||
* @global object
|
||||
@@ -790,18 +792,21 @@ function choice_reset_userdata($data) {
|
||||
* @param object $cm
|
||||
* @param int $groupmode
|
||||
* @param bool $onlyactive Whether to get response data for active users only.
|
||||
* @param int $groupid Group id, null for current group if choice has groups.
|
||||
* @return array
|
||||
*/
|
||||
function choice_get_response_data($choice, $cm, $groupmode, $onlyactive) {
|
||||
function choice_get_response_data($choice, $cm, $groupmode, $onlyactive, ?int $groupid = null) {
|
||||
global $CFG, $USER, $DB;
|
||||
|
||||
$context = context_module::instance($cm->id);
|
||||
|
||||
/// Get the current group
|
||||
if ($groupmode > 0) {
|
||||
$currentgroup = groups_get_activity_group($cm);
|
||||
if (is_null($groupid)) {
|
||||
// Get the current group.
|
||||
$groupid = groups_get_activity_group($cm);
|
||||
}
|
||||
} else {
|
||||
$currentgroup = 0;
|
||||
$groupid = 0;
|
||||
}
|
||||
|
||||
/// Initialise the returned array, which is a matrix: $allresponses[responseid][userid] = responseobject
|
||||
@@ -812,7 +817,7 @@ function choice_get_response_data($choice, $cm, $groupmode, $onlyactive) {
|
||||
// TODO Does not support custom user profile fields (MDL-70456).
|
||||
$userfieldsapi = \core_user\fields::for_identity($context, false)->with_userpic();
|
||||
$userfields = $userfieldsapi->get_sql('u', false, '', '', false)->selects;
|
||||
$allresponses[0] = get_enrolled_users($context, 'mod/choice:choose', $currentgroup,
|
||||
$allresponses[0] = get_enrolled_users($context, 'mod/choice:choose', $groupid,
|
||||
$userfields, null, 0, 0, $onlyactive);
|
||||
|
||||
/// Get all the recorded responses for this choice
|
||||
|
||||
@@ -34,6 +34,7 @@ require_once($CFG->dirroot . '/mod/choice/lib.php');
|
||||
* @category external
|
||||
* @copyright 2015 Costantino Cito <[email protected]>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
* @covers \mod_choice_external
|
||||
*/
|
||||
final class externallib_test extends externallib_advanced_testcase {
|
||||
|
||||
@@ -144,6 +145,176 @@ final class externallib_test extends externallib_advanced_testcase {
|
||||
$this->assertEquals(1, $resultsarr[$myanswer]['numberofuser']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_choice_results using groups.
|
||||
*/
|
||||
public function test_get_choice_results_with_groups(): void {
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
$group1 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
|
||||
$group2 = $this->getDataGenerator()->create_group(['courseid' => $course->id]);
|
||||
$choicegenerator = $this->getDataGenerator()->get_plugin_generator('mod_choice');
|
||||
|
||||
// Create 3 choices: one with separate groups, one with visible groups and one with no groups.
|
||||
$commonparams = [
|
||||
'course' => $course->id,
|
||||
'option' => ['fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza'],
|
||||
'name' => 'Separate groups choice',
|
||||
'showresults' => CHOICE_SHOWRESULTS_ALWAYS,
|
||||
'publish' => 1,
|
||||
];
|
||||
|
||||
$nogroupschoice = $choicegenerator->create_instance(array_merge($commonparams, ['groupmode' => NOGROUPS]));
|
||||
$separatechoice = $choicegenerator->create_instance(array_merge($commonparams, ['groupmode' => SEPARATEGROUPS]));
|
||||
$visiblechoice = $choicegenerator->create_instance(array_merge($commonparams, ['groupmode' => VISIBLEGROUPS]));
|
||||
$nogroupsoptions = array_keys(choice_get_choice($nogroupschoice->id)->option);
|
||||
$separateoptions = array_keys(choice_get_choice($separatechoice->id)->option);
|
||||
$visibleoptions = array_keys(choice_get_choice($visiblechoice->id)->option);
|
||||
$nogroupscm = get_coursemodule_from_id('choice', $nogroupschoice->cmid);
|
||||
$separatecm = get_coursemodule_from_id('choice', $separatechoice->cmid);
|
||||
$visiblecm = get_coursemodule_from_id('choice', $visiblechoice->cmid);
|
||||
|
||||
// Enrol 3 students in the course. One student will have no group, the others will belong one to each group.
|
||||
$student1 = $this->getDataGenerator()->create_user();
|
||||
$student2 = $this->getDataGenerator()->create_user();
|
||||
$studentnogroup = $this->getDataGenerator()->create_user();
|
||||
|
||||
self::getDataGenerator()->enrol_user($student1->id, $course->id, 'student');
|
||||
self::getDataGenerator()->enrol_user($student2->id, $course->id, 'student');
|
||||
self::getDataGenerator()->enrol_user($studentnogroup->id, $course->id, 'student');
|
||||
|
||||
groups_add_member($group1, $student1);
|
||||
groups_add_member($group2, $student2);
|
||||
|
||||
// Add answers for both users in all choices.
|
||||
$this->setUser($student1);
|
||||
choice_user_submit_response($nogroupsoptions[0], $nogroupschoice, $student1->id, $course, $nogroupscm);
|
||||
choice_user_submit_response($separateoptions[0], $separatechoice, $student1->id, $course, $separatecm);
|
||||
choice_user_submit_response($visibleoptions[0], $visiblechoice, $student1->id, $course, $visiblecm);
|
||||
|
||||
$this->setUser($student2);
|
||||
choice_user_submit_response($nogroupsoptions[1], $nogroupschoice, $student2->id, $course, $nogroupscm);
|
||||
choice_user_submit_response($separateoptions[1], $separatechoice, $student2->id, $course, $separatecm);
|
||||
choice_user_submit_response($visibleoptions[1], $visiblechoice, $student2->id, $course, $visiblecm);
|
||||
|
||||
// No groups: check that the groupid parameter is ignored.
|
||||
$results = mod_choice_external::get_choice_results($nogroupschoice->id, $group1->id);
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
|
||||
|
||||
$resultsarr = [];
|
||||
foreach ($results['options'] as $option) {
|
||||
$resultsarr[$option['id']] = $option['userresponses'];
|
||||
}
|
||||
$this->assertEquals($resultsarr[$nogroupsoptions[0]][0]['userid'], $student1->id);
|
||||
$this->assertEquals($resultsarr[$nogroupsoptions[1]][0]['userid'], $student2->id);
|
||||
|
||||
$results = mod_choice_external::get_choice_results($nogroupschoice->id, $group2->id);
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
|
||||
|
||||
$resultsarr = [];
|
||||
foreach ($results['options'] as $option) {
|
||||
$resultsarr[$option['id']] = $option['userresponses'];
|
||||
}
|
||||
$this->assertEquals($resultsarr[$nogroupsoptions[0]][0]['userid'], $student1->id);
|
||||
$this->assertEquals($resultsarr[$nogroupsoptions[1]][0]['userid'], $student2->id);
|
||||
|
||||
// Separate groups: check that students can only see results of the group they belong.
|
||||
$this->setUser($student1);
|
||||
$results = mod_choice_external::get_choice_results($separatechoice->id, $group1->id);
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
|
||||
|
||||
$resultsarr = [];
|
||||
foreach ($results['options'] as $option) {
|
||||
$resultsarr[$option['id']] = $option['userresponses'];
|
||||
}
|
||||
$this->assertEquals($resultsarr[$separateoptions[0]][0]['userid'], $student1->id);
|
||||
$this->assertCount(0, $resultsarr[$separateoptions[1]]); // The answer for the group 2 is not returned.
|
||||
|
||||
try {
|
||||
mod_choice_external::get_choice_results($separatechoice->id, $group2->id);
|
||||
$this->fail('Exception expected due to not visible group.');
|
||||
} catch (\moodle_exception $e) {
|
||||
$this->assertEquals('notingroup', $e->errorcode);
|
||||
}
|
||||
|
||||
try {
|
||||
mod_choice_external::get_choice_results($separatechoice->id, 0); // All participants also throws error.
|
||||
$this->fail('Exception expected due to not visible group.');
|
||||
} catch (\moodle_exception $e) {
|
||||
$this->assertEquals('notingroup', $e->errorcode);
|
||||
}
|
||||
|
||||
$this->setUser($student2);
|
||||
$results = mod_choice_external::get_choice_results($separatechoice->id, $group2->id);
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
|
||||
|
||||
$resultsarr = [];
|
||||
foreach ($results['options'] as $option) {
|
||||
$resultsarr[$option['id']] = $option['userresponses'];
|
||||
}
|
||||
$this->assertEquals($resultsarr[$separateoptions[1]][0]['userid'], $student2->id);
|
||||
$this->assertCount(0, $resultsarr[$separateoptions[0]]); // The answer for the group 1 is not returned.
|
||||
|
||||
try {
|
||||
mod_choice_external::get_choice_results($separatechoice->id, $group1->id);
|
||||
$this->fail('Exception expected due to not visible group.');
|
||||
} catch (\moodle_exception $e) {
|
||||
$this->assertEquals('notingroup', $e->errorcode);
|
||||
}
|
||||
|
||||
// Visible groups: check that students can see results of all groups, including 'All participants'.
|
||||
$this->setUser($student1);
|
||||
$results = mod_choice_external::get_choice_results($visiblechoice->id, $group1->id);
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
|
||||
|
||||
$resultsarr = [];
|
||||
foreach ($results['options'] as $option) {
|
||||
$resultsarr[$option['id']] = $option['userresponses'];
|
||||
}
|
||||
$this->assertEquals($resultsarr[$visibleoptions[0]][0]['userid'], $student1->id);
|
||||
$this->assertCount(0, $resultsarr[$visibleoptions[1]]); // The answer for the other group is not returned.
|
||||
|
||||
$results = mod_choice_external::get_choice_results($visiblechoice->id, $group2->id);
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
|
||||
|
||||
$resultsarr = [];
|
||||
foreach ($results['options'] as $option) {
|
||||
$resultsarr[$option['id']] = $option['userresponses'];
|
||||
}
|
||||
$this->assertEquals($resultsarr[$visibleoptions[1]][0]['userid'], $student2->id);
|
||||
$this->assertCount(0, $resultsarr[$visibleoptions[0]]); // The answer for the other group is not returned.
|
||||
|
||||
$results = mod_choice_external::get_choice_results($visiblechoice->id, 0);
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
|
||||
|
||||
$resultsarr = [];
|
||||
foreach ($results['options'] as $option) {
|
||||
$resultsarr[$option['id']] = $option['userresponses'];
|
||||
}
|
||||
$this->assertEquals($resultsarr[$visibleoptions[0]][0]['userid'], $student1->id);
|
||||
$this->assertEquals($resultsarr[$visibleoptions[1]][0]['userid'], $student2->id);
|
||||
|
||||
// User with no groups can view results for the visible groups choice, but not for separate groups.
|
||||
$this->setUser($studentnogroup);
|
||||
$results = mod_choice_external::get_choice_results($visiblechoice->id, 0);
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::get_choice_results_returns(), $results);
|
||||
|
||||
$resultsarr = [];
|
||||
foreach ($results['options'] as $option) {
|
||||
$resultsarr[$option['id']] = $option['userresponses'];
|
||||
}
|
||||
$this->assertEquals($resultsarr[$visibleoptions[0]][0]['userid'], $student1->id);
|
||||
$this->assertEquals($resultsarr[$visibleoptions[1]][0]['userid'], $student2->id);
|
||||
|
||||
try {
|
||||
mod_choice_external::get_choice_results($separatechoice->id, 0);
|
||||
$this->fail('Exception expected due to not visible group.');
|
||||
} catch (\moodle_exception $e) {
|
||||
$this->assertEquals('notingroup', $e->errorcode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_choice_options
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user