MDL-57431 mod_quiz: Quiz editing help icon fix
[moodle.git] / mod / quiz / classes / output / edit_renderer.php
CommitLineData
e1a2d0d9
CC
1<?php
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
17/**
18 * Renderer outputting the quiz editing UI.
19 *
20 * @package mod_quiz
21 * @copyright 2013 The Open University.
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23 */
24
25namespace mod_quiz\output;
26defined('MOODLE_INTERNAL') || die();
27
28use \mod_quiz\structure;
29use \html_writer;
91898889 30use renderable;
e1a2d0d9
CC
31
32/**
33 * Renderer outputting the quiz editing UI.
34 *
35 * @copyright 2013 The Open University.
36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
37 * @since Moodle 2.7
38 */
39class edit_renderer extends \plugin_renderer_base {
40
41 /**
42 * Render the edit page
43 *
44 * @param \quiz $quizobj object containing all the quiz settings information.
45 * @param structure $structure object containing the structure of the quiz.
46 * @param \question_edit_contexts $contexts the relevant question bank contexts.
47 * @param \moodle_url $pageurl the canonical URL of this page.
48 * @param array $pagevars the variables from {@link question_edit_setup()}.
49 * @return string HTML to output.
50 */
51 public function edit_page(\quiz $quizobj, structure $structure,
52 \question_edit_contexts $contexts, \moodle_url $pageurl, array $pagevars) {
53 $output = '';
54
55 // Page title.
56 $output .= $this->heading_with_help(get_string('editingquizx', 'quiz',
57 format_string($quizobj->get_quiz_name())), 'editingquiz', 'quiz', '',
58 get_string('basicideasofquiz', 'quiz'), 2);
59
60 // Information at the top.
61 $output .= $this->quiz_state_warnings($structure);
f37cffb6
CC
62
63 $output .= html_writer::start_div('mod_quiz-edit-top-controls');
e1a2d0d9 64 $output .= $this->quiz_information($structure);
441d284a 65 $output .= $this->maximum_grade_input($structure, $pageurl);
f37cffb6
CC
66
67 $output .= html_writer::start_div('mod_quiz-edit-action-buttons btn-group edit-toolbar', ['role' => 'group']);
e1a2d0d9 68 $output .= $this->repaginate_button($structure, $pageurl);
f37cffb6
CC
69 $output .= $this->selectmultiple_button($structure);
70 $output .= html_writer::end_tag('div');
71
e1a2d0d9
CC
72 $output .= $this->total_marks($quizobj->get_quiz());
73
f37cffb6
CC
74 $output .= $this->selectmultiple_controls($structure);
75 $output .= html_writer::end_tag('div');
76
e1a2d0d9 77 // Show the questions organised into sections and pages.
6d19eb4b 78 $output .= $this->start_section_list($structure);
e1a2d0d9 79
5d949702
K
80 foreach ($structure->get_sections() as $section) {
81 $output .= $this->start_section($structure, $section);
e1a2d0d9 82 $output .= $this->questions_in_section($structure, $section, $contexts, $pagevars, $pageurl);
5d949702
K
83
84 if ($structure->is_last_section($section)) {
e1a2d0d9
CC
85 $output .= \html_writer::start_div('last-add-menu');
86 $output .= html_writer::tag('span', $this->add_menu_actions($structure, 0,
87 $pageurl, $contexts, $pagevars), array('class' => 'add-menu-outer'));
88 $output .= \html_writer::end_div();
89 }
5d949702 90
e1a2d0d9
CC
91 $output .= $this->end_section();
92 }
93
94 $output .= $this->end_section_list();
95
32498c28 96 // Initialise the JavaScript.
441d284a 97 $this->initialise_editing_javascript($structure, $contexts, $pagevars, $pageurl);
e1a2d0d9
CC
98
99 // Include the contents of any other popups required.
100 if ($structure->can_be_edited()) {
101 $popups = '';
102
103 $popups .= $this->question_bank_loading();
104 $this->page->requires->yui_module('moodle-mod_quiz-quizquestionbank',
105 'M.mod_quiz.quizquestionbank.init',
106 array('class' => 'questionbank', 'cmid' => $structure->get_cmid()));
107
108 $popups .= $this->random_question_form($pageurl, $contexts, $pagevars);
109 $this->page->requires->yui_module('moodle-mod_quiz-randomquestion',
110 'M.mod_quiz.randomquestion.init');
111
112 $output .= html_writer::div($popups, 'mod_quiz_edit_forms');
113
114 // Include the question chooser.
115 $output .= $this->question_chooser();
e1a2d0d9
CC
116 }
117
118 return $output;
119 }
120
121 /**
122 * Render any warnings that might be required about the state of the quiz,
123 * e.g. if it has been attempted, or if the shuffle questions option is
124 * turned on.
125 *
126 * @param structure $structure the quiz structure.
127 * @return string HTML to output.
128 */
129 public function quiz_state_warnings(structure $structure) {
130 $warnings = $structure->get_edit_page_warnings();
131
132 if (empty($warnings)) {
133 return '';
134 }
135
136 $output = array();
137 foreach ($warnings as $warning) {
138 $output[] = \html_writer::tag('p', $warning);
139 }
140 return $this->box(implode("\n", $output), 'statusdisplay');
141 }
142
143 /**
144 * Render the status bar.
145 *
146 * @param structure $structure the quiz structure.
147 * @return string HTML to output.
148 */
149 public function quiz_information(structure $structure) {
150 list($currentstatus, $explanation) = $structure->get_dates_summary();
151
152 $output = html_writer::span(
153 get_string('numquestionsx', 'quiz', $structure->get_question_count()),
154 'numberofquestions') . ' | ' .
155 html_writer::span($currentstatus, 'quizopeningstatus',
156 array('title' => $explanation));
157
158 return html_writer::div($output, 'statusbar');
159 }
160
161 /**
162 * Render the form for setting a quiz' overall grade
163 *
441d284a 164 * @param structure $structure the quiz structure.
e1a2d0d9
CC
165 * @param \moodle_url $pageurl the canonical URL of this page.
166 * @return string HTML to output.
167 */
441d284a 168 public function maximum_grade_input($structure, \moodle_url $pageurl) {
e1a2d0d9
CC
169 $output = '';
170 $output .= html_writer::start_div('maxgrade');
171 $output .= html_writer::start_tag('form', array('method' => 'post', 'action' => 'edit.php',
12d6dfc1 172 'class' => 'quizsavegradesform form-inline'));
e1a2d0d9
CC
173 $output .= html_writer::start_tag('fieldset', array('class' => 'invisiblefieldset'));
174 $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey()));
175 $output .= html_writer::input_hidden_params($pageurl);
030d8f22
TH
176 $output .= html_writer::tag('label', get_string('maximumgrade') . ' ',
177 array('for' => 'inputmaxgrade'));
178 $output .= html_writer::empty_tag('input', array('type' => 'text', 'id' => 'inputmaxgrade',
441d284a 179 'name' => 'maxgrade', 'size' => ($structure->get_decimal_places_for_grades() + 2),
12d6dfc1
DW
180 'value' => $structure->formatted_quiz_grade(),
181 'class' => 'form-control'));
12d6dfc1 182 $output .= html_writer::empty_tag('input', array('type' => 'submit', 'class' => 'btn btn-secondary m-l-1',
e1a2d0d9
CC
183 'name' => 'savechanges', 'value' => get_string('save', 'quiz')));
184 $output .= html_writer::end_tag('fieldset');
185 $output .= html_writer::end_tag('form');
186 $output .= html_writer::end_tag('div');
187 return $output;
188 }
189
190 /**
191 * Return the repaginate button
192 * @param structure $structure the structure of the quiz being edited.
193 * @param \moodle_url $pageurl the canonical URL of this page.
194 * @return string HTML to output.
195 */
196 protected function repaginate_button(structure $structure, \moodle_url $pageurl) {
197
198 $header = html_writer::tag('span', get_string('repaginatecommand', 'quiz'), array('class' => 'repaginatecommand'));
199 $form = $this->repaginate_form($structure, $pageurl);
e1a2d0d9
CC
200
201 $buttonoptions = array(
202 'type' => 'submit',
203 'name' => 'repaginate',
204 'id' => 'repaginatecommand',
205 'value' => get_string('repaginatecommand', 'quiz'),
12d6dfc1 206 'class' => 'btn btn-secondary m-b-1',
f37cffb6
CC
207 'data-header' => $header,
208 'data-form' => $form,
e1a2d0d9
CC
209 );
210 if (!$structure->can_be_repaginated()) {
211 $buttonoptions['disabled'] = 'disabled';
212 } else {
213 $this->page->requires->yui_module('moodle-mod_quiz-repaginate', 'M.mod_quiz.repaginate.init');
214 }
215
f37cffb6 216 return html_writer::empty_tag('input', $buttonoptions);
5d803e53
LB
217 }
218
219 /**
f37cffb6
CC
220 * Generate the bulk action button.
221 *
5d803e53
LB
222 * @param structure $structure the structure of the quiz being edited.
223 * @return string HTML to output.
224 */
f37cffb6 225 protected function selectmultiple_button(structure $structure) {
5d803e53
LB
226 $buttonoptions = array(
227 'type' => 'button',
f37cffb6
CC
228 'name' => 'selectmultiple',
229 'id' => 'selectmultiplecommand',
230 'value' => get_string('selectmultipleitems', 'quiz'),
231 'class' => 'btn btn-secondary m-b-1'
5d803e53 232 );
f37cffb6 233 if (!$structure->can_be_edited()) {
5d803e53
LB
234 $buttonoptions['disabled'] = 'disabled';
235 }
f37cffb6
CC
236
237 return html_writer::tag('button', get_string('selectmultipleitems', 'quiz'), $buttonoptions);
238 }
239
240 /**
241 * Generate the controls that appear when the bulk action button is pressed.
242 *
243 * @param structure $structure the structure of the quiz being edited.
244 * @return string HTML to output.
245 */
246 protected function selectmultiple_controls(structure $structure) {
247 $output = '';
248
249 // Bulk action button delete and bulk action button cancel.
250 $buttondeleteoptions = array(
251 'type' => 'button',
252 'id' => 'selectmultipledeletecommand',
253 'value' => get_string('deleteselected', 'mod_quiz'),
254 'class' => 'btn btn-secondary'
255 );
256 $buttoncanceloptions = array(
257 'type' => 'button',
258 'id' => 'selectmultiplecancelcommand',
259 'value' => get_string('cancel', 'moodle'),
260 'class' => 'btn btn-secondary'
261 );
262
263 $groupoptions = array(
264 'class' => 'btn-group selectmultiplecommand actions',
265 'role' => 'group'
266 );
267
268 $output .= html_writer::tag('div',
269 html_writer::tag('button', get_string('deleteselected', 'mod_quiz'), $buttondeleteoptions) .
270 " " .
271 html_writer::tag('button', get_string('cancel', 'moodle'),
272 $buttoncanceloptions), $groupoptions);
273
274 $toolbaroptions = array(
275 'class' => 'btn-toolbar',
276 'role' => 'toolbar',
277 'aria-label' => get_string('selectmultipletoolbar', 'quiz'),
278 );
279
280 // Select all/deselect all questions.
281 $buttonselectalloptions = array(
282 'role' => 'button',
283 'id' => 'questionselectall',
284 'class' => 'btn btn-link'
285 );
286 $buttondeselectalloptions = array(
287 'role' => 'button',
288 'id' => 'questiondeselectall',
289 'class' => 'btn btn-link'
290 );
291 $output .= html_writer::tag('div',
292 html_writer::tag('div',
293 html_writer::link('#', get_string('selectall', 'quiz'), $buttonselectalloptions) .
294 html_writer::tag('span', "/", ['class' => 'separator']) .
295 html_writer::link('#', get_string('selectnone', 'quiz'), $buttondeselectalloptions),
296 array('class' => 'btn-group selectmultiplecommandbuttons')),
297 $toolbaroptions);
298 return $output;
e1a2d0d9
CC
299 }
300
301 /**
302 * Return the repaginate form
303 * @param structure $structure the structure of the quiz being edited.
304 * @param \moodle_url $pageurl the canonical URL of this page.
305 * @return string HTML to output.
306 */
307 protected function repaginate_form(structure $structure, \moodle_url $pageurl) {
308 $perpage = array();
309 $perpage[0] = get_string('allinone', 'quiz');
310 for ($i = 1; $i <= 50; ++$i) {
311 $perpage[$i] = $i;
312 }
313
314 $hiddenurl = clone($pageurl);
315 $hiddenurl->param('sesskey', sesskey());
316
317 $select = html_writer::select($perpage, 'questionsperpage',
12d6dfc1 318 $structure->get_questions_per_page(), false, array('class' => 'custom-select'));
e1a2d0d9 319
12d6dfc1
DW
320 $buttonattributes = array(
321 'type' => 'submit',
322 'name' => 'repaginate',
323 'value' => get_string('go'),
324 'class' => 'btn btn-secondary m-l-1'
325 );
e1a2d0d9
CC
326
327 $formcontent = html_writer::tag('form', html_writer::div(
328 html_writer::input_hidden_params($hiddenurl) .
329 get_string('repaginate', 'quiz', $select) .
330 html_writer::empty_tag('input', $buttonattributes)
331 ), array('action' => 'edit.php', 'method' => 'post'));
332
333 return html_writer::div($formcontent, '', array('id' => 'repaginatedialog'));
334 }
335
336 /**
337 * Render the total marks available for the quiz.
338 *
339 * @param \stdClass $quiz the quiz settings from the database.
340 * @return string HTML to output.
341 */
342 public function total_marks($quiz) {
343 $totalmark = html_writer::span(quiz_format_grade($quiz, $quiz->sumgrades), 'mod_quiz_summarks');
344 return html_writer::tag('span',
345 get_string('totalmarksx', 'quiz', $totalmark),
346 array('class' => 'totalpoints'));
347 }
348
349 /**
350 * Generate the starting container html for the start of a list of sections
6d19eb4b 351 * @param structure $structure the structure of the quiz being edited.
e1a2d0d9
CC
352 * @return string HTML to output.
353 */
6d19eb4b
TH
354 protected function start_section_list(structure $structure) {
355 $class = 'slots';
356 if ($structure->get_section_count() == 1) {
357 $class .= ' only-one-section';
358 }
359 return html_writer::start_tag('ul', array('class' => $class));
e1a2d0d9
CC
360 }
361
362 /**
363 * Generate the closing container html for the end of a list of sections
364 * @return string HTML to output.
365 */
366 protected function end_section_list() {
367 return html_writer::end_tag('ul');
368 }
369
370 /**
371 * Display the start of a section, before the questions.
372 *
5d949702 373 * @param structure $structure the structure of the quiz being edited.
e1a2d0d9
CC
374 * @param \stdClass $section The quiz_section entry from DB
375 * @return string HTML to output.
376 */
5d949702 377 protected function start_section($structure, $section) {
e1a2d0d9
CC
378
379 $output = '';
5d949702 380
e1a2d0d9 381 $sectionstyle = '';
5d949702
K
382 if ($structure->is_only_one_slot_in_section($section)) {
383 $sectionstyle = ' only-has-one-slot';
384 }
e1a2d0d9
CC
385
386 $output .= html_writer::start_tag('li', array('id' => 'section-'.$section->id,
387 'class' => 'section main clearfix'.$sectionstyle, 'role' => 'region',
388 'aria-label' => $section->heading));
389
e1a2d0d9
CC
390 $output .= html_writer::start_div('content');
391
5d949702
K
392 $output .= html_writer::start_div('section-heading');
393
394 $headingtext = $this->heading(html_writer::span(
395 html_writer::span($section->heading, 'instancesection'), 'sectioninstance'), 3);
396
397 if (!$structure->can_be_edited()) {
398 $editsectionheadingicon = '';
399 } else {
400 $editsectionheadingicon = html_writer::link(new \moodle_url('#'),
401 $this->pix_icon('t/editstring', get_string('sectionheadingedit', 'quiz', $section->heading),
402 'moodle', array('class' => 'editicon visibleifjs')),
403 array('class' => 'editing_section', 'data-action' => 'edit_section_title'));
404 }
405 $output .= html_writer::div($headingtext . $editsectionheadingicon, 'instancesectioncontainer');
406
407 if (!$structure->is_first_section($section) && $structure->can_be_edited()) {
408 $output .= $this->section_remove_icon($section);
409 }
410 $output .= $this->section_shuffle_questions($structure, $section);
411
412 $output .= html_writer::end_div($output, 'section-heading');
413
e1a2d0d9
CC
414 return $output;
415 }
416
417 /**
5d949702 418 * Display a checkbox for shuffling question within a section.
e1a2d0d9 419 *
5d949702
K
420 * @param structure $structure object containing the structure of the quiz.
421 * @param \stdClass $section data from the quiz_section table.
e1a2d0d9
CC
422 * @return string HTML to output.
423 */
5d949702
K
424 public function section_shuffle_questions(structure $structure, $section) {
425 $checkboxattributes = array(
426 'type' => 'checkbox',
427 'id' => 'shuffle-' . $section->id,
428 'value' => 1,
429 'data-action' => 'shuffle_questions',
430 'class' => 'cm-edit-action',
431 );
e1a2d0d9 432
5d949702
K
433 if (!$structure->can_be_edited()) {
434 $checkboxattributes['disabled'] = 'disabled';
435 }
436 if ($section->shufflequestions) {
437 $checkboxattributes['checked'] = 'checked';
438 }
439
440 if ($structure->is_first_section($section)) {
441 $help = $this->help_icon('shufflequestions', 'quiz');
442 } else {
443 $help = '';
444 }
445
aa6b85d2 446 $helpspan = html_writer::span($help, 'shuffle-help-tip');
5d949702
K
447 $progressspan = html_writer::span('', 'shuffle-progress');
448 $checkbox = html_writer::empty_tag('input', $checkboxattributes);
aa6b85d2 449 $label = html_writer::label(get_string('shufflequestions', 'quiz'),
5d949702 450 $checkboxattributes['id'], false);
aa6b85d2 451 return html_writer::span($progressspan . $checkbox . $label. ' ' . $helpspan,
5d949702 452 'instanceshufflequestions', array('data-action' => 'shuffle_questions'));
e1a2d0d9
CC
453 }
454
455 /**
5d949702 456 * Display the end of a section, after the questions.
e1a2d0d9 457 *
e1a2d0d9
CC
458 * @return string HTML to output.
459 */
5d949702
K
460 protected function end_section() {
461 $output = html_writer::end_tag('div');
462 $output .= html_writer::end_tag('li');
463
464 return $output;
e1a2d0d9
CC
465 }
466
467 /**
5d949702 468 * Render an icon to remove a section from the quiz.
e1a2d0d9 469 *
5d949702 470 * @param object $section the section to be removed.
e1a2d0d9
CC
471 * @return string HTML to output.
472 */
5d949702
K
473 public function section_remove_icon($section) {
474 $title = get_string('sectionheadingremove', 'quiz', $section->heading);
475 $url = new \moodle_url('/mod/quiz/edit.php',
476 array('sesskey' => sesskey(), 'removesection' => '1', 'sectionid' => $section->id));
477 $image = $this->pix_icon('t/delete', $title);
478 return $this->action_link($url, $image, null, array(
479 'class' => 'cm-edit-action editing_delete', 'data-action' => 'deletesection'));
e1a2d0d9
CC
480 }
481
482 /**
483 * Renders HTML to display the questions in a section of the quiz.
484 *
485 * This function calls {@link core_course_renderer::quiz_section_question()}
486 *
487 * @param structure $structure object containing the structure of the quiz.
488 * @param \stdClass $section information about the section.
489 * @param \question_edit_contexts $contexts the relevant question bank contexts.
490 * @param array $pagevars the variables from {@link \question_edit_setup()}.
491 * @param \moodle_url $pageurl the canonical URL of this page.
492 * @return string HTML to output.
493 */
494 public function questions_in_section(structure $structure, $section,
495 $contexts, $pagevars, $pageurl) {
496
497 $output = '';
441d284a
TH
498 foreach ($structure->get_slots_in_section($section->id) as $slot) {
499 $output .= $this->question_row($structure, $slot, $contexts, $pagevars, $pageurl);
e1a2d0d9 500 }
e1a2d0d9
CC
501 return html_writer::tag('ul', $output, array('class' => 'section img-text'));
502 }
503
504 /**
505 * Displays one question with the surrounding controls.
506 *
507 * @param structure $structure object containing the structure of the quiz.
441d284a 508 * @param int $slot which slot we are outputting.
e1a2d0d9
CC
509 * @param \question_edit_contexts $contexts the relevant question bank contexts.
510 * @param array $pagevars the variables from {@link \question_edit_setup()}.
511 * @param \moodle_url $pageurl the canonical URL of this page.
512 * @return string HTML to output.
513 */
441d284a 514 public function question_row(structure $structure, $slot, $contexts, $pagevars, $pageurl) {
e1a2d0d9
CC
515 $output = '';
516
441d284a 517 $output .= $this->page_row($structure, $slot, $contexts, $pagevars, $pageurl);
a69f81f0
CC
518
519 // Page split/join icon.
520 $joinhtml = '';
5d949702
K
521 if ($structure->can_be_edited() && !$structure->is_last_slot_in_quiz($slot) &&
522 !$structure->is_last_slot_in_section($slot)) {
441d284a 523 $joinhtml = $this->page_split_join_button($structure, $slot);
a69f81f0 524 }
a69f81f0 525 // Question HTML.
441d284a
TH
526 $questionhtml = $this->question($structure, $slot, $pageurl);
527 $qtype = $structure->get_question_type_for_slot($slot);
528 $questionclasses = 'activity ' . $qtype . ' qtype_' . $qtype . ' slot';
a69f81f0
CC
529
530 $output .= html_writer::tag('li', $questionhtml . $joinhtml,
441d284a
TH
531 array('class' => $questionclasses, 'id' => 'slot-' . $structure->get_slot_id_for_slot($slot),
532 'data-canfinish' => $structure->can_finish_during_the_attempt($slot)));
a69f81f0
CC
533
534 return $output;
535 }
536
537 /**
538 * Displays one question with the surrounding controls.
539 *
540 * @param structure $structure object containing the structure of the quiz.
441d284a 541 * @param int $slot the first slot on the page we are outputting.
a69f81f0
CC
542 * @param \question_edit_contexts $contexts the relevant question bank contexts.
543 * @param array $pagevars the variables from {@link \question_edit_setup()}.
544 * @param \moodle_url $pageurl the canonical URL of this page.
545 * @return string HTML to output.
546 */
441d284a 547 public function page_row(structure $structure, $slot, $contexts, $pagevars, $pageurl) {
a69f81f0
CC
548 $output = '';
549
441d284a
TH
550 $pagenumber = $structure->get_page_number_for_slot($slot);
551
5d949702
K
552 // Put page in a heading for accessibility and styling.
553 $page = $this->heading(get_string('page') . ' ' . $pagenumber, 4);
e1a2d0d9 554
441d284a 555 if ($structure->is_first_slot_on_page($slot)) {
e1a2d0d9
CC
556 // Add the add-menu at the page level.
557 $addmenu = html_writer::tag('span', $this->add_menu_actions($structure,
441d284a 558 $pagenumber, $pageurl, $contexts, $pagevars),
e1a2d0d9
CC
559 array('class' => 'add-menu-outer'));
560
561 $addquestionform = $this->add_question_form($structure,
441d284a 562 $pagenumber, $pageurl, $pagevars);
e1a2d0d9
CC
563
564 $output .= html_writer::tag('li', $page . $addmenu . $addquestionform,
441d284a 565 array('class' => 'pagenumber activity yui3-dd-drop page', 'id' => 'page-' . $pagenumber));
e1a2d0d9
CC
566 }
567
e1a2d0d9
CC
568 return $output;
569 }
570
571 /**
572 * Returns the add menu that is output once per page.
573 * @param structure $structure object containing the structure of the quiz.
574 * @param int $page the page number that this menu will add to.
575 * @param \moodle_url $pageurl the canonical URL of this page.
576 * @param \question_edit_contexts $contexts the relevant question bank contexts.
577 * @param array $pagevars the variables from {@link \question_edit_setup()}.
578 * @return string HTML to output.
579 */
580 public function add_menu_actions(structure $structure, $page, \moodle_url $pageurl,
581 \question_edit_contexts $contexts, array $pagevars) {
582
583 $actions = $this->edit_menu_actions($structure, $page, $pageurl, $pagevars);
584 if (empty($actions)) {
585 return '';
586 }
587 $menu = new \action_menu();
5d949702 588 $menu->set_alignment(\action_menu::TR, \action_menu::TR);
77dca4d0 589 $menu->set_constraint('.mod-quiz-edit-content');
e1a2d0d9
CC
590 $trigger = html_writer::tag('span', get_string('add', 'quiz'), array('class' => 'add-menu'));
591 $menu->set_menu_trigger($trigger);
8a375d27
SH
592 // The menu appears within an absolutely positioned element causing width problems.
593 // Make sure no-wrap is set so that we don't get a squashed menu.
594 $menu->set_nowrap_on_items(true);
e1a2d0d9
CC
595
596 // Disable the link if quiz has attempts.
597 if (!$structure->can_be_edited()) {
598 return $this->render($menu);
599 }
600
601 foreach ($actions as $action) {
602 if ($action instanceof \action_menu_link) {
603 $action->add_class('add-menu');
604 }
605 $menu->add($action);
606 }
607 $menu->attributes['class'] .= ' page-add-actions commands';
608
609 // Prioritise the menu ahead of all other actions.
610 $menu->prioritise = true;
611
612 return $this->render($menu);
613 }
614
615 /**
616 * Returns the list of actions to go in the add menu.
617 * @param structure $structure object containing the structure of the quiz.
618 * @param int $page the page number that this menu will add to.
619 * @param \moodle_url $pageurl the canonical URL of this page.
620 * @param array $pagevars the variables from {@link \question_edit_setup()}.
621 * @return array the actions.
622 */
623 public function edit_menu_actions(structure $structure, $page,
624 \moodle_url $pageurl, array $pagevars) {
625 $questioncategoryid = question_get_category_id_from_pagevars($pagevars);
626 static $str;
627 if (!isset($str)) {
5d949702 628 $str = get_strings(array('addasection', 'addaquestion', 'addarandomquestion',
e1a2d0d9
CC
629 'addarandomselectedquestion', 'questionbank'), 'quiz');
630 }
631
632 // Get section, page, slotnumber and maxmark.
633 $actions = array();
634
5d949702
K
635 // Add a new section to the add_menu if possible. This is always added to the HTML
636 // then hidden with CSS when no needed, so that as things are re-ordered, etc. with
637 // Ajax it can be relevaled again when necessary.
32498c28 638 $params = array('cmid' => $structure->get_cmid(), 'addsectionatpage' => $page);
5d949702
K
639
640 $actions['addasection'] = new \action_menu_link_secondary(
641 new \moodle_url($pageurl, $params),
642 new \pix_icon('t/add', $str->addasection, 'moodle', array('class' => 'iconsmall', 'title' => '')),
643 $str->addasection, array('class' => 'cm-edit-action addasection', 'data-action' => 'addasection')
644 );
645
e1a2d0d9
CC
646 // Add a new question to the quiz.
647 $returnurl = new \moodle_url($pageurl, array('addonpage' => $page));
648 $params = array('returnurl' => $returnurl->out_as_local_url(false),
649 'cmid' => $structure->get_cmid(), 'category' => $questioncategoryid,
650 'addonpage' => $page, 'appendqnumstring' => 'addquestion');
651
652 $actions['addaquestion'] = new \action_menu_link_secondary(
653 new \moodle_url('/question/addquestion.php', $params),
654 new \pix_icon('t/add', $str->addaquestion, 'moodle', array('class' => 'iconsmall', 'title' => '')),
655 $str->addaquestion, array('class' => 'cm-edit-action addquestion', 'data-action' => 'addquestion')
656 );
657
658 // Call question bank.
659 $icon = new \pix_icon('t/add', $str->questionbank, 'moodle', array('class' => 'iconsmall', 'title' => ''));
ca79762a
TH
660 if ($page) {
661 $title = get_string('addquestionfrombanktopage', 'quiz', $page);
662 } else {
663 $title = get_string('addquestionfrombankatend', 'quiz');
664 }
e1a2d0d9
CC
665 $attributes = array('class' => 'cm-edit-action questionbank',
666 'data-header' => $title, 'data-action' => 'questionbank', 'data-addonpage' => $page);
667 $actions['questionbank'] = new \action_menu_link_secondary($pageurl, $icon, $str->questionbank, $attributes);
668
669 // Add a random question.
670 $returnurl = new \moodle_url('/mod/quiz/edit.php', array('cmid' => $structure->get_cmid(), 'data-addonpage' => $page));
671 $params = array('returnurl' => $returnurl, 'cmid' => $structure->get_cmid(), 'appendqnumstring' => 'addarandomquestion');
672 $url = new \moodle_url('/mod/quiz/addrandom.php', $params);
673 $icon = new \pix_icon('t/add', $str->addarandomquestion, 'moodle', array('class' => 'iconsmall', 'title' => ''));
674 $attributes = array('class' => 'cm-edit-action addarandomquestion', 'data-action' => 'addarandomquestion');
ca79762a
TH
675 if ($page) {
676 $title = get_string('addrandomquestiontopage', 'quiz', $page);
677 } else {
678 $title = get_string('addrandomquestionatend', 'quiz');
679 }
e1a2d0d9
CC
680 $attributes = array_merge(array('data-header' => $title, 'data-addonpage' => $page), $attributes);
681 $actions['addarandomquestion'] = new \action_menu_link_secondary($url, $icon, $str->addarandomquestion, $attributes);
682
683 return $actions;
684 }
685
686 /**
687 * Render the form that contains the data for adding a new question to the quiz.
688 *
689 * @param structure $structure object containing the structure of the quiz.
690 * @param int $page the page number that this menu will add to.
691 * @param \moodle_url $pageurl the canonical URL of this page.
692 * @param array $pagevars the variables from {@link \question_edit_setup()}.
693 * @return string HTML to output.
694 */
695 protected function add_question_form(structure $structure, $page, \moodle_url $pageurl, array $pagevars) {
696
697 $questioncategoryid = question_get_category_id_from_pagevars($pagevars);
698
699 $output = html_writer::tag('input', null,
700 array('type' => 'hidden', 'name' => 'returnurl',
701 'value' => $pageurl->out_as_local_url(false, array('addonpage' => $page))));
702 $output .= html_writer::tag('input', null,
703 array('type' => 'hidden', 'name' => 'cmid', 'value' => $structure->get_cmid()));
704 $output .= html_writer::tag('input', null,
705 array('type' => 'hidden', 'name' => 'appendqnumstring', 'value' => 'addquestion'));
706 $output .= html_writer::tag('input', null,
707 array('type' => 'hidden', 'name' => 'category', 'value' => $questioncategoryid));
708
709 return html_writer::tag('form', html_writer::div($output),
710 array('class' => 'addnewquestion', 'method' => 'post',
711 'action' => new \moodle_url('/question/addquestion.php')));
712 }
713
714 /**
715 * Display a question.
716 *
717 * @param structure $structure object containing the structure of the quiz.
441d284a 718 * @param int $slot the first slot on the page we are outputting.
e1a2d0d9
CC
719 * @param \moodle_url $pageurl the canonical URL of this page.
720 * @return string HTML to output.
721 */
441d284a 722 public function question(structure $structure, $slot, \moodle_url $pageurl) {
e1a2d0d9 723 $output = '';
e1a2d0d9
CC
724 $output .= html_writer::start_tag('div');
725
726 if ($structure->can_be_edited()) {
441d284a 727 $output .= $this->question_move_icon($structure, $slot);
e1a2d0d9
CC
728 }
729
730 $output .= html_writer::start_div('mod-indent-outer');
5d803e53
LB
731 $output .= html_writer::tag('input', '', array('id' => 'selectquestion-' .
732 $structure->get_displayed_number_for_slot($slot), 'name' => 'selectquestion[]',
f37cffb6 733 'type' => 'checkbox', 'class' => 'select-multiple-checkbox',
5d803e53 734 'value' => $structure->get_displayed_number_for_slot($slot)));
441d284a 735 $output .= $this->question_number($structure->get_displayed_number_for_slot($slot));
e1a2d0d9
CC
736
737 // This div is used to indent the content.
738 $output .= html_writer::div('', 'mod-indent');
739
740 // Display the link to the question (or do nothing if question has no url).
441d284a
TH
741 if ($structure->get_question_type_for_slot($slot) == 'random') {
742 $questionname = $this->random_question($structure, $slot, $pageurl);
e1a2d0d9 743 } else {
441d284a 744 $questionname = $this->question_name($structure, $slot, $pageurl);
e1a2d0d9
CC
745 }
746
747 // Start the div for the activity title, excluding the edit icons.
748 $output .= html_writer::start_div('activityinstance');
749 $output .= $questionname;
750
751 // Closing the tag which contains everything but edit icons. Content part of the module should not be part of this.
752 $output .= html_writer::end_tag('div'); // .activityinstance.
753
754 // Action icons.
755 $questionicons = '';
441d284a 756 $questionicons .= $this->question_preview_icon($structure->get_quiz(), $structure->get_question_in_slot($slot));
e1a2d0d9 757 if ($structure->can_be_edited()) {
441d284a 758 $questionicons .= $this->question_remove_icon($structure, $slot, $pageurl);
e1a2d0d9 759 }
441d284a 760 $questionicons .= $this->marked_out_of_field($structure, $slot);
e1a2d0d9 761 $output .= html_writer::span($questionicons, 'actions'); // Required to add js spinner icon.
441d284a
TH
762 if ($structure->can_be_edited()) {
763 $output .= $this->question_dependency_icon($structure, $slot);
764 }
e1a2d0d9
CC
765
766 // End of indentation div.
767 $output .= html_writer::end_tag('div');
768 $output .= html_writer::end_tag('div');
769
770 return $output;
771 }
772
773 /**
774 * Render the move icon.
775 *
441d284a
TH
776 * @param structure $structure object containing the structure of the quiz.
777 * @param int $slot the first slot on the page we are outputting.
778 * @return string The markup for the move action.
e1a2d0d9 779 */
441d284a 780 public function question_move_icon(structure $structure, $slot) {
e1a2d0d9
CC
781 return html_writer::link(new \moodle_url('#'),
782 $this->pix_icon('i/dragdrop', get_string('move'), 'moodle', array('class' => 'iconsmall', 'title' => '')),
783 array('class' => 'editing_move', 'data-action' => 'move')
784 );
785 }
786
787 /**
788 * Output the question number.
789 * @param string $number The number, or 'i'.
790 * @return string HTML to output.
791 */
792 public function question_number($number) {
793 if (is_numeric($number)) {
f7785e42 794 $number = html_writer::span(get_string('question'), 'accesshide') . ' ' . $number;
e1a2d0d9
CC
795 }
796 return html_writer::tag('span', $number, array('class' => 'slotnumber'));
797 }
798
799 /**
800 * Render the preview icon.
801 *
802 * @param \stdClass $quiz the quiz settings from the database.
803 * @param \stdClass $question data from the question and quiz_slots tables.
804 * @param bool $label if true, show the preview question label after the icon
de3b803d 805 * @param int $variant which question variant to preview (optional).
e1a2d0d9
CC
806 * @return string HTML to output.
807 */
de3b803d
TH
808 public function question_preview_icon($quiz, $question, $label = null, $variant = null) {
809 $url = quiz_question_preview_url($quiz, $question, $variant);
e1a2d0d9
CC
810
811 // Do we want a label?
812 $strpreviewlabel = '';
813 if ($label) {
814 $strpreviewlabel = ' ' . get_string('preview', 'quiz');
815 }
816
817 // Build the icon.
818 $strpreviewquestion = get_string('previewquestion', 'quiz');
819 $image = $this->pix_icon('t/preview', $strpreviewquestion);
820
821 $action = new \popup_action('click', $url, 'questionpreview',
822 question_preview_popup_params());
823
824 return $this->action_link($url, $image . $strpreviewlabel, $action,
825 array('title' => $strpreviewquestion, 'class' => 'preview'));
826 }
827
828 /**
829 * Render an icon to remove a question from the quiz.
830 *
441d284a
TH
831 * @param structure $structure object containing the structure of the quiz.
832 * @param int $slot the first slot on the page we are outputting.
e1a2d0d9
CC
833 * @param \moodle_url $pageurl the canonical URL of the edit page.
834 * @return string HTML to output.
835 */
441d284a
TH
836 public function question_remove_icon(structure $structure, $slot, $pageurl) {
837 $url = new \moodle_url($pageurl, array('sesskey' => sesskey(), 'remove' => $slot));
e1a2d0d9
CC
838 $strdelete = get_string('delete');
839
840 $image = $this->pix_icon('t/delete', $strdelete);
841
842 return $this->action_link($url, $image, null, array('title' => $strdelete,
843 'class' => 'cm-edit-action editing_delete', 'data-action' => 'delete'));
844 }
845
846 /**
847 * Display an icon to split or join two pages of the quiz.
848 *
441d284a
TH
849 * @param structure $structure object containing the structure of the quiz.
850 * @param int $slot the first slot on the page we are outputting.
e1a2d0d9
CC
851 * @return string HTML to output.
852 */
441d284a
TH
853 public function page_split_join_button($structure, $slot) {
854 $insertpagebreak = !$structure->is_last_slot_on_page($slot);
855 $url = new \moodle_url('repaginate.php', array('quizid' => $structure->get_quizid(),
856 'slot' => $slot, 'repag' => $insertpagebreak ? 2 : 1, 'sesskey' => sesskey()));
e1a2d0d9
CC
857
858 if ($insertpagebreak) {
a69f81f0 859 $title = get_string('addpagebreak', 'quiz');
3e6adcd6 860 $image = $this->image_icon('e/insert_page_break', $title);
a69f81f0 861 $action = 'addpagebreak';
e1a2d0d9 862 } else {
a69f81f0 863 $title = get_string('removepagebreak', 'quiz');
3e6adcd6 864 $image = $this->image_icon('e/remove_page_break', $title);
a69f81f0 865 $action = 'removepagebreak';
e1a2d0d9
CC
866 }
867
868 // Disable the link if quiz has attempts.
869 $disabled = null;
441d284a
TH
870 if (!$structure->can_be_edited()) {
871 $disabled = 'disabled';
e1a2d0d9
CC
872 }
873 return html_writer::span($this->action_link($url, $image, null, array('title' => $title,
a69f81f0 874 'class' => 'page_split_join cm-edit-action', 'disabled' => $disabled, 'data-action' => $action)),
f7785e42
K
875 'page_split_join_wrapper');
876 }
877
878 /**
441d284a
TH
879 * Display the icon for whether this question can only be seen if the previous
880 * one has been answered.
f7785e42 881 *
441d284a
TH
882 * @param structure $structure object containing the structure of the quiz.
883 * @param int $slot the first slot on the page we are outputting.
884 * @return string HTML to output.
f7785e42 885 */
441d284a
TH
886 public function question_dependency_icon($structure, $slot) {
887 $a = array(
888 'thisq' => $structure->get_displayed_number_for_slot($slot),
889 'previousq' => $structure->get_displayed_number_for_slot(max($slot - 1, 1)),
890 );
891 if ($structure->is_question_dependent_on_previous_slot($slot)) {
892 $title = get_string('questiondependencyremove', 'quiz', $a);
893 $image = $this->pix_icon('t/locked', get_string('questiondependsonprevious', 'quiz'),
894 'moodle', array('title' => ''));
895 $action = 'removedependency';
f7785e42 896 } else {
441d284a
TH
897 $title = get_string('questiondependencyadd', 'quiz', $a);
898 $image = $this->pix_icon('t/unlocked', get_string('questiondependencyfree', 'quiz'),
899 'moodle', array('title' => ''));
900 $action = 'adddependency';
f7785e42
K
901 }
902
903 // Disable the link if quiz has attempts.
904 $disabled = null;
441d284a
TH
905 if (!$structure->can_be_edited()) {
906 $disabled = 'disabled';
f7785e42 907 }
441d284a
TH
908 $extraclass = '';
909 if (!$structure->can_question_depend_on_previous_slot($slot)) {
910 $extraclass = ' question_dependency_cannot_depend';
911 }
912 return html_writer::span($this->action_link('#', $image, null, array('title' => $title,
913 'class' => 'cm-edit-action', 'disabled' => $disabled, 'data-action' => $action)),
914 'question_dependency_wrapper' . $extraclass);
e1a2d0d9
CC
915 }
916
917 /**
918 * Renders html to display a name with the link to the question on a quiz edit page
919 *
920 * If the user does not have permission to edi the question, it is rendered
921 * without a link
922 *
923 * @param structure $structure object containing the structure of the quiz.
441d284a 924 * @param int $slot which slot we are outputting.
e1a2d0d9
CC
925 * @param \moodle_url $pageurl the canonical URL of this page.
926 * @return string HTML to output.
927 */
441d284a 928 public function question_name(structure $structure, $slot, $pageurl) {
e1a2d0d9
CC
929 $output = '';
930
441d284a 931 $question = $structure->get_question_in_slot($slot);
e1a2d0d9
CC
932 $editurl = new \moodle_url('/question/question.php', array(
933 'returnurl' => $pageurl->out_as_local_url(),
934 'cmid' => $structure->get_cmid(), 'id' => $question->id));
935
936 $instancename = quiz_question_tostring($question);
937
938 $qtype = \question_bank::get_qtype($question->qtype, false);
939 $namestr = $qtype->local_name();
940
941 $icon = $this->pix_icon('icon', $namestr, $qtype->plugin_name(), array('title' => $namestr,
942 'class' => 'icon activityicon', 'alt' => ' ', 'role' => 'presentation'));
943
944 $editicon = $this->pix_icon('t/edit', '', 'moodle', array('title' => ''));
945
946 // Need plain question name without html tags for link title.
947 $title = shorten_text(format_string($question->name), 100);
948
949 // Display the link itself.
950 $activitylink = $icon . html_writer::tag('span', $editicon . $instancename, array('class' => 'instancename'));
951 $output .= html_writer::link($editurl, $activitylink,
952 array('title' => get_string('editquestion', 'quiz').' '.$title));
953
954 return $output;
955 }
956
957 /**
958 * Renders html to display a random question the link to edit the configuration
959 * and also to see that category in the question bank.
960 *
961 * @param structure $structure object containing the structure of the quiz.
441d284a 962 * @param int $slot which slot we are outputting.
e1a2d0d9
CC
963 * @param \moodle_url $pageurl the canonical URL of this page.
964 * @return string HTML to output.
965 */
441d284a 966 public function random_question(structure $structure, $slot, $pageurl) {
e1a2d0d9 967
441d284a 968 $question = $structure->get_question_in_slot($slot);
e1a2d0d9
CC
969 $editurl = new \moodle_url('/question/question.php', array(
970 'returnurl' => $pageurl->out_as_local_url(),
971 'cmid' => $structure->get_cmid(), 'id' => $question->id));
972
973 $temp = clone($question);
974 $temp->questiontext = '';
975 $instancename = quiz_question_tostring($temp);
976
977 $configuretitle = get_string('configurerandomquestion', 'quiz');
978 $qtype = \question_bank::get_qtype($question->qtype, false);
979 $namestr = $qtype->local_name();
980 $icon = $this->pix_icon('icon', $namestr, $qtype->plugin_name(), array('title' => $namestr,
981 'class' => 'icon activityicon', 'alt' => ' ', 'role' => 'presentation'));
982
983 $editicon = $this->pix_icon('t/edit', $configuretitle, 'moodle', array('title' => ''));
984
985 // If this is a random question, display a link to show the questions
986 // selected from in the question bank.
987 $qbankurl = new \moodle_url('/question/edit.php', array(
988 'cmid' => $structure->get_cmid(),
989 'cat' => $question->category . ',' . $question->contextid,
990 'recurse' => !empty($question->questiontext)));
991 $qbanklink = ' ' . \html_writer::link($qbankurl,
992 get_string('seequestions', 'quiz'), array('class' => 'mod_quiz_random_qbank_link'));
993
994 return html_writer::link($editurl, $icon . $editicon, array('title' => $configuretitle)) .
995 ' ' . $instancename . ' ' . $qbanklink;
996 }
997
998 /**
999 * Display the 'marked out of' information for a question.
1000 * Along with the regrade action.
441d284a
TH
1001 * @param structure $structure object containing the structure of the quiz.
1002 * @param int $slot which slot we are outputting.
e1a2d0d9
CC
1003 * @return string HTML to output.
1004 */
441d284a
TH
1005 public function marked_out_of_field(structure $structure, $slot) {
1006 if (!$structure->is_real_question($slot)) {
97ef7ea2 1007 $output = html_writer::span('',
441d284a 1008 'instancemaxmark decimalplaces_' . $structure->get_decimal_places_for_question_marks());
97ef7ea2
TH
1009
1010 $output .= html_writer::span(
1011 $this->pix_icon('spacer', '', 'moodle', array('class' => 'editicon visibleifjs', 'title' => '')),
1012 'editing_maxmark');
1013 return html_writer::span($output, 'instancemaxmarkcontainer infoitem');
1014 }
1015
441d284a
TH
1016 $output = html_writer::span($structure->formatted_question_grade($slot),
1017 'instancemaxmark decimalplaces_' . $structure->get_decimal_places_for_question_marks(),
e1a2d0d9
CC
1018 array('title' => get_string('maxmark', 'quiz')));
1019
1020 $output .= html_writer::span(
1021 html_writer::link(
1022 new \moodle_url('#'),
97ef7ea2 1023 $this->pix_icon('t/editstring', '', 'moodle', array('class' => 'editicon visibleifjs', 'title' => '')),
e1a2d0d9
CC
1024 array(
1025 'class' => 'editing_maxmark',
1026 'data-action' => 'editmaxmark',
1027 'title' => get_string('editmaxmark', 'quiz'),
1028 )
1029 )
1030 );
1031 return html_writer::span($output, 'instancemaxmarkcontainer');
1032 }
1033
91898889
FM
1034 /**
1035 * Renders the question chooser.
1036 *
1037 * @param renderable
1038 * @return string
1039 */
1040 public function render_question_chooser(renderable $chooser) {
1041 return $this->render_from_template('mod_quiz/question_chooser', $chooser->export_for_template($this));
1042 }
1043
e1a2d0d9
CC
1044 /**
1045 * Render the question type chooser dialogue.
1046 * @return string HTML to output.
1047 */
1048 public function question_chooser() {
91898889
FM
1049 $chooser = \mod_quiz\output\question_chooser::get($this->page->course, [], null);
1050 $container = html_writer::div($this->render($chooser), '', array('id' => 'qtypechoicecontainer'));
e1a2d0d9
CC
1051 return html_writer::div($container, 'createnewquestion');
1052 }
1053
1054 /**
1055 * Render the contents of the question bank pop-up in its initial state,
1056 * when it just contains a loading progress indicator.
1057 * @return string HTML to output.
1058 */
1059 public function question_bank_loading() {
8857c715 1060 return html_writer::div($this->pix_icon('i/loading', get_string('loading')), 'questionbankloading');
e1a2d0d9
CC
1061 }
1062
1063 /**
1064 * Return random question form.
1065 * @param \moodle_url $thispageurl the canonical URL of this page.
1066 * @param \question_edit_contexts $contexts the relevant question bank contexts.
1067 * @param array $pagevars the variables from {@link \question_edit_setup()}.
1068 * @return string HTML to output.
1069 */
1070 protected function random_question_form(\moodle_url $thispageurl, \question_edit_contexts $contexts, array $pagevars) {
1071
1072 if (!$contexts->have_cap('moodle/question:useall')) {
1073 return '';
1074 }
1075 $randomform = new \quiz_add_random_form(new \moodle_url('/mod/quiz/addrandom.php'),
1076 array('contexts' => $contexts, 'cat' => $pagevars['cat']));
1077 $randomform->set_data(array(
1078 'category' => $pagevars['cat'],
1079 'returnurl' => $thispageurl->out_as_local_url(true),
1080 'randomnumber' => 1,
1081 'cmid' => $thispageurl->param('cmid'),
1082 ));
1083 return html_writer::div($randomform->render(), 'randomquestionformforpopup');
1084 }
1085
1086 /**
1087 * Initialise the JavaScript for the general editing. (JavaScript for popups
1088 * is handled with the specific code for those.)
1089 *
a69f81f0
CC
1090 * @param structure $structure object containing the structure of the quiz.
1091 * @param \question_edit_contexts $contexts the relevant question bank contexts.
1092 * @param array $pagevars the variables from {@link \question_edit_setup()}.
1093 * @param \moodle_url $pageurl the canonical URL of this page.
e1a2d0d9
CC
1094 * @return bool Always returns true
1095 */
441d284a 1096 protected function initialise_editing_javascript(structure $structure,
a69f81f0 1097 \question_edit_contexts $contexts, array $pagevars, \moodle_url $pageurl) {
e1a2d0d9
CC
1098
1099 $config = new \stdClass();
1100 $config->resourceurl = '/mod/quiz/edit_rest.php';
1101 $config->sectionurl = '/mod/quiz/edit_rest.php';
1102 $config->pageparams = array();
441d284a 1103 $config->questiondecimalpoints = $structure->get_decimal_places_for_question_marks();
a69f81f0 1104 $config->pagehtml = $this->new_page_template($structure, $contexts, $pagevars, $pageurl);
441d284a 1105 $config->addpageiconhtml = $this->add_page_icon_template($structure);
e1a2d0d9 1106
e1a2d0d9
CC
1107 $this->page->requires->yui_module('moodle-mod_quiz-toolboxes',
1108 'M.mod_quiz.init_resource_toolbox',
1109 array(array(
441d284a
TH
1110 'courseid' => $structure->get_courseid(),
1111 'quizid' => $structure->get_quizid(),
e1a2d0d9
CC
1112 'ajaxurl' => $config->resourceurl,
1113 'config' => $config,
1114 ))
1115 );
a69f81f0
CC
1116 unset($config->pagehtml);
1117 unset($config->addpageiconhtml);
1118
5d803e53 1119 $this->page->requires->strings_for_js(array('areyousureremoveselected'), 'quiz');
e1a2d0d9
CC
1120 $this->page->requires->yui_module('moodle-mod_quiz-toolboxes',
1121 'M.mod_quiz.init_section_toolbox',
1122 array(array(
441d284a
TH
1123 'courseid' => $structure,
1124 'quizid' => $structure->get_quizid(),
e1a2d0d9
CC
1125 'ajaxurl' => $config->sectionurl,
1126 'config' => $config,
1127 ))
1128 );
1129
e1a2d0d9
CC
1130 $this->page->requires->yui_module('moodle-mod_quiz-dragdrop', 'M.mod_quiz.init_section_dragdrop',
1131 array(array(
441d284a
TH
1132 'courseid' => $structure,
1133 'quizid' => $structure->get_quizid(),
e1a2d0d9
CC
1134 'ajaxurl' => $config->sectionurl,
1135 'config' => $config,
1136 )), null, true);
1137
1138 $this->page->requires->yui_module('moodle-mod_quiz-dragdrop', 'M.mod_quiz.init_resource_dragdrop',
1139 array(array(
441d284a
TH
1140 'courseid' => $structure,
1141 'quizid' => $structure->get_quizid(),
e1a2d0d9
CC
1142 'ajaxurl' => $config->resourceurl,
1143 'config' => $config,
1144 )), null, true);
1145
1146 // Require various strings for the command toolbox.
1147 $this->page->requires->strings_for_js(array(
84b45a24 1148 'clicktohideshow',
e1a2d0d9
CC
1149 'deletechecktype',
1150 'deletechecktypename',
1151 'edittitle',
1152 'edittitleinstructions',
84b45a24 1153 'emptydragdropregion',
e1a2d0d9 1154 'hide',
e1a2d0d9 1155 'markedthistopic',
84b45a24 1156 'markthistopic',
e1a2d0d9 1157 'move',
e1a2d0d9 1158 'movecontent',
84b45a24
TH
1159 'moveleft',
1160 'movesection',
a69f81f0
CC
1161 'page',
1162 'question',
e1a2d0d9 1163 'selectall',
84b45a24 1164 'show',
e1a2d0d9 1165 'tocontent',
e1a2d0d9
CC
1166 ), 'moodle');
1167
1168 $this->page->requires->strings_for_js(array(
a69f81f0 1169 'addpagebreak',
5d949702 1170 'confirmremovesectionheading',
e1a2d0d9
CC
1171 'confirmremovequestion',
1172 'dragtoafter',
1173 'dragtostart',
6375e98c 1174 'numquestionsx',
5d949702
K
1175 'sectionheadingedit',
1176 'sectionheadingremove',
a69f81f0 1177 'removepagebreak',
441d284a
TH
1178 'questiondependencyadd',
1179 'questiondependencyfree',
1180 'questiondependencyremove',
1181 'questiondependsonprevious',
e1a2d0d9
CC
1182 ), 'quiz');
1183
1184 foreach (\question_bank::get_all_qtypes() as $qtype => $notused) {
1185 $this->page->requires->string_for_js('pluginname', 'qtype_' . $qtype);
1186 }
1187
1188 return true;
1189 }
1190
a69f81f0
CC
1191 /**
1192 * HTML for a page, with ids stripped, so it can be used as a javascript template.
1193 *
1194 * @param structure $structure object containing the structure of the quiz.
1195 * @param \question_edit_contexts $contexts the relevant question bank contexts.
1196 * @param array $pagevars the variables from {@link \question_edit_setup()}.
1197 * @param \moodle_url $pageurl the canonical URL of this page.
1198 * @return string HTML for a new page.
1199 */
1200 protected function new_page_template(structure $structure,
1201 \question_edit_contexts $contexts, array $pagevars, \moodle_url $pageurl) {
1202 if (!$structure->has_questions()) {
1203 return '';
1204 }
1205
441d284a 1206 $pagehtml = $this->page_row($structure, 1, $contexts, $pagevars, $pageurl);
a69f81f0
CC
1207
1208 // Normalise the page number.
441d284a 1209 $pagenumber = $structure->get_page_number_for_slot(1);
a69f81f0
CC
1210 $strcontexts = array();
1211 $strcontexts[] = 'page-';
1212 $strcontexts[] = get_string('page') . ' ';
1213 $strcontexts[] = 'addonpage%3D';
1214 $strcontexts[] = 'addonpage=';
1215 $strcontexts[] = 'addonpage="';
1216 $strcontexts[] = get_string('addquestionfrombanktopage', 'quiz', '');
1217 $strcontexts[] = 'data-addonpage%3D';
1218 $strcontexts[] = 'action-menu-';
1219
1220 foreach ($strcontexts as $strcontext) {
1221 $pagehtml = str_replace($strcontext . $pagenumber, $strcontext . '%%PAGENUMBER%%', $pagehtml);
1222 }
1223
1224 return $pagehtml;
1225 }
1226
1227 /**
1228 * HTML for a page, with ids stripped, so it can be used as a javascript template.
1229 *
1230 * @param structure $structure object containing the structure of the quiz.
a69f81f0
CC
1231 * @return string HTML for a new icon
1232 */
441d284a 1233 protected function add_page_icon_template(structure $structure) {
a69f81f0
CC
1234
1235 if (!$structure->has_questions()) {
1236 return '';
1237 }
1238
441d284a 1239 $html = $this->page_split_join_button($structure, 1);
a69f81f0
CC
1240 return str_replace('&amp;slot=1&amp;', '&amp;slot=%%SLOT%%&amp;', $html);
1241 }
1242
e1a2d0d9
CC
1243 /**
1244 * Return the contents of the question bank, to be displayed in the question-bank pop-up.
1245 *
8aa5e0cf 1246 * @param \mod_quiz\question\bank\custom_view $questionbank the question bank view object.
e1a2d0d9
CC
1247 * @param array $pagevars the variables from {@link \question_edit_setup()}.
1248 * @return string HTML to output / send back in response to an AJAX request.
1249 */
8aa5e0cf 1250 public function question_bank_contents(\mod_quiz\question\bank\custom_view $questionbank, array $pagevars) {
e1a2d0d9
CC
1251
1252 $qbank = $questionbank->render('editq', $pagevars['qpage'], $pagevars['qperpage'],
1253 $pagevars['cat'], $pagevars['recurse'], $pagevars['showhidden'], $pagevars['qbshowtext']);
1254 return html_writer::div(html_writer::div($qbank, 'bd'), 'questionbankformforpopup');
1255 }
1256}