mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 00:12:56 +02:00
MDL-23273 mod_choice: Using locks to ensure choice limits
This commit is contained in:
parent
95751e81ac
commit
e776b415f4
@ -27,6 +27,7 @@ $string['addmorechoices'] = 'Add more choices';
|
||||
$string['allowupdate'] = 'Allow choice to be updated';
|
||||
$string['allowmultiple'] = 'Allow more than one choice to be selected';
|
||||
$string['answered'] = 'Answered';
|
||||
$string['cannotsubmit'] = 'Sorry, there was a problem submitting your choice. Please try again.';
|
||||
$string['completionsubmit'] = 'Show as complete when user makes a choice';
|
||||
$string['displayhorizontal'] = 'Display horizontally';
|
||||
$string['displaymode'] = 'Display mode for the options';
|
||||
|
@ -236,12 +236,15 @@ function choice_prepare_options($choice, $user, $coursemodule, $allresponses) {
|
||||
}
|
||||
|
||||
/**
|
||||
* @global object
|
||||
* @param int $formanswer
|
||||
* @param object $choice
|
||||
* @param int $userid
|
||||
* @param object $course Course object
|
||||
* @param object $cm
|
||||
* Process user submitted answers for a choice,
|
||||
* and either updating them or saving new answers.
|
||||
*
|
||||
* @param int $formanswer users submitted answers.
|
||||
* @param object $choice the selected choice.
|
||||
* @param int $userid user identifier.
|
||||
* @param object $course current course.
|
||||
* @param object $cm course context.
|
||||
* @return void
|
||||
*/
|
||||
function choice_user_submit_response($formanswer, $choice, $userid, $course, $cm) {
|
||||
global $DB, $CFG;
|
||||
@ -260,6 +263,20 @@ function choice_user_submit_response($formanswer, $choice, $userid, $course, $cm
|
||||
$formanswers = array($formanswer);
|
||||
}
|
||||
|
||||
// Start lock to prevent synchronous access to the same data
|
||||
// before it's updated.
|
||||
$timeout = 10;
|
||||
$locktype = 'mod_choice_choice_user_submit_response';
|
||||
// Limiting access to this choice.
|
||||
$resouce = 'choiceid:' . $choice->id;
|
||||
$lockfactory = \core\lock\lock_config::get_lock_factory($locktype);
|
||||
|
||||
// Opening the lock.
|
||||
$choicelock = $lockfactory->get_lock($resouce, $timeout);
|
||||
if (!$choicelock) {
|
||||
print_error('cannotsubmit', 'choice');
|
||||
}
|
||||
|
||||
$current = $DB->get_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $userid));
|
||||
$context = context_module::instance($cm->id);
|
||||
|
||||
@ -305,7 +322,7 @@ function choice_user_submit_response($formanswer, $choice, $userid, $course, $cm
|
||||
}
|
||||
}
|
||||
foreach ($countanswers as $opt => $count) {
|
||||
if ($count > $choice->maxanswers[$opt]) {
|
||||
if ($count >= $choice->maxanswers[$opt]) {
|
||||
$choicesexceeded = true;
|
||||
break;
|
||||
}
|
||||
@ -316,7 +333,7 @@ function choice_user_submit_response($formanswer, $choice, $userid, $course, $cm
|
||||
if (!($choice->limitanswers && $choicesexceeded)) {
|
||||
$answersnapshots = array();
|
||||
if ($current) {
|
||||
|
||||
// Update an existing answer.
|
||||
$existingchoices = array();
|
||||
foreach ($current as $c) {
|
||||
if (in_array($c->optionid, $formanswers)) {
|
||||
@ -341,25 +358,10 @@ function choice_user_submit_response($formanswer, $choice, $userid, $course, $cm
|
||||
}
|
||||
}
|
||||
|
||||
$eventdata = array();
|
||||
$eventdata['context'] = $context;
|
||||
$eventdata['objectid'] = $choice->id;
|
||||
$eventdata['userid'] = $userid;
|
||||
$eventdata['courseid'] = $course->id;
|
||||
$eventdata['other'] = array();
|
||||
$eventdata['other']['choiceid'] = $choice->id;
|
||||
$eventdata['other']['optionid'] = $formanswer;
|
||||
|
||||
$event = \mod_choice\event\answer_updated::create($eventdata);
|
||||
$event->add_record_snapshot('course', $course);
|
||||
$event->add_record_snapshot('course_modules', $cm);
|
||||
$event->add_record_snapshot('choice', $choice);
|
||||
foreach ($answersnapshots as $record) {
|
||||
$event->add_record_snapshot('choice_answers', $record);
|
||||
}
|
||||
$event->trigger();
|
||||
// Initialised as true, meaning we updated the answer.
|
||||
$answerupdated = true;
|
||||
} else {
|
||||
|
||||
// Add new answer.
|
||||
foreach ($formanswers as $answer) {
|
||||
$newanswer = new stdClass();
|
||||
$newanswer->choiceid = $choice->id;
|
||||
@ -376,31 +378,48 @@ function choice_user_submit_response($formanswer, $choice, $userid, $course, $cm
|
||||
$completion->update_state($cm, COMPLETION_COMPLETE);
|
||||
}
|
||||
|
||||
$eventdata = array();
|
||||
$eventdata['context'] = $context;
|
||||
$eventdata['objectid'] = $choice->id;
|
||||
$eventdata['userid'] = $userid;
|
||||
$eventdata['courseid'] = $course->id;
|
||||
$eventdata['other'] = array();
|
||||
$eventdata['other']['choiceid'] = $choice->id;
|
||||
$eventdata['other']['optionid'] = $formanswers;
|
||||
|
||||
$event = \mod_choice\event\answer_submitted::create($eventdata);
|
||||
$event->add_record_snapshot('course', $course);
|
||||
$event->add_record_snapshot('course_modules', $cm);
|
||||
$event->add_record_snapshot('choice', $choice);
|
||||
foreach ($answersnapshots as $record) {
|
||||
$event->add_record_snapshot('choice_answers', $record);
|
||||
}
|
||||
$event->trigger();
|
||||
// Initalised as false, meaning we submitted a new answer.
|
||||
$answerupdated = false;
|
||||
}
|
||||
} else {
|
||||
// Check to see if current choice already selected - if not display error.
|
||||
$currentids = array_keys($current);
|
||||
|
||||
if (array_diff($currentids, $formanswers) || array_diff($formanswers, $currentids) ) {
|
||||
// Release lock before error.
|
||||
$choicelock->release();
|
||||
print_error('choicefull', 'choice');
|
||||
}
|
||||
}
|
||||
|
||||
// Release lock.
|
||||
$choicelock->release();
|
||||
|
||||
// Now record completed event.
|
||||
if (isset($answerupdated)) {
|
||||
$eventdata = array();
|
||||
$eventdata['context'] = $context;
|
||||
$eventdata['objectid'] = $choice->id;
|
||||
$eventdata['userid'] = $userid;
|
||||
$eventdata['courseid'] = $course->id;
|
||||
$eventdata['other'] = array();
|
||||
$eventdata['other']['choiceid'] = $choice->id;
|
||||
|
||||
if ($answerupdated) {
|
||||
$eventdata['other']['optionid'] = $formanswer;
|
||||
$event = \mod_choice\event\answer_updated::create($eventdata);
|
||||
} else {
|
||||
$eventdata['other']['optionid'] = $formanswers;
|
||||
$event = \mod_choice\event\answer_submitted::create($eventdata);
|
||||
}
|
||||
$event->add_record_snapshot('course', $course);
|
||||
$event->add_record_snapshot('course_modules', $cm);
|
||||
$event->add_record_snapshot('choice', $choice);
|
||||
foreach ($answersnapshots as $record) {
|
||||
$event->add_record_snapshot('choice_answers', $record);
|
||||
}
|
||||
$event->trigger();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user