Moving quiz-independent question scripts to their new location. In a following commit...
[moodle.git] / question / preview.php
CommitLineData
516cf3eb 1<?php // $Id$
2/**
3* This page displays a preview of a question
4*
5* The preview uses the option settings from the quiz within which the question
6* is previewed or the default settings if no quiz is specified. The question session
7* information is stored in the session as an array of subsequent states rather
8* than in the database.
9* @version $Id$
10* @author Alex Smith as part of the Serving Mathematics project
11* {@link http://maths.york.ac.uk/serving_maths}
12* @license http://www.gnu.org/copyleft/gpl.html GNU Public License
13* @package quiz
14*/
15
16 require_once("../../config.php");
17 require_once("locallib.php");
18
19 $id = required_param('id', PARAM_INT); // question id
20 // if no quiz id is specified then a dummy quiz with default options is used
21 $quizid = optional_param('quizid', 0, PARAM_INT);
22 // Test if we are continuing an attempt at a question
23 $continue = optional_param('continue', 0, PARAM_BOOL);
24 // Check for any of the submit buttons
25 $fillcorrect = optional_param('fillcorrect', 0, PARAM_BOOL);
26 $markall = optional_param('markall', 0, PARAM_BOOL);
27 $finishattempt = optional_param('finishattempt', 0, PARAM_BOOL);
28 $back = optional_param('back', 0, PARAM_BOOL);
29 $startagain = optional_param('startagain', 0, PARAM_BOOL);
30 // We are always continuing an attempt if a submit button was pressed with the
31 // exception of the start again button
32 if ($fillcorrect || $markall || $finishattempt || $back) {
33 $continue = true;
34 } else if ($startagain) {
35 $continue = false;
36 }
37
38 require_login();
39
40 if (!isteacherinanycourse()) {
41 error('This page is for teachers only');
42 }
43
44 if (!$continue) {
45 // Start a new attempt; delete the old session
46 unset($SESSION->quizpreview);
47 // Redirect to ourselves but with continue=1; prevents refreshing the page
48 // from restarting an attempt (needed so that random questions don't change)
49 $quizid = $quizid ? '&amp;quizid=' . $quizid : '';
50 redirect($CFG->wwwroot . '/mod/quiz/preview.php?id=' . $id . $quizid .
51 '&amp;continue=1');
52 }
53
54 if (empty($quizid)) {
55 // get a sample quiz to be used as a skeleton
56 // this should really be done properly by instantiating a quiz object
57 if (!$quiz = get_records('quiz')) {
58 error('You have to create at least one quiz before using this preview');
59 }
60 $quiz = array_values($quiz);
61 $quiz = $quiz[0];
62
63 // set everything to the default values
64 foreach($quiz as $field => $value) {
65 $quizfield = "quiz_".$field;
66 if(isset($CFG->$quizfield)) {
67 $quiz->$field = $CFG->$quizfield;
68 }
69 else {
70 $quiz->$field = 0;
71 }
72 }
73
74 } else if (!$quiz = get_record('quiz', 'id', $quizid)) {
75 error("Quiz id $quizid does not exist");
76 }
77
78 // Load the question information
79 if (!$questions = get_records('quiz_questions', 'id', $id)) {
80 error('Could not load question');
81 }
82 if ($maxgrade = get_field('quiz_question_instances', 'grade', 'quiz', $quiz->id, 'question', $id)) {
83 $questions[$id]->maxgrade = $maxgrade;
84 } else {
85 $questions[$id]->maxgrade = $questions[$id]->defaultgrade;
86 }
87
88 $quiz->id = 0; // just for safety
89 $quiz->questions = $id;
90
91 if (!$category = get_record("quiz_categories", "id", $questions[$id]->category)) {
92 error("This question doesn't belong to a valid category!");
93 }
94
95 if (!isteacher($category->course) and !$category->publish) {
96 error("You can't preview these questions!");
97 }
98 $quiz->course = $category->course;
99
100 // Load the question type specific information
101 if (!quiz_get_question_options($questions)) {
102 error(get_string('newattemptfail', 'quiz'));
103 }
104
105 // Create a dummy quiz attempt
106 $attempt = quiz_create_attempt($quiz, 0);
107 $attempt->id = 0;
108
109 // Restore the history of question sessions from the moodle session or create
110 // new sessions. Make $states a reference to the states array in the moodle
111 // session.
112 if (isset($SESSION->quizpreview->states) and $SESSION->quizpreview->questionid
113 == $id) {
114 // Reload the question session history from the moodle session
115 $states =& $SESSION->quizpreview->states;
116 $historylength = count($states) - 1;
117 if ($back && $historylength > 0) {
118 // Go back one step in the history
119 unset($states[$historylength]);
120 $historylength--;
121 }
122 } else {
123 // Record the question id in the moodle session
124 $SESSION->quizpreview->questionid = $id;
125 // Create an empty session for the question
126 if (!$newstates =
127 quiz_get_states($questions, $quiz, $attempt)) {
128 error(get_string('newattemptfail', 'quiz'));
129 }
130 $SESSION->quizpreview->states = array($newstates);
131 $states =& $SESSION->quizpreview->states;
132 $historylength = 0;
133 }
134
135 if (!$fillcorrect && !$back && ($form = data_submitted())) {
136 $form = (array)$form;
137 $submitted = true;
138
139 // Create a new item in the history of question states (don't simplify!)
140 $states[$historylength + 1] = array();
141 $states[$historylength + 1][$id] = clone($states[$historylength][$id]);
142 $historylength++;
143 $curstate =& $states[$historylength][$id];
144
145 // Process the responses
146 unset($form['id']);
147 unset($form['quizid']);
148 unset($form['continue']);
149 unset($form['markall']);
150 unset($form['finishattempt']);
151 unset($form['back']);
152 unset($form['startagain']);
153
154 $event = $finishattempt ? QUIZ_EVENTCLOSE : ($markall ? QUIZ_EVENTGRADE : QUIZ_EVENTSAVE);
155 if ($actions = quiz_extract_responses($questions, $form, $event)) {
156 $actions[$id]->timestamp = 0; // We do not care about timelimits here
157 quiz_process_responses($questions[$id], $states[$historylength][$id], $actions[$id], $quiz, $attempt);
158 if (QUIZ_EVENTGRADE != $curstate->event && QUIZ_EVENTCLOSE != $curstate->event) {
159 // Update the current state rather than creating a new one
160 $historylength--;
161 unset($states[$historylength]);
162 $states = array_values($states);
163 $curstate =& $states[$historylength][$id];
164 }
165 }
166 } else {
167 $submitted = false;
168 $curstate =& $states[$historylength][$id];
169 }
170
171 $options = quiz_get_renderoptions($quiz, $curstate);
172
173 // Fill in the correct responses (unless the question is in readonly mode)
174 if ($fillcorrect && !$options->readonly) {
175 $curstate->responses = $QUIZ_QTYPES[$questions[$id]->qtype]
176 ->get_correct_responses($questions[$id], $curstate);
177 }
178
179 $strpreview = get_string('previewquestion', 'quiz');
180 print_header($strpreview);
181 print_heading($strpreview);
182
183 echo '<p align="center">' . get_string('modulename', 'quiz') . ': ';
184 if (empty($quizid)) {
185 echo '[' . get_string('default', 'quiz') . ']';
186 } else {
187 p($quiz->name);
188 }
189 echo '<br />'.get_string('question', 'quiz').': ';
190 p($questions[$id]->name);
191 echo "</p>\n";
192 $number = 1;
193 echo "<form method=\"post\" action=\"preview.php\" autocomplete=\"off\">\n";
194 echo "<input type=\"hidden\" name=\"id\" value=\"$id\" />\n";
195 echo "<input type=\"hidden\" name=\"quizid\" value=\"$quizid\" />\n";
196 echo "<input type=\"hidden\" name=\"continue\" value=\"1\" />\n";
197
198 quiz_print_quiz_question($questions[$id], $curstate, $number, $quiz, $options);
199
200 echo '<br />';
201 echo '<center>';
202
203 // Print the mark and finish attempt buttons
204 echo '<input name="markall" type="submit" value="' . get_string('markall',
205 'quiz') . "\" />\n";
206 echo '<input name="finishattempt" type="submit" value="' .
207 get_string('finishattempt', 'quiz') . "\" />\n";
208 echo '<br />';
209 echo '<br />';
210 // Print the fill correct button (unless the question is in readonly mode)
211 if (!$options->readonly) {
212 echo '<input name="fillcorrect" type="submit" value="' .
213 get_string('fillcorrect', 'quiz') . "\" />\n";
214 }
215 // Print the navigation buttons
216 if ($historylength > 0) {
217 echo '<input name="back" type="submit" value="' . get_string('previous',
218 'quiz') . "\" />\n";
219 }
220 // Print the start again button
221 echo '<input name="startagain" type="submit" value="' .
222 get_string('startagain', 'quiz') . "\" />\n";
223 // Print the close window button
224 echo '<input type="button" onclick="window.close()" value="' .
225 get_string('closepreview', 'quiz') . "\" />";
226 echo '</center>';
227 echo '</form>';
228 print_footer();
229?>