Merged branch 'MDL-27692_master' of git://github.com/MaryE/moodle.git
[moodle.git] / question / preview.php
CommitLineData
aeb15530 1<?php
c76145d3
TH
2// This file is part of Moodle - http://moodle.org/
3//
4// Moodle is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// Moodle is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
16
516cf3eb 17/**
4323d029 18 * This page displays a preview of a question
19 *
20 * The preview uses the option settings from the activity within which the question
21 * is previewed or the default settings if no activity is specified. The question session
22 * information is stored in the session as an array of subsequent states rather
23 * than in the database.
24 *
017bc1d9 25 * @package moodlecore
7764183a 26 * @subpackage questionengine
017bc1d9 27 * @copyright Alex Smith {@link http://maths.york.ac.uk/serving_maths} and
c76145d3 28 * numerous contributors.
7764183a 29 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
4323d029 30 */
516cf3eb 31
017bc1d9 32
c76145d3
TH
33require_once(dirname(__FILE__) . '/../config.php');
34require_once($CFG->libdir . '/questionlib.php');
c76145d3
TH
35require_once(dirname(__FILE__) . '/previewlib.php');
36
37// Get and validate question id.
38$id = required_param('id', PARAM_INT);
39$question = question_bank::load_question($id);
40require_login();
c014b989
TH
41$category = $DB->get_record('question_categories',
42 array('id' => $question->category), '*', MUST_EXIST);
c76145d3
TH
43question_require_capability_on($question, 'use');
44$PAGE->set_pagelayout('popup');
45$PAGE->set_context(get_context_instance_by_id($category->contextid));
46
47// Get and validate display options.
c014b989 48$maxvariant = $question->get_num_variants();
c76145d3
TH
49$options = new question_preview_options($question);
50$options->load_user_defaults();
51$options->set_from_request();
52$PAGE->set_url(question_preview_url($id, $options->behaviour, $options->maxmark, $options));
53
54// Get and validate exitsing preview, or start a new one.
612106b3
TH
55$previewid = optional_param('previewid', 0, PARAM_INT);
56
c76145d3
TH
57if ($previewid) {
58 if (!isset($SESSION->question_previews[$previewid])) {
59 print_error('notyourpreview', 'question');
60 }
61 try {
62 $quba = question_engine::load_questions_usage_by_activity($previewid);
c014b989 63 } catch (Exception $e) {
c76145d3
TH
64 print_error('submissionoutofsequencefriendlymessage', 'question',
65 question_preview_url($question->id, $options->behaviour,
66 $options->maxmark, $options), null, $e);
67 }
68 $slot = $quba->get_first_question_number();
69 $usedquestion = $quba->get_question($slot);
70 if ($usedquestion->id != $question->id) {
71 print_error('questionidmismatch', 'question');
72 }
73 $question = $usedquestion;
c014b989 74 $options->variant = $quba->get_variant($slot);
c76145d3
TH
75
76} else {
77 $quba = question_engine::make_questions_usage_by_activity('core_question_preview',
78 get_context_instance_by_id($category->contextid));
79 $quba->set_preferred_behaviour($options->behaviour);
80 $slot = $quba->add_question($question, $options->maxmark);
c014b989
TH
81
82 if ($options->variant) {
83 $options->variant = min($maxvariant, max(1, $options->variant));
84 } else {
85 $options->variant = rand(1, $maxvariant);
86 }
87
88 $quba->start_question($slot, $options->variant);
c76145d3
TH
89
90 $transaction = $DB->start_delegated_transaction();
91 question_engine::save_questions_usage_by_activity($quba);
92 $transaction->allow_commit();
93
94 $SESSION->question_previews[$quba->get_id()] = true;
95}
96$options->behaviour = $quba->get_preferred_behaviour();
97$options->maxmark = $quba->get_question_max_mark($slot);
98
99// Create the settings form, and initialise the fields.
c014b989
TH
100$optionsform = new preview_options_form(new moodle_url('/question/preview.php',
101 array('id' => $question->id)), array('quba' => $quba, 'maxvariant' => $maxvariant));
c76145d3
TH
102$optionsform->set_data($options);
103
104// Process change of settings, if that was requested.
105if ($newoptions = $optionsform->get_submitted_data()) {
106 // Set user preferences
107 $options->save_user_preview_options($newoptions);
612106b3
TH
108 if (!isset($newoptions->variant)) {
109 $newoptions->variant = $options->variant;
110 }
c76145d3
TH
111 restart_preview($previewid, $question->id, $newoptions);
112}
113
114// Prepare a URL that is used in various places.
115$actionurl = question_preview_action_url($question->id, $quba->get_id(), $options);
116
117// Process any actions from the buttons at the bottom of the form.
118if (data_submitted() && confirm_sesskey()) {
119 if (optional_param('restart', false, PARAM_BOOL)) {
120 restart_preview($previewid, $question->id, $options);
121
122 } else if (optional_param('fill', null, PARAM_BOOL)) {
123 $correctresponse = $quba->get_correct_response($slot);
124 $quba->process_action($slot, $correctresponse);
125
126 $transaction = $DB->start_delegated_transaction();
127 question_engine::save_questions_usage_by_activity($quba);
128 $transaction->allow_commit();
129
130 redirect($actionurl);
131
132 } else if (optional_param('finish', null, PARAM_BOOL)) {
133 try {
134 $quba->process_all_actions();
c014b989 135 } catch (question_out_of_sequence_exception $e) {
c76145d3
TH
136 print_error('submissionoutofsequencefriendlymessage', 'question', $actionurl);
137 }
138 $quba->finish_all_questions();
516cf3eb 139
c76145d3
TH
140 $transaction = $DB->start_delegated_transaction();
141 question_engine::save_questions_usage_by_activity($quba);
142 $transaction->allow_commit();
143 redirect($actionurl);
516cf3eb 144
516cf3eb 145 } else {
c76145d3
TH
146 try {
147 $quba->process_all_actions();
c014b989 148 } catch (question_out_of_sequence_exception $e) {
c76145d3 149 print_error('submissionoutofsequencefriendlymessage', 'question', $actionurl);
516cf3eb 150 }
516cf3eb 151
c76145d3
TH
152 $transaction = $DB->start_delegated_transaction();
153 question_engine::save_questions_usage_by_activity($quba);
154 $transaction->allow_commit();
516cf3eb 155
c76145d3
TH
156 $scrollpos = optional_param('scrollpos', '', PARAM_RAW);
157 if ($scrollpos !== '') {
612106b3 158 $actionurl->param('scrollpos', (int) $scrollpos);
c76145d3
TH
159 }
160 redirect($actionurl);
161 }
162}
163
164if ($question->length) {
165 $displaynumber = '1';
166} else {
167 $displaynumber = 'i';
168}
169$restartdisabled = '';
170$finishdisabled = '';
171$filldisabled = '';
172if ($quba->get_question_state($slot)->is_finished()) {
173 $finishdisabled = ' disabled="disabled"';
174 $filldisabled = ' disabled="disabled"';
175}
176if (!$previewid) {
177 $restartdisabled = ' disabled="disabled"';
178}
179
c76145d3
TH
180// Output
181$title = get_string('previewquestion', 'question', format_string($question->name));
182$headtags = question_engine::initialise_js() . $quba->render_question_head_html($slot);
183$PAGE->set_title($title);
184$PAGE->set_heading($title);
185echo $OUTPUT->header();
186
187// Start the question form.
612106b3 188echo '<form method="post" action="' . $actionurl .
c76145d3
TH
189 '" enctype="multipart/form-data" id="responseform">', "\n";
190echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />', "\n";
191echo '<input type="hidden" name="slots" value="' . $slot . '" />', "\n";
192
193// Output the question.
194echo $quba->render_question($slot, $options, $displaynumber);
195
196echo '<p class="notifytiny">' . get_string('behaviourbeingused', 'question',
197 question_engine::get_behaviour_name(
198 $quba->get_question_attempt($slot)->get_behaviour_name())) . '</p>';
199// Finish the question form.
200echo '<div id="previewcontrols" class="controls">';
201echo '<input type="submit" name="restart"' . $restartdisabled .
202 ' value="' . get_string('restart', 'question') . '" />', "\n";
203echo '<input type="submit" name="fill"' . $filldisabled .
204 ' value="' . get_string('fillincorrect', 'question') . '" />', "\n";
205echo '<input type="submit" name="finish"' . $finishdisabled .
206 ' value="' . get_string('submitandfinish', 'question') . '" />', "\n";
207echo '<input type="hidden" name="scrollpos" id="scrollpos" value="" />';
208echo '</div>';
209echo '</form>';
210
211// Display the settings form.
212$optionsform->display();
213
cce1b655
TH
214$PAGE->requires->js_init_call('M.core_question_preview.init', null, false, array(
215 'name' => 'core_question_preview',
216 'fullpath' => '/question/preview.js',
217 'requires' => array('base', 'dom', 'event-delegate', 'event-key', 'core_question_engine'),
218 'strings' => array(
219 array('closepreview', 'question'),
220 )));
c76145d3 221echo $OUTPUT->footer();
aeb15530 222