function restore_questions($old_category_id, $best_question_cat, $info, $restore) { global $CFG, $QTYPES; $status = true; $restored_questions = array(); //Get the questions array if (!empty($info['QUESTION_CATEGORY']['#']['QUESTIONS'])) { $questions = $info['QUESTION_CATEGORY']['#']['QUESTIONS']['0']['#']['QUESTION']; } else { $questions = array(); } //Iterate over questions for ($i = 0; $i < sizeof($questions); $i++) { $que_info = $questions[$i]; //traverse_xmlize($que_info); //Debug //print_object ($GLOBALS['traverse_array']); //Debug //$GLOBALS['traverse_array']=""; //Debug //We'll need this later!! $oldid = backup_todb($que_info['#']['ID']['0']['#']); //Now, build the question record structure $question = new object(); $question->parent = backup_todb($que_info['#']['PARENT']['0']['#']); $question->name = backup_todb($que_info['#']['NAME']['0']['#']); $question->questiontext = backup_todb($que_info['#']['QUESTIONTEXT']['0']['#']); $question->questiontextformat = backup_todb($que_info['#']['QUESTIONTEXTFORMAT']['0']['#']); $question->image = backup_todb($que_info['#']['IMAGE']['0']['#']); $question->generalfeedback = backup_todb_optional_field($que_info, 'GENERALFEEDBACK', ''); $question->defaultgrade = backup_todb($que_info['#']['DEFAULTGRADE']['0']['#']); $question->penalty = backup_todb($que_info['#']['PENALTY']['0']['#']); $question->qtype = backup_todb($que_info['#']['QTYPE']['0']['#']); $question->length = backup_todb($que_info['#']['LENGTH']['0']['#']); $question->stamp = backup_todb($que_info['#']['STAMP']['0']['#']); $question->version = backup_todb($que_info['#']['VERSION']['0']['#']); $question->hidden = backup_todb($que_info['#']['HIDDEN']['0']['#']); $question->timecreated = backup_todb_optional_field($que_info, 'TIMECREATED', 0); $question->timemodified = backup_todb_optional_field($que_info, 'TIMEMODIFIED', 0); $question->createdby = backup_todb_optional_field($que_info, 'CREATEDBY', null); $question->modifiedby = backup_todb_optional_field($que_info, 'MODIFIEDBY', null); if ($restore->backup_version < 2006032200) { // The qtype was an integer that now needs to be converted to the name $qtypenames = array(1 => 'shortanswer', 2 => 'truefalse', 3 => 'multichoice', 4 => 'random', 5 => 'match', 6 => 'randomsamatch', 7 => 'description', 8 => 'numerical', 9 => 'multianswer', 10 => 'calculated', 11 => 'rqp', 12 => 'essay'); $question->qtype = $qtypenames[$question->qtype]; } //Check if the question exists by category, stamp, and version //first check for the question in the context specified in backup $existingquestion = get_record("question", "category", $best_question_cat->id, "stamp", $question->stamp, "version", $question->version); //If the question exists, only record its id //always use existing question, no permissions check here if ($existingquestion) { $question = $existingquestion; $creatingnewquestion = false; } else { //then if context above course level check permissions and if no permission //to restore above course level then restore to cat in course context. $bestcontext = get_context_instance_by_id($best_question_cat->contextid); if (($bestcontext->contextlevel == CONTEXT_SYSTEM || $bestcontext->contextlevel == CONTEXT_COURSECAT) && !has_capability('moodle/question:add', $bestcontext)) { if (!isset($course_question_cat)) { $coursecontext = get_context_instance(CONTEXT_COURSE, $restore->course_id); $course_question_cat = clone $best_question_cat; $course_question_cat->contextid = $coursecontext->id; //create cat if it doesn't exist if (!($fcat = get_record('question_categories', 'contextid', $course_question_cat->contextid, 'stamp', $course_question_cat->stamp))) { $course_question_cat->id = insert_record("question_categories", $course_question_cat); backup_putid($restore->backup_unique_code, "question_categories", $old_category_id, $course_question_cat->id); } else { $course_question_cat = $fcat; } //will fix category parents after all questions and categories restored. Will set parent to 0 if //no parent in same context. } $question->category = $course_question_cat->id; //does question already exist in course cat $existingquestion = get_record("question", "category", $question->category, "stamp", $question->stamp, "version", $question->version); } else { //permissions ok, restore to best cat $question->category = $best_question_cat->id; } if (!$existingquestion) { //The structure is equal to the db, so insert the question $question->id = insert_record("question", $question); $creatingnewquestion = true; } else { $question = $existingquestion; $creatingnewquestion = false; } } // Fixing bug #5482: random questions have parent field set to its own id, // see: $QTYPES['random']->get_question_options() if ($question->qtype == 'random' && $creatingnewquestion) { $question->parent = $question->id; $status = set_field('question', 'parent', $question->parent, 'id', $question->id); } //Save newid to backup tables if ($question->id) { //We have the newid, update backup_ids backup_putid($restore->backup_unique_code, "question", $oldid, $question->id); } $restored_questions[$i] = new stdClass(); $restored_questions[$i]->newid = $question->id; $restored_questions[$i]->oldid = $oldid; $restored_questions[$i]->qtype = $question->qtype; $restored_questions[$i]->parent = $question->parent; $restored_questions[$i]->is_new = $creatingnewquestion; } backup_flush(300); // Loop again, now all the question id mappings exist, so everything can // be restored. for ($i = 0; $i < sizeof($questions); $i++) { $que_info = $questions[$i]; $newid = $restored_questions[$i]->newid; $oldid = $restored_questions[$i]->oldid; $question = new object(); $question->qtype = $restored_questions[$i]->qtype; $question->parent = $restored_questions[$i]->parent; /// If it's a new question in the DB, restore it if ($restored_questions[$i]->is_new) { /// We have to recode the parent field if ($question->parent && $question->qtype != 'random') { /// If the parent field needs to be changed, do it here. Random questions are dealt with above. if ($parent = backup_getid($restore->backup_unique_code, "question", $question->parent)) { $question->parent = $parent->new_id; if ($question->parent != $restored_questions[$i]->parent) { if (!set_field('question', 'parent', $question->parent, 'id', $newid)) { echo 'Could not update parent ' . $question->parent . ' for question ' . $oldid . '<br />'; $status = false; } } } else { echo 'Could not recode parent ' . $question->parent . ' for question ' . $oldid . '<br />'; $status = false; } } //Now, restore every question_answers in this question $status = question_restore_answers($oldid, $newid, $que_info, $restore); // Restore questiontype specific data if (array_key_exists($question->qtype, $QTYPES)) { $status = $QTYPES[$question->qtype]->restore($oldid, $newid, $que_info, $restore); } else { echo 'Unknown question type ' . $question->qtype . ' for question ' . $oldid . '<br />'; $status = false; } } 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); // Do the questiontype specific mapping if (array_key_exists($question->qtype, $QTYPES)) { $status = $QTYPES[$question->qtype]->restore_map($oldid, $newid, $que_info, $restore); } else { echo 'Unknown question type ' . $question->qtype . ' for question ' . $oldid . '<br />'; $status = false; } } //Do some output if (($i + 1) % 2 == 0) { if (!defined('RESTORE_SILENTLY')) { echo "."; if (($i + 1) % 40 == 0) { echo "<br />"; } } backup_flush(300); } } return $status; }
function restore_questions($old_category_id, $new_category_id, $info, $restore) { global $CFG, $QTYPES; $status = true; $restored_questions = array(); //Get the questions array if (!empty($info['QUESTION_CATEGORY']['#']['QUESTIONS'])) { $questions = $info['QUESTION_CATEGORY']['#']['QUESTIONS']['0']['#']['QUESTION']; } else { $questions = array(); } //Iterate over questions for ($i = 0; $i < sizeof($questions); $i++) { $que_info = $questions[$i]; //traverse_xmlize($que_info); //Debug //print_object ($GLOBALS['traverse_array']); //Debug //$GLOBALS['traverse_array']=""; //Debug //We'll need this later!! $oldid = backup_todb($que_info['#']['ID']['0']['#']); //Now, build the question record structure $question = new object(); $question->category = $new_category_id; $question->parent = backup_todb($que_info['#']['PARENT']['0']['#']); $question->name = backup_todb($que_info['#']['NAME']['0']['#']); $question->questiontext = backup_todb($que_info['#']['QUESTIONTEXT']['0']['#']); $question->questiontextformat = backup_todb($que_info['#']['QUESTIONTEXTFORMAT']['0']['#']); $question->image = backup_todb($que_info['#']['IMAGE']['0']['#']); if (array_key_exists('GENERALFEEDBACK', $que_info['#'])) { $question->generalfeedback = backup_todb($que_info['#']['GENERALFEEDBACK']['0']['#']); } else { $question->generalfeedback = ''; } $question->defaultgrade = backup_todb($que_info['#']['DEFAULTGRADE']['0']['#']); $question->penalty = backup_todb($que_info['#']['PENALTY']['0']['#']); $question->qtype = backup_todb($que_info['#']['QTYPE']['0']['#']); $question->length = backup_todb($que_info['#']['LENGTH']['0']['#']); $question->stamp = backup_todb($que_info['#']['STAMP']['0']['#']); $question->version = backup_todb($que_info['#']['VERSION']['0']['#']); $question->hidden = backup_todb($que_info['#']['HIDDEN']['0']['#']); if ($restore->backup_version < 2006032200) { // The qtype was an integer that now needs to be converted to the name $qtypenames = array(1 => 'shortanswer', 2 => 'truefalse', 3 => 'multichoice', 4 => 'random', 5 => 'match', 6 => 'randomsamatch', 7 => 'description', 8 => 'numerical', 9 => 'multianswer', 10 => 'calculated', 11 => 'rqp', 12 => 'essay'); $question->qtype = $qtypenames[$question->qtype]; } //Check if the question exists //by category, stamp, and version $question_exists = get_record("question", "category", $question->category, "stamp", $question->stamp, "version", $question->version); //If the question exists, only record its id if ($question_exists) { $newid = $question_exists->id; $creatingnewquestion = false; //Else, create a new question } else { //The structure is equal to the db, so insert the question $newid = insert_record("question", $question); $creatingnewquestion = true; } // 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 ($newid) { //We have the newid, update backup_ids backup_putid($restore->backup_unique_code, "question", $oldid, $newid); } $restored_questions[$i] = new stdClass(); $restored_questions[$i]->newid = $newid; $restored_questions[$i]->oldid = $oldid; $restored_questions[$i]->qtype = $question->qtype; $restored_questions[$i]->parent = $question->parent; $restored_questions[$i]->is_new = $creatingnewquestion; } // Loop again, now all the question id mappings exist, so everything can // be restored. for ($i = 0; $i < sizeof($questions); $i++) { $que_info = $questions[$i]; $newid = $restored_questions[$i]->newid; $oldid = $restored_questions[$i]->oldid; $question = new object(); $question->qtype = $restored_questions[$i]->qtype; $question->parent = $restored_questions[$i]->parent; /// If it's a new question in the DB, restore it if ($restored_questions[$i]->is_new) { /// We have to recode the parent field if ($question->parent && $question->qtype != 'random') { /// If the parent field needs to be changed, do it here. Random questions are dealt with above. if ($parent = backup_getid($restore->backup_unique_code, "question", $question->parent)) { $question->parent = $parent->new_id; if ($question->parent != $restored_questions[$i]->parent) { if (!set_field('question', 'parent', $question->parent, 'id', $newid)) { echo 'Could not update parent ' . $question->parent . ' for question ' . $oldid . '<br />'; $status = false; } } } else { echo 'Could not recode parent ' . $question->parent . ' for question ' . $oldid . '<br />'; $status = false; } } //Now, restore every question_answers in this question $status = question_restore_answers($oldid, $newid, $que_info, $restore); // Restore questiontype specific data if (array_key_exists($question->qtype, $QTYPES)) { $status = $QTYPES[$question->qtype]->restore($oldid, $newid, $que_info, $restore); } else { echo 'Unknown question type ' . $question->qtype . ' for question ' . $oldid . '<br />'; $status = false; } } 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); // Do the questiontype specific mapping if (array_key_exists($question->qtype, $QTYPES)) { $status = $QTYPES[$question->qtype]->restore_map($oldid, $newid, $que_info, $restore); } else { echo 'Unknown question type ' . $question->qtype . ' for question ' . $oldid . '<br />'; $status = false; } } //Do some output if (($i + 1) % 2 == 0) { if (!defined('RESTORE_SILENTLY')) { echo "."; if (($i + 1) % 40 == 0) { echo "<br />"; } } backup_flush(300); } } return $status; }