From 315559d354161981f944a34e8849e38f94284905 Mon Sep 17 00:00:00 2001 From: gustav_delius Date: Tue, 21 Mar 2006 20:59:32 +0000 Subject: [PATCH] Moving question restore code into questiontype classes. The restore is now temporarily broken but I will fix it as soon as I get home. --- .../questiontypes/calculated/questiontype.php | 65 +++++ question/questiontypes/essay/questiontype.php | 71 ++++++ question/questiontypes/match/questiontype.php | 161 +++++++++++++ .../multianswer/questiontype.php | 179 ++++++++++++++ .../multichoice/questiontype.php | 106 +++++++++ .../questiontypes/numerical/questiontype.php | 54 +++++ question/questiontypes/questiontype.php | 27 +++ .../randomsamatch/questiontype.php | 82 +++++++ question/questiontypes/rqp/questiontype.php | 73 +++++- .../shortanswer/questiontype.php | 67 ++++++ .../questiontypes/truefalse/questiontype.php | 67 ++++++ question/restorelib.php | 224 +----------------- 12 files changed, 959 insertions(+), 217 deletions(-) diff --git a/question/questiontypes/calculated/questiontype.php b/question/questiontypes/calculated/questiontype.php index 50cd73e695..884d7bc742 100644 --- a/question/questiontypes/calculated/questiontype.php +++ b/question/questiontypes/calculated/questiontype.php @@ -633,6 +633,71 @@ class question_calculated_qtype extends question_dataset_dependent_questiontype } return $status; } + +/// RESTORE FUNCTIONS ///////////////// + + /* + * Restores the data in the question + * + * This is used in question/restorelib.php + */ + function restore($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the calculated-s array + $calculateds = $info['#']['CALCULATED']; + + //Iterate over calculateds + for($i = 0; $i < sizeof($calculateds); $i++) { + $cal_info = $calculateds[$i]; + //traverse_xmlize($cal_info); //Debug + //print_object ($GLOBALS['traverse_array']); //Debug + //$GLOBALS['traverse_array']=""; //Debug + + //Now, build the question_calculated record structure + $calculated->question = $new_question_id; + $calculated->answer = backup_todb($cal_info['#']['ANSWER']['0']['#']); + $calculated->tolerance = backup_todb($cal_info['#']['TOLERANCE']['0']['#']); + $calculated->tolerancetype = backup_todb($cal_info['#']['TOLERANCETYPE']['0']['#']); + $calculated->correctanswerlength = backup_todb($cal_info['#']['CORRECTANSWERLENGTH']['0']['#']); + $calculated->correctanswerformat = backup_todb($cal_info['#']['CORRECTANSWERFORMAT']['0']['#']); + + ////We have to recode the answer field + $answer = backup_getid($restore->backup_unique_code,"question_answers",$calculated->answer); + if ($answer) { + $calculated->answer = $answer->new_id; + } + + //The structure is equal to the db, so insert the question_calculated + $newid = insert_record ("question_calculated",$calculated); + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } + + //Now restore numerical_units + $status = question_restore_numerical_units ($old_question_id,$new_question_id,$cal_info,$restore); + + //Now restore dataset_definitions + if ($status && $newid) { + $status = question_restore_dataset_definitions ($old_question_id,$new_question_id,$cal_info,$restore); + } + + if (!$newid) { + $status = false; + } + } + + return $status; + } } //// END OF CLASS //// diff --git a/question/questiontypes/essay/questiontype.php b/question/questiontypes/essay/questiontype.php index 03bbe2c02c..dc0d6d3f2a 100644 --- a/question/questiontypes/essay/questiontype.php +++ b/question/questiontypes/essay/questiontype.php @@ -335,6 +335,77 @@ class question_essay_qtype extends default_questiontype { return $status; } +/// RESTORE FUNCTIONS ///////////////// + + /* + * Restores the data in the question + * + * This is used in question/restorelib.php + */ + function restore($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the truefalse array + $essays = $info['#']['ESSAY']; + + //Iterate over truefalse + for($i = 0; $i < sizeof($essays); $i++) { + $essay_info = $essays[$i]; + + //Now, build the question_essay record structure + $essay->question = $new_question_id; + $essay->answer = backup_todb($essay_info['#']['ANSWER']['0']['#']); + + ////We have to recode the answer field + $answer = backup_getid($restore->backup_unique_code,"question_answers",$essay->answer); + if ($answer) { + $essay->answer = $answer->new_id; + } + + //The structure is equal to the db, so insert the question_essay + $newid = insert_record ("question_essay",$essay); + + //Do some output + if (($i+1) % 50 == 0) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + backup_flush(300); + } + + if (!$newid) { + $status = false; + } + } + + return $status; + } + + + //This function restores the question_essay_states + function restore_state($state_id,$info,$restore) { + + $status = true; + + //Get the question_essay_state + $essay_state = $info['#']['ESSAY_STATE']['0']; + if ($essay_state) { + + //Now, build the ESSAY_STATES record structure + $state->stateid = $state_id; + $state->graded = backup_todb($essay_state['#']['GRADED']['0']['#']); + $state->fraction = backup_todb($essay_state['#']['FRACTION']['0']['#']); + $state->response = backup_todb($essay_state['#']['RESPONSE']['0']['#']); + + //The structure is equal to the db, so insert the question_states + $newid = insert_record ("question_essay_states",$state); + } + + return $status; + } + } //// END OF CLASS //// diff --git a/question/questiontypes/match/questiontype.php b/question/questiontypes/match/questiontype.php index c27c122df2..5035ba92dd 100644 --- a/question/questiontypes/match/questiontype.php +++ b/question/questiontypes/match/questiontype.php @@ -365,6 +365,167 @@ class question_match_qtype extends default_questiontype { return $status; } +/// RESTORE FUNCTIONS ///////////////// + + /* + * Restores the data in the question + * + * This is used in question/restorelib.php + */ + function restore($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the matchs array + $matchs = $info['#']['MATCHS']['0']['#']['MATCH']; + + //We have to build the subquestions field (a list of match_sub id) + $subquestions_field = ""; + $in_first = true; + + //Iterate over matchs + for($i = 0; $i < sizeof($matchs); $i++) { + $mat_info = $matchs[$i]; + + //We'll need this later!! + $oldid = backup_todb($mat_info['#']['ID']['0']['#']); + + //Now, build the question_match_SUB record structure + $match_sub->question = $new_question_id; + $match_sub->code = backup_todb($mat_info['#']['CODE']['0']['#']); + if (!$match_sub->code) { + $match_sub->code = $oldid; + } + $match_sub->questiontext = backup_todb($mat_info['#']['QUESTIONTEXT']['0']['#']); + $match_sub->answertext = backup_todb($mat_info['#']['ANSWERTEXT']['0']['#']); + + //The structure is equal to the db, so insert the question_match_sub + $newid = insert_record ("question_match_sub",$match_sub); + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } + + if ($newid) { + //We have the newid, update backup_ids + backup_putid($restore->backup_unique_code,"question_match_sub",$oldid, + $newid); + //We have a new match_sub, append it to subquestions_field + if ($in_first) { + $subquestions_field .= $newid; + $in_first = false; + } else { + $subquestions_field .= ",".$newid; + } + } else { + $status = false; + } + } + + //We have created every match_sub, now create the match + $match->question = $new_question_id; + $match->subquestions = $subquestions_field; + + //The structure is equal to the db, so insert the question_match_sub + $newid = insert_record ("question_match",$match); + + if (!$newid) { + $status = false; + } + + return $status; + } + + function restore_map($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the matchs array + $matchs = $info['#']['MATCHS']['0']['#']['MATCH']; + + //We have to build the subquestions field (a list of match_sub id) + $subquestions_field = ""; + $in_first = true; + + //Iterate over matchs + for($i = 0; $i < sizeof($matchs); $i++) { + $mat_info = $matchs[$i]; + + //We'll need this later!! + $oldid = backup_todb($mat_info['#']['ID']['0']['#']); + + //Now, build the question_match_SUB record structure + $match_sub->question = $new_question_id; + $match_sub->questiontext = backup_todb($mat_info['#']['QUESTIONTEXT']['0']['#']); + $match_sub->answertext = backup_todb($mat_info['#']['ANSWERTEXT']['0']['#']); + + //If we are in this method is because the question exists in DB, so its + //match_sub must exist too. + //Now, we are going to look for that match_sub in DB and to create the + //mappings in backup_ids to use them later where restoring states (user level). + + //Get the match_sub from DB (by question, questiontext and answertext) + $db_match_sub = get_record ("question_match_sub","question",$new_question_id, + "questiontext",$match_sub->questiontext, + "answertext",$match_sub->answertext); + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } + + //We have the database match_sub, so update backup_ids + if ($db_match_sub) { + //We have the newid, update backup_ids + backup_putid($restore->backup_unique_code,"question_match_sub",$oldid, + $db_match_sub->id); + } else { + $status = false; + } + } + + return $status; + } + + function restore_recode_answer($state, $restore) { + + //The answer is a comma separated list of hypen separated math_subs (for question and answer) + $answer_field = ""; + $in_first = true; + $tok = strtok($state->answer,","); + while ($tok) { + //Extract the match_sub for the question and the answer + $exploded = explode("-",$tok); + $match_question_id = $exploded[0]; + $match_answer_code = $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.'
'; + } + 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; + } + //check for next + $tok = strtok(","); + } + return $answer_field; + } + } //// END OF CLASS //// diff --git a/question/questiontypes/multianswer/questiontype.php b/question/questiontypes/multianswer/questiontype.php index a29a2b1f2e..f0fd55ea17 100644 --- a/question/questiontypes/multianswer/questiontype.php +++ b/question/questiontypes/multianswer/questiontype.php @@ -412,6 +412,185 @@ class quiz_embedded_cloze_qtype extends default_questiontype { return $status; } +/// RESTORE FUNCTIONS ///////////////// + + /* + * Restores the data in the question + * + * This is used in question/restorelib.php + */ + function restore($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the multianswers array + $multianswers = $info['#']['MULTIANSWERS']['0']['#']['MULTIANSWER']; + //Iterate over multianswers + for($i = 0; $i < sizeof($multianswers); $i++) { + $mul_info = $multianswers[$i]; + + //We need this later + $oldid = backup_todb($mul_info['#']['ID']['0']['#']); + + //Now, build the question_multianswer record structure + $multianswer->question = $new_question_id; + $multianswer->sequence = backup_todb($mul_info['#']['SEQUENCE']['0']['#']); + + //We have to recode the sequence field (a list of question ids) + //Extracts question id from sequence + $sequence_field = ""; + $in_first = true; + $tok = strtok($multianswer->sequence,","); + while ($tok) { + //Get the answer from backup_ids + $question = backup_getid($restore->backup_unique_code,"question",$tok); + if ($question) { + if ($in_first) { + $sequence_field .= $question->new_id; + $in_first = false; + } else { + $sequence_field .= ",".$question->new_id; + } + } + //check for next + $tok = strtok(","); + } + //We have the answers field recoded to its new ids + $multianswer->sequence = $sequence_field; + //The structure is equal to the db, so insert the question_multianswer + $newid = insert_record ("question_multianswer",$multianswer); + + //Save ids in backup_ids + if ($newid) { + backup_putid($restore->backup_unique_code,"question_multianswer", + $oldid, $newid); + } + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } +/* + //If we have created the question_multianswer record, now, depending of the + //answertype, delegate the restore to every qtype function + if ($newid) { + if ($multianswer->answertype == "1") { + $status = quiz_restore_shortanswer ($old_question_id,$new_question_id,$mul_info,$restore); + } else if ($multianswer->answertype == "3") { + $status = quiz_restore_multichoice ($old_question_id,$new_question_id,$mul_info,$restore); + } else if ($multianswer->answertype == "8") { + $status = quiz_restore_numerical ($old_question_id,$new_question_id,$mul_info,$restore); + } + } else { + $status = false; + } +*/ + } + + return $status; + } + + function restore_map($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the multianswers array + $multianswers = $info['#']['MULTIANSWERS']['0']['#']['MULTIANSWER']; + //Iterate over multianswers + for($i = 0; $i < sizeof($multianswers); $i++) { + $mul_info = $multianswers[$i]; + + //We need this later + $oldid = backup_todb($mul_info['#']['ID']['0']['#']); + + //Now, build the question_multianswer record structure + $multianswer->question = $new_question_id; + $multianswer->answers = backup_todb($mul_info['#']['ANSWERS']['0']['#']); + $multianswer->positionkey = backup_todb($mul_info['#']['POSITIONKEY']['0']['#']); + $multianswer->answertype = backup_todb($mul_info['#']['ANSWERTYPE']['0']['#']); + $multianswer->norm = backup_todb($mul_info['#']['NORM']['0']['#']); + + //If we are in this method is because the question exists in DB, so its + //multianswer must exist too. + //Now, we are going to look for that multianswer in DB and to create the + //mappings in backup_ids to use them later where restoring states (user level). + + //Get the multianswer from DB (by question and positionkey) + $db_multianswer = get_record ("question_multianswer","question",$new_question_id, + "positionkey",$multianswer->positionkey); + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } + + //We have the database multianswer, so update backup_ids + if ($db_multianswer) { + //We have the newid, update backup_ids + backup_putid($restore->backup_unique_code,"question_multianswer",$oldid, + $db_multianswer->id); + } else { + $status = false; + } + } + + return $status; + } + + function restore_recode_answer($state, $restore) { + //The answer is a comma separated list of hypen separated sequence number and answers. We may have to recode the answers + $answer_field = ""; + $in_first = true; + $tok = strtok($state->answer,","); + while ($tok) { + //Extract the multianswer_id and the answer + $exploded = explode("-",$tok); + $seqnum = $exploded[0]; + $answer = $exploded[1]; + // $sequence is an ordered array of the question ids. + if (!$sequence = get_field('question_multianswer', 'sequence', 'question', $state->question)) { + error("The cloze question $state->question is missing its options"); + } + $sequence = explode(',', $sequence); + // The id of the current question. + $wrappedquestionid = $sequence[$seqnum-1]; + // now we can find the question + if (!$wrappedquestion = get_record('question', 'id', $wrappedquestionid)) { + error("Can't find the subquestion $wrappedquestionid that is used as part $seqnum in cloze question $state->question"); + } + // For multichoice question we need to recode the answer + if ($answer and $wrappedquestion->qtype == MULTICHOICE) { + //The answer is an answer_id, look for it in backup_ids + if (!$ans = backup_getid($restore->backup_unique_code,"question_answers",$answer)) { + echo 'Could not recode cloze multichoice answer '.$answer.'
'; + } + $answer = $ans->new_id; + } + //build the new answer field for each pair + if ($in_first) { + $answer_field .= $seqnum."-".$answer; + $in_first = false; + } else { + $answer_field .= ",".$seqnum."-".$answer; + } + //check for next + $tok = strtok(","); + } + return $answer_field; + } + + } //// END OF CLASS //// diff --git a/question/questiontypes/multichoice/questiontype.php b/question/questiontypes/multichoice/questiontype.php index a7602f8fec..b63a97b484 100644 --- a/question/questiontypes/multichoice/questiontype.php +++ b/question/questiontypes/multichoice/questiontype.php @@ -402,6 +402,112 @@ class question_multichoice_qtype extends default_questiontype { return $status; } +/// RESTORE FUNCTIONS ///////////////// + + /* + * Restores the data in the question + * + * This is used in question/restorelib.php + */ + function restore($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the multichoices array + $multichoices = $info['#']['MULTICHOICE']; + + //Iterate over multichoices + for($i = 0; $i < sizeof($multichoices); $i++) { + $mul_info = $multichoices[$i]; + + //Now, build the question_multichoice record structure + $multichoice->question = $new_question_id; + $multichoice->layout = backup_todb($mul_info['#']['LAYOUT']['0']['#']); + $multichoice->answers = backup_todb($mul_info['#']['ANSWERS']['0']['#']); + $multichoice->single = backup_todb($mul_info['#']['SINGLE']['0']['#']); + $multichoice->shuffleanswers = backup_todb($mul_info['#']['SHUFFLEANSWERS']['0']['#']); + + //We have to recode the answers field (a list of answers id) + //Extracts answer id from sequence + $answers_field = ""; + $in_first = true; + $tok = strtok($multichoice->answers,","); + while ($tok) { + //Get the answer from backup_ids + $answer = backup_getid($restore->backup_unique_code,"question_answers",$tok); + if ($answer) { + if ($in_first) { + $answers_field .= $answer->new_id; + $in_first = false; + } else { + $answers_field .= ",".$answer->new_id; + } + } + //check for next + $tok = strtok(","); + } + //We have the answers field recoded to its new ids + $multichoice->answers = $answers_field; + + //The structure is equal to the db, so insert the question_shortanswer + $newid = insert_record ("question_multichoice",$multichoice); + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } + + if (!$newid) { + $status = false; + } + } + + return $status; + } + + function restore_recode_answer($state, $restore) { + $pos = strpos($state->answer, ':'); + $order = array(); + $responses = array(); + if (false === $pos) { // No order of answers is given, so use the default + if ($state->answer) { + $responses = explode(',', $state->answer); + } + } else { + $order = explode(',', substr($state->answer, 0, $pos)); + if ($responsestring = substr($state->answer, $pos + 1)) { + $responses = explode(',', $responsestring); + } + } + if ($order) { + foreach ($order as $key => $oldansid) { + $answer = backup_getid($restore->backup_unique_code,"question_answers",$oldansid); + if ($answer) { + $order[$key] = $answer->new_id; + } else { + echo 'Could not recode multichoice answer id '.$oldansid.' for state '.$oldid.'
'; + } + } + } + if ($responses) { + foreach ($responses as $key => $oldansid) { + $answer = backup_getid($restore->backup_unique_code,"question_answers",$oldansid); + if ($answer) { + $responses[$key] = $answer->new_id; + } else { + echo 'Could not recode multichoice response answer id '.$oldansid.' for state '.$oldid.'
'; + } + } + } + return implode(',', $order).':'.implode(',', $responses); + } + } //// END OF CLASS //// diff --git a/question/questiontypes/numerical/questiontype.php b/question/questiontypes/numerical/questiontype.php index a8c3b620f7..6231c205c2 100644 --- a/question/questiontypes/numerical/questiontype.php +++ b/question/questiontypes/numerical/questiontype.php @@ -437,6 +437,60 @@ class question_numerical_qtype extends question_shortanswer_qtype { return $status; } +/// RESTORE FUNCTIONS ///////////////// + + /* + * Restores the data in the question + * + * This is used in question/restorelib.php + */ + function restore($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the numerical array + $numericals = $info['#']['NUMERICAL']; + + //Iterate over numericals + for($i = 0; $i < sizeof($numericals); $i++) { + $num_info = $numericals[$i]; + + //Now, build the question_numerical record structure + $numerical->question = $new_question_id; + $numerical->answer = backup_todb($num_info['#']['ANSWER']['0']['#']); + $numerical->tolerance = backup_todb($num_info['#']['TOLERANCE']['0']['#']); + + ////We have to recode the answer field + $answer = backup_getid($restore->backup_unique_code,"question_answers",$numerical->answer); + if ($answer) { + $numerical->answer = $answer->new_id; + } + + //The structure is equal to the db, so insert the question_numerical + $newid = insert_record ("question_numerical",$numerical); + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } + + //Now restore numerical_units + $status = question_restore_numerical_units ($old_question_id,$new_question_id,$num_info,$restore); + + if (!$newid) { + $status = false; + } + } + + return $status; + } + } //// END OF CLASS //// diff --git a/question/questiontypes/questiontype.php b/question/questiontypes/questiontype.php index 1f9b1e922b..44ed8ddaf9 100644 --- a/question/questiontypes/questiontype.php +++ b/question/questiontypes/questiontype.php @@ -955,6 +955,33 @@ class default_questiontype { return true; } +/// RESTORE FUNCTIONS ///////////////// + + /* + * Restores the data in the question + * + * This is used in question/restorelib.php + */ + function restore($old_question_id,$new_question_id,$info,$restore) { + // The default question type has nothing to restore + return true; + } + + function restore_map($old_question_id,$new_question_id,$info,$restore) { + // There is nothing to decode + return true; + } + + function restore_recode_answer($state, $restore) { + // There is nothing to decode + return true; + } + + //This function restores the question_rqp_states + function restore_state($state_id,$info,$restore) { + // The default question type does not keep its own state information + return true; + } } diff --git a/question/questiontypes/randomsamatch/questiontype.php b/question/questiontypes/randomsamatch/questiontype.php index a888901a09..25ee59fc40 100644 --- a/question/questiontypes/randomsamatch/questiontype.php +++ b/question/questiontypes/randomsamatch/questiontype.php @@ -267,6 +267,88 @@ class question_randomsamatch_qtype extends question_match_qtype { } return $status; } + +/// RESTORE FUNCTIONS ///////////////// + + /* + * Restores the data in the question + * + * This is used in question/restorelib.php + */ + function restore($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the randomsamatchs array + $randomsamatchs = $info['#']['RANDOMSAMATCH']; + + //Iterate over randomsamatchs + for($i = 0; $i < sizeof($randomsamatchs); $i++) { + $ran_info = $randomsamatchs[$i]; + + //Now, build the question_randomsamatch record structure + $randomsamatch->question = $new_question_id; + $randomsamatch->choose = backup_todb($ran_info['#']['CHOOSE']['0']['#']); + $randomsamatch->shuffleanswers = backup_todb($ran_info['#']['SHUFFLEANSWERS']['0']['#']); + + //The structure is equal to the db, so insert the question_randomsamatch + $newid = insert_record ("question_randomsamatch",$randomsamatch); + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } + + if (!$newid) { + $status = false; + } + } + + return $status; + } + + function restore_recode_answer($state, $restore) { + + //The answer is a comma separated list of hypen separated question_id and answer_id. We must recode them + $answer_field = ""; + $in_first = true; + $tok = strtok($state->answer,","); + while ($tok) { + //Extract the question_id and the answer_id + $exploded = explode("-",$tok); + $question_id = $exploded[0]; + $answer_id = $exploded[1]; + //Get the question from backup_ids + if (!$que = backup_getid($restore->backup_unique_code,"question",$question_id)) { + echo 'Could not recode randomsamatch question '.$question_id.'
'; + } + + if ($answer_id == 0) { // no response yet + $ans->new_id = 0; + } else { + //Get the answer from backup_ids + if (!$ans = backup_getid($restore->backup_unique_code,"question_answers",$answer_id)) { + echo 'Could not recode randomsamatch answer '.$answer_id.'
'; + } + } + if ($in_first) { + $answer_field .= $que->new_id."-".$ans->new_id; + $in_first = false; + } else { + $answer_field .= ",".$que->new_id."-".$ans->new_id; + } + //check for next + $tok = strtok(","); + } + return $answer_field; + } + } //// END OF CLASS //// diff --git a/question/questiontypes/rqp/questiontype.php b/question/questiontypes/rqp/questiontype.php index 3546e9e5a4..22135ee03e 100644 --- a/question/questiontypes/rqp/questiontype.php +++ b/question/questiontypes/rqp/questiontype.php @@ -426,7 +426,6 @@ class question_rqp_qtype extends default_questiontype { * be included on the quiz module admin page. */ function get_config_options() { - global $CFG; // for the time being disable rqp unless we have php 5 if(!check_php_version('5.0.0')) { @@ -467,6 +466,78 @@ class question_rqp_qtype extends default_questiontype { return $status; } +/// RESTORE FUNCTIONS ///////////////// + + /* + * Restores the data in the question + * + * This is used in question/restorelib.php + */ + function restore($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the truefalse array + $rqps = $info['#']['RQP']; + + //Iterate over rqp + for($i = 0; $i < sizeof($rqps); $i++) { + $tru_info = $rqps[$i]; + + //Now, build the question_rqp record structure + $rqp->question = $new_question_id; + $rqp->type = backup_todb($tru_info['#']['TYPE']['0']['#']); + $rqp->source = backup_todb($tru_info['#']['SOURCE']['0']['#']); + $rqp->format = backup_todb($tru_info['#']['FORMAT']['0']['#']); + $rqp->flags = backup_todb($tru_info['#']['FLAGS']['0']['#']); + $rqp->maxscore = backup_todb($tru_info['#']['MAXSCORE']['0']['#']); + + //The structure is equal to the db, so insert the question_rqp + $newid = insert_record ("question_rqp",$rqp); + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } + + if (!$newid) { + $status = false; + } + } + + return $status; + } + + + //This function restores the question_rqp_state + function restore_state($state_id,$info,$restore) { + + $status = true; + + //Get the question_rqp_state + $rqp_state = $info['#']['RQP_STATE']['0']; + if ($rqp_state) { + + //Now, build the RQP_STATES record structure + $state->stateid = $state_id; + $state->responses = backup_todb($rqp_state['#']['RESPONSES']['0']['#']); + $state->persistent_data = backup_todb($rqp_state['#']['PERSISTENT_DATA']['0']['#']); + $state->template_vars = backup_todb($rqp_state['#']['TEMPLATE_VARS']['0']['#']); + + //The structure is equal to the db, so insert the question_states + $newid = insert_record ("question_rqp_states",$state); + } + + return $status; + } + + } ////////////////////////////////////////////////////////////////////////// //// INITIATION - Without this line the question type is not in use... /// diff --git a/question/questiontypes/shortanswer/questiontype.php b/question/questiontypes/shortanswer/questiontype.php index 1392702cd7..c6c8c86681 100644 --- a/question/questiontypes/shortanswer/questiontype.php +++ b/question/questiontypes/shortanswer/questiontype.php @@ -272,6 +272,73 @@ class question_shortanswer_qtype extends default_questiontype { return $status; } +/// RESTORE FUNCTIONS ///////////////// + + /* + * Restores the data in the question + * + * This is used in question/restorelib.php + */ + function restore($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the shortanswers array + $shortanswers = $info['#']['SHORTANSWER']; + + //Iterate over shortanswers + for($i = 0; $i < sizeof($shortanswers); $i++) { + $sho_info = $shortanswers[$i]; + + //Now, build the question_shortanswer record structure + $shortanswer->question = $new_question_id; + $shortanswer->answers = backup_todb($sho_info['#']['ANSWERS']['0']['#']); + $shortanswer->usecase = backup_todb($sho_info['#']['USECASE']['0']['#']); + + //We have to recode the answers field (a list of answers id) + //Extracts answer id from sequence + $answers_field = ""; + $in_first = true; + $tok = strtok($shortanswer->answers,","); + while ($tok) { + //Get the answer from backup_ids + $answer = backup_getid($restore->backup_unique_code,"question_answers",$tok); + if ($answer) { + if ($in_first) { + $answers_field .= $answer->new_id; + $in_first = false; + } else { + $answers_field .= ",".$answer->new_id; + } + } + //check for next + $tok = strtok(","); + } + //We have the answers field recoded to its new ids + $shortanswer->answers = $answers_field; + + //The structure is equal to the db, so insert the question_shortanswer + $newid = insert_record ("question_shortanswer",$shortanswer); + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } + + if (!$newid) { + $status = false; + } + } + + return $status; + } + } //// END OF CLASS //// diff --git a/question/questiontypes/truefalse/questiontype.php b/question/questiontypes/truefalse/questiontype.php index 7fd126e77b..32edb27d54 100644 --- a/question/questiontypes/truefalse/questiontype.php +++ b/question/questiontypes/truefalse/questiontype.php @@ -239,6 +239,73 @@ class question_truefalse_qtype extends default_questiontype { return $status; } +/// RESTORE FUNCTIONS ///////////////// + + /* + * Restores the data in the question + * + * This is used in question/restorelib.php + */ + function restore($old_question_id,$new_question_id,$info,$restore) { + + $status = true; + + //Get the truefalse array + $truefalses = $info['#']['TRUEFALSE']; + + //Iterate over truefalse + for($i = 0; $i < sizeof($truefalses); $i++) { + $tru_info = $truefalses[$i]; + + //Now, build the question_truefalse record structure + $truefalse->question = $new_question_id; + $truefalse->trueanswer = backup_todb($tru_info['#']['TRUEANSWER']['0']['#']); + $truefalse->falseanswer = backup_todb($tru_info['#']['FALSEANSWER']['0']['#']); + + ////We have to recode the trueanswer field + $answer = backup_getid($restore->backup_unique_code,"question_answers",$truefalse->trueanswer); + if ($answer) { + $truefalse->trueanswer = $answer->new_id; + } + + ////We have to recode the falseanswer field + $answer = backup_getid($restore->backup_unique_code,"question_answers",$truefalse->falseanswer); + if ($answer) { + $truefalse->falseanswer = $answer->new_id; + } + + //The structure is equal to the db, so insert the question_truefalse + $newid = insert_record ("question_truefalse",$truefalse); + + //Do some output + if (($i+1) % 50 == 0) { + if (!defined('RESTORE_SILENTLY')) { + echo "."; + if (($i+1) % 1000 == 0) { + echo "
"; + } + } + backup_flush(300); + } + + if (!$newid) { + $status = false; + } + } + + return $status; + } + + 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 '.$oldid.'
'; + } + return ''; + } + } //// END OF CLASS //// diff --git a/question/restorelib.php b/question/restorelib.php index 82aee138d0..b4ec6893ba 100644 --- a/question/restorelib.php +++ b/question/restorelib.php @@ -161,28 +161,6 @@ global $CFG, $QTYPES; - // load questiontype-specific functions - unset($restorefns); - unset($restoremapfns); - unset($recodeansfns); - foreach ($QTYPES as $key => $qtype) { - $restorelib = $CFG->dirroot.'/question/questiontypes/'.$qtype->name().'/restorelib.php'; - if (file_exists($restorelib)) { - include_once($restorelib); - $restorefn = 'question_'.$qtype->name().'_restore'; - if (function_exists($restorefn)) { - $restorefns[$key] = $restorefn; - } - $restoremapfn = 'question_'.$qtype->name().'_restore_map'; - if (function_exists($restoremapfn)) { - $restoremapfns[$key] = $restoremapfn; - } - $recodeansfn = 'question_'.$qtype->name().'_recode_answer'; - if (function_exists($recodeansfn)) { - $recodeansfns[$key] = $recodeansfn; - } - } - } $status = true; $restored_questions = array(); @@ -269,21 +247,15 @@ if ($restored_questions[$i]->is_new) { //Now, restore every question_answers in this question $status = question_restore_answers($oldid,$newid,$que_info,$restore); - //Now, depending of the type of questions, invoke different functions - if (isset($restorefns[$question->qtype])) { - $status = $restorefns[$question->qtype]($oldid,$newid,$que_info,$restore); - } + // Restore questiontype specific data + $status = $QTYPES[$question->qtype]->restore($oldid,$newid,$que_info,$restore); } else { //We are NOT creating the question, but we need to know every question_answers //map between the XML file and the database to be able to restore the states //in each attempt. $status = question_restore_map_answers($oldid,$newid,$que_info,$restore); - //Now, depending of the type of questions, invoke different functions - //to create the necessary mappings in backup_ids, because we are not - //creating the question, but need some records in backup table - if (isset($restoremapfns[$question->qtype])) { - $status = $restoremapfns[$question->qtype]($oldid,$newid,$que_info,$restore); - } + // Do the questiontype specific mapping + $status = $QTYPE[$question->qtype]->restore_map($oldid,$newid,$que_info,$restore); } //Do some output @@ -571,7 +543,7 @@ //This function restores the question_states function question_states_restore_mods($attempt_id,$info,$restore) { - global $CFG, $restorestatefns; + global $CFG, $QTYPES; $status = true; @@ -625,175 +597,7 @@ } //Depending on the qtype, we make different recodes if ($state->answer) { - switch ($question->qtype) { - case 1: //SHORTANSWER QTYPE - //Nothing to do. The response is a text. - break; - case 2: //TRUEFALSE QTYPE - //The answer is one answer id. We must recode it - $answer = backup_getid($restore->backup_unique_code,"question_answers",$state->answer); - if ($answer) { - $state->answer = $answer->new_id; - } else { - echo 'Could not recode truefalse answer id '.$state->answer.' for state '.$oldid.'
'; - } - break; - case 3: //MULTICHOICE QTYPE - $pos = strpos($state->answer, ':'); - $order = array(); - $responses = array(); - if (false === $pos) { // No order of answers is given, so use the default - if ($state->answer) { - $responses = explode(',', $state->answer); - } - } else { - $order = explode(',', substr($state->answer, 0, $pos)); - if ($responsestring = substr($state->answer, $pos + 1)) { - $responses = explode(',', $responsestring); - } - } - if ($order) { - foreach ($order as $key => $oldansid) { - $answer = backup_getid($restore->backup_unique_code,"question_answers",$oldansid); - if ($answer) { - $order[$key] = $answer->new_id; - } else { - echo 'Could not recode multichoice answer id '.$oldansid.' for state '.$oldid.'
'; - } - } - } - if ($responses) { - foreach ($responses as $key => $oldansid) { - $answer = backup_getid($restore->backup_unique_code,"question_answers",$oldansid); - if ($answer) { - $responses[$key] = $answer->new_id; - } else { - echo 'Could not recode multichoice response answer id '.$oldansid.' for state '.$oldid.'
'; - } - } - } - $state->answer = implode(',', $order).':'.implode(',', $responses); - break; - case 4: //RANDOM QTYPE - //The answer links to another question id, we must recode it - $answer_link = backup_getid($restore->backup_unique_code,"question",$state->answer); - if ($answer_link) { - $state->answer = $answer_link->new_id; - } else { - echo 'Could not recode random question link '.$state->answer.' for state '.$oldid.'
'; - } - break; - case 5: //MATCH QTYPE - //The answer is a comma separated list of hypen separated math_subs (for question and answer) - $answer_field = ""; - $in_first = true; - $tok = strtok($state->answer,","); - while ($tok) { - //Extract the match_sub for the question and the answer - $exploded = explode("-",$tok); - $match_question_id = $exploded[0]; - $match_answer_code = $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.'
'; - } - 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; - } - //check for next - $tok = strtok(","); - } - $state->answer = $answer_field; - break; - case 6: //RANDOMSAMATCH QTYPE - //The answer is a comma separated list of hypen separated question_id and answer_id. We must recode them - $answer_field = ""; - $in_first = true; - $tok = strtok($state->answer,","); - while ($tok) { - //Extract the question_id and the answer_id - $exploded = explode("-",$tok); - $question_id = $exploded[0]; - $answer_id = $exploded[1]; - //Get the question from backup_ids - if (!$que = backup_getid($restore->backup_unique_code,"question",$question_id)) { - echo 'Could not recode randomsamatch question '.$question_id.'
'; - } - - if ($answer_id == 0) { // no response yet - $ans->new_id = 0; - } else { - //Get the answer from backup_ids - if (!$ans = backup_getid($restore->backup_unique_code,"question_answers",$answer_id)) { - echo 'Could not recode randomsamatch answer '.$answer_id.'
'; - } - } - if ($in_first) { - $answer_field .= $que->new_id."-".$ans->new_id; - $in_first = false; - } else { - $answer_field .= ",".$que->new_id."-".$ans->new_id; - } - //check for next - $tok = strtok(","); - } - $state->answer = $answer_field; - break; - case 7: //DESCRIPTION QTYPE - //Nothing to do (there is no awser to this qtype) - //But this case must exist !! - break; - case 8: //NUMERICAL QTYPE - //Nothing to do. The response is a text. - break; - case 9: //MULTIANSWER QTYPE - //The answer is a comma separated list of hypen separated sequence number and answers. We may have to recode the answers - $answer_field = ""; - $in_first = true; - $tok = strtok($state->answer,","); - while ($tok) { - //Extract the multianswer_id and the answer - $exploded = explode("-",$tok); - $seqnum = $exploded[0]; - $answer = $exploded[1]; - // $sequence is an ordered array of the question ids. - if (!$sequence = get_field('question_multianswer', 'sequence', 'question', $question->id)) { - error("The cloze question $question->id is missing its options"); - } - $sequence = explode(',', $sequence); - // The id of the current question. - $wrappedquestionid = $sequence[$seqnum-1]; - // now we can find the question - if (!$wrappedquestion = get_record('question', 'id', $wrappedquestionid)) { - error("Can't find the subquestion $wrappedquestionid that is used as part $seqnum in cloze question $question->id"); - } - // For multichoice question we need to recode the answer - if ($answer and $wrappedquestion->qtype == MULTICHOICE) { - //The answer is an answer_id, look for it in backup_ids - if (!$ans = backup_getid($restore->backup_unique_code,"question_answers",$answer)) { - echo 'Could not recode cloze multichoice answer '.$answer.'
'; - } - $answer = $ans->new_id; - } - //build the new answer field for each pair - if ($in_first) { - $answer_field .= $seqnum."-".$answer; - $in_first = false; - } else { - $answer_field .= ",".$seqnum."-".$answer; - } - //check for next - $tok = strtok(","); - } - $state->answer = $answer_field; - break; - case 10: //CALCULATED QTYPE - //Nothing to do. The response is a text. - break; - } + $state->answer = $QTYPES[$question->qtype]->restore_recode_answer($state, $restore); } //The structure is equal to the db, so insert the question_states @@ -815,20 +619,8 @@ backup_putid($restore->backup_unique_code,"question_states",$oldid, $newid); //Now process question type specific state information - - if ($qtypes = get_list_of_plugins('question/questiontypes')) { - foreach ($qtypes as $name) { - $qtype->name = $name; - $restorelib = $CFG->dirroot.'/question/questiontypes/'.$qtype->name.'/restorelib.php'; - if (file_exists($restorelib)) { - include_once($restorelib); - $restorestatefn = 'question_'.$qtype->name.'_states_restore'; - if (function_exists($restorestatefn)) { - $restorestatefn($newid,$res_info,$restore); - } - } - } - } + $qtype = get_field('question', 'qtype', 'id', $state->question); + $status = $QTYPES[$qtype]->restore_state($newid,$res_info,$restore); } else { $status = false; } -- 2.39.5