예제 #1
0
 /**
  * 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);
 }
예제 #2
0
/**
 * 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();
    }
}