/** * 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; require_once $CFG->libdir . '/completionlib.php'; $continueurl = new moodle_url('/mod/choice/view.php', array('id' => $cm->id)); if (empty($formanswer)) { print_error('atleastoneoption', 'choice', $continueurl); } if (is_array($formanswer)) { if (!$choice->allowmultiple) { print_error('multiplenotallowederror', 'choice', $continueurl); } $formanswers = $formanswer; } else { $formanswers = array($formanswer); } $options = $DB->get_records('choice_options', array('choiceid' => $choice->id), '', 'id'); foreach ($formanswers as $key => $val) { if (!isset($options[$val])) { print_error('cannotsubmit', 'choice', $continueurl); } } // Start lock to prevent synchronous access to the same data // before it's updated, if using limits. if ($choice->limitanswers) { $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', $continueurl); } } $current = $DB->get_records('choice_answers', array('choiceid' => $choice->id, 'userid' => $userid)); $context = context_module::instance($cm->id); $choicesexceeded = false; $countanswers = array(); foreach ($formanswers as $val) { $countanswers[$val] = 0; } if ($choice->limitanswers) { // Find out whether groups are being used and enabled if (groups_get_activity_groupmode($cm) > 0) { $currentgroup = groups_get_activity_group($cm); } else { $currentgroup = 0; } list($insql, $params) = $DB->get_in_or_equal($formanswers, SQL_PARAMS_NAMED); if ($currentgroup) { // If groups are being used, retrieve responses only for users in // current group global $CFG; $params['groupid'] = $currentgroup; $sql = "SELECT ca.*\n FROM {choice_answers} ca\n INNER JOIN {groups_members} gm ON ca.userid=gm.userid\n WHERE optionid {$insql}\n AND gm.groupid= :groupid"; } else { // Groups are not used, retrieve all answers for this option ID $sql = "SELECT ca.*\n FROM {choice_answers} ca\n WHERE optionid {$insql}"; } $answers = $DB->get_records_sql($sql, $params); if ($answers) { foreach ($answers as $a) { //only return enrolled users. if (is_enrolled($context, $a->userid, 'mod/choice:choose')) { $countanswers[$a->optionid]++; } } } foreach ($countanswers as $opt => $count) { if ($count >= $choice->maxanswers[$opt]) { $choicesexceeded = true; break; } } } // Check the user hasn't exceeded the maximum selections for the choice(s) they have selected. if (!($choice->limitanswers && $choicesexceeded)) { $answersnapshots = array(); if ($current) { // Update an existing answer. $existingchoices = array(); foreach ($current as $c) { if (in_array($c->optionid, $formanswers)) { $existingchoices[] = $c->optionid; $DB->set_field('choice_answers', 'timemodified', time(), array('id' => $c->id)); $answersnapshots[] = $c; } else { $DB->delete_records('choice_answers', array('id' => $c->id)); } } // Add new ones. foreach ($formanswers as $f) { if (!in_array($f, $existingchoices)) { $newanswer = new stdClass(); $newanswer->optionid = $f; $newanswer->choiceid = $choice->id; $newanswer->userid = $userid; $newanswer->timemodified = time(); $newanswer->id = $DB->insert_record("choice_answers", $newanswer); $answersnapshots[] = $newanswer; } } // 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; $newanswer->userid = $userid; $newanswer->optionid = $answer; $newanswer->timemodified = time(); $newanswer->id = $DB->insert_record("choice_answers", $newanswer); $answersnapshots[] = $newanswer; } // Update completion state $completion = new completion_info($course); if ($completion->is_enabled($cm) && $choice->completionsubmit) { $completion->update_state($cm, COMPLETION_COMPLETE); } // 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', $continueurl); } } // Release lock. if (isset($choicelock)) { $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(); } }
/** * Test custom validations * for answer_updated event. */ public function test_answer_updated_other_exception() { // Generate user data. $user = $this->getDataGenerator()->create_user(); $eventdata = array(); $eventdata['context'] = $this->context; $eventdata['objectid'] = 2; $eventdata['userid'] = $user->id; $eventdata['courseid'] = $this->course->id; $eventdata['other'] = array(); // Make sure content identifier is always set. $this->setExpectedException('coding_exception'); $event = \mod_choice\event\answer_updated::create($eventdata); $event->trigger(); $this->assertEventContextNotUsed($event); }
/** * @global object * @param int $formanswer * @param object $choice * @param int $userid * @param object $course Course object * @param object $cm */ function choice_user_submit_response($formanswer, $choice, $userid, $course, $cm) { global $DB, $CFG; require_once $CFG->libdir . '/completionlib.php'; $current = $DB->get_record('choice_answers', array('choiceid' => $choice->id, 'userid' => $userid)); $context = context_module::instance($cm->id); $countanswers = 0; if ($choice->limitanswers) { // Find out whether groups are being used and enabled if (groups_get_activity_groupmode($cm) > 0) { $currentgroup = groups_get_activity_group($cm); } else { $currentgroup = 0; } if ($currentgroup) { // If groups are being used, retrieve responses only for users in // current group global $CFG; $answers = $DB->get_records_sql("\nSELECT\n ca.*\nFROM\n {choice_answers} ca\n INNER JOIN {groups_members} gm ON ca.userid=gm.userid\nWHERE\n optionid=?\n AND gm.groupid=?", array($formanswer, $currentgroup)); } else { // Groups are not used, retrieve all answers for this option ID $answers = $DB->get_records("choice_answers", array("optionid" => $formanswer)); } if ($answers) { foreach ($answers as $a) { //only return enrolled users. if (is_enrolled($context, $a->userid, 'mod/choice:choose')) { $countanswers++; } } } $maxans = $choice->maxanswers[$formanswer]; } if (!($choice->limitanswers && $countanswers >= $maxans)) { if ($current) { $newanswer = $current; $newanswer->optionid = $formanswer; $newanswer->timemodified = time(); $DB->update_record("choice_answers", $newanswer); $eventdata = array(); $eventdata['context'] = $context; $eventdata['objectid'] = $newanswer->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('choice_answers', $newanswer); $event->add_record_snapshot('course', $course); $event->add_record_snapshot('course_modules', $cm); $event->trigger(); } else { $newanswer = new stdClass(); $newanswer->choiceid = $choice->id; $newanswer->userid = $userid; $newanswer->optionid = $formanswer; $newanswer->timemodified = time(); $newanswer->id = $DB->insert_record("choice_answers", $newanswer); // Update completion state $completion = new completion_info($course); if ($completion->is_enabled($cm) && $choice->completionsubmit) { $completion->update_state($cm, COMPLETION_COMPLETE); } $eventdata = array(); $eventdata['context'] = $context; $eventdata['objectid'] = $newanswer->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_submitted::create($eventdata); $event->add_record_snapshot('choice_answers', $newanswer); $event->add_record_snapshot('course', $course); $event->add_record_snapshot('course_modules', $cm); $event->trigger(); } } else { if (!($current->optionid == $formanswer)) { //check to see if current choice already selected - if not display error print_error('choicefull', 'choice'); } } }
/** * 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; require_once $CFG->libdir . '/completionlib.php'; $continueurl = new moodle_url('/mod/choice/view.php', array('id' => $cm->id)); // Start lock to prevent synchronous access to the same data // before it's updated, if using limits. if ($choice->limitanswers) { $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', $continueurl); } } $current = $DB->get_record('choice_answers', array('choiceid' => $choice->id, 'userid' => $userid)); $context = context_module::instance($cm->id); $countanswers = 0; if ($choice->limitanswers) { // Find out whether groups are being used and enabled if (groups_get_activity_groupmode($cm) > 0) { $currentgroup = groups_get_activity_group($cm); } else { $currentgroup = 0; } if ($currentgroup) { // If groups are being used, retrieve responses only for users in // current group global $CFG; $answers = $DB->get_records_sql("\nSELECT\n ca.*\nFROM\n {choice_answers} ca\n INNER JOIN {groups_members} gm ON ca.userid=gm.userid\nWHERE\n optionid=?\n AND gm.groupid=?", array($formanswer, $currentgroup)); } else { // Groups are not used, retrieve all answers for this option ID $answers = $DB->get_records("choice_answers", array("optionid" => $formanswer)); } if ($answers) { foreach ($answers as $a) { //only return enrolled users. if (is_enrolled($context, $a->userid, 'mod/choice:choose')) { $countanswers++; } } } $maxans = $choice->maxanswers[$formanswer]; } // Check the user hasn't exceeded the maximum selections for the choice(s) they have selected. if (!($choice->limitanswers && $countanswers >= $maxans)) { if ($current) { // Update an existing answer. $newanswer = $current; $newanswer->optionid = $formanswer; $newanswer->timemodified = time(); $DB->update_record("choice_answers", $newanswer); // Initialised as true, meaning we updated the answer. $answerupdated = true; } else { // Add new answer. $newanswer = new stdClass(); $newanswer->choiceid = $choice->id; $newanswer->userid = $userid; $newanswer->optionid = $formanswer; $newanswer->timemodified = time(); $newanswer->id = $DB->insert_record("choice_answers", $newanswer); // Update completion state $completion = new completion_info($course); if ($completion->is_enabled($cm) && $choice->completionsubmit) { $completion->update_state($cm, COMPLETION_COMPLETE); } // Initalised as false, meaning we submitted a new answer. $answerupdated = false; } } else { if (!($current->optionid == $formanswer)) { // Check to see if current choice already selected - if not display error. // Release lock before error. $choicelock->release(); print_error('choicefull', 'choice', $continueurl); } } // Release lock. if (isset($choicelock)) { $choicelock->release(); } // Now record completed event. if (isset($answerupdated)) { $eventdata = array(); $eventdata['context'] = $context; $eventdata['objectid'] = $newanswer->id; $eventdata['userid'] = $userid; $eventdata['courseid'] = $course->id; $eventdata['other'] = array(); $eventdata['other']['choiceid'] = $choice->id; $eventdata['other']['optionid'] = $formanswer; if ($answerupdated) { $event = \mod_choice\event\answer_updated::create($eventdata); } else { $event = \mod_choice\event\answer_submitted::create($eventdata); } $event->add_record_snapshot('choice_answers', $newanswer); $event->add_record_snapshot('course', $course); $event->add_record_snapshot('course_modules', $cm); $event->trigger(); } }