Search moodle.org's
Developer Documentation

See Release Notes
Long Term Support Release

  • Bug fixes for general core bugs in 3.9.x will end* 10 May 2021 (12 months).
  • Bug fixes for security issues in 3.9.x will end* 8 May 2023 (36 months).
  • PHP version: minimum PHP 7.2.0 Note: minimum PHP version has increased since Moodle 3.8. PHP 7.3.x and 7.4.x are supported too.

Differences Between: [Versions 39 and 310] [Versions 39 and 311] [Versions 39 and 400] [Versions 39 and 401] [Versions 39 and 402] [Versions 39 and 403]

This defines the core classes of the Moodle question engine.

Copyright: 2009 The Open University
License: http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
File Size: 1218 lines (48 kb)
Included or required: 43 times
Referenced: 8 times
Includes or requires: 13 files
 question/engine/datalib.php
 question/engine/questionattempt.php
 question/engine/renderer.php
 question/engine/states.php
 question/type/rendererbase.php
 question/type/questiontypebase.php
 question/engine/questionattemptstep.php
 question/behaviour/behaviourtypebase.php
 question/engine/questionusage.php
 question/type/questionbase.php
 question/behaviour/behaviourbase.php
 question/engine/bank.php
 question/behaviour/rendererbase.php

Defines 9 classes

question_engine:: (24 methods):
  make_questions_usage_by_activity()
  load_questions_usage_by_activity()
  save_questions_usage_by_activity()
  delete_questions_usage_by_activity()
  delete_questions_usage_by_activities()
  set_max_mark_in_attempts()
  is_manual_grade_in_range()
  questions_in_use()
  load_used_variants()
  make_archetypal_behaviour()
  get_behaviour_unused_display_options()
  can_questions_finish_during_the_attempt()
  make_behaviour()
  load_behaviour_class()
  get_behaviour_type()
  load_behaviour_type_class()
  get_archetypal_behaviours()
  is_behaviour_archetypal()
  sort_behaviours()
  get_behaviour_options()
  get_behaviour_name()
  get_all_response_file_areas()
  get_dp_options()
  initialise_js()

question_display_options:: (2 methods):
  hide_all_feedback()
  get_dp_options()

question_flags:: (4 methods):
  get_toggle_checksum()
  get_postdata()
  update_flag()
  initialise_js()

question_out_of_sequence_exception:: (1 method):
  __construct()

question_utils:: (12 methods):
  arrays_have_same_keys_and_values()
  arrays_same_at_key()
  arrays_same_at_key_missing_is_blank()
  arrays_same_at_key_integer()
  int_to_roman()
  int_to_letter()
  clean_param_mark()
  optional_param_mark()
  to_plain_text()
  specific_filepicker_options()
  get_filepicker_options()
  get_editor_options()

question_variant_selection_strategy:: (1 method):
  choose_variant()

question_variant_random_strategy:: (1 method):
  choose_variant()

question_variant_pseudorandom_no_repeats_strategy:: (2 methods):
  __construct()
  choose_variant()

question_variant_forced_choices_selection_strategy:: (3 methods):
  __construct()
  choose_variant()
  prepare_forced_choices_array()


Class: question_engine  - X-Ref

This static class provides access to the other question engine classes.

It provides functions for managing question behaviours), and for
creating, loading, saving and deleting {@link question_usage_by_activity}s,
which is the main class that is used by other code that wants to use questions.

make_questions_usage_by_activity($component, $context)   X-Ref
Create a new {@link question_usage_by_activity}. The usage is
created in memory. If you want it to persist, you will need to call
{@link save_questions_usage_by_activity()}.

param: string $component the plugin creating this attempt. For example mod_quiz.
param: object $context the context this usage belongs to.
return: question_usage_by_activity the newly created object.

load_questions_usage_by_activity($qubaid, moodle_database $db = null)   X-Ref
Load a {@link question_usage_by_activity} from the database, based on its id.

param: int $qubaid the id of the usage to load.
param: moodle_database $db a database connectoin. Defaults to global $DB.
return: question_usage_by_activity loaded from the database.

save_questions_usage_by_activity(question_usage_by_activity $quba, moodle_database $db = null)   X-Ref
Save a {@link question_usage_by_activity} to the database. This works either
if the usage was newly created by {@link make_questions_usage_by_activity()}
or loaded from the database using {@link load_questions_usage_by_activity()}

param: question_usage_by_activity the usage to save.
param: moodle_database $db a database connectoin. Defaults to global $DB.

