/** * 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_randchoice\event\answer_updated::create($eventdata); $event->trigger(); $this->assertEventContextNotUsed($event); }
/** * Process user submitted answers for a randchoice, * and either updating them or saving new answers. * * @param int $formanswer users submitted answers. * @param object $randchoice the selected randchoice. * @param int $userid user identifier. * @param object $course current course. * @param object $cm course context. * @return void */ function randchoice_user_submit_response($formanswer, $randchoice, $userid, $course, $cm) { global $DB, $CFG; require_once $CFG->libdir . '/completionlib.php'; $continueurl = new moodle_url('/mod/randchoice/view.php', array('id' => $cm->id)); if (empty($formanswer)) { print_error('atleastoneoption', 'randchoice', $continueurl); } if (is_array($formanswer)) { if (!$randchoice->allowmultiple) { print_error('multiplenotallowederror', 'randchoice', $continueurl); } $formanswers = $formanswer; } else { $formanswers = array($formanswer); } // Start lock to prevent synchronous access to the same data // before it's updated, if using limits. if ($randchoice->limitanswers) { $timeout = 10; $locktype = 'mod_randchoice_randchoice_user_submit_response'; // Limiting access to this randchoice. $resouce = 'randchoiceid:' . $randchoice->id; $lockfactory = \core\lock\lock_config::get_lock_factory($locktype); // Opening the lock. $randchoicelock = $lockfactory->get_lock($resouce, $timeout); if (!$randchoicelock) { print_error('cannotsubmit', 'randchoice', $continueurl); } } $current = $DB->get_records('randchoice_answers', array('randchoiceid' => $randchoice->id, 'userid' => $userid)); $context = context_module::instance($cm->id); $randchoicesexceeded = false; $countanswers = array(); foreach ($formanswers as $val) { $countanswers[$val] = 0; } if ($randchoice->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 {randchoice_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 {randchoice_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/randchoice:choose')) { $countanswers[$a->optionid]++; } } } foreach ($countanswers as $opt => $count) { if ($count >= $randchoice->maxanswers[$opt]) { $randchoicesexceeded = true; break; } } } // Check the user hasn't exceeded the maximum selections for the randchoice(s) they have selected. if (!($randchoice->limitanswers && $randchoicesexceeded)) { $answersnapshots = array(); if ($current) { // Update an existing answer. $existingrandchoices = array(); foreach ($current as $c) { if (in_array($c->optionid, $formanswers)) { $existingrandchoices[] = $c->optionid; $DB->set_field('randchoice_answers', 'timemodified', time(), array('id' => $c->id)); $answersnapshots[] = $c; } else { $DB->delete_records('randchoice_answers', array('id' => $c->id)); } } // Add new ones. foreach ($formanswers as $f) { if (!in_array($f, $existingrandchoices)) { $newanswer = new stdClass(); $newanswer->optionid = $f; $newanswer->randchoiceid = $randchoice->id; $newanswer->userid = $userid; $newanswer->timemodified = time(); $newanswer->id = $DB->insert_record("randchoice_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->randchoiceid = $randchoice->id; $newanswer->userid = $userid; $newanswer->optionid = $answer; $newanswer->timemodified = time(); $newanswer->id = $DB->insert_record("randchoice_answers", $newanswer); $answersnapshots[] = $newanswer; } // Update completion state $completion = new completion_info($course); if ($completion->is_enabled($cm) && $randchoice->completionsubmit) { $completion->update_state($cm, COMPLETION_COMPLETE); } // Initalised as false, meaning we submitted a new answer. $answerupdated = false; } } else { // Check to see if current randchoice already selected - if not display error. $currentids = array_keys($current); if (array_diff($currentids, $formanswers) || array_diff($formanswers, $currentids)) { // Release lock before error. $randchoicelock->release(); print_error('randchoicefull', 'randchoice', $continueurl); } } // Release lock. if (isset($randchoicelock)) { $randchoicelock->release(); } // Now record completed event. if (isset($answerupdated)) { $eventdata = array(); $eventdata['context'] = $context; $eventdata['objectid'] = $randchoice->id; $eventdata['userid'] = $userid; $eventdata['courseid'] = $course->id; $eventdata['other'] = array(); $eventdata['other']['randchoiceid'] = $randchoice->id; if ($answerupdated) { $eventdata['other']['optionid'] = $formanswer; $event = \mod_randchoice\event\answer_updated::create($eventdata); } else { $eventdata['other']['optionid'] = $formanswers; $event = \mod_randchoice\event\answer_submitted::create($eventdata); } $event->add_record_snapshot('course', $course); $event->add_record_snapshot('course_modules', $cm); $event->add_record_snapshot('randchoice', $randchoice); foreach ($answersnapshots as $record) { $event->add_record_snapshot('randchoice_answers', $record); } $event->trigger(); } }