MDL-20204 fixed regression from button conversion
[moodle.git] / mod / quiz / editlib.php
CommitLineData
83192608 1<?php
f4b879dd 2
3///////////////////////////////////////////////////////////////////////////
4// //
5// NOTICE OF COPYRIGHT //
6// //
7// Moodle - Modular Object-Oriented Dynamic Learning Environment //
8// http://moodle.org //
9// //
10// Copyright (C) 1999 onwards Martin Dougiamas and others //
11// //
12// This program is free software; you can redistribute it and/or modify //
13// it under the terms of the GNU General Public License as published by //
14// the Free Software Foundation; either version 2 of the License, or //
15// (at your option) any later version. //
16// //
17// This program is distributed in the hope that it will be useful, //
18// but WITHOUT ANY WARRANTY; without even the implied warranty of //
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
20// GNU General Public License for more details: //
21// //
22// http://www.gnu.org/copyleft/gpl.html //
23// //
24///////////////////////////////////////////////////////////////////////////
25
ee1fb969 26/**
f63a4ff2 27 * Functions used by edit.php to edit quizzes
28 *
f63a4ff2 29 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
30 * @package quiz
f4b879dd 31 *//** */
ee1fb969 32
f5831eea 33require_once($CFG->dirroot . '/mod/quiz/locallib.php');
ee1fb969 34
2a874d65 35define('NUM_QS_TO_SHOW_IN_RANDOM', 3);
36
ee1fb969 37/**
4299df1d 38 * Remove a question from a quiz
39 * @param object $quiz the quiz object.
40 * @param int $questionid The id of the question to be deleted.
41 */
42function quiz_remove_question($quiz, $questionid) {
9cf4a18b 43 global $DB;
ee1fb969 44
4299df1d 45 $questionids = explode(',', $quiz->questions);
46 $key = array_search($questionid, $questionids);
47 if ($key === false) {
48 return;
ee1fb969 49 }
50
4299df1d 51 unset($questionids[$key]);
52 $quiz->questions = implode(',', $questionids);
53 $DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->id));
54 $DB->delete_records('quiz_question_instances', array('quiz' => $quiz->instance, 'question' => $questionid));
55}
56
57/**
58 * Remove an empty page from the quiz layout. If that is not possible, do nothing.
59 * @param string $layout the existinng layout, $quiz->questions.
60 * @param integer $index the position into $layout where the empty page should be removed.
61 * @return the updated layout
62 */
63function quiz_delete_empty_page($layout, $index) {
64 $questionids = explode(',', $layout);
65
66 if ($index < -1 || $index >= count($questionids) - 1) {
67 return $layout;
ee1fb969 68 }
4299df1d 69
70 if (($index >= 0 && $questionids[$index] != 0) || $questionids[$index + 1] != 0) {
71 return $layout; // This was not an empty page.
72 }
73
74 unset($questionids[$index + 1]);
75
76 return implode(',', $questionids);
ee1fb969 77}
78
ee1fb969 79/**
f5831eea 80 * Add a question to a quiz
81 *
82 * Adds a question to a quiz by updating $quiz as well as the
83 * quiz and quiz_question_instances tables. It also adds a page break
84 * if required.
85 * @return boolean false if the question was already in the quiz
86 * @param int $id The id of the question to be added
87 * @param object $quiz The extended quiz object as used by edit.php
88 * This is updated by this function
89 * @param int $page Which page in quiz to add the question on; if 0 (default), add at the end
90 */
91function quiz_add_quiz_question($id, &$quiz, $page = 0) {
9cf4a18b 92 global $DB;
f5831eea 93 $questions = explode(',', $quiz->questions);
ee1fb969 94 if (in_array($id, $questions)) {
95 return false;
96 }
97
98 // remove ending page break if it is not needed
99 if ($breaks = array_keys($questions, 0)) {
100 // determine location of the last two page breaks
101 $end = end($breaks);
102 $last = prev($breaks);
103 $last = $last ? $last : -1;
f5831eea 104 if (!$quiz->questionsperpage || (($end - $last -1) < $quiz->questionsperpage)) {
ee1fb969 105 array_pop($questions);
106 }
107 }
f5831eea 108 if (is_int($page) && $page >= 1) {
109 $numofpages = quiz_number_of_pages($quiz->questions);
110 if ($numofpages<$page) {
fa583f5f 111 //the page specified does not exist in quiz
f5831eea 112 $page = 0;
113 } else {
fa583f5f 114 // add ending page break - the following logic requires doing
115 //this at this point
116 $questions[] = 0;
f5831eea 117 $currentpage = 1;
118 $addnow = false;
119 foreach ($questions as $question) {
120 if ($question == 0) {
fa583f5f 121 $currentpage++;
122 //The current page is the one after the one we want to add on,
123 //so we add the question before adding the current page.
f5831eea 124 if ($currentpage == $page + 1) {
125 $questions_new[] = $id;
fa583f5f 126 }
127 }
f5831eea 128 $questions_new[] = $question;
fa583f5f 129 }
f5831eea 130 $questions = $questions_new;
fa583f5f 131 }
132 }
f5831eea 133 if ($page == 0) {
fa583f5f 134 // add question
135 $questions[] = $id;
136 // add ending page break
137 $questions[] = 0;
138 }
ee1fb969 139
140 // Save new questionslist in database
f5831eea 141 $quiz->questions = implode(',', $questions);
9cf4a18b 142 if (!$DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->id))) {
550f9654 143 print_error('cannotsavequestion', 'quiz');
ee1fb969 144 }
145
146 // update question grades
ad65ff47 147 $quiz->grades[$id] = $DB->get_field('question', 'defaultgrade', array('id' => $id));
b72ff476 148 quiz_update_question_instance($quiz->grades[$id], $id, $quiz->instance);
7c4127ef 149
ee1fb969 150 return true;
151}
152
4299df1d 153/**
154 * Add a page break after at particular position$.
155 * @param string $layout the existinng layout, $quiz->questions.
156 * @param integer $index the position into $layout where the empty page should be removed.
157 * @return the updated layout
158 */
159function quiz_add_page_break_at($layout, $index) {
160 $questionids = explode(',', $layout);
161 if ($index < 0 || $index >= count($questionids)) {
162 return $layout;
163 }
164
165 array_splice($questionids, $index, 0, '0');
166
167 return implode(',', $questionids);
168}
169
170/**
171 * Add a page break after a particular question.
172 * @param string $layout the existinng layout, $quiz->questions.
173 * @param integer $qustionid the question to add the page break after.
174 * @return the updated layout
175 */
176function quiz_add_page_break_after($layout, $questionid) {
177 $questionids = explode(',', $layout);
178 $key = array_search($questionid, $questionids);
179 if ($key === false || !$questionid) {
180 return $layout;
181 }
182
183 array_splice($questionids, $key + 1, 0, '0');
184
185 return implode(',', $questionids);
186}
187
188/**
189 * Update the database after $quiz->questions has been changed. For example,
190 * this deletes preview attempts and updates $quiz->sumgrades.
191 * @param $quiz the quiz object.
192 */
193function quiz_save_new_layout($quiz) {
194 global $DB;
195 $DB->set_field('quiz', 'questions', $quiz->questions, array('id' => $quiz->id));
196 quiz_update_sumgrades($quiz);
197 quiz_delete_previews($quiz);
198}
199
ee1fb969 200/**
f5831eea 201 * Save changes to question instance
202 *
203 * Saves changes to the question grades in the quiz_question_instances table.
204 * It does not update 'sumgrades' in the quiz table.
205 * @return boolean Indicates success or failure.
206 * @param integer grade The maximal grade for the question
207 * @param integer $questionid The id of the question
208 * @param integer $quizid The id of the quiz to update / add the instances for.
209 */
ee1fb969 210function quiz_update_question_instance($grade, $questionid, $quizid) {
9cf4a18b 211 global $DB;
212 if ($instance = $DB->get_record('quiz_question_instances', array('quiz' => $quizid, 'question' => $questionid))) {
ee1fb969 213 $instance->grade = $grade;
9cf4a18b 214 return $DB->update_record('quiz_question_instances', $instance);
ee1fb969 215 } else {
216 unset($instance);
217 $instance->quiz = $quizid;
218 $instance->question = $questionid;
219 $instance->grade = $grade;
f5831eea 220 return $DB->insert_record('quiz_question_instances', $instance);
ee1fb969 221 }
222}
223
4299df1d 224// Private function used by the following two.
225function _quiz_move_question($layout, $questionid, $shift) {
226 if (!$questionid || !($shift == 1 || $shift == -1)) {
227 return $layout;
228 }
229
230 $questionids = explode(',', $layout);
231 $key = array_search($questionid, $questionids);
232 if ($key === false) {
233 return $layout;
234 }
235
236 $otherkey = $key + $shift;
237 if ($otherkey < 0 || $otherkey >= count($questionids) - 1) {
238 return $layout;
239 }
240
241 $temp = $questionids[$otherkey];
242 $questionids[$otherkey] = $questionids[$key];
243 $questionids[$key] = $temp;
244
245 return implode(',', $questionids);
246}
247
248/**
249 * Move a particular question one space earlier in the $quiz->questions list.
250 * If that is not possible, do nothing.
251 * @param string $layout the existinng layout, $quiz->questions.
252 * @param integer $questionid the id of a question.
253 * @return the updated layout
254 */
255function quiz_move_question_up($layout, $questionid) {
256 return _quiz_move_question($layout, $questionid, -1);
257}
258
259/**
260 * Move a particular question one space later in the $quiz->questions list.
261 * If that is not possible, do nothing.
262 * @param string $layout the existinng layout, $quiz->questions.
263 * @param integer $questionid the id of a question.
264 * @return the updated layout
265 */
266function quiz_move_question_down($layout, $questionid) {
267 return _quiz_move_question($layout, $questionid, +1);
268}
269
ee1fb969 270/**
f5831eea 271 * Prints a list of quiz questions for the edit.php main view for edit
272 * ($reordertool = false) and order and paging ($reordertool = true) tabs
273 *
274 * @return int sum of maximum grades
275 * @param object $quiz This is not the standard quiz object used elsewhere but
276 * it contains the quiz layout in $quiz->questions and the grades in
277 * $quiz->grades
278 * @param object $pageurl The url of the current page with the parameters required
279 * for links returning to the current page, as a moodle_url object
280 * @param boolean $allowdelete Indicates whether the delete icons should be displayed
281 * @param boolean $reordertool Indicates whether the reorder tool should be displayed
282 * @param boolean $quiz_qbanktool Indicates whether the question bank should be displayed
283 * @param boolean $hasattempts Indicates whether the quiz has attempts
284 */
285function quiz_print_question_list($quiz, $pageurl, $allowdelete = true,
286 $reordertool = false, $quiz_qbanktool = false,
287 $hasattempts = false) {
4096752d 288 global $USER, $CFG, $QTYPES, $DB, $OUTPUT;
f5831eea 289 $strorder = get_string('order');
290 $strquestionname = get_string('questionname', 'quiz');
291 $strgrade = get_string('grade');
ee1fb969 292 $strremove = get_string('remove', 'quiz');
f5831eea 293 $stredit = get_string('edit');
294 $strview = get_string('view');
295 $straction = get_string('action');
296 $strmove = get_string('move');
297 $strmoveup = get_string('moveup');
298 $strmovedown = get_string('movedown');
299 $strsave = get_string('save', 'quiz');
300 $strreorderquestions = get_string('reorderquestions', 'quiz');
301
302 $strselectall = get_string('selectall', 'quiz');
303 $strselectnone = get_string('selectnone', 'quiz');
304 $strtype = get_string('type', 'quiz');
305 $strpreview = get_string('preview', 'quiz');
ee1fb969 306
477c217f 307 if ($quiz->questions) {
fa583f5f 308 list($usql, $params) = $DB->get_in_or_equal(explode(',', $quiz->questions));
309 $questions = $DB->get_records_sql("SELECT q.*,c.contextid
9cf4a18b 310 FROM {question} q,
311 {question_categories} c
312 WHERE q.id $usql
fa583f5f 313 AND q.category = c.id", $params);
477c217f 314 } else {
315 $questions = array();
ee1fb969 316 }
317
f5831eea 318 $layout = quiz_clean_layout($quiz->questions);
fa583f5f 319 $order = explode(',', $layout);
f5831eea 320 $lastindex = count($order) - 1;
fa583f5f 321
3e10e429 322 $disabled = '';
323 $pagingdisabled = '';
477c217f 324 if ($hasattempts) {
f5831eea 325 $disabled = 'disabled="disabled"';
fa583f5f 326 }
3e10e429 327 if ($hasattempts || $quiz->shufflequestions) {
f5831eea 328 $pagingdisabled = 'disabled="disabled"';
ee68029a 329 }
ee1fb969 330
f5831eea 331 $reordercontrolssetdefaultsubmit = '<div style="display:none;">' .
332 '<input type="submit" name="savechanges" value="' .
3e10e429 333 $strreorderquestions . '" ' . $pagingdisabled . ' /></div>';
f5831eea 334 $reordercontrols1 = '<div class="addnewpagesafterselected">' .
335 '<input type="submit" name="addnewpagesafterselected" value="' .
336 get_string('addnewpagesafterselected', 'quiz') . '" ' .
337 $pagingdisabled . ' /></div>';
7b161e12 338 $reordercontrols1 .= '<div class="quizdeleteselected">' .
339 '<input type="submit" name="quizdeleteselected" ' .
340 'onclick="return confirm(\'' .
341 get_string('areyousureremoveselected', 'quiz') . '\');" value="' .
342 get_string('removeselected', 'quiz') . '" ' . $disabled . ' /></div>';
fa583f5f 343
f5831eea 344 $a = '<input name="moveselectedonpagetop" type="text" size="2" ' .
345 $pagingdisabled . ' />';
346
347 $reordercontrols2top = '<div class="moveselectedonpage">' .
348 get_string('moveselectedonpage', 'quiz', $a) .
349 '<input type="submit" name="savechanges" value="' .
350 $strmove . '" ' . $pagingdisabled . ' />' . '
351 <br /><input type="submit" name="savechanges" value="' .
3e10e429 352 $strreorderquestions . '" /></div>';
f5831eea 353 $reordercontrols2bottom = '<div class="moveselectedonpage">' .
354 '<input type="submit" name="savechanges" value="' .
3e10e429 355 $strreorderquestions . '" /><br />' .
f5831eea 356 get_string('moveselectedonpage', 'quiz', $a) .
357 '<input type="submit" name="savechanges" value="' .
358 $strmove . '" ' . $pagingdisabled . ' /> ' . '</div>';
359
360 $reordercontrols3 = '<a href="javascript:select_all_in(\'FORM\', null, ' .
361 '\'quizquestions\');">' .
362 $strselectall . '</a> /';
363 $reordercontrols3.= ' <a href="javascript:deselect_all_in(\'FORM\', ' .
364 'null, \'quizquestions\');">' .
365 $strselectnone . '</a>';
366
367 $reordercontrolstop = '<div class="reordercontrols">' .
368 $reordercontrolssetdefaultsubmit .
369 $reordercontrols1 . $reordercontrols2top . $reordercontrols3 . "</div>";
370 $reordercontrolsbottom = '<div class="reordercontrols">' .
371 $reordercontrolssetdefaultsubmit .
372 $reordercontrols2bottom . $reordercontrols1 . $reordercontrols3 . "</div>";
373
374 if ($reordertool) {
fa583f5f 375 echo '<form method="post" action="edit.php" id="quizquestions"><div>';
376
6ea66ff3 377 echo html_writer::input_hidden_params($pageurl);
f5831eea 378 echo '<input type="hidden" name="sesskey" value="' . sesskey() . '" />';
fa583f5f 379
380 echo $reordercontrolstop;
9cf4a18b 381 }
9aa82ed6 382
fa583f5f 383 //the current question ordinal (no descriptions)
384 $qno = 1;
385 //the current question (includes questions and descriptions)
f5831eea 386 $questioncount = 0;
fa583f5f 387 //the ordinal of current element in the layout
388 //(includes page breaks, questions and descriptions)
389 $count = 0;
390 //the current page number in iteration
391 $pagecount = 0;
392
393 $sumgrade = 0;
394
f5831eea 395 $pageopen = false;
fa583f5f 396
397 $returnurl = $pageurl->out();
f5831eea 398 $questiontotalcount = count($order);
fa583f5f 399
14afbbf0 400 foreach ($order as $i => $qnum) {
ee1fb969 401
f5831eea 402 $reordercheckbox = '';
403 $reordercheckboxlabel = '';
404 $reordercheckboxlabelclose = '';
fa583f5f 405
f5831eea 406 if ($qnum && empty($questions[$qnum])) {
14afbbf0 407 continue;
408 }
4eda4eec 409 // If the questiontype is missing change the question type
f5831eea 410 if ($qnum && !array_key_exists($questions[$qnum]->qtype, $QTYPES)) {
4eda4eec 411 $questions[$qnum]->qtype = 'missingtype';
412 }
f5831eea 413 $deletex = "delete.gif";
4299df1d 414 if ($qnum != 0 || ($qnum == 0 && !$pageopen)) {
fa583f5f 415 //this is either a question or a page break after another
416 // (no page is currently open)
4299df1d 417 if (!$pageopen) {
fa583f5f 418 //if no page is open, start display of a page
419 $pagecount++;
f5831eea 420 echo '<div class="quizpage"><span class="pagetitle">' .
421 get_string('page') . '&nbsp;' . $pagecount .
fa583f5f 422 '</span><div class="pagecontent">';
4299df1d 423 $pageopen = true;
fa583f5f 424 }
4299df1d 425 if ($qnum == 0 && $i < $questiontotalcount) {
426 // This is the second successive page break. Tell the user the page is empty.
fa583f5f 427 echo '<div class="pagestatus">';
f5831eea 428 print_string('noquestionsonpage', 'quiz');
fa583f5f 429 echo '</div>';
4299df1d 430 if ($allowdelete && !$quiz->questionsperpage) {
fa583f5f 431 echo '<div class="quizpagedelete">';
4299df1d 432 echo '<a title="' . get_string('removeemptypage', 'quiz') . '" href="' .
8afba50b 433 $pageurl->out(true, array('deleteemptypage' => $i - 1, 'sesskey'=>sesskey())) .
b5d0cafc 434 '"><img src="' . $OUTPUT->pix_url('t/delete') . '" ' .
4299df1d 435 'class="iconsmall" alt="' . $strremove . '" /></a>';
fa583f5f 436 echo '</div>';
437 }
438 }
439
f5831eea 440 if ($qnum!=0) {
fa583f5f 441 $question = $questions[$qnum];
442 $questionparams = array('returnurl' => $returnurl,
f5831eea 443 'cmid' => $quiz->cmid, 'id' => $question->id);
fa583f5f 444 $questionurl = new moodle_url("$CFG->wwwroot/question/question.php",
445 $questionparams);
446 $questioncount++;
447 //this is an actual question
4eda4eec 448
fa583f5f 449 /* Display question start */
450?>
451<div class="question">
944efb3e 452 <div class="questioncontainer <?php echo $question->qtype; ?>">
fa583f5f 453 <div class="qnum">
454 <?php
f5831eea 455 $reordercheckbox = '';
456 $reordercheckboxlabel = '';
457 $reordercheckboxlabelclose = '';
458 if ($reordertool) {
459 $reordercheckbox = '<input type="checkbox" name="s' . $question->id .
460 '" id="s' . $question->id . '" />';
461 $reordercheckboxlabel = '<label for="s' . $question->id . '">';
462 $reordercheckboxlabelclose = '</label>';
fa583f5f 463 }
464 if (!$quiz->shufflequestions) {
465 // Print and increment question number
f5831eea 466 $questioncountstring = '';
467 if ($questioncount>999 || ($reordertool && $questioncount>99)) {
468 $questioncountstring =
469 "$reordercheckboxlabel<small>$questioncount</small>" .
470 $reordercheckboxlabelclose . $reordercheckbox;
471 } else {
472 $questioncountstring = $reordercheckboxlabel . $questioncount .
473 $reordercheckboxlabelclose . $reordercheckbox;
fa583f5f 474 }
475 echo $questioncountstring;
476 $qno += $question->length;
14afbbf0 477 } else {
3e10e429 478 echo "$reordercheckboxlabel ? $reordercheckboxlabelclose" .
fa583f5f 479 " $reordercheckbox";
14afbbf0 480 }
fa583f5f 481
482 ?>
483 </div>
484 <div class="content">
485 <div class="questioncontrols">
486 <?php
487 if ($count != 0) {
4299df1d 488 if (!$hasattempts) {
f5831eea 489 $upbuttonclass = '';
4299df1d 490 if ($count >= $lastindex - 1) {
f5831eea 491 $upbuttonclass = 'upwithoutdown';
fa583f5f 492 }
f5831eea 493 echo "<a title=\"$strmoveup\" href=\"" .
8afba50b 494 $pageurl->out(true, array('up' => $question->id, 'sesskey'=>sesskey())) . "\"><img
b5d0cafc 495 src=\"" . $OUTPUT->pix_url('t/up') . "\" class=\"iconsmall
fa583f5f 496 $upbuttonclass\" alt=\"$strmoveup\" /></a>";
ee1fb969 497 }
ee1fb969 498
fa583f5f 499 }
4299df1d 500 if ($count < $lastindex - 1) {
f5831eea 501 if (!$hasattempts) {
502 echo "<a title=\"$strmovedown\" href=\"" .
8afba50b 503 $pageurl->out(true, array('down' => $question->id, 'sesskey'=>sesskey())) . "\"><img
b5d0cafc 504 src=\"" . $OUTPUT->pix_url('t/down') . "\" class=\"iconsmall\"" .
fa583f5f 505 " alt=\"$strmovedown\" /></a>";
ee1fb969 506 }
ee1fb969 507 }
4299df1d 508 if ($allowdelete && question_has_capability_on($question, 'use', $question->category)) {
509 // remove from quiz, not question delete.
510 if (!$hasattempts) {
f5831eea 511 echo "<a title=\"$strremove\" href=\"" .
8afba50b 512 $pageurl->out(true, array('remove' => $question->id, 'sesskey'=>sesskey())) . "\">
b5d0cafc 513 <img src=\"" . $OUTPUT->pix_url('t/delete') . "\" " .
fa583f5f 514 "class=\"iconsmall\" alt=\"$strremove\" /></a>";
515 }
516 }
517 ?>
518 </div><?php
519 if ($question->qtype != 'description' && !$reordertool) {
520 ?>
521<div class="points">
522<form method="post" action="edit.php"><div>
fa583f5f 523 <fieldset class="invisiblefieldset" style="display: block;">
3e10e429 524 <label for="<?php echo "inputq$question->id" ?>"><?php echo $strgrade; ?></label>:<br />
973d2660 525 <input type="hidden" name="sesskey" value="<?php echo sesskey() ?>" />
6ea66ff3 526 <?php echo html_writer::input_hidden_params($pageurl); ?>
fa583f5f 527 <input type="hidden" name="savechanges" value="save" />
528 <?php
3e10e429 529 echo '<input type="text" name="g' . $question->id . '" id="inputq' . $question->id .
530 '" size="' . ($quiz->decimalpoints + 2) . '" value="' . (0 + $quiz->grades[$qnum]) .
f5831eea 531 '" tabindex="' . ($lastindex + $qno) . '" />';
fa583f5f 532 ?>
3fd9edf0 533 <input type="submit" class="pointssubmitbutton" value="<?php echo $strsave; ?>" />
fa583f5f 534 </fieldset>
2a874d65 535<?php if ($question->qtype == 'random') {
f5831eea 536 echo '<a href="' . $questionurl->out() . '" class="configurerandomquestion">' . get_string("configurerandomquestion", "quiz") . '</a>';
3814fb96 537}
f4b879dd 538
3814fb96 539?>
fa583f5f 540</div>
541</form>
542
543 </div>
544<?php
f5831eea 545 } else if ($reordertool) {
fa583f5f 546 if ($qnum) {
547 ?>
548<div class="qorder">
549 <?php
3e10e429 550 echo '<input type="text" name="o' . $question->id . '" size="2" value="' .
f5831eea 551 (10*$count + 10) .
552 '" tabindex="' . ($lastindex + $qno) .
3e10e429 553 '" />';
fa583f5f 554 ?>
555<!-- <input type="submit" class="pointssubmitbutton" value="<?php
556 echo $strsave; ?>" /> -->
557</div>
558<?php
559 }
560 }
561?>
562 <div class="questioncontentcontainer">
f5831eea 563<?php
2a874d65 564 if ($question->qtype == 'random') { // it is a random question
565 if (!$reordertool) {
566 quiz_print_randomquestion($question, $pageurl, $quiz, $quiz_qbanktool);
567 } else {
568 quiz_print_randomquestion_reordertool($question, $pageurl, $quiz);
fa583f5f 569 }
2a874d65 570 } else { // it is a single question
571 if (!$reordertool) {
572 quiz_print_singlequestion($question, $returnurl, $quiz);
573 } else {
574 quiz_print_singlequestion_reordertool($question, $returnurl, $quiz);
fa583f5f 575 }
576 }
577 ?>
578 </div>
579 </div>
580 </div>
581</div>
582
583 <?php
584 /* Display question end */
585 $count++;
586 $sumgrade += $quiz->grades[$qnum];
587
588 }
ee1fb969 589 }
fa583f5f 590 //a page break: end the existing page.
f5831eea 591 if ($qnum == 0) {
592 if ($pageopen) {
3e10e429 593 if (!$reordertool && !($quiz->shufflequestions && $i < $questiontotalcount - 1)) {
fa583f5f 594 quiz_print_pagecontrols($quiz, $pageurl, $pagecount,
595 $hasattempts);
3e10e429 596 } else if ($i < $questiontotalcount - 1) {
fa583f5f 597 //do not include the last page break for reordering
598 //to avoid creating a new extra page in the end
3e10e429 599 echo '<input type="hidden" name="opg' . $pagecount . '" size="2" value="' .
f5831eea 600 (10*$count + 10) . '" />';
fa583f5f 601 }
602 echo "</div></div>";
603
3e10e429 604 if (!$reordertool && !$quiz->shufflequestions) {
39e37019 605 echo $OUTPUT->container_start('addpage');
eb788065 606 $url = new moodle_url($pageurl->out_omit_querystring(), array('cmid' => $quiz->cmid, 'courseid' => $quiz->course, 'addpage' => $count, 'sesskey' => sesskey()));
54aa3239 607 echo $OUTPUT->single_button($url, get_string('addpagehere', 'quiz'), 'get', array('disabled'=>$hasattempts));
39e37019 608 echo $OUTPUT->container_end();
fa583f5f 609 }
f5831eea 610 $pageopen = false;
fa583f5f 611 $count++;
612 }
ee1fb969 613 }
ee1fb969 614
fa583f5f 615 }
f5831eea 616 if ($reordertool) {
fa583f5f 617 echo $reordercontrolsbottom;
618 echo '</div></form>';
619 }
620
fa583f5f 621 return $sumgrade;
622}
623
624/**
625 * Print all the controls for adding questions directly into the
626 * specific page in the edit tab of edit.php
627 *
628 * @param unknown_type $quiz
629 * @param unknown_type $pageurl
630 * @param unknown_type $page
631 * @param unknown_type $hasattempts
632 */
f5831eea 633function quiz_print_pagecontrols($quiz, $pageurl, $page, $hasattempts) {
825116fb 634 global $CFG, $OUTPUT;
3e10e429 635 static $randombuttoncount = 0;
636 $randombuttoncount++;
fa583f5f 637 echo '<div class="pagecontrols">';
cd120b23 638
639 // Get the current context
fa583f5f 640 $thiscontext = get_context_instance(CONTEXT_COURSE, $quiz->course);
641 $contexts = new question_edit_contexts($thiscontext);
cd120b23 642
643 // Get the default category.
fa583f5f 644 $defaultcategory = question_make_default_categories($contexts->all());
cd120b23 645
646 // Create the url the question page will return to
eb788065 647 $returnurl_addtoquiz = new moodle_url($pageurl->out_omit_querystring(), array('addonpage' => $page));
cd120b23 648
649 // Print a button linking to the choose question type page.
47ce714b 650 $newquestionparams = array('returnurl' => $returnurl_addtoquiz->out(),
cd120b23 651 'cmid' => $quiz->cmid, 'appendqnumstring' => 'addquestion');
652 create_new_question_button($defaultcategory->id, $newquestionparams, get_string('addaquestion', 'quiz'),
653 get_string('createquestionandadd', 'quiz'), $hasattempts);
654
fa583f5f 655 if ($hasattempts) {
656 $disabled = 'disabled="disabled"';
657 } else {
658 $disabled = '';
659 }
fa583f5f 660 ?>
fa583f5f 661 <div class="singlebutton">
662 <form class="randomquestionform" action="<?php echo $CFG->wwwroot; ?>/mod/quiz/addrandom.php" method="get">
663 <div>
664 <input type="hidden" class="addonpage_formelement" name="addonpage_form" value="<?php echo $page; ?>" />
665 <input type="hidden" name="cmid" value="<?php echo $quiz->cmid; ?>" />
666 <input type="hidden" name="courseid" value="<?php echo $quiz->course; ?>" />
eb788065 667 <input type="hidden" name="returnurl" value="<?php echo urlencode($pageurl->out_omit_querystring()); ?>" />
3e10e429 668 <input type="submit" id="addrandomdialoglaunch_<?php echo $randombuttoncount; ?>" value="<?php echo get_string('addarandomquestion', 'quiz'); ?>" <?php echo " $disabled"; ?> />
fa583f5f 669 </div>
670 </form>
671 </div>
4bcc5118 672 <?php echo $OUTPUT->help_icon('random', get_string('random', 'quiz'), 'quiz'); ?>
fa583f5f 673 <?php
674 echo "\n</div>";
675}
676/**
677 * Process submitted form data to create a new category for a random question
678 * This is used by edit.php and addrandom.php
679 * cmid
680 *
681 * @param object $qcobject
c7c7f25a 682 * @return object an object with properties newrandomcategory and addonpage if operation successful.
683 * if operation failed, returns false.
fa583f5f 684 */
f5831eea 685function quiz_process_randomquestion_formdata(&$qcobject) {
686 global $CFG, $DB;
687 $newrandomcategory = 0;
688 $addonpage = 0;
689 $newquestioninfo = false;
690 if ($qcobject->catform_rand->is_cancelled()) {
3e10e429 691 return 'cancelled';
692 } else if ($catformdata = $qcobject->catform_rand->get_data()) {
f5831eea 693 $newquestioninfo = new stdClass;
694 $addonpage = $catformdata->addonpage;
695 $newquestioninfo->addonpage = $catformdata->addonpage;
fa583f5f 696 if (!$catformdata->id) {//new category
f5831eea 697 $newrandomcategory = $qcobject->add_category($catformdata->parent,
698 $catformdata->name, $catformdata->info, true);
699 if (!is_null($newrandomcategory)) {
700 $newquestioninfo->newrandomcategory = $newrandomcategory;
fa583f5f 701 if (! $newcategory = $DB->get_record('question_categories',
f5831eea 702 array('id' => $newrandomcategory))) {
703 $newquestioninfo->newrandomcategory = false;
fa583f5f 704 }
f5831eea 705 } else {
706 $newquestioninfo->newrandomcategory = false;
fa583f5f 707 }
ee1fb969 708 } else {
f5831eea 709 $newquestioninfo->newrandomcategory = false;
ee1fb969 710 }
fa583f5f 711 }
3e10e429 712 return $newquestioninfo;
fa583f5f 713}
714
fa583f5f 715/**
716 * Print a given single question in quiz for the edit tab of edit.php.
717 * Meant to be used from quiz_print_question_list()
f5831eea 718 *
414d5bfb 719 * @param object $question A question object from the database questions table
2a874d65 720 * @param object $returnurl The url to get back to this page, for example after editing.
414d5bfb 721 * @param object $quiz The quiz in the context of which the question is being displayed
fa583f5f 722 */
f5831eea 723function quiz_print_singlequestion($question, $returnurl, $quiz) {
2a874d65 724 global $QTYPES;
725 echo '<div class="singlequestion">';
726 echo quiz_question_edit_button($quiz->cmid, $question, $returnurl, quiz_question_tostring($question) . ' ');
727 echo '<span class="questiontype">';
728 $namestr = $QTYPES[$question->qtype]->local_name();
729 print_question_icon($question);
730 echo " $namestr</span>";
731 echo '<span class="questionpreview">' . quiz_question_preview_button($quiz, $question, true) . '</span>';
732 echo "</div>\n";
fa583f5f 733}
734/**
735 * Print a given random question in quiz for the edit tab of edit.php.
736 * Meant to be used from quiz_print_question_list()
f5831eea 737 *
414d5bfb 738 * @param object $question A question object from the database questions table
739 * @param object $questionurl The url of the question editing page as a moodle_url object
740 * @param object $quiz The quiz in the context of which the question is being displayed
f5831eea 741 * @param boolean $quiz_qbanktool Indicate to this function if the question bank window open
fa583f5f 742 */
f5831eea 743function quiz_print_randomquestion(&$question, &$pageurl, &$quiz, $quiz_qbanktool) {
92e01ab7 744 global $DB, $QTYPES, $OUTPUT;
fa583f5f 745 echo '<div class="quiz_randomquestion">';
746
fa583f5f 747 if (!$category = $DB->get_record('question_categories', array('id' => $question->category))) {
825116fb 748 echo $OUTPUT->notification('Random question category not found!');
fa583f5f 749 return;
750 }
751
752 echo '<div class="randomquestionfromcategory">';
753 print_question_icon($question);
3cac440b 754 print_random_option_icon($question);
8e84d978 755 echo ' ' . get_string('randomfromcategory', 'quiz') . '</div>';
fa583f5f 756
8333ad82 757 $a = new stdClass;
92e01ab7 758 $a->arrow = $OUTPUT->rarrow();
2a874d65 759 $strshowcategorycontents = get_string('showcategorycontents', 'quiz', $a);
f4b879dd 760
b9bc2019 761 $openqbankurl = $pageurl->out(true, array('qbanktool' => 1,
2a874d65 762 'cat' => $category->id . ',' . $category->contextid));
763 $linkcategorycontents = ' <a href="' . $openqbankurl . '">' . $strshowcategorycontents . '</a>';
fa583f5f 764
2a874d65 765 echo '<div class="randomquestioncategory">';
766 echo '<a href="' . $openqbankurl . '" title="' . $strshowcategorycontents . '">' . $category->name . '</a>';
767 echo '<span class="questionpreview">' . quiz_question_preview_button($quiz, $question, true) . '</span>';
768 echo '</div>';
fa583f5f 769
2a874d65 770 $questionids = $QTYPES['random']->get_usable_questions_from_category(
771 $category->id, $question->questiontext == '1', '0');
772 $questioncount = count($questionids);
fa583f5f 773
774 echo '<div class="randomquestionqlist">';
2a874d65 775 if ($questioncount == 0) {
776 // No questions in category, give an error plus instructions
fa583f5f 777 echo '<span class="error">';
2a874d65 778 print_string('noquestionsnotinuse', 'quiz');
9cdcf826 779 echo '</span>';
fa583f5f 780 echo '<br />';
9cdcf826 781
2a874d65 782 // Embed the link into the string with instructions
9cdcf826 783 $a = new stdClass;
784 $a->catname = '<strong>' . $category->name . '</strong>';
2a874d65 785 $a->link = $linkcategorycontents;
f5831eea 786 echo get_string('addnewquestionsqbank', 'quiz', $a);
537daa79 787
2a874d65 788 } else {
789 // Category has questions
f4b879dd 790
2a874d65 791 // Get a sample from the database,
792 $toshow = array_slice($questionids, 0, NUM_QS_TO_SHOW_IN_RANDOM);
793 $questionidstoshow = array();
794 foreach ($toshow as $a) {
795 $questionidstoshow[] = $a->id;
796 }
797 $questionstoshow = $DB->get_records_list('question', 'id', $questionidstoshow,
5bbdaed2 798 '', 'id,qtype,name,questiontext,questiontextformat');
9cdcf826 799
2a874d65 800 // list them,
801 echo '<ul>';
802 foreach ($questionstoshow as $question) {
803 echo '<li>' . quiz_question_tostring($question, true) . '</li>';
804 }
f4b879dd 805
2a874d65 806 // and then display the total number.
807 echo '<li class="totalquestionsinrandomqcategory">';
808 if ($questioncount > NUM_QS_TO_SHOW_IN_RANDOM) {
809 echo '... ';
810 }
811 print_string('totalquestionsinrandomqcategory', 'quiz', $questioncount);
812 echo ' ' . $linkcategorycontents;
813 echo '</li>';
814 echo '</ul>';
ee1fb969 815 }
816
2a874d65 817 echo '</div>';
fa583f5f 818 echo '<div class="randomquestioncategorycount">';
2a874d65 819 echo '</div>';
820 echo '</div>';
ee1fb969 821
fa583f5f 822}
ee1fb969 823
fa583f5f 824/**
825 * Print a given single question in quiz for the reordertool tab of edit.php.
826 * Meant to be used from quiz_print_question_list()
f5831eea 827 *
414d5bfb 828 * @param object $question A question object from the database questions table
829 * @param object $questionurl The url of the question editing page as a moodle_url object
830 * @param object $quiz The quiz in the context of which the question is being displayed
fa583f5f 831 */
f5831eea 832function quiz_print_singlequestion_reordertool($question, $returnurl, $quiz) {
2a874d65 833 echo '<div class="singlequestion">';
834 echo '<label for="s' . $question->id . '">';
835 print_question_icon($question);
836 echo ' ' . quiz_question_tostring($question);
837 echo '</label>';
838 echo '<span class="questionpreview">' .
839 quiz_question_action_icons($quiz, $quiz->cmid, $question, $returnurl) . '</span>';
840 echo "</div>\n";
fa583f5f 841}
3cac440b 842
fa583f5f 843/**
844 * Print a given random question in quiz for the reordertool tab of edit.php.
845 * Meant to be used from quiz_print_question_list()
f5831eea 846 *
414d5bfb 847 * @param object $question A question object from the database questions table
848 * @param object $questionurl The url of the question editing page as a moodle_url object
849 * @param object $quiz The quiz in the context of which the question is being displayed
fa583f5f 850 */
f5831eea 851function quiz_print_randomquestion_reordertool(&$question, &$pageurl, &$quiz) {
825116fb 852 global $DB, $QTYPES, $OUTPUT;
fa583f5f 853
2a874d65 854 // Load the category, and the number of available questions in it.
fa583f5f 855 if (!$category = $DB->get_record('question_categories', array('id' => $question->category))) {
825116fb 856 echo $OUTPUT->notification('Random question category not found!');
fa583f5f 857 return;
858 }
2a874d65 859 $questioncount = count($QTYPES['random']->get_usable_questions_from_category(
860 $category->id, $question->questiontext == '1', '0'));
fa583f5f 861
f5831eea 862 $reordercheckboxlabel = '<label for="s' . $question->id . '">';
2a874d65 863 $reordercheckboxlabelclose = '</label>';
864
865 echo '<div class="quiz_randomquestion">';
866 echo '<div class="randomquestionfromcategory">';
fa583f5f 867 echo $reordercheckboxlabel;
868 print_question_icon($question);
3cac440b 869 print_random_option_icon($question);
fa583f5f 870
2a874d65 871 if ($questioncount == 0) {
fa583f5f 872 echo '<span class="error">';
2a874d65 873 print_string('empty', 'quiz');
fa583f5f 874 echo '</span> ';
875 }
876
2a874d65 877 print_string('random', 'quiz');
fa583f5f 878 echo ": $reordercheckboxlabelclose</div>";
879
880 echo '<div class="randomquestioncategory">';
2a874d65 881 echo $reordercheckboxlabel . $category->name . $reordercheckboxlabelclose;
3814fb96 882 echo '<span class="questionpreview">';
2a874d65 883 echo quiz_question_preview_button($quiz, $question, false);
fa583f5f 884 echo '</span>';
885 echo "</div>";
886
fa583f5f 887 echo '<div class="randomquestioncategorycount">';
2a874d65 888 echo '</div>';
889 echo '</div>';
fa583f5f 890
891}
3cac440b 892
893/**
894 * Print an icon to indicate the 'include subcategories' state of a random question.
895 * @param $question the random question.
896 */
897function print_random_option_icon($question) {
5d3b9994 898 global $OUTPUT;
3cac440b 899 if (!empty($question->questiontext)) {
900 $icon = 'withsubcat';
901 $tooltip = get_string('randomwithsubcat', 'quiz');
902 } else {
903 $icon = 'nosubcat';
904 $tooltip = get_string('randomnosubcat', 'quiz');
905 }
b5d0cafc 906 echo '<img src="' . $OUTPUT->pix_url('i/' . $icon) . '" alt="' .
8e84d978 907 $tooltip . '" title="' . $tooltip . '" class="uihint" />';
f5831eea 908
3cac440b 909}
910
fa583f5f 911/**
912 * Creates a textual representation of a question for display.
f5831eea 913 *
414d5bfb 914 * @param object $question A question object from the database questions table
915 * @param boolean $showicon If true, show the question's icon with the question. False by default.
f5831eea 916 * @param boolean $showquestiontext If true (default), show question text after question name.
414d5bfb 917 * If false, show only question name.
f5831eea 918 * @param boolean $return If true (default), return the output. If false, print it.
fa583f5f 919 */
414d5bfb 920
f5831eea 921function quiz_question_tostring(&$question, $showicon = false, $showquestiontext = true, $return = true) {
fa583f5f 922 global $COURSE;
f5831eea 923 $result = '';
924 $result .= '<span class="questionname">';
925 if ($showicon) {
926 $result .= print_question_icon($question, true);
fa583f5f 927 echo " ";
96241873 928 }
f5831eea 929 $result .= shorten_text(format_string($question->name), 200) . '</span>';
930 if ($showquestiontext) {
fa583f5f 931 $formatoptions = new stdClass;
932 $formatoptions->noclean = true;
933 $formatoptions->para = false;
f5831eea 934 $questiontext = strip_tags(format_text($question->questiontext,
fa583f5f 935 $question->questiontextformat,
936 $formatoptions, $COURSE->id));
f5831eea 937 $questiontext = shorten_text($questiontext, 200);
938 $result .= '<span class="questiontext">';
939 if (!empty($questiontext)) {
940 $result .= $questiontext;
941 } else {
942 $result .= '<span class="error">';
943 $result .= get_string('questiontextisempty', 'quiz');
944 $result .= '</span>';
fa583f5f 945 }
f5831eea 946 $result .= '</span>';
fa583f5f 947 }
f5831eea 948 if ($return) {
fa583f5f 949 return $result;
f5831eea 950 } else {
fa583f5f 951 echo $result;
952 }
953}
96241873 954
971c6fca 955/**
956 * A column type for the add this question to the quiz.
957 */
958class question_bank_add_to_quiz_action_column extends question_bank_action_column_base {
959 protected $stradd;
960
961 public function init() {
962 parent::init();
963 $this->stradd = get_string('addtoquiz', 'quiz');
964 }
965
966 public function get_name() {
967 return 'addtoquizaction';
968 }
969
970 protected function display_content($question, $rowclasses) {
971 // for RTL languages: switch right and left arrows
972 if (right_to_left()) {
2a874d65 973 $movearrow = 't/removeright.gif';
971c6fca 974 } else {
2a874d65 975 $movearrow = 't/moveleft.gif';
971c6fca 976 }
977 $this->print_icon($movearrow, $this->stradd, $this->qbank->add_to_quiz_url($question->id));
978 }
979
980 public function get_required_fields() {
981 return array('q.id');
982 }
983}
984
985/**
986 * A column type for the name followed by the start of the question text.
987 */
988class question_bank_question_name_text_column extends question_bank_question_name_column {
989 public function get_name() {
990 return 'questionnametext';
991 }
992
993 protected function display_content($question, $rowclasses) {
994 echo '<div>';
995 $labelfor = $this->label_for($question);
996 if ($labelfor) {
997 echo '<label for="' . $labelfor . '">';
998 }
999 echo quiz_question_tostring($question, false, true, true);
1000 if ($labelfor) {
1001 echo '</label>';
1002 }
1003 echo '</div>';
1004 }
1005
1006 public function get_required_fields() {
1007 $fields = parent::get_required_fields();
1008 $fields[] = 'q.questiontext';
e4d1d5e0 1009 $fields[] = 'q.questiontextformat';
971c6fca 1010 return $fields;
1011 }
1012}
1013
f4b879dd 1014/**
1015 * Subclass to customise the view of the question bank for the quiz editing screen.
1016 */
1017class quiz_question_bank_view extends question_bank_view {
1018 protected $quizhasattempts = false;
96241873 1019
cd120b23 1020 protected function known_field_types() {
1021 $types = parent::known_field_types();
971c6fca 1022 $types[] = new question_bank_add_to_quiz_action_column($this);
1023 $types[] = new question_bank_question_name_text_column($this);
1024 return $types;
1025 }
1026
1027 protected function wanted_columns() {
1028 return array('addtoquizaction', 'checkbox', 'qtype', 'questionnametext', 'editaction', 'previewaction');
f4b879dd 1029 }
fa583f5f 1030
f4b879dd 1031 /**
1032 * Let the question bank display know whether the quiz has been attempted,
1033 * hence whether some bits of UI, like the add this question to the quiz icon,
1034 * should be displayed.
1035 * @param boolean $quizhasattempts whether the quiz has attempts.
1036 */
1037 public function set_quiz_has_attempts($quizhasattempts) {
1038 $this->quizhasattempts = $quizhasattempts;
971c6fca 1039 if ($quizhasattempts && isset($this->visiblecolumns['addtoquizaction'])) {
1040 unset($this->visiblecolumns['addtoquizaction']);
1041 }
1042 }
1043
e4d1d5e0 1044 public function preview_question_url($questionid) {
1045 global $CFG;
1046 return $CFG->wwwroot . '/question/preview.php?id=' . $questionid . $this->quizorcourseid;
1047 }
1048
971c6fca 1049 public function add_to_quiz_url($questionid) {
1050 global $CFG;
8afba50b
PS
1051 $params = $this->baseurl->params();
1052 $params['addquestion'] = $questionid;
1053 $params['sesskey'] = sesskey();
1054 return new moodle_url('/mod/quiz/edit.php', $params);
f4b879dd 1055 }
fa583f5f 1056
5bd22790 1057 public function display($tabname, $page, $perpage, $sortorder,
f5831eea 1058 $sortorderdecoded, $cat, $recurse, $showhidden, $showquestiontext) {
3b1d5cc4 1059 global $OUTPUT;
5bd22790 1060 if ($this->process_actions_needing_ui()) {
5b5e5ab2 1061 return;
1062 }
f4b879dd 1063
971c6fca 1064 // Display the current category.
1065 if (!$category = $this->get_current_category($cat)) {
5b5e5ab2 1066 return;
fa583f5f 1067 }
971c6fca 1068 $this->print_category_info($category);
5b5e5ab2 1069
3b1d5cc4 1070 echo $OUTPUT->box_start('generalbox questionbank');
5b5e5ab2 1071
5bd22790 1072 $this->display_category_form($this->contexts->having_one_edit_tab_cap($tabname),
971c6fca 1073 $this->baseurl, $cat);
5b5e5ab2 1074
1075 // continues with list of questions
5bd22790 1076 $this->display_question_list($this->contexts->having_one_edit_tab_cap($tabname), $this->baseurl, $cat, $this->cm,
5b5e5ab2 1077 $recurse, $page, $perpage, $showhidden, $sortorder, $sortorderdecoded, $showquestiontext,
5bd22790 1078 $this->contexts->having_cap('moodle/question:add'));
5b5e5ab2 1079
971c6fca 1080 $this->display_options($recurse, $showhidden, $showquestiontext);
3b1d5cc4 1081 echo $OUTPUT->box_end();
f4b879dd 1082 }
5b5e5ab2 1083
971c6fca 1084 protected function print_choose_category_message($categoryandcontext) {
3b1d5cc4 1085 global $OUTPUT;
1086 echo $OUTPUT->box_start('generalbox questionbank');
971c6fca 1087 $this->display_category_form($this->contexts->having_one_edit_tab_cap('edit'), $this->baseurl, $categoryandcontext);
1088 echo "<p style=\"text-align:center;\"><b>";
f5831eea 1089 print_string('selectcategoryabove', 'quiz');
971c6fca 1090 echo "</b></p>";
3b1d5cc4 1091 echo $OUTPUT->box_end();
5bd22790 1092 }
1093
971c6fca 1094 protected function print_category_info($category) {
1095 $formatoptions = new stdClass;
1096 $formatoptions->noclean = true;
1097 $strcategory = get_string('category', 'quiz');
f5831eea 1098 echo '<div class="categoryinfo"><div class="categorynamefieldcontainer">' .
971c6fca 1099 $strcategory;
1100 echo ': <span class="categorynamefield">';
1101 echo shorten_text(strip_tags(format_text($category->name, FORMAT_MOODLE,
f5831eea 1102 $formatoptions, $this->course->id)), 60);
971c6fca 1103 echo '</span></div><div class="categoryinfofieldcontainer"><span class="categoryinfofield">';
1104 echo shorten_text(strip_tags(format_text($category->info, FORMAT_MOODLE,
f5831eea 1105 $formatoptions, $this->course->id)), 200);
971c6fca 1106 echo '</span></div></div>';
5bd22790 1107 }
1108
971c6fca 1109 protected function display_options($recurse = 1, $showhidden = false, $showquestiontext = false) {
1110 echo '<form method="get" action="edit.php" id="displayoptions">';
1111 echo "<fieldset class='invisiblefieldset'>";
6ea66ff3 1112 echo html_writer::input_hidden_params($this->baseurl, array('recurse', 'showhidden', 'showquestiontext'));
b7a9dc51 1113 $this->display_category_form_checkbox('recurse', get_string('recurse', 'quiz'));
1114 $this->display_category_form_checkbox('showhidden', get_string('showhidden', 'quiz'));
f5831eea 1115 echo '<noscript><div class="centerpara"><input type="submit" value="'. get_string('go') . '" />';
971c6fca 1116 echo '</div></noscript></fieldset></form>';
5bd22790 1117 }
8bccba71 1118}
f4b879dd 1119
8bccba71 1120/**
1121 * Prints the form for setting a quiz' overall grade
f5831eea 1122 *
414d5bfb 1123 * @param object $quiz The quiz object of the quiz in question
f5831eea 1124 * @param object $pageurl The url of the current page with the parameters required
414d5bfb 1125 * for links returning to the current page, as a moodle_url object
1126 * @param integer $tabindex The tabindex to start from for the form elements created
1127 * @return integer The tabindex from which the calling page can continue, that is,
1128 * the last value used +1.
8bccba71 1129 */
f5831eea 1130function quiz_print_grading_form($quiz, $pageurl, $tabindex) {
825116fb 1131 global $USER, $OUTPUT;
f5831eea 1132 $strsave = get_string('save', 'quiz');
8bccba71 1133 echo "<form method=\"post\" action=\"edit.php\"><div>";
1134 echo '<fieldset class="invisiblefieldset" style="display: block;">';
f5831eea 1135 echo "<input type=\"hidden\" name=\"sesskey\" value=\"" . sesskey() . "\" />";
6ea66ff3 1136 echo html_writer::input_hidden_params($pageurl);
f5831eea 1137 $a = '<input type="text" id="inputmaxgrade" name="maxgrade" size="' . ($quiz->decimalpoints + 2) . '" tabindex="' . $tabindex
1138 . '" value="' . quiz_format_grade($quiz, $quiz->grade) . '" />';
1139 echo '<label for="inputmaxgrade">' . get_string('maximumgradex', '', $a) . "</label>";
1140 echo '<input type="hidden" name="savechanges" value="save" />';
1141 echo '<input type="submit" value="' . $strsave . '" />';
4bcc5118 1142 echo $OUTPUT->help_icon('maxgrade', get_string('maximumgrade'), 'quiz');
8bccba71 1143 echo '</fieldset>';
1144 echo "</div></form>\n";
f5831eea 1145 return $tabindex + 1;
8bccba71 1146}
f4b879dd 1147
8bccba71 1148/**
1149 * Print the status bar
1150 *
414d5bfb 1151 * @param object $quiz The quiz object of the quiz in question
8bccba71 1152 */
f5831eea 1153function quiz_print_status_bar($quiz) {
8bccba71 1154 global $CFG;
f5831eea 1155 $numberofquestions = quiz_number_of_questions_in_quiz($quiz->questions);
3e10e429 1156 ?><div class="statusbar"><span class="totalpoints">
4e6f553d 1157 <?php echo get_string('totalpointsx', 'quiz', quiz_format_grade($quiz, $quiz->sumgrades)) ?></span>
8bccba71 1158 | <span class="numberofquestions">
1159 <?php
f5831eea 1160 echo get_string('numquestionsx', 'quiz', $numberofquestions);
8bccba71 1161 ?></span>
8bccba71 1162 <?php
940b5fbb 1163
1164// Current status of the quiz, with open an close dates as a tool tip.
ad041fad 1165 $currentstatus = get_string('quizisopen', 'quiz');
e476804c 1166 $dates = array();
1167 $timenow = time();
e476804c 1168 if ($quiz->timeopen > 0) {
1169 if ($timenow > $quiz->timeopen) {
940b5fbb 1170 $dates[] = get_string('quizopenedon', 'quiz', userdate($quiz->timeopen));
e476804c 1171 } else {
940b5fbb 1172 $dates[] = get_string('quizwillopen', 'quiz', userdate($quiz->timeopen));
ad041fad 1173 print_string('quizisclosed', 'quiz');
e476804c 1174 }
1175 }
1176 if ($quiz->timeclose > 0) {
1177 if ($timenow > $quiz->timeclose) {
940b5fbb 1178 $dates[] = get_string('quizclosed', 'quiz', userdate($quiz->timeclose));
ad041fad 1179 print_string('quizisclosed', 'quiz');
e476804c 1180 } else {
940b5fbb 1181 $dates[] = get_string('quizcloseson', 'quiz', userdate($quiz->timeclose));
ad041fad 1182 $currentstatus = get_string('quizisopenwillclose', 'quiz', userdate($quiz->timeclose, get_string('strftimedatetimeshort', 'langconfig')));
e476804c 1183 }
1184 }
1185 if (empty($dates)) {
1186 $dates[] = get_string('alwaysavailable', 'quiz');
1187 }
ad041fad 1188 $dates = implode(', ', $dates);
1189 echo ' | <span class="quizopeningstatus" title="' . $dates . '">' . $currentstatus . '</span>';
940b5fbb 1190
8bccba71 1191 ?>
1192 </div>
1193 <?php
1194}
1195
3b1d5cc4 1196?>