id)
// |
// |
// |.......................................
// | .
// | .
// | -------question_datasets------ .
// | | (CL,pk->id,fk->question, | .
// | | fk->dataset_definition) | .
// | | | .
// | | | .
// | | | .
// | | question_dataset_definitions
// | | (CL,pk->id,fk->category)
// question |
// (CL,pk->id,fk->category,files) |
// | question_dataset_items
// | (CL,pk->id,fk->definition)
// | question_rqp_type
// | (SL,pk->id)
// | |
// -------------------------------------------------------------------------------------------------------------- |
// | | | | | | | question_rqp
// | | | | | | |--(CL,pk->id,fk->question)
// | | | | question_calculated | |
// question_truefalse | question_multichoice | (CL,pl->id,fk->question) | |
// (CL,pk->id,fk->question) | (CL,pk->id,fk->question) | . | | question_randomsamatch
// . | . | . | |--(CL,pk->id,fk->question)
// . question_shortanswer . question_numerical . question_multianswer. |
// . (CL,pk->id,fk->question) . (CL,pk->id,fk->question) . (CL,pk->id,fk->question) |
// . . . . . . | question_match
// . . . . . . |--(CL,pk->id,fk->question)
// . . . . . . | .
// . . . . . . | .
// . . . . . . | .
// . . . . . . | question_match_sub
// ........................................................................................ |--(CL,pk->id,fk->question)
// . |
// . |
// . | question_numerical_units
// question_answers |--(CL,pk->id,fk->question)
// (CL,pk->id,fk->question)----------------------------------------------------------
//
//
// The following holds the information about student interaction with the questions
//
// question_sessions
// (UL,pk->id,fk->attempt,question)
// .
// .
// question_states
// (UL,pk->id,fk->attempt,question)
// |
// question_rqp_states
// (UL,pk->id,fk->stateid)
//
// Meaning: pk->primary key field of the table
// fk->foreign key to link with parent
// nt->nested field (recursive data)
// SL->site level info
// CL->course level info
// UL->user level info
// files->table may have files
//
//-----------------------------------------------------------
include_once($CFG->libdir.'/questionlib.php');
function restore_question_categories($category,$restore) {
global $CFG;
$status = true;
//Hook to call Moodle < 1.5 Quiz Restore
if ($restore->backup_version < 2005043000) {
include_once($CFG->dirroot.'/mod/quiz/restorelibpre15.php');
return quiz_restore_pre15_question_categories($category,$restore);
}
//Get record from backup_ids
$data = backup_getid($restore->backup_unique_code,"question_categories",$category->id);
if ($data) {
//Now get completed xmlized object
$info = $data->info;
//traverse_xmlize($info); //Debug
//print_object ($GLOBALS['traverse_array']); //Debug
//$GLOBALS['traverse_array']=""; //Debug
//Now, build the question_categories record structure
$question_cat = new stdClass;
$question_cat->course = $restore->course_id;
$question_cat->name = backup_todb($info['QUESTION_CATEGORY']['#']['NAME']['0']['#']);
$question_cat->info = backup_todb($info['QUESTION_CATEGORY']['#']['INFO']['0']['#']);
$question_cat->publish = backup_todb($info['QUESTION_CATEGORY']['#']['PUBLISH']['0']['#']);
$question_cat->stamp = backup_todb($info['QUESTION_CATEGORY']['#']['STAMP']['0']['#']);
$question_cat->parent = backup_todb($info['QUESTION_CATEGORY']['#']['PARENT']['0']['#']);
$question_cat->sortorder = backup_todb($info['QUESTION_CATEGORY']['#']['SORTORDER']['0']['#']);
if ($catfound = restore_get_best_question_category($question_cat, $restore->course_id)) {
$newid = $catfound;
} else {
if (!$question_cat->stamp) {
$question_cat->stamp = make_unique_id_code();
}
$newid = insert_record ("question_categories",$question_cat);
}
//Do some output
if ($newid) {
if (!defined('RESTORE_SILENTLY')) {
echo "
".get_string('category', 'quiz')." \"".$question_cat->name."\"
";
}
} else {
//We must never arrive here !!
if (!defined('RESTORE_SILENTLY')) {
echo "".get_string('category', 'quiz')." \"".$question_cat->name."\" Error!
";
}
$status = false;
}
backup_flush(300);
//Here category has been created or selected, so save results in backup_ids and start with questions
if ($newid and $status) {
//We have the newid, update backup_ids
backup_putid($restore->backup_unique_code,"question_categories",
$category->id, $newid);
//Now restore question
$status = restore_questions ($category->id, $newid,$info,$restore);
} else {
$status = false;
}
if (!defined('RESTORE_SILENTLY')) {
echo '';
}
} else {
echo 'Could not get backup info for question category'. $category->id;
}
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;
}
//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) {
if ($parent = backup_getid($restore->backup_unique_code,"question",$question->parent)) {
$question->parent = $parent->new_id;
} elseif ($question->parent = $oldid) {
$question->parent = $newid;
} else {
echo 'Could not recode parent '.$question->parent.' for question '.$oldid.'
';
}
}
//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.'
';
$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)) {