MDL-79863 qtype_ordering: qtype_ordering rename 'answernumbering' to 'numberingstyle' and include this field in import/export of xml/gift formats.

This commit is contained in:
Gordon Bateson 2019-07-12 17:08:59 +09:00 committed by Mathew May
parent 76a6fce839
commit d784021b8d
14 changed files with 249 additions and 160 deletions

View file

@ -51,7 +51,8 @@ class backup_qtype_ordering_plugin extends backup_qtype_plugin {
$this->add_question_question_answers($pluginwrapper); $this->add_question_question_answers($pluginwrapper);
// Now create the qtype own structures. // Now create the qtype own structures.
$fields = array('layouttype', 'selecttype', 'selectcount', 'gradingtype', 'showgrading', 'answernumbering', $fields = array('layouttype', 'selecttype', 'selectcount',
'gradingtype', 'showgrading', 'numberingstyle',
'correctfeedback', 'correctfeedbackformat', 'correctfeedback', 'correctfeedbackformat',
'incorrectfeedback', 'incorrectfeedbackformat', 'incorrectfeedback', 'incorrectfeedbackformat',
'partiallycorrectfeedback', 'partiallycorrectfeedbackformat'); 'partiallycorrectfeedback', 'partiallycorrectfeedbackformat');

View file

@ -10,13 +10,13 @@
<FIELD NAME="selectcount" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="selectcount" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="gradingtype" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="gradingtype" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="showgrading" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="showgrading" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="numberingstyle" TYPE="char" LENGTH="10" NOTNULL="true" DEFAULT="none" SEQUENCE="false" COMMENT="Indicates whether and how choices should be numbered."/>
<FIELD NAME="correctfeedback" TYPE="text" NOTNULL="false" SEQUENCE="false"/> <FIELD NAME="correctfeedback" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="correctfeedbackformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="correctfeedbackformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="incorrectfeedback" TYPE="text" NOTNULL="false" SEQUENCE="false"/> <FIELD NAME="incorrectfeedback" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="incorrectfeedbackformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="incorrectfeedbackformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="partiallycorrectfeedback" TYPE="text" NOTNULL="false" SEQUENCE="false"/> <FIELD NAME="partiallycorrectfeedback" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="partiallycorrectfeedbackformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/> <FIELD NAME="partiallycorrectfeedbackformat" TYPE="int" LENGTH="2" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="answernumbering" TYPE="char" LENGTH="10" NOTNULL="true" DEFAULT="none" SEQUENCE="false" COMMENT="Indicates how and whether the choices should be numbered."/>
</FIELDS> </FIELDS>
<KEYS> <KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for question_ordering"/> <KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for question_ordering"/>

View file

@ -231,15 +231,30 @@ function xmldb_qtype_ordering_upgrade($oldversion) {
upgrade_plugin_savepoint(true, $newversion, 'qtype', 'ordering'); upgrade_plugin_savepoint(true, $newversion, 'qtype', 'ordering');
} }
$newversion = 2019062000; $newversion = 2019071191;
if ($oldversion < $newversion) { if ($oldversion < $newversion) {
// Define field answernumbering to be added to qtype_ordering_options. // Add field "numberingstyle" to table "qtype_ordering_options".
// This field was briefly called "answernumbering".
$table = new xmldb_table('qtype_ordering_options'); $table = new xmldb_table('qtype_ordering_options');
$field = new xmldb_field('answernumbering', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, 'none', 'partiallycorrectfeedbackformat'); $field = new xmldb_field('answernumbering', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, 'none', 'showgrading');
$newname = 'numberingstyle';
// Conditionally launch add field answernumbering. $oldexists = $dbman->field_exists($table, $field);
if (!$dbman->field_exists($table, $field)) { $newexists = $dbman->field_exists($table, $newname);
if ($oldexists) {
if ($newexists) {
$dbman->drop_field($table, $field);
} else {
$dbman->rename_field($table, $field, $newname);
$newexists = true;
}
$oldexists = false;
}
$field->setName($newname);
if ($newexists) {
$dbman->change_field_type($table, $field);
} else {
$dbman->add_field($table, $field); $dbman->add_field($table, $field);
} }

View file

@ -120,14 +120,16 @@ class qtype_ordering_edit_form extends question_edit_form {
$mform->addHelpButton($name, $name, $plugin); $mform->addHelpButton($name, $name, $plugin);
$mform->setDefault($name, $this->get_default_value($name, 1)); $mform->setDefault($name, $this->get_default_value($name, 1));
$name = 'numberingstyle';
$label = get_string($name, $plugin);
$options = qtype_ordering_question::get_numbering_styles();
$mform->addElement('select', $name, $label, $options);
$mform->addHelpButton($name, $name, $plugin);
$mform->setDefault($name, $this->get_default_value($name, qtype_ordering_question::NUMBERING_STYLE_DEFAULT));
$elements = array(); $elements = array();
$options = array(); $options = array();
$name = 'answernumbering';
$label = get_string($name, 'qtype_ordering');
$mform->addElement('select', $name, $label, qtype_ordering::get_numbering_styles());
$mform->setDefault($name, $this->get_default_value($name, get_config('qtype_ordering', $name)));
$name = 'answerheader'; $name = 'answerheader';
$label = get_string($name, $plugin); $label = get_string($name, $plugin);
$elements[] = $mform->createElement('header', $name, $label); $elements[] = $mform->createElement('header', $name, $label);
@ -342,7 +344,8 @@ class qtype_ordering_edit_form extends question_edit_form {
'selecttype' => qtype_ordering_question::SELECT_ALL, 'selecttype' => qtype_ordering_question::SELECT_ALL,
'selectcount' => 0, // 0 means ALL. 'selectcount' => 0, // 0 means ALL.
'gradingtype' => qtype_ordering_question::GRADING_ABSOLUTE_POSITION, 'gradingtype' => qtype_ordering_question::GRADING_ABSOLUTE_POSITION,
'showgrading' => 1 // 1 means SHOW. 'showgrading' => 1, // 1 means SHOW.
'numberingstyle' => qtype_ordering_question::NUMBERING_STYLE_DEFAULT
); );
foreach ($names as $name => $default) { foreach ($names as $name => $default) {
if (isset($question->options->$name)) { if (isset($question->options->$name)) {
@ -396,7 +399,8 @@ class qtype_ordering_edit_form extends question_edit_form {
// If adding a new ordering question, update defaults. // If adding a new ordering question, update defaults.
if (empty($errors) && empty($data['id'])) { if (empty($errors) && empty($data['id'])) {
$fields = array('layouttype', 'selecttype', 'selectcount', 'gradingtype', 'showgrading'); $fields = array('layouttype', 'selecttype', 'selectcount',
'gradingtype', 'showgrading', 'numberingstyle');
foreach ($fields as $field) { foreach ($fields as $field) {
if (array_key_exists($field, $data)) { if (array_key_exists($field, $data)) {
$this->set_default_value($field, $data[$field]); $this->set_default_value($field, $data[$field]);

View file

@ -28,14 +28,6 @@ $string['addsingleanswer'] = 'Add one more item';
$string['allornothing'] = 'All or nothing'; $string['allornothing'] = 'All or nothing';
$string['answer'] = 'Item text'; $string['answer'] = 'Item text';
$string['answerheader'] = 'Draggable item {no}'; $string['answerheader'] = 'Draggable item {no}';
$string['answernumbering'] = 'Number the choices?';
$string['answernumbering123'] = '1., 2., 3., ...';
$string['answernumberingabc'] = 'a., b., c., ...';
$string['answernumberingABCD'] = 'A., B., C., ...';
$string['answernumberingiii'] = 'i., ii., iii., ...';
$string['answernumberingIIII'] = 'I., II., III., ...';
$string['answernumberingnone'] = 'No numbering';
$string['answernumbering_desc'] = 'The default numbering style.';
$string['correctorder'] = 'The correct order for these items is as follows:'; $string['correctorder'] = 'The correct order for these items is as follows:';
@ -87,6 +79,16 @@ $string['noresponsedetails'] = 'Sorry, no details of the response to this questi
$string['noscore'] = 'No score'; $string['noscore'] = 'No score';
$string['notenoughanswers'] = 'Ordering questions must have more than {$a} answers.'; $string['notenoughanswers'] = 'Ordering questions must have more than {$a} answers.';
$string['numberingstyle'] = 'Number the choices?';
$string['numberingstylenone'] = 'No numbering';
$string['numberingstyle123'] = '1., 2., 3., ...';
$string['numberingstyleabc'] = 'a., b., c., ...';
$string['numberingstyleABC'] = 'A., B., C., ...';
$string['numberingstyleiii'] = 'i., ii., iii., ...';
$string['numberingstyleIII'] = 'I., II., III., ...';
$string['numberingstyle_desc'] = 'The default numbering style.';
$string['numberingstyle_help'] = 'Choose the numbering style for draggable items in this question.';
$string['positionx'] = 'Position {$a}'; $string['positionx'] = 'Position {$a}';
$string['pluginname'] = 'Ordering'; $string['pluginname'] = 'Ordering';
$string['pluginname_help'] = 'Several items are displayed in a jumbled order. The items can be dragged into a meaningful order.'; $string['pluginname_help'] = 'Several items are displayed in a jumbled order. The items can be dragged into a meaningful order.';

View file

@ -46,8 +46,8 @@ class qtype_ordering_question extends question_graded_automatically {
/** Show answers in one horizontal line */ /** Show answers in one horizontal line */
const LAYOUT_HORIZONTAL = 1; const LAYOUT_HORIZONTAL = 1;
/** Show answernumbering default */ /** Default value for numberingstyle */
const ANSWER_NUMBERING_DEFAULT = 'none'; const NUMBERING_STYLE_DEFAULT = 'none';
/** @var int Zero grade on any error */ /** @var int Zero grade on any error */
const GRADING_ALL_OR_NOTHING = -1; const GRADING_ALL_OR_NOTHING = -1;
@ -537,14 +537,14 @@ class qtype_ordering_question extends question_graded_automatically {
'selecttype' => self::SELECT_ALL, 'selecttype' => self::SELECT_ALL,
'selectcount' => 0, 'selectcount' => 0,
'gradingtype' => self::GRADING_ABSOLUTE_POSITION, 'gradingtype' => self::GRADING_ABSOLUTE_POSITION,
'showgradingdetails' => 1, 'showgrading' => 1,
'numberingstyle' => self::NUMBERING_STYLE_DEFAULT,
'correctfeedback' => '', 'correctfeedback' => '',
'correctfeedbackformat' => FORMAT_MOODLE, 'correctfeedbackformat' => FORMAT_MOODLE,
'incorrectfeedback' => '', 'incorrectfeedback' => '',
'incorrectfeedbackformat' => FORMAT_MOODLE, 'incorrectfeedbackformat' => FORMAT_MOODLE,
'partiallycorrectfeedback' => '', 'partiallycorrectfeedback' => '',
'partiallycorrectfeedbackformat' => FORMAT_MOODLE, 'partiallycorrectfeedbackformat' => FORMAT_MOODLE
'answernumbering' => self::ANSWER_NUMBERING_DEFAULT
); );
$this->options->id = $DB->insert_record('qtype_ordering_options', $this->options); $this->options->id = $DB->insert_record('qtype_ordering_options', $this->options);
} }
@ -827,4 +827,22 @@ class qtype_ordering_question extends question_graded_automatically {
); );
return self::get_types($types, $type); return self::get_types($types, $type);
} }
/**
* @param string $style
* @return array of the numbering styles supported. For each one, there
* should be a lang string numberingstylexxx in the qtype_ordering
* language file, and a case in the switch statement in number_in_style,
* and it should be listed in the definition of this column in install.xml.
*/
public static function get_numbering_styles($style=null) {
$plugin = 'qtype_ordering';
$styles = array('none' => get_string('numberingstylenone', $plugin),
'abc' => get_string('numberingstyleabc', $plugin),
'ABC' => get_string('numberingstyleABC', $plugin),
'123' => get_string('numberingstyle123', $plugin),
'iii' => get_string('numberingstyleiii', $plugin),
'III' => get_string('numberingstyleIII', $plugin));
return self::get_types($styles, $style);
}
} }

View file

@ -35,6 +35,28 @@ class qtype_ordering extends question_type {
/** @var array Combined feedback fields */ /** @var array Combined feedback fields */
public $feedbackfields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback'); public $feedbackfields = array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback');
/**
* @return whether the question_answers.answer field needs to have
* restore_decode_content_links_worker called on it.
*/
public function has_html_answers() {
return true;
}
/**
* If your question type has a table that extends the question table, and
* you want the base class to automatically save, backup and restore the extra fields,
* override this method to return an array wherer the first element is the table name,
* and the subsequent entries are the column names (apart from id and questionid).
*
* @return mixed array as above, or null to tell the base class to do nothing.
*/
public function extra_question_fields() {
return array('qtype_ordering_options',
'layouttype', 'selecttype', 'selectcount',
'gradingtype', 'showgrading', 'numberingstyle');
}
/** /**
* Initialise the common question_definition fields. * Initialise the common question_definition fields.
* @param question_definition $question the question_definition we are creating. * @param question_definition $question the question_definition we are creating.
@ -42,7 +64,6 @@ class qtype_ordering extends question_type {
*/ */
protected function initialise_question_instance(question_definition $question, $questiondata) { protected function initialise_question_instance(question_definition $question, $questiondata) {
parent::initialise_question_instance($question, $questiondata); parent::initialise_question_instance($question, $questiondata);
$question->answernumbering = $questiondata->options->answernumbering;
$this->initialise_combined_feedback($question, $questiondata); $this->initialise_combined_feedback($question, $questiondata);
} }
@ -167,7 +188,7 @@ class qtype_ordering extends question_type {
'selectcount' => $question->selectcount, 'selectcount' => $question->selectcount,
'gradingtype' => $question->gradingtype, 'gradingtype' => $question->gradingtype,
'showgrading' => $question->showgrading, 'showgrading' => $question->showgrading,
'answernumbering' => $question->answernumbering 'numberingstyle' => $question->numberingstyle
); );
$options = $this->save_combined_feedback_helper($options, $question, $context, true); $options = $this->save_combined_feedback_helper($options, $question, $context, true);
$this->save_hints($question, false); $this->save_hints($question, false);
@ -336,18 +357,21 @@ class qtype_ordering extends question_type {
'LONGEST_ORDERED_SUBSET|'. 'LONGEST_ORDERED_SUBSET|'.
'LONGEST_CONTIGUOUS_SUBSET)?'; 'LONGEST_CONTIGUOUS_SUBSET)?';
$showgrading = '(?:SHOW|TRUE|YES|1|HIDE|FALSE|NO|0)?'; $showgrading = '(?:SHOW|TRUE|YES|1|HIDE|FALSE|NO|0)?';
$numberingstyle = '(?:none|123|abc|ABC|iii|III)?';
$search = '/^\s*>\s*('.$selectcount.')\s*'. $search = '/^\s*>\s*('.$selectcount.')\s*'.
'('.$selecttype.')\s*'. '('.$selecttype.')\s*'.
'('.$layouttype.')\s*'. '('.$layouttype.')\s*'.
'('.$gradingtype.')\s*'. '('.$gradingtype.')\s*'.
'('.$showgrading.')\s*'. '('.$showgrading.')\s*'.
'('.$numberingstyle.')\s*'.
'(.*?)\s*$/s'; '(.*?)\s*$/s';
// Item $1 the number of items to be shown. // Item $1 the number of items to be shown.
// Item $2 the extraction/grading type. // Item $2 the extraction/grading type.
// Item $3 the layout type. // Item $3 the layout type.
// Item $4 the grading type. // Item $4 the grading type.
// Item $5 show the grading details (SHOW/HIDE). // Item $5 show the grading details (SHOW/HIDE).
// Item $6 the lines of items to be ordered. // Item $6 the numbering style (none/123/abc/...).
// Item $7 the lines of items to be ordered.
if (! $extra) { if (! $extra) {
return false; // Format not recognized. return false; // Format not recognized.
} }
@ -360,8 +384,9 @@ class qtype_ordering extends question_type {
$layouttype = trim($matches[3]); $layouttype = trim($matches[3]);
$gradingtype = trim($matches[4]); $gradingtype = trim($matches[4]);
$showgrading = trim($matches[5]); $showgrading = trim($matches[5]);
$numberingstyle = trim($matches[6]);
$answers = preg_split('/[\r\n]+/', $matches[6]); $answers = preg_split('/[\r\n]+/', $matches[7]);
$answers = array_filter($answers); $answers = array_filter($answers);
if (empty($question)) { if (empty($question)) {
@ -416,7 +441,7 @@ class qtype_ordering extends question_type {
} else { } else {
$selectcount = min(6, count($answers)); $selectcount = min(6, count($answers));
} }
$this->set_layout_select_count_grading($question, $layouttype, $selecttype, $selectcount, $gradingtype, $showgrading); $this->set_options_for_import($question, $layouttype, $selecttype, $selectcount, $gradingtype, $showgrading, $numberingstyle);
// Remove blank items. // Remove blank items.
$answers = array_map('trim', $answers); $answers = array_map('trim', $answers);
@ -465,82 +490,88 @@ class qtype_ordering extends question_type {
* where layouttype, selecttype, gradingtype and showgrading are string representations. * where layouttype, selecttype, gradingtype and showgrading are string representations.
* *
* @param object $question * @param object $question
* @return array(layouttype, selecttype, selectcount, gradingtype) * @return array(layouttype, selecttype, selectcount, gradingtype, $showgrading, $numberingstyle)
*/ */
public function extract_layout_select_count_grading($question) { public function extract_options_for_export($question) {
switch ($question->options->layouttype) { switch ($question->options->layouttype) {
case qtype_ordering_question::LAYOUT_VERTICAL: case qtype_ordering_question::LAYOUT_VERTICAL:
$layout = 'VERTICAL'; $layouttype = 'VERTICAL';
break; break;
case qtype_ordering_question::LAYOUT_HORIZONTAL: case qtype_ordering_question::LAYOUT_HORIZONTAL:
$layout = 'HORIZONTAL'; $layouttype = 'HORIZONTAL';
break; break;
default: default:
$layout = ''; // Shouldn't happen !! $layouttype = ''; // Shouldn't happen !!
} }
switch ($question->options->selecttype) { switch ($question->options->selecttype) {
case qtype_ordering_question::SELECT_ALL: case qtype_ordering_question::SELECT_ALL:
$select = 'ALL'; $selecttype = 'ALL';
break; break;
case qtype_ordering_question::SELECT_RANDOM: case qtype_ordering_question::SELECT_RANDOM:
$select = 'RANDOM'; $selecttype = 'RANDOM';
break; break;
case qtype_ordering_question::SELECT_CONTIGUOUS: case qtype_ordering_question::SELECT_CONTIGUOUS:
$select = 'CONTIGUOUS'; $selecttype = 'CONTIGUOUS';
break; break;
default: default:
$select = ''; // Shouldn't happen !! $selecttype = ''; // Shouldn't happen !!
} }
switch ($question->options->gradingtype) { switch ($question->options->gradingtype) {
case qtype_ordering_question::GRADING_ALL_OR_NOTHING: case qtype_ordering_question::GRADING_ALL_OR_NOTHING:
$grading = 'ALL_OR_NOTHING'; $gradingtype = 'ALL_OR_NOTHING';
break; break;
case qtype_ordering_question::GRADING_ABSOLUTE_POSITION: case qtype_ordering_question::GRADING_ABSOLUTE_POSITION:
$grading = 'ABSOLUTE_POSITION'; $gradingtype = 'ABSOLUTE_POSITION';
break; break;
case qtype_ordering_question::GRADING_RELATIVE_NEXT_EXCLUDE_LAST: case qtype_ordering_question::GRADING_RELATIVE_NEXT_EXCLUDE_LAST:
$grading = 'RELATIVE_NEXT_EXCLUDE_LAST'; $gradingtype = 'RELATIVE_NEXT_EXCLUDE_LAST';
break; break;
case qtype_ordering_question::GRADING_RELATIVE_NEXT_INCLUDE_LAST: case qtype_ordering_question::GRADING_RELATIVE_NEXT_INCLUDE_LAST:
$grading = 'RELATIVE_NEXT_INCLUDE_LAST'; $gradingtype = 'RELATIVE_NEXT_INCLUDE_LAST';
break; break;
case qtype_ordering_question::GRADING_RELATIVE_ONE_PREVIOUS_AND_NEXT: case qtype_ordering_question::GRADING_RELATIVE_ONE_PREVIOUS_AND_NEXT:
$grading = 'RELATIVE_ONE_PREVIOUS_AND_NEXT'; $gradingtype = 'RELATIVE_ONE_PREVIOUS_AND_NEXT';
break; break;
case qtype_ordering_question::GRADING_RELATIVE_ALL_PREVIOUS_AND_NEXT: case qtype_ordering_question::GRADING_RELATIVE_ALL_PREVIOUS_AND_NEXT:
$grading = 'RELATIVE_ALL_PREVIOUS_AND_NEXT'; $gradingtype = 'RELATIVE_ALL_PREVIOUS_AND_NEXT';
break; break;
case qtype_ordering_question::GRADING_LONGEST_ORDERED_SUBSET: case qtype_ordering_question::GRADING_LONGEST_ORDERED_SUBSET:
$grading = 'LONGEST_ORDERED_SUBSET'; $gradingtype = 'LONGEST_ORDERED_SUBSET';
break; break;
case qtype_ordering_question::GRADING_LONGEST_CONTIGUOUS_SUBSET: case qtype_ordering_question::GRADING_LONGEST_CONTIGUOUS_SUBSET:
$grading = 'LONGEST_CONTIGUOUS_SUBSET'; $gradingtype = 'LONGEST_CONTIGUOUS_SUBSET';
break; break;
case qtype_ordering_question::GRADING_RELATIVE_TO_CORRECT: case qtype_ordering_question::GRADING_RELATIVE_TO_CORRECT:
$grading = 'RELATIVE_TO_CORRECT'; $gradingtype = 'RELATIVE_TO_CORRECT';
break; break;
default: default:
$grading = ''; // Shouldn't happen !! $gradingtype = ''; // Shouldn't happen !!
} }
switch ($question->options->showgrading) { switch ($question->options->showgrading) {
case 0: case 0:
$show = 'HIDE'; $showgrading = 'HIDE';
break; break;
case 1: case 1:
$show = 'SHOW'; $showgrading = 'SHOW';
break; break;
default: default:
$show = ''; // Shouldn't happen !! $showgrading = ''; // Shouldn't happen !!
}
if (empty($question->options->numberingstyle)) {
$numberingstyle = qtype_ordering_question::NUMBERING_STYLE_DEFAULT;
} else {
$numberingstyle = $question->options->numberingstyle;
} }
// Note: this used to be (selectcount + 2). // Note: this used to be (selectcount + 2).
$count = $question->options->selectcount; $selectcount = $question->options->selectcount;
return array($layout, $select, $count, $grading, $show); return array($layouttype, $selecttype, $selectcount, $gradingtype, $showgrading, $numberingstyle);
} }
/** /**
@ -570,9 +601,9 @@ class qtype_ordering extends question_type {
$output .= $question->questiontext.'{'; $output .= $question->questiontext.'{';
list($layouttype, $selecttype, $selectcount, $gradingtype, $showgrading) = list($layouttype, $selecttype, $selectcount, $gradingtype, $showgrading, $numberingstyle) =
$this->extract_layout_select_count_grading($question); $this->extract_options_for_export($question);
$output .= ">$selectcount $selecttype $layouttype $gradingtype $showgrading".PHP_EOL; $output .= ">$selectcount $selecttype $layouttype $gradingtype $showgrading $numberingstyle".PHP_EOL;
foreach ($question->options->answers as $answer) { foreach ($question->options->answers as $answer) {
$output .= $answer->answer.PHP_EOL; $output .= $answer->answer.PHP_EOL;
@ -594,8 +625,8 @@ class qtype_ordering extends question_type {
global $CFG; global $CFG;
require_once($CFG->dirroot.'/question/type/ordering/question.php'); require_once($CFG->dirroot.'/question/type/ordering/question.php');
list($layouttype, $selecttype, $selectcount, $gradingtype, $showgrading) = list($layouttype, $selecttype, $selectcount, $gradingtype, $showgrading, $numberingstyle) =
$this->extract_layout_select_count_grading($question); $this->extract_options_for_export($question);
$output = ''; $output = '';
$output .= " <layouttype>$layouttype</layouttype>\n"; $output .= " <layouttype>$layouttype</layouttype>\n";
@ -603,6 +634,7 @@ class qtype_ordering extends question_type {
$output .= " <selectcount>$selectcount</selectcount>\n"; $output .= " <selectcount>$selectcount</selectcount>\n";
$output .= " <gradingtype>$gradingtype</gradingtype>\n"; $output .= " <gradingtype>$gradingtype</gradingtype>\n";
$output .= " <showgrading>$showgrading</showgrading>\n"; $output .= " <showgrading>$showgrading</showgrading>\n";
$output .= " <numberingstyle>$numberingstyle</numberingstyle>\n";
$output .= $format->write_combined_feedback($question->options, $question->id, $question->contextid); $output .= $format->write_combined_feedback($question->options, $question->id, $question->contextid);
foreach ($question->options->answers as $answer) { foreach ($question->options->answers as $answer) {
@ -663,7 +695,8 @@ class qtype_ordering extends question_type {
$selectcount = $format->getpath($data, array('#', $selectcount, 0, '#'), 6); $selectcount = $format->getpath($data, array('#', $selectcount, 0, '#'), 6);
$gradingtype = $format->getpath($data, array('#', 'gradingtype', 0, '#'), 'RELATIVE'); $gradingtype = $format->getpath($data, array('#', 'gradingtype', 0, '#'), 'RELATIVE');
$showgrading = $format->getpath($data, array('#', 'showgrading', 0, '#'), '1'); $showgrading = $format->getpath($data, array('#', 'showgrading', 0, '#'), '1');
$this->set_layout_select_count_grading($newquestion, $layouttype, $selecttype, $selectcount, $gradingtype, $showgrading); $numberingstyle = $format->getpath($data, array('#', 'numberingstyle', 0, '#'), '1');
$this->set_options_for_import($newquestion, $layouttype, $selecttype, $selectcount, $gradingtype, $showgrading, $numberingstyle);
$newquestion->answer = array(); $newquestion->answer = array();
$newquestion->answerformat = array(); $newquestion->answerformat = array();
@ -725,132 +758,150 @@ class qtype_ordering extends question_type {
* @param string $grading the grading type * @param string $grading the grading type
* @param string $show the grading details or not * @param string $show the grading details or not
*/ */
public function set_layout_select_count_grading(&$question, $layout, $select, $count, $grading, $show) { public function set_options_for_import(&$question, $layouttype, $selecttype, $selectcount,
$gradingtype, $showgrading, $numberingstyle) {
// Set default values. // set "layouttype" option
$layouttype = qtype_ordering_question::LAYOUT_VERTICAL; switch (strtoupper($layouttype)) {
$selecttype = qtype_ordering_question::SELECT_RANDOM;
$selectcount = 3;
$gradingtype = qtype_ordering_question::GRADING_RELATIVE_NEXT_EXCLUDE_LAST;
$showgrading = 1;
switch (strtoupper($layout)) {
case 'HORIZONTAL': case 'HORIZONTAL':
case 'HORI': case 'HORI':
case 'H': case 'H':
case '1': case '1':
$layouttype = qtype_ordering_question::LAYOUT_HORIZONTAL; $question->layouttype = qtype_ordering_question::LAYOUT_HORIZONTAL;
break; break;
case 'VERTICAL': case 'VERTICAL':
case 'VERT': case 'VERT':
case 'V': case 'V':
case '0': case '0':
$layouttype = qtype_ordering_question::LAYOUT_VERTICAL; $question->layouttype = qtype_ordering_question::LAYOUT_VERTICAL;
break; break;
default:
$question->layouttype = qtype_ordering_question::LAYOUT_VERTICAL;
} }
// Set "selecttype" from $select. // Set "selecttype" option.
switch (strtoupper($select)) { switch (strtoupper($selecttype)) {
case 'ALL': case 'ALL':
case 'EXACT': case 'EXACT':
$selecttype = qtype_ordering_question::SELECT_ALL; $question->selecttype = qtype_ordering_question::SELECT_ALL;
break; break;
case 'RANDOM': case 'RANDOM':
case 'REL': case 'REL':
$selecttype = qtype_ordering_question::SELECT_RANDOM; $question->selecttype = qtype_ordering_question::SELECT_RANDOM;
break; break;
case 'CONTIGUOUS': case 'CONTIGUOUS':
case 'CONTIG': case 'CONTIG':
$selecttype = qtype_ordering_question::SELECT_CONTIGUOUS; $question->selecttype = qtype_ordering_question::SELECT_CONTIGUOUS;
break; break;
default:
$question->selecttype = qtype_ordering_question::SELECT_RANDOM;
} }
// Set "selectcount" from $count // Set "selectcount" option - this used to be ($count - 2).
// this used to be ($count - 2). if (is_numeric($selectcount)) {
if (is_numeric($count)) { $question->selectcount = intval($selectcount);
$selectcount = intval($count); } else {
$question->selectcount = 3; // default
} }
// Set "gradingtype" from $grading. // Set "gradingtype" option.
switch (strtoupper($grading)) { switch (strtoupper($gradingtype)) {
case 'ALL_OR_NOTHING': case 'ALL_OR_NOTHING':
$gradingtype = qtype_ordering_question::GRADING_ALL_OR_NOTHING; $question->gradingtype = qtype_ordering_question::GRADING_ALL_OR_NOTHING;
break; break;
case 'ABS': case 'ABS':
case 'ABSOLUTE': case 'ABSOLUTE':
case 'ABSOLUTE_POSITION': case 'ABSOLUTE_POSITION':
$gradingtype = qtype_ordering_question::GRADING_ABSOLUTE_POSITION; $question->gradingtype = qtype_ordering_question::GRADING_ABSOLUTE_POSITION;
break; break;
case 'REL': case 'REL':
case 'RELATIVE': case 'RELATIVE':
case 'RELATIVE_NEXT_EXCLUDE_LAST': case 'RELATIVE_NEXT_EXCLUDE_LAST':
$gradingtype = qtype_ordering_question::GRADING_RELATIVE_NEXT_EXCLUDE_LAST; $question->gradingtype = qtype_ordering_question::GRADING_RELATIVE_NEXT_EXCLUDE_LAST;
break; break;
case 'RELATIVE_NEXT_INCLUDE_LAST': case 'RELATIVE_NEXT_INCLUDE_LAST':
$gradingtype = qtype_ordering_question::GRADING_RELATIVE_NEXT_INCLUDE_LAST; $question->gradingtype = qtype_ordering_question::GRADING_RELATIVE_NEXT_INCLUDE_LAST;
break; break;
case 'RELATIVE_ONE_PREVIOUS_AND_NEXT': case 'RELATIVE_ONE_PREVIOUS_AND_NEXT':
$gradingtype = qtype_ordering_question::GRADING_RELATIVE_ONE_PREVIOUS_AND_NEXT; $question->gradingtype = qtype_ordering_question::GRADING_RELATIVE_ONE_PREVIOUS_AND_NEXT;
break; break;
case 'RELATIVE_ALL_PREVIOUS_AND_NEXT': case 'RELATIVE_ALL_PREVIOUS_AND_NEXT':
$gradingtype = qtype_ordering_question::GRADING_RELATIVE_ALL_PREVIOUS_AND_NEXT; $question->gradingtype = qtype_ordering_question::GRADING_RELATIVE_ALL_PREVIOUS_AND_NEXT;
break; break;
case 'LONGEST_ORDERED_SUBSET': case 'LONGEST_ORDERED_SUBSET':
$gradingtype = qtype_ordering_question::GRADING_LONGEST_ORDERED_SUBSET; $question->gradingtype = qtype_ordering_question::GRADING_LONGEST_ORDERED_SUBSET;
break; break;
case 'LONGEST_CONTIGUOUS_SUBSET': case 'LONGEST_CONTIGUOUS_SUBSET':
$gradingtype = qtype_ordering_question::GRADING_LONGEST_CONTIGUOUS_SUBSET; $question->gradingtype = qtype_ordering_question::GRADING_LONGEST_CONTIGUOUS_SUBSET;
break; break;
case 'RELATIVE_TO_CORRECT': case 'RELATIVE_TO_CORRECT':
$gradingtype = qtype_ordering_question::GRADING_RELATIVE_TO_CORRECT; $question->gradingtype = qtype_ordering_question::GRADING_RELATIVE_TO_CORRECT;
break; break;
default:
$question->gradingtype = qtype_ordering_question::GRADING_RELATIVE_NEXT_EXCLUDE_LAST;
} }
// Set "showgrading" from $show. // Set "showgrading" option.
switch (strtoupper($show)) { switch (strtoupper($showgrading)) {
case 'SHOW': case 'SHOW':
case 'TRUE': case 'TRUE':
case 'YES': case 'YES':
$showgrading = 1; $question->showgrading = 1;
break; break;
case 'HIDE': case 'HIDE':
case 'FALSE': case 'FALSE':
case 'NO': case 'NO':
$showgrading = 0; $question->showgrading = 0;
break; break;
default:
$question->showgrading = 1;
break;
} }
$question->layouttype = $layouttype; // Set "numberingstyle" option.
$question->selecttype = $selecttype; switch ($numberingstyle) {
$question->selectcount = $selectcount;
$question->gradingtype = $gradingtype; case 'none':
$question->showgrading = $showgrading; case '123':
case 'abc':
case 'ABC':
case 'iii':
case 'III':
$question->numberingstyle = $numberingstyle;
break;
default:
$question->numberingstyle = qtype_ordering_question::NUMBERING_STYLE_DEFAULT;
}
} }
/** /**
* Return the answer numbering style * Return the answer numbering style.
* This method is used by "tests/questiontype_test.php".
* @param $questiondata * @param $questiondata
* @return string * @return string
*/ */
public function get_answernumbering($questiondata) { public function get_numberingstyle($questiondata) {
return $questiondata->options->answernumbering; return $questiondata->options->numberingstyle;
}
/**
* @return array of the numbering styles supported. For each one, there
* should be a lang string answernumberingxxx in the qtype_ordering
* language file, and a case in the switch statement in number_in_style,
* and it should be listed in the definition of this column in install.xml.
*/
public static function get_numbering_styles() {
$styles = [];
$numberingoptions = ['abc', 'ABCD', '123', 'iii', 'IIII', \qtype_ordering_question::ANSWER_NUMBERING_DEFAULT];
foreach ($numberingoptions as $numberingoption) {
$styles[$numberingoption] =
get_string('answernumbering' . $numberingoption, 'qtype_ordering');
}
return $styles;
} }
} }

View file

@ -93,13 +93,15 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
// this represents the initial position of the items. // this represents the initial position of the items.
$md5keys = array(); $md5keys = array();
// Set layout class. // Set CSS classes for sortable list and sortable items.
$layoutclass = $question->get_ordering_layoutclass(); $sortablelist = 'sortablelist';
$activeclass = '';
if ($qa->get_state()->is_active()) { if ($qa->get_state()->is_active()) {
$activeclass = ' orderingactive'; $sortablelist .= ' orderingactive';
} }
$numberingclass = 'numbering' . $question->options->answernumbering; if ($sortableitem = $question->get_ordering_layoutclass()) {
$sortableitem .= ' ';
}
$sortableitem .= 'numbering' . $question->options->numberingstyle;
// Generate ordering items. // Generate ordering items.
foreach ($currentresponse as $position => $answerid) { foreach ($currentresponse as $position => $answerid) {
@ -115,7 +117,7 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
$printeditems = true; $printeditems = true;
$result .= html_writer::start_tag('div', array('class' => 'ablock', 'id' => $ablockid)); $result .= html_writer::start_tag('div', array('class' => 'ablock', 'id' => $ablockid));
$result .= html_writer::start_tag('div', array('class' => 'answer ordering')); $result .= html_writer::start_tag('div', array('class' => 'answer ordering'));
$result .= html_writer::start_tag('ul', array('class' => 'sortablelist' . $activeclass, 'id' => $sortableid)); $result .= html_writer::start_tag('ul', array('class' => $sortablelist, 'id' => $sortableid));
} }
// Set the CSS class and correctness img for this response. // Set the CSS class and correctness img for this response.
@ -137,7 +139,7 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
$img = ''; $img = '';
break; break;
} }
$class = trim("$class $layoutclass $numberingclass"); $class = trim("$class $sortableitem");
// Format the answer text. // Format the answer text.
$answer = $question->answers[$answerid]; $answer = $question->answers[$answerid];
@ -219,8 +221,8 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
$totalscore = 0; $totalscore = 0;
$totalmaxscore = 0; $totalmaxscore = 0;
$layoutclass = $question->get_ordering_layoutclass(); $sortableitem = $question->get_ordering_layoutclass();
$params = array('class' => $layoutclass); $params = array('class' => $sortableitem);
$scoredetails .= html_writer::tag('p', get_string('scoredetails', $plugin)); $scoredetails .= html_writer::tag('p', get_string('scoredetails', $plugin));
$scoredetails .= html_writer::start_tag('ol', array('class' => 'scoredetails')); $scoredetails .= html_writer::start_tag('ol', array('class' => 'scoredetails'));
@ -297,7 +299,7 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
} }
} }
if ($showcorrect) { if ($showcorrect) {
$layoutclass = $question->get_ordering_layoutclass(); $sortableitem = $question->get_ordering_layoutclass();
$output .= html_writer::tag('p', get_string('correctorder', 'qtype_ordering')); $output .= html_writer::tag('p', get_string('correctorder', 'qtype_ordering'));
$output .= html_writer::start_tag('ol', array('class' => 'correctorder')); $output .= html_writer::start_tag('ol', array('class' => 'correctorder'));
$correctresponse = $question->correctresponse; $correctresponse = $question->correctresponse;
@ -305,7 +307,7 @@ class qtype_ordering_renderer extends qtype_with_combined_feedback_renderer {
$answer = $question->answers[$answerid]; $answer = $question->answers[$answerid];
$answertext = $question->format_text($answer->answer, $answer->answerformat, $answertext = $question->format_text($answer->answer, $answer->answerformat,
$qa, 'question', 'answer', $answerid); $qa, 'question', 'answer', $answerid);
$output .= html_writer::tag('li', $answertext, array('class' => $layoutclass)); $output .= html_writer::tag('li', $answertext, array('class' => $sortableitem));
} }
$output .= html_writer::end_tag('ol'); $output .= html_writer::end_tag('ol');
} }

