MDL-20636 Add missing defined('MOODLE_INTERNAL') || die();
[moodle.git] / question / previewlib.php
CommitLineData
fe6ce234
DC
1<?php
2
3// This file is part of Moodle - http://moodle.org/
4//
5// Moodle is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// Moodle is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
17
18/**
19 * Library functions used by question/preview.php.
20 *
06f8ed54 21 * @package moodlecore
fe6ce234
DC
22 * @subpackage questionengine
23 * @copyright 2010 The Open University
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 */
26
06f8ed54 27
a17b297d
TH
28defined('MOODLE_INTERNAL') || die();
29
7a719748
TH
30require_once($CFG->libdir . '/formslib.php');
31
32
06f8ed54
TH
33/**
34 * Settings form for the preview options.
35 *
36 * @copyright 2009 The Open University
37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 */
39class preview_options_form extends moodleform {
40 public function definition() {
41 $mform = $this->_form;
42
43 $hiddenofvisible = array(
44 question_display_options::HIDDEN => get_string('notshown', 'question'),
45 question_display_options::VISIBLE => get_string('shown', 'question'),
46 );
47
48 $mform->addElement('header', 'optionsheader', get_string('changeoptions', 'question'));
49
50 $behaviours = question_engine::get_behaviour_options($this->_customdata->get_preferred_behaviour());
51 $mform->addElement('select', 'behaviour', get_string('howquestionsbehave', 'question'), $behaviours);
c76145d3 52 $mform->addHelpButton('behaviour', 'howquestionsbehave', 'question');
06f8ed54
TH
53
54 $mform->addElement('text', 'maxmark', get_string('markedoutof', 'question'), array('size' => '5'));
55 $mform->setType('maxmark', PARAM_NUMBER);
56
57 $mform->addElement('select', 'correctness', get_string('whethercorrect', 'question'), $hiddenofvisible);
58
59 $marksoptions = array(
60 question_display_options::HIDDEN => get_string('notshown', 'question'),
61 question_display_options::MAX_ONLY => get_string('showmaxmarkonly', 'question'),
62 question_display_options::MARK_AND_MAX => get_string('showmarkandmax', 'question'),
63 );
64 $mform->addElement('select', 'marks', get_string('marks', 'question'), $marksoptions);
65
66 $mform->addElement('select', 'markdp', get_string('decimalplacesingrades', 'question'),
67 question_engine::get_dp_options());
68
69 $mform->addElement('select', 'feedback', get_string('specificfeedback', 'question'), $hiddenofvisible);
70
71 $mform->addElement('select', 'generalfeedback', get_string('generalfeedback', 'question'), $hiddenofvisible);
72
73 $mform->addElement('select', 'rightanswer', get_string('rightanswer', 'question'), $hiddenofvisible);
74
75 $mform->addElement('select', 'history', get_string('responsehistory', 'question'), $hiddenofvisible);
76
77 $mform->addElement('submit', 'submit', get_string('restartwiththeseoptions', 'question'), $hiddenofvisible);
78 }
79}
80
81
82/**
83 * Displays question preview options as default and set the options
84 * Setting default, getting and setting user preferences in question preview options.
85 *
86 * @copyright 2010 The Open University
87 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
88 */
89class question_preview_options extends question_display_options {
90 /** @var string the behaviour to use for this preview. */
91 public $behaviour;
92
93 /** @var number the maximum mark to use for this preview. */
94 public $maxmark;
95
96 /** @var string prefix to append to field names to get user_preference names. */
97 const OPTIONPREFIX = 'question_preview_options_';
98
99 /**
100 * Constructor.
101 */
102 public function __construct($question) {
103 global $CFG;
104 $this->behaviour = 'deferredfeedback';
105 $this->maxmark = $question->defaultmark;
106 $this->correctness = self::VISIBLE;
107 $this->marks = self::MARK_AND_MAX;
c76145d3 108 $this->markdp = get_config('quiz', 'decimalpoints');
06f8ed54
TH
109 $this->feedback = self::VISIBLE;
110 $this->numpartscorrect = $this->feedback;
111 $this->generalfeedback = self::VISIBLE;
112 $this->rightanswer = self::VISIBLE;
113 $this->history = self::HIDDEN;
114 $this->flags = self::HIDDEN;
115 $this->manualcomment = self::HIDDEN;
116 }
117
118 /**
119 * @return array names of the options we store in the user preferences table.
120 */
121 protected function get_user_pref_fields() {
122 return array('behaviour', 'correctness', 'marks', 'markdp', 'feedback',
123 'generalfeedback', 'rightanswer', 'history');
124 }
125
126 /**
127 * @return array names and param types of the options we read from the request.
128 */
129 protected function get_field_types() {
130 return array(
131 'behaviour' => PARAM_ALPHA,
132 'maxmark' => PARAM_NUMBER,
133 'correctness' => PARAM_BOOL,
134 'marks' => PARAM_INT,
135 'markdp' => PARAM_INT,
136 'feedback' => PARAM_BOOL,
137 'generalfeedback' => PARAM_BOOL,
138 'rightanswer' => PARAM_BOOL,
139 'history' => PARAM_BOOL,
140 );
141 }
142
143 /**
144 * Load the value of the options from the user_preferences table.
145 */
146 public function load_user_defaults() {
147 foreach ($this->get_user_pref_fields() as $field) {
148 $this->$field = get_user_preferences(
149 self::OPTIONPREFIX . $field, $this->$field);
150 }
151 $this->numpartscorrect = $this->feedback;
152 }
153
154 /**
155 * Save a change to the user's preview options to the database.
156 * @param object $newoptions
157 */
158 public function save_user_preview_options($newoptions) {
159 foreach ($this->get_user_pref_fields() as $field) {
160 if (isset($newoptions->$field)) {
161 set_user_preference(self::OPTIONPREFIX . $field, $newoptions->$field);
162 }
163 }
164 }
165
166 /**
167 * Set the value of any fields included in the request.
168 */
169 public function set_from_request() {
170 foreach ($this->get_field_types() as $field => $type) {
171 $this->$field = optional_param($field, $this->$field, $type);
172 }
173 $this->numpartscorrect = $this->feedback;
174 }
175
176 /**
177 * @return string URL fragment. Parameters needed in the URL when continuing
178 * this preview.
179 */
180 public function get_query_string() {
181 $querystring = array();
182 foreach ($this->get_field_types() as $field => $notused) {
183 if ($field == 'behaviour' || $field == 'maxmark') {
184 continue;
185 }
186 $querystring[] = $field . '=' . $this->$field;
187 }
188 return implode('&', $querystring);
189 }
190}
191
192
fe6ce234
DC
193/**
194 * Called via pluginfile.php -> question_pluginfile to serve files belonging to
195 * a question in a question_attempt when that attempt is a preview.
196 *
197 * @param object $course course settings object
198 * @param object $context context object
199 * @param string $component the name of the component we are serving files for.
200 * @param string $filearea the name of the file area.
7a719748
TH
201 * @param integer $qubaid the question_usage this image belongs to.
202 * @param integer $slot the relevant slot within the usage.
fe6ce234
DC
203 * @param array $args the remaining bits of the file path.
204 * @param bool $forcedownload whether the user must be forced to download the file.
205 * @return bool false if file not found, does not return if found - justsend the file
206 */
207function question_preview_question_pluginfile($course, $context, $component,
7a719748
TH
208 $filearea, $qubaid, $slot, $args, $forcedownload) {
209 global $USER, $DB, $CFG;
fe6ce234 210
7a719748 211 $quba = question_engine::load_questions_usage_by_activity($qubaid);
fe6ce234 212
7a719748 213 if ($quba->get_owning_context()->id != $context->id) {
fe6ce234
DC
214 send_file_not_found();
215 }
216
7a719748 217 if (!question_has_capability_on($quba->get_question($slot), 'use')) {
fe6ce234
DC
218 send_file_not_found();
219 }
220
7a719748
TH
221 $options = new question_display_options();
222 $options->feedback = question_display_options::VISIBLE;
223 $options->numpartscorrect = question_display_options::VISIBLE;
224 $options->generalfeedback = question_display_options::VISIBLE;
225 $options->rightanswer = question_display_options::VISIBLE;
226 $options->manualcomment = question_display_options::VISIBLE;
227 $options->history = question_display_options::VISIBLE;
228 if (!$quba->check_file_access($slot, $options, $component,
fe6ce234
DC
229 $filearea, $args, $forcedownload)) {
230 send_file_not_found();
231 }
232
233 $fs = get_file_storage();
234 $relativepath = implode('/', $args);
235 $fullpath = "/$context->id/$component/$filearea/$relativepath";
236 if (!$file = $fs->get_file_by_hash(sha1($fullpath)) or $file->is_directory()) {
237 send_file_not_found();
238 }
239
240 send_stored_file($file, 0, 0, $forcedownload);
241}
06f8ed54
TH
242
243/**
244 * The the URL to use for actions relating to this preview.
245 * @param integer $questionid the question being previewed.
246 * @param integer $qubaid the id of the question usage for this preview.
247 * @param question_preview_options $options the options in use.
248 */
249function question_preview_action_url($questionid, $qubaid,
250 question_preview_options $options) {
251 global $CFG;
252 $url = $CFG->wwwroot . '/question/preview.php?id=' . $questionid . '&previewid=' . $qubaid;
253 return $url . '&' . $options->get_query_string();
254}
255
256/**
257 * Delete the current preview, if any, and redirect to start a new preview.
258 * @param integer $previewid
259 * @param integer $questionid
260 * @param object $displayoptions
261 */
262function restart_preview($previewid, $questionid, $displayoptions) {
c76145d3
TH
263 global $DB;
264
06f8ed54 265 if ($previewid) {
c76145d3 266 $transaction = $DB->start_delegated_transaction();
06f8ed54 267 question_engine::delete_questions_usage_by_activity($previewid);
c76145d3 268 $transaction->allow_commit();
06f8ed54
TH
269 }
270 redirect(question_preview_url($questionid, $displayoptions->behaviour, $displayoptions->maxmark, $displayoptions));
271}