[ Index ] |
PHP Cross Reference of moodle-2.8 |
[Summary view] [Print] [Text view]
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 25 namespace mod_quiz\output; 26 defined('MOODLE_INTERNAL') || die(); 27 28 use \mod_quiz\structure; 29 use \html_writer; 30 31 /** 32 * Renderer outputting the quiz editing UI. 33 * 34 * @copyright 2013 The Open University. 35 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 * @since Moodle 2.7 37 */ 38 class edit_renderer extends \plugin_renderer_base { 39 40 /** 41 * Render the edit page 42 * 43 * @param \quiz $quizobj object containing all the quiz settings information. 44 * @param structure $structure object containing the structure of the quiz. 45 * @param \question_edit_contexts $contexts the relevant question bank contexts. 46 * @param \moodle_url $pageurl the canonical URL of this page. 47 * @param array $pagevars the variables from {@link question_edit_setup()}. 48 * @return string HTML to output. 49 */ 50 public function edit_page(\quiz $quizobj, structure $structure, 51 \question_edit_contexts $contexts, \moodle_url $pageurl, array $pagevars) { 52 $output = ''; 53 54 // Page title. 55 $output .= $this->heading_with_help(get_string('editingquizx', 'quiz', 56 format_string($quizobj->get_quiz_name())), 'editingquiz', 'quiz', '', 57 get_string('basicideasofquiz', 'quiz'), 2); 58 59 // Information at the top. 60 $output .= $this->quiz_state_warnings($structure); 61 $output .= $this->quiz_information($structure); 62 $output .= $this->maximum_grade_input($quizobj->get_quiz(), $this->page->url); 63 $output .= $this->repaginate_button($structure, $pageurl); 64 $output .= $this->total_marks($quizobj->get_quiz()); 65 66 // Show the questions organised into sections and pages. 67 $output .= $this->start_section_list(); 68 69 $sections = $structure->get_quiz_sections(); 70 $lastsection = end($sections); 71 foreach ($sections as $section) { 72 $output .= $this->start_section($section); 73 $output .= $this->questions_in_section($structure, $section, $contexts, $pagevars, $pageurl); 74 if ($section === $lastsection) { 75 $output .= \html_writer::start_div('last-add-menu'); 76 $output .= html_writer::tag('span', $this->add_menu_actions($structure, 0, 77 $pageurl, $contexts, $pagevars), array('class' => 'add-menu-outer')); 78 $output .= \html_writer::end_div(); 79 } 80 $output .= $this->end_section(); 81 } 82 83 $output .= $this->end_section_list(); 84 85 // Inialise the JavaScript. 86 $this->initialise_editing_javascript($quizobj->get_course(), $quizobj->get_quiz(), 87 $structure, $contexts, $pagevars, $pageurl); 88 89 // Include the contents of any other popups required. 90 if ($structure->can_be_edited()) { 91 $popups = ''; 92 93 $popups .= $this->question_bank_loading(); 94 $this->page->requires->yui_module('moodle-mod_quiz-quizquestionbank', 95 'M.mod_quiz.quizquestionbank.init', 96 array('class' => 'questionbank', 'cmid' => $structure->get_cmid())); 97 98 $popups .= $this->random_question_form($pageurl, $contexts, $pagevars); 99 $this->page->requires->yui_module('moodle-mod_quiz-randomquestion', 100 'M.mod_quiz.randomquestion.init'); 101 102 $output .= html_writer::div($popups, 'mod_quiz_edit_forms'); 103 104 // Include the question chooser. 105 $output .= $this->question_chooser(); 106 $this->page->requires->yui_module('moodle-mod_quiz-questionchooser', 'M.mod_quiz.init_questionchooser'); 107 } 108 109 return $output; 110 } 111 112 /** 113 * Render any warnings that might be required about the state of the quiz, 114 * e.g. if it has been attempted, or if the shuffle questions option is 115 * turned on. 116 * 117 * @param structure $structure the quiz structure. 118 * @return string HTML to output. 119 */ 120 public function quiz_state_warnings(structure $structure) { 121 $warnings = $structure->get_edit_page_warnings(); 122 123 if (empty($warnings)) { 124 return ''; 125 } 126 127 $output = array(); 128 foreach ($warnings as $warning) { 129 $output[] = \html_writer::tag('p', $warning); 130 } 131 return $this->box(implode("\n", $output), 'statusdisplay'); 132 } 133 134 /** 135 * Render the status bar. 136 * 137 * @param structure $structure the quiz structure. 138 * @return string HTML to output. 139 */ 140 public function quiz_information(structure $structure) { 141 list($currentstatus, $explanation) = $structure->get_dates_summary(); 142 143 $output = html_writer::span( 144 get_string('numquestionsx', 'quiz', $structure->get_question_count()), 145 'numberofquestions') . ' | ' . 146 html_writer::span($currentstatus, 'quizopeningstatus', 147 array('title' => $explanation)); 148 149 return html_writer::div($output, 'statusbar'); 150 } 151 152 /** 153 * Render the form for setting a quiz' overall grade 154 * 155 * @param \stdClass $quiz the quiz settings from the database. 156 * @param \moodle_url $pageurl the canonical URL of this page. 157 * @return string HTML to output. 158 */ 159 public function maximum_grade_input($quiz, \moodle_url $pageurl) { 160 $output = ''; 161 $output .= html_writer::start_div('maxgrade'); 162 $output .= html_writer::start_tag('form', array('method' => 'post', 'action' => 'edit.php', 163 'class' => 'quizsavegradesform')); 164 $output .= html_writer::start_tag('fieldset', array('class' => 'invisiblefieldset')); 165 $output .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => 'sesskey', 'value' => sesskey())); 166 $output .= html_writer::input_hidden_params($pageurl); 167 $a = html_writer::empty_tag('input', array('type' => 'text', 'id' => 'inputmaxgrade', 168 'name' => 'maxgrade', 'size' => ($quiz->decimalpoints + 2), 169 'value' => quiz_format_grade($quiz, $quiz->grade))); 170 $output .= html_writer::tag('label', get_string('maximumgradex', '', $a), 171 array('for' => 'inputmaxgrade')); 172 $output .= html_writer::empty_tag('input', array('type' => 'submit', 173 'name' => 'savechanges', 'value' => get_string('save', 'quiz'))); 174 $output .= html_writer::end_tag('fieldset'); 175 $output .= html_writer::end_tag('form'); 176 $output .= html_writer::end_tag('div'); 177 return $output; 178 } 179 180 /** 181 * Return the repaginate button 182 * @param structure $structure the structure of the quiz being edited. 183 * @param \moodle_url $pageurl the canonical URL of this page. 184 * @return string HTML to output. 185 */ 186 protected function repaginate_button(structure $structure, \moodle_url $pageurl) { 187 188 $header = html_writer::tag('span', get_string('repaginatecommand', 'quiz'), array('class' => 'repaginatecommand')); 189 $form = $this->repaginate_form($structure, $pageurl); 190 $containeroptions = array( 191 'class' => 'rpcontainerclass', 192 'cmid' => $structure->get_cmid(), 193 'header' => $header, 194 'form' => $form, 195 ); 196 197 $buttonoptions = array( 198 'type' => 'submit', 199 'name' => 'repaginate', 200 'id' => 'repaginatecommand', 201 'value' => get_string('repaginatecommand', 'quiz'), 202 ); 203 if (!$structure->can_be_repaginated()) { 204 $buttonoptions['disabled'] = 'disabled'; 205 } else { 206 $this->page->requires->yui_module('moodle-mod_quiz-repaginate', 'M.mod_quiz.repaginate.init'); 207 } 208 209 return html_writer::tag('div', 210 html_writer::empty_tag('input', $buttonoptions), $containeroptions); 211 } 212 213 /** 214 * Return the repaginate form 215 * @param structure $structure the structure of the quiz being edited. 216 * @param \moodle_url $pageurl the canonical URL of this page. 217 * @return string HTML to output. 218 */ 219 protected function repaginate_form(structure $structure, \moodle_url $pageurl) { 220 $perpage = array(); 221 $perpage[0] = get_string('allinone', 'quiz'); 222 for ($i = 1; $i <= 50; ++$i) { 223 $perpage[$i] = $i; 224 } 225 226 $hiddenurl = clone($pageurl); 227 $hiddenurl->param('sesskey', sesskey()); 228 229 $select = html_writer::select($perpage, 'questionsperpage', 230 $structure->get_questions_per_page(), false); 231 232 $buttonattributes = array('type' => 'submit', 'name' => 'repaginate', 'value' => get_string('go')); 233 234 $formcontent = html_writer::tag('form', html_writer::div( 235 html_writer::input_hidden_params($hiddenurl) . 236 get_string('repaginate', 'quiz', $select) . 237 html_writer::empty_tag('input', $buttonattributes) 238 ), array('action' => 'edit.php', 'method' => 'post')); 239 240 return html_writer::div($formcontent, '', array('id' => 'repaginatedialog')); 241 } 242 243 /** 244 * Render the total marks available for the quiz. 245 * 246 * @param \stdClass $quiz the quiz settings from the database. 247 * @return string HTML to output. 248 */ 249 public function total_marks($quiz) { 250 $totalmark = html_writer::span(quiz_format_grade($quiz, $quiz->sumgrades), 'mod_quiz_summarks'); 251 return html_writer::tag('span', 252 get_string('totalmarksx', 'quiz', $totalmark), 253 array('class' => 'totalpoints')); 254 } 255 256 /** 257 * Generate the starting container html for the start of a list of sections 258 * @return string HTML to output. 259 */ 260 protected function start_section_list() { 261 return html_writer::start_tag('ul', array('class' => 'slots')); 262 } 263 264 /** 265 * Generate the closing container html for the end of a list of sections 266 * @return string HTML to output. 267 */ 268 protected function end_section_list() { 269 return html_writer::end_tag('ul'); 270 } 271 272 /** 273 * Display the start of a section, before the questions. 274 * 275 * @param \stdClass $section The quiz_section entry from DB 276 * @return string HTML to output. 277 */ 278 protected function start_section($section) { 279 280 $output = ''; 281 $sectionstyle = ''; 282 283 $output .= html_writer::start_tag('li', array('id' => 'section-'.$section->id, 284 'class' => 'section main clearfix'.$sectionstyle, 'role' => 'region', 285 'aria-label' => $section->heading)); 286 287 $leftcontent = $this->section_left_content($section); 288 $output .= html_writer::div($leftcontent, 'left side'); 289 290 $rightcontent = $this->section_right_content($section); 291 $output .= html_writer::div($rightcontent, 'right side'); 292 $output .= html_writer::start_div('content'); 293 294 return $output; 295 } 296 297 /** 298 * Display the end of a section, after the questions. 299 * 300 * @return string HTML to output. 301 */ 302 protected function end_section() { 303 $output = html_writer::end_tag('div'); 304 $output .= html_writer::end_tag('li'); 305 306 return $output; 307 } 308 309 /** 310 * Generate the content to be displayed on the left part of a section. 311 * 312 * @param \stdClass $section The quiz_section entry from DB 313 * @return string HTML to output. 314 */ 315 protected function section_left_content($section) { 316 return $this->output->spacer(); 317 } 318 319 /** 320 * Generate the content to displayed on the right part of a section. 321 * 322 * @param \stdClass $section The quiz_section entry from DB 323 * @return string HTML to output. 324 */ 325 protected function section_right_content($section) { 326 return $this->output->spacer(); 327 } 328 329 /** 330 * Renders HTML to display the questions in a section of the quiz. 331 * 332 * This function calls {@link core_course_renderer::quiz_section_question()} 333 * 334 * @param structure $structure object containing the structure of the quiz. 335 * @param \stdClass $section information about the section. 336 * @param \question_edit_contexts $contexts the relevant question bank contexts. 337 * @param array $pagevars the variables from {@link \question_edit_setup()}. 338 * @param \moodle_url $pageurl the canonical URL of this page. 339 * @return string HTML to output. 340 */ 341 public function questions_in_section(structure $structure, $section, 342 $contexts, $pagevars, $pageurl) { 343 344 $output = ''; 345 foreach ($structure->get_questions_in_section($section->id) as $question) { 346 $output .= $this->question_row($structure, $question, $contexts, $pagevars, $pageurl); 347 } 348 349 return html_writer::tag('ul', $output, array('class' => 'section img-text')); 350 } 351 352 /** 353 * Displays one question with the surrounding controls. 354 * 355 * @param structure $structure object containing the structure of the quiz. 356 * @param \stdClass $question data from the question and quiz_slots tables. 357 * @param \question_edit_contexts $contexts the relevant question bank contexts. 358 * @param array $pagevars the variables from {@link \question_edit_setup()}. 359 * @param \moodle_url $pageurl the canonical URL of this page. 360 * @return string HTML to output. 361 */ 362 public function question_row(structure $structure, $question, $contexts, $pagevars, $pageurl) { 363 $output = ''; 364 365 $output .= $this->page_row($structure, $question, $contexts, $pagevars, $pageurl); 366 367 // Page split/join icon. 368 $joinhtml = ''; 369 if ($structure->can_be_edited() && !$structure->is_last_slot_in_quiz($question->slot)) { 370 $joinhtml = $this->page_split_join_button($structure->get_quiz(), 371 $question, !$structure->is_last_slot_on_page($question->slot)); 372 } 373 374 // Question HTML. 375 $questionhtml = $this->question($structure, $question, $pageurl); 376 $questionclasses = 'activity ' . $question->qtype . ' qtype_' . $question->qtype . ' slot'; 377 378 $output .= html_writer::tag('li', $questionhtml . $joinhtml, 379 array('class' => $questionclasses, 'id' => 'slot-' . $question->slotid)); 380 381 return $output; 382 } 383 384 /** 385 * Displays one question with the surrounding controls. 386 * 387 * @param structure $structure object containing the structure of the quiz. 388 * @param \stdClass $question data from the question and quiz_slots tables. 389 * @param \question_edit_contexts $contexts the relevant question bank contexts. 390 * @param array $pagevars the variables from {@link \question_edit_setup()}. 391 * @param \moodle_url $pageurl the canonical URL of this page. 392 * @return string HTML to output. 393 */ 394 public function page_row(structure $structure, $question, $contexts, $pagevars, $pageurl) { 395 $output = ''; 396 397 // Put page in a span for easier styling. 398 $page = html_writer::tag('span', get_string('page') . ' ' . $question->page, 399 array('class' => 'text')); 400 401 if ($structure->is_first_slot_on_page($question->slot)) { 402 // Add the add-menu at the page level. 403 $addmenu = html_writer::tag('span', $this->add_menu_actions($structure, 404 $question->page, $pageurl, $contexts, $pagevars), 405 array('class' => 'add-menu-outer')); 406 407 $addquestionform = $this->add_question_form($structure, 408 $question->page, $pageurl, $pagevars); 409 410 $output .= html_writer::tag('li', $page . $addmenu . $addquestionform, 411 array('class' => 'pagenumber activity yui3-dd-drop page', 'id' => 'page-' . $question->page)); 412 } 413 414 return $output; 415 } 416 417 /** 418 * Returns the add menu that is output once per page. 419 * @param structure $structure object containing the structure of the quiz. 420 * @param int $page the page number that this menu will add to. 421 * @param \moodle_url $pageurl the canonical URL of this page. 422 * @param \question_edit_contexts $contexts the relevant question bank contexts. 423 * @param array $pagevars the variables from {@link \question_edit_setup()}. 424 * @return string HTML to output. 425 */ 426 public function add_menu_actions(structure $structure, $page, \moodle_url $pageurl, 427 \question_edit_contexts $contexts, array $pagevars) { 428 429 $actions = $this->edit_menu_actions($structure, $page, $pageurl, $pagevars); 430 if (empty($actions)) { 431 return ''; 432 } 433 $menu = new \action_menu(); 434 $menu->set_alignment(\action_menu::TR, \action_menu::BR); 435 $menu->set_constraint('.mod-quiz-edit-content'); 436 $trigger = html_writer::tag('span', get_string('add', 'quiz'), array('class' => 'add-menu')); 437 $menu->set_menu_trigger($trigger); 438 // The menu appears within an absolutely positioned element causing width problems. 439 // Make sure no-wrap is set so that we don't get a squashed menu. 440 $menu->set_nowrap_on_items(true); 441 442 // Disable the link if quiz has attempts. 443 if (!$structure->can_be_edited()) { 444 return $this->render($menu); 445 } 446 447 foreach ($actions as $action) { 448 if ($action instanceof \action_menu_link) { 449 $action->add_class('add-menu'); 450 } 451 $menu->add($action); 452 } 453 $menu->attributes['class'] .= ' page-add-actions commands'; 454 455 // Prioritise the menu ahead of all other actions. 456 $menu->prioritise = true; 457 458 return $this->render($menu); 459 } 460 461 /** 462 * Returns the list of actions to go in the add menu. 463 * @param structure $structure object containing the structure of the quiz. 464 * @param int $page the page number that this menu will add to. 465 * @param \moodle_url $pageurl the canonical URL of this page. 466 * @param array $pagevars the variables from {@link \question_edit_setup()}. 467 * @return array the actions. 468 */ 469 public function edit_menu_actions(structure $structure, $page, 470 \moodle_url $pageurl, array $pagevars) { 471 $questioncategoryid = question_get_category_id_from_pagevars($pagevars); 472 static $str; 473 if (!isset($str)) { 474 $str = get_strings(array('addaquestion', 'addarandomquestion', 475 'addarandomselectedquestion', 'questionbank'), 'quiz'); 476 } 477 478 // Get section, page, slotnumber and maxmark. 479 $actions = array(); 480 481 // Add a new question to the quiz. 482 $returnurl = new \moodle_url($pageurl, array('addonpage' => $page)); 483 $params = array('returnurl' => $returnurl->out_as_local_url(false), 484 'cmid' => $structure->get_cmid(), 'category' => $questioncategoryid, 485 'addonpage' => $page, 'appendqnumstring' => 'addquestion'); 486 487 $actions['addaquestion'] = new \action_menu_link_secondary( 488 new \moodle_url('/question/addquestion.php', $params), 489 new \pix_icon('t/add', $str->addaquestion, 'moodle', array('class' => 'iconsmall', 'title' => '')), 490 $str->addaquestion, array('class' => 'cm-edit-action addquestion', 'data-action' => 'addquestion') 491 ); 492 493 // Call question bank. 494 $icon = new \pix_icon('t/add', $str->questionbank, 'moodle', array('class' => 'iconsmall', 'title' => '')); 495 $title = get_string('addquestionfrombanktopage', 'quiz', $page); 496 $attributes = array('class' => 'cm-edit-action questionbank', 497 'data-header' => $title, 'data-action' => 'questionbank', 'data-addonpage' => $page); 498 $actions['questionbank'] = new \action_menu_link_secondary($pageurl, $icon, $str->questionbank, $attributes); 499 500 // Add a random question. 501 $returnurl = new \moodle_url('/mod/quiz/edit.php', array('cmid' => $structure->get_cmid(), 'data-addonpage' => $page)); 502 $params = array('returnurl' => $returnurl, 'cmid' => $structure->get_cmid(), 'appendqnumstring' => 'addarandomquestion'); 503 $url = new \moodle_url('/mod/quiz/addrandom.php', $params); 504 $icon = new \pix_icon('t/add', $str->addarandomquestion, 'moodle', array('class' => 'iconsmall', 'title' => '')); 505 $attributes = array('class' => 'cm-edit-action addarandomquestion', 'data-action' => 'addarandomquestion'); 506 $title = get_string('addrandomquestiontopage', 'quiz', $page); 507 $attributes = array_merge(array('data-header' => $title, 'data-addonpage' => $page), $attributes); 508 $actions['addarandomquestion'] = new \action_menu_link_secondary($url, $icon, $str->addarandomquestion, $attributes); 509 510 return $actions; 511 } 512 513 /** 514 * Render the form that contains the data for adding a new question to the quiz. 515 * 516 * @param structure $structure object containing the structure of the quiz. 517 * @param int $page the page number that this menu will add to. 518 * @param \moodle_url $pageurl the canonical URL of this page. 519 * @param array $pagevars the variables from {@link \question_edit_setup()}. 520 * @return string HTML to output. 521 */ 522 protected function add_question_form(structure $structure, $page, \moodle_url $pageurl, array $pagevars) { 523 524 $questioncategoryid = question_get_category_id_from_pagevars($pagevars); 525 526 $output = html_writer::tag('input', null, 527 array('type' => 'hidden', 'name' => 'returnurl', 528 'value' => $pageurl->out_as_local_url(false, array('addonpage' => $page)))); 529 $output .= html_writer::tag('input', null, 530 array('type' => 'hidden', 'name' => 'cmid', 'value' => $structure->get_cmid())); 531 $output .= html_writer::tag('input', null, 532 array('type' => 'hidden', 'name' => 'appendqnumstring', 'value' => 'addquestion')); 533 $output .= html_writer::tag('input', null, 534 array('type' => 'hidden', 'name' => 'category', 'value' => $questioncategoryid)); 535 536 return html_writer::tag('form', html_writer::div($output), 537 array('class' => 'addnewquestion', 'method' => 'post', 538 'action' => new \moodle_url('/question/addquestion.php'))); 539 } 540 541 /** 542 * Display a question. 543 * 544 * @param structure $structure object containing the structure of the quiz. 545 * @param \stdClass $question data from the question and quiz_slots tables. 546 * @param \moodle_url $pageurl the canonical URL of this page. 547 * @return string HTML to output. 548 */ 549 public function question(structure $structure, $question, \moodle_url $pageurl) { 550 $output = ''; 551 552 $output .= html_writer::start_tag('div'); 553 554 if ($structure->can_be_edited()) { 555 $output .= $this->question_move_icon($question); 556 } 557 558 $output .= html_writer::start_div('mod-indent-outer'); 559 $output .= $this->question_number($question->displayednumber); 560 561 // This div is used to indent the content. 562 $output .= html_writer::div('', 'mod-indent'); 563 564 // Display the link to the question (or do nothing if question has no url). 565 if ($question->qtype == 'random') { 566 $questionname = $this->random_question($structure, $question, $pageurl); 567 } else { 568 $questionname = $this->question_name($structure, $question, $pageurl); 569 } 570 571 // Start the div for the activity title, excluding the edit icons. 572 $output .= html_writer::start_div('activityinstance'); 573 $output .= $questionname; 574 575 // Closing the tag which contains everything but edit icons. Content part of the module should not be part of this. 576 $output .= html_writer::end_tag('div'); // .activityinstance. 577 578 // Action icons. 579 $questionicons = ''; 580 $questionicons .= $this->question_preview_icon($structure->get_quiz(), $question); 581 if ($structure->can_be_edited()) { 582 $questionicons .= $this->question_remove_icon($question, $pageurl); 583 } 584 $questionicons .= $this->marked_out_of_field($structure->get_quiz(), $question); 585 $output .= html_writer::span($questionicons, 'actions'); // Required to add js spinner icon. 586 587 // End of indentation div. 588 $output .= html_writer::end_tag('div'); 589 $output .= html_writer::end_tag('div'); 590 591 return $output; 592 } 593 594 /** 595 * Render the move icon. 596 * 597 * @param \stdClass $question data from the question and quiz_slots tables. 598 * @return string The markup for the move action, or an empty string if not available. 599 */ 600 public function question_move_icon($question) { 601 return html_writer::link(new \moodle_url('#'), 602 $this->pix_icon('i/dragdrop', get_string('move'), 'moodle', array('class' => 'iconsmall', 'title' => '')), 603 array('class' => 'editing_move', 'data-action' => 'move') 604 ); 605 } 606 607 /** 608 * Output the question number. 609 * @param string $number The number, or 'i'. 610 * @return string HTML to output. 611 */ 612 public function question_number($number) { 613 if (is_numeric($number)) { 614 $number = html_writer::span(get_string('question'), 'accesshide') . 615 ' ' . $number; 616 } 617 return html_writer::tag('span', $number, array('class' => 'slotnumber')); 618 } 619 620 /** 621 * Render the preview icon. 622 * 623 * @param \stdClass $quiz the quiz settings from the database. 624 * @param \stdClass $question data from the question and quiz_slots tables. 625 * @param bool $label if true, show the preview question label after the icon 626 * @return string HTML to output. 627 */ 628 public function question_preview_icon($quiz, $question, $label = null) { 629 $url = quiz_question_preview_url($quiz, $question); 630 631 // Do we want a label? 632 $strpreviewlabel = ''; 633 if ($label) { 634 $strpreviewlabel = ' ' . get_string('preview', 'quiz'); 635 } 636 637 // Build the icon. 638 $strpreviewquestion = get_string('previewquestion', 'quiz'); 639 $image = $this->pix_icon('t/preview', $strpreviewquestion); 640 641 $action = new \popup_action('click', $url, 'questionpreview', 642 question_preview_popup_params()); 643 644 return $this->action_link($url, $image . $strpreviewlabel, $action, 645 array('title' => $strpreviewquestion, 'class' => 'preview')); 646 } 647 648 /** 649 * Render an icon to remove a question from the quiz. 650 * 651 * @param object $question The module to produce a move button for. 652 * @param \moodle_url $pageurl the canonical URL of the edit page. 653 * @return string HTML to output. 654 */ 655 public function question_remove_icon($question, $pageurl) { 656 $url = new \moodle_url($pageurl, array('sesskey' => sesskey(), 'remove' => $question->slot)); 657 $strdelete = get_string('delete'); 658 659 $image = $this->pix_icon('t/delete', $strdelete); 660 661 return $this->action_link($url, $image, null, array('title' => $strdelete, 662 'class' => 'cm-edit-action editing_delete', 'data-action' => 'delete')); 663 } 664 665 /** 666 * Display an icon to split or join two pages of the quiz. 667 * 668 * @param \stdClass $quiz the quiz settings from the database. 669 * @param \stdClass $question data from the question and quiz_slots tables. 670 * @param bool $insertpagebreak if true, show an insert page break icon. 671 * else show a join pages icon. 672 * @return string HTML to output. 673 */ 674 public function page_split_join_button($quiz, $question, $insertpagebreak) { 675 $url = new \moodle_url('repaginate.php', array('cmid' => $quiz->cmid, 'quizid' => $quiz->id, 676 'slot' => $question->slot, 'repag' => $insertpagebreak ? 2 : 1, 'sesskey' => sesskey())); 677 678 if ($insertpagebreak) { 679 $title = get_string('addpagebreak', 'quiz'); 680 $image = $this->pix_icon('e/insert_page_break', $title); 681 $action = 'addpagebreak'; 682 } else { 683 $title = get_string('removepagebreak', 'quiz'); 684 $image = $this->pix_icon('e/remove_page_break', $title); 685 $action = 'removepagebreak'; 686 } 687 688 // Disable the link if quiz has attempts. 689 $disabled = null; 690 if (quiz_has_attempts($quiz->id)) { 691 $disabled = "disabled"; 692 } 693 return html_writer::span($this->action_link($url, $image, null, array('title' => $title, 694 'class' => 'page_split_join cm-edit-action', 'disabled' => $disabled, 'data-action' => $action)), 695 'page_split_join_wrapper'); 696 } 697 698 /** 699 * Renders html to display a name with the link to the question on a quiz edit page 700 * 701 * If the user does not have permission to edi the question, it is rendered 702 * without a link 703 * 704 * @param structure $structure object containing the structure of the quiz. 705 * @param \stdClass $question data from the question and quiz_slots tables. 706 * @param \moodle_url $pageurl the canonical URL of this page. 707 * @return string HTML to output. 708 */ 709 public function question_name(structure $structure, $question, $pageurl) { 710 $output = ''; 711 712 $editurl = new \moodle_url('/question/question.php', array( 713 'returnurl' => $pageurl->out_as_local_url(), 714 'cmid' => $structure->get_cmid(), 'id' => $question->id)); 715 716 $instancename = quiz_question_tostring($question); 717 718 $qtype = \question_bank::get_qtype($question->qtype, false); 719 $namestr = $qtype->local_name(); 720 721 $icon = $this->pix_icon('icon', $namestr, $qtype->plugin_name(), array('title' => $namestr, 722 'class' => 'icon activityicon', 'alt' => ' ', 'role' => 'presentation')); 723 724 $editicon = $this->pix_icon('t/edit', '', 'moodle', array('title' => '')); 725 726 // Need plain question name without html tags for link title. 727 $title = shorten_text(format_string($question->name), 100); 728 729 // Display the link itself. 730 $activitylink = $icon . html_writer::tag('span', $editicon . $instancename, array('class' => 'instancename')); 731 $output .= html_writer::link($editurl, $activitylink, 732 array('title' => get_string('editquestion', 'quiz').' '.$title)); 733 734 return $output; 735 } 736 737 /** 738 * Renders html to display a random question the link to edit the configuration 739 * and also to see that category in the question bank. 740 * 741 * @param structure $structure object containing the structure of the quiz. 742 * @param \stdClass $question data from the question and quiz_slots tables. 743 * @param \moodle_url $pageurl the canonical URL of this page. 744 * @return string HTML to output. 745 */ 746 public function random_question(structure $structure, $question, $pageurl) { 747 748 $editurl = new \moodle_url('/question/question.php', array( 749 'returnurl' => $pageurl->out_as_local_url(), 750 'cmid' => $structure->get_cmid(), 'id' => $question->id)); 751 752 $temp = clone($question); 753 $temp->questiontext = ''; 754 $instancename = quiz_question_tostring($temp); 755 756 $configuretitle = get_string('configurerandomquestion', 'quiz'); 757 $qtype = \question_bank::get_qtype($question->qtype, false); 758 $namestr = $qtype->local_name(); 759 $icon = $this->pix_icon('icon', $namestr, $qtype->plugin_name(), array('title' => $namestr, 760 'class' => 'icon activityicon', 'alt' => ' ', 'role' => 'presentation')); 761 762 $editicon = $this->pix_icon('t/edit', $configuretitle, 'moodle', array('title' => '')); 763 764 // If this is a random question, display a link to show the questions 765 // selected from in the question bank. 766 $qbankurl = new \moodle_url('/question/edit.php', array( 767 'cmid' => $structure->get_cmid(), 768 'cat' => $question->category . ',' . $question->contextid, 769 'recurse' => !empty($question->questiontext))); 770 $qbanklink = ' ' . \html_writer::link($qbankurl, 771 get_string('seequestions', 'quiz'), array('class' => 'mod_quiz_random_qbank_link')); 772 773 return html_writer::link($editurl, $icon . $editicon, array('title' => $configuretitle)) . 774 ' ' . $instancename . ' ' . $qbanklink; 775 } 776 777 /** 778 * Display the 'marked out of' information for a question. 779 * Along with the regrade action. 780 * @param \stdClass $quiz the quiz settings from the database. 781 * @param \stdClass $question data from the question and quiz_slots tables. 782 * @return string HTML to output. 783 */ 784 public function marked_out_of_field($quiz, $question) { 785 if ($question->length == 0) { 786 $output = html_writer::span('', 787 'instancemaxmark decimalplaces_' . quiz_get_grade_format($quiz)); 788 789 $output .= html_writer::span( 790 $this->pix_icon('spacer', '', 'moodle', array('class' => 'editicon visibleifjs', 'title' => '')), 791 'editing_maxmark'); 792 return html_writer::span($output, 'instancemaxmarkcontainer infoitem'); 793 } 794 795 $output = html_writer::span(quiz_format_question_grade($quiz, $question->maxmark), 796 'instancemaxmark decimalplaces_' . quiz_get_grade_format($quiz), 797 array('title' => get_string('maxmark', 'quiz'))); 798 799 $output .= html_writer::span( 800 html_writer::link( 801 new \moodle_url('#'), 802 $this->pix_icon('t/editstring', '', 'moodle', array('class' => 'editicon visibleifjs', 'title' => '')), 803 array( 804 'class' => 'editing_maxmark', 805 'data-action' => 'editmaxmark', 806 'title' => get_string('editmaxmark', 'quiz'), 807 ) 808 ) 809 ); 810 return html_writer::span($output, 'instancemaxmarkcontainer'); 811 } 812 813 /** 814 * Render the question type chooser dialogue. 815 * @return string HTML to output. 816 */ 817 public function question_chooser() { 818 $container = html_writer::div(print_choose_qtype_to_add_form(array(), null, false), '', 819 array('id' => 'qtypechoicecontainer')); 820 return html_writer::div($container, 'createnewquestion'); 821 } 822 823 /** 824 * Render the contents of the question bank pop-up in its initial state, 825 * when it just contains a loading progress indicator. 826 * @return string HTML to output. 827 */ 828 public function question_bank_loading() { 829 return html_writer::div(html_writer::empty_tag('img', 830 array('alt' => 'loading', 'class' => 'loading-icon', 'src' => $this->pix_url('i/loading'))), 831 'questionbankloading'); 832 } 833 834 /** 835 * Return random question form. 836 * @param \moodle_url $thispageurl the canonical URL of this page. 837 * @param \question_edit_contexts $contexts the relevant question bank contexts. 838 * @param array $pagevars the variables from {@link \question_edit_setup()}. 839 * @return string HTML to output. 840 */ 841 protected function random_question_form(\moodle_url $thispageurl, \question_edit_contexts $contexts, array $pagevars) { 842 843 if (!$contexts->have_cap('moodle/question:useall')) { 844 return ''; 845 } 846 $randomform = new \quiz_add_random_form(new \moodle_url('/mod/quiz/addrandom.php'), 847 array('contexts' => $contexts, 'cat' => $pagevars['cat'])); 848 $randomform->set_data(array( 849 'category' => $pagevars['cat'], 850 'returnurl' => $thispageurl->out_as_local_url(true), 851 'randomnumber' => 1, 852 'cmid' => $thispageurl->param('cmid'), 853 )); 854 return html_writer::div($randomform->render(), 'randomquestionformforpopup'); 855 } 856 857 /** 858 * Initialise the JavaScript for the general editing. (JavaScript for popups 859 * is handled with the specific code for those.) 860 * 861 * @param \stdClass $course the course settings from the database. 862 * @param \stdClass $quiz the quiz settings from the database. 863 * @param structure $structure object containing the structure of the quiz. 864 * @param \question_edit_contexts $contexts the relevant question bank contexts. 865 * @param array $pagevars the variables from {@link \question_edit_setup()}. 866 * @param \moodle_url $pageurl the canonical URL of this page. 867 * @return bool Always returns true 868 */ 869 protected function initialise_editing_javascript($course, $quiz, structure $structure, 870 \question_edit_contexts $contexts, array $pagevars, \moodle_url $pageurl) { 871 872 $config = new \stdClass(); 873 $config->resourceurl = '/mod/quiz/edit_rest.php'; 874 $config->sectionurl = '/mod/quiz/edit_rest.php'; 875 $config->pageparams = array(); 876 $config->questiondecimalpoints = $quiz->questiondecimalpoints; 877 $config->pagehtml = $this->new_page_template($structure, $contexts, $pagevars, $pageurl); 878 $config->addpageiconhtml = $this->add_page_icon_template($structure, $quiz); 879 880 $this->page->requires->yui_module('moodle-mod_quiz-toolboxes', 881 'M.mod_quiz.init_resource_toolbox', 882 array(array( 883 'courseid' => $course->id, 884 'quizid' => $quiz->id, 885 'ajaxurl' => $config->resourceurl, 886 'config' => $config, 887 )) 888 ); 889 unset($config->pagehtml); 890 unset($config->addpageiconhtml); 891 892 $this->page->requires->yui_module('moodle-mod_quiz-toolboxes', 893 'M.mod_quiz.init_section_toolbox', 894 array(array( 895 'courseid' => $course->id, 896 'quizid' => $quiz->id, 897 'format' => $course->format, 898 'ajaxurl' => $config->sectionurl, 899 'config' => $config, 900 )) 901 ); 902 903 $this->page->requires->yui_module('moodle-mod_quiz-dragdrop', 'M.mod_quiz.init_section_dragdrop', 904 array(array( 905 'courseid' => $course->id, 906 'quizid' => $quiz->id, 907 'ajaxurl' => $config->sectionurl, 908 'config' => $config, 909 )), null, true); 910 911 $this->page->requires->yui_module('moodle-mod_quiz-dragdrop', 'M.mod_quiz.init_resource_dragdrop', 912 array(array( 913 'courseid' => $course->id, 914 'quizid' => $quiz->id, 915 'ajaxurl' => $config->resourceurl, 916 'config' => $config, 917 )), null, true); 918 919 // Require various strings for the command toolbox. 920 $this->page->requires->strings_for_js(array( 921 'clicktohideshow', 922 'deletechecktype', 923 'deletechecktypename', 924 'edittitle', 925 'edittitleinstructions', 926 'emptydragdropregion', 927 'hide', 928 'markedthistopic', 929 'markthistopic', 930 'move', 931 'movecontent', 932 'moveleft', 933 'movesection', 934 'page', 935 'question', 936 'selectall', 937 'show', 938 'tocontent', 939 ), 'moodle'); 940 941 $this->page->requires->strings_for_js(array( 942 'addpagebreak', 943 'confirmremovequestion', 944 'dragtoafter', 945 'dragtostart', 946 'numquestionsx', 947 'removepagebreak', 948 ), 'quiz'); 949 950 foreach (\question_bank::get_all_qtypes() as $qtype => $notused) { 951 $this->page->requires->string_for_js('pluginname', 'qtype_' . $qtype); 952 } 953 954 return true; 955 } 956 957 /** 958 * HTML for a page, with ids stripped, so it can be used as a javascript template. 959 * 960 * @param structure $structure object containing the structure of the quiz. 961 * @param \question_edit_contexts $contexts the relevant question bank contexts. 962 * @param array $pagevars the variables from {@link \question_edit_setup()}. 963 * @param \moodle_url $pageurl the canonical URL of this page. 964 * @return string HTML for a new page. 965 */ 966 protected function new_page_template(structure $structure, 967 \question_edit_contexts $contexts, array $pagevars, \moodle_url $pageurl) { 968 if (!$structure->has_questions()) { 969 return ''; 970 } 971 972 $question = $structure->get_question_in_slot(1); 973 $pagehtml = $this->page_row($structure, $question, $contexts, $pagevars, $pageurl); 974 975 // Normalise the page number. 976 $pagenumber = $question->page; 977 $strcontexts = array(); 978 $strcontexts[] = 'page-'; 979 $strcontexts[] = get_string('page') . ' '; 980 $strcontexts[] = 'addonpage%3D'; 981 $strcontexts[] = 'addonpage='; 982 $strcontexts[] = 'addonpage="'; 983 $strcontexts[] = get_string('addquestionfrombanktopage', 'quiz', ''); 984 $strcontexts[] = 'data-addonpage%3D'; 985 $strcontexts[] = 'action-menu-'; 986 987 foreach ($strcontexts as $strcontext) { 988 $pagehtml = str_replace($strcontext . $pagenumber, $strcontext . '%%PAGENUMBER%%', $pagehtml); 989 } 990 991 return $pagehtml; 992 } 993 994 /** 995 * HTML for a page, with ids stripped, so it can be used as a javascript template. 996 * 997 * @param structure $structure object containing the structure of the quiz. 998 * @param \stdClass $quiz the quiz settings. 999 * @return string HTML for a new icon 1000 */ 1001 protected function add_page_icon_template(structure $structure, $quiz) { 1002 1003 if (!$structure->has_questions()) { 1004 return ''; 1005 } 1006 1007 $question = $structure->get_question_in_slot(1); 1008 $html = $this->page_split_join_button($quiz, $question, true); 1009 return str_replace('&slot=1&', '&slot=%%SLOT%%&', $html); 1010 } 1011 1012 /** 1013 * Return the contents of the question bank, to be displayed in the question-bank pop-up. 1014 * 1015 * @param \mod_quiz\question\bank\custom_view $questionbank the question bank view object. 1016 * @param array $pagevars the variables from {@link \question_edit_setup()}. 1017 * @return string HTML to output / send back in response to an AJAX request. 1018 */ 1019 public function question_bank_contents(\mod_quiz\question\bank\custom_view $questionbank, array $pagevars) { 1020 1021 $qbank = $questionbank->render('editq', $pagevars['qpage'], $pagevars['qperpage'], 1022 $pagevars['cat'], $pagevars['recurse'], $pagevars['showhidden'], $pagevars['qbshowtext']); 1023 return html_writer::div(html_writer::div($qbank, 'bd'), 'questionbankformforpopup'); 1024 } 1025 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Fri Nov 28 20:29:05 2014 | Cross-referenced by PHPXref 0.7.1 |