MDL-15942 - separate data escaped for database entry from unescaped data
[moodle-linuxchix.git] / question / preview.php
blobe6b278e5566e11a0a1f615c9ea0ff755eb81ec9c
1 <?php // $Id$
2 /**
3 * This page displays a preview of a question
5 * The preview uses the option settings from the activity within which the question
6 * is previewed or the default settings if no activity is specified. The question session
7 * information is stored in the session as an array of subsequent states rather
8 * than in the database.
10 * TODO: make this work with activities other than quiz
12 * @author Alex Smith as part of the Serving Mathematics project
13 * {@link http://maths.york.ac.uk/serving_maths}
14 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
15 * @package questionbank
18 require_once("../config.php");
19 require_once($CFG->libdir.'/questionlib.php');
20 require_once($CFG->dirroot.'/mod/quiz/locallib.php'); // We really want to get rid of this
22 $id = required_param('id', PARAM_INT); // question id
23 // if no quiz id is specified then a dummy quiz with default options is used
24 $quizid = optional_param('quizid', 0, PARAM_INT);
25 // if no quiz id is specified then tell us the course
26 if (empty($quizid)) {
27 $courseid = required_param('courseid', PARAM_INT);
30 // Test if we are continuing an attempt at a question
31 $continue = optional_param('continue', 0, PARAM_BOOL);
32 // Check for any of the submit buttons
33 $fillcorrect = optional_param('fillcorrect', 0, PARAM_BOOL);
34 $markall = optional_param('markall', 0, PARAM_BOOL);
35 $finishattempt = optional_param('finishattempt', 0, PARAM_BOOL);
36 $back = optional_param('back', 0, PARAM_BOOL);
37 $startagain = optional_param('startagain', 0, PARAM_BOOL);
38 // We are always continuing an attempt if a submit button was pressed with the
39 // exception of the start again button
40 if ($fillcorrect || $markall || $finishattempt || $back) {
41 $continue = true;
42 } else if ($startagain) {
43 $continue = false;
46 $url = new moodle_url($CFG->wwwroot . '/question/preview.php');
47 $url->param('id', $id);
48 if ($quizid) {
49 $url->param('quizid', $quizid);
50 } else {
51 $url->param('courseid', $courseid);
53 $url->param('continue', 1);
54 if (!$continue) {
55 // Start a new attempt; delete the old session
56 unset($SESSION->quizpreview);
57 // Redirect to ourselves but with continue=1; prevents refreshing the page
58 // from restarting an attempt (needed so that random questions don't change)
59 redirect($url->out());
61 // Load the question information
62 if (!$questions = get_records('question', 'id', $id)) {
63 error('Could not load question');
65 if (empty($quizid)) {
66 $quiz = new cmoptions;
67 $quiz->id = 0;
68 $quiz->review = $CFG->quiz_review;
69 require_login($courseid, false);
70 $quiz->course = $courseid;
71 } else if (!$quiz = get_record('quiz', 'id', $quizid)) {
72 error("Quiz id $quizid does not exist");
73 } else {
74 require_login($quiz->course, false, get_coursemodule_from_instance('quiz', $quizid, $quiz->course));
79 if ($maxgrade = get_field('quiz_question_instances', 'grade', 'quiz', $quiz->id, 'question', $id)) {
80 $questions[$id]->maxgrade = $maxgrade;
81 } else {
82 $questions[$id]->maxgrade = $questions[$id]->defaultgrade;
85 $quiz->id = 0; // just for safety
86 $quiz->questions = $id;
88 if (!$category = get_record("question_categories", "id", $questions[$id]->category)) {
89 error("This question doesn't belong to a valid category!");
92 if (!question_has_capability_on($questions[$id], 'use', $questions[$id]->category)){
93 error("You can't preview these questions!");
95 if (isset($COURSE)){
96 $quiz->course = $COURSE->id;
99 // Load the question type specific information
100 if (!get_question_options($questions)) {
101 print_error('newattemptfail', 'quiz');
104 // Create a dummy quiz attempt
105 // TODO: find out what of the following we really need. What is $attempt
106 // really used for?
107 $timenow = time();
108 $attempt->quiz = $quiz->id;
109 $attempt->userid = $USER->id;
110 $attempt->attempt = 0;
111 $attempt->sumgrades = 0;
112 $attempt->timestart = $timenow;
113 $attempt->timefinish = 0;
114 $attempt->timemodified = $timenow;
115 $attempt->uniqueid = 0;
116 $attempt->id = 0;
118 // Restore the history of question sessions from the moodle session or create
119 // new sessions. Make $states a reference to the states array in the moodle
120 // session.
121 if (isset($SESSION->quizpreview->states) and $SESSION->quizpreview->questionid == $id) {
122 // Reload the question session history from the moodle session
123 $states =& $SESSION->quizpreview->states;
124 $historylength = count($states) - 1;
125 if ($back && $historylength > 0) {
126 // Go back one step in the history
127 unset($states[$historylength]);
128 $historylength--;
130 } else {
131 // Record the question id in the moodle session
132 $SESSION->quizpreview->questionid = $id;
133 // Create an empty session for the question
134 if (!$newstates =
135 get_question_states($questions, $quiz, $attempt)) {
136 print_error('newattemptfail', 'quiz');
138 $SESSION->quizpreview->states = array($newstates);
139 $states =& $SESSION->quizpreview->states;
140 $historylength = 0;
143 if (!$fillcorrect && !$back && ($form = data_submitted())) {
144 $form = (array)$form;
145 $submitted = true;
147 // Create a new item in the history of question states (don't simplify!)
148 $states[$historylength + 1] = array();
149 $states[$historylength + 1][$id] = clone($states[$historylength][$id]);
150 $historylength++;
151 $curstate =& $states[$historylength][$id];
152 $curstate->changed = false;
154 // Process the responses
155 unset($form['id']);
156 unset($form['quizid']);
157 unset($form['continue']);
158 unset($form['markall']);
159 unset($form['finishattempt']);
160 unset($form['back']);
161 unset($form['startagain']);
163 $event = $finishattempt ? QUESTION_EVENTCLOSE : QUESTION_EVENTSUBMIT;
164 if ($actions = question_extract_responses($questions, $form, $event)) {
165 $actions[$id]->timestamp = 0; // We do not care about timelimits here
166 if (!question_process_responses($questions[$id], $curstate, $actions[$id], $quiz, $attempt)) {
167 unset($SESSION->quizpreview);
168 print_error('errorprocessingresponses', 'question', $url->out());
170 if (!$curstate->changed) {
171 // Update the current state rather than creating a new one
172 $historylength--;
173 unset($states[$historylength]);
174 $states = array_values($states);
175 $curstate =& $states[$historylength][$id];
178 } else {
179 $submitted = false;
180 $curstate =& $states[$historylength][$id];
183 // TODO: should not use quiz-specific function here
184 $options = quiz_get_renderoptions($quiz->review, $curstate);
186 // Fill in the correct responses (unless the question is in readonly mode)
187 if ($fillcorrect && !$options->readonly) {
188 $curstate->responses = $QTYPES[$questions[$id]->qtype]
189 ->get_correct_responses($questions[$id], $curstate);
192 $strpreview = get_string('preview', 'quiz').' '.format_string($questions[$id]->name);
193 $questionlist = array($id);
194 $headtags = get_html_head_contributions($questionlist, $questions, $states[$historylength]);
195 print_header($strpreview, '', '', '', $headtags);
196 print_heading($strpreview);
198 if (!empty($quizid)) {
199 echo '<p class="quemodname">'.get_string('modulename', 'quiz') . ': ';
200 p(format_string($quiz->name));
201 echo "</p>\n";
203 $number = 1;
204 echo '<form method="post" action="'.$url->out(true).'" enctype="multipart/form-data" id="responseform">', "\n";
205 print_question($questions[$id], $curstate, $number, $quiz, $options);
207 echo '<div class="controls">';
208 echo $url->hidden_params_out();
210 // Print the mark and finish attempt buttons
211 echo '<input name="markall" type="submit" value="' . get_string('markall',
212 'quiz') . "\" />\n";
213 echo '<input name="finishattempt" type="submit" value="' .
214 get_string('finishattempt', 'quiz') . "\" />\n";
215 echo '<br />';
216 echo '<br />';
217 // Print the fill correct button (unless the question is in readonly mode)
218 if (!$options->readonly) {
219 echo '<input name="fillcorrect" type="submit" value="' .
220 get_string('fillcorrect', 'quiz') . "\" />\n";
222 // Print the navigation buttons
223 if ($historylength > 0) {
224 echo '<input name="back" type="submit" value="' . get_string('previous',
225 'quiz') . "\" />\n";
227 // Print the start again button
228 echo '<input name="startagain" type="submit" value="' .
229 get_string('startagain', 'quiz') . "\" />\n";
230 // Print the close window button
231 echo '<input type="button" onclick="window.close()" value="' .
232 get_string('closepreview', 'quiz') . "\" />";
233 echo '</div>';
234 echo '</form>';
235 print_footer();