delete_questions_usage_by_activity($qubaid)   X-Ref
Delete a {@link question_usage_by_activity} from the database, based on its id.

param: int $qubaid the id of the usage to delete.

delete_questions_usage_by_activities(qubaid_condition $qubaids)   X-Ref
Delete {@link question_usage_by_activity}s from the database.

param: qubaid_condition $qubaids identifies which questions usages to delete.

set_max_mark_in_attempts(qubaid_condition $qubaids,$slot, $newmaxmark)   X-Ref
Change the maxmark for the question_attempt with number in usage $slot
for all the specified question_attempts.

param: qubaid_condition $qubaids Selects which usages are updated.
param: int $slot the number is usage to affect.
param: number $newmaxmark the new max mark to set.

is_manual_grade_in_range($qubaid, $slot)   X-Ref
Validate that the manual grade submitted for a particular question is in range.

param: int $qubaid the question_usage id.
param: int $slot the slot number within the usage.
return: bool whether the submitted data is in range.

questions_in_use(array $questionids, qubaid_condition $qubaids = null)   X-Ref

param: array $questionids of question ids.
param: qubaid_condition $qubaids ids of the usages to consider.
return: boolean whether any of these questions are being used by any of

load_used_variants(array $questionids, qubaid_condition $qubaids)   X-Ref
Get the number of times each variant has been used for each question in a list
in a set of usages.

param: array $questionids of question ids.
param: qubaid_condition $qubaids ids of the usages to consider.
return: array questionid => variant number => num uses.

make_archetypal_behaviour($preferredbehaviour, question_attempt $qa)   X-Ref
Create an archetypal behaviour for a particular question attempt.
Used by {@link question_definition::make_behaviour()}.

param: string $preferredbehaviour the type of model required.
param: question_attempt $qa the question attempt the model will process.
return: question_behaviour an instance of appropriate behaviour class.

get_behaviour_unused_display_options($behaviour)   X-Ref

param: string $behaviour the name of a behaviour.
return: array of {@link question_display_options} field names, that are

can_questions_finish_during_the_attempt($behaviour)   X-Ref
With this behaviour, is it possible that a question might finish as the student
interacts with it, without a call to the {@link question_attempt::finish()} method?

param: string $behaviour the name of a behaviour. E.g. 'deferredfeedback'.
return: bool whether with this behaviour, questions may finish naturally.

make_behaviour($behaviour, question_attempt $qa, $preferredbehaviour)   X-Ref
Create a behaviour for a particular type. If that type cannot be
found, return an instance of qbehaviour_missing.

Normally you should use {@link make_archetypal_behaviour()}, or
call the constructor of a particular model class directly. This method
is only intended for use by {@link question_attempt::load_from_records()}.

param: string $behaviour the type of model to create.
param: question_attempt $qa the question attempt the model will process.
param: string $preferredbehaviour the preferred behaviour for the containing usage.
return: question_behaviour an instance of appropriate behaviour class.

load_behaviour_class($behaviour)   X-Ref
Load the behaviour class(es) belonging to a particular model. That is,
include_once('/question/behaviour/' . $behaviour . '/behaviour.php'), with a bit
of checking.

param: string $qtypename the question type name. For example 'multichoice' or 'shortanswer'.

get_behaviour_type($behaviour)   X-Ref
Create a behaviour for a particular type. If that type cannot be
found, return an instance of qbehaviour_missing.

Normally you should use {@link make_archetypal_behaviour()}, or
call the constructor of a particular model class directly. This method
is only intended for use by {@link question_attempt::load_from_records()}.

param: string $behaviour the type of model to create.
param: question_attempt $qa the question attempt the model will process.
param: string $preferredbehaviour the preferred behaviour for the containing usage.
return: question_behaviour_type an instance of appropriate behaviour class.

load_behaviour_type_class($behaviour)   X-Ref
Load the behaviour type class for a particular behaviour. That is,
include_once('/question/behaviour/' . $behaviour . '/behaviourtype.php').

param: string $behaviour the behaviour name. For example 'interactive' or 'deferredfeedback'.

get_archetypal_behaviours()   X-Ref
Return an array where the keys are the internal names of the archetypal
behaviours, and the values are a human-readable name. An
archetypal behaviour is one that is suitable to pass the name of to
{@link question_usage_by_activity::set_preferred_behaviour()}.

return: array model name => lang string for this behaviour name.

is_behaviour_archetypal($behaviour)   X-Ref

