MDL-15452 - Put the OU quiz navigation improvements into the Moodle codebase. I was...
[moodle.git] / mod / quiz / startattempt.php
CommitLineData
78e7a3dd 1<?php // $Id$
2/**
3 * This page deals with starting a new attempt at a quiz.
4 *
5 * Normally, it will end up redirecting to attempt.php - unless a password form is displayed.
6 *
7 * @author Tim Hunt.
8 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
9 * @package quiz
10 */
11
12require_once(dirname(__FILE__) . '/../../config.php');
13require_once($CFG->dirroot . '/mod/quiz/locallib.php');
14
15/// Get submitted parameters.
16$id = required_param('cmid', PARAM_INT); // Course Module ID
17$forcenew = optional_param('forcenew', false, PARAM_BOOL); // Used to force a new preview
18
19if (!$cm = get_coursemodule_from_id('quiz', $id)) {
20 print_error('invalidcoursemodule');
21}
22if (!$course = $DB->get_record('course', array('id' => $cm->course))) {
23 print_error("coursemisconf");
24}
25if (!$quiz = $DB->get_record('quiz', array('id' => $cm->instance))) {
26 print_error('invalidcoursemodule');
27}
28
29$quizobj = new quiz($quiz, $cm, $course);
30
b1103f2b 31/// Check login and sesskey.
78e7a3dd 32require_login($quizobj->get_courseid(), false, $quizobj->get_cm());
b1103f2b 33if (!confirm_sesskey()) {
34 throw new moodle_exception('confirmsesskeybad', 'error', $quizobj->view_url());
35}
78e7a3dd 36
37/// if no questions have been set up yet redirect to edit.php
38if (!$quizobj->get_question_ids() && $quizobj->has_capability('mod/quiz:manage')) {
39 redirect($quizobj->edit_url());
40}
41
42/// Create an object to manage all the other (non-roles) access rules.
43$accessmanager = $quizobj->get_access_manager(time());
44if ($quizobj->is_preview_user() && $forcenew) {
45 $accessmanager->clear_password_access();
46}
47
78e7a3dd 48
49/// Check capabilites.
50if (!$quizobj->is_preview_user()) {
51 $quizobj->require_capability('mod/quiz:attempt');
52}
53
54/// Check to see if a new preview was requested.
55if ($quizobj->is_preview_user() && $forcenew) {
56/// To force the creation of a new preview, we set a finish time on the
57/// current attempt (if any). It will then automatically be deleted below
58 $DB->set_field('quiz_attempts', 'timefinish', time(), array('quiz' => $quiz->id, 'userid' => $USER->id));
59}
60
61/// Look for an existing attempt.
62$lastattempt = quiz_get_latest_attempt_by_user($quiz->id, $USER->id);
63
64if ($lastattempt && !$lastattempt->timefinish) {
65/// Continuation of an attempt - check password then redirect.
66 $accessmanager->do_password_check($quizobj->is_preview_user());
67 redirect($quizobj->attempt_url($lastattempt->id));
68}
69
70/// Get number for the next or unfinished attempt
71if ($lastattempt && !$lastattempt->preview && !$quizobj->is_preview_user()) {
72 $lastattemptid = $lastattempt->id;
73 $attemptnumber = $lastattempt->attempt + 1;
74} else {
75 $lastattempt = false;
76 $lastattemptid = false;
77 $attemptnumber = 1;
78}
79
80/// Check access.
81$messages = $accessmanager->prevent_access() +
82 $accessmanager->prevent_new_attempt($attemptnumber - 1, $lastattempt);
83if (!$quizobj->is_preview_user() && $messages) {
84 print_error('attempterror', 'quiz', $quizobj->view_url(),
85 $accessmanager->print_messages($messages, true));
86}
87$accessmanager->do_password_check($quizobj->is_preview_user());
88
89/// Delete any previous preview attempts belonging to this user.
90if ($oldattempts = $DB->get_records_select('quiz_attempts', "quiz = ?
91 AND userid = ? AND preview = 1", array($quiz->id, $USER->id))) {
92 foreach ($oldattempts as $oldattempt) {
93 quiz_delete_attempt($oldattempt, $quiz);
94 }
95}
96
97/// Create the new attempt and initialize the question sessions
98$attempt = quiz_create_attempt($quiz, $attemptnumber, $lastattempt, time(), $quizobj->is_preview_user());
99
100/// Save the attempt in the database.
101if (!$attempt->id = $DB->insert_record('quiz_attempts', $attempt)) {
102 quiz_error($quiz, 'newattemptfail');
103}
104
105/// Log the new attempt.
106if ($attempt->preview) {
b1103f2b 107 add_to_log($course->id, 'quiz', 'preview', 'view.php?id=' . $quizobj->get_cmid(),
108 $quizobj->get_quizid(), $quizobj->get_cmid());
78e7a3dd 109} else {
b1103f2b 110 add_to_log($course->id, 'quiz', 'attempt', 'review.php?attempt=' . $attempt->id,
111 $quizobj->get_quizid(), $quizobj->get_cmid());
78e7a3dd 112}
113
114/// Fully load all the questions in this quiz.
115$quizobj->preload_questions();
116$quizobj->load_questions();
117
118/// Create initial states for all questions in this quiz.
119if (!$states = get_question_states($quizobj->get_questions(), $quizobj->get_quiz(), $attempt, $lastattemptid)) {
120 print_error('cannotrestore', 'quiz');
121}
122
123/// Save all the newly created states.
124foreach ($quizobj->get_questions() as $i => $question) {
125 save_question_session($question, $states[$i]);
126}
127
128/// Redirect to the attempt page.
129redirect($quizobj->attempt_url($attempt->id));
130?>