}
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 "<br />";
+ }
+ }
+ 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 ////
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 "<br />";
+ }
+ 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 ////
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 "<br />";
+ }
+ }
+ 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 "<br />";
+ }
+ }
+ 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.'<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;
+ }
+ //check for next
+ $tok = strtok(",");
+ }
+ return $answer_field;
+ }
+
}
//// END OF CLASS ////
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 "<br />";
+ }
+ }
+ 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 "<br />";
+ }
+ }
+ 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.'<br />';
+ }
+ $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 ////
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 "<br />";
+ }
+ }
+ 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.'<br />';
+ }
+ }
+ }
+ 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.'<br />';
+ }
+ }
+ }
+ return implode(',', $order).':'.implode(',', $responses);
+ }
+
}
//// END OF CLASS ////
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 "<br />";
+ }
+ }
+ 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 ////
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;
+ }
}
}
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 "<br />";
+ }
+ }
+ 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.'<br />';
+ }
+
+ 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.'<br />';
+ }
+ }
+ 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 ////
* 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')) {
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 "<br />";
+ }
+ }
+ 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... ///
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 "<br />";
+ }
+ }
+ backup_flush(300);
+ }
+
+ if (!$newid) {
+ $status = false;
+ }
+ }
+
+ return $status;
+ }
+
}
//// END OF CLASS ////
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 "<br />";
+ }
+ }
+ 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.'<br />';
+ }
+ return '';
+ }
+
}
//// END OF CLASS ////
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();
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
//This function restores the question_states
function question_states_restore_mods($attempt_id,$info,$restore) {
- global $CFG, $restorestatefns;
+ global $CFG, $QTYPES;
$status = true;
}
//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.'<br />';
- }
- 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.'<br />';
- }
- }
- }
- 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.'<br />';
- }
- }
- }
- $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.'<br />';
- }
- 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.'<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;
- }
- //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.'<br />';
- }
-
- 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.'<br />';
- }
- }
- 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.'<br />';
- }
- $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
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;
}