param: string $behaviour the name of a behaviour. E.g. 'deferredfeedback'.
return: bool whether this is an archetypal behaviour.

sort_behaviours($archetypes, $orderlist, $disabledlist, $current=null)   X-Ref
Return an array where the keys are the internal names of the behaviours
in preferred order and the values are a human-readable name.

param: array $archetypes, array of behaviours
param: string $orderlist, a comma separated list of behaviour names
param: string $disabledlist, a comma separated list of behaviour names
param: string $current, current behaviour name
return: array model name => lang string for this behaviour name.

get_behaviour_options($currentbehaviour)   X-Ref
Return an array where the keys are the internal names of the behaviours
in preferred order and the values are a human-readable name.

param: string $currentbehaviour
return: array model name => lang string for this behaviour name.

get_behaviour_name($behaviour)   X-Ref
Get the translated name of a behaviour, for display in the UI.

param: string $behaviour the internal name of the model.
return: string name from the current language pack.

get_all_response_file_areas()   X-Ref

return: array all the file area names that may contain response files.

get_dp_options()   X-Ref
Returns the valid choices for the number of decimal places for showing
question marks. For use in the user interface.

return: array suitable for passing to {@link html_writer::select()} or similar.

initialise_js()   X-Ref
Initialise the JavaScript required on pages where questions will be displayed.

return: string

Class: question_display_options  - X-Ref

This class contains all the options that controls how a question is displayed.

Normally, what will happen is that the calling code will set up some display
options to indicate what sort of question display it wants, and then before the
question is rendered, the behaviour will be given a chance to modify the
display options, so that, for example, A question that is finished will only
be shown read-only, and a question that has not been submitted will not have
any sort of feedback displayed.

hide_all_feedback()   X-Ref
Set all the feedback-related fields {@link $feedback}, {@link generalfeedback},
{@link rightanswer} and {@link manualcomment} to
{@link question_display_options::HIDDEN}.


get_dp_options()   X-Ref
Returns the valid choices for the number of decimal places for showing
question marks. For use in the user interface.

Calling code should probably use {@link question_engine::get_dp_options()}
rather than calling this method directly.

return: array suitable for passing to {@link html_writer::select()} or similar.

Class: question_flags  - X-Ref

Contains the logic for handling question flags.

get_toggle_checksum($qubaid, $questionid,$qaid, $slot, $user = null)   X-Ref
Get the checksum that validates that a toggle request is valid.

param: int $qubaid the question usage id.
param: int $questionid the question id.
param: int $sessionid the question_attempt id.
param: object $user the user. If null, defaults to $USER.
return: string that needs to be sent to question/toggleflag.php for it to work.

get_postdata(question_attempt $qa)   X-Ref
Get the postdata that needs to be sent to question/toggleflag.php to change the flag state.
You need to append &newstate=0/1 to this.

return: the post data to send.

update_flag($qubaid, $questionid, $qaid, $slot, $checksum, $newstate)   X-Ref
If the request seems valid, update the flag state of a question attempt.
Throws exceptions if this is not a valid update request.

param: int $qubaid the question usage id.
param: int $questionid the question id.
param: int $sessionid the question_attempt id.
param: string $checksum checksum, as computed by {@link get_toggle_checksum()}
param: bool $newstate the new state of the flag. true = flagged.

initialise_js()   X-Ref
No description

Class: question_out_of_sequence_exception  - X-Ref

Exception thrown when the system detects that a student has done something
out-of-order to a question. This can happen, for example, if they click
the browser's back button in a quiz, then try to submit a different response.

__construct($qubaid, $slot, $postdata)   X-Ref
No description

Class: question_utils  - X-Ref

Useful functions for writing question types and behaviours.

arrays_have_same_keys_and_values(array $array1, array $array2)   X-Ref
Tests to see whether two arrays have the same keys, with the same values
(as compared by ===) for each key. However, the order of the arrays does
not have to be the same.

param: array $array1 the first array.
param: array $array2 the second array.
return: bool whether the two arrays have the same keys with the same

arrays_same_at_key(array $array1, array $array2, $key)   X-Ref
Tests to see whether two arrays have the same value at a particular key.
This method will return true if:
1. Neither array contains the key; or
2. Both arrays contain the key, and the corresponding values compare
identical when cast to strings and compared with ===.

