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 namespace mod_quiz\output; 18 19 use mod_quiz\quiz_attempt; 20 use moodle_url; 21 use question_attempt; 22 use question_display_options; 23 use question_state; 24 use renderable; 25 use user_picture; 26 27 /** 28 * Represents the navigation panel, and builds a {@see block_contents} to allow it to be output. 29 * 30 * This class is not currently renderable or templatable, but it probably should be in the future, 31 * which is why it is already in the output namespace. 32 * 33 * @package mod_quiz 34 * @category output 35 * @copyright 2008 Tim Hunt 36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 */ 38 abstract class navigation_panel_base { 39 /** @var quiz_attempt */ 40 protected $attemptobj; 41 /** @var question_display_options */ 42 protected $options; 43 /** @var integer */ 44 protected $page; 45 /** @var boolean */ 46 protected $showall; 47 48 /** 49 * Constructor. 50 * 51 * @param quiz_attempt $attemptobj construct the panel for this attempt. 52 * @param question_display_options $options display options in force. 53 * @param int $page which page of the quiz attempt is being shown, -1 if all. 54 * @param bool $showall whether all pages are being shown at once. 55 */ 56 public function __construct(quiz_attempt $attemptobj, 57 question_display_options $options, $page, $showall) { 58 $this->attemptobj = $attemptobj; 59 $this->options = $options; 60 $this->page = $page; 61 $this->showall = $showall; 62 } 63 64 /** 65 * Get the buttons and section headings to go in the quiz navigation block. 66 * 67 * @return renderable[] the buttons, possibly interleaved with section headings. 68 */ 69 public function get_question_buttons() { 70 $buttons = []; 71 foreach ($this->attemptobj->get_slots() as $slot) { 72 $heading = $this->attemptobj->get_heading_before_slot($slot); 73 if (!is_null($heading)) { 74 $sections = $this->attemptobj->get_quizobj()->get_sections(); 75 if (!(empty($heading) && count($sections) == 1)) { 76 $buttons[] = new navigation_section_heading(format_string($heading)); 77 } 78 } 79 80 $qa = $this->attemptobj->get_question_attempt($slot); 81 $showcorrectness = $this->options->correctness && $qa->has_marks(); 82 83 $button = new navigation_question_button(); 84 $button->id = 'quiznavbutton' . $slot; 85 $button->isrealquestion = $this->attemptobj->is_real_question($slot); 86 $button->number = $this->attemptobj->get_question_number($slot); 87 $button->stateclass = $qa->get_state_class($showcorrectness); 88 $button->navmethod = $this->attemptobj->get_navigation_method(); 89 if (!$showcorrectness && $button->stateclass === 'notanswered') { 90 $button->stateclass = 'complete'; 91 } 92 $button->statestring = $this->get_state_string($qa, $showcorrectness); 93 $button->page = $this->attemptobj->get_question_page($slot); 94 $button->currentpage = $this->showall || $button->page == $this->page; 95 $button->flagged = $qa->is_flagged(); 96 $button->url = $this->get_question_url($slot); 97 if ($this->attemptobj->is_blocked_by_previous_question($slot)) { 98 $button->url = null; 99 $button->stateclass = 'blocked'; 100 $button->statestring = get_string('questiondependsonprevious', 'quiz'); 101 } 102 $buttons[] = $button; 103 } 104 105 return $buttons; 106 } 107 108 /** 109 * Get the human-readable description of the current state of a particular question. 110 * 111 * @param question_attempt $qa the attempt at the question of interest. 112 * @param bool $showcorrectness whether the current use is allowed to see if they have got the question right. 113 * @return string Human-readable description of the state. 114 */ 115 protected function get_state_string(question_attempt $qa, $showcorrectness) { 116 if ($qa->get_question(false)->length > 0) { 117 return $qa->get_state_string($showcorrectness); 118 } 119 120 // Special case handling for 'information' items. 121 if ($qa->get_state() == question_state::$todo) { 122 return get_string('notyetviewed', 'quiz'); 123 } else { 124 return get_string('viewed', 'quiz'); 125 } 126 } 127 128 /** 129 * Hook for subclasses to override to do output above the question buttons. 130 * 131 * @param renderer $output the quiz renderer to use. 132 * @return string HTML to output. 133 */ 134 public function render_before_button_bits(renderer $output) { 135 return ''; 136 } 137 138 /** 139 * Hook that subclasses must override to do output after the question buttons. 140 * 141 * @param renderer $output the quiz renderer to use. 142 * @return string HTML to output. 143 */ 144 abstract public function render_end_bits(renderer $output); 145 146 /** 147 * Render the restart preview button. 148 * 149 * @param renderer $output the quiz renderer to use. 150 * @return string HTML to output. 151 */ 152 protected function render_restart_preview_link($output) { 153 if (!$this->attemptobj->is_own_preview()) { 154 return ''; 155 } 156 return $output->restart_preview_button(new moodle_url( 157 $this->attemptobj->start_attempt_url(), ['forcenew' => true])); 158 } 159 160 /** 161 * Get the URL to navigate to a particular question. 162 * 163 * @param int $slot slot number, to identify the question. 164 * @return moodle_url|null URL if the user can navigate there, or null if they cannot. 165 */ 166 abstract protected function get_question_url($slot); 167 168 /** 169 * Get the user picture which should be displayed, if required. 170 * 171 * @return user_picture|null 172 */ 173 public function user_picture() { 174 global $DB; 175 if ($this->attemptobj->get_quiz()->showuserpicture == QUIZ_SHOWIMAGE_NONE) { 176 return null; 177 } 178 $user = $DB->get_record('user', ['id' => $this->attemptobj->get_userid()]); 179 $userpicture = new user_picture($user); 180 $userpicture->courseid = $this->attemptobj->get_courseid(); 181 if ($this->attemptobj->get_quiz()->showuserpicture == QUIZ_SHOWIMAGE_LARGE) { 182 $userpicture->size = true; 183 } 184 return $userpicture; 185 } 186 187 /** 188 * Return 'allquestionsononepage' as CSS class name when $showall is set, 189 * otherwise, return 'multipages' as CSS class name. 190 * 191 * @return string, CSS class name 192 */ 193 public function get_button_container_class() { 194 // Quiz navigation is set on 'Show all questions on one page'. 195 if ($this->showall) { 196 return 'allquestionsononepage'; 197 } 198 // Quiz navigation is set on 'Show one page at a time'. 199 return 'multipages'; 200 } 201 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body