/** * Test custom validations. * * @expectedException coding_exception */ public function test_answer_created_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. $event = \mod_choice\event\answer_created::create($eventdata); $event->trigger(); $this->assertEventContextNotUsed($event); }
/** * 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, $USER; 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, MINSECS); 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. $answersnapshots = array(); $deletedanswersnapshots = array(); if (!($choice->limitanswers && $choicesexceeded)) { 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)); } else { $deletedanswersnapshots[] = $c; $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; } } } 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); } } } 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(); } // Trigger events. foreach ($deletedanswersnapshots as $answer) { \mod_choice\event\answer_deleted::create_from_object($answer, $choice, $cm, $course)->trigger(); } foreach ($answersnapshots as $answer) { \mod_choice\event\answer_created::create_from_object($answer, $choice, $cm, $course)->trigger(); } }