From f9d3265499d14639016fa7f54acbe41fa071d7d1 Mon Sep 17 00:00:00 2001 From: Tim Hunt Date: Mon, 26 Feb 2024 15:17:45 +0000 Subject: [PATCH] Start documenting core_question and qbank_ --- docs/apis/plugintypes/qbank/index.md | 15 +++- docs/apis/plugintypes/qtype/index.md | 28 +++++++ .../plugintypes/qtype/newquestiondefaults.md | 73 +++++++++++++++++++ docs/apis/subsystems/question/index.md | 73 +++++++++++++++++++ 4 files changed, 185 insertions(+), 4 deletions(-) create mode 100644 docs/apis/plugintypes/qtype/index.md create mode 100644 docs/apis/plugintypes/qtype/newquestiondefaults.md create mode 100644 docs/apis/subsystems/question/index.md diff --git a/docs/apis/plugintypes/qbank/index.md b/docs/apis/plugintypes/qbank/index.md index c34a5ff5aa..6560be6e95 100644 --- a/docs/apis/plugintypes/qbank/index.md +++ b/docs/apis/plugintypes/qbank/index.md @@ -1,11 +1,10 @@ --- -title: Question Bank plugins +title: Question bank plugins tags: - Plugins - Question - qbank - - Quiz -description: Question type plugins allow you to extend the functionality of the Moodle Question bank. +description: Question bank plugins allow you to extend the functionality of the Moodle Question bank. documentationDraft: true --- @@ -16,10 +15,18 @@ import { Since } from '@site/src/components'; issueNumber="MDL-70329" /> -Question type plugins allow you to extend the functionality of the Moodle Question bank, and support features including: +Question bank plugins allow you to extend the functionality of the Moodle Question bank. They just one of the plugin +types used by core_question. To see how they fit in, please read +[this overview of the question subsystems](../subsystems/question/). + +Question bank plugins can extend the question bank in many ways, including: - Table columns - Action menu items - Bulk actions - Navigation node (tabs) - Question preview additions (via callback) + +The place to start implementing most of these is with a class `classes/plugin_features.php` in your plugin, +that declares which features you want to add to the question bank. Until more documentation is written, +looking at the examples of the plugins in Moodle core should give you a good idea what you need to do. diff --git a/docs/apis/plugintypes/qtype/index.md b/docs/apis/plugintypes/qtype/index.md new file mode 100644 index 0000000000..0c4b596ad0 --- /dev/null +++ b/docs/apis/plugintypes/qtype/index.md @@ -0,0 +1,28 @@ +--- +title: Question type plugins +tags: + - Plugins + - Question + - qtype +description: Question type plugins implement the different types of question that the core Question subsystem can handle. +--- + +Question types are one of the plugins used by the question subsystem. To see how they fit in, please read +[this overview of the question subsystems](../subsystems/question/). + +Question types have to do many things: + +1. `edit_..._form.php` - Provide an editing form so that teachers can create and edit questions of this type. +2. `questiontypes.php` - Define a class to handle loading and saving data from this form. +3. ... and related methods providing metadata about this question types. +4. ... and import and export in any Question formats that the type wants to support. +5. `question.php` - this class represents one instance of this question type, while it is being attempted by a user. It must do many things +6. ... Start a new attempt (e.g. in a multiple choice question, this is where we randomly shuffle the choices). +7. ... or if we are continuing an existing attmept, re-initalise the question to the same state, using the data from the DB. +8. ... Tell the question engine what data this question type is expecting to be submitted. +9. ... Analyse those submitted responses: e.g. has it changed? is it complete. +10. ... Automatically grade the response to give a 'fraction' (mark between 0 and 1) and a state (correct / partially correct / incorrect). +11. ... check access to files for the file API. +12. `renderer.php` - to display the key bits of this question types for the `core_question_renderer` to combine into the overall question display. +13. Implements Backup and restore, and all the other standard parts of a Moodle plugin like DB tables. +14. Track [users preferences for the settings used for newly created questions](./qtype/newquestiondefaults). diff --git a/docs/apis/plugintypes/qtype/newquestiondefaults.md b/docs/apis/plugintypes/qtype/newquestiondefaults.md new file mode 100644 index 0000000000..2807592e50 --- /dev/null +++ b/docs/apis/plugintypes/qtype/newquestiondefaults.md @@ -0,0 +1,73 @@ +--- +title: Question type plugins - defaults for new questions +tags: + - Plugins + - Question + - qtype +description: A way for question types to remember a user's preferred settings for creating questions of a given type. +documentationDraft: true +--- + +Many question types are quite flexible, and so have a lot of options on their editing form. Quite often, when a teacher +is creating a number of questions, it is likely that the teacher will want to keep using the same values for some options. +Therefore, the question system has a way for question types to easily save certain settings, and re-use them. + +Note, this is only done when a teacher creates and saves a new question. We don't save the preferences when a teacher edits +an existing question (which might have been created by someone else with different preferences). + +Here is how you implement this: + +### Decide which settings should be saved + +It does not make sense to save all settings. For example, it woule by stupid to remember the name and question text, +because these are things that make a particular question what it is, and will alwasy be different. So, we only want to +save settings where that makes sense. For example do you want the choices in your multiple-choice question numbered +'a, b, c, ...' or '1, 2, 3, ...' or not numbered at all? You need to think about this. Looking through what other question +types do is probably a good way to get a feel for what sorts of things it makes sense to remember. + +### In the form class - use any previously saved defaults + +Before implementing this feature, your form class is likely to have code like + +```php +$mform->setDefault('shuffleanswers', 1); +``` + +For all the settings where you want to implement this feature, need to change the hard-coded default (`1` here) to instead +fetch the default from the user's preferences using the `get_default_value` method: + +```php +$mform->setDefault('shuffleanswers', $this->get_default_value('shuffleanswers', 1)); +``` + +### In the question-type class + +Here we need to override the method `save_defaults_for_new_questions` to save the values these settings. For example: + +```php + public function save_defaults_for_new_questions(stdClass $fromform): void { + parent::save_defaults_for_new_questions($fromform); + $this->set_default_value('shuffleanswers', $fromform->shuffleanswers); + } +``` + +All the settings save here should match the ones fetched by `get_default_value` in the form. +You need to call `parent` because Moodle core saves some of the settings that apply to all question types. + +### Privacy provider + +Because this feature works using user preferences, you need to declare that in your privacy provider. + +This is boring but necessary. Easiest way to see what to do is to [copy another quetion type](https://github.com/moodle/moodle/blob/master/question/type/match/classes/privacy/provider.php). + +Note, it is necessary for your provider to declare the ones saved by core. (I suppose, ideally, someone would make a helpful base class, or trait, to make it easier to implement this.) + +### Automated tests + +Always a good idea. You are likely to need: + +1. [Unit tests for the privacy provider](https://github.com/moodle/moodle/blob/master/question/type/match/tests/privacy/provider_test.php). +2. Behat test to show that the saved settings are re-used. Many question types have + [a `behat/add.feature` file where it is easy to add coverage for this](https://github.com/moodle/moodle/blob/master/question/type/match/tests/behat/add.feature). + +The links in that list go to examples of how these are implemented in `qtype_match`. diff --git a/docs/apis/subsystems/question/index.md b/docs/apis/subsystems/question/index.md new file mode 100644 index 0000000000..81dc9d1c41 --- /dev/null +++ b/docs/apis/subsystems/question/index.md @@ -0,0 +1,73 @@ +--- +title: Questions API +tags: + - API + - Subsystem + - Question +documentationDraft: true +--- + +The question subsystem in Moodle manages the creation, editing and management of interactive questions, +and then enables those questions to be presented to users so they can be attempted. It is useful to +consider these as separate subcomponents. + +## The question engine + +This is the part that makes questions work when users attempt or otherwise interact with questions as part of a learning experience. + +The main user of this in the standard Moodle package is mod_quiz, but there is also qbank_previewquestion, and numerous plugins, includin +[filter_embedquestion](https://moodle.org/plugins/filter_embedquestion). + +The goal of this part of the system is to allow the widest ranges of interactive learning experiences to be created, therefore the question +engine supports two types of plugin: + +### [Question types (qtype_)](../../plugintypes/qtype/index.md) + +This defines what the question is. For example a multiple choice or drag-drop question question, or +a text input question graded as eith a string (e.g. shortanswer or [pattern-match](https://moodle.org/plugins/qtype_pmatch)) +or as a number. It might be something much more complex, like a [crossword](https://moodle.org/plugins/qtype_crossword), or a [coding exercise](https://moodle.org/plugins/qtype_coderunner). + +### Question behaviours (qbehaviour_) + +These let Moodle support different ways for a student to interact with questions. +For example it might be like a classic exams, where initially the student just inputs their answers to all the questions, which are then +only graded, and feedback given later (qbehaviour_deferredfeedback). Or it the student might have a 'Check' button in each question +so their work can be graded immediately (qbahviour_immediatefeebdack). It might even be that after their first try, if that is not right, +the students can immediately Try again, to see if they can correct their mistake based on the initial feedback (qbehaviour_interactive). + +### Core question engine + +So, core question engine mostly serves orchestrates these two plugin types working together to present a attempt at a particular question to a user. +Some key classes here are: + +1. `question_engine` - this class is the main entry point into this part of the API. +2. `question_attempt` - this represents a users attempt at on question. Since most of the time user's attempt a group of related + questions together, and even more important class is `question_usage_by_activity`. +3. `question state` - as stated above, question types and behaviours should have as much freedom as possible to present interesting + educational interactions to users. But, on the other hand, parts of the system that use questions (e.g. the quiz) need to have some + idea what is going on with each question. The various question states try to find an appropriate compromise, so the state of each + question can be tracked, but withough restricting the freedom of the question behaviours to work how they want. +4. `question_display_options` - when questions are used, e.g. in a quiz, there may be limitations one what the user can see. For example, + perhaps the student is only allowed to see the grade and feedback on their attempt after all students have finished. The display options + class is how the quiz can control which bits should be visible when a question is rendered. In addition, depending what state we are in + with the question behviour might also affect what is visible right now, so qbehaviour_plugins can modify the display options based + on the current state of the question_attempt, as part of the rendering process. +5. `core_question_renderer` - renders the overall layout of the questions. It works with the applicable qtype_ and qbehaviour_ renderer to + rendner the details of the current attempt. + +## Question bank + +The question bank provies the UI where teachers create, edit and manage questions. + +### [Question bank plugins (qbank_)](../../plugintypes/qbank/index.md) + +These add features to the qusetion bank. The core question bank code mainly just ties all these features together. + +### Question import/export plugins (qformat_) + +Allow questions to be exported and imported in a variety of formats. Use by plugins like qbank_exportquestions, qbank_importquestions and qbank_exporttoxml. + +### [Question types (qtype_)](../../plugintypes/qtype/index.md) + +Question types do not only interact with the question engine. They also need to work with the question bank, so that teachers +can create and edit questions of their type.