|
Moodle
2.2.1
http://www.collinsharper.com
|
00001 <?php 00002 // This file is part of Moodle - http://moodle.org/ 00003 // 00004 // Moodle is free software: you can redistribute it and/or modify 00005 // it under the terms of the GNU General Public License as published by 00006 // the Free Software Foundation, either version 3 of the License, or 00007 // (at your option) any later version. 00008 // 00009 // Moodle is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU General Public License 00015 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 00016 00027 defined('MOODLE_INTERNAL') || die(); 00028 00029 00038 class core_question_renderer extends plugin_renderer_base { 00039 public function get_page() { 00040 return $this->page; 00041 } 00042 00059 public function question(question_attempt $qa, qbehaviour_renderer $behaviouroutput, 00060 qtype_renderer $qtoutput, question_display_options $options, $number) { 00061 00062 $output = ''; 00063 $output .= html_writer::start_tag('div', array( 00064 'id' => 'q' . $qa->get_slot(), 00065 'class' => implode(' ', array( 00066 'que', 00067 $qa->get_question()->qtype->name(), 00068 $qa->get_behaviour_name(), 00069 $qa->get_state_class($options->correctness && $qa->has_marks()), 00070 )) 00071 )); 00072 00073 $output .= html_writer::tag('div', 00074 $this->info($qa, $behaviouroutput, $qtoutput, $options, $number), 00075 array('class' => 'info')); 00076 00077 $output .= html_writer::start_tag('div', array('class' => 'content')); 00078 00079 $output .= html_writer::tag('div', 00080 $this->add_part_heading($qtoutput->formulation_heading(), 00081 $this->formulation($qa, $behaviouroutput, $qtoutput, $options)), 00082 array('class' => 'formulation')); 00083 $output .= html_writer::nonempty_tag('div', 00084 $this->add_part_heading(get_string('feedback', 'question'), 00085 $this->outcome($qa, $behaviouroutput, $qtoutput, $options)), 00086 array('class' => 'outcome')); 00087 $output .= html_writer::nonempty_tag('div', 00088 $this->add_part_heading(get_string('comments', 'question'), 00089 $this->manual_comment($qa, $behaviouroutput, $qtoutput, $options)), 00090 array('class' => 'comment')); 00091 $output .= html_writer::nonempty_tag('div', 00092 $this->response_history($qa, $behaviouroutput, $qtoutput, $options), 00093 array('class' => 'history')); 00094 00095 $output .= html_writer::end_tag('div'); 00096 $output .= html_writer::end_tag('div'); 00097 return $output; 00098 } 00099 00113 protected function info(question_attempt $qa, qbehaviour_renderer $behaviouroutput, 00114 qtype_renderer $qtoutput, question_display_options $options, $number) { 00115 $output = ''; 00116 $output .= $this->number($number); 00117 $output .= $this->status($qa, $behaviouroutput, $options); 00118 $output .= $this->mark_summary($qa, $options); 00119 $output .= $this->question_flag($qa, $options->flags); 00120 $output .= $this->edit_question_link($qa, $options); 00121 return $output; 00122 } 00123 00130 protected function number($number) { 00131 $numbertext = ''; 00132 if (is_numeric($number)) { 00133 $numbertext = get_string('questionx', 'question', 00134 html_writer::tag('span', $number, array('class' => 'qno'))); 00135 } else if ($number == 'i') { 00136 $numbertext = get_string('information', 'question'); 00137 } 00138 if (!$numbertext) { 00139 return ''; 00140 } 00141 return html_writer::tag('h2', $numbertext, array('class' => 'no')); 00142 } 00143 00151 protected function add_part_heading($heading, $content) { 00152 if ($content) { 00153 $content = html_writer::tag('h3', $heading, array('class' => 'accesshide')) . $content; 00154 } 00155 return $content; 00156 } 00157 00167 protected function status(question_attempt $qa, qbehaviour_renderer $behaviouroutput, 00168 question_display_options $options) { 00169 return html_writer::tag('div', $qa->get_state_string($options->correctness), 00170 array('class' => 'state')); 00171 } 00172 00179 protected function mark_summary(question_attempt $qa, question_display_options $options) { 00180 if (!$options->marks) { 00181 return ''; 00182 } 00183 00184 if ($qa->get_max_mark() == 0) { 00185 $summary = get_string('notgraded', 'question'); 00186 00187 } else if ($options->marks == question_display_options::MAX_ONLY || 00188 is_null($qa->get_fraction())) { 00189 $summary = get_string('markedoutofmax', 'question', 00190 $qa->format_max_mark($options->markdp)); 00191 00192 } else { 00193 $a = new stdClass(); 00194 $a->mark = $qa->format_mark($options->markdp); 00195 $a->max = $qa->format_max_mark($options->markdp); 00196 $summary = get_string('markoutofmax', 'question', $a); 00197 } 00198 00199 return html_writer::tag('div', $summary, array('class' => 'grade')); 00200 } 00201 00208 protected function question_flag(question_attempt $qa, $flagsoption) { 00209 global $CFG; 00210 switch ($flagsoption) { 00211 case question_display_options::VISIBLE: 00212 $flagcontent = $this->get_flag_html($qa->is_flagged()); 00213 break; 00214 case question_display_options::EDITABLE: 00215 $id = $qa->get_flag_field_name(); 00216 if ($qa->is_flagged()) { 00217 $checked = 'checked="checked" '; 00218 } else { 00219 $checked = ''; 00220 } 00221 $postdata = question_flags::get_postdata($qa); 00222 // The checkbox id must be different from any element name, because 00223 // of a stupid IE bug: 00224 // http://www.456bereastreet.com/archive/200802/beware_of_id_and_name_attribute_mixups_when_using_getelementbyid_in_internet_explorer/ 00225 $flagcontent = '<input type="hidden" name="' . $id . '" value="0" />' . 00226 '<input type="checkbox" id="' . $id . 'checkbox" name="' . $id . 00227 '" value="1" ' . $checked . ' />' . 00228 '<input type="hidden" value="' . s($postdata) . 00229 '" class="questionflagpostdata" />' . 00230 '<label id="' . $id . 'label" for="' . $id . 'checkbox">' . 00231 $this->get_flag_html($qa->is_flagged(), $id . 'img') . 00232 '</label>' . "\n"; 00233 break; 00234 default: 00235 $flagcontent = ''; 00236 } 00237 if ($flagcontent) { 00238 return '<div class="questionflag">' . $flagcontent . "</div>\n"; 00239 } 00240 } 00241 00249 protected function get_flag_html($flagged, $id = '') { 00250 if ($flagged) { 00251 $icon = 'i/flagged'; 00252 $alt = get_string('flagged', 'question'); 00253 } else { 00254 $icon = 'i/unflagged'; 00255 $alt = get_string('notflagged', 'question'); 00256 } 00257 $attributes = array( 00258 'src' => $this->pix_url($icon), 00259 'alt' => $alt, 00260 ); 00261 if ($id) { 00262 $attributes['id'] = $id; 00263 } 00264 $img = html_writer::empty_tag('img', $attributes); 00265 if ($flagged) { 00266 $img .= ' ' . get_string('flagged', 'question'); 00267 } 00268 return $img; 00269 } 00270 00271 protected function edit_question_link(question_attempt $qa, 00272 question_display_options $options) { 00273 global $CFG; 00274 00275 if (empty($options->editquestionparams)) { 00276 return ''; 00277 } 00278 00279 $params = $options->editquestionparams; 00280 if ($params['returnurl'] instanceof moodle_url) { 00281 $params['returnurl'] = str_replace($CFG->wwwroot, '', 00282 $params['returnurl']->out(false)); 00283 } 00284 $params['id'] = $qa->get_question()->id; 00285 $editurl = new moodle_url('/question/question.php', $params); 00286 00287 return html_writer::tag('div', html_writer::link( 00288 $editurl, $this->pix_icon('i/edit', get_string('edit')) . 00289 get_string('editquestion', 'question')), 00290 array('class' => 'editquestion')); 00291 } 00292 00307 protected function formulation(question_attempt $qa, qbehaviour_renderer $behaviouroutput, 00308 qtype_renderer $qtoutput, question_display_options $options) { 00309 $output = ''; 00310 $output .= html_writer::empty_tag('input', array( 00311 'type' => 'hidden', 00312 'name' => $qa->get_control_field_name('sequencecheck'), 00313 'value' => $qa->get_num_steps())); 00314 $output .= $qtoutput->formulation_and_controls($qa, $options); 00315 if ($options->clearwrong) { 00316 $output .= $qtoutput->clear_wrong($qa); 00317 } 00318 $output .= html_writer::nonempty_tag('div', 00319 $behaviouroutput->controls($qa, $options), array('class' => 'im-controls')); 00320 return $output; 00321 } 00322 00335 protected function outcome(question_attempt $qa, qbehaviour_renderer $behaviouroutput, 00336 qtype_renderer $qtoutput, question_display_options $options) { 00337 $output = ''; 00338 $output .= html_writer::nonempty_tag('div', 00339 $qtoutput->feedback($qa, $options), array('class' => 'feedback')); 00340 $output .= html_writer::nonempty_tag('div', 00341 $behaviouroutput->feedback($qa, $options), array('class' => 'im-feedback')); 00342 return $output; 00343 } 00344 00345 protected function manual_comment(question_attempt $qa, qbehaviour_renderer $behaviouroutput, 00346 qtype_renderer $qtoutput, question_display_options $options) { 00347 return $qtoutput->manual_comment($qa, $options) . 00348 $behaviouroutput->manual_comment($qa, $options); 00349 } 00350 00363 protected function response_history(question_attempt $qa, qbehaviour_renderer $behaviouroutput, 00364 qtype_renderer $qtoutput, question_display_options $options) { 00365 00366 if (!$options->history) { 00367 return ''; 00368 } 00369 00370 $table = new html_table(); 00371 $table->head = array ( 00372 get_string('step', 'question'), 00373 get_string('time'), 00374 get_string('action', 'question'), 00375 get_string('state', 'question'), 00376 ); 00377 if ($options->marks >= question_display_options::MARK_AND_MAX) { 00378 $table->head[] = get_string('marks', 'question'); 00379 } 00380 00381 foreach ($qa->get_full_step_iterator() as $i => $step) { 00382 $stepno = $i + 1; 00383 00384 $rowclass = ''; 00385 if ($stepno == $qa->get_num_steps()) { 00386 $rowclass = 'current'; 00387 } else if (!empty($options->questionreviewlink)) { 00388 $url = new moodle_url($options->questionreviewlink, 00389 array('slot' => $qa->get_slot(), 'step' => $i)); 00390 $stepno = $this->output->action_link($url, $stepno, 00391 new popup_action('click', $url, 'reviewquestion', 00392 array('width' => 450, 'height' => 650)), 00393 array('title' => get_string('reviewresponse', 'question'))); 00394 } 00395 00396 $restrictedqa = new question_attempt_with_restricted_history($qa, $i, null); 00397 00398 $user = new stdClass(); 00399 $user->id = $step->get_user_id(); 00400 $row = array( 00401 $stepno, 00402 userdate($step->get_timecreated(), get_string('strftimedatetimeshort')), 00403 s($qa->summarise_action($step)), 00404 $restrictedqa->get_state_string($options->correctness), 00405 ); 00406 00407 if ($options->marks >= question_display_options::MARK_AND_MAX) { 00408 $row[] = $qa->format_fraction_as_mark($step->get_fraction(), $options->markdp); 00409 } 00410 00411 $table->rowclasses[] = $rowclass; 00412 $table->data[] = $row; 00413 } 00414 00415 return html_writer::tag('h3', get_string('responsehistory', 'question'), 00416 array('class' => 'responsehistoryheader')) . html_writer::tag('div', 00417 html_writer::table($table, true), array('class' => 'responsehistoryheader')); 00418 } 00419 00420 }