Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Importing or exporting questions

Questions coming from other Moodle courses or from other e-learning systems (i.e. Blackboard, Webct etc.) can be imported in Moodle. Similarlay Moodle offers a process to export questions to other systems in different format ( XML, QTI etc.). The import and export code is mostly written in format.php files located in a directory specific to the type of format files from which the import or export is done.

  • typically
    • question/format/aiken/format.php
    • question/format/blackboard/format.php
    • question/format/qti2/format.php
    • question/format/xml/format.php

there is a default class qformat_default defined in question/format.php and the process is controlled by

  • question/import.php
  • question/export.php

The main difficulty in coding these specific format.php files is that the developpers should be aware of

  • the coding format of the import or export files (XML, QTI etc.)
  • the parameters needed for the various question types already installed of Moodle and the new types that could easily be introduced in the near future due to the reworking of the question Moodle code By Gustav Delius and his group.

Where to find the information to code for import/export format.php files.

As we are developping new questiontypes or new import functions from external files, we need to safeguard the default_questiontype->save_question() from importing bad question data. We must well document these question parameters and get stronger validation before saving a new question.

The most exhaustive developper documentations rely on the knowledge of the database tables, the tags definition and a good comprehension of the few comments inserted in the code.

Efforts have been made to document the database (i.e. Gustav Delius has work a lot on the question part) but as usual solving the bugs and developping new features took most of the energy.

For the description of the different question parameters you should look at the developper docs Quiz database structure and the quiz_questions table that have been renamed question when the question code has been replaced as independent from the quiz in moodle 1.6.

These docs illustrate well the difficulty to maintain an up-to-date, I had to correct it (at least I try...) for the modifications done by Gustav himself in the database .

The format.php code flow for import

When importing questions

  • the import.php let select the file and import format
    • pass the control to format.php and format/$format/format.php
$format being the selected file format ( Blackboard, XML etc.)
       require("format.php");  // Parent class
       require("format/$format/format.php");
       $classname = "qformat_$format";
       $qformat = new $classname();
       if (! $qformat->importpreprocess($category,$course)) {  // Do anything before that we need to
           error( $txt->importerror ,
                     "$CFG->wwwroot/question/import.php?courseid={$course->id}&category=$category->id");
       }
       if (! $qformat->importprocess($importfile, $params->matchgrades) ) {  // Process the uploaded file
           error( $txt->importerror ,
                 "$CFG->wwwroot/question/import.php?courseid={$course->id}&category=$category->id");
       }
       if (! $qformat->importpostprocess()) {                  // In case anything needs to be done after
  • format.php call format/$format/format.php (i.e. the the specific format.php)
to read the imput file and return the questions (if any) that are in the imported files
        if (! $questions = $this->readquestions($lines)) {   // Extract all the questions
           notify( get_string('noquestionsinfile','quiz') );
           return false;
       }
       notify( get_string('importingquestions','quiz',count($questions)) );
  • get list of valid answer grades
        $grades = get_grade_options();
       $gradeoptionsfull = $grades->gradeoptionsfull;
  • Process some data and store each question
  • check for answer grades validity (must match fixed list of grades)
  • store question general parameters DIRECTLY in the dadabase
           $question->category = $this->category->id;
           $question->stamp = make_unique_id_code();  // Set the unique code (not to be changed)
           if (!$question->id = insert_record("question", $question)) {
               error( get_string('cannotinsert','quiz') );
           }
           $this->questionids[] = $question->id;
  • save the options using the qtype->save_question_options() function
$QTYPES being the different questiontypes (shortanwer,truefalse etc.)
           global $QTYPES;
           $result = $QTYPES[$question->qtype]
                   ->save_question_options($question);
  • diplay errors or notices
           if (!empty($result->error)) {
               notify($result->error);
               return false;
           }
           if (!empty($result->notice)) {
               notify($result->notice);
               return true;
           }
  • if noerrors and no notices
Give the question a unique version stamp determined by question_hash()
           set_field('question', 'version', question_hash($question), 'id', $question->id);

Cloning the default_questiontype->save_question() implications

saving the question common elements

the format.php clone in a certain way the default_questiontype->save_question()

by saving the question common elements

saving the question options elements

format.php calls the specific qtype->save_question_options() function 

which is the regular way to save these options that were retrieved from the imported file. This should be the correct way to implement a stable code and it will work correctly if ALL the necessary data supplementary to have a valid questiontype which is currently saved, is handled by a one call to qtype->save_question_options(). This is the case for almost all actual questiontypes implement in Moodle, one of the exceptions being calculated questiontype. The solution found in older Moodle version was to create a special save_question_options() in the extended filetype_format.php class to handle the saving of the data items elements. A better solution would be to modify the calculated/questiontype.php->save_question_options() function so that it could save all the data ( options and data items).

This code be done by checking if the dataitemsdefs and the associated data items are set in $question

See also

Lesson question types - both Lesson and Quiz can import the basic Moodle question types.