MDL-24224 fixing a couple more 'strin' typos
[moodle.git] / mod / quiz / backuplib.php
CommitLineData
83192608 1<?php
fe1106f0 2 //This php script contains all the stuff to backup quizzes
d7c93ec8 3
2e1111c5 4//This is the "graphical" structure of the quiz mod:
04bc8ed1 5 //To see, put your terminal to 160cc
d7c93ec8 6
d7c93ec8 7 //
fe1106f0 8 // quiz
9 // (CL,pk->id)
10 // |
11 // -------------------------------------------------------------------
6b224376 12 // | | | |
13 // | quiz_grades | |
14 // | (UL,pk->id,fk->quiz) | |
212b7b8c 15 // | | |
16 // quiz_attempts quiz_question_instances quiz_feedback
17 // (UL,pk->id,fk->quiz) (CL,pk->id,fk->quiz,question) (CL,pk->id,fk->quiz)
57ddd6ad 18 //
d7c93ec8 19 // Meaning: pk->primary key field of the table
20 // fk->foreign key to link with parent
21 // nt->nested field (recursive data)
57ddd6ad 22 // SL->site level info
d7c93ec8 23 // CL->course level info
24 // UL->user level info
25 // files->table may have files
26 //
27 //-----------------------------------------------------------
28
fe1106f0 29 // When we backup a quiz we also need to backup the questions and possibly
30 // the data about student interaction with the questions. The functions to do
31 // that are included with the following library
c5d94c41 32 require_once("$CFG->dirroot/question/backuplib.php");
a6a89b9e 33
271e6dec 34 /*
ede67707 35 * Insert necessary category ids to backup_ids table. Called during backup_check.html.
36 * This backs up ids for quiz module. It backs up :
37 * all categories and questions in course
38 * all categories and questions in contexts of quiz module instances which have been selected for backup
39 * all categories and questions in contexts above course level that are used by quizzes that have been selected for backup
271e6dec 40 */
b667e698 41 function quiz_insert_category_and_question_ids($course, $backup_unique_code, $instances = null) {
9cf4a18b 42 global $CFG, $DB;
ede67707 43 $status = true;
a6a89b9e 44
5a56d938 45 // Create missing categories and reasign orphaned questions.
b667e698 46 quiz_fix_orphaned_questions($course);
ede67707 47
271e6dec 48 $coursecontext = get_context_instance(CONTEXT_COURSE, $course);
ede67707 49 $status = $status && question_insert_c_and_q_ids_for_course($coursecontext, $backup_unique_code);
a6a89b9e 50
ede67707 51 // then, all categories and questions from this course's modules' contexts.
52 $status = $status && question_insert_c_and_q_ids_for_module($backup_unique_code, $course, 'quiz', $instances);
53
271e6dec 54
55 // Then categories from parent contexts used by the quizzes we are backing up.
271e6dec 56 $parentcontexts = get_parent_contexts($coursecontext);
9cf4a18b 57 $params = array($course);
58 $from = "{quiz} quiz,";
59 $where = "AND quiz.course = ?
271e6dec 60 AND qqi.quiz = quiz.id";
1ecea976 61 if (!empty($instances) && is_array($instances) && count($instances)) {
62f34fdb 62 $questionselectsqlfrom = '';
9cf4a18b 63 list($quiz_usql, $quiz_params) = $DB->get_in_or_equal(array_keys($instances));
64 $questionselectsqlwhere = "AND qqi.quiz $quiz_usql";
65 $params = array_merge($params, $quiz_params);
62f34fdb 66 } else {
9cf4a18b 67 $questionselectsqlfrom = "{quiz} quiz,";
68 $questionselectsqlwhere = "AND quiz.course = ? AND qqi.quiz = quiz.id";
69 $params[] = $course;
1ecea976 70 }
9cf4a18b 71
72 list($usql, $context_params) = $DB->get_in_or_equal($parentcontexts);
73 $params = array_merge($context_params, $params);
74 $categories = $DB->get_records_sql("
87454054 75 SELECT id, parent, 0 AS childrendone
9cf4a18b 76 FROM {question_categories}
77 WHERE contextid $usql
87454054 78 AND id IN (
62f34fdb 79 SELECT DISTINCT question.category
9cf4a18b 80 FROM {question} question,
62f34fdb 81 $questionselectsqlfrom
9cf4a18b 82 {quiz_question_instances} qqi
87454054 83 WHERE qqi.question = question.id
62f34fdb 84 $questionselectsqlwhere
9cf4a18b 85 )", $params);
271e6dec 86 if (!$categories) {
87 $categories = array();
88 } else {
89 //put the ids of the used questions from all these categories into the db.
9cf4a18b 90 $status = $status && $DB->execute("INSERT INTO {backup_ids}
271e6dec 91 (backup_code, table_name, old_id, info)
27cabbe6 92 SELECT DISTINCT $backup_unique_code, 'question', q.id, ''
9cf4a18b 93 FROM {question} q,
271e6dec 94 $from
9cf4a18b 95 {question_categories} qc,
96 {quiz_question_instances} qqi
271e6dec 97 WHERE (qqi.question = q.id
98 OR qqi.question = q.parent)
99 AND q.category = qc.id
9cf4a18b 100 AND qc.contextid $usql $where", array_merge($context_params, array($course)));
271e6dec 101
102 // Add the parent categories, of these categories up to the top of the category tree.
103 // not backing up the questions in these categories.
104 foreach ($categories as $category) {
105 while ($category->parent != 0) {
106 if (array_key_exists($category->parent, $categories)) {
107 // Parent category already on the list.
108 break;
109 }
110 $currentid = $category->id;
9cf4a18b 111 $category = $DB->get_record('question_categories', array('id' => $category->parent), 'id, parent, 0 AS childrendone');
271e6dec 112 if ($category) {
113 $categories[$category->id] = $category;
114 } else {
115 // Parent not found: this indicates an error, but just fix it.
9cf4a18b 116 $DB->set_field('question_categories', 'parent', 0, array('id' => $currentid));
271e6dec 117 break;
118 }
2e1111c5 119 }
120 }
62f34fdb 121
271e6dec 122 // Now we look for categories from other courses containing random questions
123 // in our quizzes that select from the category and its subcategories. That implies
124 // those subcategories also need to be backed up. (The categories themselves
125 // and their parents will already have been included.)
9cf4a18b 126 $categorieswithrandom = $DB->get_records_sql("
27cabbe6 127 SELECT question.category AS id, SUM(" .
245ac557 128 $DB->sql_cast_char2int('questiontext', true) . ") AS numqsusingsubcategories
9cf4a18b 129 FROM {quiz_question_instances} qqi,
271e6dec 130 $from
9cf4a18b 131 {question} question
271e6dec 132 WHERE question.id = qqi.question
133 AND question.qtype = '" . RANDOM . "'
134 $where
135 GROUP BY question.category
9cf4a18b 136 ", array($course));
271e6dec 137 $randomselectedquestions = array();
138 if ($categorieswithrandom) {
139 foreach ($categorieswithrandom as $category) {
27cabbe6 140 if ($category->numqsusingsubcategories > 0) {
271e6dec 141 $status = $status && quiz_backup_add_sub_categories($categories, $randomselectedquestions, $category->id);
142 }
143 }
9cf4a18b 144 list($usql, $params) = $DB->get_in_or_equal(array_keys($categorieswithrandom));
145 $returnval = $DB->get_records_sql("
271e6dec 146 SELECT question.id
9cf4a18b 147 FROM {question} question
148 WHERE question.category $usql", $params);
271e6dec 149 if ($returnval) {
150 $randomselectedquestions += $returnval;
62f34fdb 151 }
6a687a0e 152 }
2e1111c5 153
271e6dec 154 // Finally, add all these extra categories to the backup_ids table.
155 foreach ($categories as $category) {
156 $status = $status && backup_putid($backup_unique_code, 'question_categories', $category->id, 0);
157 }
158 // Finally, add all these extra categories to the backup_ids table.
159 foreach ($randomselectedquestions as $question) {
160 $status = $status && backup_putid($backup_unique_code, 'question', $question->id, 0);
161 }
87454054 162 }
2e1111c5 163 return $status;
164 }
a6a89b9e 165
6a687a0e 166 /**
87454054 167 * Helper function adding the id of all the subcategories of a category to an array.
168 */
271e6dec 169 function quiz_backup_add_sub_categories(&$categories, &$questions, $categoryid) {
9cf4a18b 170 global $CFG, $DB;
87454054 171 $status = true;
172 if ($categories[$categoryid]->childrendone) {
173 return $status;
174 }
9cf4a18b 175 if ($subcategories = $DB->get_records('question_categories', array('parent' => $categoryid), '', 'id, 0 AS childrendone')) {
6a687a0e 176 foreach ($subcategories as $subcategory) {
87454054 177 if (!array_key_exists($subcategory->id, $categories)) {
178 $categories[$subcategory->id] = $subcategory;
179 }
271e6dec 180 $status = $status && quiz_backup_add_sub_categories($categories, $questions, $subcategory->id);
181 }
9cf4a18b 182 list($usql, $params) = $DB->get_in_or_equal(array_keys($subcategories));
183 $returnval = $DB->get_records_sql("
271e6dec 184 SELECT question.id
9cf4a18b 185 FROM {question} question
186 WHERE question.category $usql", $params);
271e6dec 187 if ($returnval) {
188 $questions += $returnval;
6a687a0e 189 }
190 }
87454054 191 $categories[$categoryid]->childrendone = 1;
6a687a0e 192 return $status;
193 }
62f34fdb 194
2e1111c5 195
196 //This function is used to detect orphaned questions (pointing to a
197 //non existing category) and to recreate such category. This function
198 //is used by the backup process, to ensure consistency and should be
199 //executed in the upgrade process and, perhaps in the health center.
b667e698 200 function quiz_fix_orphaned_questions ($course) {
2e1111c5 201
9cf4a18b 202 global $CFG, $DB;
2e1111c5 203
9cf4a18b 204 $categories = $DB->get_records_sql("SELECT DISTINCT t.category, t.category
205 FROM {question} t,
206 {quiz_question_instances} g,
207 {quiz} q
208 WHERE q.course = ? AND
209 g.quiz = q.id AND
2bc71036 210 g.question = t.id", array($course));
2e1111c5 211 if ($categories) {
212 foreach ($categories as $key => $category) {
9cf4a18b 213 $exist = $DB->get_record('question_categories', array('id' => $key));
2e1111c5 214 //If the category doesn't exist
215 if (!$exist) {
216 //Build a new category
199e43d4 217 $db_cat = new stdClass;
271e6dec 218 // always create missing categories in course context
219 $db_cat->contextid = get_context_instance(CONTEXT_COURSE, $course);
2e1111c5 220 $db_cat->name = get_string('recreatedcategory','',$key);
221 $db_cat->info = get_string('recreatedcategory','',$key);
2e1111c5 222 $db_cat->stamp = make_unique_id_code();
223 //Insert the new category
9cf4a18b 224 $catid = $DB->insert_record('question_categories',$db_cat);
2e1111c5 225 unset ($db_cat);
226 if ($catid) {
227 //Reasign orphaned questions to their new category
9cf4a18b 228 $DB->set_field ('question','category',$catid,array('category' =>$key));
2e1111c5 229 }
230 }
231 }
232 }
233 }
bb7e09a4 234
d7c93ec8 235
c6293e00 236//STEP 2. Backup quizzes and associated structures
237 // (course dependent)
1ecea976 238
239 function quiz_backup_one_mod($bf,$preferences,$quiz) {
9cf4a18b 240 global $DB;
1ecea976 241 $status = true;
242
243 if (is_numeric($quiz)) {
9cf4a18b 244 $quiz = $DB->get_record('quiz', array('id' => $quiz));
1ecea976 245 }
62f34fdb 246
1ecea976 247 //Start mod
248 fwrite ($bf,start_tag("MOD",3,true));
249 //Print quiz data
250 fwrite ($bf,full_tag("ID",4,false,$quiz->id));
251 fwrite ($bf,full_tag("MODTYPE",4,false,"quiz"));
252 fwrite ($bf,full_tag("NAME",4,false,$quiz->name));
253 fwrite ($bf,full_tag("INTRO",4,false,$quiz->intro));
254 fwrite ($bf,full_tag("TIMEOPEN",4,false,$quiz->timeopen));
255 fwrite ($bf,full_tag("TIMECLOSE",4,false,$quiz->timeclose));
256 fwrite ($bf,full_tag("OPTIONFLAGS",4,false,$quiz->optionflags));
257 fwrite ($bf,full_tag("PENALTYSCHEME",4,false,$quiz->penaltyscheme));
258 fwrite ($bf,full_tag("ATTEMPTS_NUMBER",4,false,$quiz->attempts));
259 fwrite ($bf,full_tag("ATTEMPTONLAST",4,false,$quiz->attemptonlast));
260 fwrite ($bf,full_tag("GRADEMETHOD",4,false,$quiz->grademethod));
261 fwrite ($bf,full_tag("DECIMALPOINTS",4,false,$quiz->decimalpoints));
262 fwrite ($bf,full_tag("REVIEW",4,false,$quiz->review));
263 fwrite ($bf,full_tag("QUESTIONSPERPAGE",4,false,$quiz->questionsperpage));
264 fwrite ($bf,full_tag("SHUFFLEQUESTIONS",4,false,$quiz->shufflequestions));
265 fwrite ($bf,full_tag("SHUFFLEANSWERS",4,false,$quiz->shuffleanswers));
266 fwrite ($bf,full_tag("QUESTIONS",4,false,$quiz->questions));
267 fwrite ($bf,full_tag("SUMGRADES",4,false,$quiz->sumgrades));
268 fwrite ($bf,full_tag("GRADE",4,false,$quiz->grade));
269 fwrite ($bf,full_tag("TIMECREATED",4,false,$quiz->timecreated));
270 fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$quiz->timemodified));
84e628a0 271 fwrite ($bf,full_tag("TIMELIMIT",4,false,round($quiz->timelimit/60)));
272 fwrite ($bf,full_tag("TIMELIMITSECS",4,false,$quiz->timelimit));
1ecea976 273 fwrite ($bf,full_tag("PASSWORD",4,false,$quiz->password));
274 fwrite ($bf,full_tag("SUBNET",4,false,$quiz->subnet));
275 fwrite ($bf,full_tag("POPUP",4,false,$quiz->popup));
fd198b87 276 fwrite ($bf,full_tag("DELAY1",4,false,$quiz->delay1));
277 fwrite ($bf,full_tag("DELAY2",4,false,$quiz->delay2));
1ecea976 278 //Now we print to xml question_instances (Course Level)
c4c7a2a6 279 $status = backup_quiz_question_instances($bf,$preferences,$quiz->id);
212b7b8c 280 //Now we print to xml quiz_feedback (Course Level)
281 $status = backup_quiz_feedback($bf,$preferences,$quiz->id);
990650f9
TH
282 //Now we print to xml quiz_overrides (Course Level)
283 $status = backup_quiz_overrides($bf,$preferences,$quiz->id);
1ecea976 284 //if we've selected to backup users info, then execute:
285 // - backup_quiz_grades
286 // - backup_quiz_attempts
287 if (backup_userdata_selected($preferences,'quiz',$quiz->id) && $status) {
c4c7a2a6 288 $status = backup_quiz_grades($bf,$preferences,$quiz->id);
1ecea976 289 if ($status) {
c4c7a2a6 290 $status = backup_quiz_attempts($bf,$preferences,$quiz->id);
1ecea976 291 }
292 }
293 //End mod
c4c7a2a6 294 $status = fwrite ($bf,end_tag("MOD",3,true));
62f34fdb 295
1ecea976 296 return $status;
297 }
298
299
d7c93ec8 300 function quiz_backup_mods($bf,$preferences) {
9cf4a18b 301 global $DB;
d7c93ec8 302
303 global $CFG;
304
305 $status = true;
306
307 //Iterate over quiz table
9cf4a18b 308 $quizzes = $DB->get_records('quiz',array('course' => $preferences->backup_course),'id');
d7c93ec8 309 if ($quizzes) {
310 foreach ($quizzes as $quiz) {
1ecea976 311 if (backup_mod_selected($preferences,'quiz',$quiz->id)) {
c4c7a2a6 312 $status = quiz_backup_one_mod($bf,$preferences,$quiz);
d7c93ec8 313 }
d7c93ec8 314 }
315 }
316 return $status;
317 }
318
ee1fb969 319 //Backup quiz_question_instances contents (executed from quiz_backup_mods)
320 function backup_quiz_question_instances ($bf,$preferences,$quiz) {
9cf4a18b 321 global $DB;
d7c93ec8 322 $status = true;
323
9cf4a18b 324 $quiz_question_instances = $DB->get_records('quiz_question_instances',array('quiz' =>$quiz),'id');
ee1fb969 325 //If there are question_instances
326 if ($quiz_question_instances) {
d7c93ec8 327 //Write start tag
c4c7a2a6 328 $status = fwrite ($bf,start_tag("QUESTION_INSTANCES",4,true));
ee1fb969 329 //Iterate over each question_instance
330 foreach ($quiz_question_instances as $que_ins) {
331 //Start question instance
c4c7a2a6 332 $status = fwrite ($bf,start_tag("QUESTION_INSTANCE",5,true));
ee1fb969 333 //Print question_instance contents
334 fwrite ($bf,full_tag("ID",6,false,$que_ins->id));
335 fwrite ($bf,full_tag("QUESTION",6,false,$que_ins->question));
336 fwrite ($bf,full_tag("GRADE",6,false,$que_ins->grade));
337 //End question instance
c4c7a2a6 338 $status = fwrite ($bf,end_tag("QUESTION_INSTANCE",5,true));
ee1fb969 339 }
340 //Write end tag
c4c7a2a6 341 $status = fwrite ($bf,end_tag("QUESTION_INSTANCES",4,true));
ee1fb969 342 }
343 return $status;
344 }
345
990650f9
TH
346 //Backup quiz_overrides contents (executed from quiz_backup_mods)
347 function backup_quiz_overrides ($bf,$preferences,$quiz) {
348 global $DB;
349 $status = true;
350 $douserdata = backup_userdata_selected($preferences,'quiz',$quiz);
351
352 $quiz_overrides = $DB->get_records('quiz_overrides',array('quiz' =>$quiz),'id');
353 //If there are quiz_overrides
354 if ($quiz_overrides) {
355 //Write start tag
356 $status = fwrite ($bf,start_tag("OVERRIDES",4,true));
357 //Iterate over each quiz_override
358 foreach ($quiz_overrides as $quiz_override) {
359 // Only backup user overrides if we are backing up user data
360 if ($douserdata || $quiz_override->userid == 0) {
361 //Start quiz override
362 $status = fwrite ($bf,start_tag("OVERRIDE",5,true));
363 //Print quiz_override contents
364 fwrite ($bf,full_tag("ID",6,false,$quiz_override->id));
365 fwrite ($bf,full_tag("USERID",6,false,$quiz_override->userid));
366 fwrite ($bf,full_tag("GROUPID",6,false,$quiz_override->groupid));
367 fwrite ($bf,full_tag("TIMEOPEN",6,false,$quiz_override->timeopen));
368 fwrite ($bf,full_tag("TIMECLOSE",6,false,$quiz_override->timeclose));
369 fwrite ($bf,full_tag("TIMELIMIT",6,false,$quiz_override->timelimit));
370 fwrite ($bf,full_tag("ATTEMPTS",6,false,$quiz_override->attempts));
371 fwrite ($bf,full_tag("PASSWORD",6,false,$quiz_override->password));
372 //End quiz override
373 $status = fwrite ($bf,end_tag("OVERRIDE",5,true));
374 }
375 }
376 //Write end tag
377 $status = fwrite ($bf,end_tag("OVERRIDES",4,true));
378 }
379 return $status;
380 }
381
212b7b8c 382 //Backup quiz_question_instances contents (executed from quiz_backup_mods)
383 function backup_quiz_feedback ($bf,$preferences,$quiz) {
9cf4a18b 384 global $DB;
212b7b8c 385 $status = true;
386
9cf4a18b 387 $quiz_feedback = $DB->get_records('quiz_feedback', array('quizid' => $quiz), 'id');
212b7b8c 388 // If there are question_instances ...
389 if ($quiz_feedback) {
390 // Write start tag.
391 $status = $status & fwrite($bf,start_tag('FEEDBACKS', 4, true));
62f34fdb 392
212b7b8c 393 // Iterate over each question_instance.
394 foreach ($quiz_feedback as $feedback) {
62f34fdb 395
212b7b8c 396 //Start feedback instance
397 $status = $status & fwrite($bf, start_tag('FEEDBACK',5,true));
62f34fdb 398
212b7b8c 399 //Print question_instance contents.
400 $status = $status & fwrite($bf, full_tag('ID', 6, false, $feedback->id));
401 $status = $status & fwrite($bf, full_tag('QUIZID', 6, false, $feedback->quizid));
402 $status = $status & fwrite($bf, full_tag('FEEDBACKTEXT', 6, false, $feedback->feedbacktext));
403 $status = $status & fwrite($bf, full_tag('MINGRADE', 6, false, $feedback->mingrade));
404 $status = $status & fwrite($bf, full_tag('MAXGRADE', 6, false, $feedback->maxgrade));
62f34fdb 405
212b7b8c 406 // End feedback instance.
407 $status = $status & fwrite($bf, end_tag('FEEDBACK', 5, true));
408 }
62f34fdb 409
212b7b8c 410 // Write end tag.
411 $status = $status & fwrite($bf, end_tag('FEEDBACKS', 4, true));
412 }
413 return $status;
414 }
62f34fdb 415
d7c93ec8 416 //Backup quiz_grades contents (executed from quiz_backup_mods)
417 function backup_quiz_grades ($bf,$preferences,$quiz) {
9cf4a18b 418 global $DB;
d7c93ec8 419 $status = true;
420
9cf4a18b 421 $quiz_grades = $DB->get_records('quiz_grades',array('quiz' => $quiz),'id');
d7c93ec8 422 //If there are grades
423 if ($quiz_grades) {
424 //Write start tag
c4c7a2a6 425 $status = fwrite ($bf,start_tag("GRADES",4,true));
d7c93ec8 426 //Iterate over each grade
427 foreach ($quiz_grades as $gra) {
428 //Start grade
c4c7a2a6 429 $status = fwrite ($bf,start_tag("GRADE",5,true));
d7c93ec8 430 //Print grade contents
431 fwrite ($bf,full_tag("ID",6,false,$gra->id));
432 fwrite ($bf,full_tag("USERID",6,false,$gra->userid));
433 fwrite ($bf,full_tag("GRADEVAL",6,false,$gra->grade));
434 fwrite ($bf,full_tag("TIMEMODIFIED",6,false,$gra->timemodified));
435 //End question grade
c4c7a2a6 436 $status = fwrite ($bf,end_tag("GRADE",5,true));
d7c93ec8 437 }
438 //Write end tag
c4c7a2a6 439 $status = fwrite ($bf,end_tag("GRADES",4,true));
d7c93ec8 440 }
441 return $status;
442 }
443
444 //Backup quiz_attempts contents (executed from quiz_backup_mods)
445 function backup_quiz_attempts ($bf,$preferences,$quiz) {
9cf4a18b 446 global $DB;
d7c93ec8 447 $status = true;
448
9cf4a18b 449 $quiz_attempts = $DB->get_records('quiz_attempts', array('quiz' => $quiz),'id');
d7c93ec8 450 //If there are attempts
451 if ($quiz_attempts) {
452 //Write start tag
c4c7a2a6 453 $status = fwrite ($bf,start_tag("ATTEMPTS",4,true));
d7c93ec8 454 //Iterate over each attempt
455 foreach ($quiz_attempts as $attempt) {
456 //Start attempt
c4c7a2a6 457 $status = fwrite ($bf,start_tag("ATTEMPT",5,true));
d7c93ec8 458 //Print attempt contents
459 fwrite ($bf,full_tag("ID",6,false,$attempt->id));
d115d8c7 460 fwrite ($bf,full_tag("UNIQUEID",6,false,$attempt->uniqueid));
d7c93ec8 461 fwrite ($bf,full_tag("USERID",6,false,$attempt->userid));
462 fwrite ($bf,full_tag("ATTEMPTNUM",6,false,$attempt->attempt));
463 fwrite ($bf,full_tag("SUMGRADES",6,false,$attempt->sumgrades));
464 fwrite ($bf,full_tag("TIMESTART",6,false,$attempt->timestart));
465 fwrite ($bf,full_tag("TIMEFINISH",6,false,$attempt->timefinish));
466 fwrite ($bf,full_tag("TIMEMODIFIED",6,false,$attempt->timemodified));
57ddd6ad 467 fwrite ($bf,full_tag("LAYOUT",6,false,$attempt->layout));
468 fwrite ($bf,full_tag("PREVIEW",6,false,$attempt->preview));
ee1fb969 469 //Now write to xml the states (in this attempt)
4f48fb42 470 $status = backup_question_states ($bf,$preferences,$attempt->uniqueid);
c6293e00 471 //Now write to xml the sessions (in this attempt)
472 $status = backup_question_sessions ($bf,$preferences,$attempt->uniqueid);
d7c93ec8 473 //End attempt
c4c7a2a6 474 $status = fwrite ($bf,end_tag("ATTEMPT",5,true));
d7c93ec8 475 }
476 //Write end tag
c4c7a2a6 477 $status = fwrite ($bf,end_tag("ATTEMPTS",4,true));
d7c93ec8 478 }
479 return $status;
480 }
481
1ecea976 482 function quiz_check_backup_mods_instances($instance,$backup_unique_code) {
483 // the keys in this array need to be unique as they get merged...
484 $info[$instance->id.'0'][0] = '<b>'.$instance->name.'</b>';
485 $info[$instance->id.'0'][1] = '';
486
487 //Categories
488 $info[$instance->id.'1'][0] = get_string("categories","quiz");
dc1f00de 489 if ($ids = question_category_ids_by_backup ($backup_unique_code)) {
1ecea976 490 $info[$instance->id.'1'][1] = count($ids);
491 } else {
492 $info[$instance->id.'1'][1] = 0;
493 }
494 //Questions
e1eed5cc 495 $info[$instance->id.'2'][0] = get_string("questionsinclhidden","quiz");
fe1106f0 496 if ($ids = question_ids_by_backup ($backup_unique_code)) {
1ecea976 497 $info[$instance->id.'2'][1] = count($ids);
498 } else {
499 $info[$instance->id.'2'][1] = 0;
500 }
501
502 //Now, if requested, the user_data
503 if (!empty($instance->userdata)) {
504 //Grades
505 $info[$instance->id.'3'][0] = get_string("grades");
506 if ($ids = quiz_grade_ids_by_instance ($instance->id)) {
507 $info[$instance->id.'3'][1] = count($ids);
508 } else {
509 $info[$instance->id.'3'][1] = 0;
510 }
511 }
512 return $info;
513 }
62f34fdb 514
d7c93ec8 515 ////Return an array of info (name,value)
1ecea976 516/// $instances is an array with key = instanceid, value = object (name,id,userdata)
6a687a0e 517 function quiz_check_backup_mods($course,$user_data= false,$backup_unique_code,$instances=null) {
271e6dec 518 //this function selects all the questions / categories to be backed up.
b667e698 519 quiz_insert_category_and_question_ids($course, $backup_unique_code, $instances);
271e6dec 520 if ($course != SITEID){
521 question_insert_site_file_names($course, $backup_unique_code);
522 }
1ecea976 523 if (!empty($instances) && is_array($instances) && count($instances)) {
524 $info = array();
525 foreach ($instances as $id => $instance) {
526 $info += quiz_check_backup_mods_instances($instance,$backup_unique_code);
527 }
528 return $info;
529 }
d7c93ec8 530 //First the course data
531 $info[0][0] = get_string("modulenameplural","quiz");
532 if ($ids = quiz_ids ($course)) {
533 $info[0][1] = count($ids);
534 } else {
535 $info[0][1] = 0;
536 }
537 //Categories
538 $info[1][0] = get_string("categories","quiz");
dc1f00de 539 if ($ids = question_category_ids_by_backup ($backup_unique_code)) {
d7c93ec8 540 $info[1][1] = count($ids);
541 } else {
542 $info[1][1] = 0;
543 }
544 //Questions
545 $info[2][0] = get_string("questions","quiz");
fe1106f0 546 if ($ids = question_ids_by_backup ($backup_unique_code)) {
d7c93ec8 547 $info[2][1] = count($ids);
548 } else {
549 $info[2][1] = 0;
550 }
551
552 //Now, if requested, the user_data
553 if ($user_data) {
57ddd6ad 554 //Grades
555 $info[3][0] = get_string("grades");
556 if ($ids = quiz_grade_ids_by_course ($course)) {
d7c93ec8 557 $info[3][1] = count($ids);
558 } else {
559 $info[3][1] = 0;
560 }
561 }
562
563 return $info;
564 }
565
bb7e09a4 566 //Return a content encoded to support interactivities linking. Every module
567 //should have its own. They are called automatically from the backup procedure.
568 function quiz_encode_content_links ($content,$preferences) {
569
570 global $CFG;
571
572 $base = preg_quote($CFG->wwwroot,"/");
573
574 //Link to the list of quizs
575 $buscar="/(".$base."\/mod\/quiz\/index.php\?id\=)([0-9]+)/";
576 $result= preg_replace($buscar,'$@QUIZINDEX*$2@$',$content);
577
578 //Link to quiz view by moduleid
579 $buscar="/(".$base."\/mod\/quiz\/view.php\?id\=)([0-9]+)/";
580 $result= preg_replace($buscar,'$@QUIZVIEWBYID*$2@$',$result);
8cfd7faf 581
582 //Link to quiz view by quizid
583 $buscar="/(".$base."\/mod\/quiz\/view.php\?q\=)([0-9]+)/";
584 $result= preg_replace($buscar,'$@QUIZVIEWBYQ*$2@$',$result);
bb7e09a4 585
586 return $result;
587 }
d7c93ec8 588
2e1111c5 589// INTERNAL FUNCTIONS. BASED IN THE MOD STRUCTURE
d7c93ec8 590
591 //Returns an array of quiz id
592 function quiz_ids ($course) {
593
9cf4a18b 594 global $CFG, $DB;
d7c93ec8 595
9cf4a18b 596 return $DB->get_records_sql ("SELECT a.id, a.course
597 FROM {quiz} a
598 WHERE a.course = ?", array($course));
d7c93ec8 599 }
600
d7c93ec8 601 function quiz_grade_ids_by_course ($course) {
602
9cf4a18b 603 global $CFG, $DB;
d7c93ec8 604
9cf4a18b 605 return $DB->get_records_sql ("SELECT g.id, g.quiz
606 FROM {quiz} a,
607 {quiz_grades} g
608 WHERE a.course = ? and
609 g.quiz = a.id", array($course));
d7c93ec8 610 }
611
1ecea976 612 function quiz_grade_ids_by_instance($instanceid) {
613
9cf4a18b 614 global $CFG, $DB;
1ecea976 615
9cf4a18b 616 return $DB->get_records_sql ("SELECT g.id, g.quiz
617 FROM {quiz_grades} g
618 WHERE g.quiz = ?", array($instanceid));
1ecea976 619 }
620
83192608 621