// (CL,pk->id) (CL,pk->id)
// | |
// ----------------------------------------------- |
- // | | | |
- // | | | |
- // | | | |
- // quiz_attempts quiz_grades quiz_question_grades |
- // (UL,pk->id, fk->quiz) (UL,pk->id,fk->quiz) (CL,pk->id,fk->quiz) |
- // | | |
- // | | |
- // | | |
- // quiz_responses | quiz_questions
- // (UL,pk->id, fk->attempt)----------------------------------------------------(CL,pk->id,fk->category,files)
- // |
- // |
- // |
+ // | | | |.......................................
+ // | | | | .
+ // | | | | .
+ // quiz_attempts quiz_grades quiz_question_grades | ----quiz_question_datasets---- .
+ // (UL,pk->id, fk->quiz) (UL,pk->id,fk->quiz) (CL,pk->id,fk->quiz) | | (CL,pk->id,fk->question, | .
+ // | | | | fk->dataset_definition) | .
+ // | | | | | .
+ // | | | | | .
+ // | | | | | .
+ // quiz_responses | quiz_questions quiz_dataset_definitions
+ // (UL,pk->id, fk->attempt)----------------------------------------------------(CL,pk->id,fk->category,files) (CL,pk->id,fk->category)
+ // | |
+ // | |
+ // | |
+ // | quiz_dataset_items
+ // | (CL,pk->id,fk->definition)
+ // |
+ // |
+ // |
// --------------------------------------------------------------------------------------------------------------
// | | | | | | |
// | | | | | | |
// - quiz_randomsamatch
// - quiz_match
// - quiz_match_sub
+ // - quiz_calculated
// - quiz_answers
// - quiz_numerical_units
+ // - quiz_question_datasets
+ // - quiz_dataset_definitions
+ // - quiz_dataset_items
// All this backup info have its own section in moodle.xml (QUESTION_CATEGORIES) and it's generated
// before every module backup standard invocation. And only if to backup quizzes has been selected !!
// It's invoked with quiz_backup_question_categories. (course independent).
$status = quiz_backup_numerical($bf,$preferences,$question->id);
} else if ($question->qtype == "9") {
$status = quiz_backup_multianswer($bf,$preferences,$question->id);
+ } else if ($question->qtype == "10") {
+ $status = quiz_backup_calculated($bf,$preferences,$question->id);
}
//End question
$status =fwrite ($bf,end_tag("QUESTION",5,true));
return $status;
}
+ //This function backups the data in a calculated question (qtype=10) and its
+ //asociated data
+ function quiz_backup_calculated($bf,$preferences,$question,$level=6,$include_answers=true) {
+
+ global $CFG;
+
+ $status = true;
+
+ $calculateds = get_records("quiz_calculated","question",$question,"id");
+ //If there are calculated-s
+ if ($calculateds) {
+ //Iterate over each calculateds
+ foreach ($calculateds as $calculated) {
+ $status =fwrite ($bf,start_tag("CALCULATED",$level,true));
+ //Print calculated contents
+ fwrite ($bf,full_tag("ANSWER",$level+1,false,$calculated->answer));
+ fwrite ($bf,full_tag("TOLERANCE",$level+1,false,$calculated->tolerance));
+ fwrite ($bf,full_tag("TOLERANCETYPE",$level+1,false,$calculated->tolerancetype));
+ fwrite ($bf,full_tag("CORRECTANSWERLENGTH",$level+1,false,$calculated->correctanswerlength));
+ //Now backup numerical_units
+ $status = quiz_backup_numerical_units($bf,$preferences,$question,7);
+ //Now backup required dataset definitions and items...
+ $status = quiz_backup_datasets($bf,$preferences,$question,7);
+ //End calculated data
+ $status =fwrite ($bf,end_tag("CALCULATED",$level,true));
+ }
+ //Now print quiz_answers
+ if ($include_answers) {
+ $status = quiz_backup_answers($bf,$preferences,$question);
+ }
+ }
+ return $status;
+ }
+
//This function backups the answers data in some question types
- //(truefalse, shortanswer,multichoice,numerical)
+ //(truefalse, shortanswer,multichoice,numerical,calculated)
function quiz_backup_answers($bf,$preferences,$question) {
global $CFG;
}
+ //This function backups dataset_definitions (via question_datasets) from different question types
+ function quiz_backup_datasets($bf,$preferences,$question,$level=7) {
+
+ global $CFG;
+
+ $status = true;
+
+ //First, we get the used datasets for this question
+ $question_datasets = get_records("quiz_question_datasets","question",$question,"id");
+ //If there are question_datasets
+ if ($question_datasets) {
+ $status =fwrite ($bf,start_tag("DATASET_DEFINITIONS",$level,true));
+ //Iterate over each question_dataset
+ foreach ($question_datasets as $question_dataset) {
+ $def = NULL;
+ //Get dataset_definition
+ if ($def = get_record("quiz_dataset_definitions","id",$question_dataset->datasetdefinition)) {;
+ $status =fwrite ($bf,start_tag("DATASET_DEFINITION",$level+1,true));
+ //Print question_dataset contents
+ fwrite ($bf,full_tag("CATEGORY",$level+2,false,$def->category));
+ fwrite ($bf,full_tag("NAME",$level+2,false,$def->name));
+ fwrite ($bf,full_tag("TYPE",$level+2,false,$def->type));
+ fwrite ($bf,full_tag("OPTIONS",$level+2,false,$def->options));
+ fwrite ($bf,full_tag("ITEMCOUNT",$level+2,false,$def->itemcount));
+ //Now backup dataset_entries
+ $status = quiz_backup_dataset_items($bf,$preferences,$def->id,$level+2);
+ //End dataset definition
+ $status =fwrite ($bf,end_tag("DATASET_DEFINITION",$level+1,true));
+ }
+ }
+ $status =fwrite ($bf,end_tag("DATASET_DEFINITIONS",$level,true));
+ }
+
+ return $status;
+
+ }
+
+ //This function backups datases_items from dataset_definitions
+ function quiz_backup_dataset_items($bf,$preferences,$datasetdefinition,$level=9) {
+
+ global $CFG;
+
+ $status = true;
+
+ //First, we get the datasets_items for this dataset_definition
+ $dataset_items = get_records("quiz_dataset_items","definition",$datasetdefinition,"id");
+ //If there are dataset_items
+ if ($dataset_items) {
+ $status =fwrite ($bf,start_tag("DATASET_ITEMS",$level,true));
+ //Iterate over each dataset_item
+ foreach ($dataset_items as $dataset_item) {
+ $status =fwrite ($bf,start_tag("DATASET_ITEM",$level+1,true));
+ //Print question_dataset contents
+ fwrite ($bf,full_tag("NUMBER",$level+2,false,$dataset_item->number));
+ fwrite ($bf,full_tag("VALUE",$level+2,false,$dataset_item->value));
+ //End dataset definition
+ $status =fwrite ($bf,end_tag("DATASET_ITEM",$level+1,true));
+ }
+ $status =fwrite ($bf,end_tag("DATASET_ITEMS",$level,true));
+ }
+
+ return $status;
+
+ }
//STEP 2. Backup quizzes and associated structures
// (course dependent)
//This php script contains all the stuff to backup/restore
//quiz mods
- //To see, put your terminal to 132cc
+ //To see, put your terminal to 160cc
//This is the "graphical" structure of the quiz mod:
//
// (CL,pk->id) (CL,pk->id)
// | |
// ----------------------------------------------- |
- // | | | |
- // | | | |
- // | | | |
- // quiz_attempts quiz_grades quiz_question_grades |
- // (UL,pk->id, fk->quiz) (UL,pk->id,fk->quiz) (CL,pk->id,fk->quiz) |
- // | | |
- // | | |
- // | | |
- // quiz_responses | quiz_questions
- // (UL,pk->id, fk->attempt)----------------------------------------------------(CL,pk->id,fk->category,files)
+ // | | | |.......................................
+ // | | | | .
+ // | | | | .
+ // quiz_attempts quiz_grades quiz_question_grades | ----quiz_question_datasets---- .
+ // (UL,pk->id, fk->quiz) (UL,pk->id,fk->quiz) (CL,pk->id,fk->quiz) | | (CL,pk->id,fk->question, | .
+ // | | | | fk->dataset_definition) | .
+ // | | | | | .
+ // | | | | | .
+ // | | | | | .
+ // quiz_responses | quiz_questions quiz_dataset_definitions
+ // (UL,pk->id, fk->attempt)----------------------------------------------------(CL,pk->id,fk->category,files) (CL,pk->id,fk->category)
+ // | |
+ // | |
+ // | |
+ // | quiz_dataset_items
+ // | (CL,pk->id,fk->definition)
// |
// |
// |
// - quiz_randomsamatch
// - quiz_match
// - quiz_match_sub
+ // - quiz_calculated
// - quiz_answers
// - quiz_numerical_units
+ // - quiz_question_datasets
+ // - quiz_dataset_definitions
+ // - quiz_dataset_items
// All this backup info have its own section in moodle.xml (QUESTION_CATEGORIES) and it's generated
// before every module backup standard invocation. And only if to restore quizzes has been selected !!
// It's invoked with quiz_restore_question_categories. (course independent).
$status = quiz_restore_numerical($oldid,$newid,$que_info,$restore);
} else if ($question->qtype == "9") {
$status = quiz_restore_multianswer($oldid,$newid,$que_info,$restore);
+ } else if ($question->qtype == "10") {
+ $status = quiz_restore_calculated($oldid,$newid,$que_info,$restore);
}
} else {
//We are NOT creating the question, but we need to know every quiz_answers
//Numerical question. Nothing to remap
} else if ($question->qtype == "9") {
$status = quiz_restore_map_multianswer($oldid,$newid,$que_info,$restore);
+ } else if ($question->qtype == "10") {
+ //Calculated question. Nothing to remap
}
}
}
return $status;
}
+ function quiz_restore_calculated ($old_question_id,$new_question_id,$info,$restore) {
+
+ global $CFG;
+
+ $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 QUIZ_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']['#']);
+
+ ////We have to recode the answer field
+ $answer = backup_getid($restore->backup_unique_code,"quiz_answers",$calculated->answer);
+ if ($answer) {
+ $calculated->answer = $answer->new_id;
+ }
+
+ //The structure is equal to the db, so insert the quiz_calculated
+ $newid = insert_record ("quiz_calculated",$calculated);
+
+ //Do some output
+ if (($i+1) % 50 == 0) {
+ echo ".";
+ if (($i+1) % 1000 == 0) {
+ echo "<br>";
+ }
+ backup_flush(300);
+ }
+
+ //Now restore numerical_units
+ $status = quiz_restore_numerical_units ($old_question_id,$new_question_id,$cal_info,$restore);
+
+ //Now restore dataset_definitions
+ if ($status && $newid) {
+ $status = quiz_restore_dataset_definitions ($old_question_id,$new_question_id,$cal_info,$restore);
+ }
+
+ if (!$newid) {
+ $status = false;
+ }
+ }
+
+ return $status;
+ }
+
function quiz_restore_multianswer ($old_question_id,$new_question_id,$info,$restore) {
global $CFG;
//Iterate over numerical_units
for($i = 0; $i < sizeof($numerical_units); $i++) {
$nu_info = $numerical_units[$i];
- traverse_xmlize($nu_info); //Debug
- print_object ($GLOBALS['traverse_array']); //Debug
- $GLOBALS['traverse_array']=""; //Debug
+ //traverse_xmlize($nu_info); //Debug
+ //print_object ($GLOBALS['traverse_array']); //Debug
+ //$GLOBALS['traverse_array']=""; //Debug
//Now, build the QUIZ_NUMERICAL_UNITS record structure
$numerical_unit->question = $new_question_id;
return $status;
}
+ function quiz_restore_dataset_definitions ($old_question_id,$new_question_id,$info,$restore) {
+
+ global $CFG;
+
+ $status = true;
+
+ //Get the dataset_definitions array
+ $dataset_definitions = $info['#']['DATASET_DEFINITIONS']['0']['#']['DATASET_DEFINITION'];
+
+ //Iterate over dataset_definitions
+ for($i = 0; $i < sizeof($dataset_definitions); $i++) {
+ $dd_info = $dataset_definitions[$i];
+ //traverse_xmlize($dd_info); //Debug
+ //print_object ($GLOBALS['traverse_array']); //Debug
+ //$GLOBALS['traverse_array']=""; //Debug
+
+ //Now, build the QUIZ_DATASET_DEFINITION record structure
+ $dataset_definition->category = backup_todb($dd_info['#']['CATEGORY']['0']['#']);
+ $dataset_definition->name = backup_todb($dd_info['#']['NAME']['0']['#']);
+ $dataset_definition->type = backup_todb($dd_info['#']['TYPE']['0']['#']);
+ $dataset_definition->options = backup_todb($dd_info['#']['OPTIONS']['0']['#']);
+ $dataset_definition->itemcount = backup_todb($dd_info['#']['ITEMCOUNT']['0']['#']);
+
+ //We have to recode the category field (only if the category != 0)
+ if ($dataset_definition->category != 0) {
+ $category = backup_getid($restore->backup_unique_code,"quiz_categories",$dataset_definition->category);
+ if ($category) {
+ $dataset_definition->category = $category->new_id;
+ }
+ }
+
+ //Now, we hace to decide when to create the new records or reuse an existing one
+ $create_definition = false;
+
+ //If the dataset_definition->category = 0, it's a individual question dataset_definition, so we'll create it
+ if ($dataset_definition->category == 0) {
+ $create_definition = true;
+ } else {
+ //The category isn't 0, so it's a category question dataset_definition, we have to see if it exists
+ //Look for a definition with the same category, name and type
+ if ($definitionrec = get_record_sql("SELECT d.*
+ FROM {$CFG->prefix}quiz_dataset_definitions d
+ WHERE d.category = '$dataset_definition->category' AND
+ d.name = '$dataset_definition->name' AND
+ d.type = '$dataset_definition->type'")) {
+ //Such dataset_definition exist. Now we must check if it has enough itemcount
+ if ($definitionrec->itemcount < $dataset_definition->itemcount) {
+ //We haven't enough itemcount, so we have to create the definition as an individual question one.
+ $dataset_definition->category = 0;
+ $create_definition = true;
+ } else {
+ //We have enough itemcount, so we'll reuse the existing definition
+ $create_definition = false;
+ $newid = $definitionrec->id;
+ }
+ } else {
+ //Such dataset_definition doesn't exist. We'll create it.
+ $create_definition = true;
+ }
+ }
+
+ //If we've to create the definition, do it
+ if ($create_definition) {
+ //The structure is equal to the db, so insert the quiz_dataset_definitions
+ $newid = insert_record ("quiz_dataset_definitions",$dataset_definition);
+ if ($newid) {
+ //Restore quiz_dataset_items
+ $status = quiz_restore_dataset_items($newid,$dd_info,$restore);
+ }
+ }
+
+ //Now, we must have a definition (created o reused). Its id is in newid. Create the quiz_question_datasets record
+ //to join the question and the dataset_definition
+ if ($newid) {
+ $question_dataset->question = $new_question_id;
+ $question_dataset->datasetdefinition = $newid;
+ $newid = insert_record ("quiz_question_datasets",$question_dataset);
+ }
+
+ if (!$newid) {
+ $status = false;
+ }
+ }
+
+ return $status;
+ }
+
+ function quiz_restore_dataset_items ($definitionid,$info,$restore) {
+
+ global $CFG;
+
+ $status = true;
+
+ //Get the items array
+ $dataset_items = $info['#']['DATASET_ITEMS']['0']['#']['DATASET_ITEM'];
+
+ //Iterate over dataset_items
+ for($i = 0; $i < sizeof($dataset_items); $i++) {
+ $di_info = $dataset_items[$i];
+ //traverse_xmlize($di_info); //Debug
+ //print_object ($GLOBALS['traverse_array']); //Debug
+ //$GLOBALS['traverse_array']=""; //Debug
+
+ //Now, build the QUIZ_DATASET_ITEMS record structure
+ $dataset_item->definition = $definitionid;
+ $dataset_item->number = backup_todb($di_info['#']['NUMBER']['0']['#']);
+ $dataset_item->value = backup_todb($di_info['#']['VALUE']['0']['#']);
+
+ //The structure is equal to the db, so insert the quiz_dataset_items
+ $newid = insert_record ("quiz_dataset_items",$dataset_item);
+
+ if (!$newid) {
+ $status = false;
+ }
+ }
+
+ return $status;
+ }
//STEP 2. Restore quizzes and associated structures
// (course dependent)
}
$response->answer = $answer_field;
break;
+ case 10: //CALCULATED QTYPE
+ //Nothing to do. The response is a text.
+ break;
default: //UNMATCHED QTYPE.
//This is an error (unimplemented qtype)
$status = false;