Skip to content

Commit c4c2efd

Browse files
author
hieuvu
committed
Matrix add support for sub-questions to be lists
1 parent c2c88a7 commit c4c2efd

17 files changed

+118
-24
lines changed

.github/workflows/ci.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,6 @@ jobs:
110110
run: moodle-plugin-ci mustache
111111

112112
- name: Grunt
113-
if: ${{ matrix.moodle-branch == 'MOODLE_401_STABLE' }}
114113
run: moodle-plugin-ci grunt --max-lint-warnings 0
115114

116115
- name: PHPUnit tests

backup/moodle2/backup_qtype_oumatrix_plugin.class.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ protected function define_question_plugin_structure(): backup_plugin_element {
4040
// Now create the qtype own structures.
4141
$matrix = new backup_nested_element('oumatrix', ['id'], ['inputtype', 'grademethod', 'shuffleanswers',
4242
'correctfeedback', 'correctfeedbackformat', 'partiallycorrectfeedback', 'partiallycorrectfeedbackformat',
43-
'incorrectfeedback', 'incorrectfeedbackformat', 'shownumcorrect',
43+
'incorrectfeedback', 'incorrectfeedbackformat', 'shownumcorrect', 'questionnumbering',
4444
]);
4545
$pluginwrapper->add_child($matrix);
4646

db/install.xml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="UTF-8" ?>
2-
<XMLDB PATH="question/type/oumatrix/db" VERSION="20230621" COMMENT="XMLDB file for Moodle question/type/oumatrix"
3-
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
2+
<XMLDB PATH="question/type/oumatrix/db" VERSION="20250903" COMMENT="XMLDB file for Moodle question/type/oumatrix"
3+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4+
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
55
>
66
<TABLES>
77
<TABLE NAME="qtype_oumatrix_options" COMMENT="Options for OU matrix question">
@@ -18,6 +18,7 @@
1818
<FIELD NAME="incorrectfeedback" TYPE="text" LENGTH="small" NOTNULL="true" SEQUENCE="false" COMMENT="Feedback shown for any incorrect response."/>
1919
<FIELD NAME="incorrectfeedbackformat" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false"/>
2020
<FIELD NAME="shownumcorrect" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false"/>
21+
<FIELD NAME="questionnumbering" TYPE="char" LENGTH="10" NOTNULL="true" DEFAULT="none" SEQUENCE="false"/>
2122
</FIELDS>
2223
<KEYS>
2324
<KEY NAME="primary" TYPE="primary" FIELDS="id"/>

db/upgrade.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,22 @@
3030
*/
3131
function xmldb_qtype_oumatrix_upgrade($oldversion) {
3232
global $DB;
33-
33+
$dbman = $DB->get_manager();
3434
// Put any upgrade step following this.
35+
if ($oldversion < 2025090200) {
36+
37+
// Define field questionnumbering to be added to qtype_oumatrix_options.
38+
$table = new xmldb_table('qtype_oumatrix_options');
39+
$field = new xmldb_field('questionnumbering', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, 'none', 'shownumcorrect');
40+
41+
// Conditionally launch add field questionnumbering.
42+
if (!$dbman->field_exists($table, $field)) {
43+
$dbman->add_field($table, $field);
44+
}
45+
46+
// Oumatrix savepoint reached.
47+
upgrade_plugin_savepoint(true, 2025090200, 'qtype', 'oumatrix');
48+
}
3549

3650
return true;
3751
}

edit_oumatrix_form.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,13 @@
1414
// You should have received a copy of the GNU General Public License
1515
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
1616

17+
defined('MOODLE_INTERNAL') || die();
18+
1719
use qtype_oumatrix\row;
1820
use qtype_oumatrix\column;
1921
use qtype_oumatrix\utils;
22+
require_once($CFG->dirroot . '/question/type/multichoice/questiontype.php');
23+
2024
/**
2125
* Editing form for the oumatrix question type.
2226
*
@@ -110,6 +114,10 @@ protected function definition_inner($mform) {
110114
$mform->setDefault('shuffleanswers', $this->get_default_value('shuffleanswers',
111115
get_config('qtype_oumatrix', 'shuffleanswers')));
112116

117+
$mform->addElement('select', 'questionnumbering',
118+
get_string('questionnumbering', 'qtype_oumatrix'), qtype_multichoice::get_numbering_styles());
119+
$mform->setDefault('questionnumbering', 'none');
120+
113121
// Add update field.
114122
$mform->addElement('submit', 'updateform', get_string('updateform', 'qtype_oumatrix'));
115123
$mform->registerNoSubmitButton('updateform');
@@ -236,6 +244,7 @@ protected function data_preprocessing_options(stdClass $question): object {
236244
$question->inputtype = $question->options->inputtype;
237245
$question->grademethod = $question->options->grademethod;
238246
$question->shuffleanswers = $question->options->shuffleanswers;
247+
$question->questionnumbering = $question->options->questionnumbering;
239248
$question->shownumcorrect = $question->options->shownumcorrect;
240249
return $question;
241250
}

lang/en/qtype_oumatrix.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@
6262
$string['privacy:preference:inputtype'] = 'Whether the \'One or multiple answers?\' should be \'Single choice\' or \'Multiple response\'.';
6363
$string['privacy:preference:penalty'] = 'The penalty for each incorrect try when questions are run using the \'Interactive with multiple tries\' or \'Adaptive mode\' behaviour.';
6464
$string['privacy:preference:shuffleanswers'] = 'Whether the answers should be automatically shuffled.';
65+
$string['questionnumbering'] = 'Number the sub-questions?';
6566
$string['regradeissuenumcolumnschanged'] = 'The number of columns has changed.';
6667
$string['regradeissuenumrowschanged'] = 'The number of rows has changed.';
6768
$string['row'] = 'Row {$a}';

question.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ abstract class qtype_oumatrix_base extends question_graded_automatically {
3838
/** @var int whether the rows/columns or both should be shuffled. */
3939
public int $shuffleanswers;
4040

41+
/** @var string 'abc', 'ABCD', '123', etc. or '' for no numbering. */
42+
public string $questionnumbering;
43+
4144
/** @var string 'All or none' or 'partial' grading method for multiple response. */
4245
public string $grademethod;
4346

questiontype.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ public function save_defaults_for_new_questions(stdClass $fromform): void {
6060
$this->set_default_value('inputtype', $fromform->inputtype);
6161
$this->set_default_value('grademethod', $fromform->grademethod);
6262
$this->set_default_value('shuffleanswers', $fromform->shuffleanswers);
63+
$this->set_default_value('questionnumbering', $fromform->questionnumbering);
6364
$this->set_default_value('shownumcorrect', $fromform->shownumcorrect);
6465
}
6566

@@ -74,6 +75,7 @@ public function save_question_options($question) {
7475
$options->inputtype = '';
7576
$options->grademethod = '';
7677
$options->shuffleanswers = 0;
78+
$options->questionnumbering = 'none';
7779
$options->correctfeedback = '';
7880
$options->partiallycorrectfeedback = '';
7981
$options->incorrectfeedback = '';
@@ -84,6 +86,7 @@ public function save_question_options($question) {
8486
$options->inputtype = $question->inputtype;
8587
$options->grademethod = $question->grademethod;
8688
$options->shuffleanswers = $question->shuffleanswers;
89+
$options->questionnumbering = $question->questionnumbering;
8790
$options = $this->save_combined_feedback_helper($options, $question, $context, true);
8891
$DB->update_record('qtype_oumatrix_options', $options);
8992

@@ -188,6 +191,7 @@ protected function initialise_question_instance(question_definition $question, $
188191
parent::initialise_question_instance($question, $questiondata);
189192
$question->grademethod = $questiondata->options->grademethod;
190193
$question->shuffleanswers = $questiondata->options->shuffleanswers;
194+
$question->questionnumbering = $questiondata->options->questionnumbering;
191195
$this->initialise_question_columns($question, $questiondata);
192196
$this->initialise_question_rows($question, $questiondata);
193197
$this->initialise_combined_feedback($question, $questiondata, true);
@@ -393,6 +397,9 @@ public function import_from_xml($data, $question, qformat_xml $format, $extra =
393397
$format->getpath($data, ['#', 'inputtype'], 'single'));
394398
$question->grademethod = $format->import_text(
395399
$format->getpath($data, ['#', 'grademethod'], 'partial'));
400+
$question->questionnumbering = $format->getpath($data, ['#', 'questionnumbering'], '')
401+
? $format->import_text($format->getpath($data, ['#', 'questionnumbering'], '')) : 'none';
402+
396403
$shuffleanswers = $format->getpath($data, ['#', 'shuffleanswers', 0, '#'], 1);
397404
$question->shuffleanswers = $shuffleanswers === 'false' || $shuffleanswers === 'true'
398405
? $format->trans_single($shuffleanswers) : $shuffleanswers;
@@ -487,6 +494,9 @@ public function export_to_xml($question, qformat_xml $format, $extra = null) {
487494
$output .= ' <grademethod>' . $format->xml_escape($question->options->grademethod)
488495
. "</grademethod>\n";
489496
$output .= " <shuffleanswers>" . $question->options->shuffleanswers . "</shuffleanswers>\n";
497+
$output .= " <questionnumbering>" . $format->xml_escape(
498+
$question->options->questionnumbering) . "</questionnumbering>\n";
499+
490500

491501
// Export columns data.
492502
$output .= " <columns>\n";

renderer.php

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
*/
2424

2525
use qtype_oumatrix\column;
26+
use question_utils;
2627

2728
defined('MOODLE_INTERNAL') || die();
2829

@@ -168,14 +169,17 @@ public function matrix_table(question_attempt $qa, question_display_options $opt
168169
$inputattributes['type'] = $this->get_input_type();
169170

170171
// Adding table rows for the sub-questions.
172+
$columncount = 0;
171173
foreach ($question->get_roworder($qa) as $rowkey => $rowid) {
172174

173175
$row = $question->rows[$rowid];
174176
$rownewid = 'row'. $rowkey;
175177
$feedback = '';
176178

177179
$table .= html_writer::start_tag('tr');
178-
$table .= html_writer::tag('th', html_writer::span(format_string($row->name), '', ['id' => $rownewid]),
180+
$table .= html_writer::tag('th', html_writer::span(
181+
$this->number_in_style($columncount, $question->questionnumbering) .
182+
format_string($row->name), '', ['id' => $rownewid]),
179183
['class' => 'subquestion align-middle', 'scope' => 'row']);
180184

181185
foreach ($question->get_colorder($qa) as $colkey => $colid) {
@@ -222,6 +226,7 @@ public function matrix_table(question_attempt $qa, question_display_options $opt
222226
$table .= html_writer::tag('td', $feedback);
223227
}
224228
$table .= html_writer::end_tag('tr');
229+
$columncount++;
225230
}
226231

227232
$table .= html_writer::end_tag('table');
@@ -253,6 +258,48 @@ protected function correct_choices(array $right): string {
253258
return "";
254259
}
255260
}
261+
262+
/**
263+
* Renders a number in a particular style.
264+
*
265+
* @param int $num The number, starting at 0.
266+
* @param string $style The style to render the number in.
267+
* @return string the number $num in the requested style.
268+
*/
269+
protected function number_in_style(int $num, string $style): string {
270+
switch($style) {
271+
case 'abc':
272+
$number = chr(ord('a') + $num);
273+
break;
274+
case 'ABCD':
275+
$number = chr(ord('A') + $num);
276+
break;
277+
case '123':
278+
$number = $num + 1;
279+
break;
280+
case 'iii':
281+
$number = question_utils::int_to_roman($num + 1);
282+
break;
283+
case 'IIII':
284+
$number = strtoupper(question_utils::int_to_roman($num + 1));
285+
break;
286+
case 'none':
287+
return '';
288+
default:
289+
return 'ERR';
290+
}
291+
return $this->number_html($number);
292+
}
293+
294+
/**
295+
* Returns the HTML to display before the number in a question.
296+
*
297+
* @param string $qnum The question number, in whatever format is required.
298+
* @return string HTML to display before the question number.
299+
*/
300+
protected function number_html(string $qnum): string {
301+
return $qnum . '. ';
302+
}
256303
}
257304

258305
/**

styles.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
background-color: rgba(0, 0, 0, 0.03);
1212
}
1313
.que.oumatrix .answer .generaltable tbody tr:nth-of-type(odd) {
14-
background-color: #FFFFFF;
14+
background-color: #fff;
1515
}
1616

1717
/* Editing form. */

0 commit comments

Comments
 (0)