|
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 require_once($CFG->dirroot . '/question/type/multichoice/questiontype.php'); 00030 require_once($CFG->dirroot . '/question/type/calculated/questiontype.php'); 00031 00032 00039 class qtype_calculatedmulti extends qtype_calculated { 00040 00041 public function save_question_options($question) { 00042 global $CFG, $DB; 00043 $context = $question->context; 00044 00045 // Calculated options 00046 $update = true; 00047 $options = $DB->get_record('question_calculated_options', 00048 array('question' => $question->id)); 00049 if (!$options) { 00050 $options = new stdClass(); 00051 $options->question = $question->id; 00052 $options->correctfeedback = ''; 00053 $options->partiallycorrectfeedback = ''; 00054 $options->incorrectfeedback = ''; 00055 $options->id = $DB->insert_record('question_calculated_options', $options); 00056 } 00057 $options->synchronize = $question->synchronize; 00058 $options->single = $question->single; 00059 $options->answernumbering = $question->answernumbering; 00060 $options->shuffleanswers = $question->shuffleanswers; 00061 $options = $this->save_combined_feedback_helper($options, $question, $context, true); 00062 $DB->update_record('question_calculated_options', $options); 00063 00064 // Get old versions of the objects 00065 if (!$oldanswers = $DB->get_records('question_answers', 00066 array('question' => $question->id), 'id ASC')) { 00067 $oldanswers = array(); 00068 } 00069 if (!$oldoptions = $DB->get_records('question_calculated', 00070 array('question' => $question->id), 'answer ASC')) { 00071 $oldoptions = array(); 00072 } 00073 00074 // Insert all the new answers 00075 if (isset($question->answer) && !isset($question->answers)) { 00076 $question->answers = $question->answer; 00077 } 00078 foreach ($question->answers as $key => $answerdata) { 00079 if (is_array($answerdata)) { 00080 $answerdata = $answerdata['text']; 00081 } 00082 if (trim($answerdata) == '') { 00083 continue; 00084 } 00085 00086 // Update an existing answer if possible. 00087 $answer = array_shift($oldanswers); 00088 if (!$answer) { 00089 $answer = new stdClass(); 00090 $answer->question = $question->id; 00091 $answer->answer = ''; 00092 $answer->feedback = ''; 00093 $answer->id = $DB->insert_record('question_answers', $answer); 00094 } 00095 00096 if (is_array($answerdata)) { 00097 // Doing an import 00098 $answer->answer = $this->import_or_save_files($answerdata, 00099 $context, 'question', 'answer', $answer->id); 00100 $answer->answerformat = $answerdata['format']; 00101 } else { 00102 // Saving the form 00103 $answer->answer = $answerdata; 00104 $answer->answerformat = FORMAT_HTML; 00105 } 00106 $answer->fraction = $question->fraction[$key]; 00107 $answer->feedback = $this->import_or_save_files($question->feedback[$key], 00108 $context, 'question', 'answerfeedback', $answer->id); 00109 $answer->feedbackformat = $question->feedback[$key]['format']; 00110 00111 $DB->update_record("question_answers", $answer); 00112 00113 // Set up the options object 00114 if (!$options = array_shift($oldoptions)) { 00115 $options = new stdClass(); 00116 } 00117 $options->question = $question->id; 00118 $options->answer = $answer->id; 00119 $options->tolerance = trim($question->tolerance[$key]); 00120 $options->tolerancetype = trim($question->tolerancetype[$key]); 00121 $options->correctanswerlength = trim($question->correctanswerlength[$key]); 00122 $options->correctanswerformat = trim($question->correctanswerformat[$key]); 00123 00124 // Save options 00125 if (isset($options->id)) { 00126 // reusing existing record 00127 $DB->update_record('question_calculated', $options); 00128 } else { 00129 // new options 00130 $DB->insert_record('question_calculated', $options); 00131 } 00132 } 00133 00134 // delete old answer records 00135 if (!empty($oldanswers)) { 00136 foreach ($oldanswers as $oa) { 00137 $DB->delete_records('question_answers', array('id' => $oa->id)); 00138 } 00139 } 00140 if (!empty($oldoptions)) { 00141 foreach ($oldoptions as $oo) { 00142 $DB->delete_records('question_calculated', array('id' => $oo->id)); 00143 } 00144 } 00145 00146 $this->save_hints($question, true); 00147 00148 if (isset($question->import_process) && $question->import_process) { 00149 $this->import_datasets($question); 00150 } 00151 // Report any problems. 00152 if (!empty($result->notice)) { 00153 return $result; 00154 } 00155 00156 return true; 00157 } 00158 00159 protected function make_question_instance($questiondata) { 00160 question_bank::load_question_definition_classes($this->name()); 00161 if ($questiondata->options->single) { 00162 $class = 'qtype_calculatedmulti_single_question'; 00163 } else { 00164 $class = 'qtype_calculatedmulti_multi_question'; 00165 } 00166 return new $class(); 00167 } 00168 00169 protected function initialise_question_instance(question_definition $question, $questiondata) { 00170 question_type::initialise_question_instance($question, $questiondata); 00171 00172 $question->shuffleanswers = $questiondata->options->shuffleanswers; 00173 $question->answernumbering = $questiondata->options->answernumbering; 00174 if (!empty($questiondata->options->layout)) { 00175 $question->layout = $questiondata->options->layout; 00176 } else { 00177 $question->layout = qtype_multichoice_single_question::LAYOUT_VERTICAL; 00178 } 00179 00180 $question->synchronised = $questiondata->options->synchronize; 00181 00182 $this->initialise_combined_feedback($question, $questiondata, true); 00183 $this->initialise_question_answers($question, $questiondata); 00184 00185 foreach ($questiondata->options->answers as $a) { 00186 $question->answers[$a->id]->correctanswerlength = $a->correctanswerlength; 00187 $question->answers[$a->id]->correctanswerformat = $a->correctanswerformat; 00188 } 00189 00190 $question->datasetloader = new qtype_calculated_dataset_loader($questiondata->id); 00191 } 00192 00193 public function comment_header($question) { 00194 $strheader = ''; 00195 $delimiter = ''; 00196 00197 $answers = $question->options->answers; 00198 00199 foreach ($answers as $key => $answer) { 00200 if (is_string($answer)) { 00201 $strheader .= $delimiter.$answer; 00202 } else { 00203 $strheader .= $delimiter.$answer->answer; 00204 } 00205 $delimiter = '<br/>'; 00206 } 00207 return $strheader; 00208 } 00209 00210 public function comment_on_datasetitems($qtypeobj, $questionid, $questiontext, 00211 $answers, $data, $number) { 00212 global $DB; 00213 $comment = new stdClass(); 00214 $comment->stranswers = array(); 00215 $comment->outsidelimit = false; 00216 $comment->answers = array(); 00217 00218 $answers = fullclone($answers); 00219 $errors = ''; 00220 $delimiter = ': '; 00221 foreach ($answers as $key => $answer) { 00222 $answer->answer = $this->substitute_variables($answer->answer, $data); 00223 //evaluate the equations i.e {=5+4) 00224 $qtext = ''; 00225 $qtextremaining = $answer->answer; 00226 while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) { 00227 $qtextsplits = explode($regs1[0], $qtextremaining, 2); 00228 $qtext =$qtext.$qtextsplits[0]; 00229 $qtextremaining = $qtextsplits[1]; 00230 if (empty($regs1[1])) { 00231 $str = ''; 00232 } else { 00233 if ($formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) { 00234 $str=$formulaerrors; 00235 } else { 00236 eval('$str = '.$regs1[1].';'); 00237 } 00238 } 00239 $qtext = $qtext.$str; 00240 } 00241 $answer->answer = $qtext.$qtextremaining; 00242 $comment->stranswers[$key] = $answer->answer; 00243 } 00244 return fullclone($comment); 00245 } 00246 00247 public function get_virtual_qtype() { 00248 return question_bank::get_qtype('multichoice'); 00249 } 00250 00251 public function get_possible_responses($questiondata) { 00252 if ($questiondata->options->single) { 00253 $responses = array(); 00254 00255 foreach ($questiondata->options->answers as $aid => $answer) { 00256 $responses[$aid] = new question_possible_response($answer->answer, 00257 $answer->fraction); 00258 } 00259 00260 $responses[null] = question_possible_response::no_response(); 00261 return array($questiondata->id => $responses); 00262 } else { 00263 $parts = array(); 00264 00265 foreach ($questiondata->options->answers as $aid => $answer) { 00266 $parts[$aid] = array($aid => 00267 new question_possible_response($answer->answer, $answer->fraction)); 00268 } 00269 00270 return $parts; 00271 } 00272 } 00273 00274 public function move_files($questionid, $oldcontextid, $newcontextid) { 00275 $fs = get_file_storage(); 00276 00277 parent::move_files($questionid, $oldcontextid, $newcontextid); 00278 $this->move_files_in_answers($questionid, $oldcontextid, $newcontextid, true); 00279 00280 $fs->move_area_files_to_new_context($oldcontextid, 00281 $newcontextid, 'qtype_calculatedmulti', 'correctfeedback', $questionid); 00282 $fs->move_area_files_to_new_context($oldcontextid, 00283 $newcontextid, 'qtype_calculatedmulti', 'partiallycorrectfeedback', $questionid); 00284 $fs->move_area_files_to_new_context($oldcontextid, 00285 $newcontextid, 'qtype_calculatedmulti', 'incorrectfeedback', $questionid); 00286 } 00287 00288 protected function delete_files($questionid, $contextid) { 00289 $fs = get_file_storage(); 00290 00291 parent::delete_files($questionid, $contextid); 00292 $this->delete_files_in_answers($questionid, $contextid, true); 00293 00294 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 00295 'correctfeedback', $questionid); 00296 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 00297 'partiallycorrectfeedback', $questionid); 00298 $fs->delete_area_files($contextid, 'qtype_calculatedmulti', 00299 'incorrectfeedback', $questionid); 00300 } 00301 }