<?PHP //$Id: backuplib.php,v 1.12 2004/08/06 23:43:19 stronk7 Exp $
    //This php script contains all the stuff to backup/restore
    //quiz mods

    //To see, put your terminal to 160cc

    //This is the "graphical" structure of the quiz mod:
    //
    //                           quiz                                                      quiz_categories
    //                        (CL,pk->id)                                                   (CL,pk->id)
    //                            |                                                              |
    //             -----------------------------------------------                               |
    //             |                        |                    |                               |.......................................
    //             |                        |                    |                               |                                      .
    //             |                        |                    |                               |                                      .
    //        quiz_attempts          quiz_grades         quiz_question_grades                    |    ----quiz_question_datasets----    .
    //   (UL,pk->id, fk->quiz)   (UL,pk->id,fk->quiz)    (CL,pk->id,fk->quiz)                    |    |  (CL,pk->id,fk->question,  |    .
    //             |                                              |                              |    |   fk->dataset_definition)  |    .             
    //             |                                              |                              |    |                            |    .
    //             |                                              |                              |    |                            |    .
    //             |                                              |                              |    |                            |    .
    //       quiz_responses                                       |                        quiz_questions                     quiz_dataset_definitions 
    //  (UL,pk->id, fk->attempt)----------------------------------------------------(CL,pk->id,fk->category,files)            (CL,pk->id,fk->category)   
    //                                                                                           |                                      |
    //                                                                                           |                                      |
    //                                                                                           |                                      |
    //                                                                                           |                               quiz_dataset_items
    //                                                                                           |                            (CL,pk->id,fk->definition) 
    //                                                                                           |                              
    //                                                                                           |                              
    //                                                                                           |                              
    //             --------------------------------------------------------------------------------------------------------------
    //             |             |              |              |                       |                  |                     |    
    //             |             |              |              |                       |                  |                     |
    //             |             |              |              |                 quiz_calculated          |                     |    quiz_randomsamatch
    //      quiz_truefalse       |       quiz_multichoice      |             (CL,pl->id,fk->question)     |                     |--(CL,pl->id,fk->question)
    // (CL,pl->id,fk->question)  |   (CL,pl->id,fk->question)  |                       .                  |                     |
    //             .             |              .              |                       .                  |                     |
    //             .      quiz_shortanswer      .       quiz_numerical                 .            quiz_multianswer.           |
    //             .  (CL,pl->id,fk->question)  .  (CL,pl->id,fk->question)            .        (CL,pl->id,fk->question)        |         quiz_match 
    //             .             .              .              .                       .                  .                     |--(CL,pl->id,fk->question)
    //             .             .              .              .                       .                  .                     |             .
    //             .             .              .              .                       .                  .                     |             .
    //             .             .              .              .                       .                  .                     |             .
    //             .             .              .              .                       .                  .                     |       quiz_match_sub
    //             .             .              .              .                       .                  .                     |--(CL,pl->id,fk->question)
    //             ........................................................................................                     |
    //                                                   .                                                                      |
    //                                                   .                                                                      |
    //                                                   .                                                                      |    quiz_numerical_units
    //                                                quiz_answers                                                              |--(CL,pl->id,fk->question)
    //                                         (CL,pk->id,fk->question)----------------------------------------------------------
    // 
    // Meaning: pk->primary key field of the table
    //          fk->foreign key to link with parent
    //          nt->nested field (recursive data)
    //          CL->course level info
    //          UL->user level info
    //          files->table may have files
    //
    //-----------------------------------------------------------

    //THIS MOD BACKUP NEEDS TO USE THE mdl_backup_ids TABLE

    //This module is special, because we make the backup in two steps:
    // 1.-We backup every category and their questions (complete structure). It includes this tables:
    //     - quiz_categories
    //     - quiz_questions
    //     - quiz_truefalse
    //     - quiz_shortanswer
    //     - quiz_multianswer
    //     - quiz_multichoice
    //     - quiz_numerical
    //     - quiz_randomsamatch
    //     - quiz_match
    //     - quiz_match_sub
    //     - quiz_calculated
    //     - quiz_answers
    //     - quiz_numerical_units
    //     - quiz_question_datasets
    //     - quiz_dataset_definitions
    //     - quiz_dataset_items
    //    All this backup info have its own section in moodle.xml (QUESTION_CATEGORIES) and it's generated
    //    before every module backup standard invocation. And only if to backup quizzes has been selected !!
    //    It's invoked with quiz_backup_question_categories. (course independent).

    // 2.-Standard module backup (Invoked via quiz_backup_mods). It includes this tables:
    //     - quiz
    //     - quiz_question_grades
    //     - quiz_attempts
    //     - quiz_grades
    //     - quiz_responses
    //    This step is the standard mod backup. (course dependent).

    //STEP 1. Backup categories/questions and associated structures
    //    (course independent)
    function quiz_backup_question_categories($bf,$preferences) {

        global $CFG;

        $status = true;

        //First, we get the used categories from backup_ids
        $categories = quiz_category_ids_by_backup ($preferences->backup_unique_code);
      
        //If we've categories
        if ($categories) {
             //Write start tag
             $status = fwrite($bf,start_tag("QUESTION_CATEGORIES",2,true));
             //Iterate over each category
            foreach ($categories as $cat) {
                //Start category
                $status =fwrite ($bf,start_tag("QUESTION_CATEGORY",3,true));
                //Get category data from quiz_categories
                $category = get_record ("quiz_categories","id",$cat->old_id);
                //Print category contents
                fwrite($bf,full_tag("ID",4,false,$category->id));
                fwrite($bf,full_tag("NAME",4,false,$category->name));
                fwrite($bf,full_tag("INFO",4,false,$category->info));
                fwrite($bf,full_tag("PUBLISH",4,false,$category->publish));
                fwrite($bf,full_tag("STAMP",4,false,$category->stamp));
                //Now, backup their questions
                $status = quiz_backup_question($bf,$preferences,$category->id);
                //End category
                $status =fwrite ($bf,end_tag("QUESTION_CATEGORY",3,true));
            }
            //Write end tag    
            $status =fwrite ($bf,end_tag("QUESTION_CATEGORIES",2,true));
        }

        return $status;
    }
    
    //This function backups all the questions in selected category and their
    //asociated data 
    function quiz_backup_question($bf,$preferences,$category) {

        global $CFG;

        $status = true;

        $questions = get_records("quiz_questions","category",$category,"id");
        //If there is questions
        if ($questions) {
            //Write start tag
            $status =fwrite ($bf,start_tag("QUESTIONS",4,true));
            $counter = 0;
            //Iterate over each question
            foreach ($questions as $question) {
                //Start question
                $status =fwrite ($bf,start_tag("QUESTION",5,true));
                //Print question contents
                fwrite ($bf,full_tag("ID",6,false,$question->id));
                fwrite ($bf,full_tag("NAME",6,false,$question->name));
                fwrite ($bf,full_tag("QUESTIONTEXT",6,false,$question->questiontext));
                fwrite ($bf,full_tag("QUESTIONTEXTFORMAT",6,false,$question->questiontextformat));
                fwrite ($bf,full_tag("IMAGE",6,false,$question->image));
                fwrite ($bf,full_tag("DEFAULTGRADE",6,false,$question->defaultgrade));
                fwrite ($bf,full_tag("QTYPE",6,false,$question->qtype));
                fwrite ($bf,full_tag("STAMP",6,false,$question->stamp));
                fwrite ($bf,full_tag("VERSION",6,false,$question->version));
                //Now, depending of the qtype, call one function or other
                if ($question->qtype == "1") {
                    $status = quiz_backup_shortanswer($bf,$preferences,$question->id);
                } else if ($question->qtype == "2") {
                    $status = quiz_backup_truefalse($bf,$preferences,$question->id);
                } else if ($question->qtype == "3") {
                    $status = quiz_backup_multichoice($bf,$preferences,$question->id);
                } else if ($question->qtype == "4") {
                    //Random question. Nothing to write.
                } else if ($question->qtype == "5") {
                    $status = quiz_backup_match($bf,$preferences,$question->id);
                } else if ($question->qtype == "6") {
                    $status = quiz_backup_randomsamatch($bf,$preferences,$question->id);
                } else if ($question->qtype == "7") {
                    //Description question. Nothing to write.
                } else if ($question->qtype == "8") {
                    $status = quiz_backup_numerical($bf,$preferences,$question->id);
                } else if ($question->qtype == "9") {
                    $status = quiz_backup_multianswer($bf,$preferences,$question->id);
                } else if ($question->qtype == "10") {
                    $status = quiz_backup_calculated($bf,$preferences,$question->id);
                }
                //End question
                $status =fwrite ($bf,end_tag("QUESTION",5,true));
                //Do some output
                $counter++;
                if ($counter % 10 == 0) {
                    echo ".";            
                    if ($counter % 200 == 0) {
                        echo "<br>";
                    }
                    backup_flush(300);
                }
            }
            //Write end tag
            $status =fwrite ($bf,end_tag("QUESTIONS",4,true));
        }
        return $status;
    }

    //This function backups the data in a truefalse question (qtype=2) and its
    //asociated data
    function quiz_backup_truefalse($bf,$preferences,$question) {

        global $CFG;

        $status = true;

        $truefalses = get_records("quiz_truefalse","question",$question,"id");
        //If there are truefalses
        if ($truefalses) {
            //Iterate over each truefalse
            foreach ($truefalses as $truefalse) {
                $status =fwrite ($bf,start_tag("TRUEFALSE",6,true));
                //Print truefalse contents
                fwrite ($bf,full_tag("TRUEANSWER",7,false,$truefalse->trueanswer));
                fwrite ($bf,full_tag("FALSEANSWER",7,false,$truefalse->falseanswer));
                $status =fwrite ($bf,end_tag("TRUEFALSE",6,true));
            }
            //Now print quiz_answers
            $status = quiz_backup_answers($bf,$preferences,$question);
        }
        return $status;
    }

    //This function backups the data in a shortanswer question (qtype=1) and its
    //asociated data
    function quiz_backup_shortanswer($bf,$preferences,$question,$level=6,$include_answers=true) {

        global $CFG;

        $status = true;

        $shortanswers = get_records("quiz_shortanswer","question",$question,"id");
        //If there are shortanswers
        if ($shortanswers) {
            //Iterate over each shortanswer
            foreach ($shortanswers as $shortanswer) {
                $status =fwrite ($bf,start_tag("SHORTANSWER",$level,true));
                //Print shortanswer contents
                fwrite ($bf,full_tag("ANSWERS",$level+1,false,$shortanswer->answers));
                fwrite ($bf,full_tag("USECASE",$level+1,false,$shortanswer->usecase));
                $status =fwrite ($bf,end_tag("SHORTANSWER",$level,true));
            }
            //Now print quiz_answers
            if ($include_answers) {
                $status = quiz_backup_answers($bf,$preferences,$question);
            }
        }
        return $status;
    } 

    //This function backups the data in a multichoice question (qtype=3) and its
    //asociated data
    function quiz_backup_multichoice($bf,$preferences,$question,$level=6,$include_answers=true) {

        global $CFG;

        $status = true;

        $multichoices = get_records("quiz_multichoice","question",$question,"id");
        //If there are multichoices
        if ($multichoices) {
            //Iterate over each multichoice
            foreach ($multichoices as $multichoice) {
                $status =fwrite ($bf,start_tag("MULTICHOICE",$level,true));
                //Print multichoice contents
                fwrite ($bf,full_tag("LAYOUT",$level+1,false,$multichoice->layout));
                fwrite ($bf,full_tag("ANSWERS",$level+1,false,$multichoice->answers));
                fwrite ($bf,full_tag("SINGLE",$level+1,false,$multichoice->single));
                $status =fwrite ($bf,end_tag("MULTICHOICE",$level,true));
            }
            //Now print quiz_answers
            if ($include_answers) {
                $status = quiz_backup_answers($bf,$preferences,$question);
            }
        }
        return $status;
    }

    //This function backups the data in a randomsamatch question (qtype=6) and its
    //asociated data
    function quiz_backup_randomsamatch($bf,$preferences,$question) {

        global $CFG;

        $status = true;

        $randomsamatchs = get_records("quiz_randomsamatch","question",$question,"id");
        //If there are randomsamatchs
        if ($randomsamatchs) {
            //Iterate over each randomsamatch
            foreach ($randomsamatchs as $randomsamatch) {
                $status =fwrite ($bf,start_tag("RANDOMSAMATCH",6,true));
                //Print randomsamatch contents
                fwrite ($bf,full_tag("CHOOSE",7,false,$randomsamatch->choose));
                $status =fwrite ($bf,end_tag("RANDOMSAMATCH",6,true));
            }
        }
        return $status;
    }

    //This function backups the data in a match question (qtype=5) and its
    //asociated data
    function quiz_backup_match($bf,$preferences,$question) {

        global $CFG;

        $status = true;

        $matchs = get_records("quiz_match_sub","question",$question,"id");
        //If there are matchs
        if ($matchs) {
            $status =fwrite ($bf,start_tag("MATCHS",6,true));
            //Iterate over each match
            foreach ($matchs as $match) {
                $status =fwrite ($bf,start_tag("MATCH",7,true));
                //Print match contents
                fwrite ($bf,full_tag("ID",8,false,$match->id));
                fwrite ($bf,full_tag("QUESTIONTEXT",8,false,$match->questiontext));
                fwrite ($bf,full_tag("ANSWERTEXT",8,false,$match->answertext));
                $status =fwrite ($bf,end_tag("MATCH",7,true));
            }
            $status =fwrite ($bf,end_tag("MATCHS",6,true));
        }
        return $status;
    }

    //This function backups the data in a numerical question (qtype=8) and its
    //asociated data
    function quiz_backup_numerical($bf,$preferences,$question,$level=6,$include_answers=true) {

        global $CFG;

        $status = true;

        $numericals = get_records("quiz_numerical","question",$question,"id");
        //If there are numericals
        if ($numericals) {
            //Iterate over each numerical
            foreach ($numericals as $numerical) {
                $status =fwrite ($bf,start_tag("NUMERICAL",$level,true));
                //Print numerical contents
                fwrite ($bf,full_tag("ANSWER",$level+1,false,$numerical->answer));
                fwrite ($bf,full_tag("MIN",$level+1,false,$numerical->min));
                fwrite ($bf,full_tag("MAX",$level+1,false,$numerical->max));
                //Now backup numerical_units
                $status = quiz_backup_numerical_units($bf,$preferences,$question,7);
                $status =fwrite ($bf,end_tag("NUMERICAL",$level,true));
            }
            //Now print quiz_answers
            if ($include_answers) {
                $status = quiz_backup_answers($bf,$preferences,$question);
            }
        }
        return $status;
    }

    //This function backups the data in a multianswer question (qtype=9) and its      
    //asociated data
    function quiz_backup_multianswer($bf,$preferences,$question) {

        global $CFG;

        $status = true;

        $multianswers = get_records("quiz_multianswers","question",$question,"id");
        //If there are multianswers
        if ($multianswers) {
            //Print multianswers header
            $status =fwrite ($bf,start_tag("MULTIANSWERS",6,true));
            //Iterate over each multianswer
            foreach ($multianswers as $multianswer) {
                $status =fwrite ($bf,start_tag("MULTIANSWER",7,true));
                //Print multianswer contents
                fwrite ($bf,full_tag("ID",8,false,$multianswer->id));
                fwrite ($bf,full_tag("ANSWERS",8,false,$multianswer->answers));
                fwrite ($bf,full_tag("POSITIONKEY",8,false,$multianswer->positionkey));
                fwrite ($bf,full_tag("ANSWERTYPE",8,false,$multianswer->answertype));
                fwrite ($bf,full_tag("NORM",8,false,$multianswer->norm));
                //Depending of the ANSWERTYPE, we must encode different info
                //to be able to re-create records in quiz_shortanswer, quiz_multichoice and
                //quiz_numerical
                if ($multianswer->answertype == "1") {
                    $status = quiz_backup_shortanswer($bf,$preferences,$question,8,false);
                } else if ($multianswer->answertype == "3") {
                    $status = quiz_backup_multichoice($bf,$preferences,$question,8,false);
                } else if ($multianswer->answertype == "8") {
                    $status = quiz_backup_numerical($bf,$preferences,$question,8,false);
                }

                $status =fwrite ($bf,end_tag("MULTIANSWER",7,true));
            }
            //Print multianswers footer
            $status =fwrite ($bf,end_tag("MULTIANSWERS",6,true));
            //Now print quiz_answers
            $status = quiz_backup_answers($bf,$preferences,$question);
        }
        return $status;
    }

    //This function backups the data in a calculated question (qtype=10) and its
    //asociated data
    function quiz_backup_calculated($bf,$preferences,$question,$level=6,$include_answers=true) {

        global $CFG;

        $status = true;

        $calculateds = get_records("quiz_calculated","question",$question,"id");
        //If there are calculated-s
        if ($calculateds) {
            //Iterate over each calculateds
            foreach ($calculateds as $calculated) {
                $status =fwrite ($bf,start_tag("CALCULATED",$level,true));
                //Print calculated contents
                fwrite ($bf,full_tag("ANSWER",$level+1,false,$calculated->answer));
                fwrite ($bf,full_tag("TOLERANCE",$level+1,false,$calculated->tolerance));
                fwrite ($bf,full_tag("TOLERANCETYPE",$level+1,false,$calculated->tolerancetype));
                fwrite ($bf,full_tag("CORRECTANSWERLENGTH",$level+1,false,$calculated->correctanswerlength));
                //Now backup numerical_units
                $status = quiz_backup_numerical_units($bf,$preferences,$question,7);
                //Now backup required dataset definitions and items...
                $status = quiz_backup_datasets($bf,$preferences,$question,7);
                //End calculated data
                $status =fwrite ($bf,end_tag("CALCULATED",$level,true));
            }
            //Now print quiz_answers
            if ($include_answers) {
                $status = quiz_backup_answers($bf,$preferences,$question);
            }
        }
        return $status;
    }

    //This function backups the answers data in some question types
    //(truefalse, shortanswer,multichoice,numerical,calculated)
    function quiz_backup_answers($bf,$preferences,$question) {

        global $CFG;

        $status = true;

        $answers = get_records("quiz_answers","question",$question,"id");
        //If there are answers
        if ($answers) {
            $status =fwrite ($bf,start_tag("ANSWERS",6,true));
            //Iterate over each answer
            foreach ($answers as $answer) {
                $status =fwrite ($bf,start_tag("ANSWER",7,true));
                //Print answer contents
                fwrite ($bf,full_tag("ID",8,false,$answer->id));
                fwrite ($bf,full_tag("ANSWER_TEXT",8,false,$answer->answer));
                fwrite ($bf,full_tag("FRACTION",8,false,$answer->fraction));
                fwrite ($bf,full_tag("FEEDBACK",8,false,$answer->feedback));
                $status =fwrite ($bf,end_tag("ANSWER",7,true));
            }
            $status =fwrite ($bf,end_tag("ANSWERS",6,true));
        }
        return $status;
    }

    //This function backups quiz_numerical_units from different question types
    function quiz_backup_numerical_units($bf,$preferences,$question,$level=7) {

        global $CFG;

        $status = true;

        $numerical_units = get_records("quiz_numerical_units","question",$question,"id");
        //If there are numericals_units
        if ($numerical_units) {
            $status =fwrite ($bf,start_tag("NUMERICAL_UNITS",$level,true));
            //Iterate over each numerical_unit
            foreach ($numerical_units as $numerical_unit) {
                $status =fwrite ($bf,start_tag("NUMERICAL_UNIT",$level+1,true));
                //Print numerical_unit contents
                fwrite ($bf,full_tag("MULTIPLIER",$level+2,false,$numerical_unit->multiplier));
                fwrite ($bf,full_tag("UNIT",$level+2,false,$numerical_unit->unit));
                //Now backup numerical_units
                $status =fwrite ($bf,end_tag("NUMERICAL_UNIT",$level+1,true));
            }
            $status =fwrite ($bf,end_tag("NUMERICAL_UNITS",$level,true));
        }

        return $status;

    }

    //This function backups dataset_definitions (via question_datasets) from different question types
    function quiz_backup_datasets($bf,$preferences,$question,$level=7) {

        global $CFG;

        $status = true;

        //First, we get the used datasets for this question
        $question_datasets = get_records("quiz_question_datasets","question",$question,"id");
        //If there are question_datasets
        if ($question_datasets) {
            $status =fwrite ($bf,start_tag("DATASET_DEFINITIONS",$level,true));
            //Iterate over each question_dataset
            foreach ($question_datasets as $question_dataset) {
                $def = NULL;
                //Get dataset_definition
                if ($def = get_record("quiz_dataset_definitions","id",$question_dataset->datasetdefinition)) {;
                    $status =fwrite ($bf,start_tag("DATASET_DEFINITION",$level+1,true));
                    //Print question_dataset contents
                    fwrite ($bf,full_tag("CATEGORY",$level+2,false,$def->category));
                    fwrite ($bf,full_tag("NAME",$level+2,false,$def->name));
                    fwrite ($bf,full_tag("TYPE",$level+2,false,$def->type));
                    fwrite ($bf,full_tag("OPTIONS",$level+2,false,$def->options));
                    fwrite ($bf,full_tag("ITEMCOUNT",$level+2,false,$def->itemcount));
                    //Now backup dataset_entries
                    $status = quiz_backup_dataset_items($bf,$preferences,$def->id,$level+2);
                    //End dataset definition
                    $status =fwrite ($bf,end_tag("DATASET_DEFINITION",$level+1,true));
                }
            }
            $status =fwrite ($bf,end_tag("DATASET_DEFINITIONS",$level,true));
        }

        return $status;

    }

    //This function backups datases_items from dataset_definitions
    function quiz_backup_dataset_items($bf,$preferences,$datasetdefinition,$level=9) {

        global $CFG;

        $status = true;

        //First, we get the datasets_items for this dataset_definition
        $dataset_items = get_records("quiz_dataset_items","definition",$datasetdefinition,"id");
        //If there are dataset_items
        if ($dataset_items) {
            $status =fwrite ($bf,start_tag("DATASET_ITEMS",$level,true));
            //Iterate over each dataset_item
            foreach ($dataset_items as $dataset_item) {
                $status =fwrite ($bf,start_tag("DATASET_ITEM",$level+1,true));
                //Print question_dataset contents
                fwrite ($bf,full_tag("NUMBER",$level+2,false,$dataset_item->number));
                fwrite ($bf,full_tag("VALUE",$level+2,false,$dataset_item->value));
                //End dataset definition
                $status =fwrite ($bf,end_tag("DATASET_ITEM",$level+1,true));
            }
            $status =fwrite ($bf,end_tag("DATASET_ITEMS",$level,true));
        }

        return $status;

    }

    //STEP 2. Backup quizzes and associated structures
    //    (course dependent)
    function quiz_backup_mods($bf,$preferences) {

        global $CFG;

        $status = true;

        //Iterate over quiz table
        $quizzes = get_records ("quiz","course",$preferences->backup_course,"id");
        if ($quizzes) {
            foreach ($quizzes as $quiz) {
                //Start mod
                fwrite ($bf,start_tag("MOD",3,true));
                //Print quiz data
                fwrite ($bf,full_tag("ID",4,false,$quiz->id));
                fwrite ($bf,full_tag("MODTYPE",4,false,"quiz"));
                fwrite ($bf,full_tag("NAME",4,false,$quiz->name));
                fwrite ($bf,full_tag("INTRO",4,false,$quiz->intro));
                fwrite ($bf,full_tag("TIMEOPEN",4,false,$quiz->timeopen));
                fwrite ($bf,full_tag("TIMECLOSE",4,false,$quiz->timeclose));
                fwrite ($bf,full_tag("ATTEMPTS_NUMBER",4,false,$quiz->attempts));
                fwrite ($bf,full_tag("ATTEMPTONLAST",4,false,$quiz->attemptonlast));
                fwrite ($bf,full_tag("FEEDBACK",4,false,$quiz->feedback));
                fwrite ($bf,full_tag("CORRECTANSWERS",4,false,$quiz->correctanswers));
                fwrite ($bf,full_tag("GRADEMETHOD",4,false,$quiz->grademethod));
                fwrite ($bf,full_tag("REVIEW",4,false,$quiz->review));
                fwrite ($bf,full_tag("SHUFFLEQUESTIONS",4,false,$quiz->shufflequestions));
                fwrite ($bf,full_tag("SHUFFLEANSWERS",4,false,$quiz->shuffleanswers));
                fwrite ($bf,full_tag("QUESTIONS",4,false,$quiz->questions));
                fwrite ($bf,full_tag("SUMGRADES",4,false,$quiz->sumgrades));
                fwrite ($bf,full_tag("GRADE",4,false,$quiz->grade));
                fwrite ($bf,full_tag("TIMECREATED",4,false,$quiz->timecreated));
                fwrite ($bf,full_tag("TIMEMODIFIED",4,false,$quiz->timemodified));
                fwrite ($bf,full_tag("TIMELIMIT",4,false,$quiz->timelimit));
                fwrite ($bf,full_tag("PASSWORD",4,false,$quiz->password));
                fwrite ($bf,full_tag("SUBNET",4,false,$quiz->subnet));
                //Now we print to xml question_grades (Course Level)
                $status = backup_quiz_question_grades($bf,$preferences,$quiz->id);
                //if we've selected to backup users info, then execute:
                //    - backup_quiz_grades
                //    - backup_quiz_attempts
                if ($preferences->mods["quiz"]->userinfo and $status) {
                    $status = backup_quiz_grades($bf,$preferences,$quiz->id);
                    if ($status) {
                        $status = backup_quiz_attempts($bf,$preferences,$quiz->id);
                    }
                }
                //End mod
                $status =fwrite ($bf,end_tag("MOD",3,true));
            }
        }
        return $status;
    }

    //Backup quiz_question_grades contents (executed from quiz_backup_mods)
    function backup_quiz_question_grades ($bf,$preferences,$quiz) {

        global $CFG;

        $status = true;

        $quiz_question_grades = get_records("quiz_question_grades","quiz",$quiz,"id");
        //If there are question_grades
        if ($quiz_question_grades) {
            //Write start tag
            $status =fwrite ($bf,start_tag("QUESTION_GRADES",4,true));
            //Iterate over each question_grade
            foreach ($quiz_question_grades as $que_gra) {
                //Start question grade
                $status =fwrite ($bf,start_tag("QUESTION_GRADE",5,true));
                //Print question_grade contents
                fwrite ($bf,full_tag("ID",6,false,$que_gra->id));
                fwrite ($bf,full_tag("QUESTION",6,false,$que_gra->question));
                fwrite ($bf,full_tag("GRADE",6,false,$que_gra->grade));
                //End question grade
                $status =fwrite ($bf,end_tag("QUESTION_GRADE",5,true));
            }
            //Write end tag
            $status =fwrite ($bf,end_tag("QUESTION_GRADES",4,true));
        }
        return $status;
    }

    //Backup quiz_grades contents (executed from quiz_backup_mods)
    function backup_quiz_grades ($bf,$preferences,$quiz) {

        global $CFG;

        $status = true;

        $quiz_grades = get_records("quiz_grades","quiz",$quiz,"id");
        //If there are grades
        if ($quiz_grades) {
            //Write start tag
            $status =fwrite ($bf,start_tag("GRADES",4,true));
            //Iterate over each grade
            foreach ($quiz_grades as $gra) {
                //Start grade
                $status =fwrite ($bf,start_tag("GRADE",5,true));
                //Print grade contents
                fwrite ($bf,full_tag("ID",6,false,$gra->id));
                fwrite ($bf,full_tag("USERID",6,false,$gra->userid));
                fwrite ($bf,full_tag("GRADEVAL",6,false,$gra->grade));
                fwrite ($bf,full_tag("TIMEMODIFIED",6,false,$gra->timemodified));
                //End question grade
                $status =fwrite ($bf,end_tag("GRADE",5,true));
            }
            //Write end tag
            $status =fwrite ($bf,end_tag("GRADES",4,true));
        }
        return $status;
    }

    //Backup quiz_attempts contents (executed from quiz_backup_mods)
    function backup_quiz_attempts ($bf,$preferences,$quiz) {

        global $CFG;

        $status = true;

        $quiz_attempts = get_records("quiz_attempts","quiz",$quiz,"id");
        //If there are attempts
        if ($quiz_attempts) {
            //Write start tag
            $status =fwrite ($bf,start_tag("ATTEMPTS",4,true));
            //Iterate over each attempt
            foreach ($quiz_attempts as $attempt) {
                //Start attempt
                $status =fwrite ($bf,start_tag("ATTEMPT",5,true));
                //Print attempt contents
                fwrite ($bf,full_tag("ID",6,false,$attempt->id));
                fwrite ($bf,full_tag("USERID",6,false,$attempt->userid));
                fwrite ($bf,full_tag("ATTEMPTNUM",6,false,$attempt->attempt));
                fwrite ($bf,full_tag("SUMGRADES",6,false,$attempt->sumgrades));
                fwrite ($bf,full_tag("TIMESTART",6,false,$attempt->timestart));
                fwrite ($bf,full_tag("TIMEFINISH",6,false,$attempt->timefinish));
                fwrite ($bf,full_tag("TIMEMODIFIED",6,false,$attempt->timemodified));
                //Now write to xml the responses (in this attempt)
                $status = backup_quiz_responses ($bf,$preferences,$attempt->id);
                //End attempt
                $status =fwrite ($bf,end_tag("ATTEMPT",5,true));
            }
            //Write end tag
            $status =fwrite ($bf,end_tag("ATTEMPTS",4,true));
        }
        return $status;
    }

    //Backup quiz_responses contents (executed from backup_quiz_attempts)
    function backup_quiz_responses ($bf,$preferences,$attempt) {

        global $CFG;

        $status = true;

        $quiz_responses = get_records("quiz_responses","attempt",$attempt,"id");
        //If there are responses
        if ($quiz_responses) {
            //Write start tag
            $status =fwrite ($bf,start_tag("RESPONSES",6,true));
            //Iterate over each response
            foreach ($quiz_responses as $response) {
                //Start response
                $status =fwrite ($bf,start_tag("RESPONSE",7,true));
                //Print response contents
                fwrite ($bf,full_tag("ID",8,false,$response->id));
                fwrite ($bf,full_tag("QUESTION",8,false,$response->question));
                fwrite ($bf,full_tag("ANSWER",8,false,$response->answer));
                fwrite ($bf,full_tag("GRADE",8,false,$response->grade));
                //End response
                $status =fwrite ($bf,end_tag("RESPONSE",7,true));
            }
            //Write end tag
            $status =fwrite ($bf,end_tag("RESPONSES",6,true));
        }
        return $status;
    }






   ////Return an array of info (name,value)
   function quiz_check_backup_mods($course,$user_data=false,$backup_unique_code) {
        //Deletes data from mdl_backup_ids (categories section)
        delete_category_ids ($backup_unique_code);
        //Create date into mdl_backup_ids (categories section)
        insert_category_ids ($course,$backup_unique_code);
        //First the course data
        $info[0][0] = get_string("modulenameplural","quiz");
        if ($ids = quiz_ids ($course)) {
            $info[0][1] = count($ids);
        } else {
            $info[0][1] = 0;
        }
        //Categories
        $info[1][0] = get_string("categories","quiz");
        if ($ids = quiz_category_ids_by_backup ($backup_unique_code)) {
            $info[1][1] = count($ids);
        } else {
            $info[1][1] = 0;
        }
        //Questions
        $info[2][0] = get_string("questions","quiz");
        if ($ids = quiz_question_ids_by_backup ($backup_unique_code)) {
            $info[2][1] = count($ids);
        } else {
            $info[2][1] = 0;
        }

        //Now, if requested, the user_data
        if ($user_data) {
            //Grades 
            $info[3][0] = get_string("grades"); 
            if ($ids = quiz_grade_ids_by_course ($course)) { 
                $info[3][1] = count($ids);
            } else {
                $info[3][1] = 0;
            }
        }

        return $info;
    }






    // INTERNAL FUNCTIONS. BASED IN THE MOD STRUCTURE

    //Returns an array of quiz id
    function quiz_ids ($course) {

        global $CFG;

        return get_records_sql ("SELECT a.id, a.course
                                 FROM {$CFG->prefix}quiz a
                                 WHERE a.course = '$course'");
    }

    //Returns an array of categories id
    function quiz_category_ids_by_backup ($backup_unique_code) {

        global $CFG;

        return get_records_sql ("SELECT a.old_id, a.backup_code
                                 FROM {$CFG->prefix}backup_ids a
                                 WHERE a.backup_code = '$backup_unique_code' AND
                                       a.table_name = 'quiz_categories'");
    }

    function quiz_question_ids_by_backup ($backup_unique_code) {

        global $CFG;

        return get_records_sql ("SELECT q.id, q.category
                                 FROM {$CFG->prefix}backup_ids a,
                                      {$CFG->prefix}quiz_questions q
                                 WHERE a.backup_code = '$backup_unique_code' AND
                                       q.category = a.old_id AND 
                                       a.table_name = 'quiz_categories'");
    }

    function quiz_grade_ids_by_course ($course) {

        global $CFG;

        return get_records_sql ("SELECT g.id, g.quiz 
                                 FROM {$CFG->prefix}quiz a,
                                      {$CFG->prefix}quiz_grades g
                                 WHERE a.course = '$course' and
                                       g.quiz = a.id");
    }

?>
