require_login($quizobj->get_courseid(), false, $quizobj->get_cm()); if (!confirm_sesskey()) { throw new moodle_exception('confirmsesskeybad', 'error', $quizobj->view_url()); } /// if no questions have been set up yet redirect to edit.php if (!$quizobj->get_question_ids() && $quizobj->has_capability('mod/quiz:manage')) { redirect($quizobj->edit_url()); } /// Create an object to manage all the other (non-roles) access rules. $accessmanager = $quizobj->get_access_manager(time()); if ($quizobj->is_preview_user() && $forcenew) { $accessmanager->clear_password_access(); } /// Check capabilites. if (!$quizobj->is_preview_user()) { $quizobj->require_capability('mod/quiz:attempt'); } /// Check to see if a new preview was requested. if ($quizobj->is_preview_user() && $forcenew) { /// To force the creation of a new preview, we set a finish time on the /// current attempt (if any). It will then automatically be deleted below $DB->set_field('quiz_attempts', 'timefinish', time(), array('quiz' => $quiz->id, 'userid' => $USER->id)); } /// Look for an existing attempt. $lastattempt = quiz_get_latest_attempt_by_user($quiz->id, $USER->id); if ($lastattempt && !$lastattempt->timefinish) { /// Continuation of an attempt - check password then redirect. $accessmanager->do_password_check($quizobj->is_preview_user()); redirect($quizobj->attempt_url($lastattempt->id)); } /// Get number for the next or unfinished attempt
/** * Validate permissions for creating a new attempt and start a new preview attempt if required. * * @param quiz $quizobj quiz object * @param quiz_access_manager $accessmanager quiz access manager * @param bool $forcenew whether was required to start a new preview attempt * @param int $page page to jump to in the attempt * @param bool $redirect whether to redirect or throw exceptions (for web or ws usage) * @return array an array containing the attempt information, access error messages and the page to jump to in the attempt * @throws moodle_quiz_exception * @since Moodle 3.1 */ function quiz_validate_new_attempt(quiz $quizobj, quiz_access_manager $accessmanager, $forcenew, $page, $redirect) { global $DB, $USER; $timenow = time(); if ($quizobj->is_preview_user() && $forcenew) { $accessmanager->current_attempt_finished(); } // Check capabilities. if (!$quizobj->is_preview_user()) { $quizobj->require_capability('mod/quiz:attempt'); } // Check to see if a new preview was requested. if ($quizobj->is_preview_user() && $forcenew) { // To force the creation of a new preview, we mark the current attempt (if any) // as finished. It will then automatically be deleted below. $DB->set_field('quiz_attempts', 'state', quiz_attempt::FINISHED, array('quiz' => $quizobj->get_quizid(), 'userid' => $USER->id)); } // Look for an existing attempt. $attempts = quiz_get_user_attempts($quizobj->get_quizid(), $USER->id, 'all', true); $lastattempt = end($attempts); $attemptnumber = null; // If an in-progress attempt exists, check password then redirect to it. if ($lastattempt && ($lastattempt->state == quiz_attempt::IN_PROGRESS || $lastattempt->state == quiz_attempt::OVERDUE)) { $currentattemptid = $lastattempt->id; $messages = $accessmanager->prevent_access(); // If the attempt is now overdue, deal with that. $quizobj->create_attempt_object($lastattempt)->handle_if_time_expired($timenow, true); // And, if the attempt is now no longer in progress, redirect to the appropriate place. if ($lastattempt->state == quiz_attempt::ABANDONED || $lastattempt->state == quiz_attempt::FINISHED) { if ($redirect) { redirect($quizobj->review_url($lastattempt->id)); } else { throw new moodle_quiz_exception($quizobj, 'attemptalreadyclosed'); } } // If the page number was not explicitly in the URL, go to the current page. if ($page == -1) { $page = $lastattempt->currentpage; } } else { while ($lastattempt && $lastattempt->preview) { $lastattempt = array_pop($attempts); } // Get number for the next or unfinished attempt. if ($lastattempt) { $attemptnumber = $lastattempt->attempt + 1; } else { $lastattempt = false; $attemptnumber = 1; } $currentattemptid = null; $messages = $accessmanager->prevent_access() + $accessmanager->prevent_new_attempt(count($attempts), $lastattempt); if ($page == -1) { $page = 0; } } return array($currentattemptid, $attemptnumber, $lastattempt, $messages, $page); }