6be2160c7c0ed62cd72c3c1e81812251aa3dc16c
[moodle.git] / mod / quiz / backuplib.php
1 <?php
2     //This php script contains all the stuff to backup quizzes
4 //This is the "graphical" structure of the quiz mod:
5     //To see, put your terminal to 160cc
7     //
8     //                           quiz
9     //                        (CL,pk->id)
10     //                            |
11     //           -------------------------------------------------------------------
12     //           |               |                |                                |
13     //           |          quiz_grades           |                                |
14     //           |      (UL,pk->id,fk->quiz)      |                                |
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)
18     //
19     // Meaning: pk->primary key field of the table
20     //          fk->foreign key to link with parent
21     //          nt->nested field (recursive data)
22     //          SL->site level info
23     //          CL->course level info
24     //          UL->user level info
25     //          files->table may have files
26     //
27     //-----------------------------------------------------------
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
32     require_once("$CFG->dirroot/question/backuplib.php");
34     /*
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
40      */
41     function quiz_insert_category_and_question_ids($course, $backup_unique_code, $instances = null) {
42         global $CFG, $DB;
43         $status = true;
45         // Create missing categories and reasign orphaned questions.
46         quiz_fix_orphaned_questions($course);
48         $coursecontext = get_context_instance(CONTEXT_COURSE, $course);
49         $status = $status && question_insert_c_and_q_ids_for_course($coursecontext, $backup_unique_code);
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);
55         // Then categories from parent contexts used by the quizzes we are backing up.
56         $parentcontexts = get_parent_contexts($coursecontext);
57         $params = array($course);
58         $from = "{quiz} quiz,";
59         $where = "AND quiz.course = ?
60                      AND qqi.quiz = quiz.id";
61         if (!empty($instances) && is_array($instances) && count($instances)) {
62             $questionselectsqlfrom = '';
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);
66         } else {
67             $questionselectsqlfrom = "{quiz} quiz,";
68             $questionselectsqlwhere = "AND quiz.course = ? AND qqi.quiz = quiz.id";
69             $params[] = $course;
70         }
72         list($usql, $context_params) = $DB->get_in_or_equal($parentcontexts);
73         $params = array_merge($context_params, $params);
74         $categories = $DB->get_records_sql("
75                 SELECT id, parent, 0 AS childrendone
76                 FROM {question_categories}
77                 WHERE contextid $usql
78                   AND id IN (
79                     SELECT DISTINCT question.category
80                     FROM {question} question,
81                          $questionselectsqlfrom
82                          {quiz_question_instances} qqi
83                     WHERE qqi.question = question.id
84                       $questionselectsqlwhere
85                 )", $params);
86         if (!$categories) {
87             $categories = array();
88         } else {
89             //put the ids of the used questions from all these categories into the db.
90             $status = $status && $DB->execute("INSERT INTO {backup_ids}
91                                        (backup_code, table_name, old_id, info)
92                                        SELECT DISTINCT $backup_unique_code, 'question', q.id, ''
93                                        FROM {question} q,
94                                        $from
95                                        {question_categories} qc,
96                                        {quiz_question_instances} qqi
97                                        WHERE (qqi.question = q.id
98                                        OR qqi.question = q.parent)
99                                        AND q.category = qc.id
100                                        AND qc.contextid $usql $where", array_merge($context_params, array($course)));
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;
111                     $category = $DB->get_record('question_categories', array('id' => $category->parent), 'id, parent, 0 AS childrendone');
112                     if ($category) {
113                         $categories[$category->id] = $category;
114                     } else {
115                         // Parent not found: this indicates an error, but just fix it.
116                         $DB->set_field('question_categories', 'parent', 0, array('id' => $currentid));
117                         break;
118                     }
119                 }
120             }
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.)
126             $categorieswithrandom = $DB->get_records_sql("
127                     SELECT question.category AS id, SUM(" .
128                             $DB->sql_cast_char2int('questiontext', true) . ") AS numqsusingsubcategories
129                     FROM {quiz_question_instances} qqi,
130                          $from
131                          {question} question
132                     WHERE question.id = qqi.question
133                       AND question.qtype = '" . RANDOM . "'
134                       $where
135                     GROUP BY question.category
136                     ", array($course));
137             $randomselectedquestions = array();
138             if ($categorieswithrandom) {
139                 foreach ($categorieswithrandom as $category) {
140                     if ($category->numqsusingsubcategories > 0) {
141                         $status = $status && quiz_backup_add_sub_categories($categories, $randomselectedquestions, $category->id);
142                     }
143                 }
144                 list($usql, $params) = $DB->get_in_or_equal(array_keys($categorieswithrandom));
145                 $returnval = $DB->get_records_sql("
146                     SELECT question.id
147                     FROM {question} question
148                     WHERE question.category $usql", $params);
149                 if ($returnval) {
150                     $randomselectedquestions += $returnval;
151                 }
152             }
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             }
162         }
163         return $status;
164     }
166     /**
167      * Helper function adding the id of all the subcategories of a category to an array.
168      */
169     function quiz_backup_add_sub_categories(&$categories, &$questions, $categoryid) {
170         global $CFG, $DB;
171         $status = true;
172         if ($categories[$categoryid]->childrendone) {
173             return $status;
174         }
175         if ($subcategories = $DB->get_records('question_categories', array('parent' => $categoryid), '', 'id, 0 AS childrendone')) {
176             foreach ($subcategories as $subcategory) {
177                 if (!array_key_exists($subcategory->id, $categories)) {
178                     $categories[$subcategory->id] = $subcategory;
179                 }
180                 $status = $status && quiz_backup_add_sub_categories($categories, $questions, $subcategory->id);
181             }
182             list($usql, $params) = $DB->get_in_or_equal(array_keys($subcategories));
183             $returnval = $DB->get_records_sql("
184                 SELECT question.id
185                 FROM {question} question
186                 WHERE question.category $usql", $params);
187             if ($returnval) {
188                 $questions += $returnval;
189             }
190         }
191         $categories[$categoryid]->childrendone = 1;
192         return $status;
193     }
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.
200     function quiz_fix_orphaned_questions ($course) {
202         global $CFG, $DB;
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
210                                                  g.question = t.id", array($course));
211         if ($categories) {
212             foreach ($categories as $key => $category) {
213                 $exist = $DB->get_record('question_categories', array('id' => $key));
214                 //If the category doesn't exist
215                 if (!$exist) {
216                     //Build a new category
217                     $db_cat = new stdClass;
218                     // always create missing categories in course context
219                     $db_cat->contextid = get_context_instance(CONTEXT_COURSE, $course);
220                     $db_cat->name = get_string('recreatedcategory','',$key);
221                     $db_cat->info = get_string('recreatedcategory','',$key);
222                     $db_cat->stamp = make_unique_id_code();
223                     //Insert the new category
224                     $catid = $DB->insert_record('question_categories',$db_cat);
225                     unset ($db_cat);
226                     if ($catid) {
227                         //Reasign orphaned questions to their new category
228                         $DB->set_field ('question','category',$catid,array('category' =>$key));
229                     }
230                 }
231             }
232         }
233     }
236 //STEP 2. Backup quizzes and associated structures
237     //    (course dependent)
239     function quiz_backup_one_mod($bf,$preferences,$quiz) {
240         global $DB;
241         $status = true;
243         if (is_numeric($quiz)) {
244             $quiz = $DB->get_record('quiz', array('id' => $quiz));
245         }
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));
271         fwrite ($bf,full_tag("TIMELIMIT",4,false,round($quiz->timelimit/60)));
272         fwrite ($bf,full_tag("TIMELIMITSECS",4,false,$quiz->timelimit));
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));
276         fwrite ($bf,full_tag("DELAY1",4,false,$quiz->delay1));
277         fwrite ($bf,full_tag("DELAY2",4,false,$quiz->delay2));
278         //Now we print to xml question_instances (Course Level)
279         $status = backup_quiz_question_instances($bf,$preferences,$quiz->id);
280         //Now we print to xml quiz_feedback (Course Level)
281         $status = backup_quiz_feedback($bf,$preferences,$quiz->id);
282         //Now we print to xml quiz_overrides (Course Level)
283         $status = backup_quiz_overrides($bf,$preferences,$quiz->id);
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) {
288             $status = backup_quiz_grades($bf,$preferences,$quiz->id);
289             if ($status) {
290                 $status = backup_quiz_attempts($bf,$preferences,$quiz->id);
291             }
292         }
293         //End mod
294         $status = fwrite ($bf,end_tag("MOD",3,true));
296         return $status;
297     }
300     function quiz_backup_mods($bf,$preferences) {
301         global $DB;
303         global $CFG;
305         $status = true;
307         //Iterate over quiz table
308         $quizzes = $DB->get_records('quiz',array('course' => $preferences->backup_course),'id');
309         if ($quizzes) {
310             foreach ($quizzes as $quiz) {
311                 if (backup_mod_selected($preferences,'quiz',$quiz->id)) {
312                     $status = quiz_backup_one_mod($bf,$preferences,$quiz);
313                 }
314             }
315         }
316         return $status;
317     }
319     //Backup quiz_question_instances contents (executed from quiz_backup_mods)
320     function backup_quiz_question_instances ($bf,$preferences,$quiz) {
321         global $DB;
322         $status = true;
324         $quiz_question_instances = $DB->get_records('quiz_question_instances',array('quiz' =>$quiz),'id');
325         //If there are question_instances
326         if ($quiz_question_instances) {
327             //Write start tag
328             $status = fwrite ($bf,start_tag("QUESTION_INSTANCES",4,true));
329             //Iterate over each question_instance
330             foreach ($quiz_question_instances as $que_ins) {
331                 //Start question instance
332                 $status = fwrite ($bf,start_tag("QUESTION_INSTANCE",5,true));
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
338                 $status = fwrite ($bf,end_tag("QUESTION_INSTANCE",5,true));
339             }
340             //Write end tag
341             $status = fwrite ($bf,end_tag("QUESTION_INSTANCES",4,true));
342         }
343         return $status;
344     }
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);
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     }
382     //Backup quiz_question_instances contents (executed from quiz_backup_mods)
383     function backup_quiz_feedback ($bf,$preferences,$quiz) {
384         global $DB;
385         $status = true;
387         $quiz_feedback = $DB->get_records('quiz_feedback', array('quizid' => $quiz), 'id');
388         // If there are question_instances ...
389         if ($quiz_feedback) {
390             // Write start tag.
391             $status = $status & fwrite($bf,start_tag('FEEDBACKS', 4, true));
393             // Iterate over each question_instance.
394             foreach ($quiz_feedback as $feedback) {
396                 //Start feedback instance
397                 $status = $status & fwrite($bf, start_tag('FEEDBACK',5,true));
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));
406                 // End feedback instance.
407                 $status = $status & fwrite($bf, end_tag('FEEDBACK', 5, true));
408             }
410             // Write end tag.
411             $status = $status & fwrite($bf, end_tag('FEEDBACKS', 4, true));
412         }
413         return $status;
414     }
416     //Backup quiz_grades contents (executed from quiz_backup_mods)
417     function backup_quiz_grades ($bf,$preferences,$quiz) {
418         global $DB;
419         $status = true;
421         $quiz_grades = $DB->get_records('quiz_grades',array('quiz' => $quiz),'id');
422         //If there are grades
423         if ($quiz_grades) {
424             //Write start tag
425             $status = fwrite ($bf,start_tag("GRADES",4,true));
426             //Iterate over each grade
427             foreach ($quiz_grades as $gra) {
428                 //Start grade
429                 $status = fwrite ($bf,start_tag("GRADE",5,true));
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
436                 $status = fwrite ($bf,end_tag("GRADE",5,true));
437             }
438             //Write end tag
439             $status = fwrite ($bf,end_tag("GRADES",4,true));
440         }
441         return $status;
442     }
444     //Backup quiz_attempts contents (executed from quiz_backup_mods)
445     function backup_quiz_attempts ($bf,$preferences,$quiz) {
446         global $DB;
447         $status = true;
449         $quiz_attempts = $DB->get_records('quiz_attempts', array('quiz' => $quiz),'id');
450         //If there are attempts
451         if ($quiz_attempts) {
452             //Write start tag
453             $status = fwrite ($bf,start_tag("ATTEMPTS",4,true));
454             //Iterate over each attempt
455             foreach ($quiz_attempts as $attempt) {
456                 //Start attempt
457                 $status = fwrite ($bf,start_tag("ATTEMPT",5,true));
458                 //Print attempt contents
459                 fwrite ($bf,full_tag("ID",6,false,$attempt->id));
460                 fwrite ($bf,full_tag("UNIQUEID",6,false,$attempt->uniqueid));
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));
467                 fwrite ($bf,full_tag("LAYOUT",6,false,$attempt->layout));
468                 fwrite ($bf,full_tag("PREVIEW",6,false,$attempt->preview));
469                 //Now write to xml the states (in this attempt)
470                 $status = backup_question_states ($bf,$preferences,$attempt->uniqueid);
471                 //Now write to xml the sessions (in this attempt)
472                 $status = backup_question_sessions ($bf,$preferences,$attempt->uniqueid);
473                 //End attempt
474                 $status = fwrite ($bf,end_tag("ATTEMPT",5,true));
475             }
476             //Write end tag
477             $status = fwrite ($bf,end_tag("ATTEMPTS",4,true));
478         }
479         return $status;
480     }
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] = '';
487         //Categories
488         $info[$instance->id.'1'][0] = get_string("categories","quiz");
489         if ($ids = question_category_ids_by_backup ($backup_unique_code)) {
490             $info[$instance->id.'1'][1] = count($ids);
491         } else {
492             $info[$instance->id.'1'][1] = 0;
493         }
494         //Questions
495         $info[$instance->id.'2'][0] = get_string("questionsinclhidden","quiz");
496         if ($ids = question_ids_by_backup ($backup_unique_code)) {
497             $info[$instance->id.'2'][1] = count($ids);
498         } else {
499             $info[$instance->id.'2'][1] = 0;
500         }
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     }
515    ////Return an array of info (name,value)
516 /// $instances is an array with key = instanceid, value = object (name,id,userdata)
517    function quiz_check_backup_mods($course,$user_data= false,$backup_unique_code,$instances=null) {
518         //this function selects all the questions / categories to be backed up.
519         quiz_insert_category_and_question_ids($course, $backup_unique_code, $instances);
520         if ($course != SITEID){
521             question_insert_site_file_names($course, $backup_unique_code);
522         }
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         }
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");
539         if ($ids = question_category_ids_by_backup ($backup_unique_code)) {
540             $info[1][1] = count($ids);
541         } else {
542             $info[1][1] = 0;
543         }
544         //Questions
545         $info[2][0] = get_string("questions","quiz");
546         if ($ids = question_ids_by_backup ($backup_unique_code)) {
547             $info[2][1] = count($ids);
548         } else {
549             $info[2][1] = 0;
550         }
552         //Now, if requested, the user_data
553         if ($user_data) {
554             //Grades
555             $info[3][0] = get_string("grades");
556             if ($ids = quiz_grade_ids_by_course ($course)) {
557                 $info[3][1] = count($ids);
558             } else {
559                 $info[3][1] = 0;
560             }
561         }
563         return $info;
564     }
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) {
570         global $CFG;
572         $base = preg_quote($CFG->wwwroot,"/");
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);
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);
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);
586         return $result;
587     }
589 // INTERNAL FUNCTIONS. BASED IN THE MOD STRUCTURE
591     //Returns an array of quiz id
592     function quiz_ids ($course) {
594         global $CFG, $DB;
596         return $DB->get_records_sql ("SELECT a.id, a.course
597                                      FROM {quiz} a
598                                      WHERE a.course = ?", array($course));
599     }
601     function quiz_grade_ids_by_course ($course) {
603         global $CFG, $DB;
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));
610     }
612     function quiz_grade_ids_by_instance($instanceid) {
614         global $CFG, $DB;
616         return $DB->get_records_sql ("SELECT g.id, g.quiz
617                                      FROM {quiz_grades} g
618                                      WHERE g.quiz = ?", array($instanceid));
619     }