Commit | Line | Data |
---|---|---|
83192608 | 1 | <?php |
f9b0500f 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 | ||
f4b879dd | 17 | |
ee1fb969 | 18 | /** |
f9b0500f TH |
19 | * This contains functions that are called from within the quiz module only |
20 | * Functions that are also called by core Moodle are in {@link lib.php} | |
21 | * This script also loads the code in {@link questionlib.php} which holds | |
22 | * the module-indpendent code for handling questions and which in turn | |
23 | * initialises all the questiontype classes. | |
f63a4ff2 | 24 | * |
01773a6d | 25 | * @package mod_quiz |
ba643847 TH |
26 | * @copyright 1999 onwards Martin Dougiamas and others {@link http://moodle.com} |
27 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
f9b0500f TH |
28 | */ |
29 | ||
ee1fb969 | 30 | |
a17b297d | 31 | defined('MOODLE_INTERNAL') || die(); |
ee1fb969 | 32 | |
a17b297d | 33 | require_once($CFG->dirroot . '/mod/quiz/locallib.php'); |
f9b0500f | 34 | |
2a874d65 | 35 | define('NUM_QS_TO_SHOW_IN_RANDOM', 3); |
36 | ||
76cf77e4 TH |
37 | /** |
38 | * Verify that the question exists, and the user has permission to use it. | |
39 | * Does not return. Throws an exception if the question cannot be used. | |
40 | * @param int $questionid The id of the question. | |
41 | */ | |
42 | function quiz_require_question_use($questionid) { | |
43 | global $DB; | |
44 | $question = $DB->get_record('question', array('id' => $questionid), '*', MUST_EXIST); | |
45 | question_require_capability_on($question, 'use'); | |
46 | } | |
47 | ||
48 | /** | |
49 | * Verify that the question exists, and the user has permission to use it. | |
ccba5b88 TH |
50 | * @param object $quiz the quiz settings. |
51 | * @param int $slot which question in the quiz to test. | |
76cf77e4 TH |
52 | * @return bool whether the user can use this question. |
53 | */ | |
ccba5b88 | 54 | function quiz_has_question_use($quiz, $slot) { |
76cf77e4 | 55 | global $DB; |
ccba5b88 TH |
56 | $question = $DB->get_record_sql(" |
57 | SELECT q.* | |
58 | FROM {quiz_slots} slot | |
59 | JOIN {question} q ON q.id = slot.questionid | |
60 | WHERE slot.quizid = ? AND slot.slot = ?", array($quiz->id, $slot)); | |
61 | if (!$question) { | |
62 | return false; | |
63 | } | |
76cf77e4 TH |
64 | return question_has_capability_on($question, 'use'); |
65 | } | |
66 | ||
ee1fb969 | 67 | /** |
4299df1d | 68 | * Remove a question from a quiz |
69 | * @param object $quiz the quiz object. | |
70 | * @param int $questionid The id of the question to be deleted. | |
71 | */ | |
ccba5b88 | 72 | function quiz_remove_slot($quiz, $slotnumber) { |
9cf4a18b | 73 | global $DB; |
ee1fb969 | 74 | |
ccba5b88 TH |
75 | $slot = $DB->get_record('quiz_slots', array('quizid' => $quiz->id, 'slot' => $slotnumber)); |
76 | $maxslot = $DB->get_field_sql('SELECT MAX(slot) FROM {quiz_slots} WHERE quizid = ?', array($quiz->id)); | |
77 | if (!$slot) { | |
4299df1d | 78 | return; |
ee1fb969 | 79 | } |
80 | ||
ccba5b88 TH |
81 | $trans = $DB->start_delegated_transaction(); |
82 | $DB->delete_records('quiz_slots', array('id' => $slot->id)); | |
83 | for ($i = $slot->slot + 1; $i <= $maxslot; $i++) { | |
84 | $DB->set_field('quiz_slots', 'slot', $i - 1, | |
85 | array('quizid' => $quiz->id, 'slot' => $i)); | |
86 | } | |
828a4e9f EM |
87 | |
88 | $qtype = $DB->get_field('question', 'qtype', array('id' => $slot->questionid)); | |
89 | if ($qtype === 'random') { | |
90 | // This function automatically checks if the question is in use, and won't delete if it is. | |
91 | question_delete_question($slot->questionid); | |
92 | } | |
93 | ||
ccba5b88 | 94 | $trans->allow_commit(); |
4299df1d | 95 | } |
96 | ||
97 | /** | |
98 | * Remove an empty page from the quiz layout. If that is not possible, do nothing. | |
ccba5b88 TH |
99 | * @param object $quiz the quiz settings. |
100 | * @param int $pagenumber the page number to delete. | |
4299df1d | 101 | */ |
ccba5b88 TH |
102 | function quiz_delete_empty_page($quiz, $pagenumber) { |
103 | global $DB; | |
4299df1d | 104 | |
ccba5b88 TH |
105 | if ($DB->record_exists('quiz_slots', array('quizid' => $quiz->id, 'page' => $pagenumber))) { |
106 | // This was not an empty page. | |
107 | return; | |
4299df1d | 108 | } |
109 | ||
ccba5b88 TH |
110 | $DB->execute('UPDATE {quiz_slots} SET page = page - 1 WHERE quizid = ? AND page > ?', |
111 | array($quiz->id, $pagenumber)); | |
ee1fb969 | 112 | } |
113 | ||
ee1fb969 | 114 | /** |
f5831eea | 115 | * Add a question to a quiz |
116 | * | |
117 | * Adds a question to a quiz by updating $quiz as well as the | |
ccba5b88 TH |
118 | * quiz and quiz_slots tables. It also adds a page break if required. |
119 | * @param int $questionid The id of the question to be added | |
94dbfb3a TH |
120 | * @param object $quiz The extended quiz object as used by edit.php |
121 | * This is updated by this function | |
aac80ff3 TH |
122 | * @param int $page Which page in quiz to add the question on. If 0 (default), |
123 | * add at the end | |
ccba5b88 TH |
124 | * @param float $maxmark The maximum mark to set for this question. (Optional, |
125 | * defaults to question.defaultmark. | |
f7970e3c | 126 | * @return bool false if the question was already in the quiz |
f5831eea | 127 | */ |
ccba5b88 | 128 | function quiz_add_quiz_question($questionid, $quiz, $page = 0, $maxmark = null) { |
9cf4a18b | 129 | global $DB; |
ccba5b88 TH |
130 | $slots = $DB->get_records('quiz_slots', array('quizid' => $quiz->id), |
131 | 'slot', 'questionid, slot, page, id'); | |
132 | if (array_key_exists($questionid, $slots)) { | |
ee1fb969 | 133 | return false; |
134 | } | |
135 | ||
ccba5b88 TH |
136 | $trans = $DB->start_delegated_transaction(); |
137 | ||
138 | $maxpage = 1; | |
139 | $numonlastpage = 0; | |
140 | foreach ($slots as $slot) { | |
141 | if ($slot->page > $maxpage) { | |
142 | $maxpage = $slot->page; | |
143 | $numonlastpage = 1; | |
144 | } else { | |
145 | $numonlastpage += 1; | |
ee1fb969 | 146 | } |
147 | } | |
ccba5b88 TH |
148 | |
149 | // Add the new question instance. | |
150 | $slot = new stdClass(); | |
151 | $slot->quizid = $quiz->id; | |
152 | $slot->questionid = $questionid; | |
153 | ||
154 | if ($maxmark !== null) { | |
155 | $slot->maxmark = $maxmark; | |
156 | } else { | |
157 | $slot->maxmark = $DB->get_field('question', 'defaultmark', array('id' => $questionid)); | |
158 | } | |
159 | ||
f5831eea | 160 | if (is_int($page) && $page >= 1) { |
ccba5b88 | 161 | // Adding on a given page. |
2fa19cfe | 162 | $lastslotbefore = 0; |
ccba5b88 TH |
163 | foreach (array_reverse($slots) as $otherslot) { |
164 | if ($otherslot->page > $page) { | |
165 | $DB->set_field('quiz_slots', 'slot', $otherslot->slot + 1, array('id' => $otherslot->id)); | |
166 | } else { | |
167 | $lastslotbefore = $otherslot->slot; | |
168 | break; | |
fa583f5f | 169 | } |
fa583f5f | 170 | } |
ccba5b88 TH |
171 | $slot->slot = $lastslotbefore + 1; |
172 | $slot->page = min($page, $maxpage + 1); | |
ee1fb969 | 173 | |
ccba5b88 TH |
174 | } else { |
175 | $lastslot = end($slots); | |
176 | if ($lastslot) { | |
177 | $slot->slot = $lastslot->slot + 1; | |
178 | } else { | |
179 | $slot->slot = 1; | |
180 | } | |
181 | if ($quiz->questionsperpage && $numonlastpage >= $quiz->questionsperpage) { | |
182 | $slot->page = $maxpage + 1; | |
183 | } else { | |
184 | $slot->page = $maxpage; | |
185 | } | |
186 | } | |
ee1fb969 | 187 | |
ccba5b88 TH |
188 | $DB->insert_record('quiz_slots', $slot); |
189 | $trans->allow_commit(); | |
ee1fb969 | 190 | } |
191 | ||
ccba5b88 TH |
192 | /** |
193 | * Add a random question to the quiz at a given point. | |
194 | * @param object $quiz the quiz settings. | |
195 | * @param int $addonpage the page on which to add the question. | |
196 | * @param int $categoryid the question category to add the question from. | |
197 | * @param int $number the number of random questions to add. | |
198 | * @param bool $includesubcategories whether to include questoins from subcategories. | |
199 | */ | |
aac80ff3 TH |
200 | function quiz_add_random_questions($quiz, $addonpage, $categoryid, $number, |
201 | $includesubcategories) { | |
f9b0500f | 202 | global $DB; |
94dbfb3a TH |
203 | |
204 | $category = $DB->get_record('question_categories', array('id' => $categoryid)); | |
205 | if (!$category) { | |
206 | print_error('invalidcategoryid', 'error'); | |
207 | } | |
208 | ||
d197ea43 | 209 | $catcontext = context::instance_by_id($category->contextid); |
94dbfb3a TH |
210 | require_capability('moodle/question:useall', $catcontext); |
211 | ||
212 | // Find existing random questions in this category that are | |
213 | // not used by any quiz. | |
214 | if ($existingquestions = $DB->get_records_sql( | |
25a03faa | 215 | "SELECT q.id, q.qtype FROM {question} q |
f9b0500f | 216 | WHERE qtype = 'random' |
94dbfb3a TH |
217 | AND category = ? |
218 | AND " . $DB->sql_compare_text('questiontext') . " = ? | |
aac80ff3 TH |
219 | AND NOT EXISTS ( |
220 | SELECT * | |
ccba5b88 | 221 | FROM {quiz_slots} |
dc4a3ea1 | 222 | WHERE questionid = q.id) |
a871a7a7 | 223 | ORDER BY id", array($category->id, ($includesubcategories ? '1' : '0')))) { |
94dbfb3a TH |
224 | // Take as many of these as needed. |
225 | while (($existingquestion = array_shift($existingquestions)) && $number > 0) { | |
226 | quiz_add_quiz_question($existingquestion->id, $quiz, $addonpage); | |
227 | $number -= 1; | |
228 | } | |
229 | } | |
230 | ||
231 | if ($number <= 0) { | |
232 | return; | |
233 | } | |
234 | ||
235 | // More random questions are needed, create them. | |
94dbfb3a | 236 | for ($i = 0; $i < $number; $i += 1) { |
fd214b59 | 237 | $form = new stdClass(); |
a871a7a7 | 238 | $form->questiontext = array('text' => ($includesubcategories ? '1' : '0'), 'format' => 0); |
94dbfb3a | 239 | $form->category = $category->id . ',' . $category->contextid; |
fd214b59 TH |
240 | $form->defaultmark = 1; |
241 | $form->hidden = 1; | |
9e83f3d1 | 242 | $form->stamp = make_unique_id_code(); // Set the unique code (not to be changed). |
0ff4bd08 | 243 | $question = new stdClass(); |
f9b0500f TH |
244 | $question->qtype = 'random'; |
245 | $question = question_bank::get_qtype('random')->save_question($question, $form); | |
94dbfb3a TH |
246 | if (!isset($question->id)) { |
247 | print_error('cannotinsertrandomquestion', 'quiz'); | |
248 | } | |
249 | quiz_add_quiz_question($question->id, $quiz, $addonpage); | |
250 | } | |
251 | } | |
252 | ||
4299df1d | 253 | /** |
ccba5b88 TH |
254 | * Add a page break after a particular slot. |
255 | * @param object $quiz the quiz settings. | |
256 | * @param int $slot the slot to add the page break after. | |
4299df1d | 257 | */ |
ccba5b88 | 258 | function quiz_add_page_break_after_slot($quiz, $slot) { |
4299df1d | 259 | global $DB; |
ccba5b88 TH |
260 | |
261 | $DB->execute('UPDATE {quiz_slots} SET page = page + 1 WHERE quizid = ? AND slot > ?', | |
262 | array($quiz->id, $slot)); | |
4299df1d | 263 | } |
264 | ||
ee1fb969 | 265 | /** |
ccba5b88 | 266 | * Change the max mark for a slot. |
f5831eea | 267 | * |
ccba5b88 TH |
268 | * Saves changes to the question grades in the quiz_slots table and any |
269 | * corresponding question_attempts. | |
f5831eea | 270 | * It does not update 'sumgrades' in the quiz table. |
f9b0500f | 271 | * |
ccba5b88 TH |
272 | * @param stdClass $slot row from the quiz_slots table. |
273 | * @param float $maxmark the new maxmark. | |
f5831eea | 274 | */ |
ccba5b88 | 275 | function quiz_update_slot_maxmark($slot, $maxmark) { |
fd214b59 | 276 | global $DB; |
f9b0500f | 277 | |
ccba5b88 | 278 | if (abs($maxmark - $slot->maxmark) < 1e-7) { |
f9b0500f TH |
279 | // Grade has not changed. Nothing to do. |
280 | return; | |
281 | } | |
282 | ||
ccba5b88 TH |
283 | $slot->maxmark = $maxmark; |
284 | $DB->update_record('quiz_slots', $slot); | |
285 | question_engine::set_max_mark_in_attempts(new qubaids_for_quiz($slot->quizid), | |
286 | $slot->slot, $maxmark); | |
ee1fb969 | 287 | } |
288 | ||
ccba5b88 TH |
289 | /** |
290 | * Private function used by the following two. | |
291 | * @param object $quiz the quiz settings. | |
292 | * @param int $slotnumber the slot to move up. | |
293 | * @param int $shift +1 means move down, -1 means move up. | |
294 | */ | |
295 | function _quiz_move_question($quiz, $slotnumber, $shift) { | |
296 | global $DB; | |
297 | ||
298 | if (!$slotnumber || !($shift == 1 || $shift == -1)) { | |
299 | return; | |
4299df1d | 300 | } |
301 | ||
ccba5b88 TH |
302 | $slot = $DB->get_record('quiz_slots', |
303 | array('quizid' => $quiz->id, 'slot' => $slotnumber)); | |
304 | if (!$slot) { | |
305 | return; | |
4299df1d | 306 | } |
307 | ||
ccba5b88 TH |
308 | $otherslot = $DB->get_record('quiz_slots', |
309 | array('quizid' => $quiz->id, 'slot' => $slotnumber + $shift)); | |
310 | if (!$otherslot) { | |
07a0370b TH |
311 | // Must be first or last question being moved further that way if we can. |
312 | if ($shift + $slot->page > 0) { | |
313 | $DB->set_field('quiz_slots', 'page', $slot->page + $shift, array('id' => $slot->id)); | |
314 | } | |
ccba5b88 | 315 | return; |
4299df1d | 316 | } |
317 | ||
ccba5b88 TH |
318 | if ($otherslot->page != $slot->page) { |
319 | $DB->set_field('quiz_slots', 'page', $slot->page + $shift, array('id' => $slot->id)); | |
320 | return; | |
321 | } | |
4299df1d | 322 | |
ccba5b88 TH |
323 | $trans = $DB->start_delegated_transaction(); |
324 | $DB->set_field('quiz_slots', 'slot', -1, array('id' => $slot->id)); | |
325 | $DB->set_field('quiz_slots', 'slot', $slot->slot, array('id' => $otherslot->id)); | |
326 | $DB->set_field('quiz_slots', 'slot', $otherslot->slot, array('id' => $slot->id)); | |
327 | $trans->allow_commit(); | |
4299df1d | 328 | } |
329 | ||
330 | /** | |
ccba5b88 | 331 | * Move a particular question one space earlier in the quiz. |
4299df1d | 332 | * If that is not possible, do nothing. |
ccba5b88 TH |
333 | * @param object $quiz the quiz settings. |
334 | * @param int $slot the slot to move up. | |
4299df1d | 335 | */ |
ccba5b88 TH |
336 | function quiz_move_question_up($quiz, $slot) { |
337 | _quiz_move_question($quiz, $slot, -1); | |
4299df1d | 338 | } |
339 | ||
340 | /** | |
ccba5b88 | 341 | * Move a particular question one space later in the quiz. |
4299df1d | 342 | * If that is not possible, do nothing. |
ccba5b88 TH |
343 | * @param object $quiz the quiz settings. |
344 | * @param int $slot the slot to move down. | |
4299df1d | 345 | */ |
ccba5b88 TH |
346 | function quiz_move_question_down($quiz, $slot) { |
347 | return _quiz_move_question($quiz, $slot, 1); | |
4299df1d | 348 | } |
349 | ||
ee1fb969 | 350 | /** |
f5831eea | 351 | * Prints a list of quiz questions for the edit.php main view for edit |
352 | * ($reordertool = false) and order and paging ($reordertool = true) tabs | |
353 | * | |
ccba5b88 | 354 | * @param object $quiz The quiz settings. |
76cf77e4 | 355 | * @param moodle_url $pageurl The url of the current page with the parameters required |
f5831eea | 356 | * for links returning to the current page, as a moodle_url object |
f7970e3c TH |
357 | * @param bool $allowdelete Indicates whether the delete icons should be displayed |
358 | * @param bool $reordertool Indicates whether the reorder tool should be displayed | |
359 | * @param bool $quiz_qbanktool Indicates whether the question bank should be displayed | |
360 | * @param bool $hasattempts Indicates whether the quiz has attempts | |
76cf77e4 TH |
361 | * @param object $defaultcategoryobj |
362 | * @param bool $canaddquestion is the user able to add and use questions anywere? | |
363 | * @param bool $canaddrandom is the user able to add random questions anywere? | |
f5831eea | 364 | */ |
f2956c98 | 365 | function quiz_print_question_list($quiz, $pageurl, $allowdelete, $reordertool, |
76cf77e4 | 366 | $quiz_qbanktool, $hasattempts, $defaultcategoryobj, $canaddquestion, $canaddrandom) { |
cef18275 | 367 | global $CFG, $DB, $OUTPUT; |
f5831eea | 368 | $strorder = get_string('order'); |
369 | $strquestionname = get_string('questionname', 'quiz'); | |
5127e52d | 370 | $strmaxmark = get_string('markedoutof', 'question'); |
ee1fb969 | 371 | $strremove = get_string('remove', 'quiz'); |
f5831eea | 372 | $stredit = get_string('edit'); |
373 | $strview = get_string('view'); | |
374 | $straction = get_string('action'); | |
375 | $strmove = get_string('move'); | |
376 | $strmoveup = get_string('moveup'); | |
377 | $strmovedown = get_string('movedown'); | |
378 | $strsave = get_string('save', 'quiz'); | |
379 | $strreorderquestions = get_string('reorderquestions', 'quiz'); | |
380 | ||
381 | $strselectall = get_string('selectall', 'quiz'); | |
382 | $strselectnone = get_string('selectnone', 'quiz'); | |
383 | $strtype = get_string('type', 'quiz'); | |
384 | $strpreview = get_string('preview', 'quiz'); | |
ee1fb969 | 385 | |
ccba5b88 TH |
386 | $questions = $DB->get_records_sql("SELECT slot.slot, q.*, qc.contextid, slot.page, slot.maxmark |
387 | FROM {quiz_slots} slot | |
388 | LEFT JOIN {question} q ON q.id = slot.questionid | |
389 | LEFT JOIN {question_categories} qc ON qc.id = q.category | |
390 | WHERE slot.quizid = ? | |
391 | ORDER BY slot.slot", array($quiz->id)); | |
ee1fb969 | 392 | |
ccba5b88 | 393 | $lastindex = count($questions) - 1; |
fa583f5f | 394 | |
3e10e429 | 395 | $disabled = ''; |
396 | $pagingdisabled = ''; | |
477c217f | 397 | if ($hasattempts) { |
f5831eea | 398 | $disabled = 'disabled="disabled"'; |
fa583f5f | 399 | } |
3e10e429 | 400 | if ($hasattempts || $quiz->shufflequestions) { |
f5831eea | 401 | $pagingdisabled = 'disabled="disabled"'; |
ee68029a | 402 | } |
ee1fb969 | 403 | |
f5831eea | 404 | $reordercontrolssetdefaultsubmit = '<div style="display:none;">' . |
405 | '<input type="submit" name="savechanges" value="' . | |
3e10e429 | 406 | $strreorderquestions . '" ' . $pagingdisabled . ' /></div>'; |
f5831eea | 407 | $reordercontrols1 = '<div class="addnewpagesafterselected">' . |
408 | '<input type="submit" name="addnewpagesafterselected" value="' . | |
409 | get_string('addnewpagesafterselected', 'quiz') . '" ' . | |
410 | $pagingdisabled . ' /></div>'; | |
7b161e12 | 411 | $reordercontrols1 .= '<div class="quizdeleteselected">' . |
412 | '<input type="submit" name="quizdeleteselected" ' . | |
413 | 'onclick="return confirm(\'' . | |
414 | get_string('areyousureremoveselected', 'quiz') . '\');" value="' . | |
415 | get_string('removeselected', 'quiz') . '" ' . $disabled . ' /></div>'; | |
fa583f5f | 416 | |
3211569a | 417 | $a = '<input name="moveselectedonpagetop" type="text" size="2" ' . |
f5831eea | 418 | $pagingdisabled . ' />'; |
3211569a | 419 | $b = '<input name="moveselectedonpagebottom" type="text" size="2" ' . |
14bf4574 | 420 | $pagingdisabled . ' />'; |
f5831eea | 421 | |
422 | $reordercontrols2top = '<div class="moveselectedonpage">' . | |
0465ef6e | 423 | '<label>' . get_string('moveselectedonpage', 'quiz', $a) . '</label>' . |
f5831eea | 424 | '<input type="submit" name="savechanges" value="' . |
425 | $strmove . '" ' . $pagingdisabled . ' />' . ' | |
426 | <br /><input type="submit" name="savechanges" value="' . | |
3e10e429 | 427 | $strreorderquestions . '" /></div>'; |
f5831eea | 428 | $reordercontrols2bottom = '<div class="moveselectedonpage">' . |
429 | '<input type="submit" name="savechanges" value="' . | |
3e10e429 | 430 | $strreorderquestions . '" /><br />' . |
0465ef6e | 431 | '<label>' . get_string('moveselectedonpage', 'quiz', $b) . '</label>' . |
f5831eea | 432 | '<input type="submit" name="savechanges" value="' . |
433 | $strmove . '" ' . $pagingdisabled . ' /> ' . '</div>'; | |
434 | ||
435 | $reordercontrols3 = '<a href="javascript:select_all_in(\'FORM\', null, ' . | |
436 | '\'quizquestions\');">' . | |
437 | $strselectall . '</a> /'; | |
438 | $reordercontrols3.= ' <a href="javascript:deselect_all_in(\'FORM\', ' . | |
439 | 'null, \'quizquestions\');">' . | |
440 | $strselectnone . '</a>'; | |
441 | ||
442 | $reordercontrolstop = '<div class="reordercontrols">' . | |
443 | $reordercontrolssetdefaultsubmit . | |
444 | $reordercontrols1 . $reordercontrols2top . $reordercontrols3 . "</div>"; | |
445 | $reordercontrolsbottom = '<div class="reordercontrols">' . | |
446 | $reordercontrolssetdefaultsubmit . | |
447 | $reordercontrols2bottom . $reordercontrols1 . $reordercontrols3 . "</div>"; | |
448 | ||
449 | if ($reordertool) { | |
fa583f5f | 450 | echo '<form method="post" action="edit.php" id="quizquestions"><div>'; |
451 | ||
6ea66ff3 | 452 | echo html_writer::input_hidden_params($pageurl); |
f5831eea | 453 | echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />'; |
fa583f5f | 454 | |
455 | echo $reordercontrolstop; | |
9cf4a18b | 456 | } |
9aa82ed6 | 457 | |
ccba5b88 TH |
458 | // Build fake order for backwards compatibility. |
459 | $currentpage = 1; | |
460 | $order = array(); | |
461 | foreach ($questions as $question) { | |
462 | while ($question->page > $currentpage) { | |
463 | $currentpage += 1; | |
464 | $order[] = 0; | |
465 | } | |
466 | $order[] = $question->slot; | |
467 | } | |
468 | $order[] = 0; | |
469 | ||
9e83f3d1 | 470 | // The current question ordinal (no descriptions). |
fa583f5f | 471 | $qno = 1; |
9e83f3d1 | 472 | // The current question (includes questions and descriptions). |
f5831eea | 473 | $questioncount = 0; |
9e83f3d1 | 474 | // The current page number in iteration. |
fa583f5f | 475 | $pagecount = 0; |
476 | ||
f5831eea | 477 | $pageopen = false; |
ccba5b88 | 478 | $lastslot = 0; |
fa583f5f | 479 | |
a530d4a9 | 480 | $returnurl = $pageurl->out_as_local_url(false); |
f5831eea | 481 | $questiontotalcount = count($order); |
fa583f5f | 482 | |
07a0370b TH |
483 | $lastquestion = new stdClass(); |
484 | $lastquestion->slot = 0; // Used to get the add page here buttons right. | |
ccba5b88 | 485 | foreach ($order as $count => $qnum) { // Note: $qnum is acutally slot number, if it is not 0. |
ee1fb969 | 486 | |
f5831eea | 487 | $reordercheckbox = ''; |
488 | $reordercheckboxlabel = ''; | |
489 | $reordercheckboxlabelclose = ''; | |
fa583f5f | 490 | |
9e83f3d1 | 491 | // If the questiontype is missing change the question type. |
ccba5b88 TH |
492 | if ($qnum && $questions[$qnum]->qtype === null) { |
493 | $questions[$qnum]->id = $qnum; | |
494 | $questions[$qnum]->category = 0; | |
495 | $questions[$qnum]->qtype = 'missingtype'; | |
496 | $questions[$qnum]->name = get_string('missingquestion', 'quiz'); | |
497 | $questions[$qnum]->questiontext = ' '; | |
498 | $questions[$qnum]->questiontextformat = FORMAT_HTML; | |
499 | $questions[$qnum]->length = 1; | |
f9b0500f | 500 | |
fd214b59 | 501 | } else if ($qnum && !question_bank::qtype_exists($questions[$qnum]->qtype)) { |
4eda4eec | 502 | $questions[$qnum]->qtype = 'missingtype'; |
503 | } | |
f9b0500f | 504 | |
4299df1d | 505 | if ($qnum != 0 || ($qnum == 0 && !$pageopen)) { |
9e83f3d1 | 506 | // This is either a question or a page break after another (no page is currently open). |
4299df1d | 507 | if (!$pageopen) { |
9e83f3d1 | 508 | // If no page is open, start display of a page. |
fa583f5f | 509 | $pagecount++; |
f5831eea | 510 | echo '<div class="quizpage"><span class="pagetitle">' . |
511 | get_string('page') . ' ' . $pagecount . | |
fa583f5f | 512 | '</span><div class="pagecontent">'; |
4299df1d | 513 | $pageopen = true; |
fa583f5f | 514 | } |
07a0370b | 515 | if ($qnum == 0) { |
4299df1d | 516 | // This is the second successive page break. Tell the user the page is empty. |
fa583f5f | 517 | echo '<div class="pagestatus">'; |
f5831eea | 518 | print_string('noquestionsonpage', 'quiz'); |
fa583f5f | 519 | echo '</div>'; |
5be23736 | 520 | if ($allowdelete) { |
fa583f5f | 521 | echo '<div class="quizpagedelete">'; |
aac80ff3 | 522 | echo $OUTPUT->action_icon($pageurl->out(true, |
ccba5b88 | 523 | array('deleteemptypage' => $pagecount, 'sesskey' => sesskey())), |
fd214b59 | 524 | new pix_icon('t/delete', $strremove), |
aac80ff3 TH |
525 | new component_action('click', |
526 | 'M.core_scroll_manager.save_scroll_action'), | |
fd214b59 | 527 | array('title' => $strremove)); |
fa583f5f | 528 | echo '</div>'; |
529 | } | |
530 | } | |
531 | ||
5be23736 | 532 | if ($qnum != 0) { |
fa583f5f | 533 | $question = $questions[$qnum]; |
fb6dcdab TH |
534 | $questionparams = array( |
535 | 'returnurl' => $returnurl, | |
536 | 'cmid' => $quiz->cmid, | |
537 | 'id' => $question->id); | |
538 | $questionurl = new moodle_url('/question/question.php', | |
fa583f5f | 539 | $questionparams); |
540 | $questioncount++; | |
4eda4eec | 541 | |
9e83f3d1 | 542 | // This is an actual question. |
aac80ff3 | 543 | ?> |
fa583f5f | 544 | <div class="question"> |
944efb3e | 545 | <div class="questioncontainer <?php echo $question->qtype; ?>"> |
fa583f5f | 546 | <div class="qnum"> |
aac80ff3 TH |
547 | <?php |
548 | $reordercheckbox = ''; | |
549 | $reordercheckboxlabel = ''; | |
550 | $reordercheckboxlabelclose = ''; | |
551 | if ($reordertool) { | |
ccba5b88 TH |
552 | $reordercheckbox = '<input type="checkbox" name="s' . $question->slot . |
553 | '" id="s' . $question->slot . '" />'; | |
554 | $reordercheckboxlabel = '<label for="s' . $question->slot . '">'; | |
aac80ff3 TH |
555 | $reordercheckboxlabelclose = '</label>'; |
556 | } | |
8418e5b7 WO |
557 | if ($question->length == 0) { |
558 | $qnodisplay = get_string('infoshort', 'quiz'); | |
559 | } else if ($quiz->shufflequestions) { | |
560 | $qnodisplay = '?'; | |
561 | } else { | |
562 | if ($qno > 999 || ($reordertool && $qno > 99)) { | |
563 | $qnodisplay = html_writer::tag('small', $qno); | |
aac80ff3 | 564 | } else { |
8418e5b7 | 565 | $qnodisplay = $qno; |
aac80ff3 | 566 | } |
aac80ff3 | 567 | $qno += $question->length; |
fa583f5f | 568 | } |
8418e5b7 WO |
569 | echo $reordercheckboxlabel . $qnodisplay . $reordercheckboxlabelclose . |
570 | $reordercheckbox; | |
fa583f5f | 571 | |
aac80ff3 | 572 | ?> |
fa583f5f | 573 | </div> |
574 | <div class="content"> | |
575 | <div class="questioncontrols"> | |
576 | <?php | |
aac80ff3 TH |
577 | if ($count != 0) { |
578 | if (!$hasattempts) { | |
579 | $upbuttonclass = ''; | |
aac80ff3 | 580 | echo $OUTPUT->action_icon($pageurl->out(true, |
ccba5b88 | 581 | array('up' => $question->slot, 'sesskey' => sesskey())), |
aac80ff3 TH |
582 | new pix_icon('t/up', $strmoveup), |
583 | new component_action('click', | |
584 | 'M.core_scroll_manager.save_scroll_action'), | |
585 | array('title' => $strmoveup)); | |
fa583f5f | 586 | } |
ee1fb969 | 587 | |
ee1fb969 | 588 | } |
07a0370b TH |
589 | if (!$hasattempts) { |
590 | echo $OUTPUT->action_icon($pageurl->out(true, | |
591 | array('down' => $question->slot, 'sesskey' => sesskey())), | |
592 | new pix_icon('t/down', $strmovedown), | |
593 | new component_action('click', | |
594 | 'M.core_scroll_manager.save_scroll_action'), | |
595 | array('title' => $strmovedown)); | |
aac80ff3 | 596 | } |
068384ce | 597 | if ($allowdelete && ($question->qtype == 'missingtype' || |
aac80ff3 | 598 | question_has_capability_on($question, 'use', $question->category))) { |
9e83f3d1 | 599 | // Remove from quiz, not question delete. |
aac80ff3 TH |
600 | if (!$hasattempts) { |
601 | echo $OUTPUT->action_icon($pageurl->out(true, | |
ccba5b88 | 602 | array('remove' => $question->slot, 'sesskey' => sesskey())), |
aac80ff3 TH |
603 | new pix_icon('t/delete', $strremove), |
604 | new component_action('click', | |
605 | 'M.core_scroll_manager.save_scroll_action'), | |
606 | array('title' => $strremove)); | |
607 | } | |
fa583f5f | 608 | } |
fa583f5f | 609 | ?> |
610 | </div><?php | |
068384ce | 611 | if (!in_array($question->qtype, array('description', 'missingtype')) && !$reordertool) { |
aac80ff3 | 612 | ?> |
fa583f5f | 613 | <div class="points"> |
fd214b59 | 614 | <form method="post" action="edit.php" class="quizsavegradesform"><div> |
fa583f5f | 615 | <fieldset class="invisiblefieldset" style="display: block;"> |
ccba5b88 | 616 | <label for="<?php echo 'inputq' . $question->slot; ?>"><?php echo $strmaxmark; ?></label>:<br /> |
973d2660 | 617 | <input type="hidden" name="sesskey" value="<?php echo sesskey() ?>" /> |
6ea66ff3 | 618 | <?php echo html_writer::input_hidden_params($pageurl); ?> |
fa583f5f | 619 | <input type="hidden" name="savechanges" value="save" /> |
aac80ff3 | 620 | <?php |
ccba5b88 TH |
621 | echo '<input type="text" name="g' . $question->slot . |
622 | '" id="inputq' . $question->slot . | |
aac80ff3 | 623 | '" size="' . ($quiz->decimalpoints + 2) . |
ccba5b88 | 624 | '" value="' . (0 + $question->maxmark) . |
aac80ff3 TH |
625 | '" tabindex="' . ($lastindex + $qno) . '" />'; |
626 | ?> | |
3fd9edf0 | 627 | <input type="submit" class="pointssubmitbutton" value="<?php echo $strsave; ?>" /> |
fa583f5f | 628 | </fieldset> |
aac80ff3 TH |
629 | <?php |
630 | if ($question->qtype == 'random') { | |
631 | echo '<a href="' . $questionurl->out() . | |
632 | '" class="configurerandomquestion">' . | |
633 | get_string("configurerandomquestion", "quiz") . '</a>'; | |
634 | } | |
f4b879dd | 635 | |
aac80ff3 | 636 | ?> |
fa583f5f | 637 | </div> |
638 | </form> | |
639 | ||
640 | </div> | |
aac80ff3 TH |
641 | <?php |
642 | } else if ($reordertool) { | |
643 | if ($qnum) { | |
644 | ?> | |
fa583f5f | 645 | <div class="qorder"> |
aac80ff3 | 646 | <?php |
ccba5b88 | 647 | echo '<label class="accesshide" for="o' . $question->slot . '">' . |
0465ef6e | 648 | get_string('questionposition', 'quiz', $qnodisplay) . '</label>'; |
ccba5b88 | 649 | echo '<input type="text" name="o' . $question->slot . |
0465ef6e | 650 | '" id="o' . $question->id . '"' . |
aac80ff3 TH |
651 | '" size="2" value="' . (10*$count + 10) . |
652 | '" tabindex="' . ($lastindex + $qno) . '" />'; | |
653 | ?> | |
fa583f5f | 654 | </div> |
aac80ff3 TH |
655 | <?php |
656 | } | |
fa583f5f | 657 | } |
aac80ff3 | 658 | ?> |
fa583f5f | 659 | <div class="questioncontentcontainer"> |
aac80ff3 | 660 | <?php |
9e83f3d1 | 661 | if ($question->qtype == 'random') { // It is a random question. |
aac80ff3 TH |
662 | if (!$reordertool) { |
663 | quiz_print_randomquestion($question, $pageurl, $quiz, $quiz_qbanktool); | |
664 | } else { | |
665 | quiz_print_randomquestion_reordertool($question, $pageurl, $quiz); | |
666 | } | |
9e83f3d1 | 667 | } else { // It is a single question. |
aac80ff3 TH |
668 | if (!$reordertool) { |
669 | quiz_print_singlequestion($question, $returnurl, $quiz); | |
670 | } else { | |
671 | quiz_print_singlequestion_reordertool($question, $returnurl, $quiz); | |
672 | } | |
fa583f5f | 673 | } |
fa583f5f | 674 | ?> |
675 | </div> | |
676 | </div> | |
677 | </div> | |
678 | </div> | |
679 | ||
aac80ff3 | 680 | <?php |
fa583f5f | 681 | } |
ee1fb969 | 682 | } |
9e83f3d1 | 683 | // A page break: end the existing page. |
f5831eea | 684 | if ($qnum == 0) { |
685 | if ($pageopen) { | |
aac80ff3 TH |
686 | if (!$reordertool && !($quiz->shufflequestions && |
687 | $count < $questiontotalcount - 1)) { | |
fa583f5f | 688 | quiz_print_pagecontrols($quiz, $pageurl, $pagecount, |
76cf77e4 | 689 | $hasattempts, $defaultcategoryobj, $canaddquestion, $canaddrandom); |
f9b0500f | 690 | } else if ($count < $questiontotalcount - 1) { |
9e83f3d1 TH |
691 | // Do not include the last page break for reordering |
692 | // to avoid creating a new extra page in the end. | |
3e10e429 | 693 | echo '<input type="hidden" name="opg' . $pagecount . '" size="2" value="' . |
f5831eea | 694 | (10*$count + 10) . '" />'; |
fa583f5f | 695 | } |
696 | echo "</div></div>"; | |
697 | ||
07a0370b | 698 | if (!$reordertool && !$quiz->shufflequestions && $count < $questiontotalcount - 1) { |
39e37019 | 699 | echo $OUTPUT->container_start('addpage'); |
aac80ff3 TH |
700 | $url = new moodle_url($pageurl->out_omit_querystring(), |
701 | array('cmid' => $quiz->cmid, 'courseid' => $quiz->course, | |
07a0370b | 702 | 'addpage' => $lastquestion->slot, 'sesskey' => sesskey())); |
fd214b59 TH |
703 | echo $OUTPUT->single_button($url, get_string('addpagehere', 'quiz'), 'post', |
704 | array('disabled' => $hasattempts, | |
aac80ff3 TH |
705 | 'actions' => array(new component_action('click', |
706 | 'M.core_scroll_manager.save_scroll_action')))); | |
39e37019 | 707 | echo $OUTPUT->container_end(); |
fa583f5f | 708 | } |
f5831eea | 709 | $pageopen = false; |
fa583f5f | 710 | $count++; |
711 | } | |
ee1fb969 | 712 | } |
ee1fb969 | 713 | |
07a0370b TH |
714 | if ($qnum != 0) { |
715 | $lastquestion = $question; | |
716 | } | |
717 | ||
fa583f5f | 718 | } |
f5831eea | 719 | if ($reordertool) { |
fa583f5f | 720 | echo $reordercontrolsbottom; |
721 | echo '</div></form>'; | |
722 | } | |
fa583f5f | 723 | } |
724 | ||
725 | /** | |
726 | * Print all the controls for adding questions directly into the | |
727 | * specific page in the edit tab of edit.php | |
728 | * | |
ccba5b88 | 729 | * @param object $quiz The quiz settings. |
76cf77e4 TH |
730 | * @param moodle_url $pageurl The url of the current page with the parameters required |
731 | * for links returning to the current page, as a moodle_url object | |
732 | * @param int $page the current page number. | |
733 | * @param bool $hasattempts Indicates whether the quiz has attempts | |
734 | * @param object $defaultcategoryobj | |
735 | * @param bool $canaddquestion is the user able to add and use questions anywere? | |
736 | * @param bool $canaddrandom is the user able to add random questions anywere? | |
fa583f5f | 737 | */ |
76cf77e4 TH |
738 | function quiz_print_pagecontrols($quiz, $pageurl, $page, $hasattempts, |
739 | $defaultcategoryobj, $canaddquestion, $canaddrandom) { | |
825116fb | 740 | global $CFG, $OUTPUT; |
3e10e429 | 741 | static $randombuttoncount = 0; |
742 | $randombuttoncount++; | |
fa583f5f | 743 | echo '<div class="pagecontrols">'; |
cd120b23 | 744 | |
9e83f3d1 | 745 | // Get the current context. |
c492a78e | 746 | $thiscontext = context_course::instance($quiz->course); |
fa583f5f | 747 | $contexts = new question_edit_contexts($thiscontext); |
cd120b23 | 748 | |
749 | // Get the default category. | |
94dbfb3a | 750 | list($defaultcategoryid) = explode(',', $pageurl->param('cat')); |
f2956c98 TH |
751 | if (empty($defaultcategoryid)) { |
752 | $defaultcategoryid = $defaultcategoryobj->id; | |
753 | } | |
cd120b23 | 754 | |
76cf77e4 | 755 | if ($canaddquestion) { |
9e83f3d1 | 756 | // Create the url the question page will return to. |
76cf77e4 TH |
757 | $returnurladdtoquiz = new moodle_url($pageurl, array('addonpage' => $page)); |
758 | ||
759 | // Print a button linking to the choose question type page. | |
760 | $returnurladdtoquiz = $returnurladdtoquiz->out_as_local_url(false); | |
761 | $newquestionparams = array('returnurl' => $returnurladdtoquiz, | |
762 | 'cmid' => $quiz->cmid, 'appendqnumstring' => 'addquestion'); | |
763 | create_new_question_button($defaultcategoryid, $newquestionparams, | |
764 | get_string('addaquestion', 'quiz'), | |
765 | get_string('createquestionandadd', 'quiz'), $hasattempts); | |
766 | } | |
cd120b23 | 767 | |
fa583f5f | 768 | if ($hasattempts) { |
769 | $disabled = 'disabled="disabled"'; | |
770 | } else { | |
771 | $disabled = ''; | |
772 | } | |
76cf77e4 | 773 | if ($canaddrandom) { |
fa583f5f | 774 | ?> |
fa583f5f | 775 | <div class="singlebutton"> |
aac80ff3 TH |
776 | <form class="randomquestionform" action="<?php echo $CFG->wwwroot; |
777 | ?>/mod/quiz/addrandom.php" method="get"> | |
fa583f5f | 778 | <div> |
aac80ff3 TH |
779 | <input type="hidden" class="addonpage_formelement" name="addonpage" value="<?php |
780 | echo $page; ?>" /> | |
fa583f5f | 781 | <input type="hidden" name="cmid" value="<?php echo $quiz->cmid; ?>" /> |
782 | <input type="hidden" name="courseid" value="<?php echo $quiz->course; ?>" /> | |
aac80ff3 TH |
783 | <input type="hidden" name="category" value="<?php |
784 | echo $pageurl->param('cat'); ?>" /> | |
785 | <input type="hidden" name="returnurl" value="<?php | |
786 | echo s(str_replace($CFG->wwwroot, '', $pageurl->out(false))); ?>" /> | |
787 | <input type="submit" id="addrandomdialoglaunch_<?php | |
788 | echo $randombuttoncount; ?>" value="<?php | |
789 | echo get_string('addarandomquestion', 'quiz'); ?>" <?php | |
790 | echo " $disabled"; ?> /> | |
fa583f5f | 791 | </div> |
792 | </form> | |
793 | </div> | |
76cf77e4 TH |
794 | <?php echo $OUTPUT->help_icon('addarandomquestion', 'quiz'); |
795 | } | |
fa583f5f | 796 | echo "\n</div>"; |
797 | } | |
fa583f5f | 798 | |
fa583f5f | 799 | /** |
800 | * Print a given single question in quiz for the edit tab of edit.php. | |
801 | * Meant to be used from quiz_print_question_list() | |
f5831eea | 802 | * |
414d5bfb | 803 | * @param object $question A question object from the database questions table |
2a874d65 | 804 | * @param object $returnurl The url to get back to this page, for example after editing. |
414d5bfb | 805 | * @param object $quiz The quiz in the context of which the question is being displayed |
fa583f5f | 806 | */ |
f5831eea | 807 | function quiz_print_singlequestion($question, $returnurl, $quiz) { |
068384ce | 808 | echo '<div class="singlequestion ' . $question->qtype . '">'; |
aac80ff3 TH |
809 | echo quiz_question_edit_button($quiz->cmid, $question, $returnurl, |
810 | quiz_question_tostring($question) . ' '); | |
2a874d65 | 811 | echo '<span class="questiontype">'; |
5cc021a0 | 812 | echo print_question_icon($question); |
f9b0500f | 813 | echo ' ' . question_bank::get_qtype_name($question->qtype) . '</span>'; |
aac80ff3 TH |
814 | echo '<span class="questionpreview">' . |
815 | quiz_question_preview_button($quiz, $question, true) . '</span>'; | |
2a874d65 | 816 | echo "</div>\n"; |
fa583f5f | 817 | } |
818 | /** | |
819 | * Print a given random question in quiz for the edit tab of edit.php. | |
820 | * Meant to be used from quiz_print_question_list() | |
f5831eea | 821 | * |
414d5bfb | 822 | * @param object $question A question object from the database questions table |
823 | * @param object $questionurl The url of the question editing page as a moodle_url object | |
824 | * @param object $quiz The quiz in the context of which the question is being displayed | |
f7970e3c | 825 | * @param bool $quiz_qbanktool Indicate to this function if the question bank window open |
fa583f5f | 826 | */ |
4175a570 | 827 | function quiz_print_randomquestion($question, $pageurl, $quiz, $quiz_qbanktool) { |
f9b0500f | 828 | global $DB, $OUTPUT; |
fa583f5f | 829 | echo '<div class="quiz_randomquestion">'; |
830 | ||
aac80ff3 TH |
831 | if (!$category = $DB->get_record('question_categories', |
832 | array('id' => $question->category))) { | |
825116fb | 833 | echo $OUTPUT->notification('Random question category not found!'); |
fa583f5f | 834 | return; |
835 | } | |
836 | ||
837 | echo '<div class="randomquestionfromcategory">'; | |
5cc021a0 | 838 | echo print_question_icon($question); |
3cac440b | 839 | print_random_option_icon($question); |
8e84d978 | 840 | echo ' ' . get_string('randomfromcategory', 'quiz') . '</div>'; |
fa583f5f | 841 | |
0ff4bd08 | 842 | $a = new stdClass(); |
92e01ab7 | 843 | $a->arrow = $OUTPUT->rarrow(); |
2a874d65 | 844 | $strshowcategorycontents = get_string('showcategorycontents', 'quiz', $a); |
f4b879dd | 845 | |
b9bc2019 | 846 | $openqbankurl = $pageurl->out(true, array('qbanktool' => 1, |
2a874d65 | 847 | 'cat' => $category->id . ',' . $category->contextid)); |
848 | $linkcategorycontents = ' <a href="' . $openqbankurl . '">' . $strshowcategorycontents . '</a>'; | |
fa583f5f | 849 | |
2a874d65 | 850 | echo '<div class="randomquestioncategory">'; |
aac80ff3 TH |
851 | echo '<a href="' . $openqbankurl . '" title="' . $strshowcategorycontents . '">' . |
852 | $category->name . '</a>'; | |
853 | echo '<span class="questionpreview">' . | |
854 | quiz_question_preview_button($quiz, $question, true) . '</span>'; | |
2a874d65 | 855 | echo '</div>'; |
fa583f5f | 856 | |
fd214b59 | 857 | $questionids = question_bank::get_qtype('random')->get_available_questions_from_category( |
2a874d65 | 858 | $category->id, $question->questiontext == '1', '0'); |
859 | $questioncount = count($questionids); | |
fa583f5f | 860 | |
861 | echo '<div class="randomquestionqlist">'; | |
2a874d65 | 862 | if ($questioncount == 0) { |
9e83f3d1 | 863 | // No questions in category, give an error plus instructions. |
fa583f5f | 864 | echo '<span class="error">'; |
2a874d65 | 865 | print_string('noquestionsnotinuse', 'quiz'); |
9cdcf826 | 866 | echo '</span>'; |
fa583f5f | 867 | echo '<br />'; |
9cdcf826 | 868 | |
9e83f3d1 | 869 | // Embed the link into the string with instructions. |
0ff4bd08 | 870 | $a = new stdClass(); |
9cdcf826 | 871 | $a->catname = '<strong>' . $category->name . '</strong>'; |
2a874d65 | 872 | $a->link = $linkcategorycontents; |
f5831eea | 873 | echo get_string('addnewquestionsqbank', 'quiz', $a); |
537daa79 | 874 | |
2a874d65 | 875 | } else { |
9e83f3d1 | 876 | // Category has questions. |
f4b879dd | 877 | |
9e83f3d1 | 878 | // Get a sample from the database. |
fd214b59 | 879 | $questionidstoshow = array_slice($questionids, 0, NUM_QS_TO_SHOW_IN_RANDOM); |
2a874d65 | 880 | $questionstoshow = $DB->get_records_list('question', 'id', $questionidstoshow, |
25a03faa | 881 | '', 'id, qtype, name, questiontext, questiontextformat'); |
9cdcf826 | 882 | |
9e83f3d1 | 883 | // Then list them. |
2a874d65 | 884 | echo '<ul>'; |
4175a570 TH |
885 | foreach ($questionstoshow as $subquestion) { |
886 | echo '<li>' . quiz_question_tostring($subquestion, true) . '</li>'; | |
2a874d65 | 887 | } |
f4b879dd | 888 | |
9e83f3d1 | 889 | // Finally display the total number. |
2a874d65 | 890 | echo '<li class="totalquestionsinrandomqcategory">'; |
891 | if ($questioncount > NUM_QS_TO_SHOW_IN_RANDOM) { | |
892 | echo '... '; | |
893 | } | |
894 | print_string('totalquestionsinrandomqcategory', 'quiz', $questioncount); | |
895 | echo ' ' . $linkcategorycontents; | |
896 | echo '</li>'; | |
897 | echo '</ul>'; | |
ee1fb969 | 898 | } |
899 | ||
2a874d65 | 900 | echo '</div>'; |
fa583f5f | 901 | echo '<div class="randomquestioncategorycount">'; |
2a874d65 | 902 | echo '</div>'; |
903 | echo '</div>'; | |
fa583f5f | 904 | } |
ee1fb969 | 905 | |
fa583f5f | 906 | /** |
907 | * Print a given single question in quiz for the reordertool tab of edit.php. | |
908 | * Meant to be used from quiz_print_question_list() | |
f5831eea | 909 | * |
414d5bfb | 910 | * @param object $question A question object from the database questions table |
911 | * @param object $questionurl The url of the question editing page as a moodle_url object | |
912 | * @param object $quiz The quiz in the context of which the question is being displayed | |
fa583f5f | 913 | */ |
f5831eea | 914 | function quiz_print_singlequestion_reordertool($question, $returnurl, $quiz) { |
068384ce | 915 | echo '<div class="singlequestion ' . $question->qtype . '">'; |
2a874d65 | 916 | echo '<label for="s' . $question->id . '">'; |
5cc021a0 | 917 | echo print_question_icon($question); |
2a874d65 | 918 | echo ' ' . quiz_question_tostring($question); |
919 | echo '</label>'; | |
920 | echo '<span class="questionpreview">' . | |
921 | quiz_question_action_icons($quiz, $quiz->cmid, $question, $returnurl) . '</span>'; | |
922 | echo "</div>\n"; | |
fa583f5f | 923 | } |
3cac440b | 924 | |
fa583f5f | 925 | /** |
926 | * Print a given random question in quiz for the reordertool tab of edit.php. | |
927 | * Meant to be used from quiz_print_question_list() | |
f5831eea | 928 | * |
414d5bfb | 929 | * @param object $question A question object from the database questions table |
930 | * @param object $questionurl The url of the question editing page as a moodle_url object | |
931 | * @param object $quiz The quiz in the context of which the question is being displayed | |
fa583f5f | 932 | */ |
ccba5b88 | 933 | function quiz_print_randomquestion_reordertool($question, $pageurl, $quiz) { |
f9b0500f | 934 | global $DB, $OUTPUT; |
fa583f5f | 935 | |
2a874d65 | 936 | // Load the category, and the number of available questions in it. |
fa583f5f | 937 | if (!$category = $DB->get_record('question_categories', array('id' => $question->category))) { |
825116fb | 938 | echo $OUTPUT->notification('Random question category not found!'); |
fa583f5f | 939 | return; |
940 | } | |
aac80ff3 TH |
941 | $questioncount = count(question_bank::get_qtype( |
942 | 'random')->get_available_questions_from_category( | |
2a874d65 | 943 | $category->id, $question->questiontext == '1', '0')); |
fa583f5f | 944 | |
f5831eea | 945 | $reordercheckboxlabel = '<label for="s' . $question->id . '">'; |
2a874d65 | 946 | $reordercheckboxlabelclose = '</label>'; |
947 | ||
948 | echo '<div class="quiz_randomquestion">'; | |
949 | echo '<div class="randomquestionfromcategory">'; | |
fa583f5f | 950 | echo $reordercheckboxlabel; |
5cc021a0 | 951 | echo print_question_icon($question); |
3cac440b | 952 | print_random_option_icon($question); |
fa583f5f | 953 | |
2a874d65 | 954 | if ($questioncount == 0) { |
fa583f5f | 955 | echo '<span class="error">'; |
2a874d65 | 956 | print_string('empty', 'quiz'); |
fa583f5f | 957 | echo '</span> '; |
958 | } | |
959 | ||
2a874d65 | 960 | print_string('random', 'quiz'); |
fa583f5f | 961 | echo ": $reordercheckboxlabelclose</div>"; |
962 | ||
963 | echo '<div class="randomquestioncategory">'; | |
2a874d65 | 964 | echo $reordercheckboxlabel . $category->name . $reordercheckboxlabelclose; |
3814fb96 | 965 | echo '<span class="questionpreview">'; |
2a874d65 | 966 | echo quiz_question_preview_button($quiz, $question, false); |
fa583f5f | 967 | echo '</span>'; |
968 | echo "</div>"; | |
969 | ||
fa583f5f | 970 | echo '<div class="randomquestioncategorycount">'; |
2a874d65 | 971 | echo '</div>'; |
972 | echo '</div>'; | |
fa583f5f | 973 | } |
3cac440b | 974 | |
975 | /** | |
976 | * Print an icon to indicate the 'include subcategories' state of a random question. | |
977 | * @param $question the random question. | |
978 | */ | |
979 | function print_random_option_icon($question) { | |
5d3b9994 | 980 | global $OUTPUT; |
3cac440b | 981 | if (!empty($question->questiontext)) { |
982 | $icon = 'withsubcat'; | |
983 | $tooltip = get_string('randomwithsubcat', 'quiz'); | |
984 | } else { | |
985 | $icon = 'nosubcat'; | |
986 | $tooltip = get_string('randomnosubcat', 'quiz'); | |
987 | } | |
b5d0cafc | 988 | echo '<img src="' . $OUTPUT->pix_url('i/' . $icon) . '" alt="' . |
8e84d978 | 989 | $tooltip . '" title="' . $tooltip . '" class="uihint" />'; |
3cac440b | 990 | } |
991 | ||
fa583f5f | 992 | /** |
993 | * Creates a textual representation of a question for display. | |
f5831eea | 994 | * |
414d5bfb | 995 | * @param object $question A question object from the database questions table |
f7970e3c TH |
996 | * @param bool $showicon If true, show the question's icon with the question. False by default. |
997 | * @param bool $showquestiontext If true (default), show question text after question name. | |
414d5bfb | 998 | * If false, show only question name. |
f7970e3c | 999 | * @param bool $return If true (default), return the output. If false, print it. |
fa583f5f | 1000 | */ |
aac80ff3 TH |
1001 | function quiz_question_tostring($question, $showicon = false, |
1002 | $showquestiontext = true, $return = true) { | |
f9b0500f TH |
1003 | global $COURSE; |
1004 | $result = ''; | |
1005 | $result .= '<span class="questionname">'; | |
1006 | if ($showicon) { | |
1007 | $result .= print_question_icon($question, true); | |
1008 | echo ' '; | |
1009 | } | |
1010 | $result .= shorten_text(format_string($question->name), 200) . '</span>'; | |
1011 | if ($showquestiontext) { | |
e2b388c1 TH |
1012 | $questiontext = question_utils::to_plain_text($question->questiontext, |
1013 | $question->questiontextformat, array('noclean' => true, 'para' => false)); | |
f9b0500f TH |
1014 | $questiontext = shorten_text($questiontext, 200); |
1015 | $result .= '<span class="questiontext">'; | |
1016 | if (!empty($questiontext)) { | |
7051f3a8 | 1017 | $result .= s($questiontext); |
f5831eea | 1018 | } else { |
f9b0500f TH |
1019 | $result .= '<span class="error">'; |
1020 | $result .= get_string('questiontextisempty', 'quiz'); | |
1021 | $result .= '</span>'; | |
fa583f5f | 1022 | } |
f9b0500f TH |
1023 | $result .= '</span>'; |
1024 | } | |
1025 | if ($return) { | |
1026 | return $result; | |
1027 | } else { | |
1028 | echo $result; | |
1029 | } | |
fa583f5f | 1030 | } |
96241873 | 1031 | |
971c6fca | 1032 | /** |
1033 | * A column type for the add this question to the quiz. | |
f7970e3c TH |
1034 | * |
1035 | * @copyright 2009 Tim Hunt | |
1036 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
971c6fca | 1037 | */ |
1038 | class question_bank_add_to_quiz_action_column extends question_bank_action_column_base { | |
1039 | protected $stradd; | |
1040 | ||
1041 | public function init() { | |
1042 | parent::init(); | |
1043 | $this->stradd = get_string('addtoquiz', 'quiz'); | |
1044 | } | |
1045 | ||
1046 | public function get_name() { | |
1047 | return 'addtoquizaction'; | |
1048 | } | |
1049 | ||
1050 | protected function display_content($question, $rowclasses) { | |
76cf77e4 TH |
1051 | if (!question_has_capability_on($question, 'use')) { |
1052 | return; | |
1053 | } | |
9e83f3d1 | 1054 | // For RTL languages: switch right and left arrows. |
971c6fca | 1055 | if (right_to_left()) { |
453b28d8 | 1056 | $movearrow = 't/removeright'; |
971c6fca | 1057 | } else { |
453b28d8 | 1058 | $movearrow = 't/moveleft'; |
971c6fca | 1059 | } |
1060 | $this->print_icon($movearrow, $this->stradd, $this->qbank->add_to_quiz_url($question->id)); | |
1061 | } | |
1062 | ||
1063 | public function get_required_fields() { | |
1064 | return array('q.id'); | |
1065 | } | |
1066 | } | |
1067 | ||
1068 | /** | |
1069 | * A column type for the name followed by the start of the question text. | |
f7970e3c TH |
1070 | * |
1071 | * @copyright 2009 Tim Hunt | |
1072 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
971c6fca | 1073 | */ |
1074 | class question_bank_question_name_text_column extends question_bank_question_name_column { | |
1075 | public function get_name() { | |
1076 | return 'questionnametext'; | |
1077 | } | |
1078 | ||
1079 | protected function display_content($question, $rowclasses) { | |
1080 | echo '<div>'; | |
1081 | $labelfor = $this->label_for($question); | |
1082 | if ($labelfor) { | |
1083 | echo '<label for="' . $labelfor . '">'; | |
1084 | } | |
1085 | echo quiz_question_tostring($question, false, true, true); | |
1086 | if ($labelfor) { | |
1087 | echo '</label>'; | |
1088 | } | |
1089 | echo '</div>'; | |
1090 | } | |
1091 | ||
1092 | public function get_required_fields() { | |
1093 | $fields = parent::get_required_fields(); | |
1094 | $fields[] = 'q.questiontext'; | |
e4d1d5e0 | 1095 | $fields[] = 'q.questiontextformat'; |
971c6fca | 1096 | return $fields; |
1097 | } | |
1098 | } | |
1099 | ||
f4b879dd | 1100 | /** |
1101 | * Subclass to customise the view of the question bank for the quiz editing screen. | |
f7970e3c TH |
1102 | * |
1103 | * @copyright 2009 Tim Hunt | |
1104 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
f4b879dd | 1105 | */ |
17f229fa | 1106 | class quiz_question_bank_view extends core_question\bank\view { |
f4b879dd | 1107 | protected $quizhasattempts = false; |
612106b3 TH |
1108 | /** @var object the quiz settings. */ |
1109 | protected $quiz = false; | |
e22e7490 | 1110 | /** @var int The maximum displayed length of the category info. */ |
efa5155a | 1111 | const MAX_TEXT_LENGTH = 200; |
612106b3 TH |
1112 | |
1113 | /** | |
1114 | * Constructor | |
1115 | * @param question_edit_contexts $contexts | |
1116 | * @param moodle_url $pageurl | |
1117 | * @param object $course course settings | |
1118 | * @param object $cm activity settings. | |
1119 | * @param object $quiz quiz settings. | |
1120 | */ | |
1121 | public function __construct($contexts, $pageurl, $course, $cm, $quiz) { | |
1122 | parent::__construct($contexts, $pageurl, $course, $cm); | |
1123 | $this->quiz = $quiz; | |
1124 | } | |
96241873 | 1125 | |
971c6fca | 1126 | protected function wanted_columns() { |
17f229fa RM |
1127 | global $CFG; |
1128 | ||
1129 | if (empty($CFG->quizquestionbankcolumns)) { | |
1130 | $quizquestionbankcolumns = array('add_to_quiz_action_column', 'checkbox_column', 'question_type_column', | |
1131 | 'question_name_column', 'edit_action_column', 'preview_action_column'); | |
1132 | } else { | |
1133 | $quizquestionbankcolumns = explode(',', $CFG->quizquestionbankcolumns); | |
1134 | } | |
1135 | ||
1136 | foreach ($quizquestionbankcolumns as $fullname) { | |
1137 | if (! class_exists($fullname)) { | |
1138 | if (class_exists('question_bank_' . $fullname)) { | |
1139 | $fullname = 'question_bank_' . $fullname; | |
1140 | } else { | |
1141 | throw new coding_exception("No such class exists: $fullname"); | |
1142 | } | |
1143 | } | |
1144 | $this->requiredcolumns[$fullname] = new $fullname($this); | |
1145 | } | |
1146 | return $this->requiredcolumns; | |
f4b879dd | 1147 | } |
fa583f5f | 1148 | |
f262c4cb | 1149 | /** |
d2c9169a RW |
1150 | * Specify the column heading |
1151 | * | |
1152 | * @return string Column name for the heading | |
1153 | */ | |
1154 | protected function heading_column() { | |
1155 | return 'questionnametext'; | |
1156 | } | |
1157 | ||
29ded2d6 | 1158 | protected function default_sort() { |
17f229fa | 1159 | return array('question_bank_question_type_column' => 1, 'question_bank_question_name_column' => 1); |
29ded2d6 TH |
1160 | } |
1161 | ||
f4b879dd | 1162 | /** |
1163 | * Let the question bank display know whether the quiz has been attempted, | |
1164 | * hence whether some bits of UI, like the add this question to the quiz icon, | |
1165 | * should be displayed. | |
f7970e3c | 1166 | * @param bool $quizhasattempts whether the quiz has attempts. |
f4b879dd | 1167 | */ |
1168 | public function set_quiz_has_attempts($quizhasattempts) { | |
1169 | $this->quizhasattempts = $quizhasattempts; | |
971c6fca | 1170 | if ($quizhasattempts && isset($this->visiblecolumns['addtoquizaction'])) { |
1171 | unset($this->visiblecolumns['addtoquizaction']); | |
1172 | } | |
1173 | } | |
1174 | ||
612106b3 TH |
1175 | public function preview_question_url($question) { |
1176 | return quiz_question_preview_url($this->quiz, $question); | |
e4d1d5e0 | 1177 | } |
1178 | ||
971c6fca | 1179 | public function add_to_quiz_url($questionid) { |
1180 | global $CFG; | |
8afba50b PS |
1181 | $params = $this->baseurl->params(); |
1182 | $params['addquestion'] = $questionid; | |
1183 | $params['sesskey'] = sesskey(); | |
1184 | return new moodle_url('/mod/quiz/edit.php', $params); | |
f4b879dd | 1185 | } |
fa583f5f | 1186 | |
b72b4137 TH |
1187 | public function display($tabname, $page, $perpage, $cat, |
1188 | $recurse, $showhidden, $showquestiontext) { | |
3b1d5cc4 | 1189 | global $OUTPUT; |
5bd22790 | 1190 | if ($this->process_actions_needing_ui()) { |
5b5e5ab2 | 1191 | return; |
1192 | } | |
f4b879dd | 1193 | |
efa5155a RM |
1194 | $editcontexts = $this->contexts->having_one_edit_tab_cap($tabname); |
1195 | array_unshift($this->searchconditions, | |
d62382d1 | 1196 | new \core_question\bank\search\hidden_condition(!$showhidden)); |
efa5155a | 1197 | array_unshift($this->searchconditions, |
d62382d1 | 1198 | new \core_question\bank\search\category_condition($cat, $recurse, |
efa5155a | 1199 | $editcontexts, $this->baseurl, $this->course, self::MAX_TEXT_LENGTH)); |
5b5e5ab2 | 1200 | |
3b1d5cc4 | 1201 | echo $OUTPUT->box_start('generalbox questionbank'); |
efa5155a | 1202 | $this->display_options_form($showquestiontext); |
5b5e5ab2 | 1203 | |
9e83f3d1 | 1204 | // Continues with list of questions. |
aac80ff3 TH |
1205 | $this->display_question_list($this->contexts->having_one_edit_tab_cap($tabname), |
1206 | $this->baseurl, $cat, $this->cm, $recurse, $page, | |
b72b4137 | 1207 | $perpage, $showhidden, $showquestiontext, |
5bd22790 | 1208 | $this->contexts->having_cap('moodle/question:add')); |
5b5e5ab2 | 1209 | |
3b1d5cc4 | 1210 | echo $OUTPUT->box_end(); |
f4b879dd | 1211 | } |
5b5e5ab2 | 1212 | |
efa5155a RM |
1213 | /** |
1214 | * prints a form to choose categories | |
e22e7490 | 1215 | * @param string $categoryandcontext 'categoryID,contextID'. |
efa5155a | 1216 | * @deprecated since Moodle 2.6 MDL-40313. |
d62382d1 | 1217 | * @see \core_question\bank\search\category_condition |
efa5155a RM |
1218 | * @todo MDL-41978 This will be deleted in Moodle 2.8 |
1219 | */ | |
971c6fca | 1220 | protected function print_choose_category_message($categoryandcontext) { |
3b1d5cc4 | 1221 | global $OUTPUT; |
e22e7490 | 1222 | debugging('print_choose_category_message() is deprecated, ' . |
d62382d1 | 1223 | 'please use \core_question\bank\search\category_condition instead.', DEBUG_DEVELOPER); |
3b1d5cc4 | 1224 | echo $OUTPUT->box_start('generalbox questionbank'); |
aac80ff3 TH |
1225 | $this->display_category_form($this->contexts->having_one_edit_tab_cap('edit'), |
1226 | $this->baseurl, $categoryandcontext); | |
971c6fca | 1227 | echo "<p style=\"text-align:center;\"><b>"; |
0030db53 | 1228 | print_string('selectcategoryabove', 'question'); |
971c6fca | 1229 | echo "</b></p>"; |
3b1d5cc4 | 1230 | echo $OUTPUT->box_end(); |
5bd22790 | 1231 | } |
1232 | ||
84deaaf8 TH |
1233 | protected function display_options_form($showquestiontext, $scriptpath = '/mod/quiz/edit.php', |
1234 | $showtextoption = false) { | |
1235 | // Overridden just to change the default values of the arguments. | |
1236 | parent::display_options_form($showquestiontext, $scriptpath, $showtextoption); | |
efa5155a RM |
1237 | } |
1238 | ||
971c6fca | 1239 | protected function print_category_info($category) { |
0ff4bd08 | 1240 | $formatoptions = new stdClass(); |
971c6fca | 1241 | $formatoptions->noclean = true; |
1242 | $strcategory = get_string('category', 'quiz'); | |
f5831eea | 1243 | echo '<div class="categoryinfo"><div class="categorynamefieldcontainer">' . |
971c6fca | 1244 | $strcategory; |
1245 | echo ': <span class="categorynamefield">'; | |
22cebed5 | 1246 | echo shorten_text(strip_tags(format_string($category->name)), 60); |
aac80ff3 TH |
1247 | echo '</span></div><div class="categoryinfofieldcontainer">' . |
1248 | '<span class="categoryinfofield">'; | |
22cebed5 | 1249 | echo shorten_text(strip_tags(format_text($category->info, $category->infoformat, |
f5831eea | 1250 | $formatoptions, $this->course->id)), 200); |
971c6fca | 1251 | echo '</span></div></div>'; |
5bd22790 | 1252 | } |
1253 | ||
92e6e128 | 1254 | protected function display_options($recurse, $showhidden, $showquestiontext) { |
efa5155a | 1255 | debugging('display_options() is deprecated, see display_options_form() instead.', DEBUG_DEVELOPER); |
971c6fca | 1256 | echo '<form method="get" action="edit.php" id="displayoptions">'; |
1257 | echo "<fieldset class='invisiblefieldset'>"; | |
aac80ff3 | 1258 | echo html_writer::input_hidden_params($this->baseurl, |
e20ad67d | 1259 | array('recurse', 'showhidden', 'qbshowtext')); |
92e6e128 | 1260 | $this->display_category_form_checkbox('recurse', $recurse, |
aac80ff3 | 1261 | get_string('includesubcategories', 'question')); |
92e6e128 | 1262 | $this->display_category_form_checkbox('showhidden', $showhidden, |
aac80ff3 TH |
1263 | get_string('showhidden', 'question')); |
1264 | echo '<noscript><div class="centerpara"><input type="submit" value="' . | |
1265 | get_string('go') . '" />'; | |
971c6fca | 1266 | echo '</div></noscript></fieldset></form>'; |
5bd22790 | 1267 | } |
8bccba71 | 1268 | } |
f4b879dd | 1269 | |
8bccba71 | 1270 | /** |
1271 | * Prints the form for setting a quiz' overall grade | |
f5831eea | 1272 | * |
414d5bfb | 1273 | * @param object $quiz The quiz object of the quiz in question |
f5831eea | 1274 | * @param object $pageurl The url of the current page with the parameters required |
414d5bfb | 1275 | * for links returning to the current page, as a moodle_url object |
f7970e3c TH |
1276 | * @param int $tabindex The tabindex to start from for the form elements created |
1277 | * @return int The tabindex from which the calling page can continue, that is, | |
414d5bfb | 1278 | * the last value used +1. |
8bccba71 | 1279 | */ |
f5831eea | 1280 | function quiz_print_grading_form($quiz, $pageurl, $tabindex) { |
cef18275 | 1281 | global $OUTPUT; |
f5831eea | 1282 | $strsave = get_string('save', 'quiz'); |
fd214b59 | 1283 | echo '<form method="post" action="edit.php" class="quizsavegradesform"><div>'; |
8bccba71 | 1284 | echo '<fieldset class="invisiblefieldset" style="display: block;">'; |
f5831eea | 1285 | echo "<input type=\"hidden\" name=\"sesskey\" value=\"" . sesskey() . "\" />"; |
6ea66ff3 | 1286 | echo html_writer::input_hidden_params($pageurl); |
aac80ff3 TH |
1287 | $a = '<input type="text" id="inputmaxgrade" name="maxgrade" size="' . |
1288 | ($quiz->decimalpoints + 2) . '" tabindex="' . $tabindex | |
f5831eea | 1289 | . '" value="' . quiz_format_grade($quiz, $quiz->grade) . '" />'; |
1290 | echo '<label for="inputmaxgrade">' . get_string('maximumgradex', '', $a) . "</label>"; | |
1291 | echo '<input type="hidden" name="savechanges" value="save" />'; | |
1292 | echo '<input type="submit" value="' . $strsave . '" />'; | |
8bccba71 | 1293 | echo '</fieldset>'; |
1294 | echo "</div></form>\n"; | |
f5831eea | 1295 | return $tabindex + 1; |
8bccba71 | 1296 | } |
f4b879dd | 1297 | |
8bccba71 | 1298 | /** |
1299 | * Print the status bar | |
1300 | * | |
414d5bfb | 1301 | * @param object $quiz The quiz object of the quiz in question |
8bccba71 | 1302 | */ |
f5831eea | 1303 | function quiz_print_status_bar($quiz) { |
ccba5b88 | 1304 | global $DB; |
c5da295b TH |
1305 | |
1306 | $bits = array(); | |
1307 | ||
1308 | $bits[] = html_writer::tag('span', | |
5127e52d | 1309 | get_string('totalmarksx', 'quiz', quiz_format_grade($quiz, $quiz->sumgrades)), |
c5da295b TH |
1310 | array('class' => 'totalpoints')); |
1311 | ||
1312 | $bits[] = html_writer::tag('span', | |
ccba5b88 | 1313 | get_string('numquestionsx', 'quiz', $DB->count_records('quiz_slots', array('quizid' => $quiz->id))), |
c5da295b TH |
1314 | array('class' => 'numberofquestions')); |
1315 | ||
e476804c | 1316 | $timenow = time(); |
c5da295b TH |
1317 | |
1318 | // Exact open and close dates for the tool-tip. | |
1319 | $dates = array(); | |
e476804c | 1320 | if ($quiz->timeopen > 0) { |
1321 | if ($timenow > $quiz->timeopen) { | |
940b5fbb | 1322 | $dates[] = get_string('quizopenedon', 'quiz', userdate($quiz->timeopen)); |
e476804c | 1323 | } else { |
940b5fbb | 1324 | $dates[] = get_string('quizwillopen', 'quiz', userdate($quiz->timeopen)); |
e476804c | 1325 | } |
1326 | } | |
1327 | if ($quiz->timeclose > 0) { | |
1328 | if ($timenow > $quiz->timeclose) { | |
940b5fbb | 1329 | $dates[] = get_string('quizclosed', 'quiz', userdate($quiz->timeclose)); |
e476804c | 1330 | } else { |
940b5fbb | 1331 | $dates[] = get_string('quizcloseson', 'quiz', userdate($quiz->timeclose)); |
e476804c | 1332 | } |
1333 | } | |
1334 | if (empty($dates)) { | |
1335 | $dates[] = get_string('alwaysavailable', 'quiz'); | |
1336 | } | |
0e35ba6f | 1337 | $tooltip = implode(', ', $dates); |
c5da295b TH |
1338 | |
1339 | // Brief summary on the page. | |
1340 | if ($timenow < $quiz->timeopen) { | |
1341 | $currentstatus = get_string('quizisclosedwillopen', 'quiz', | |
72bbb091 | 1342 | userdate($quiz->timeopen, get_string('strftimedatetimeshort', 'langconfig'))); |
c5da295b TH |
1343 | } else if ($quiz->timeclose && $timenow <= $quiz->timeclose) { |
1344 | $currentstatus = get_string('quizisopenwillclose', 'quiz', | |
1345 | userdate($quiz->timeclose, get_string('strftimedatetimeshort', 'langconfig'))); | |
1346 | } else if ($quiz->timeclose && $timenow > $quiz->timeclose) { | |
1347 | $currentstatus = get_string('quizisclosed', 'quiz'); | |
1348 | } else { | |
1349 | $currentstatus = get_string('quizisopen', 'quiz'); | |
1350 | } | |
940b5fbb | 1351 | |
c5da295b TH |
1352 | $bits[] = html_writer::tag('span', $currentstatus, |
1353 | array('class' => 'quizopeningstatus', 'title' => implode(', ', $dates))); | |
1354 | ||
1355 | echo html_writer::tag('div', implode(' | ', $bits), array('class' => 'statusbar')); | |
8bccba71 | 1356 | } |