All the credit goes to Paulo Matos who carefully worked out and tested this fix, and updated the patch several times over more than a year while I very slowly got around to reviewing it and checking it in.
}
}
+ // Fixing bug #5482: random questions have parent field set to its own id,
+ // see: $QTYPES['random']->get_question_options()
+ if ($question->qtype == 'random') {
+ $question->parent = $newid;
+ //we have to update the random question if the question has been inserted
+ if ($creatingnewquestion && $newid)
+ $status = set_field('question', 'parent', $question->parent, 'id', $newid);
+ }
+
//Save newid to backup tables
if ($question->id) {
//We have the newid, update backup_ids
//Extract the match_sub for the question and the answer
$exploded = explode("-",$tok);
$match_question_id = $exploded[0];
- $match_answer_code = $exploded[1];
+ $match_answer_id = $exploded[1];
//Get the match_sub from backup_ids (for the question)
if (!$match_que = backup_getid($restore->backup_unique_code,"question_match_sub",$match_question_id)) {
- echo 'Could not recode question_match_sub '.$match_question_id.'<br />';
+ echo 'Could not recode question in question_match_sub '.$match_question_id.'<br />';
}
- if ($in_first) {
- $answer_field .= $match_que->new_id."-".$match_answer_code;
- $in_first = false;
- } else {
- $answer_field .= ",".$match_que->new_id."-".$match_answer_code;
+ //Get the match_sub from backup_ids (for the answer)
+ if ($match_answer_id) { // only recode answer if not 0, not answered yet
+ if (!$match_ans = backup_getid($restore->backup_unique_code,"question_match_sub",$match_answer_id)) {
+ echo 'Could not recode answer in question_match_sub '.$match_answer_id.'<br />';
+ }
+ }
+
+ if ($match_que) {
+ //If the question hasn't response, it must be 0
+ if (!$match_ans and $match_answer_id == 0) {
+ $match_ans->new_id = 0;
+ }
+
+ if ($in_first) {
+ $answer_field .= $match_que->new_id."-".$match_ans->new_id;
+ $in_first = false;
+ } else {
+ $answer_field .= ",".$match_que->new_id."-".$match_ans->new_id;
+ }
}
//check for next
$tok = strtok(",");
->compare_responses($wrappedquestion, $state, $teststate);
}
+ function restore_recode_answer($state, $restore) {
+ // The answer looks like 'randomXX-ANSWER', where XX is
+ // the id of the used question and ANSWER the actual
+ // response to that question.
+ // However, there may still be old-style states around,
+ // which store the id of the wrapped question in the
+ // state of the random question and store the response
+ // in a separate state for the wrapped question
+
+ global $QTYPES;
+ $answer_field = "";
+
+ if (ereg('^random([0-9]+)-(.*)$', $state->answer, $answerregs)) {
+ // Recode the question id in $answerregs[1]
+ // Get the question from backup_ids
+ if(!$wrapped = backup_getid($restore->backup_unique_code,"question",$answerregs[1])) {
+ echo 'Could not recode question in random-'.$answerregs[1].'<br />';
+ return($answer_field);
+ }
+ // Get the question type for recursion
+ if (!$wrappedquestion->qtype = get_field('question', 'qtype', 'id', $wrapped->new_id)) {
+ echo 'Could not get qtype while recoding question random-'.$answerregs[1].'<br />';
+ return($answer_field);
+ }
+ $newstate = $state;
+ $newstate->question = $wrapped->new_id;
+ $newstate->answer = $answerregs[2];
+ $answer_field = 'random'.$wrapped->new_id.'-';
+
+ // Recode the answer field in $answerregs[2] depending on
+ // the qtype of question with id $answerregs[1]
+ $answer_field .= $QTYPES[$wrappedquestion->qtype]->restore_recode_answer($newstate, $restore);
+ } else {
+ // Handle old-style states
+ $answer_link = backup_getid($restore->backup_unique_code,"question",$state->answer);
+ if ($answer_link) {
+ $answer_field = $answer_link->new_id;
+ }
+ }
+
+ return $answer_field;
+ }
+
}
//// END OF CLASS ////
}
function restore_recode_answer($state, $restore) {
- $answer = backup_getid($restore->backup_unique_code,"question_answers",$state->answer);
- if ($answer) {
- return $answer->new_id;
- } else {
- echo 'Could not recode truefalse answer id '.$state->answer.' for state '.$state->oldid.'<br />';
+ //answer may be empty
+ if ($state->answer) {
+ $answer = backup_getid($restore->backup_unique_code,"question_answers",$state->answer);
+ if ($answer) {
+ return $answer->new_id;
+ } else {
+ echo 'Could not recode truefalse answer id '.$state->answer.' for state '.$state->oldid.'<br />';
+ }
}
- return '';
}
}