blocks MDL-19010 Fixed a typo to make the title a string
[moodle.git] / mod / quiz / edit.php
1 <?php // $Id$
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 ///////////////////////////////////////////////////////////////////////////
26 /**
27  * Page to edit quizzes
28  *
29  * This page generally has two columns:
30  * The right column lists all available questions in a chosen category and
31  * allows them to be edited or more to be added. This column is only there if
32  * the quiz does not already have student attempts
33  * The left column lists all questions that have been added to the current quiz.
34  * The lecturer can add questions from the right hand list to the quiz or remove them
35  *
36  * The script also processes a number of actions:
37  * Actions affecting a quiz:
38  * up and down  Changes the order of questions and page breaks
39  * addquestion  Adds a single question to the quiz
40  * add          Adds several selected questions to the quiz
41  * addrandom    Adds a certain number of random questions to the quiz
42  * repaginate   Re-paginates the quiz
43  * delete       Removes a question from the quiz
44  * savechanges  Saves the order and grades for questions in the quiz
45  *
46  * @license http://www.gnu.org/copyleft/gpl.html GNU Public License
47  * @package quiz
48  *//** */
50 require_once('../../config.php');
51 require_once($CFG->dirroot . '/mod/quiz/editlib.php');
52 require_once($CFG->dirroot . '/question/category_class.php');
53 $PAGE->requires->yui_lib('container');
54 $PAGE->requires->yui_lib('dragdrop');
56 /**
57  * Callback function called from question_list() function
58  * (which is called from showbank())
59  * Displays button in form with checkboxes for each question.
60  */
61 function module_specific_buttons($cmid, $cmoptions) {
62     global $THEME;
63     if ($cmoptions->hasattempts) {
64         $disabled = 'disabled="disabled" ';
65     } else {
66         $disabled = '';
67     }
68     $straddtoquiz = get_string('addtoquiz', 'quiz');
69     $out = '<input type="submit" name="add" value="' . $THEME->larrow . ' ' . $straddtoquiz .
70             '" ' . $disabled . "/>\n";
71     return $out;
72 }
74 /**
75  * Callback function called from question_list() function
76  * (which is called from showbank())
77  */
78 function module_specific_controls($totalnumber, $recurse, $category, $cmid, $cmoptions) {
79     global $QTYPES;
80     $out = '';
81     $catcontext = get_context_instance_by_id($category->contextid);
82     if (has_capability('moodle/question:useall', $catcontext)) {
83         if ($cmoptions->hasattempts) {
84             $disabled = 'disabled="disabled"';
85         } else {
86             $disabled = '';
87         }
88         $randomusablequestions =
89                 $QTYPES['random']->get_usable_questions_from_category($category->id, $recurse, '0');
90         $maxrand = count($randomusablequestions);
91         if ($maxrand > 0) {
92             for ($i = 1; $i <= min(10, $maxrand); $i++) {
93                 $randomcount[$i] = $i;
94             }
95             for ($i = 20; $i <= min(100, $maxrand); $i += 10) {
96                 $randomcount[$i] = $i;
97             }
98             $straddtoquiz = get_string('addtoquiz', 'quiz');
99             $out = '<strong><label for="menurandomcount">'.get_string('addrandomfromcategory', 'quiz').
100                     '</label></strong><br />';
101             $out .= get_string('addrandom', 'quiz', choose_from_menu($randomcount,
102                     'randomcount', '1', '', '', '', true, $cmoptions->hasattempts));
103             $out .= '<input type="hidden" name="recurse" value="'.$recurse.'" />';
104             $out .= '<input type="hidden" name="categoryid" value="' . $category->id . '" />';
105             $out .= ' <input type="submit" name="addrandom" value="'.
106                     $straddtoquiz.'" '.$disabled.' />';
107             $out .= helpbutton('random', get_string('random', 'quiz'), 'quiz',
108                     true, false, '', true);
109         }
110     }
111     return $out;
114 list($thispageurl, $contexts, $cmid, $cm, $quiz, $pagevars) =
115         question_edit_setup('editq', true);
116 $PAGE->set_url('mod/quiz/edit.php', $thispageurl->params());
117 $PAGE->set_generaltype('form');
119 $defaultcategoryobj = question_make_default_categories($contexts->all());
120 $defaultcategoryid = $defaultcategoryobj->id;
121 $defaultcategorycontext = $defaultcategoryobj->contextid;
122 $defaultcategory = $defaultcategoryid . ',' . $defaultcategorycontext;
124 //these params are only passed from page request to request while we stay on
125 //this page otherwise they would go in question_edit_setup
126 $quiz_reordertool = optional_param('reordertool', 0, PARAM_BOOL);
127 $quiz_qbanktool = optional_param('qbanktool', -1, PARAM_BOOL);
128 if ($quiz_qbanktool > -1) {
129     $thispageurl->param('qbanktool', $quiz_qbanktool);
130     set_user_preference('quiz_qbanktool_open', $quiz_qbanktool);
131 } else {
132     $quiz_qbanktool = get_user_preferences('quiz_qbanktool_open', 0);
135 //will be set further down in the code
136 $quizhasattempts = quiz_has_attempts($quiz->id);
138 if ($quiz_reordertool != 0) {
139     $thispageurl->param('reordertool', $quiz_reordertool);
142 $strquizzes = get_string('modulenameplural', 'quiz');
143 $strquiz = get_string('modulename', 'quiz');
144 $streditingquestions = get_string('editquestions', 'quiz');
146 //this just does not work for at least finnish, where words are conjugated:
147 //$streditingquiz = get_string('editinga', 'moodle', $strquiz);
148 $streditingquiz = get_string('editingquiz', 'quiz');
149 $strorderingquiz = get_string('orderingquiz', 'quiz');
150 $pagetitle = $streditingquiz;
151 if ($quiz_reordertool) {
152     $pagetitle = $strorderingquiz;
154 // Get the course object and related bits.
155 $course = $DB->get_record('course', array('id' => $quiz->course));
156 if (!$course) {
157     print_error('invalidcourseid', 'error');
160 $questionbank = new quiz_question_bank_view($contexts, $thispageurl, $course, $cm);
161 $questionbank->set_quiz_has_attempts($quizhasattempts);
163 // Log this visit.
164 add_to_log($cm->course, 'quiz', 'editquestions',
165             "view.php?id=$cm->id", "$quiz->id", $cm->id);
167 // You need mod/quiz:manage in addition to question capabilities to access this page.
168 require_capability('mod/quiz:manage', $contexts->lowest());
170 if (empty($quiz->grades)) {  // Construct an array to hold all the grades.
171     $quiz->grades = quiz_get_all_question_grades($quiz);
174 // Process commands ============================================================
175 if ($quiz->shufflequestions) {
176     // Strip page breaks before processing actions, so that re-ordering works
177     // as expected when shuffle questions is on.
178     $quiz->questions = quiz_repaginate($quiz->questions, 0);
181 // Get the list of question ids had their check-boxes ticked.
182 $selectedquestionids = array();
183 $params = (array) data_submitted();
184 foreach ($params as $key => $value) {
185     if (preg_match('!^s([0-9]+)$!', $key, $matches)) {
186         $selectedquestionids[] = $matches[1];
187     }
190 if (($up = optional_param('up', false, PARAM_INT)) && confirm_sesskey()) {
191     $quiz->questions = quiz_move_question_up($quiz->questions, $up);
192     quiz_save_new_layout($quiz);
193     redirect($thispageurl->out());
196 if (($down = optional_param('down', false, PARAM_INT)) && confirm_sesskey()) {
197     $quiz->questions = quiz_move_question_down($quiz->questions, $down);
198     quiz_save_new_layout($quiz);
199     redirect($thispageurl->out());
202 if (optional_param('repaginate', false, PARAM_BOOL) && confirm_sesskey()) {
203     // Re-paginate the quiz
204     $questionsperpage = optional_param('questionsperpage', $quiz->questionsperpage, PARAM_INT);
205     $quiz->questions = quiz_repaginate($quiz->questions, $questionsperpage );
206     quiz_save_new_layout($quiz);
209 if (($addquestion = optional_param('addquestion', 0, PARAM_INT)) && confirm_sesskey()) {
210 /// Add a single question to the current quiz
211     $addonpage = optional_param('addonpage', 0, PARAM_INT);
212     quiz_add_quiz_question($addquestion, $quiz, $addonpage);
213     quiz_update_sumgrades($quiz);
214     quiz_delete_previews($quiz);
215     redirect($thispageurl->out());
218 if (optional_param('add', false, PARAM_BOOL) && confirm_sesskey()) {
219 /// Add selected questions to the current quiz
220     $rawdata = (array) data_submitted();
221     foreach ($rawdata as $key => $value) {    // Parse input for question ids
222         if (preg_match('!^q([0-9]+)$!', $key, $matches)) {
223             $key = $matches[1];
224             quiz_add_quiz_question($key, $quiz);
225         }
226     }
227     quiz_update_sumgrades($quiz);
228     quiz_delete_previews($quiz);
229     redirect($thispageurl->out());
232 $qcobject = new question_category_object($pagevars['cpage'], $thispageurl,
233         $contexts->having_one_edit_tab_cap('categories'), $defaultcategoryid,
234         $defaultcategory, null, $contexts->having_cap('moodle/question:add'));
236 $newrandomcategory = false;
237 $newquestioninfo = quiz_process_randomquestion_formdata($qcobject);
238 if ($newquestioninfo && $newquestioninfo != 'cancelled') {
239     $newrandomcategory = $newquestioninfo->newrandomcategory;
240     if (!$newrandomcategory) {
241         print_error('cannotcreatecategory');
242     } else {
243         add_to_log($quiz->course, 'quiz', 'addcategory',
244                 "view.php?id=$cm->id", $newrandomcategory, $cm->id);
245     }
248 if ((optional_param('addrandom', false, PARAM_BOOL) || $newrandomcategory) && confirm_sesskey()) {
250     /// Add random questions to the quiz
251     $recurse = optional_param('recurse', 0, PARAM_BOOL);
252     $addonpage = optional_param('addonpage', 0, PARAM_INT);
253     if ($newrandomcategory) {
254         $categoryid = $newrandomcategory;
255         $randomcount = optional_param('randomcount', 1, PARAM_INT);
256     } else {
257         $categoryid = required_param('categoryid', PARAM_INT);
258         $randomcount = required_param('randomcount', PARAM_INT);
259     }
260     // load category
261     $category = $DB->get_record('question_categories', array('id' => $categoryid));
262     if (!$category) {
263         print_error('invalidcategoryid', 'error');
264     }
265     $catcontext = get_context_instance_by_id($category->contextid);
266     require_capability('moodle/question:useall', $catcontext);
267     $category->name = $category->name;
268     // Find existing random questions in this category that are
269     // not used by any quiz.
270     if ($existingquestions = $DB->get_records_sql(
271             "SELECT q.id,q.qtype FROM {question} q
272             WHERE qtype = '" . RANDOM . "'
273                 AND category = ?
274                 AND " . $DB->sql_compare_text('questiontext') . " = ?
275                 AND NOT EXISTS (SELECT * FROM {quiz_question_instances} WHERE question = q.id)
276             ORDER BY id", array($category->id, $recurse))) {
277         // Take as many of these as needed.
278         while (($existingquestion = array_shift($existingquestions)) && $randomcount > 0) {
279             quiz_add_quiz_question($existingquestion->id, $quiz, $addonpage);
280             $randomcount--;
281         }
282     }
284     // If more are needed, create them.
285     if ($randomcount > 0) {
286         $form->questiontext = $recurse; // we use the questiontext field
287                 // to store the info on whether to include
288                 // questions in subcategories
289         $form->questiontextformat = 0;
290         $form->image = '';
291         $form->defaultgrade = 1;
292         $form->hidden = 1;
293         for ($i = 0; $i < $randomcount; $i++) {
294             $form->category = $category->id . ',' . $category->contextid;
295             $form->stamp = make_unique_id_code(); // Set the unique
296                     //code (not to be changed)
297             $question = new stdClass;
298             $question->qtype = RANDOM;
299             $question = $QTYPES[RANDOM]->save_question($question, $form,
300                     $course);
301             if(!isset($question->id)) {
302                 print_error('cannotinsertrandomquestion', 'quiz');
303             }
304             quiz_add_quiz_question($question->id, $quiz, $addonpage);
305         }
306     }
308     quiz_update_sumgrades($quiz);
309     quiz_delete_previews($quiz);
310     redirect($thispageurl->out());
313 if (optional_param('addnewpagesafterselected', null) && !empty($selectedquestionids) && confirm_sesskey()) {
314     foreach ($selectedquestionids as $questionid) {
315         $quiz->questions = quiz_add_page_break_after($quiz->questions, $questionid);
316     }
317     quiz_save_new_layout($quiz);
318     redirect($thispageurl->out());
321 $addpage = optional_param('addpage', false, PARAM_INT);
322 if ($addpage !== false && confirm_sesskey()) {
323     $quiz->questions = quiz_add_page_break_at($quiz->questions, $addpage);
324     quiz_save_new_layout($quiz);
325     redirect($thispageurl->out());
328 $deleteemptypage = optional_param('deleteemptypage', false, PARAM_INT);
329 if (($deleteemptypage !== false) && confirm_sesskey()) {
330     $quiz->questions = quiz_delete_empty_page($quiz->questions, $deleteemptypage);
331     quiz_save_new_layout($quiz);
332     redirect($thispageurl->out());
335 $remove = optional_param('remove', false, PARAM_INT);
336 if (($remove = optional_param('remove', false, PARAM_INT)) && confirm_sesskey()) {
337     quiz_remove_question($quiz, $remove);
338     quiz_update_sumgrades($quiz);
339     quiz_delete_previews($quiz);
340     redirect($thispageurl->out());
343 if (optional_param('quizdeleteselected', false, PARAM_BOOL) && !empty($selectedquestionids) && confirm_sesskey()) {
344     foreach ($selectedquestionids as $questionid) {
345         quiz_remove_question($quiz, $questionid);
346     }
347     quiz_update_sumgrades($quiz);
348     quiz_delete_previews($quiz);
349     redirect($thispageurl->out());
352 if (optional_param('savechanges', false, PARAM_BOOL) && confirm_sesskey()) {
353     $oldquestions = explode(',', $quiz->questions); // the questions in the old order
354     $questions = array(); // for questions in the new order
355     $rawdata = (array) data_submitted();
356     $moveonpagequestions = array();
357     $moveselectedonpage = optional_param('moveselectedonpagetop', 0, PARAM_INT);
358     if (!$moveselectedonpage) {
359         $moveselectedonpage = optional_param('moveselectedonpagebottom', 0, PARAM_INT);
360     }
362     foreach ($rawdata as $key => $value) {
363         if (preg_match('!^g([0-9]+)$!', $key, $matches)) {
364             /// Parse input for question -> grades
365             $questionid = $matches[1];
366             $quiz->grades[$questionid] = clean_param($value, PARAM_FLOAT);
367             quiz_update_question_instance($quiz->grades[$questionid], $questionid, $quiz->id);
368             quiz_delete_previews($quiz);
369             quiz_update_sumgrades($quiz);
371         } else if (preg_match('!^o(pg)?([0-9]+)$!', $key, $matches)) {
372             /// Parse input for ordering info
373             $questionid = $matches[2];
374             // Make sure two questions don't overwrite each other. If we get a second
375             // question with the same position, shift the second one along to the next gap.
376             $value = clean_param($value, PARAM_INTEGER);
377             while (array_key_exists($value, $questions)) {
378                 $value++;
379             }
380             if ($matches[1]) {
381                 // This is a page-break entry.
382                 $questions[$value] = 0;
383             } else {
384                 $questions[$value] = $questionid;
385             }
386         }
387     }
389     // If ordering info was given, reorder the questions
390     if ($questions) {
391         ksort($questions);
392         $questions[] = 0;
393         $quiz->questions = implode(',', $questions);
394         quiz_save_new_layout($quiz);
395         quiz_delete_previews($quiz);
396     }
398     //get a list of questions to move, later to be added in the appropriate
399     //place in the string
400     if ($moveselectedonpage) {
401         $questions = explode(',', $quiz->questions);
402         $newquestions = array();
403         //remove the questions from their original positions first
404         foreach ($questions as $questionid) {
405             if (!in_array($questionid, $selectedquestionids)) {
406                 $newquestions[] = $questionid;
407             }
408         }
409         $questions = $newquestions;
411         //move to the end of the selected page
412         $pagebreakpositions = array_keys($questions, 0);
413         $numpages = count($pagebreakpositions);
414         // Ensure the target page number is in range.
415         $moveselectedonpage = max(1, min($moveselectedonpage, $pagebreakpositions));
416         $moveselectedpos = $pagebreakpositions[$moveselectedonpage - 1];
417         array_splice($questions, $moveselectedpos, 0, $selectedquestionids);
418         $quiz->questions = implode(',', $questions);
419         quiz_save_new_layout($quiz);
420         quiz_delete_previews($quiz);
421     }
423     // If rescaling is required save the new maximum
424     $maxgrade = optional_param('maxgrade', -1, PARAM_FLOAT);
425     if ($maxgrade >= 0) {
426         quiz_set_grade($maxgrade, $quiz);
427     }
429     redirect($thispageurl->out());
432 $questionbank->process_actions($thispageurl, $cm);
434 // End of process commands =====================================================
436 // Print the header.
437 $questionbankmanagement = '<a href="'.$CFG->wwwroot.
438         '/question/edit.php?courseid='.$course->id.'">'.
439         get_string('questionbankmanagement', 'quiz').'</a> ';
440 $strupdatemodule = has_capability('moodle/course:manageactivities',
441         $contexts->lowest()) ?
442         update_module_button($cm->id, $course->id,
443         get_string('modulename', 'quiz')) :
444         "";
445 $navigation = build_navigation($pagetitle, $cm);
447 $PAGE->requires->skip_link_to('questionbank',  get_string('skipto', 'access', get_string('questionbank', 'question')));
448 $PAGE->requires->skip_link_to('quizcontentsblock',  get_string('skipto', 'access', get_string('questionsinthisquiz', 'quiz')));
450 print_header_simple($pagetitle, '', $navigation, '', '', true,
451         $questionbankmanagement.$strupdatemodule);
453 // Initialise the JavaScript.
454 $quizeditconfig = new stdClass;
455 $quizeditconfig->url = $thispageurl->out(false, array('qbanktool' => '0'));
456 $quizeditconfig->dialoglisteners = array();
457 $numberoflisteners = max(quiz_number_of_pages($quiz->questions), 1);
458 for ($pageiter = 1; $pageiter <= $numberoflisteners; $pageiter++) {
459     $quizeditconfig->dialoglisteners[] = 'addrandomdialoglaunch_' . $pageiter;
461 $PAGE->requires->data_for_js('quiz_edit_config', $quizeditconfig);
462 $PAGE->requires->js('mod/quiz/edit.js');
464 // Print the tabs.
465 $currenttab = 'edit';
466 $mode = 'editq';
467 if ($quiz_reordertool) {
468     $mode = 'reorder';
470 include('tabs.php');
472 if ($quiz_qbanktool) {
473     $bankclass = '';
474     $quizcontentsclass = '';
475 } else {
476     $bankclass = 'collapsed';
477     $quizcontentsclass = 'quizwhenbankcollapsed';
480 // Nasty short-term hack, becuase I am getting rid of separate print_side_block_start/end functions.
481 ob_start();
482 echo '<span id="questionbank"></span>';
483 echo '<div class="container">';
484 echo '<div id="module" class="module">';
485 echo '<div class="bd">';
486 $questionbank->display('editq',
487         $pagevars['qpage'],
488         $pagevars['qperpage'], $pagevars['qsortorder'],
489         $pagevars['qsortorderdecoded'],
490         $pagevars['cat'], $pagevars['recurse'], $pagevars['showhidden'],
491         $pagevars['showquestiontext']);
492 echo '</div>';
493 echo '</div>';
494 echo '</div>';
495 $qbhtml = ob_get_contents();
496 ob_end_clean();
498 print_side_block(get_string('questionbankcontents', 'quiz') .
499         ' <a href="' . $thispageurl->out(false, array('qbanktool' => '1')) .
500        '" id="showbankcmd">[' . get_string('show').
501        ']</a>
502        <a href="' . $thispageurl->out(false, array('qbanktool' => '0')) .
503        '" id="hidebankcmd">[' . get_string('hide').
504        ']</a>
505        ', $qbhtml, null, null, '', array('class' => 'questionbankwindow ' . $bankclass));
507 echo '<div class="quizcontents ' . $quizcontentsclass . '" id="quizcontentsblock">';
508 if ($quiz->shufflequestions) {
509     $repaginatingdisabledhtml = 'disabled="disabled"';
510     $repaginatingdisabled = true;
511     $quiz->questions = quiz_repaginate($quiz->questions, $quiz->questionsperpage);
512 } else {
513     $repaginatingdisabledhtml = '';
514     $repaginatingdisabled = false;
516 if ($quiz_reordertool) {
517     echo '<div class="repaginatecommand"><button id="repaginatecommand" '.$repaginatingdisabledhtml.'>'.
518             get_string('repaginatecommand', 'quiz').'...</button>';
519     echo '</div>';
521 print_heading($pagetitle.": ".$quiz->name, '', 2);
522 helpbutton('editconcepts', get_string('basicideasofquiz', 'quiz'), 'quiz',
523         true, get_string('basicideasofquiz', 'quiz'));
524 quiz_print_status_bar($quiz);
526 $tabindex = 0;
527 if (!$quiz_reordertool) {
528     quiz_print_grading_form($quiz, $thispageurl, $tabindex);
531 $notifystrings = array();
532 if ($quizhasattempts) {
533     $reviewlink = '<a href="' . $CFG->wwwroot . '/mod/quiz/report.php?mode=overview&amp;id=' . $cm->id . '">' .
534             quiz_num_attempt_summary($quiz, $cm) . '</a>';
535     $notifystrings[] = get_string('cannoteditafterattempts', 'quiz', $reviewlink);
537 if ($quiz->shufflequestions) {
538     $updateurl = new moodle_url("$CFG->wwwroot/course/mod.php",
539             array('return' => 'true', 'update' => $quiz->cmid, 'sesskey' => sesskey()));
540     $updatelink = '<a href="'.$updateurl->out().'">' . get_string('updatethis', '',
541             get_string('modulename', 'quiz')) . '</a>';
542     $notifystrings[] = get_string('shufflequestionsselected', 'quiz', $updatelink);
544 if (!empty($notifystrings)) {
545     print_box('<p>' . implode('</p><p>', $notifystrings) . '</p>', 'statusdisplay');
548 if ($quiz_reordertool) {
549     $perpage= array();
550     $perpage[0] = get_string('allinone', 'quiz');
551     for ($i = 1; $i <= 50; ++$i) {
552         $perpage[$i] = $i;
553     }
554     $gostring = get_string('go');
555     echo '<div id="repaginatedialog"><div class="hd">';
556     echo get_string('repaginatecommand', 'quiz');
557     echo '</div><div class="bd">';
558     echo '<form action="edit.php" method="post">';
559     echo '<fieldset class="invisiblefieldset">';
560     echo $thispageurl->hidden_params_out();
561     echo '<input type="hidden" name="sesskey" value="'.sesskey().'" />';
562     //YUI does not submit the value of the submit button so
563             //we need to add the value:
564     echo '<input type="hidden" name="repaginate" value="'.$gostring.'" />';
565     print_string('repaginate', 'quiz',
566             choose_from_menu($perpage, 'questionsperpage',
567             $quiz->questionsperpage, '', '', '', true, $repaginatingdisabled));
568     echo '<div class="quizquestionlistcontrols">';
569     echo ' <input type="submit" name="repaginate" value="'. $gostring .'" '.$repaginatingdisabledhtml.' />';
570     echo '</div></fieldset></form></div></div>';
573 echo '<div class="' . $currenttab . '">';
574 quiz_print_question_list($quiz, $thispageurl, true,
575         $quiz_reordertool, $quiz_qbanktool, $quizhasattempts);
576 echo '</div>';
578 // Close <div class="quizcontents">:
579 echo '</div>';
581 if (!$quiz_reordertool) {
582     // display category adding UI
583     ?>
584 <div id="randomquestiondialog">
585 <div class="hd"><?php print_string('addrandomquestiontoquiz', 'quiz', $quiz->name); ?>
586 <span id="pagenumber"><!-- JavaScript will insert the page number here. -->
587 </span>
588 </div>
589 <div class="bd"><?php
590 $qcobject->display_randomquestion_user_interface();
591 ?></div>
592 </div>
593     <?php
595 print_footer($course);
596 ?>