[ 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 * Question type class for the calculated multiple-choice question type. 19 * 20 * @package qtype 21 * @subpackage calculatedmulti 22 * @copyright 2009 Pierre Pichet 23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 */ 25 26 27 defined('MOODLE_INTERNAL') || die(); 28 29 require_once($CFG->dirroot . '/question/type/multichoice/questiontype.php'); 30 require_once($CFG->dirroot . '/question/type/calculated/questiontype.php'); 31 32 33 /** 34 * The calculated multiple-choice question type. 35 * 36 * @copyright 2009 Pierre Pichet 37 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 */ 39 class qtype_calculatedmulti extends qtype_calculated { 40 41 public function save_question_options($question) { 42 global $CFG, $DB; 43 $context = $question->context; 44 45 // Make it impossible to save bad formulas anywhere. 46 $this->validate_question_data($question); 47 48 // Calculated options. 49 $update = true; 50 $options = $DB->get_record('question_calculated_options', 51 array('question' => $question->id)); 52 if (!$options) { 53 $options = new stdClass(); 54 $options->question = $question->id; 55 $options->correctfeedback = ''; 56 $options->partiallycorrectfeedback = ''; 57 $options->incorrectfeedback = ''; 58 $options->id = $DB->insert_record('question_calculated_options', $options); 59 } 60 $options->synchronize = $question->synchronize; 61 $options->single = $question->single; 62 $options->answernumbering = $question->answernumbering; 63 $options->shuffleanswers = $question->shuffleanswers; 64 $options = $this->save_combined_feedback_helper($options, $question, $context, true); 65 $DB->update_record('question_calculated_options', $options); 66 67 // Get old versions of the objects. 68 if (!$oldanswers = $DB->get_records('question_answers', 69 array('question' => $question->id), 'id ASC')) { 70 $oldanswers = array(); 71 } 72 if (!$oldoptions = $DB->get_records('question_calculated', 73 array('question' => $question->id), 'answer ASC')) { 74 $oldoptions = array(); 75 } 76 77 // Insert all the new answers. 78 foreach ($question->answer as $key => $answerdata) { 79 if (is_array($answerdata)) { 80 $answerdata = $answerdata['text']; 81 } 82 if (trim($answerdata) == '') { 83 continue; 84 } 85 86 // Update an existing answer if possible. 87 $answer = array_shift($oldanswers); 88 if (!$answer) { 89 $answer = new stdClass(); 90 $answer->question = $question->id; 91 $answer->answer = ''; 92 $answer->feedback = ''; 93 $answer->id = $DB->insert_record('question_answers', $answer); 94 } 95 96 if (is_array($answerdata)) { 97 // Doing an import. 98 $answer->answer = $this->import_or_save_files($answerdata, 99 $context, 'question', 'answer', $answer->id); 100 $answer->answerformat = $answerdata['format']; 101 } else { 102 // Saving the form. 103 $answer->answer = $answerdata; 104 $answer->answerformat = FORMAT_HTML; 105 } 106 $answer->fraction = $question->fraction[$key]; 107 $answer->feedback = $this->import_or_save_files($question->feedback[$key], 108 $context, 'question', 'answerfeedback', $answer->id); 109 $answer->feedbackformat = $question->feedback[$key]['format']; 110 111 $DB->update_record("question_answers", $answer); 112 113 // Set up the options object. 114 if (!$options = array_shift($oldoptions)) { 115 $options = new stdClass(); 116 } 117 $options->question = $question->id; 118 $options->answer = $answer->id; 119 $options->tolerance = trim($question->tolerance[$key]); 120 $options->tolerancetype = trim($question->tolerancetype[$key]); 121 $options->correctanswerlength = trim($question->correctanswerlength[$key]); 122 $options->correctanswerformat = trim($question->correctanswerformat[$key]); 123 124 // Save options. 125 if (isset($options->id)) { 126 // Reusing existing record. 127 $DB->update_record('question_calculated', $options); 128 } else { 129 // New options. 130 $DB->insert_record('question_calculated', $options); 131 } 132 } 133 134 // Delete old answer records. 135 if (!empty($oldanswers)) { 136 foreach ($oldanswers as $oa) { 137 $DB->delete_records('question_answers', array('id' => $oa->id)); 138 } 139 } 140 if (!empty($oldoptions)) { 141 foreach ($oldoptions as $oo) { 142 $DB->delete_records('question_calculated', array('id' => $oo->id)); 143 } 144 } 145 146 $this->save_hints($question, true); 147 148 if (isset($question->import_process) && $question->import_process) { 149 $this->import_datasets($question); 150 } 151 // Report any problems. 152 if (!empty($result->notice)) { 153 return $result; 154 } 155 156 return true; 157 } 158 159 protected function validate_answer($answer) { 160 $error = qtype_calculated_find_formula_errors_in_text($answer); 161 if ($error) { 162 throw new coding_exception($error); 163 } 164 } 165 166 protected function validate_question_data($question) { 167 parent::validate_question_data($question); 168 $this->validate_text($question->correctfeedback['text']); 169 $this->validate_text($question->partiallycorrectfeedback['text']); 170 $this->validate_text($question->incorrectfeedback['text']); 171 } 172 173 protected function make_question_instance($questiondata) { 174 question_bank::load_question_definition_classes($this->name()); 175 if ($questiondata->options->single) { 176 $class = 'qtype_calculatedmulti_single_question'; 177 } else { 178 $class = 'qtype_calculatedmulti_multi_question'; 179 } 180 return new $class(); 181 } 182 183 protected function initialise_question_instance(question_definition $question, $questiondata) { 184 question_type::initialise_question_instance($question, $questiondata); 185 186 $question->shuffleanswers = $questiondata->options->shuffleanswers; 187 $question->answernumbering = $questiondata->options->answernumbering; 188 if (!empty($questiondata->options->layout)) { 189 $question->layout = $questiondata->options->layout; 190 } else { 191 $question->layout = qtype_multichoice_single_question::LAYOUT_VERTICAL; 192 } 193 194 $question->synchronised = $questiondata->options->synchronize; 195 196 $this->initialise_combined_feedback($question, $questiondata, true); 197 $this->initialise_question_answers($question, $questiondata); 198 199 foreach ($questiondata->options->answers as $a) { 200 $question->answers[$a->id]->correctanswerlength = $a->correctanswerlength; 201 $question->answers[$a->id]->correctanswerformat = $a->correctanswerformat; 202 } 203 204 $question->datasetloader = new qtype_calculated_dataset_loader($questiondata->id); 205 } 206 207 /** 208 * Public override method, created so that make_answer will be available 209 * for use by classes which extend qtype_multichoice_base. 210 * 211 * @param stdClass $answer Moodle DB question_answers object. 212 * @return question_answer 213 */ 214 public function make_answer($answer) { 215 return parent::make_answer($answer); 216 } 217 218 public function comment_header($question) { 219 $strheader = ''; 220 $delimiter = ''; 221 222 $answers = $question->options->answers; 223 224 foreach ($answers as $key => $answer) { 225 $ans = shorten_text($answer->answer, 17, true); 226 $strheader .= $delimiter.$ans; 227 $delimiter = '<br/><br/>'; 228 } 229 return $strheader; 230 } 231 232 public function comment_on_datasetitems($qtypeobj, $questionid, $questiontext, 233 $answers, $data, $number) { 234 global $DB; 235 $comment = new stdClass(); 236 $comment->stranswers = array(); 237 $comment->outsidelimit = false; 238 $comment->answers = array(); 239 240 $answers = fullclone($answers); 241 $errors = ''; 242 $delimiter = ': '; 243 foreach ($answers as $key => $answer) { 244 $anssubstituted = $this->substitute_variables($answer->answer, $data); 245 // Evaluate the equations i.e {=5+4). 246 $anstext = ''; 247 $anstextremaining = $anssubstituted; 248 while (preg_match('~\{=([^[:space:]}]*)}~', $anstextremaining, $regs1)) { 249 $anstextsplits = explode($regs1[0], $anstextremaining, 2); 250 $anstext =$anstext.$anstextsplits[0]; 251 $anstextremaining = $anstextsplits[1]; 252 if (empty($regs1[1])) { 253 $str = ''; 254 } else { 255 if ($formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) { 256 $str=$formulaerrors; 257 } else { 258 eval('$str = '.$regs1[1].';'); 259 } 260 } 261 $anstext = $anstext.$str; 262 } 263 $anstext .= $anstextremaining; 264 $comment->stranswers[$key] = $anssubstituted.'<br/>'.$anstext; 265 } 266 return fullclone($comment); 267 } 268 269 public function get_virtual_qtype() { 270 return question_bank::get_qtype('multichoice'); 271 } 272 273 public function get_possible_responses($questiondata) { 274 if ($questiondata->options->single) { 275 $responses = array(); 276 277 foreach ($questiondata->options->answers as $aid => $answer) { 278 $responses[$aid] = new question_possible_response($answer->answer, 279 $answer->fraction); 280 } 281 282 $responses[null] = question_possible_response::no_response(); 283 return array($questiondata->id => $responses); 284 } else { 285 $parts = array(); 286 287 foreach ($questiondata->options->answers as $aid => $answer) { 288 $parts[$aid] = array($aid => 289 new question_possible_response($answer->answer, $answer->fraction)); 290 } 291 292 return $parts; 293 } 294 } 295 296 public function move_files($questionid, $oldcontextid, $newcontextid) { 297 $fs = get_file_storage(); 298 299 parent::move_files($questionid, $oldcontextid, $newcontextid); 300 $this->move_files_in_answers($questionid, $oldcontextid, $newcontextid, true); 301 $this->move_files_in_hints($questionid, $oldcontextid, $newcontextid); 302 303 $fs->move_area_files_to_new_context($oldcontextid, 304 $newcontextid, 'qtype_calculatedmulti', 'correctfeedback', $questionid); 305 $fs->move_area_files_to_new_context($oldcontextid, 306 $newcontextid, 'qtype_calculatedmulti', 'partiallycorrectfeedback', $questionid); 307 $fs->move_area_files_to_new_context($oldcontextid, 308 $newcontextid, 'qtype_calculatedmulti', 'incorrectfeedback', $questionid); 309 } 310 311 protected function delete_files($questionid, $contextid) { 312 $fs = get_file_storage(); 313 314 parent::delete_files($questionid, $contextid); 315 $this->delete_files_in_answers($questionid, $contextid, true); 316 $this->delete_files_in_hints($questionid, $contextid); 317 318 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 319 'correctfeedback', $questionid); 320 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 321 'partiallycorrectfeedback', $questionid); 322 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 323 'incorrectfeedback', $questionid); 324 } 325 }
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 |