View file

@ -29,25 +29,25 @@
margin-left : 26px; /* The margin is needed for the list-style-type in numberingxxx classes */ margin-left : 26px; /* The margin is needed for the list-style-type in numberingxxx classes */
} }
.que.ordering ul.sortablelist li.sortableitem.numberingnone {
list-style-type : none;
margin-left: 0px;
}
.que.ordering ul.sortablelist li.sortableitem.numbering123 { .que.ordering ul.sortablelist li.sortableitem.numbering123 {
list-style-type : decimal; list-style-type : decimal;
} }
.que.ordering ul.sortablelist li.sortableitem.numberingabc { .que.ordering ul.sortablelist li.sortableitem.numberingabc {
list-style-type : lower-alpha; list-style-type : lower-alpha;
} }
.que.ordering ul.sortablelist li.sortableitem.numberingABCD { .que.ordering ul.sortablelist li.sortableitem.numberingABC {
list-style-type : upper-alpha; list-style-type : upper-alpha;
} }
.que.ordering ul.sortablelist li.sortableitem.numberingiii { .que.ordering ul.sortablelist li.sortableitem.numberingiii {
list-style-type : lower-roman; list-style-type : lower-roman;
} }
.que.ordering ul.sortablelist li.sortableitem.numberingIIII { .que.ordering ul.sortablelist li.sortableitem.numberingIII {
list-style-type : upper-roman; list-style-type : upper-roman;
} }
.que.ordering ul.sortablelist li.sortableitem.numberingnone {
list-style-type : none;
margin-left: 0px;
}
.que.ordering ul.sortablelist li.sortableitem:focus { .que.ordering ul.sortablelist li.sortableitem:focus {
border-color: #0a0; border-color: #0a0;

View file

@ -27,7 +27,6 @@ defined('MOODLE_INTERNAL') || die();
global $CFG; global $CFG;
require_once($CFG->dirroot . '/question/type/ordering/question.php'); require_once($CFG->dirroot . '/question/type/ordering/question.php');
/** /**
* Test helper for the ordering question type. * Test helper for the ordering question type.
* *
@ -70,7 +69,7 @@ class qtype_ordering_test_helper extends question_test_helper {
$q->options->selectcount = 0; $q->options->selectcount = 0;
$q->options->gradingtype = qtype_ordering_question::GRADING_RELATIVE_ALL_PREVIOUS_AND_NEXT; $q->options->gradingtype = qtype_ordering_question::GRADING_RELATIVE_ALL_PREVIOUS_AND_NEXT;
$q->options->showgrading = true; $q->options->showgrading = true;
$q->options->answernumbering = qtype_ordering_question::ANSWER_NUMBERING_DEFAULT; $q->options->numberingstyle = qtype_ordering_question::NUMBERING_STYLE_DEFAULT;
return $q; return $q;
} }
@ -130,7 +129,7 @@ class qtype_ordering_test_helper extends question_test_helper {
$form->selectcount = 0; $form->selectcount = 0;
$form->gradingtype = qtype_ordering_question::GRADING_RELATIVE_ALL_PREVIOUS_AND_NEXT; $form->gradingtype = qtype_ordering_question::GRADING_RELATIVE_ALL_PREVIOUS_AND_NEXT;
$form->showgrading = true; $form->showgrading = true;
$form->answernumbering = qtype_ordering_question::ANSWER_NUMBERING_DEFAULT; $form->numberingstyle = qtype_ordering_question::NUMBERING_STYLE_DEFAULT;
$form->countanswers = 6; $form->countanswers = 6;
$form->answer = [ $form->answer = [
@ -175,7 +174,7 @@ class qtype_ordering_test_helper extends question_test_helper {
$questiondata->options->selectcount = 0; $questiondata->options->selectcount = 0;
$questiondata->options->gradingtype = qtype_ordering_question::GRADING_RELATIVE_ALL_PREVIOUS_AND_NEXT; $questiondata->options->gradingtype = qtype_ordering_question::GRADING_RELATIVE_ALL_PREVIOUS_AND_NEXT;
$questiondata->options->showgrading = true; $questiondata->options->showgrading = true;
$questiondata->options->answernumbering = qtype_ordering_question::ANSWER_NUMBERING_DEFAULT; $questiondata->options->numberingstyle = qtype_ordering_question::NUMBERING_STYLE_DEFAULT;
$questiondata->options->answers = [ $questiondata->options->answers = [
13 => $this->make_answer(13, 'Modular', FORMAT_HTML, 1), 13 => $this->make_answer(13, 'Modular', FORMAT_HTML, 1),

View file

@ -29,7 +29,6 @@ defined('MOODLE_INTERNAL') || die();
global $CFG; global $CFG;
require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
/** /**
* Unit tests for the ordering question definition class. * Unit tests for the ordering question definition class.
* *

View file

@ -31,7 +31,6 @@ require_once($CFG->dirroot . '/question/type/ordering/questiontype.php');
require_once($CFG->dirroot . '/question/type/edit_question_form.php'); require_once($CFG->dirroot . '/question/type/edit_question_form.php');
require_once($CFG->dirroot . '/question/type/ordering/edit_ordering_form.php'); require_once($CFG->dirroot . '/question/type/ordering/edit_ordering_form.php');
/** /**
* Unit tests for the ordering question type class. * Unit tests for the ordering question type class.
* *
@ -161,35 +160,35 @@ class qtype_ordering_test extends advanced_testcase {
$this->assertEquals($expectedresponseclasses, $possibleresponses, '', 0.0000005); $this->assertEquals($expectedresponseclasses, $possibleresponses, '', 0.0000005);
} }
public function test_get_answernumbering() { public function test_get_numberingstyle() {
$questiondata = test_question_maker::get_question_data('ordering'); $questiondata = test_question_maker::get_question_data('ordering');
$expected = qtype_ordering_question::ANSWER_NUMBERING_DEFAULT; $expected = qtype_ordering_question::NUMBERING_STYLE_DEFAULT;
$actual = $this->qtype->get_answernumbering($questiondata); $actual = $this->qtype->get_numberingstyle($questiondata);
$this->assertEquals($expected, $actual); $this->assertEquals($expected, $actual);
$questiondata->options->answernumbering = 'abc'; $questiondata->options->numberingstyle = 'abc';
$expected = 'abc'; $expected = 'abc';
$actual = $this->qtype->get_answernumbering($questiondata); $actual = $this->qtype->get_numberingstyle($questiondata);
$this->assertEquals($expected, $actual); $this->assertEquals($expected, $actual);
$questiondata->options->answernumbering = 'ABCD'; $questiondata->options->numberingstyle = 'ABCD';
$expected = 'ABCD'; $expected = 'ABCD';
$actual = $this->qtype->get_answernumbering($questiondata); $actual = $this->qtype->get_numberingstyle($questiondata);
$this->assertEquals($expected, $actual); $this->assertEquals($expected, $actual);
$questiondata->options->answernumbering = '123'; $questiondata->options->numberingstyle = '123';
$expected = '123'; $expected = '123';
$actual = $this->qtype->get_answernumbering($questiondata); $actual = $this->qtype->get_numberingstyle($questiondata);
$this->assertEquals($expected, $actual); $this->assertEquals($expected, $actual);
$questiondata->options->answernumbering = 'iii'; $questiondata->options->numberingstyle = 'iii';
$expected = 'iii'; $expected = 'iii';
$actual = $this->qtype->get_answernumbering($questiondata); $actual = $this->qtype->get_numberingstyle($questiondata);
$this->assertEquals($expected, $actual); $this->assertEquals($expected, $actual);
$questiondata->options->answernumbering = 'III'; $questiondata->options->numberingstyle = 'III';
$expected = 'III'; $expected = 'III';
$actual = $this->qtype->get_answernumbering($questiondata); $actual = $this->qtype->get_numberingstyle($questiondata);
$this->assertEquals($expected, $actual); $this->assertEquals($expected, $actual);
} }

View file

@ -29,7 +29,6 @@ global $CFG;
require_once($CFG->dirroot . '/question/engine/tests/helpers.php'); require_once($CFG->dirroot . '/question/engine/tests/helpers.php');
require_once($CFG->dirroot . '/question/type/ddwtos/tests/helper.php'); require_once($CFG->dirroot . '/question/type/ddwtos/tests/helper.php');
/** /**
* Unit tests for the ordering question type. * Unit tests for the ordering question type.
* *

View file

@ -29,5 +29,5 @@ $plugin->cron = 0;
$plugin->component = 'qtype_ordering'; $plugin->component = 'qtype_ordering';
$plugin->maturity = MATURITY_STABLE; $plugin->maturity = MATURITY_STABLE;
$plugin->requires = 2015051100; // Moodle 2.9. $plugin->requires = 2015051100; // Moodle 2.9.
$plugin->version = 2019062000; $plugin->version = 2019071292;
$plugin->release = '2019-03-06 (89)'; $plugin->release = '2019-07-12 (92)';