From 3ff8a1877a71808fc407be2a17321f8757cf1aa4 Mon Sep 17 00:00:00 2001 From: tjhunt Date: Wed, 7 May 2008 12:32:03 +0000 Subject: [PATCH] MDL-5482 - Backup and restore problems for match, random and truefalse question types. 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. --- question/restorelib.php | 9 +++++ question/type/match/questiontype.php | 28 +++++++++++---- question/type/random/questiontype.php | 43 ++++++++++++++++++++++++ question/type/truefalse/questiontype.php | 14 ++++---- 4 files changed, 81 insertions(+), 13 deletions(-) diff --git a/question/restorelib.php b/question/restorelib.php index 8ed49822de..678a785e91 100644 --- a/question/restorelib.php +++ b/question/restorelib.php @@ -390,6 +390,15 @@ } } + // 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 diff --git a/question/type/match/questiontype.php b/question/type/match/questiontype.php index 6ab57da88f..bf60e8f57c 100644 --- a/question/type/match/questiontype.php +++ b/question/type/match/questiontype.php @@ -596,16 +596,30 @@ class question_match_qtype extends default_questiontype { //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.'
'; + echo 'Could not recode question in question_match_sub '.$match_question_id.'
'; } - 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.'
'; + } + } + + 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(","); diff --git a/question/type/random/questiontype.php b/question/type/random/questiontype.php index 20c8546579..d6024c41b1 100644 --- a/question/type/random/questiontype.php +++ b/question/type/random/questiontype.php @@ -284,6 +284,49 @@ class random_qtype extends default_questiontype { ->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].'
'; + 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].'
'; + 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 //// diff --git a/question/type/truefalse/questiontype.php b/question/type/truefalse/questiontype.php index a45bdc56ad..b34c4bf226 100644 --- a/question/type/truefalse/questiontype.php +++ b/question/type/truefalse/questiontype.php @@ -334,13 +334,15 @@ class question_truefalse_qtype extends default_questiontype { } 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.'
'; + //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.'
'; + } } - return ''; } } -- 2.39.5