/** * Saves the current state of the question session to the database * * The state object representing the current state of the session for the * question is saved to the question_states table with ->responses[''] saved * to the answer field of the database table. The information in the * question_sessions table is updated. * The question type specific data is then saved. * @return mixed The id of the saved or updated state or false * @param object $question The question for which session is to be saved. * @param object $state The state information to be saved. In particular the * most recent responses are in ->responses. The object * is updated to hold the new ->id. */ function save_question_session($question, $state) { global $QTYPES, $DB; // Check if the state has changed if (!$state->changed && isset($state->id)) { if (isset($state->newflaggedstate) && $state->flagged != $state->newflaggedstate) { // If this fails, don't worry too much, it is not critical data. question_update_flag($state->questionsessionid, $state->newflaggedstate); } return $state->id; } // Set the legacy answer field $state->answer = isset($state->responses['']) ? $state->responses[''] : ''; // Save the state if (!empty($state->update)) { // this forces the old state record to be overwritten $DB->update_record('question_states', $state); } else { if (!($state->id = $DB->insert_record('question_states', $state))) { unset($state->id); unset($state->answer); return false; } } // create or update the session if (!($session = $DB->get_record('question_sessions', array('attemptid' => $state->attempt, 'questionid' => $question->id)))) { $session = new stdClass(); $session->attemptid = $state->attempt; $session->questionid = $question->id; $session->newest = $state->id; // The following may seem weird, but the newgraded field needs to be set // already even if there is no graded state yet. $session->newgraded = $state->id; $session->sumpenalty = $state->sumpenalty; $session->manualcomment = $state->manualcomment; $session->flagged = !empty($state->newflaggedstate); if (!$DB->insert_record('question_sessions', $session)) { return false; } } else { $session->newest = $state->id; if (question_state_is_graded($state) or $state->event == QUESTION_EVENTOPEN) { // this state is graded or newly opened, so it goes into the lastgraded field as well $session->newgraded = $state->id; $session->sumpenalty = $state->sumpenalty; $session->manualcomment = $state->manualcomment; } else { $session->manualcomment = $session->manualcomment; } $session->flagged = !empty($state->newflaggedstate); if (!$DB->update_record('question_sessions', $session)) { return false; } } unset($state->answer); // Save the question type specific state information and responses if (!$QTYPES[$question->qtype]->save_session_and_responses($question, $state)) { return false; } // Reset the changed flag $state->changed = false; return $state->id; }
require_once $CFG->libdir . '/questionlib.php'; // Parameters $sessionid = required_param('qsid', PARAM_INT); $attemptid = required_param('aid', PARAM_INT); $questionid = required_param('qid', PARAM_INT); $newstate = required_param('newstate', PARAM_BOOL); $checksum = required_param('checksum', PARAM_ALPHANUM); // Check user is logged in. require_login(); // Check the sesskey. if (!confirm_sesskey()) { echo 'sesskey failure'; } // Check the checksum - it is very hard to know who a question session belongs // to, so we require that checksum parameter is matches an md5 hash of the // three ids and the users username. Since we are only updating a flag, that // probably makes it sufficiently difficult for malicious users to toggle // other users flags. if ($checksum != md5($attemptid . "_" . $USER->secret . "_" . $questionid . "_" . $sessionid)) { echo 'checksum failure'; } // Check that the requested session really exists $questionsession = $DB->get_record('question_sessions', array('id' => $sessionid, 'attemptid' => $attemptid, 'questionid' => $questionid)); if (!$questionsession) { echo 'invalid ids'; } // Now change state if (!question_update_flag($sessionid, $newstate)) { echo 'update failed'; } echo 'OK';