param: array $array1 the first array.
param: array $array2 the second array.
param: string $key an array key.
return: bool whether the two arrays have the same value (or lack of

arrays_same_at_key_missing_is_blank(array $array1, array $array2, $key)   X-Ref
Tests to see whether two arrays have the same value at a particular key.
Missing values are replaced by '', and then the values are cast to
strings and compared with ===.

param: array $array1 the first array.
param: array $array2 the second array.
param: string $key an array key.
return: bool whether the two arrays have the same value (or lack of

arrays_same_at_key_integer(array $array1, array $array2, $key)   X-Ref
Tests to see whether two arrays have the same value at a particular key.
Missing values are replaced by 0, and then the values are cast to
integers and compared with ===.

param: array $array1 the first array.
param: array $array2 the second array.
param: string $key an array key.
return: bool whether the two arrays have the same value (or lack of

int_to_roman($number)   X-Ref
Convert an integer to roman numerals.

param: int $number an integer between 1 and 3999 inclusive. Anything else
return: string the number converted to lower case roman numerals.

int_to_letter($number)   X-Ref
Convert an integer to a letter of alphabet.

param: int $number an integer between 1 and 26 inclusive.
return: string the number converted to upper case letter of alphabet.

clean_param_mark($mark)   X-Ref
Typically, $mark will have come from optional_param($name, null, PARAM_RAW_TRIMMED).
This method copes with:
- keeping null or '' input unchanged - important to let teaches set a question back to requries grading.
- numbers that were typed as either 1.00 or 1,00 form.
- invalid things, which get turned into null.

param: string|null $mark raw use input of a mark.
return: float|string|null cleaned mark as a float if possible. Otherwise '' or null.

optional_param_mark($parname)   X-Ref
Get a sumitted variable (from the GET or POST data) that is a mark.

param: string $parname the submitted variable name.
return: float|string|null cleaned mark as a float if possible. Otherwise '' or null.

to_plain_text($text, $format, $options = array('noclean' => 'true')   X-Ref
Convert part of some question content to plain text.

param: string $text the text.
param: int $format the text format.
param: array $options formatting options. Passed to {@link format_text}.
return: float|string|null cleaned mark as a float if possible. Otherwise '' or null.

specific_filepicker_options($acceptedtypes, $draftitemid, $context)   X-Ref
Get the options required to configure the filepicker for one of the editor
toolbar buttons.

param: mixed $acceptedtypes array of types of '*'.
param: int $draftitemid the draft area item id.
param: object $context the context.
return: object the required options.

get_filepicker_options($context, $draftitemid)   X-Ref
Get filepicker options for question related text areas.

param: object $context the context.
param: int $draftitemid the draft area item id.
return: array An array of options

get_editor_options($context)   X-Ref
Get editor options for question related text areas.

param: object $context the context.
return: array An array of options

Interface: question_variant_selection_strategy  - X-Ref

The interface for strategies for controlling which variant of each question is used.

choose_variant($maxvariants, $seed)   X-Ref

param: int $maxvariants the num
param: string $seed data that can be used to controls how the variant is selected
return: int the variant to use, a number betweeb 1 and $maxvariants inclusive.

Class: question_variant_random_strategy  - X-Ref

A {@link question_variant_selection_strategy} that is completely random.

choose_variant($maxvariants, $seed)   X-Ref
No description

Class: question_variant_pseudorandom_no_repeats_strategy  - X-Ref

A {@link question_variant_selection_strategy} that is effectively random
for the first attempt, and then after that cycles through the available
variants so that the students will not get a repeated variant until they have
seen them all.

__construct($attemptno, $userid = null, $extrarandomness = '')   X-Ref
Constructor.

param: int $attemptno The attempt number.
param: int $userid the user the attempt is for (defaults to $USER->id).

choose_variant($maxvariants, $seed)   X-Ref
No description

Class: question_variant_forced_choices_selection_strategy  - X-Ref

A {@link question_variant_selection_strategy} designed ONLY for testing.
For selected questions it wil return a specific variants. For the other
slots it will use a fallback strategy.

__construct(array $forcedchoices, question_variant_selection_strategy $basestrategy)   X-Ref
Constructor.

param: array $forcedchoices array seed => variant to select.
param: question_variant_selection_strategy $basestrategy strategy used

choose_variant($maxvariants, $seed)   X-Ref
No description

prepare_forced_choices_array(array $variantsbyslot,question_usage_by_activity $quba)   X-Ref
Helper method for preparing the $forcedchoices array.

param: array                      $variantsbyslot slot number => variant to select.
param: question_usage_by_activity $quba           the question usage we need a strategy for.
return: array that can be passed to the constructor as $forcedchoices.