mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
MDL-51566 mod_choice: New WS mod_choice_delete_choice_responses
This commit is contained in:
parent
35d3e8b00b
commit
4b93c3e342
@ -1237,6 +1237,7 @@ $services = array(
|
||||
'mod_choice_submit_choice_response',
|
||||
'mod_choice_view_choice',
|
||||
'mod_choice_get_choices_by_courses',
|
||||
'mod_choice_delete_choice_responses',
|
||||
'mod_imscp_view_imscp',
|
||||
'mod_imscp_get_imscps_by_courses',
|
||||
),
|
||||
|
@ -584,4 +584,116 @@ class mod_choice_external extends external_api {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the parameters for delete_choice_responses.
|
||||
*
|
||||
* @return external_external_function_parameters
|
||||
* @since Moodle 3.0
|
||||
*/
|
||||
public static function delete_choice_responses_parameters() {
|
||||
return new external_function_parameters (
|
||||
array(
|
||||
'choiceid' => new external_value(PARAM_INT, 'choice instance id'),
|
||||
'responses' => new external_multiple_structure(
|
||||
new external_value(PARAM_INT, 'response id'),
|
||||
'Array of response ids, empty for deleting all the user responses',
|
||||
VALUE_DEFAULT,
|
||||
array()
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given submitted responses in a choice
|
||||
*
|
||||
* @param int $choiceid the choice instance id
|
||||
* @param array $responses the response ids, empty for deleting all the user responses
|
||||
* @return array status information and warnings
|
||||
* @throws moodle_exception
|
||||
* @since Moodle 3.0
|
||||
*/
|
||||
public static function delete_choice_responses($choiceid, $responses = array()) {
|
||||
|
||||
$status = false;
|
||||
$warnings = array();
|
||||
$params = self::validate_parameters(self::delete_choice_responses_parameters(),
|
||||
array(
|
||||
'choiceid' => $choiceid,
|
||||
'responses' => $responses
|
||||
));
|
||||
|
||||
if (!$choice = choice_get_choice($params['choiceid'])) {
|
||||
throw new moodle_exception("invalidcoursemodule", "error");
|
||||
}
|
||||
list($course, $cm) = get_course_and_cm_from_instance($choice, 'choice');
|
||||
|
||||
$context = context_module::instance($cm->id);
|
||||
self::validate_context($context);
|
||||
|
||||
require_capability('mod/choice:choose', $context);
|
||||
|
||||
// If we have the capability, delete all the passed responses.
|
||||
if (has_capability('mod/choice:deleteresponses', $context)) {
|
||||
if (empty($params['responses'])) {
|
||||
// Get all the responses for the choice.
|
||||
$params['responses'] = array_keys(choice_get_all_responses($choice));
|
||||
}
|
||||
$status = choice_delete_responses($params['responses'], $choice, $cm, $course);
|
||||
} else if ($choice->allowupdate) {
|
||||
// Check if we can delate our own responses.
|
||||
$timenow = time();
|
||||
if ($choice->timeclose != 0) {
|
||||
if ($timenow > $choice->timeclose) {
|
||||
throw new moodle_exception("expired", "choice", '', userdate($choice->timeclose));
|
||||
}
|
||||
}
|
||||
// Delete only our responses.
|
||||
$myresponses = array_keys(choice_get_my_response($choice));
|
||||
|
||||
if (empty($params['responses'])) {
|
||||
$todelete = $myresponses;
|
||||
} else {
|
||||
$todelete = array();
|
||||
foreach ($params['responses'] as $response) {
|
||||
if (!in_array($response, $myresponses)) {
|
||||
$warnings[] = array(
|
||||
'item' => 'response',
|
||||
'itemid' => $response,
|
||||
'warningcode' => 'nopermissions',
|
||||
'message' => 'No permission to delete this response'
|
||||
);
|
||||
} else {
|
||||
$todelete[] = $response;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$status = choice_delete_responses($todelete, $choice, $cm, $course);
|
||||
} else {
|
||||
// The user requires the capability to delete responses.
|
||||
throw new required_capability_exception($context, 'mod/choice:deleteresponses', 'nopermissions', '');
|
||||
}
|
||||
|
||||
return array(
|
||||
'status' => $status,
|
||||
'warnings' => $warnings
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Describes the delete_choice_responses return value.
|
||||
*
|
||||
* @return external_multiple_structure
|
||||
* @since Moodle 3.0
|
||||
*/
|
||||
public static function delete_choice_responses_returns() {
|
||||
return new external_single_structure(
|
||||
array(
|
||||
'status' => new external_value(PARAM_BOOL, 'status, true if everything went right'),
|
||||
'warnings' => new external_warnings(),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -68,4 +68,12 @@ $functions = array(
|
||||
'type' => 'read',
|
||||
'capabilities' => ''
|
||||
),
|
||||
|
||||
'mod_choice_delete_choice_responses' => array(
|
||||
'classname' => 'mod_choice_external',
|
||||
'methodname' => 'delete_choice_responses',
|
||||
'description' => 'Delete the given submitted responses in a choice',
|
||||
'type' => 'write',
|
||||
'capabilities' => 'mod/choice:choose'
|
||||
),
|
||||
);
|
||||
|
@ -935,6 +935,20 @@ function choice_get_my_response($choice) {
|
||||
return $DB->get_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $USER->id));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all the responses on a given choice.
|
||||
*
|
||||
* @param stdClass $choice Choice record
|
||||
* @return array of choice answers records
|
||||
* @since Moodle 3.0
|
||||
*/
|
||||
function choice_get_all_responses($choice) {
|
||||
global $DB;
|
||||
return $DB->get_records('choice_answers', array('choiceid' => $choice->id));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return true if we are allowd to view the choice results.
|
||||
*
|
||||
|
@ -415,4 +415,139 @@ class mod_choice_externallib_testcase extends externallib_advanced_testcase {
|
||||
$choices = external_api::clean_returnvalue(mod_choice_external::get_choices_by_courses_returns(), $choices);
|
||||
$this->assertFalse(isset($choices['choices'][0]['timeopen']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test delete_choice_responses
|
||||
*/
|
||||
public function test_delete_choice_responses() {
|
||||
global $DB;
|
||||
|
||||
$this->resetAfterTest(true);
|
||||
|
||||
$course = self::getDataGenerator()->create_course();
|
||||
$params = new stdClass();
|
||||
$params->course = $course->id;
|
||||
$params->option = array('fried rice', 'spring rolls', 'sweet and sour pork', 'satay beef', 'gyouza');
|
||||
$params->name = 'First Choice Activity';
|
||||
$params->showresults = CHOICE_SHOWRESULTS_ALWAYS;
|
||||
$params->allowmultiple = 1;
|
||||
$params->showunanswered = 1;
|
||||
$choice = self::getDataGenerator()->create_module('choice', $params);
|
||||
$cm = get_coursemodule_from_id('choice', $choice->cmid);
|
||||
|
||||
$choiceinstance = choice_get_choice($cm->instance);
|
||||
$options = array_keys($choiceinstance->option);
|
||||
|
||||
$student = $this->getDataGenerator()->create_user();
|
||||
$studentrole = $DB->get_record('role', array('shortname' => 'student'));
|
||||
|
||||
// Enroll student in Course1.
|
||||
self::getDataGenerator()->enrol_user($student->id, $course->id, $studentrole->id);
|
||||
|
||||
$this->setUser($student);
|
||||
$results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
|
||||
|
||||
$myresponses = array_keys(choice_get_my_response($choice));
|
||||
|
||||
// Try to delete responses when allow update is false.
|
||||
try {
|
||||
mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0], $myresponses[0]));
|
||||
$this->fail('Exception expected due to missing permissions.');
|
||||
} catch (required_capability_exception $e) {
|
||||
$this->assertEquals('nopermissions', $e->errorcode);
|
||||
}
|
||||
|
||||
// Set allow update to true, and a passed time close.
|
||||
$DB->set_field('choice', 'allowupdate', 1, array('id' => $choice->id));
|
||||
$DB->set_field('choice', 'timeclose', time() - DAYSECS, array('id' => $choice->id));
|
||||
try {
|
||||
mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0], $myresponses[1]));
|
||||
$this->fail('Exception expected due to expired choice.');
|
||||
} catch (moodle_exception $e) {
|
||||
$this->assertEquals('expired', $e->errorcode);
|
||||
}
|
||||
|
||||
// Reset time close. We should be able now to delete all the responses.
|
||||
$DB->set_field('choice', 'timeclose', 0, array('id' => $choice->id));
|
||||
$results = mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0], $myresponses[1]));
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
|
||||
|
||||
$this->assertTrue($results['status']);
|
||||
$this->assertCount(0, $results['warnings']);
|
||||
// Now, in the DB 0 responses.
|
||||
$this->assertCount(0, choice_get_my_response($choice));
|
||||
|
||||
// Submit again the responses.
|
||||
$results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
|
||||
|
||||
$myresponses = array_keys(choice_get_my_response($choice));
|
||||
// Delete only one response.
|
||||
$results = mod_choice_external::delete_choice_responses($choice->id, array($myresponses[0]));
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
|
||||
$this->assertTrue($results['status']);
|
||||
$this->assertCount(0, $results['warnings']);
|
||||
// Now, in the DB 1 response still.
|
||||
$this->assertCount(1, choice_get_my_response($choice));
|
||||
|
||||
// Delete the remaining response, passing 2 invalid responses ids.
|
||||
$results = mod_choice_external::delete_choice_responses($choice->id, array($myresponses[1], $myresponses[0] + 2,
|
||||
$myresponses[0] + 3));
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
|
||||
$this->assertTrue($results['status']);
|
||||
// 2 warnings, 2 invalid responses.
|
||||
$this->assertCount(2, $results['warnings']);
|
||||
// Now, in the DB 0 responses.
|
||||
$this->assertCount(0, choice_get_my_response($choice));
|
||||
|
||||
// Now, as an admin we must be able to delete all the responses under any condition.
|
||||
// Submit again the responses.
|
||||
$results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
|
||||
$studentresponses = array_keys(choice_get_my_response($choice));
|
||||
|
||||
$this->setAdminUser();
|
||||
$DB->set_field('choice', 'allowupdate', 0, array('id' => $choice->id));
|
||||
$DB->set_field('choice', 'timeclose', time() - DAYSECS, array('id' => $choice->id));
|
||||
|
||||
$results = mod_choice_external::delete_choice_responses($choice->id, array($studentresponses[0], $studentresponses[1]));
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
|
||||
|
||||
$this->assertTrue($results['status']);
|
||||
$this->assertCount(0, $results['warnings']);
|
||||
|
||||
// Submit again the responses.
|
||||
$DB->set_field('choice', 'timeclose', 0, array('id' => $choice->id));
|
||||
$results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
|
||||
// With other user account too, so we can test all the responses are deleted.
|
||||
choice_user_submit_response( array($options[1], $options[2]), $choice, $student->id, $course, $cm);
|
||||
|
||||
// Test deleting all (not passing the answers ids), event not only mine.
|
||||
$results = mod_choice_external::delete_choice_responses($choice->id);
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
|
||||
|
||||
$this->assertTrue($results['status']);
|
||||
$this->assertCount(0, $results['warnings']);
|
||||
$this->assertCount(0, choice_get_all_responses($choice));
|
||||
|
||||
// Now, in the DB 0 responses.
|
||||
$this->setUser($student);
|
||||
|
||||
// Submit again respones.
|
||||
$DB->set_field('choice', 'allowupdate', 1, array('id' => $choice->id));
|
||||
$DB->set_field('choice', 'timeclose', 0, array('id' => $choice->id));
|
||||
$results = mod_choice_external::submit_choice_response($choice->id, array($options[1], $options[2]));
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::submit_choice_response_returns(), $results);
|
||||
|
||||
// Delete all responses.
|
||||
$results = mod_choice_external::delete_choice_responses($choice->id);
|
||||
$results = external_api::clean_returnvalue(mod_choice_external::delete_choice_responses_returns(), $results);
|
||||
|
||||
$this->assertTrue($results['status']);
|
||||
$this->assertCount(0, $results['warnings']);
|
||||
$this->assertCount(0, choice_get_my_response($choice));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$plugin->version = 2015051102; // The current module version (Date: YYYYMMDDXX)
|
||||
$plugin->version = 2015051103; // The current module version (Date: YYYYMMDDXX)
|
||||
$plugin->requires = 2015050500; // Requires this Moodle version
|
||||
$plugin->component = 'mod_choice'; // Full name of the plugin (used for diagnostics)
|
||||
$plugin->cron = 0;
|
||||
|
@ -29,7 +29,7 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
$version = 2015100200.00; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
$version = 2015100200.01; // YYYYMMDD = weekly release date of this DEV branch.
|
||||
// RR = release increments - 00 in DEV branches.
|
||||
// .XX = incremental changes.
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user