Question type plugin how to
This page refers to Moodle 1.9. It is not useful any more. See Question types for up-to-date documentation.
To follow this guide, you need to get hold of the New question type template. You can get it by checking out the contrib/question/type/TEMPLATE directory from the CVS repository or from the modules and plugins database. The rest of this guide is just a copy of the README.txt file from in there. (Or is the readme file a copy of this page?)
New question type template README file
Welcome to the new question type template.
This blank skeleton is a good place to start if you want to implement your own Moodle question type plugin.
Another good way to start is by looking at an existing question type that has good documentation in the code like TODO (if there is one, otherwise we'll hope that Tims will "light the way" :-) )
The latest version of the template can be found in CVS in http://moodle.cvs.sourceforge.net/moodle/contrib/plugins/question/type/TEMPLATE/. Because you want your own copy do a cvs export, not a cvs checkout. The package can also been downloaded from the Modules and plugins database.
The latest version of this help can be read (nicely formatted) at http://docs.moodle.org/en/How_to_write_a_question_type_plugin
WARNING, THIS TEMPLATE IS NOT COMPLETE YET!
Before you get to the interesting bit, you need to do a bit of file-renaming and search-and-replacing to turn this generic template into your own question type. You need to have chosen two things
- The identifier for your question type
- This is a string of lowercase letters and perhaps underscores that the Moodle code uses to refer to your question type. This needs to be unique, so perhaps start it with your initials. For example, all the questions types I create while working at the OU will be referred to as ou_something. For the rest of these instructions, I will assume you have chosen ‘myqtypeidentifier’.
- The name of your question type
- This is the name that people will see in the Moodle User-interface (in the English translation). For these instructions I will assume you have chosen ‘My Question Type Name’.
Then you need to
- Change all the places TEMPLATE appears in file names to myqtypeidentifier. That is:
- rename the top level TEMPLATE directory to myqtypeidentifier.
- rename the language file lang/en_utf8/qtype_TEMPLATE.php to lang/en_utf8/qtype_myqtypeidentifier.php
- rename the help file lang/en_utf8/help/TEMPLATE/TEMPLATE.html to lang/en_utf8/help/myqtypeidentifier/myqtypeidentifier.html
- rename the editing form edit_TEMPLATE_form.php to edit_myqtypeidentifier_form.php.
- Search and replace 'QTYPEID' with ‘myqtypeidentifier'’ in all the files. You should find:
- 2 occurrences in the language file (should now be lang/en_utf8/qtype_myqtypeidentifier.php after renaming)
- 1 occurrence in db/install.xml
- 4 occurrences in simpletest/testquestiontype.php
- 2 occurrences in edit_myqtypeidentifier_form.php
- 4 occurrences in questiontype.php
- Search and replace 'QTYPENAME' with ‘My Question Type Name’ in all the files. You should find:
- 1 occurrence in the help file (should now be lang/en_utf8/help/myqtypeidentifier/myqtypeidentifier.html after renaming)
- 3 occurrences in the language file (should now be lang/en_utf8/qtype_myqtypeidentifier.php after renaming)
- 1 occurrence in edit_myqtypeidentifier_form.php
- 2 occurrences in questiontype.php
- Search and replace YOURNAME with your name. (This is only in the comments at the top of each file so it is not critical, but surely you want to take credit for your work.) You should find one occurrence in:
- Search and replace YOUREMAILADDRESS with your email address. (Again, this is only in the file header comments, but it is helpful if people can contact you if they have any questions about your code.)
- There should be one occurrence of YOUREMAILADDRESS in each of the files listed under YOURNAME.
- Search and replace YOURPACKAGENAME with a package name for your code. This is used by PHPdocumentor when building the documentation for your classes. I suggest you make up one package name for all the question types you write. For example all the question types I write are in the package ou_questiontypes.
- There should be one occurrence of YOURPACKAGENAME in each of the files listed under YOURNAME.
- Edit icon.gif to make an icon that represents your question type.
- Move your new question type folder in the question/type folder of your Moodle development codebase, so you can test the code as you work on it.
Now for the interesting bit
Now you need to write the code to
- Describe any database tables you need in db/install.xml. If you don't need to create any database tables, you can delete the db directory.
- Edit edit_myqtypeidentifier_form.php to create the question editing form.
- Create the template that will display the question to the student. This is in display.html. To make good flexible formatting you should use CSS classes and use already existing ones when possible. An easy way to find which CSS classes exist is TODO.
- Implement the rest of the question type class. This is in questiontype.php. You need to consider
- Storing, retrieving, and deleting additional question options from the database when editing the question instance
- Storing, retrieving, and deleting additional question options and the session when the question is used in a quiz
- Displaying the question to the student
- Dealing with responses: grading responses, providing the correct responses, etc.
- Backing up and restoring a question instance.
- Importing and exporting a question instance.
- Make sure that the language file contains all the strings you refer to. Note that some of the strings you want may already be in the language files in Moodle core. If so, use the existing strings. An easy way to find the existing strings is to search the files in lang/en_utf8 (or whichever language), particularly lang/en_utf8/quiz.php .
- Write the help file for your question type, and any other help files you need.
- Write a set of unit tests for your question type.
All the places in the code where you need to do things are marked TODO, and there are comments right there giving more detailed instructions.
Note that these comments are not complete or accurate yet. I have only just started implementing my own question type, and I will be filling in those comments and finishing this document as I go along.Tim Hunt 11:46, 12 April 2007 (CDT)
Import & Export Support
You can provide import and export support by adding a function for (each) format type you wish to support. The naming format is import_from_format and export_to_format, replacing format as appropriate (e.g., export_to_xml). Not all import/export plugins currently support this. See Import/export_for_questiontype_plugins for more information.
Note in particular that it is vital that your import format checks that the data passed really is for the same type of question as your plugin. In most cases this will simply be a matter of checking the question type (qtype) name in $data. This is done because the type name in the import format may not match the plugin name so all plugins will be polled to find one to handle the question.
In lang/en_utf8/qtype_myqtypeidentifier.php you need to define at least the following strings:
$string['addingQTYPEID'] = 'Adding a QTYPENAME question';
$string['editingQTYPEID'] = 'Editing a QTYPENAME question';
$string['QTYPEID'] = 'QTYPENAME';
$string['QTYPEIDsummary'] = 'One or two sentence summary of what this question type does.';
Model Question Types
If your question is similar to an existing question type (perhaps varying only in how it is displayed or how it is graded), it may be easier to adapt an existing question type rather than to start from the TEMPLATE question.
Be aware that backup/restore and import/export are handled differently for core question types than for contrib questions, so you will need to add backup/restore and import/export functions if you base your new question type on a core question type.
Even if your question is very different from existing question types, existing question types can provide good examples for various subtasks:
- manual grading
- adaptive grading for a single response
- grading a single response disallowing adaptive grading
- adaptive grading for multiple responses
- grading numerical answers with tolerance
Backup/Restore and Import/Export
Backup/restore and import/export are handled separately for core question types, so take a look at question types in contrib such as order or regexp.
From Moodle 2.0 onwards, these files will also be include on the question/question.php page that shows the editing form for your question type.
If you have more complicated requirements, you can instead override the get_html_head_contributions and get_editing_head_contributions (2.0+) methods of the question type class.
Alternatively, if you really must, you can generate the CSS and JS using PHP code in by calling the files styles.php and script.php but that is really not recommended.
Configuration settings for your question type
Sometimes you question type may need some configuration settings in the site admin area. Two examples of this would be the JUnit question type, which needs to know the path to java and javac on the server, and the Opaque question type, where you need to set up question engines to connect to.
To have admin settings for your question type, you just need to create a file settings.php inside your question type folder. In there, you need to create admin_settings objects, and add them to the $settings object that will be in scope when settings.php is included. For example, the following code, if placed in question/type/sojunit/settings.php, would defined three text settings for the sojunit question type where the admin can type in the paths required to make this question type work.
get_string('pathtojava', 'qtype_sojunit'), get_string('configpathtojava', 'qtype_sojunit'),
get_string('pathtojavac', 'qtype_sojunit'), get_string('configpathtojavac', 'qtype_sojunit'),
get_string('pathtojunit', 'qtype_sojunit'), get_string('configpathtojunit', 'qtype_sojunit'),
The question type code could then access these settings by doing
$sojunitcfg = get_config('qtype_sojunit');
// Use $sojunitcfg->pathtojava, etc. in the processing.
How do you know that your new question type is working, and that you have done everything you need to? If you do all of the following tests, you can be fairly confident that you have done everything you need to:
- Create some new questions of your type, exercising each significantly different combination of options.
- Go back to the editing form for each question to make sure that the options were saved accurately and that you can change them and that the changes are then saved.
- Try typing invalid input into the editing form, and ensure it is rejected.
- Add your questions to three quizzes, one in adaptive mode, one in non-adaptive mode, and one in non-adaptive mode with each attempt builds on last. Perhaps mix in some standard question types. Make one of the quizzes one question per page, and another with all the questions on the same page.
- Try those quizzes several times in preview mode, entering a range of correct and incorrect responses.
- Now log in as a student and take the quizzes for real.
- View all of the quiz reports, and ensure that they correctly display the information about your questions.
- Backup the course, restore it as a new course, and ensure that all your questions have been copied across accurately. Before doing this test, edit at least one of the questions and wherever HTML can be entered, insert a link to another part of the course, for example a resource. Ensure that after backup and restore, the link has been updated to point to the new URL of the restored resource.
- Export your questions from the original course to each of the import/export formats your support. Import these questions to a new question category, and ensure they have been copied accurately (within the limits to which your question type can be represented in each format).
- Check your question type against Accessibility guidelines, for example the Web Content Accessibility Guidelines.
Here are some tips to help while trying to get your question type working:
- Watch the results of this database query while attempting the question in a quiz, to see what is being stored in the database. This is a really useful way to find out what is going on in the code.
When you have finished
Consider checking your question type into the contrib area of the Moodle CVS server (if you have access, if not, request it or post your code as a zip file in the quiz forum) so that other people can share it.
Add your new question type to the modules and plugins database.