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 // //----------------------------------------------------------- require_once("$CFG->libdir/questionlib.php"); function backup_question_categories($bf,$preferences) { global $CFG; $status = true; //First, we get the used categories from backup_ids $categories = question_category_ids_by_backup ($preferences->backup_unique_code); //If we've categories if ($categories) { //Write start tag $status = fwrite($bf,start_tag("QUESTION_CATEGORIES",2,true)); //Iterate over each category foreach ($categories as $cat) { //Start category $status = fwrite ($bf,start_tag("QUESTION_CATEGORY",3,true)); //Get category data from question_categories $category = get_record ("question_categories","id",$cat->old_id); //Print category contents fwrite($bf,full_tag("ID",4,false,$category->id)); fwrite($bf,full_tag("NAME",4,false,$category->name)); fwrite($bf,full_tag("INFO",4,false,$category->info)); fwrite($bf,full_tag("PUBLISH",4,false,$category->publish)); fwrite($bf,full_tag("STAMP",4,false,$category->stamp)); fwrite($bf,full_tag("PARENT",4,false,$category->parent)); fwrite($bf,full_tag("SORTORDER",4,false,$category->sortorder)); //Now, backup their questions $status = backup_question($bf,$preferences,$category->id); //End category $status = fwrite ($bf,end_tag("QUESTION_CATEGORY",3,true)); } //Write end tag $status = fwrite ($bf,end_tag("QUESTION_CATEGORIES",2,true)); } return $status; } //This function backups all the questions in selected category and their //asociated data function backup_question($bf,$preferences,$category) { global $CFG, $QTYPES; $status = true; // We'll fetch the questions sorted by parent so that questions with no parents // (these are the ones which could be parents themselves) are backed up first. This // is important for the recoding of the parent field during the restore process $questions = get_records("question","category",$category,"parent ASC, id"); //If there are questions if ($questions) { //Write start tag $status = fwrite ($bf,start_tag("QUESTIONS",4,true)); $counter = 0; //Iterate over each question foreach ($questions as $question) { //Start question $status = fwrite ($bf,start_tag("QUESTION",5,true)); //Print question contents fwrite ($bf,full_tag("ID",6,false,$question->id)); fwrite ($bf,full_tag("PARENT",6,false,$question->parent)); fwrite ($bf,full_tag("NAME",6,false,$question->name)); fwrite ($bf,full_tag("QUESTIONTEXT",6,false,$question->questiontext)); fwrite ($bf,full_tag("QUESTIONTEXTFORMAT",6,false,$question->questiontextformat)); fwrite ($bf,full_tag("IMAGE",6,false,$question->image)); fwrite ($bf,full_tag("GENERALFEEDBACK",6,false,$question->generalfeedback)); fwrite ($bf,full_tag("DEFAULTGRADE",6,false,$question->defaultgrade)); fwrite ($bf,full_tag("PENALTY",6,false,$question->penalty)); fwrite ($bf,full_tag("QTYPE",6,false,$question->qtype)); fwrite ($bf,full_tag("LENGTH",6,false,$question->length)); fwrite ($bf,full_tag("STAMP",6,false,$question->stamp)); fwrite ($bf,full_tag("VERSION",6,false,$question->version)); fwrite ($bf,full_tag("HIDDEN",6,false,$question->hidden)); // Backup question type specific data $status = $QTYPES[$question->qtype]->backup($bf,$preferences,$question->id); //End question $status = fwrite ($bf,end_tag("QUESTION",5,true)); //Do some output $counter++; if ($counter % 10 == 0) { echo "."; if ($counter % 200 == 0) { echo "
"; } backup_flush(300); } } //Write end tag $status = fwrite ($bf,end_tag("QUESTIONS",4,true)); } return $status; } //This function backups the answers data in some question types //(truefalse, shortanswer,multichoice,numerical,calculated) function question_backup_answers($bf,$preferences,$question) { global $CFG; $status = true; $answers = get_records("question_answers","question",$question,"id"); //If there are answers if ($answers) { $status = fwrite ($bf,start_tag("ANSWERS",6,true)); //Iterate over each answer foreach ($answers as $answer) { $status = fwrite ($bf,start_tag("ANSWER",7,true)); //Print answer contents fwrite ($bf,full_tag("ID",8,false,$answer->id)); fwrite ($bf,full_tag("ANSWER_TEXT",8,false,$answer->answer)); fwrite ($bf,full_tag("FRACTION",8,false,$answer->fraction)); fwrite ($bf,full_tag("FEEDBACK",8,false,$answer->feedback)); $status = fwrite ($bf,end_tag("ANSWER",7,true)); } $status = fwrite ($bf,end_tag("ANSWERS",6,true)); } return $status; } //This function backups question_numerical_units from different question types function question_backup_numerical_units($bf,$preferences,$question,$level=7) { global $CFG; $status = true; $numerical_units = get_records("question_numerical_units","question",$question,"id"); //If there are numericals_units if ($numerical_units) { $status = fwrite ($bf,start_tag("NUMERICAL_UNITS",$level,true)); //Iterate over each numerical_unit foreach ($numerical_units as $numerical_unit) { $status = fwrite ($bf,start_tag("NUMERICAL_UNIT",$level+1,true)); //Print numerical_unit contents fwrite ($bf,full_tag("MULTIPLIER",$level+2,false,$numerical_unit->multiplier)); fwrite ($bf,full_tag("UNIT",$level+2,false,$numerical_unit->unit)); //Now backup numerical_units $status = fwrite ($bf,end_tag("NUMERICAL_UNIT",$level+1,true)); } $status = fwrite ($bf,end_tag("NUMERICAL_UNITS",$level,true)); } return $status; } //This function backups dataset_definitions (via question_datasets) from different question types function question_backup_datasets($bf,$preferences,$question,$level=7) { global $CFG; $status = true; //First, we get the used datasets for this question $question_datasets = get_records("question_datasets","question",$question,"id"); //If there are question_datasets if ($question_datasets) { $status = $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("question_dataset_definitions","id",$question_dataset->datasetdefinition)) {; $status = $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 = question_backup_dataset_items($bf,$preferences,$def->id,$level+2); //End dataset definition $status = $status &&fwrite ($bf,end_tag("DATASET_DEFINITION",$level+1,true)); } } $status = $status &&fwrite ($bf,end_tag("DATASET_DEFINITIONS",$level,true)); } return $status; } //This function backups datases_items from dataset_definitions function question_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("question_dataset_items","definition",$datasetdefinition,"id"); //If there are dataset_items if ($dataset_items) { $status = $status &&fwrite ($bf,start_tag("DATASET_ITEMS",$level,true)); //Iterate over each dataset_item foreach ($dataset_items as $dataset_item) { $status = $status &&fwrite ($bf,start_tag("DATASET_ITEM",$level+1,true)); //Print question_dataset contents fwrite ($bf,full_tag("NUMBER",$level+2,false,$dataset_item->itemnumber)); fwrite ($bf,full_tag("VALUE",$level+2,false,$dataset_item->value)); //End dataset definition $status = $status &&fwrite ($bf,end_tag("DATASET_ITEM",$level+1,true)); } $status = $status &&fwrite ($bf,end_tag("DATASET_ITEMS",$level,true)); } return $status; } //Backup question_states contents (executed from backup_quiz_attempts) function backup_question_states ($bf,$preferences,$attempt) { global $CFG; $status = true; $question_states = get_records("question_states","attempt",$attempt,"id"); //If there are states if ($question_states) { //Write start tag $status = fwrite ($bf,start_tag("STATES",6,true)); //Iterate over each state foreach ($question_states as $state) { //Start state $status = fwrite ($bf,start_tag("STATE",7,true)); //Print state contents fwrite ($bf,full_tag("ID",8,false,$state->id)); fwrite ($bf,full_tag("QUESTION",8,false,$state->question)); fwrite ($bf,full_tag("ORIGINALQUESTION",8,false,$state->originalquestion)); fwrite ($bf,full_tag("SEQ_NUMBER",8,false,$state->seq_number)); fwrite ($bf,full_tag("ANSWER",8,false,$state->answer)); fwrite ($bf,full_tag("TIMESTAMP",8,false,$state->timestamp)); fwrite ($bf,full_tag("EVENT",8,false,$state->event)); fwrite ($bf,full_tag("GRADE",8,false,$state->grade)); fwrite ($bf,full_tag("RAW_GRADE",8,false,$state->raw_grade)); fwrite ($bf,full_tag("PENALTY",8,false,$state->penalty)); // now back up question type specific state information $status = backup_question_rqp_state ($bf,$preferences,$state->id); //End state $status = fwrite ($bf,end_tag("STATE",7,true)); } //Write end tag $status = fwrite ($bf,end_tag("STATES",6,true)); } } //Backup question_sessions contents (executed from backup_quiz_attempts) function backup_question_sessions ($bf,$preferences,$attempt) { global $CFG; $status = true; $question_sessions = get_records("question_sessions","attemptid",$attempt,"id"); //If there are sessions if ($question_sessions) { //Write start tag (the funny name 'newest states' has historical reasons) $status = fwrite ($bf,start_tag("NEWEST_STATES",6,true)); //Iterate over each newest_state foreach ($question_sessions as $newest_state) { //Start newest_state $status = fwrite ($bf,start_tag("NEWEST_STATE",7,true)); //Print newest_state contents fwrite ($bf,full_tag("ID",8,false,$newest_state->id)); fwrite ($bf,full_tag("QUESTIONID",8,false,$newest_state->questionid)); fwrite ($bf,full_tag("NEWEST",8,false,$newest_state->newest)); fwrite ($bf,full_tag("NEWGRADED",8,false,$newest_state->newgraded)); fwrite ($bf,full_tag("SUMPENALTY",8,false,$newest_state->sumpenalty)); //End newest_state $status = fwrite ($bf,end_tag("NEWEST_STATE",7,true)); } //Write end tag $status = fwrite ($bf,end_tag("NEWEST_STATES",6,true)); } return $status; } //Backup question_rqp_state contents (executed from backup_question_states) function backup_question_rqp_state ($bf,$preferences,$state) { global $CFG; $status = true; $rqp_state = get_record("question_rqp_states","stateid",$state); //If there is a state if ($rqp_state) { //Write start tag $status = fwrite ($bf,start_tag("RQP_STATE",8,true)); //Print state contents fwrite ($bf,full_tag("RESPONSES",9,false,$rqp_state->responses)); fwrite ($bf,full_tag("PERSISTENT_DATA",9,false,$rqp_state->persistent_data)); fwrite ($bf,full_tag("TEMPLATE_VARS",9,false,$rqp_state->template_vars)); //Write end tag $status = fwrite ($bf,end_tag("RQP_STATE",8,true)); } return $status; } //Returns an array of categories id function question_category_ids_by_backup ($backup_unique_code) { global $CFG; return get_records_sql ("SELECT a.old_id, a.backup_code FROM {$CFG->prefix}backup_ids a WHERE a.backup_code = '$backup_unique_code' AND a.table_name = 'question_categories'"); } function question_ids_by_backup ($backup_unique_code) { global $CFG; return get_records_sql ("SELECT q.id, q.category FROM {$CFG->prefix}backup_ids a, {$CFG->prefix}question q WHERE a.backup_code = '$backup_unique_code' AND q.category = a.old_id AND a.table_name = 'question_categories'"); } //Delete category ids from backup_ids table function delete_category_ids ($backup_unique_code) { global $CFG; $status = true; $status = execute_sql("DELETE FROM {$CFG->prefix}backup_ids WHERE backup_code = '$backup_unique_code'",false); return $status; } ?>