2 //This php script contains all the stuff to backup/restore
5 //To see, put your terminal to 160cc
7 //This is the "graphical" structure of the quiz mod:
9 // quiz quiz_categories
10 // (CL,pk->id) (CL,pk->id)
12 // ------------------------------------------------------------------- |
13 // | | | | |.......................................
16 // quiz_attempts quiz_grades quiz_question_grades quiz_question_versions | ----quiz_question_datasets---- .
17 // (UL,pk->id, fk->quiz) (UL,pk->id,fk->quiz) (CL,pk->id,fk->quiz) (CL,pk->id,fk->quiz) | | (CL,pk->id,fk->question, | .
18 // | | . | | fk->dataset_definition) | .
22 // quiz_responses | quiz_questions quiz_dataset_definitions
23 // (UL,pk->id, fk->attempt)----------------------------------------------------(CL,pk->id,fk->category,files) (CL,pk->id,fk->category)
27 // | quiz_dataset_items
28 // | (CL,pk->id,fk->definition)
32 // --------------------------------------------------------------------------------------------------------------
35 // | | | | quiz_calculated | | quiz_randomsamatch
36 // quiz_truefalse | quiz_multichoice | (CL,pl->id,fk->question) | |--(CL,pl->id,fk->question)
37 // (CL,pl->id,fk->question) | (CL,pl->id,fk->question) | . | |
39 // . quiz_shortanswer . quiz_numerical . quiz_multianswer. |
40 // . (CL,pl->id,fk->question) . (CL,pl->id,fk->question) . (CL,pl->id,fk->question) | quiz_match
41 // . . . . . . |--(CL,pl->id,fk->question)
45 // . . . . . . | quiz_match_sub
46 // . . . . . . |--(CL,pl->id,fk->question)
47 // ........................................................................................ |
50 // . | quiz_numerical_units
51 // quiz_answers |--(CL,pl->id,fk->question)
52 // (CL,pk->id,fk->question)----------------------------------------------------------
54 // Meaning: pk->primary key field of the table
55 // fk->foreign key to link with parent
56 // nt->nested field (recursive data)
57 // CL->course level info
58 // UL->user level info
59 // files->table may have files
61 //-----------------------------------------------------------
63 //This module is special, because we make the restore in two steps:
64 // 1.-We restore every category and their questions (complete structure). It includes this tables:
72 // - quiz_randomsamatch
77 // - quiz_numerical_units
78 // - quiz_question_datasets
79 // - quiz_dataset_definitions
80 // - quiz_dataset_items
81 // All this backup info have its own section in moodle.xml (QUESTION_CATEGORIES) and it's generated
82 // before every module backup standard invocation. And only if to restore quizzes has been selected !!
83 // It's invoked with quiz_restore_question_categories. (course independent).
85 // 2.-Standard module restore (Invoked via quiz_restore_mods). It includes this tables:
87 // - quiz_question_versions
88 // - quiz_question_grades
92 // This step is the standard mod backup. (course dependent).
94 //We are going to nedd quiz libs to be able to mimic the upgrade process
95 require_once("$CFG->dirroot/mod/quiz/locallib.php");
97 //STEP 1. Restore categories/questions and associated structures
98 // (course independent)
99 function quiz_restore_pre15_question_categories($category,$restore) {
105 //Get record from backup_ids
106 $data = backup_getid($restore->backup_unique_code
,"quiz_categories",$category->id
);
109 //Now get completed xmlized object
111 //traverse_xmlize($info); //Debug
112 //print_object ($GLOBALS['traverse_array']); //Debug
113 //$GLOBALS['traverse_array']=""; //Debug
115 //Now, build the QUIZ_CATEGORIES record structure
116 $quiz_cat->course
= $restore->course_id
;
117 $quiz_cat->name
= backup_todb($info['QUESTION_CATEGORY']['#']['NAME']['0']['#']);
118 $quiz_cat->info
= backup_todb($info['QUESTION_CATEGORY']['#']['INFO']['0']['#']);
119 $quiz_cat->publish
= backup_todb($info['QUESTION_CATEGORY']['#']['PUBLISH']['0']['#']);
120 $quiz_cat->stamp
= backup_todb($info['QUESTION_CATEGORY']['#']['STAMP']['0']['#']);
121 $quiz_cat->parent
= backup_todb($info['QUESTION_CATEGORY']['#']['PARENT']['0']['#']);
122 $quiz_cat->sortorder
= backup_todb($info['QUESTION_CATEGORY']['#']['SORTORDER']['0']['#']);
124 if ($catfound = restore_get_best_quiz_category($quiz_cat, $restore->course_id
)) {
127 if (!$quiz_cat->stamp
) {
128 $quiz_cat->stamp
= make_unique_id_code();
130 $newid = insert_record ("quiz_categories",$quiz_cat);
135 echo "<li>".get_string('category', 'quiz')." \"".$quiz_cat->name
."\"<br />";
137 //We must never arrive here !!
138 echo "<li>".get_string('category', 'quiz')." \"".$quiz_cat->name
."\" Error!<br />";
143 //Here category has been created or selected, so save results in backup_ids and start with questions
144 if ($newid and $status) {
145 //We have the newid, update backup_ids
146 backup_putid($restore->backup_unique_code
,"quiz_categories",
147 $category->id
, $newid);
148 //Now restore quiz_questions
149 $status = quiz_restore_pre15_questions ($category->id
, $newid,$info,$restore);
159 function quiz_restore_pre15_questions ($old_category_id,$new_category_id,$info,$restore) {
165 //Get the questions array
166 $questions = $info['QUESTION_CATEGORY']['#']['QUESTIONS']['0']['#']['QUESTION'];
168 //Iterate over questions
169 for($i = 0; $i < sizeof($questions); $i++
) {
170 $question = new object;
171 $que_info = $questions[$i];
172 //traverse_xmlize($que_info); //Debug
173 //print_object ($GLOBALS['traverse_array']); //Debug
174 //$GLOBALS['traverse_array']=""; //Debug
176 //We'll need this later!!
177 $oldid = backup_todb($que_info['#']['ID']['0']['#']);
179 //Now, build the QUIZ_QUESTIONS record structure
180 $question->category
= $new_category_id;
181 $question->parent
= backup_todb($que_info['#']['PARENT']['0']['#']);
182 $question->name
= backup_todb($que_info['#']['NAME']['0']['#']);
183 $question->questiontext
= backup_todb($que_info['#']['QUESTIONTEXT']['0']['#']);
184 $question->questiontextformat
= backup_todb($que_info['#']['QUESTIONTEXTFORMAT']['0']['#']);
185 $question->image
= backup_todb($que_info['#']['IMAGE']['0']['#']);
186 $question->defaultgrade
= backup_todb($que_info['#']['DEFAULTGRADE']['0']['#']);
187 if (isset($que_info['#']['PENALTY']['0']['#'])) { //Only if it's set, to apply DB default else.
188 $question->penalty
= backup_todb($que_info['#']['PENALTY']['0']['#']);
190 $question->qtype
= backup_todb($que_info['#']['QTYPE']['0']['#']);
191 if (isset($que_info['#']['LENGTH']['0']['#'])) { //Only if it's set, to apply DB default else.
192 $question->length
= backup_todb($que_info['#']['LENGTH']['0']['#']);
194 $question->stamp
= backup_todb($que_info['#']['STAMP']['0']['#']);
195 if (isset($que_info['#']['VERSION']['0']['#'])) { //Only if it's set, to apply DB default else.
196 $question->version
= backup_todb($que_info['#']['VERSION']['0']['#']);
198 if (isset($que_info['#']['HIDDEN']['0']['#'])) { //Only if it's set, to apply DB default else.
199 $question->hidden
= backup_todb($que_info['#']['HIDDEN']['0']['#']);
202 //Although only a few backups can have questions with parent, we try to recode it
203 //if it contains something
204 if ($question->parent
and $parent = backup_getid($restore->backup_unique_code
,"quiz_questions",$question->parent
)) {
205 $question->parent
= $parent->new_id
;
208 // If it is a random question then hide it
209 if ($question->qtype
== RANDOM
) {
210 $question->hidden
= 1;
213 //If it is a description question, length = 0
214 if ($question->qtype
== DESCRIPTION
) {
215 $question->length
= 0;
218 //Check if the question exists
219 //by category and stamp
220 $question_exists = get_record ("quiz_questions","category",$question->category
,
221 "stamp",$question->stamp
);
222 //If the stamp doesn't exists, check if question exists
223 //by category, name and questiontext and calculate stamp
224 //Mantains pre Beta 1.1 compatibility !!
225 if (!$question->stamp
) {
226 $question->stamp
= make_unique_id_code();
227 $question->version
= 1;
228 $question_exists = get_record ("quiz_questions","category",$question->category
,
229 "name",$question->name
,
230 "questiontext",$question->questiontext
);
233 //If the question exists, only record its id
234 if ($question_exists) {
235 $newid = $question_exists->id
;
236 $creatingnewquestion = false;
237 //Else, create a new question
239 //The structure is equal to the db, so insert the quiz_questions
240 $newid = insert_record ("quiz_questions",$question);
241 //If it is a random question, parent = id
242 if ($newid && $question->qtype
== RANDOM
) {
243 set_field ('quiz_questions', 'parent', $newid, 'id', $newid);
245 $creatingnewquestion = true;
249 if (($i+
1) %
2 == 0) {
251 if (($i+
1) %
40 == 0) {
256 //Save newid to backup tables
258 //We have the newid, update backup_ids
259 backup_putid($restore->backup_unique_code
,"quiz_questions",$oldid,
262 //If it's a new question in the DB, restore it
263 if ($creatingnewquestion) {
264 //Now, restore every quiz_answers in this question
265 $status = quiz_restore_pre15_answers($oldid,$newid,$que_info,$restore);
266 //Now, depending of the type of questions, invoke different functions
267 if ($question->qtype
== "1") {
268 $status = quiz_restore_pre15_shortanswer($oldid,$newid,$que_info,$restore);
269 } else if ($question->qtype
== "2") {
270 $status = quiz_restore_pre15_truefalse($oldid,$newid,$que_info,$restore);
271 } else if ($question->qtype
== "3") {
272 $status = quiz_restore_pre15_multichoice($oldid,$newid,$que_info,$restore);
273 } else if ($question->qtype
== "4") {
274 //Random question. Nothing to do.
275 } else if ($question->qtype
== "5") {
276 $status = quiz_restore_pre15_match($oldid,$newid,$que_info,$restore);
277 } else if ($question->qtype
== "6") {
278 $status = quiz_restore_pre15_randomsamatch($oldid,$newid,$que_info,$restore);
279 } else if ($question->qtype
== "7") {
280 //Description question. Nothing to do.
281 } else if ($question->qtype
== "8") {
282 $status = quiz_restore_pre15_numerical($oldid,$newid,$que_info,$restore);
283 } else if ($question->qtype
== "9") {
284 $status = quiz_restore_pre15_multianswer($oldid,$newid,$que_info,$restore);
285 } else if ($question->qtype
== "10") {
286 $status = quiz_restore_pre15_calculated($oldid,$newid,$que_info,$restore);
289 //We are NOT creating the question, but we need to know every quiz_answers
290 //map between the XML file and the database to be able to restore the responses
292 $status = quiz_restore_pre15_map_answers($oldid,$newid,$que_info,$restore);
293 //Now, depending of the type of questions, invoke different functions
294 //to create the necessary mappings in backup_ids, because we are not
295 //creating the question, but need some records in backup table
296 if ($question->qtype
== "1") {
297 //Shortanswer question. Nothing to remap
298 } else if ($question->qtype
== "2") {
299 //Truefalse question. Nothing to remap
300 } else if ($question->qtype
== "3") {
301 //Multichoice question. Nothing to remap
302 } else if ($question->qtype
== "4") {
303 //Random question. Nothing to remap
304 } else if ($question->qtype
== "5") {
305 $status = quiz_restore_pre15_map_match($oldid,$newid,$que_info,$restore);
306 } else if ($question->qtype
== "6") {
307 //Randomsamatch question. Nothing to remap
308 } else if ($question->qtype
== "7") {
309 //Description question. Nothing to remap
310 } else if ($question->qtype
== "8") {
311 //Numerical question. Nothing to remap
312 } else if ($question->qtype
== "9") {
313 //Multianswer question. Nothing to remap
314 } else if ($question->qtype
== "10") {
315 //Calculated question. Nothing to remap
322 function quiz_restore_pre15_answers ($old_question_id,$new_question_id,$info,$restore) {
328 //Get the answers array
329 if (isset($info['#']['ANSWERS']['0']['#']['ANSWER'])) {
330 $answers = $info['#']['ANSWERS']['0']['#']['ANSWER'];
332 //Iterate over answers
333 for($i = 0; $i < sizeof($answers); $i++
) {
334 $ans_info = $answers[$i];
335 //traverse_xmlize($ans_info); //Debug
336 //print_object ($GLOBALS['traverse_array']); //Debug
337 //$GLOBALS['traverse_array']=""; //Debug
339 //We'll need this later!!
340 $oldid = backup_todb($ans_info['#']['ID']['0']['#']);
342 //Now, build the QUIZ_ANSWERS record structure
343 $answer->question
= $new_question_id;
344 $answer->answer
= backup_todb($ans_info['#']['ANSWER_TEXT']['0']['#']);
345 $answer->fraction
= backup_todb($ans_info['#']['FRACTION']['0']['#']);
346 $answer->feedback
= backup_todb($ans_info['#']['FEEDBACK']['0']['#']);
348 //The structure is equal to the db, so insert the quiz_answers
349 $newid = insert_record ("quiz_answers",$answer);
352 if (($i+
1) %
50 == 0) {
354 if (($i+
1) %
1000 == 0) {
361 //We have the newid, update backup_ids
362 backup_putid($restore->backup_unique_code
,"quiz_answers",$oldid,
373 function quiz_restore_pre15_map_answers ($old_question_id,$new_question_id,$info,$restore) {
379 if (!isset($info['#']['ANSWERS'])) { // No answers in this question (eg random)
383 //Get the answers array
384 $answers = $info['#']['ANSWERS']['0']['#']['ANSWER'];
386 //Iterate over answers
387 for($i = 0; $i < sizeof($answers); $i++
) {
388 $ans_info = $answers[$i];
389 //traverse_xmlize($ans_info); //Debug
390 //print_object ($GLOBALS['traverse_array']); //Debug
391 //$GLOBALS['traverse_array']=""; //Debug
393 //We'll need this later!!
394 $oldid = backup_todb($ans_info['#']['ID']['0']['#']);
396 //Now, build the QUIZ_ANSWERS record structure
397 $answer->question
= $new_question_id;
398 $answer->answer
= backup_todb($ans_info['#']['ANSWER_TEXT']['0']['#']);
399 $answer->fraction
= backup_todb($ans_info['#']['FRACTION']['0']['#']);
400 $answer->feedback
= backup_todb($ans_info['#']['FEEDBACK']['0']['#']);
402 //If we are in this method is because the question exists in DB, so its
403 //answers must exist too.
404 //Now, we are going to look for that answer in DB and to create the
405 //mappings in backup_ids to use them later where restoring responses (user level).
407 //Get the answer from DB (by question, answer and fraction)
408 $db_answer = get_record ("quiz_answers","question",$new_question_id,
409 "answer",$answer->answer
,
410 "fraction",$answer->fraction
);
413 if (($i+
1) %
50 == 0) {
415 if (($i+
1) %
1000 == 0) {
422 //We have the database answer, update backup_ids
423 backup_putid($restore->backup_unique_code
,"quiz_answers",$oldid,
433 function quiz_restore_pre15_shortanswer ($old_question_id,$new_question_id,$info,$restore,$restrictto = '') {
439 //Get the shortanswers array
440 $shortanswers = $info['#']['SHORTANSWER'];
442 //Iterate over shortanswers
443 for($i = 0; $i < sizeof($shortanswers); $i++
) {
444 $sho_info = $shortanswers[$i];
445 //traverse_xmlize($sho_info); //Debug
446 //print_object ($GLOBALS['traverse_array']); //Debug
447 //$GLOBALS['traverse_array']=""; //Debug
449 //Now, build the QUIZ_SHORTANSWER record structure
450 $shortanswer->question
= $new_question_id;
451 $shortanswer->answers
= backup_todb($sho_info['#']['ANSWERS']['0']['#']);
452 $shortanswer->usecase
= backup_todb($sho_info['#']['USECASE']['0']['#']);
454 //We have to recode the answers field (a list of answers id)
455 //Extracts answer id from sequence
458 $tok = strtok($shortanswer->answers
,",");
460 //Get the answer from backup_ids
461 $answer = backup_getid($restore->backup_unique_code
,"quiz_answers",$tok);
464 $answers_field .= $answer->new_id
;
467 $answers_field .= ",".$answer->new_id
;
473 //We have the answers field recoded to its new ids
474 $shortanswer->answers
= $answers_field;
476 //The structure is equal to the db, so insert the quiz_shortanswer
477 //Only if there aren't restrictions or there are restriction concordance
478 if (empty($restrictto) ||
(!empty($restrictto) && $shortanswer->answers
== $restrictto)) {
479 $newid = insert_record ("quiz_shortanswer",$shortanswer);
483 if (($i+
1) %
50 == 0) {
485 if (($i+
1) %
1000 == 0) {
491 if (!$newid && !$restrictto) {
499 function quiz_restore_pre15_truefalse ($old_question_id,$new_question_id,$info,$restore) {
505 //Get the truefalse array
506 $truefalses = $info['#']['TRUEFALSE'];
508 //Iterate over truefalse
509 for($i = 0; $i < sizeof($truefalses); $i++
) {
510 $tru_info = $truefalses[$i];
511 //traverse_xmlize($tru_info); //Debug
512 //print_object ($GLOBALS['traverse_array']); //Debug
513 //$GLOBALS['traverse_array']=""; //Debug
515 //Now, build the QUIZ_TRUEFALSE record structure
516 $truefalse->question
= $new_question_id;
517 $truefalse->trueanswer
= backup_todb($tru_info['#']['TRUEANSWER']['0']['#']);
518 $truefalse->falseanswer
= backup_todb($tru_info['#']['FALSEANSWER']['0']['#']);
520 ////We have to recode the trueanswer field
521 $answer = backup_getid($restore->backup_unique_code
,"quiz_answers",$truefalse->trueanswer
);
523 $truefalse->trueanswer
= $answer->new_id
;
526 ////We have to recode the falseanswer field
527 $answer = backup_getid($restore->backup_unique_code
,"quiz_answers",$truefalse->falseanswer
);
529 $truefalse->falseanswer
= $answer->new_id
;
532 //The structure is equal to the db, so insert the quiz_truefalse
533 $newid = insert_record ("quiz_truefalse",$truefalse);
536 if (($i+
1) %
50 == 0) {
538 if (($i+
1) %
1000 == 0) {
552 function quiz_restore_pre15_multichoice ($old_question_id,$new_question_id,$info,$restore, $restrictto = '') {
558 //Get the multichoices array
559 $multichoices = $info['#']['MULTICHOICE'];
561 //Iterate over multichoices
562 for($i = 0; $i < sizeof($multichoices); $i++
) {
563 $mul_info = $multichoices[$i];
564 //traverse_xmlize($mul_info); //Debug
565 //print_object ($GLOBALS['traverse_array']); //Debug
566 //$GLOBALS['traverse_array']=""; //Debug
568 //Now, build the QUIZ_MULTICHOICE record structure
569 $multichoice->question
= $new_question_id;
570 $multichoice->layout
= backup_todb($mul_info['#']['LAYOUT']['0']['#']);
571 $multichoice->answers
= backup_todb($mul_info['#']['ANSWERS']['0']['#']);
572 $multichoice->single
= backup_todb($mul_info['#']['SINGLE']['0']['#']);
574 //We have to recode the answers field (a list of answers id)
575 //Extracts answer id from sequence
578 $tok = strtok($multichoice->answers
,",");
580 //Get the answer from backup_ids
581 $answer = backup_getid($restore->backup_unique_code
,"quiz_answers",$tok);
584 $answers_field .= $answer->new_id
;
587 $answers_field .= ",".$answer->new_id
;
593 //We have the answers field recoded to its new ids
594 $multichoice->answers
= $answers_field;
596 //The structure is equal to the db, so insert the quiz_shortanswer
597 //Only if there aren't restrictions or there are restriction concordance
598 if (empty($restrictto) ||
(!empty($restrictto) && $multichoice->answers
== $restrictto)) {
599 $newid = insert_record ("quiz_multichoice",$multichoice);
603 if (($i+
1) %
50 == 0) {
605 if (($i+
1) %
1000 == 0) {
611 if (!$newid && !$restrictto) {
619 function quiz_restore_pre15_match ($old_question_id,$new_question_id,$info,$restore) {
625 //Get the matchs array
626 $matchs = $info['#']['MATCHS']['0']['#']['MATCH'];
628 //We have to build the subquestions field (a list of match_sub id)
629 $subquestions_field = "";
632 //Iterate over matchs
633 for($i = 0; $i < sizeof($matchs); $i++
) {
634 $mat_info = $matchs[$i];
635 //traverse_xmlize($mat_info); //Debug
636 //print_object ($GLOBALS['traverse_array']); //Debug
637 //$GLOBALS['traverse_array']=""; //Debug
639 //We'll need this later!!
640 $oldid = backup_todb($mat_info['#']['ID']['0']['#']);
642 //Now, build the QUIZ_MATCH_SUB record structure
643 $match_sub->question
= $new_question_id;
644 $match_sub->questiontext
= backup_todb($mat_info['#']['QUESTIONTEXT']['0']['#']);
645 $match_sub->answertext
= backup_todb($mat_info['#']['ANSWERTEXT']['0']['#']);
647 //The structure is equal to the db, so insert the quiz_match_sub
648 $newid = insert_record ("quiz_match_sub",$match_sub);
651 if (($i+
1) %
50 == 0) {
653 if (($i+
1) %
1000 == 0) {
660 //We have the newid, update backup_ids
661 backup_putid($restore->backup_unique_code
,"quiz_match_sub",$oldid,
663 //We have a new match_sub, append it to subquestions_field
665 $subquestions_field .= $newid;
668 $subquestions_field .= ",".$newid;
675 //We have created every match_sub, now create the match
676 $match->question
= $new_question_id;
677 $match->subquestions
= $subquestions_field;
679 //The structure is equal to the db, so insert the quiz_match_sub
680 $newid = insert_record ("quiz_match",$match);
689 function quiz_restore_pre15_map_match ($old_question_id,$new_question_id,$info,$restore) {
695 //Get the matchs array
696 $matchs = $info['#']['MATCHS']['0']['#']['MATCH'];
698 //We have to build the subquestions field (a list of match_sub id)
699 $subquestions_field = "";
702 //Iterate over matchs
703 for($i = 0; $i < sizeof($matchs); $i++
) {
704 $mat_info = $matchs[$i];
705 //traverse_xmlize($mat_info); //Debug
706 //print_object ($GLOBALS['traverse_array']); //Debug
707 //$GLOBALS['traverse_array']=""; //Debug
709 //We'll need this later!!
710 $oldid = backup_todb($mat_info['#']['ID']['0']['#']);
712 //Now, build the QUIZ_MATCH_SUB record structure
713 $match_sub->question
= $new_question_id;
714 $match_sub->questiontext
= backup_todb($mat_info['#']['QUESTIONTEXT']['0']['#']);
715 $match_sub->answertext
= backup_todb($mat_info['#']['ANSWERTEXT']['0']['#']);
717 //If we are in this method is because the question exists in DB, so its
718 //match_sub must exist too.
719 //Now, we are going to look for that match_sub in DB and to create the
720 //mappings in backup_ids to use them later where restoring responses (user level).
722 //Get the match_sub from DB (by question, questiontext and answertext)
723 $db_match_sub = get_record ("quiz_match_sub","question",$new_question_id,
724 "questiontext",$match_sub->questiontext
,
725 "answertext",$match_sub->answertext
);
727 if (($i+
1) %
50 == 0) {
729 if (($i+
1) %
1000 == 0) {
735 //We have the database match_sub, so update backup_ids
737 //We have the newid, update backup_ids
738 backup_putid($restore->backup_unique_code
,"quiz_match_sub",$oldid,
748 function quiz_restore_pre15_randomsamatch ($old_question_id,$new_question_id,$info,$restore) {
754 //Get the randomsamatchs array
755 $randomsamatchs = $info['#']['RANDOMSAMATCH'];
757 //Iterate over randomsamatchs
758 for($i = 0; $i < sizeof($randomsamatchs); $i++
) {
759 $ran_info = $randomsamatchs[$i];
760 //traverse_xmlize($ran_info); //Debug
761 //print_object ($GLOBALS['traverse_array']); //Debug
762 //$GLOBALS['traverse_array']=""; //Debug
764 //Now, build the QUIZ_RANDOMSAMATCH record structure
765 $randomsamatch->question
= $new_question_id;
766 $randomsamatch->choose
= backup_todb($ran_info['#']['CHOOSE']['0']['#']);
768 //The structure is equal to the db, so insert the quiz_randomsamatch
769 $newid = insert_record ("quiz_randomsamatch",$randomsamatch);
772 if (($i+
1) %
50 == 0) {
774 if (($i+
1) %
1000 == 0) {
788 function quiz_restore_pre15_numerical ($old_question_id,$new_question_id,$info,$restore, $restrictto = '') {
794 //Get the numerical array
795 $numericals = $info['#']['NUMERICAL'];
797 //Iterate over numericals
798 for($i = 0; $i < sizeof($numericals); $i++
) {
799 $num_info = $numericals[$i];
800 //traverse_xmlize($num_info); //Debug
801 //print_object ($GLOBALS['traverse_array']); //Debug
802 //$GLOBALS['traverse_array']=""; //Debug
804 //Now, build the QUIZ_NUMERICAL record structure
805 $numerical->question
= $new_question_id;
806 $numerical->answer
= backup_todb($num_info['#']['ANSWER']['0']['#']);
807 $numerical->min
= backup_todb($num_info['#']['MIN']['0']['#']);
808 $numerical->max
= backup_todb($num_info['#']['MAX']['0']['#']);
810 ////We have to recode the answer field
811 $answer = backup_getid($restore->backup_unique_code
,"quiz_answers",$numerical->answer
);
813 $numerical->answer
= $answer->new_id
;
816 //Answer goes to answers in 1.5 (although it continues being only one!)
817 //Changed 12-05 (chating with Gustav and Julian this remains = pre15 = answer)
818 //$numerical->answers = $numerical->answer;
820 //We have to calculate the tolerance field of the numerical question
821 $numerical->tolerance
= ($numerical->max
- $numerical->min
)/2;
823 //The structure is equal to the db, so insert the quiz_numerical
824 //Only if there aren't restrictions or there are restriction concordance
825 if (empty($restrictto) ||
(!empty($restrictto) && in_array($numerical->answer
,explode(",",$restrictto)))) {
826 $newid = insert_record ("quiz_numerical",$numerical);
830 if (($i+
1) %
50 == 0) {
832 if (($i+
1) %
1000 == 0) {
838 //Now restore numerical_units
840 $status = quiz_restore_pre15_numerical_units ($old_question_id,$new_question_id,$num_info,$restore);
843 if (!$newid && !$restrictto) {
851 function quiz_restore_pre15_calculated ($old_question_id,$new_question_id,$info,$restore) {
857 //Get the calculated-s array
858 $calculateds = $info['#']['CALCULATED'];
860 //Iterate over calculateds
861 for($i = 0; $i < sizeof($calculateds); $i++
) {
862 $cal_info = $calculateds[$i];
863 //traverse_xmlize($cal_info); //Debug
864 //print_object ($GLOBALS['traverse_array']); //Debug
865 //$GLOBALS['traverse_array']=""; //Debug
867 //Now, build the QUIZ_CALCULATED record structure
868 $calculated->question
= $new_question_id;
869 $calculated->answer
= backup_todb($cal_info['#']['ANSWER']['0']['#']);
870 $calculated->tolerance
= backup_todb($cal_info['#']['TOLERANCE']['0']['#']);
871 $calculated->tolerancetype
= backup_todb($cal_info['#']['TOLERANCETYPE']['0']['#']);
872 $calculated->correctanswerlength
= backup_todb($cal_info['#']['CORRECTANSWERLENGTH']['0']['#']);
873 $calculated->correctanswerformat
= backup_todb($cal_info['#']['CORRECTANSWERFORMAT']['0']['#']);
875 ////We have to recode the answer field
876 $answer = backup_getid($restore->backup_unique_code
,"quiz_answers",$calculated->answer
);
878 $calculated->answer
= $answer->new_id
;
881 //If we haven't correctanswerformat, it defaults to 2 (in DB)
882 if (empty($calculated->correctanswerformat
)) {
883 $calculated->correctanswerformat
= 2;
886 //The structure is equal to the db, so insert the quiz_calculated
887 $newid = insert_record ("quiz_calculated",$calculated);
890 if (($i+
1) %
50 == 0) {
892 if (($i+
1) %
1000 == 0) {
898 //Now restore numerical_units
899 $status = quiz_restore_pre15_numerical_units ($old_question_id,$new_question_id,$cal_info,$restore);
901 //Now restore dataset_definitions
902 if ($status && $newid) {
903 $status = quiz_restore_pre15_dataset_definitions ($old_question_id,$new_question_id,$cal_info,$restore);
914 function quiz_restore_pre15_multianswer ($old_question_id,$new_question_id,$info,$restore) {
920 //We need some question fields here so we get the full record from DB
921 $parentquestion = get_record('quiz_questions','id',$new_question_id);
923 //We need to store all the positions with their created questions
924 //to be able to calculate the sequence field
925 $createdquestions = array();
927 //Under 1.5, every multianswer record becomes a question itself
928 //with its parent set to the cloze question. And there is only
929 //ONE multianswer record with the sequence of questions used.
931 //Get the multianswers array
932 $multianswers_array = $info['#']['MULTIANSWERS']['0']['#']['MULTIANSWER'];
933 //Iterate over multianswers_array
934 for($i = 0; $i < sizeof($multianswers_array); $i++
) {
935 $mul_info = $multianswers_array[$i];
936 //traverse_xmlize($mul_info); //Debug
937 //print_object ($GLOBALS['traverse_array']); //Debug
938 //$GLOBALS['traverse_array']=""; //Debug
941 $oldid = backup_todb($mul_info['#']['ID']['0']['#']);
943 //Now, build the QUIZ_MULTIANSWER record structure
944 $multianswer->question
= $new_question_id;
945 $multianswer->answers
= backup_todb($mul_info['#']['ANSWERS']['0']['#']);
946 $multianswer->positionkey
= backup_todb($mul_info['#']['POSITIONKEY']['0']['#']);
947 $multianswer->answertype
= backup_todb($mul_info['#']['ANSWERTYPE']['0']['#']);
948 $multianswer->norm
= backup_todb($mul_info['#']['NORM']['0']['#']);
950 //Saving multianswer and positionkey to use them later restoring states
951 backup_putid ($restore->backup_unique_code
,'multianswer-pos',$oldid,$multianswer->positionkey
);
953 //We have to recode all the answers to their new ids
954 $ansarr = explode(",", $multianswer->answers
);
955 foreach ($ansarr as $key => $value) {
956 //Get the answer from backup_ids
957 $answer = backup_getid($restore->backup_unique_code
,'quiz_answers',$value);
958 $ansarr[$key] = $answer->new_id
;
960 $multianswer->answers
= implode(",",$ansarr);
962 //Build the new question structure
963 $question = new object;
964 $question->category
= $parentquestion->category
;
965 $question->parent
= $parentquestion->id
;
966 $question->name
= $parentquestion->name
;
967 $question->questiontextformat
= $parentquestion->questiontextformat
;
968 $question->defaultgrade
= $multianswer->norm
;
969 $question->penalty
= $parentquestion->penalty
;
970 $question->qtype
= $multianswer->answertype
;
971 $question->version
= $parentquestion->version
;
972 $question->hidden
= $parentquestion->hidden
;
973 $question->length
= 0;
974 $question->questiontext
= '';
975 $question->stamp
= make_unique_id_code();
977 //Save the new question to DB
978 $newid = insert_record('quiz_questions', $question);
981 $createdquestions[$multianswer->positionkey
] = $newid;
985 if (($i+
1) %
50 == 0) {
987 if (($i+
1) %
1000 == 0) {
993 //Remap quiz_answers records from the original multianswer question
994 //to their newly created question
996 $answersdb = get_records_list('quiz_answers','id',$multianswer->answers
);
997 foreach ($answersdb as $answerdb) {
998 set_field('quiz_answers','question',$newid,'id',$answerdb->id
);
1002 //If we have created the quiz_questions record, now, depending of the
1003 //answertype, delegate the restore to every qtype function
1005 if ($multianswer->answertype
== "1") {
1006 $status = quiz_restore_pre15_shortanswer ($old_question_id,$newid,$mul_info,$restore,$multianswer->answers
);
1007 } else if ($multianswer->answertype
== "3") {
1008 $status = quiz_restore_pre15_multichoice ($old_question_id,$newid,$mul_info,$restore,$multianswer->answers
);
1009 } else if ($multianswer->answertype
== "8") {
1010 $status = quiz_restore_pre15_numerical ($old_question_id,$newid,$mul_info,$restore,$multianswer->answers
);
1017 //Everything is created, just going to create the multianswer record
1019 ksort($createdquestions);
1021 $multianswerdb = new object;
1022 $multianswerdb->question
= $parentquestion->id
;
1023 $multianswerdb->sequence
= implode(",",$createdquestions);
1024 $mid = insert_record('quiz_multianswers', $multianswerdb);
1034 function quiz_restore_pre15_numerical_units ($old_question_id,$new_question_id,$info,$restore) {
1040 //Get the numerical array
1041 $numerical_units = $info['#']['NUMERICAL_UNITS']['0']['#']['NUMERICAL_UNIT'];
1043 //Iterate over numerical_units
1044 for($i = 0; $i < sizeof($numerical_units); $i++
) {
1045 $nu_info = $numerical_units[$i];
1046 //traverse_xmlize($nu_info); //Debug
1047 //print_object ($GLOBALS['traverse_array']); //Debug
1048 //$GLOBALS['traverse_array']=""; //Debug
1050 //Now, build the QUIZ_NUMERICAL_UNITS record structure
1051 $numerical_unit->question
= $new_question_id;
1052 $numerical_unit->multiplier
= backup_todb($nu_info['#']['MULTIPLIER']['0']['#']);
1053 $numerical_unit->unit
= backup_todb($nu_info['#']['UNIT']['0']['#']);
1055 //The structure is equal to the db, so insert the quiz_numerical_units
1056 $newid = insert_record ("quiz_numerical_units",$numerical_unit);
1066 function quiz_restore_pre15_dataset_definitions ($old_question_id,$new_question_id,$info,$restore) {
1072 //Get the dataset_definitions array
1073 $dataset_definitions = $info['#']['DATASET_DEFINITIONS']['0']['#']['DATASET_DEFINITION'];
1075 //Iterate over dataset_definitions
1076 for($i = 0; $i < sizeof($dataset_definitions); $i++
) {
1077 $dd_info = $dataset_definitions[$i];
1078 //traverse_xmlize($dd_info); //Debug
1079 //print_object ($GLOBALS['traverse_array']); //Debug
1080 //$GLOBALS['traverse_array']=""; //Debug
1082 //Now, build the QUIZ_DATASET_DEFINITION record structure
1083 $dataset_definition->category
= backup_todb($dd_info['#']['CATEGORY']['0']['#']);
1084 $dataset_definition->name
= backup_todb($dd_info['#']['NAME']['0']['#']);
1085 $dataset_definition->type
= backup_todb($dd_info['#']['TYPE']['0']['#']);
1086 $dataset_definition->options
= backup_todb($dd_info['#']['OPTIONS']['0']['#']);
1087 $dataset_definition->itemcount
= backup_todb($dd_info['#']['ITEMCOUNT']['0']['#']);
1089 //We have to recode the category field (only if the category != 0)
1090 if ($dataset_definition->category
!= 0) {
1091 $category = backup_getid($restore->backup_unique_code
,"quiz_categories",$dataset_definition->category
);
1093 $dataset_definition->category
= $category->new_id
;
1097 //Now, we hace to decide when to create the new records or reuse an existing one
1098 $create_definition = false;
1100 //If the dataset_definition->category = 0, it's a individual question dataset_definition, so we'll create it
1101 if ($dataset_definition->category
== 0) {
1102 $create_definition = true;
1104 //The category isn't 0, so it's a category question dataset_definition, we have to see if it exists
1105 //Look for a definition with the same category, name and type
1106 if ($definitionrec = get_record_sql("SELECT d.*
1107 FROM {$CFG->prefix}quiz_dataset_definitions d
1108 WHERE d.category = '$dataset_definition->category' AND
1109 d.name = '$dataset_definition->name' AND
1110 d.type = '$dataset_definition->type'")) {
1111 //Such dataset_definition exist. Now we must check if it has enough itemcount
1112 if ($definitionrec->itemcount
< $dataset_definition->itemcount
) {
1113 //We haven't enough itemcount, so we have to create the definition as an individual question one.
1114 $dataset_definition->category
= 0;
1115 $create_definition = true;
1117 //We have enough itemcount, so we'll reuse the existing definition
1118 $create_definition = false;
1119 $newid = $definitionrec->id
;
1122 //Such dataset_definition doesn't exist. We'll create it.
1123 $create_definition = true;
1127 //If we've to create the definition, do it
1128 if ($create_definition) {
1129 //The structure is equal to the db, so insert the quiz_dataset_definitions
1130 $newid = insert_record ("quiz_dataset_definitions",$dataset_definition);
1132 //Restore quiz_dataset_items
1133 $status = quiz_restore_pre15_dataset_items($newid,$dd_info,$restore);
1137 //Now, we must have a definition (created o reused). Its id is in newid. Create the quiz_question_datasets record
1138 //to join the question and the dataset_definition
1140 $question_dataset->question
= $new_question_id;
1141 $question_dataset->datasetdefinition
= $newid;
1142 $newid = insert_record ("quiz_question_datasets",$question_dataset);
1153 function quiz_restore_pre15_dataset_items ($definitionid,$info,$restore) {
1159 //Get the items array
1160 $dataset_items = $info['#']['DATASET_ITEMS']['0']['#']['DATASET_ITEM'];
1162 //Iterate over dataset_items
1163 for($i = 0; $i < sizeof($dataset_items); $i++
) {
1164 $di_info = $dataset_items[$i];
1165 //traverse_xmlize($di_info); //Debug
1166 //print_object ($GLOBALS['traverse_array']); //Debug
1167 //$GLOBALS['traverse_array']=""; //Debug
1169 //Now, build the QUIZ_DATASET_ITEMS record structure
1170 $dataset_item->definition
= $definitionid;
1171 $dataset_item->number
= backup_todb($di_info['#']['NUMBER']['0']['#']);
1172 $dataset_item->value
= backup_todb($di_info['#']['VALUE']['0']['#']);
1174 //The structure is equal to the db, so insert the quiz_dataset_items
1175 $newid = insert_record ("quiz_dataset_items",$dataset_item);
1185 //STEP 2. Restore quizzes and associated structures
1186 // (course dependent)
1187 function quiz_restore_pre15_mods($mod,$restore) {
1193 //Get record from backup_ids
1194 $data = backup_getid($restore->backup_unique_code
,$mod->modtype
,$mod->id
);
1197 //Now get completed xmlized object
1198 $info = $data->info
;
1199 //traverse_xmlize($info); //Debug
1200 //print_object ($GLOBALS['traverse_array']); //Debug
1201 //$GLOBALS['traverse_array']=""; //Debug
1203 //Now, build the QUIZ record structure
1204 $quiz->course
= $restore->course_id
;
1205 $quiz->name
= backup_todb($info['MOD']['#']['NAME']['0']['#']);
1206 $quiz->intro
= backup_todb($info['MOD']['#']['INTRO']['0']['#']);
1207 $quiz->timeopen
= backup_todb($info['MOD']['#']['TIMEOPEN']['0']['#']);
1208 $quiz->timeclose
= backup_todb($info['MOD']['#']['TIMECLOSE']['0']['#']);
1209 $quiz->attempts
= backup_todb($info['MOD']['#']['ATTEMPTS_NUMBER']['0']['#']);
1210 $quiz->attemptonlast
= backup_todb($info['MOD']['#']['ATTEMPTONLAST']['0']['#']);
1211 $quiz->feedback
= backup_todb($info['MOD']['#']['FEEDBACK']['0']['#']);
1212 $quiz->correctanswers
= backup_todb($info['MOD']['#']['CORRECTANSWERS']['0']['#']);
1213 $quiz->grademethod
= backup_todb($info['MOD']['#']['GRADEMETHOD']['0']['#']);
1214 if (isset($info['MOD']['#']['DECIMALPOINTS']['0']['#'])) { //Only if it's set, to apply DB default else.
1215 $quiz->decimalpoints
= backup_todb($info['MOD']['#']['DECIMALPOINTS']['0']['#']);
1217 $quiz->review
= backup_todb($info['MOD']['#']['REVIEW']['0']['#']);
1218 $quiz->questionsperpage
= backup_todb($info['MOD']['#']['QUESTIONSPERPAGE']['0']['#']);
1219 $quiz->shufflequestions
= backup_todb($info['MOD']['#']['SHUFFLEQUESTIONS']['0']['#']);
1220 $quiz->shuffleanswers
= backup_todb($info['MOD']['#']['SHUFFLEANSWERS']['0']['#']);
1221 $quiz->questions
= backup_todb($info['MOD']['#']['QUESTIONS']['0']['#']);
1222 $quiz->sumgrades
= backup_todb($info['MOD']['#']['SUMGRADES']['0']['#']);
1223 $quiz->grade
= backup_todb($info['MOD']['#']['GRADE']['0']['#']);
1224 $quiz->timecreated
= backup_todb($info['MOD']['#']['TIMECREATED']['0']['#']);
1225 $quiz->timemodified
= backup_todb($info['MOD']['#']['TIMEMODIFIED']['0']['#']);
1226 $quiz->timelimit
= backup_todb($info['MOD']['#']['TIMELIMIT']['0']['#']);
1227 $quiz->password
= backup_todb($info['MOD']['#']['PASSWORD']['0']['#']);
1228 $quiz->subnet
= backup_todb($info['MOD']['#']['SUBNET']['0']['#']);
1229 $quiz->popup
= backup_todb($info['MOD']['#']['POPUP']['0']['#']);
1231 //We have to recode the questions field (a list of questions id)
1232 $newquestions = array();
1233 if ($questionsarr = explode (",",$quiz->questions
)) {
1234 foreach ($questionsarr as $key => $value) {
1235 if ($question = backup_getid($restore->backup_unique_code
,"quiz_questions",$value)) {
1236 $newquestions[] = $question->new_id
;
1240 $quiz->questions
= implode (",", $newquestions);
1242 //Recalculate the questions field to include page breaks if necessary
1243 $quiz->questions
= quiz_repaginate($quiz->questions
, $quiz->questionsperpage
);
1245 //Calculate the new review field contents (logic extracted from upgrade)
1246 $review = (QUIZ_REVIEW_IMMEDIATELY
& (QUIZ_REVIEW_RESPONSES + QUIZ_REVIEW_SCORES
));
1247 if ($quiz->feedback
) {
1248 $review +
= (QUIZ_REVIEW_IMMEDIATELY
& QUIZ_REVIEW_FEEDBACK
);
1250 if ($quiz->correctanswers
) {
1251 $review +
= (QUIZ_REVIEW_IMMEDIATELY
& QUIZ_REVIEW_ANSWERS
);
1253 if ($quiz->review
& 1) {
1254 $review +
= QUIZ_REVIEW_CLOSED
;
1256 if ($quiz->review
& 2) {
1257 $review +
= QUIZ_REVIEW_OPEN
;
1259 $quiz->review
= $review;
1261 //The structure is equal to the db, so insert the quiz
1262 $newid = insert_record ("quiz",$quiz);
1265 echo "<li>".get_string("modulename","quiz")." \"".format_string(stripslashes($quiz->name
),true)."\"</li>";
1269 //We have the newid, update backup_ids
1270 backup_putid($restore->backup_unique_code
,$mod->modtype
,
1272 //We have to restore the quiz_question_instances now (old quiz_question_grades, course level)
1273 $status = quiz_question_instances_restore_pre15_mods($newid,$info,$restore);
1274 //We have to restore the question_versions now (course level table)
1275 $status = quiz_question_versions_restore_pre15_mods($newid,$info,$restore);
1276 //Now check if want to restore user data and do it.
1277 if ($restore->mods
['quiz']->userinfo
) {
1278 //Restore quiz_attempts
1279 $status = quiz_attempts_restore_pre15_mods ($newid,$info,$restore, $quiz->questions
);
1281 //Restore quiz_grades
1282 $status = quiz_grades_restore_pre15_mods ($newid,$info,$restore);
1295 //This function restores the quiz_question_instances (old quiz_question_grades)
1296 function quiz_question_instances_restore_pre15_mods($quiz_id,$info,$restore) {
1302 //Get the quiz_question_grades array
1303 $grades = $info['MOD']['#']['QUESTION_GRADES']['0']['#']['QUESTION_GRADE'];
1305 //Iterate over question_grades
1306 for($i = 0; $i < sizeof($grades); $i++
) {
1307 $gra_info = $grades[$i];
1308 //traverse_xmlize($gra_info); //Debug
1309 //print_object ($GLOBALS['traverse_array']); //Debug
1310 //$GLOBALS['traverse_array']=""; //Debug
1312 //We'll need this later!!
1313 $oldid = backup_todb($gra_info['#']['ID']['0']['#']);
1315 //Now, build the QUESTION_GRADES record structure
1316 $grade->quiz
= $quiz_id;
1317 $grade->question
= backup_todb($gra_info['#']['QUESTION']['0']['#']);
1318 $grade->grade
= backup_todb($gra_info['#']['GRADE']['0']['#']);
1320 //We have to recode the question field
1321 $question = backup_getid($restore->backup_unique_code
,"quiz_questions",$grade->question
);
1323 $grade->question
= $question->new_id
;
1326 //The structure is equal to the db, so insert the quiz_question_grades
1327 $newid = insert_record ("quiz_question_instances",$grade);
1330 if (($i+
1) %
10 == 0) {
1332 if (($i+
1) %
200 == 0) {
1339 //We have the newid, update backup_ids
1340 backup_putid($restore->backup_unique_code
,"quiz_question_instances",$oldid,
1350 //This function restores the quiz_question_versions
1351 function quiz_question_versions_restore_pre15_mods($quiz_id,$info,$restore) {
1357 //Get the quiz_question_versions array
1358 $versions = $info['MOD']['#']['QUESTION_VERSIONS']['0']['#']['QUESTION_VERSION'];
1360 //Iterate over question_versions
1361 for($i = 0; $i < sizeof($versions); $i++
) {
1362 $ver_info = $versions[$i];
1363 //traverse_xmlize($ver_info); //Debug
1364 //print_object ($GLOBALS['traverse_array']); //Debug
1365 //$GLOBALS['traverse_array']=""; //Debug
1367 //We'll need this later!!
1368 $oldid = backup_todb($ver_info['#']['ID']['0']['#']);
1370 //Now, build the QUESTION_VERSIONS record structure
1371 $version->quiz
= $quiz_id;
1372 $version->oldquestion
= backup_todb($ver_info['#']['OLDQUESTION']['0']['#']);
1373 $version->newquestion
= backup_todb($ver_info['#']['NEWQUESTION']['0']['#']);
1374 $version->userid
= backup_todb($ver_info['#']['USERID']['0']['#']);
1375 $version->timestamp
= backup_todb($ver_info['#']['TIMESTAMP']['0']['#']);
1377 //We have to recode the oldquestion field
1378 $question = backup_getid($restore->backup_unique_code
,"quiz_questions",$version->oldquestion
);
1380 $version->oldquestion
= $question->new_id
;
1383 //We have to recode the newquestion field
1384 $question = backup_getid($restore->backup_unique_code
,"quiz_questions",$version->newquestion
);
1386 $version->newquestion
= $question->new_id
;
1389 //We have to recode the userid field
1390 $user = backup_getid($restore->backup_unique_code
,"user",$version->userid
);
1392 $version->userid
= $user->new_id
;
1393 } else { //Assign to current user
1394 $version->userid
= $USER->id
;
1397 //The structure is equal to the db, so insert the quiz_question_versions
1398 $newid = insert_record ("quiz_question_versions",$version);
1401 if (($i+
1) %
10 == 0) {
1403 if (($i+
1) %
200 == 0) {
1410 //We have the newid, update backup_ids
1411 backup_putid($restore->backup_unique_code
,"quiz_question_versions",$oldid,
1421 //This function restores the quiz_attempts
1422 function quiz_attempts_restore_pre15_mods($quiz_id,$info,$restore,$quizquestions) {
1428 //Get the quiz_attempts array
1429 $attempts = $info['MOD']['#']['ATTEMPTS']['0']['#']['ATTEMPT'];
1431 //Iterate over attempts
1432 for($i = 0; $i < sizeof($attempts); $i++
) {
1433 $att_info = $attempts[$i];
1434 //traverse_xmlize($att_info); //Debug
1435 //print_object ($GLOBALS['traverse_array']); //Debug
1436 //$GLOBALS['traverse_array']=""; //Debug
1438 //We'll need this later!!
1439 $oldid = backup_todb($att_info['#']['ID']['0']['#']);
1440 $olduserid = backup_todb($att_info['#']['USERID']['0']['#']);
1442 //Now, build the ATTEMPTS record structure
1443 $attempt->quiz
= $quiz_id;
1444 $attempt->userid
= backup_todb($att_info['#']['USERID']['0']['#']);
1445 $attempt->attempt
= backup_todb($att_info['#']['ATTEMPTNUM']['0']['#']);
1446 $attempt->sumgrades
= backup_todb($att_info['#']['SUMGRADES']['0']['#']);
1447 $attempt->timestart
= backup_todb($att_info['#']['TIMESTART']['0']['#']);
1448 $attempt->timefinish
= backup_todb($att_info['#']['TIMEFINISH']['0']['#']);
1449 $attempt->timemodified
= backup_todb($att_info['#']['TIMEMODIFIED']['0']['#']);
1451 //We have to recode the userid field
1452 $user = backup_getid($restore->backup_unique_code
,"user",$attempt->userid
);
1454 $attempt->userid
= $user->new_id
;
1457 //Set the layout field (inherited from quiz by default)
1458 $attempt->layout
= $quizquestions;
1460 //Set the preview field (code from upgrade)
1461 if (isteacher($restore->course_id
,$attempt->userid
)) {
1462 $attempt->preview
= 1;
1466 //The structure is equal to the db, so insert the quiz_attempts
1467 $newid = insert_record ("quiz_attempts",$attempt);
1470 if (($i+
1) %
10 == 0) {
1472 if (($i+
1) %
200 == 0) {
1479 //We have the newid, update backup_ids
1480 backup_putid($restore->backup_unique_code
,"quiz_attempts",$oldid,
1482 //Now process quiz_states (old quiz_responses table)
1483 $status = quiz_states_restore_pre15_mods($newid,$att_info,$restore);
1492 //This function restores the quiz_states (old quiz_responses)
1493 function quiz_states_restore_pre15_mods($attempt_id,$info,$restore) {
1499 //Get the quiz_responses array
1500 $responses = $info['#']['RESPONSES']['0']['#']['RESPONSE'];
1501 //Iterate over responses
1502 for($i = 0; $i < sizeof($responses); $i++
) {
1503 $res_info = $responses[$i];
1504 //traverse_xmlize($res_info); //Debug
1505 //print_object ($GLOBALS['traverse_array']); //Debug
1506 //$GLOBALS['traverse_array']=""; //Debug
1508 //We'll need this later!!
1509 $oldid = backup_todb($res_info['#']['ID']['0']['#']);
1511 //Now, build the RESPONSES record structure
1512 $response->attempt
= $attempt_id;
1513 $response->question
= backup_todb($res_info['#']['QUESTION']['0']['#']);
1514 $response->originalquestion
= backup_todb($res_info['#']['ORIGINALQUESTION']['0']['#']);
1515 $response->answer
= backup_todb($res_info['#']['ANSWER']['0']['#']);
1516 $response->grade
= backup_todb($res_info['#']['GRADE']['0']['#']);
1518 //We have to recode the question field
1519 $question = backup_getid($restore->backup_unique_code
,"quiz_questions",$response->question
);
1521 $response->question
= $question->new_id
;
1524 //We have to recode the originalquestion field
1525 $question = backup_getid($restore->backup_unique_code
,"quiz_questions",$response->originalquestion
);
1527 $response->originalquestion
= $question->new_id
;
1530 //Set the raw_grade field (default to the existing grade one, no penalty in pre15 backups)
1531 $response->raw_grade
= $response->grade
;
1533 //We have to recode the answer field
1534 //It depends of the question type !!
1535 //We get the question first
1536 $question = get_record("quiz_questions","id",$response->question
);
1539 //Depending of the qtype, we make different recodes
1540 switch ($question->qtype
) {
1541 case 1: //SHORTANSWER QTYPE
1542 //Nothing to do. The response is a text.
1544 case 2: //TRUEFALSE QTYPE
1545 //The answer is one answer id. We must recode it
1546 $answer = backup_getid($restore->backup_unique_code
,"quiz_answers",$response->answer
);
1548 $response->answer
= $answer->new_id
;
1551 case 3: //MULTICHOICE QTYPE
1552 //The answer is a comma separated list of answers. We must recode them
1555 $tok = strtok($response->answer
,",");
1557 //Get the answer from backup_ids
1558 $answer = backup_getid($restore->backup_unique_code
,"quiz_answers",$tok);
1561 $answer_field .= $answer->new_id
;
1564 $answer_field .= ",".$answer->new_id
;
1570 $response->answer
= $answer_field;
1572 case 4: //RANDOM QTYPE
1573 //The answer links to another question id, we must recode it
1574 $answer_link = backup_getid($restore->backup_unique_code
,"quiz_questions",$response->answer
);
1576 $response->answer
= $answer_link->new_id
;
1579 case 5: //MATCH QTYPE
1580 //The answer is a comma separated list of hypen separated math_subs (for question and answer)
1583 $tok = strtok($response->answer
,",");
1585 //Extract the match_sub for the question and the answer
1586 $exploded = explode("-",$tok);
1587 $match_question_id = $exploded[0];
1588 $match_answer_id = $exploded[1];
1589 //Get the match_sub from backup_ids (for the question)
1590 $match_que = backup_getid($restore->backup_unique_code
,"quiz_match_sub",$match_question_id);
1591 //Get the match_sub from backup_ids (for the answer)
1592 $match_ans = backup_getid($restore->backup_unique_code
,"quiz_match_sub",$match_answer_id);
1594 //It the question hasn't response, it must be 0
1595 if (!$match_ans and $match_answer_id == 0) {
1596 $match_ans->new_id
= 0;
1599 $answer_field .= $match_que->new_id
."-".$match_ans->new_id
;
1602 $answer_field .= ",".$match_que->new_id
."-".$match_ans->new_id
;
1608 $response->answer
= $answer_field;
1610 case 6: //RANDOMSAMATCH QTYPE
1611 //The answer is a comma separated list of hypen separated question_id and answer_id. We must recode them
1614 $tok = strtok($response->answer
,",");
1616 //Extract the question_id and the answer_id
1617 $exploded = explode("-",$tok);
1618 $question_id = $exploded[0];
1619 $answer_id = $exploded[1];
1620 //Get the question from backup_ids
1621 $que = backup_getid($restore->backup_unique_code
,"quiz_questions",$question_id);
1622 //Get the answer from backup_ids
1623 $ans = backup_getid($restore->backup_unique_code
,"quiz_answers",$answer_id);
1625 //It the question hasn't response, it must be 0
1626 if (!$ans and $answer_id == 0) {
1630 $answer_field .= $que->new_id
."-".$ans->new_id
;
1633 $answer_field .= ",".$que->new_id
."-".$ans->new_id
;
1639 $response->answer
= $answer_field;
1641 case 7: //DESCRIPTION QTYPE
1642 //Nothing to do (there is no awser to this qtype)
1643 //But this case must exist !!
1645 case 8: //NUMERICAL QTYPE
1646 //Nothing to do. The response is a text.
1648 case 9: //MULTIANSWER QTYPE
1649 //The answer is a comma separated list of hypen separated multianswer ids and answers. We must recode them.
1650 //We need to have the sequence of questions here to be able to detect qtypes
1651 $multianswerdb = get_record('quiz_multianswers','question',$response->question
);
1652 //Make an array of sequence to easy access
1653 $sequencearr = explode(",",$multianswerdb->sequence
);
1656 $tok = strtok($response->answer
,",");
1659 //Extract the multianswer_id and the answer
1660 $exploded = explode("-",$tok);
1661 $multianswer_id = $exploded[0];
1662 $answer = $exploded[1];
1663 //Get position key (if it fails, next iteration)
1664 if ($oldposrec = backup_getid($restore->backup_unique_code
,'multianswer-pos',$multianswer_id)) {
1665 $positionkey = $oldposrec->new_id
;
1671 //Calculate question type
1672 $questiondb = get_record('quiz_questions','id',$sequencearr[$counter-1]);
1673 $questiontype = $questiondb->qtype
;
1674 //Now, depending of the answertype field in quiz_multianswers
1675 //we do diferent things
1676 if ($questiontype == "1") {
1678 //The answer is text, do nothing
1679 } else if ($questiontype == "3") {
1681 //The answer is an answer_id, look for it in backup_ids
1682 $ans = backup_getid($restore->backup_unique_code
,"quiz_answers",$answer);
1683 $answer = $ans->new_id
;
1684 } else if ($questiontype == "8") {
1686 //The answer is text, do nothing
1689 //Finaly, build the new answer field for each pair
1691 $answer_field .= $positionkey."-".$answer;
1694 $answer_field .= ",".$positionkey."-".$answer;
1700 $response->answer
= $answer_field;
1702 case 10: //CALCULATED QTYPE
1703 //Nothing to do. The response is a text.
1705 default: //UNMATCHED QTYPE.
1706 //This is an error (unimplemented qtype)
1714 //The structure is equal to the db, so insert the quiz_states
1715 $newid = insert_record ("quiz_states",$response);
1718 if (($i+
1) %
10 == 0) {
1720 if (($i+
1) %
200 == 0) {
1727 //We have the newid, update backup_ids
1728 backup_putid($restore->backup_unique_code
,"quiz_states",$oldid,
1738 //This function restores the quiz_grades
1739 function quiz_grades_restore_pre15_mods($quiz_id,$info,$restore) {
1745 //Get the quiz_grades array
1746 $grades = $info['MOD']['#']['GRADES']['0']['#']['GRADE'];
1748 //Iterate over grades
1749 for($i = 0; $i < sizeof($grades); $i++
) {
1750 $gra_info = $grades[$i];
1751 //traverse_xmlize($gra_info); //Debug
1752 //print_object ($GLOBALS['traverse_array']); //Debug
1753 //$GLOBALS['traverse_array']=""; //Debug
1755 //We'll need this later!!
1756 $oldid = backup_todb($gra_info['#']['ID']['0']['#']);
1757 $olduserid = backup_todb($gra_info['#']['USERID']['0']['#']);
1759 //Now, build the GRADES record structure
1760 $grade->quiz
= $quiz_id;
1761 $grade->userid
= backup_todb($gra_info['#']['USERID']['0']['#']);
1762 $grade->grade
= backup_todb($gra_info['#']['GRADEVAL']['0']['#']);
1763 $grade->timemodified
= backup_todb($gra_info['#']['TIMEMODIFIED']['0']['#']);
1765 //We have to recode the userid field
1766 $user = backup_getid($restore->backup_unique_code
,"user",$grade->userid
);
1768 $grade->userid
= $user->new_id
;
1771 //The structure is equal to the db, so insert the quiz_grades
1772 $newid = insert_record ("quiz_grades",$grade);
1775 if (($i+
1) %
10 == 0) {
1777 if (($i+
1) %
200 == 0) {
1784 //We have the newid, update backup_ids
1785 backup_putid($restore->backup_unique_code
,"quiz_grades",$oldid,
1795 //This function converts texts in FORMAT_WIKI to FORMAT_MARKDOWN for
1796 //some texts in the module
1797 function quiz_restore_pre15_wiki2markdown ($restore) {
1803 //Convert quiz_questions->questiontext
1804 if ($records = get_records_sql ("SELECT q.id, q.questiontext, q.questiontextformat
1805 FROM {$CFG->prefix}quiz_questions q,
1806 {$CFG->prefix}backup_ids b
1807 WHERE b.backup_code = $restore->backup_unique_code AND
1808 b.table_name = 'quiz_questions' AND
1810 q.questiontextformat = ".FORMAT_WIKI
)) {
1811 foreach ($records as $record) {
1812 //Rebuild wiki links
1813 $record->questiontext
= restore_decode_wiki_content($record->questiontext
, $restore);
1814 //Convert to Markdown
1815 $wtm = new WikiToMarkdown();
1816 $record->questiontext
= $wtm->convert($record->questiontext
, $restore->course_id
);
1817 $record->questiontextformat
= FORMAT_MARKDOWN
;
1818 $status = update_record('quiz_questions', addslashes_object($record));
1821 if (($i+
1) %
1 == 0) {
1823 if (($i+
1) %
20 == 0) {
1833 //This function returns a log record with all the necessay transformations
1834 //done. It's used by restore_log_module() to restore modules log.
1835 function quiz_restore_pre15_logs($restore,$log) {
1839 //Depending of the action, we recode different things
1840 switch ($log->action
) {
1843 //Get the new_id of the module (to recode the info field)
1844 $mod = backup_getid($restore->backup_unique_code
,$log->module
,$log->info
);
1846 $log->url
= "view.php?id=".$log->cmid
;
1847 $log->info
= $mod->new_id
;
1854 //Get the new_id of the module (to recode the info field)
1855 $mod = backup_getid($restore->backup_unique_code
,$log->module
,$log->info
);
1857 $log->url
= "view.php?id=".$log->cmid
;
1858 $log->info
= $mod->new_id
;
1865 //Get the new_id of the module (to recode the info field)
1866 $mod = backup_getid($restore->backup_unique_code
,$log->module
,$log->info
);
1868 $log->url
= "view.php?id=".$log->cmid
;
1869 $log->info
= $mod->new_id
;
1875 $log->url
= "index.php?id=".$log->course
;
1880 //Get the new_id of the module (to recode the info field)
1881 $mod = backup_getid($restore->backup_unique_code
,$log->module
,$log->info
);
1883 $log->url
= "report.php?id=".$log->cmid
;
1884 $log->info
= $mod->new_id
;
1891 //Get the new_id of the module (to recode the info field)
1892 $mod = backup_getid($restore->backup_unique_code
,$log->module
,$log->info
);
1894 //Extract the attempt id from the url field
1895 $attid = substr(strrchr($log->url
,"="),1);
1896 //Get the new_id of the attempt (to recode the url field)
1897 $att = backup_getid($restore->backup_unique_code
,"quiz_attempts",$attid);
1899 $log->url
= "review.php?id=".$log->cmid
."&attempt=".$att->new_id
;
1900 $log->info
= $mod->new_id
;
1908 //Get the new_id of the module (to recode the info field)
1909 $mod = backup_getid($restore->backup_unique_code
,$log->module
,$log->info
);
1911 //Extract the attempt id from the url field
1912 $attid = substr(strrchr($log->url
,"="),1);
1913 //Get the new_id of the attempt (to recode the url field)
1914 $att = backup_getid($restore->backup_unique_code
,"quiz_attempts",$attid);
1916 $log->url
= "review.php?id=".$log->cmid
."&attempt=".$att->new_id
;
1917 $log->info
= $mod->new_id
;
1925 //Get the new_id of the module (to recode the info field)
1926 $mod = backup_getid($restore->backup_unique_code
,$log->module
,$log->info
);
1928 //Extract the attempt id from the url field
1929 $attid = substr(strrchr($log->url
,"="),1);
1930 //Get the new_id of the attempt (to recode the url field)
1931 $att = backup_getid($restore->backup_unique_code
,"quiz_attempts",$attid);
1933 $log->url
= "review.php?id=".$log->cmid
."&attempt=".$att->new_id
;
1934 $log->info
= $mod->new_id
;
1940 case "editquestions":
1942 //Get the new_id of the module (to recode the url field)
1943 $mod = backup_getid($restore->backup_unique_code
,$log->module
,$log->info
);
1945 $log->url
= "view.php?id=".$log->cmid
;
1946 $log->info
= $mod->new_id
;
1952 echo "action (".$log->module
."-".$log->action
.") unknow. Not restored<br />"; //Debug