[ Index ] |
PHP Cross Reference of Unnamed Project |
[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 * The questiontype class for the multiple choice question type. 19 * 20 * @package qtype 21 * @subpackage multichoice 22 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 global $CFG; 30 require_once($CFG->libdir . '/questionlib.php'); 31 32 33 /** 34 * The multiple choice question type. 35 * 36 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com} 37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 */ 39 class qtype_multichoice extends question_type { 40 public function get_question_options($question) { 41 global $DB, $OUTPUT; 42 $question->options = $DB->get_record('qtype_multichoice_options', 43 array('questionid' => $question->id), '*', MUST_EXIST); 44 parent::get_question_options($question); 45 } 46 47 public function save_question_options($question) { 48 global $DB; 49 $context = $question->context; 50 $result = new stdClass(); 51 52 $oldanswers = $DB->get_records('question_answers', 53 array('question' => $question->id), 'id ASC'); 54 55 // Following hack to check at least two answers exist. 56 $answercount = 0; 57 foreach ($question->answer as $key => $answer) { 58 if ($answer != '') { 59 $answercount++; 60 } 61 } 62 if ($answercount < 2) { // Check there are at lest 2 answers for multiple choice. 63 $result->notice = get_string('notenoughanswers', 'qtype_multichoice', '2'); 64 return $result; 65 } 66 67 // Insert all the new answers. 68 $totalfraction = 0; 69 $maxfraction = -1; 70 foreach ($question->answer as $key => $answerdata) { 71 if (trim($answerdata['text']) == '') { 72 continue; 73 } 74 75 // Update an existing answer if possible. 76 $answer = array_shift($oldanswers); 77 if (!$answer) { 78 $answer = new stdClass(); 79 $answer->question = $question->id; 80 $answer->answer = ''; 81 $answer->feedback = ''; 82 $answer->id = $DB->insert_record('question_answers', $answer); 83 } 84 85 // Doing an import. 86 $answer->answer = $this->import_or_save_files($answerdata, 87 $context, 'question', 'answer', $answer->id); 88 $answer->answerformat = $answerdata['format']; 89 $answer->fraction = $question->fraction[$key]; 90 $answer->feedback = $this->import_or_save_files($question->feedback[$key], 91 $context, 'question', 'answerfeedback', $answer->id); 92 $answer->feedbackformat = $question->feedback[$key]['format']; 93 94 $DB->update_record('question_answers', $answer); 95 96 if ($question->fraction[$key] > 0) { 97 $totalfraction += $question->fraction[$key]; 98 } 99 if ($question->fraction[$key] > $maxfraction) { 100 $maxfraction = $question->fraction[$key]; 101 } 102 } 103 104 // Delete any left over old answer records. 105 $fs = get_file_storage(); 106 foreach ($oldanswers as $oldanswer) { 107 $fs->delete_area_files($context->id, 'question', 'answerfeedback', $oldanswer->id); 108 $DB->delete_records('question_answers', array('id' => $oldanswer->id)); 109 } 110 111 $options = $DB->get_record('qtype_multichoice_options', array('questionid' => $question->id)); 112 if (!$options) { 113 $options = new stdClass(); 114 $options->questionid = $question->id; 115 $options->correctfeedback = ''; 116 $options->partiallycorrectfeedback = ''; 117 $options->incorrectfeedback = ''; 118 $options->id = $DB->insert_record('qtype_multichoice_options', $options); 119 } 120 121 $options->single = $question->single; 122 if (isset($question->layout)) { 123 $options->layout = $question->layout; 124 } 125 $options->answernumbering = $question->answernumbering; 126 $options->shuffleanswers = $question->shuffleanswers; 127 $options = $this->save_combined_feedback_helper($options, $question, $context, true); 128 $DB->update_record('qtype_multichoice_options', $options); 129 130 $this->save_hints($question, true); 131 132 // Perform sanity checks on fractional grades. 133 if ($options->single) { 134 if ($maxfraction != 1) { 135 $result->noticeyesno = get_string('fractionsnomax', 'qtype_multichoice', 136 $maxfraction * 100); 137 return $result; 138 } 139 } else { 140 $totalfraction = round($totalfraction, 2); 141 if ($totalfraction != 1) { 142 $result->noticeyesno = get_string('fractionsaddwrong', 'qtype_multichoice', 143 $totalfraction * 100); 144 return $result; 145 } 146 } 147 } 148 149 protected function make_question_instance($questiondata) { 150 question_bank::load_question_definition_classes($this->name()); 151 if ($questiondata->options->single) { 152 $class = 'qtype_multichoice_single_question'; 153 } else { 154 $class = 'qtype_multichoice_multi_question'; 155 } 156 return new $class(); 157 } 158 159 protected function make_hint($hint) { 160 return question_hint_with_parts::load_from_record($hint); 161 } 162 163 protected function initialise_question_instance(question_definition $question, $questiondata) { 164 parent::initialise_question_instance($question, $questiondata); 165 $question->shuffleanswers = $questiondata->options->shuffleanswers; 166 $question->answernumbering = $questiondata->options->answernumbering; 167 if (!empty($questiondata->options->layout)) { 168 $question->layout = $questiondata->options->layout; 169 } else { 170 $question->layout = qtype_multichoice_single_question::LAYOUT_VERTICAL; 171 } 172 $this->initialise_combined_feedback($question, $questiondata, true); 173 174 $this->initialise_question_answers($question, $questiondata, false); 175 } 176 177 public function make_answer($answer) { 178 // Overridden just so we can make it public for use by question.php. 179 return parent::make_answer($answer); 180 } 181 182 public function delete_question($questionid, $contextid) { 183 global $DB; 184 $DB->delete_records('qtype_multichoice_options', array('questionid' => $questionid)); 185 186 parent::delete_question($questionid, $contextid); 187 } 188 189 public function get_random_guess_score($questiondata) { 190 if (!$questiondata->options->single) { 191 // Pretty much impossible to compute for _multi questions. Don't try. 192 return null; 193 } 194 195 // Single choice questions - average choice fraction. 196 $totalfraction = 0; 197 foreach ($questiondata->options->answers as $answer) { 198 $totalfraction += $answer->fraction; 199 } 200 return $totalfraction / count($questiondata->options->answers); 201 } 202 203 public function get_possible_responses($questiondata) { 204 if ($questiondata->options->single) { 205 $responses = array(); 206 207 foreach ($questiondata->options->answers as $aid => $answer) { 208 $responses[$aid] = new question_possible_response( 209 question_utils::to_plain_text($answer->answer, $answer->answerformat), 210 $answer->fraction); 211 } 212 213 $responses[null] = question_possible_response::no_response(); 214 return array($questiondata->id => $responses); 215 } else { 216 $parts = array(); 217 218 foreach ($questiondata->options->answers as $aid => $answer) { 219 $parts[$aid] = array($aid => new question_possible_response( 220 question_utils::to_plain_text($answer->answer, $answer->answerformat), 221 $answer->fraction)); 222 } 223 224 return $parts; 225 } 226 } 227 228 /** 229 * @return array of the numbering styles supported. For each one, there 230 * should be a lang string answernumberingxxx in teh qtype_multichoice 231 * language file, and a case in the switch statement in number_in_style, 232 * and it should be listed in the definition of this column in install.xml. 233 */ 234 public static function get_numbering_styles() { 235 $styles = array(); 236 foreach (array('abc', 'ABCD', '123', 'iii', 'IIII', 'none') as $numberingoption) { 237 $styles[$numberingoption] = 238 get_string('answernumbering' . $numberingoption, 'qtype_multichoice'); 239 } 240 return $styles; 241 } 242 243 public function move_files($questionid, $oldcontextid, $newcontextid) { 244 parent::move_files($questionid, $oldcontextid, $newcontextid); 245 $this->move_files_in_answers($questionid, $oldcontextid, $newcontextid, true); 246 $this->move_files_in_combined_feedback($questionid, $oldcontextid, $newcontextid); 247 $this->move_files_in_hints($questionid, $oldcontextid, $newcontextid); 248 } 249 250 protected function delete_files($questionid, $contextid) { 251 parent::delete_files($questionid, $contextid); 252 $this->delete_files_in_answers($questionid, $contextid, true); 253 $this->delete_files_in_combined_feedback($questionid, $contextid); 254 $this->delete_files_in_hints($questionid, $contextid); 255 } 256 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |