weekly release 2.3dev
[moodle.git] / question / type / multianswer / questiontype.php
CommitLineData
aeb15530 1<?php
d3603157
TH
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 multi-answer question type.
19 *
20 * @package qtype
21 * @subpackage multianswer
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
a17b297d
TH
27defined('MOODLE_INTERNAL') || die();
28
dcedbb0e
TH
29require_once($CFG->dirroot . '/question/type/multichoice/question.php');
30
a17b297d 31
1976496e 32/**
d3603157
TH
33 * The multi-answer question type class.
34 *
35 * @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
7375c542 37 */
ab50232b 38class qtype_multianswer extends question_type {
516cf3eb 39
ab50232b
TH
40 public function can_analyse_responses() {
41 return false;
42 }
43
59a3fcd3
TH
44 public function get_question_options($question) {
45 global $DB, $OUTPUT;
516cf3eb 46
47 // Get relevant data indexed by positionkey from the multianswers table
ab50232b
TH
48 $sequence = $DB->get_field('question_multianswer', 'sequence',
49 array('question' => $question->id), '*', MUST_EXIST);
516cf3eb 50
ab50232b
TH
51 $wrappedquestions = $DB->get_records_list('question', 'id',
52 explode(',', $sequence), 'id ASC');
516cf3eb 53
54 // We want an array with question ids as index and the positions as values
55 $sequence = array_flip(explode(',', $sequence));
56 array_walk($sequence, create_function('&$val', '$val++;'));
ab50232b
TH
57
58 // If a question is lost, the corresponding index is null
aeb15530 59 // so this null convention is used to test $question->options->questions
857caf3b 60 // before using the values.
aeb15530 61 // first all possible questions from sequence are nulled
857caf3b 62 // then filled with the data if available in $wrappedquestions
59a3fcd3
TH
63 foreach ($sequence as $seq) {
64 $question->options->questions[$seq] = '';
df79079f 65 }
ab50232b
TH
66
67 foreach ($wrappedquestions as $wrapped) {
68 question_bank::get_qtype($wrapped->qtype)->get_question_options($wrapped);
69 // for wrapped questions the maxgrade is always equal to the defaultmark,
70 // there is no entry in the question_instances table for them
71 $wrapped->maxmark = $wrapped->defaultmark;
72 $question->options->questions[$sequence[$wrapped->id]] = $wrapped;
857caf3b 73 }
516cf3eb 74
a4499532
TH
75 $question->hints = $DB->get_records('question_hints',
76 array('questionid' => $question->id), 'id ASC');
77
516cf3eb 78 return true;
79 }
80
59a3fcd3
TH
81 public function save_question_options($question) {
82 global $DB;
0ff4bd08 83 $result = new stdClass();
9fc3100f 84
516cf3eb 85 // This function needs to be able to handle the case where the existing set of wrapped
86 // questions does not match the new set of wrapped questions so that some need to be
87 // created, some modified and some deleted
88 // Unfortunately the code currently simply overwrites existing ones in sequence. This
9fc3100f 89 // will make re-marking after a re-ordering of wrapped questions impossible and
516cf3eb 90 // will also create difficulties if questiontype specific tables reference the id.
9fc3100f 91
516cf3eb 92 // First we get all the existing wrapped questions
ab50232b
TH
93 if (!$oldwrappedids = $DB->get_field('question_multianswer', 'sequence',
94 array('question' => $question->id))) {
857caf3b 95 $oldwrappedquestions = array();
0a5b58af 96 } else {
12c6e008
TH
97 $oldwrappedquestions = $DB->get_records_list('question', 'id',
98 explode(',', $oldwrappedids), 'id ASC');
516cf3eb 99 }
ab50232b 100
516cf3eb 101 $sequence = array();
59a3fcd3
TH
102 foreach ($question->options->questions as $wrapped) {
103 if (!empty($wrapped)) {
df79079f 104 // if we still have some old wrapped question ids, reuse the next of them
f34488b2 105
12c6e008
TH
106 if (is_array($oldwrappedquestions) &&
107 $oldwrappedquestion = array_shift($oldwrappedquestions)) {
857caf3b 108 $wrapped->id = $oldwrappedquestion->id;
59a3fcd3 109 if ($oldwrappedquestion->qtype != $wrapped->qtype) {
857caf3b 110 switch ($oldwrappedquestion->qtype) {
59a3fcd3 111 case 'multichoice':
ab50232b
TH
112 $DB->delete_records('question_multichoice',
113 array('question' => $oldwrappedquestion->id));
59a3fcd3
TH
114 break;
115 case 'shortanswer':
ab50232b
TH
116 $DB->delete_records('question_shortanswer',
117 array('question' => $oldwrappedquestion->id));
59a3fcd3
TH
118 break;
119 case 'numerical':
ab50232b
TH
120 $DB->delete_records('question_numerical',
121 array('question' => $oldwrappedquestion->id));
59a3fcd3
TH
122 break;
123 default:
ab50232b
TH
124 throw new moodle_exception('qtypenotrecognized',
125 'qtype_multianswer', '', $oldwrappedquestion->qtype);
59a3fcd3 126 $wrapped->id = 0;
df79079f 127 }
e9028ffc 128 }
59a3fcd3
TH
129 } else {
130 $wrapped->id = 0;
e9028ffc 131 }
516cf3eb 132 }
77fa3a0d 133 $wrapped->name = $question->name;
134 $wrapped->parent = $question->id;
59a3fcd3 135 $previousid = $wrapped->id;
ab50232b
TH
136 // save_question strips this extra bit off the category again.
137 $wrapped->category = $question->category . ',1';
138 $wrapped = question_bank::get_qtype($wrapped->qtype)->save_question(
139 $wrapped, clone($wrapped));
516cf3eb 140 $sequence[] = $wrapped->id;
59a3fcd3 141 if ($previousid != 0 && $previousid != $wrapped->id) {
26053641 142 // for some reasons a new question has been created
143 // so delete the old one
3908a523 144 question_delete_question($previousid);
26053641 145 }
516cf3eb 146 }
147
148 // Delete redundant wrapped questions
59a3fcd3 149 if (is_array($oldwrappedquestions) && count($oldwrappedquestions)) {
26053641 150 foreach ($oldwrappedquestions as $oldwrappedquestion) {
3908a523 151 question_delete_question($oldwrappedquestion->id);
e9028ffc 152 }
4bc4ca50 153 }
516cf3eb 154
155 if (!empty($sequence)) {
0ff4bd08 156 $multianswer = new stdClass();
516cf3eb 157 $multianswer->question = $question->id;
158 $multianswer->sequence = implode(',', $sequence);
12c6e008
TH
159 if ($oldid = $DB->get_field('question_multianswer', 'id',
160 array('question' => $question->id))) {
516cf3eb 161 $multianswer->id = $oldid;
ab50232b 162 $DB->update_record('question_multianswer', $multianswer);
516cf3eb 163 } else {
ab50232b 164 $DB->insert_record('question_multianswer', $multianswer);
516cf3eb 165 }
166 }
a4499532
TH
167
168 $this->save_hints($question);
516cf3eb 169 }
170
59a3fcd3 171 public function save_question($authorizedquestion, $form) {
e51efd7e 172 $question = qtype_multianswer_extract_question($form->questiontext);
516cf3eb 173 if (isset($authorizedquestion->id)) {
174 $question->id = $authorizedquestion->id;
516cf3eb 175 }
176
516cf3eb 177 $question->category = $authorizedquestion->category;
ab50232b 178 $form->defaultmark = $question->defaultmark;
516cf3eb 179 $form->questiontext = $question->questiontext;
180 $form->questiontextformat = 0;
77fa3a0d 181 $form->options = clone($question->options);
516cf3eb 182 unset($question->options);
94dbfb3a 183 return parent::save_question($question, $form);
516cf3eb 184 }
185
59a3fcd3 186 public function delete_question($questionid, $contextid) {
f34488b2 187 global $DB;
ab50232b 188 $DB->delete_records('question_multianswer', array('question' => $questionid));
9203b705
TH
189
190 parent::delete_question($questionid, $contextid);
516cf3eb 191 }
192
ab50232b
TH
193 protected function initialise_question_instance($question, $questiondata) {
194 parent::initialise_question_instance($question, $questiondata);
42a5b055
TH
195
196 $bits = preg_split('/\{#(\d+)\}/', $question->questiontext,
197 null, PREG_SPLIT_DELIM_CAPTURE);
198 $question->textfragments[0] = array_shift($bits);
199 $i = 1;
200 while (!empty($bits)) {
201 $question->places[$i] = array_shift($bits);
202 $question->textfragments[$i] = array_shift($bits);
203 $i += 1;
204 }
205
ab50232b
TH
206 foreach ($questiondata->options->questions as $key => $subqdata) {
207 $subqdata->contextid = $questiondata->contextid;
208 $question->subquestions[$key] = question_bank::make_question($subqdata);
fa6c8620 209 $question->subquestions[$key]->maxmark = $subqdata->defaultmark;
7ac7977c
TH
210 if (isset($subqdata->options->layout)) {
211 $question->subquestions[$key]->layout = $subqdata->options->layout;
212 }
869309b8 213 }
869309b8 214 }
869309b8 215
ab50232b
TH
216 public function get_random_guess_score($questiondata) {
217 $fractionsum = 0;
218 $fractionmax = 0;
219 foreach ($questiondata->options->questions as $key => $subqdata) {
fa6c8620 220 $fractionmax += $subqdata->defaultmark;
ab50232b
TH
221 $fractionsum += question_bank::get_qtype(
222 $subqdata->qtype)->get_random_guess_score($subqdata);
516cf3eb 223 }
ab50232b 224 return $fractionsum / $fractionmax;
516cf3eb 225 }
516cf3eb 226}
516cf3eb 227
ab50232b 228
0b346164 229// ANSWER_ALTERNATIVE regexes
ab50232b 230define('ANSWER_ALTERNATIVE_FRACTION_REGEX',
0b346164 231 '=|%(-?[0-9]+)%');
232// for the syntax '(?<!' see http://www.perl.com/doc/manual/html/pod/perlre.html#item_C
ab50232b 233define('ANSWER_ALTERNATIVE_ANSWER_REGEX',
e51efd7e 234 '.+?(?<!\\\\|&|&amp;)(?=[~#}]|$)');
ab50232b 235define('ANSWER_ALTERNATIVE_FEEDBACK_REGEX',
0b346164 236 '.*?(?<!\\\\)(?=[~}]|$)');
ab50232b 237define('ANSWER_ALTERNATIVE_REGEX',
e51efd7e 238 '(' . ANSWER_ALTERNATIVE_FRACTION_REGEX .')?' .
239 '(' . ANSWER_ALTERNATIVE_ANSWER_REGEX . ')' .
240 '(#(' . ANSWER_ALTERNATIVE_FEEDBACK_REGEX .'))?');
0b346164 241
242// Parenthesis positions for ANSWER_ALTERNATIVE_REGEX
ab50232b
TH
243define('ANSWER_ALTERNATIVE_REGEX_PERCENTILE_FRACTION', 2);
244define('ANSWER_ALTERNATIVE_REGEX_FRACTION', 1);
245define('ANSWER_ALTERNATIVE_REGEX_ANSWER', 3);
246define('ANSWER_ALTERNATIVE_REGEX_FEEDBACK', 5);
0b346164 247
248// NUMBER_FORMATED_ALTERNATIVE_ANSWER_REGEX is used
249// for identifying numerical answers in ANSWER_ALTERNATIVE_REGEX_ANSWER
ab50232b 250define('NUMBER_REGEX',
0b346164 251 '-?(([0-9]+[.,]?[0-9]*|[.,][0-9]+)([eE][-+]?[0-9]+)?)');
ab50232b 252define('NUMERICAL_ALTERNATIVE_REGEX',
0b346164 253 '^(' . NUMBER_REGEX . ')(:' . NUMBER_REGEX . ')?$');
254
255// Parenthesis positions for NUMERICAL_FORMATED_ALTERNATIVE_ANSWER_REGEX
ab50232b
TH
256define('NUMERICAL_CORRECT_ANSWER', 1);
257define('NUMERICAL_ABS_ERROR_MARGIN', 6);
0b346164 258
259// Remaining ANSWER regexes
ab50232b 260define('ANSWER_TYPE_DEF_REGEX',
12c6e008
TH
261 '(NUMERICAL|NM)|(MULTICHOICE|MC)|(MULTICHOICE_V|MCV)|(MULTICHOICE_H|MCH)|' .
262 '(SHORTANSWER|SA|MW)|(SHORTANSWER_C|SAC|MWC)');
ab50232b 263define('ANSWER_START_REGEX',
0b346164 264 '\{([0-9]*):(' . ANSWER_TYPE_DEF_REGEX . '):');
265
ab50232b 266define('ANSWER_REGEX',
0b346164 267 ANSWER_START_REGEX
268 . '(' . ANSWER_ALTERNATIVE_REGEX
269 . '(~'
270 . ANSWER_ALTERNATIVE_REGEX
59a3fcd3 271 . ')*)\}');
0b346164 272
273// Parenthesis positions for singulars in ANSWER_REGEX
ab50232b
TH
274define('ANSWER_REGEX_NORM', 1);
275define('ANSWER_REGEX_ANSWER_TYPE_NUMERICAL', 3);
276define('ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE', 4);
277define('ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_REGULAR', 5);
278define('ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_HORIZONTAL', 6);
279define('ANSWER_REGEX_ANSWER_TYPE_SHORTANSWER', 7);
280define('ANSWER_REGEX_ANSWER_TYPE_SHORTANSWER_C', 8);
281define('ANSWER_REGEX_ALTERNATIVES', 9);
516cf3eb 282
7518b645 283function qtype_multianswer_extract_question($text) {
61dfe97e 284 // $text is an array [text][format][itemid]
0ff4bd08 285 $question = new stdClass();
dfa47f96 286 $question->qtype = 'multianswer';
516cf3eb 287 $question->questiontext = $text;
61dfe97e 288 $question->generalfeedback['text'] = '';
c1f15d35 289 $question->generalfeedback['format'] = FORMAT_HTML;
61dfe97e 290 $question->generalfeedback['itemid'] = '';
59a3fcd3
TH
291
292 $question->options->questions = array();
ab50232b 293 $question->defaultmark = 0; // Will be increased for each answer norm
516cf3eb 294
ab50232b
TH
295 for ($positionkey = 1;
296 preg_match('/'.ANSWER_REGEX.'/', $question->questiontext['text'], $answerregs);
297 ++$positionkey) {
0ff4bd08 298 $wrapped = new stdClass();
61dfe97e 299 $wrapped->generalfeedback['text'] = '';
c1f15d35 300 $wrapped->generalfeedback['format'] = FORMAT_HTML;
61dfe97e 301 $wrapped->generalfeedback['itemid'] = '';
59a3fcd3 302 if (isset($answerregs[ANSWER_REGEX_NORM])&& $answerregs[ANSWER_REGEX_NORM]!== '') {
ab50232b 303 $wrapped->defaultmark = $answerregs[ANSWER_REGEX_NORM];
8795a5ae 304 } else {
ab50232b 305 $wrapped->defaultmark = '1';
8795a5ae 306 }
516cf3eb 307 if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_NUMERICAL])) {
dfa47f96 308 $wrapped->qtype = 'numerical';
516cf3eb 309 $wrapped->multiplier = array();
310 $wrapped->units = array();
61dfe97e 311 $wrapped->instructions['text'] = '';
c1f15d35 312 $wrapped->instructions['format'] = FORMAT_HTML;
61dfe97e 313 $wrapped->instructions['itemid'] = '';
59a3fcd3 314 } else if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_SHORTANSWER])) {
dfa47f96 315 $wrapped->qtype = 'shortanswer';
516cf3eb 316 $wrapped->usecase = 0;
59a3fcd3 317 } else if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_SHORTANSWER_C])) {
fd97082c 318 $wrapped->qtype = 'shortanswer';
319 $wrapped->usecase = 1;
59a3fcd3 320 } else if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE])) {
dfa47f96 321 $wrapped->qtype = 'multichoice';
516cf3eb 322 $wrapped->single = 1;
1cacb059 323 $wrapped->shuffleanswers = 1;
271e6dec 324 $wrapped->answernumbering = 0;
61dfe97e 325 $wrapped->correctfeedback['text'] = '';
c1f15d35 326 $wrapped->correctfeedback['format'] = FORMAT_HTML;
61dfe97e
PP
327 $wrapped->correctfeedback['itemid'] = '';
328 $wrapped->partiallycorrectfeedback['text'] = '';
c1f15d35 329 $wrapped->partiallycorrectfeedback['format'] = FORMAT_HTML;
61dfe97e
PP
330 $wrapped->partiallycorrectfeedback['itemid'] = '';
331 $wrapped->incorrectfeedback['text'] = '';
c1f15d35 332 $wrapped->incorrectfeedback['format'] = FORMAT_HTML;
61dfe97e 333 $wrapped->incorrectfeedback['itemid'] = '';
7ac7977c 334 $wrapped->layout = qtype_multichoice_base::LAYOUT_DROPDOWN;
59a3fcd3 335 } else if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_REGULAR])) {
e5ebbd53 336 $wrapped->qtype = 'multichoice';
337 $wrapped->single = 1;
1cacb059 338 $wrapped->shuffleanswers = 0;
e5ebbd53 339 $wrapped->answernumbering = 0;
61dfe97e 340 $wrapped->correctfeedback['text'] = '';
c1f15d35 341 $wrapped->correctfeedback['format'] = FORMAT_HTML;
61dfe97e
PP
342 $wrapped->correctfeedback['itemid'] = '';
343 $wrapped->partiallycorrectfeedback['text'] = '';
c1f15d35 344 $wrapped->partiallycorrectfeedback['format'] = FORMAT_HTML;
61dfe97e
PP
345 $wrapped->partiallycorrectfeedback['itemid'] = '';
346 $wrapped->incorrectfeedback['text'] = '';
c1f15d35 347 $wrapped->incorrectfeedback['format'] = FORMAT_HTML;
61dfe97e 348 $wrapped->incorrectfeedback['itemid'] = '';
7ac7977c 349 $wrapped->layout = qtype_multichoice_base::LAYOUT_VERTICAL;
59a3fcd3 350 } else if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_MULTICHOICE_HORIZONTAL])) {
e5ebbd53 351 $wrapped->qtype = 'multichoice';
352 $wrapped->single = 1;
1cacb059 353 $wrapped->shuffleanswers = 0;
e5ebbd53 354 $wrapped->answernumbering = 0;
61dfe97e 355 $wrapped->correctfeedback['text'] = '';
c1f15d35 356 $wrapped->correctfeedback['format'] = FORMAT_HTML;
61dfe97e
PP
357 $wrapped->correctfeedback['itemid'] = '';
358 $wrapped->partiallycorrectfeedback['text'] = '';
c1f15d35 359 $wrapped->partiallycorrectfeedback['format'] = FORMAT_HTML;
61dfe97e
PP
360 $wrapped->partiallycorrectfeedback['itemid'] = '';
361 $wrapped->incorrectfeedback['text'] = '';
c1f15d35 362 $wrapped->incorrectfeedback['format'] = FORMAT_HTML;
61dfe97e 363 $wrapped->incorrectfeedback['itemid'] = '';
7ac7977c 364 $wrapped->layout = qtype_multichoice_base::LAYOUT_HORIZONTAL;
516cf3eb 365 } else {
2471ef86 366 print_error('unknownquestiontype', 'question', '', $answerregs[2]);
516cf3eb 367 return false;
368 }
369
370 // Each $wrapped simulates a $form that can be processed by the
371 // respective save_question and save_question_options methods of the
372 // wrapped questiontypes
373 $wrapped->answer = array();
374 $wrapped->fraction = array();
375 $wrapped->feedback = array();
61dfe97e 376 $wrapped->questiontext['text'] = $answerregs[0];
c1f15d35 377 $wrapped->questiontext['format'] = FORMAT_HTML;
59a3fcd3
TH
378 $wrapped->questiontext['itemid'] = '';
379 $answerindex = 0;
516cf3eb 380
381 $remainingalts = $answerregs[ANSWER_REGEX_ALTERNATIVES];
382 while (preg_match('/~?'.ANSWER_ALTERNATIVE_REGEX.'/', $remainingalts, $altregs)) {
383 if ('=' == $altregs[ANSWER_ALTERNATIVE_REGEX_FRACTION]) {
61dfe97e 384 $wrapped->fraction["$answerindex"] = '1';
59a3fcd3 385 } else if ($percentile = $altregs[ANSWER_ALTERNATIVE_REGEX_PERCENTILE_FRACTION]) {
61dfe97e 386 $wrapped->fraction["$answerindex"] = .01 * $percentile;
516cf3eb 387 } else {
61dfe97e 388 $wrapped->fraction["$answerindex"] = '0';
516cf3eb 389 }
e51efd7e 390 if (isset($altregs[ANSWER_ALTERNATIVE_REGEX_FEEDBACK])) {
ab50232b
TH
391 $feedback = html_entity_decode(
392 $altregs[ANSWER_ALTERNATIVE_REGEX_FEEDBACK], ENT_QUOTES, 'UTF-8');
095b599a 393 $feedback = str_replace('\}', '}', $feedback);
61dfe97e 394 $wrapped->feedback["$answerindex"]['text'] = str_replace('\#', '#', $feedback);
c1f15d35 395 $wrapped->feedback["$answerindex"]['format'] = FORMAT_HTML;
61dfe97e 396 $wrapped->feedback["$answerindex"]['itemid'] = '';
e51efd7e 397 } else {
61dfe97e 398 $wrapped->feedback["$answerindex"]['text'] = '';
c1f15d35
TH
399 $wrapped->feedback["$answerindex"]['format'] = FORMAT_HTML;
400 $wrapped->feedback["$answerindex"]['itemid'] = '';
61dfe97e 401
e51efd7e 402 }
516cf3eb 403 if (!empty($answerregs[ANSWER_REGEX_ANSWER_TYPE_NUMERICAL])
ab50232b
TH
404 && preg_match('~'.NUMERICAL_ALTERNATIVE_REGEX.'~',
405 $altregs[ANSWER_ALTERNATIVE_REGEX_ANSWER], $numregs)) {
e51efd7e 406 $wrapped->answer[] = $numregs[NUMERICAL_CORRECT_ANSWER];
c83ed025 407 if (array_key_exists(NUMERICAL_ABS_ERROR_MARGIN, $numregs)) {
61dfe97e 408 $wrapped->tolerance["$answerindex"] =
e51efd7e 409 $numregs[NUMERICAL_ABS_ERROR_MARGIN];
516cf3eb 410 } else {
61dfe97e 411 $wrapped->tolerance["$answerindex"] = 0;
516cf3eb 412 }
413 } else { // Tolerance can stay undefined for non numerical questions
1f8db780 414 // Undo quoting done by the HTML editor.
ab50232b
TH
415 $answer = html_entity_decode(
416 $altregs[ANSWER_ALTERNATIVE_REGEX_ANSWER], ENT_QUOTES, 'UTF-8');
095b599a 417 $answer = str_replace('\}', '}', $answer);
61dfe97e 418 $wrapped->answer["$answerindex"] = str_replace('\#', '#', $answer);
c1f15d35
TH
419 if ($wrapped->qtype == 'multichoice') {
420 $wrapped->answer["$answerindex"] = array(
421 'text' => $wrapped->answer["$answerindex"],
422 'format' => FORMAT_HTML,
423 'itemid' => '');
424 }
516cf3eb 425 }
426 $tmp = explode($altregs[0], $remainingalts, 2);
427 $remainingalts = $tmp[1];
59a3fcd3 428 $answerindex++;
516cf3eb 429 }
430
ab50232b 431 $question->defaultmark += $wrapped->defaultmark;
516cf3eb 432 $question->options->questions[$positionkey] = clone($wrapped);
61dfe97e
PP
433 $question->questiontext['text'] = implode("{#$positionkey}",
434 explode($answerregs[0], $question->questiontext['text'], 2));
516cf3eb 435 }
516cf3eb 436 return $question;
437}