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 * Defines the renderer base classes for question types. 19 * 20 * @package moodlecore 21 * @subpackage questiontypes 22 * @copyright 2009 The Open University 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 30 /** 31 * Renderer base classes for question types. 32 * 33 * @copyright 2009 The Open University 34 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 */ 36 abstract class qtype_renderer extends plugin_renderer_base { 37 /** 38 * Generate the display of the formulation part of the question. This is the 39 * area that contains the quetsion text, and the controls for students to 40 * input their answers. Some question types also embed bits of feedback, for 41 * example ticks and crosses, in this area. 42 * 43 * @param question_attempt $qa the question attempt to display. 44 * @param question_display_options $options controls what should and should not be displayed. 45 * @return string HTML fragment. 46 */ 47 public function formulation_and_controls(question_attempt $qa, 48 question_display_options $options) { 49 return $qa->get_question()->format_questiontext($qa); 50 } 51 52 /** 53 * In the question output there are some class="accesshide" headers to help 54 * screen-readers. This method returns the text to use for the heading above 55 * the formulation_and_controls section. 56 * @return string to use as the heading. 57 */ 58 public function formulation_heading() { 59 return get_string('questiontext', 'question'); 60 } 61 62 /** 63 * Output hidden form fields to clear any wrong parts of the student's response. 64 * 65 * This method will only be called if the question is in read-only mode. 66 * @param question_attempt $qa the question attempt to display. 67 * @return string HTML fragment. 68 */ 69 public function clear_wrong(question_attempt $qa) { 70 $response = $qa->get_last_qt_data(); 71 if (!$response) { 72 return ''; 73 } 74 $cleanresponse = $qa->get_question()->clear_wrong_from_response($response); 75 $output = ''; 76 foreach ($cleanresponse as $name => $value) { 77 $attr = array( 78 'type' => 'hidden', 79 'name' => $qa->get_qt_field_name($name), 80 'value' => s($value), 81 ); 82 $output .= html_writer::empty_tag('input', $attr); 83 } 84 return $output; 85 } 86 87 /** 88 * Generate the display of the outcome part of the question. This is the 89 * area that contains the various forms of feedback. This function generates 90 * the content of this area belonging to the question type. 91 * 92 * Subclasses will normally want to override the more specific methods 93 * {specific_feedback()}, {general_feedback()} and {correct_response()} 94 * that this method calls. 95 * 96 * @param question_attempt $qa the question attempt to display. 97 * @param question_display_options $options controls what should and should not be displayed. 98 * @return string HTML fragment. 99 */ 100 public function feedback(question_attempt $qa, question_display_options $options) { 101 $output = ''; 102 $hint = null; 103 104 if ($options->feedback) { 105 $output .= html_writer::nonempty_tag('div', $this->specific_feedback($qa), 106 array('class' => 'specificfeedback')); 107 $hint = $qa->get_applicable_hint(); 108 } 109 110 if ($options->numpartscorrect) { 111 $output .= html_writer::nonempty_tag('div', $this->num_parts_correct($qa), 112 array('class' => 'numpartscorrect')); 113 } 114 115 if ($hint) { 116 $output .= $this->hint($qa, $hint); 117 } 118 119 if ($options->generalfeedback) { 120 $output .= html_writer::nonempty_tag('div', $this->general_feedback($qa), 121 array('class' => 'generalfeedback')); 122 } 123 124 if ($options->rightanswer) { 125 $output .= html_writer::nonempty_tag('div', $this->correct_response($qa), 126 array('class' => 'rightanswer')); 127 } 128 129 return $output; 130 } 131 132 /** 133 * Generate the specific feedback. This is feedback that varies according to 134 * the response the student gave. 135 * @param question_attempt $qa the question attempt to display. 136 * @return string HTML fragment. 137 */ 138 protected function specific_feedback(question_attempt $qa) { 139 return ''; 140 } 141 142 /** 143 * Gereate a brief statement of how many sub-parts of this question the 144 * student got right. 145 * @param question_attempt $qa the question attempt to display. 146 * @return string HTML fragment. 147 */ 148 protected function num_parts_correct(question_attempt $qa) { 149 $a = new stdClass(); 150 list($a->num, $a->outof) = $qa->get_question()->get_num_parts_right( 151 $qa->get_last_qt_data()); 152 if (is_null($a->outof)) { 153 return ''; 154 } else { 155 return get_string('yougotnright', 'question', $a); 156 } 157 } 158 159 /** 160 * Gereate the specific feedback. This is feedback that varies according to 161 * the response the student gave. 162 * @param question_attempt $qa the question attempt to display. 163 * @return string HTML fragment. 164 */ 165 protected function hint(question_attempt $qa, question_hint $hint) { 166 return html_writer::nonempty_tag('div', 167 $qa->get_question()->format_hint($hint, $qa), array('class' => 'hint')); 168 } 169 170 /** 171 * Gereate the general feedback. This is feedback is shown ot all students. 172 * 173 * @param question_attempt $qa the question attempt to display. 174 * @return string HTML fragment. 175 */ 176 protected function general_feedback(question_attempt $qa) { 177 return $qa->get_question()->format_generalfeedback($qa); 178 } 179 180 /** 181 * Gereate an automatic description of the correct response to this question. 182 * Not all question types can do this. If it is not possible, this method 183 * should just return an empty string. 184 * 185 * @param question_attempt $qa the question attempt to display. 186 * @return string HTML fragment. 187 */ 188 protected function correct_response(question_attempt $qa) { 189 return ''; 190 } 191 192 /** 193 * Display any extra question-type specific content that should be visible 194 * when grading, if appropriate. 195 * 196 * @param question_attempt $qa a question attempt. 197 * @param question_display_options $options controls what should and should not be displayed. 198 * @return string HTML fragment. 199 */ 200 public function manual_comment(question_attempt $qa, question_display_options $options) { 201 return ''; 202 } 203 204 /** 205 * Return any HTML that needs to be included in the page's <head> when this 206 * question is used. 207 * @param $qa the question attempt that will be displayed on the page. 208 * @return string HTML fragment. 209 */ 210 public function head_code(question_attempt $qa) { 211 // This method is used by the Opaque question type. The remote question 212 // engine can send back arbitrary CSS that we have to link to in the 213 // page header. If it was not for that, we might be able to eliminate 214 // this method and load the required CSS and JS some other way. 215 $qa->get_question()->qtype->find_standard_scripts(); 216 } 217 218 protected function feedback_class($fraction) { 219 return question_state::graded_state_for_fraction($fraction)->get_feedback_class(); 220 } 221 222 /** 223 * Return an appropriate icon (green tick, red cross, etc.) for a grade. 224 * @param float $fraction grade on a scale 0..1. 225 * @param bool $selected whether to show a big or small icon. (Deprecated) 226 * @return string html fragment. 227 */ 228 protected function feedback_image($fraction, $selected = true) { 229 $feedbackclass = question_state::graded_state_for_fraction($fraction)->get_feedback_class(); 230 231 return $this->output->pix_icon('i/grade_' . $feedbackclass, get_string($feedbackclass, 'question')); 232 } 233 } 234 235 /** 236 * Renderer base classes for question types. 237 * 238 * @copyright 2010 The Open University 239 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 240 */ 241 abstract class qtype_with_combined_feedback_renderer extends qtype_renderer { 242 protected function combined_feedback(question_attempt $qa) { 243 $question = $qa->get_question(); 244 245 $state = $qa->get_state(); 246 247 if (!$state->is_finished()) { 248 $response = $qa->get_last_qt_data(); 249 if (!$qa->get_question()->is_gradable_response($response)) { 250 return ''; 251 } 252 list($notused, $state) = $qa->get_question()->grade_response($response); 253 } 254 255 $feedback = ''; 256 $field = $state->get_feedback_class() . 'feedback'; 257 $format = $state->get_feedback_class() . 'feedbackformat'; 258 if ($question->$field) { 259 $feedback .= $question->format_text($question->$field, $question->$format, 260 $qa, 'question', $field, $question->id); 261 } 262 263 return $feedback; 264 } 265 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body