Note:

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

Question formats: Difference between revisions

From MoodleDocs
 
(21 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{Question development}}
==Importing or exporting questions==
==Importing or exporting questions==
{{Questiontype developer docs}}
 
Questions coming from other Moodle courses or from other e-learning systems (i.e. Blackboard, Webct etc.) can be imported in Moodle.
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.).
Similarly, 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.
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
 
* examples:
** '''question/format/aiken/format.php'''
** '''question/format/aiken/format.php'''
** '''question/format/blackboard/format.php'''
** '''question/format/blackboard/format.php'''
Line 13: Line 16:
* '''question/export.php'''
* '''question/export.php'''


The main difficulty in coding these specific format.php files is that the developpers should be aware of
Import/Export formats are a pluggable resource and will automatically be "discovered" and made available to users simply by adding the plugin to question/format. Cross-support for optional questiontype plugins was added in 1.9 and support for language files (specifically a help file) has been implemented in Moodle 2.0.
* 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.==
=== Developing an import/export plugin ===
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.
The simplest and most comprehensive import/export type is probably the Moodle XML format. There are also a few option plugins in contrib (plugins/question/format) that you can look at. It is worth studying these file (question/format/xml/format.php) along with the parent class (question/format.php) to get an understanding of what is going on. Some other custom formats circumvent the normal rules and structure and should be studied with caution.


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.
Some things to note:
 
* Study the question/format.php file to establish which methods must be overridden.  
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.
* Each format.php file can support import, export or both indicated by the '''provide_import()''' and '''provide_export()''' methods which must be overridden to return ''true'' as required. 
 
* Do not read or write directly to the database, this is handled for you by the parent class
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 .
* when importing, question objects need to be in a format suitable for use by the questiontype->save_options() method (see question/type/questiontype.php class). The easiest way to get this information is to do a '''print_r($question);''' at the start of the '''save_options()''' method for the appropriate question type when a question is saved. The imported object must be the same format.
==The format.php code flow for import==
* when importing, always obtain 'empty' question objects from the '''defaultquestion()''' method, which sets all required properties to their default values.
When importing questions
* for exporting the populated $question object is supplied to the format class. Again, '''print_r($question)''' can be used to learn the format.
*the '''import.php''' let select the file and import format
* You should add a help file for the plugin using the structure lang/en_utf8/help/''myformat''/''myformat''.html where ''myformat'' is the name of your import/export plugin (Moodle 2.0).
** 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.
However the '''format.php''' '''do not verify''' or '''validate''' these common elements the same way that '''question/type/questiontype->save_question()'''do.
'''format.php''' let to each '''filetype/format.php''' the responsability to verify or validate these common question elements.
 
A more stable code will be to centralize the verification and validation of the question common elements to '''questiontype->save_question().'''
However the code flow of the '''questiontype->save_question()''' when creating or modifying a question by the user is not necesseraly the code flow when importing from files in '''format->save_question()''' when errors occured in one or the other process.
A '''better''' solution will be to '''separate''' the three steps of questiontype->save_question().
# verification and validation of the question common elements
# question saving in the database
# call to '''qtype/questiontype->save_question_options()'''
by creating two new functions
*'''questiontype->validate_question_common_elements()'''
*'''questiontype->save_question_common_elements()'''
With these two additional functions, '''questiontype->save_question()''' and '''format->save_question()'''  could process the saving of questions by a call to
# '''questiontype->validate_question_common_elements()'''
## '''questiontype''' or '''format''' processing of errors and notices.  
# '''questiontype->save_question_common_elements()'''
## '''questiontype''' or '''format''' processing of errors and notices.  
# '''qtype->save_question_options()'''
## '''questiontype''' or '''format''' processing of errors and notices.
and each class have the complete control for the treatment of errors or notices at the return of the three common functions.
 
====saving the question options elements====
'''format.php''' calls the specific '''qtype->save_question_options()''' function.
This 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 question of the questiontype that is currently saved,
is handled by a one call to the regular specific '''qtype/questiontype->save_question_options()'''.
This is the case for almost all actual questiontypes implemented 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 file  (ex. $QTYPES[CALCULATED] = new qformat_webct_modified_calculated_qtype();) to handle the saving of the data items elements.
This imply that for each new file format you need to create a new code or copy the qformat_webct_modified_calculated_qtype one.
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 could be done by checking if the dataitemsdefs and the associated data items are set in $question


== See also ==
== See also ==
Line 125: Line 36:
[[Category:Quiz]]
[[Category:Quiz]]
[[Category:Lesson]]
[[Category:Lesson]]
[[Category:Plugins]]

Latest revision as of 06:06, 30 January 2012

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. Similarly, 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.

  • examples:
    • 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

Import/Export formats are a pluggable resource and will automatically be "discovered" and made available to users simply by adding the plugin to question/format. Cross-support for optional questiontype plugins was added in 1.9 and support for language files (specifically a help file) has been implemented in Moodle 2.0.

Developing an import/export plugin

The simplest and most comprehensive import/export type is probably the Moodle XML format. There are also a few option plugins in contrib (plugins/question/format) that you can look at. It is worth studying these file (question/format/xml/format.php) along with the parent class (question/format.php) to get an understanding of what is going on. Some other custom formats circumvent the normal rules and structure and should be studied with caution.

Some things to note:

  • Study the question/format.php file to establish which methods must be overridden.
  • Each format.php file can support import, export or both indicated by the provide_import() and provide_export() methods which must be overridden to return true as required.
  • Do not read or write directly to the database, this is handled for you by the parent class
  • when importing, question objects need to be in a format suitable for use by the questiontype->save_options() method (see question/type/questiontype.php class). The easiest way to get this information is to do a print_r($question); at the start of the save_options() method for the appropriate question type when a question is saved. The imported object must be the same format.
  • when importing, always obtain 'empty' question objects from the defaultquestion() method, which sets all required properties to their default values.
  • for exporting the populated $question object is supplied to the format class. Again, print_r($question) can be used to learn the format.
  • You should add a help file for the plugin using the structure lang/en_utf8/help/myformat/myformat.html where myformat is the name of your import/export plugin (Moodle 2.0).

See also

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