From 997a407b3793719be1bcbb4460bfb69a58bfb8fd Mon Sep 17 00:00:00 2001 From: Mahmoud Kassaei Date: Fri, 20 Nov 2020 16:44:16 +0000 Subject: [PATCH] MDL-68597 qtype_essay: add word min/max for online text input --- .../backup_qtype_essay_plugin.class.php | 7 +-- .../restore_qtype_essay_plugin.class.php | 8 +++ question/type/essay/db/install.xml | 2 + question/type/essay/db/upgrade.php | 25 ++++++++ question/type/essay/edit_essay_form.php | 54 +++++++++++++++++ question/type/essay/lang/en/qtype_essay.php | 11 ++++ question/type/essay/question.php | 53 +++++++++++++++++ question/type/essay/questiontype.php | 4 ++ question/type/essay/renderer.php | 6 ++ .../tests/behat/min_max_text_input.feature | 58 +++++++++++++++++++ .../tests/fixtures/testquestion.moodle.xml | 2 + question/type/essay/tests/helper.php | 8 +++ question/type/essay/tests/question_test.php | 55 +++++++++++++++++- question/type/essay/version.php | 2 +- 14 files changed, 289 insertions(+), 6 deletions(-) create mode 100644 question/type/essay/tests/behat/min_max_text_input.feature diff --git a/question/type/essay/backup/moodle2/backup_qtype_essay_plugin.class.php b/question/type/essay/backup/moodle2/backup_qtype_essay_plugin.class.php index b491217316e..6215989b129 100644 --- a/question/type/essay/backup/moodle2/backup_qtype_essay_plugin.class.php +++ b/question/type/essay/backup/moodle2/backup_qtype_essay_plugin.class.php @@ -49,10 +49,9 @@ class backup_qtype_essay_plugin extends backup_qtype_plugin { // Now create the qtype own structures. $essay = new backup_nested_element('essay', array('id'), array( - 'responseformat', 'responserequired', 'responsefieldlines', - 'attachments', 'attachmentsrequired', 'graderinfo', - 'graderinfoformat', 'responsetemplate', 'responsetemplateformat', - 'filetypeslist', 'maxbytes')); + 'responseformat', 'responserequired', 'responsefieldlines', 'minwordlimit', 'maxwordlimit', + 'attachments', 'attachmentsrequired', 'graderinfo', 'graderinfoformat', 'responsetemplate', + 'responsetemplateformat', 'filetypeslist', 'maxbytes')); // Now the own qtype tree. $pluginwrapper->add_child($essay); diff --git a/question/type/essay/backup/moodle2/restore_qtype_essay_plugin.class.php b/question/type/essay/backup/moodle2/restore_qtype_essay_plugin.class.php index d806e4b1ff7..11919b2e0fd 100644 --- a/question/type/essay/backup/moodle2/restore_qtype_essay_plugin.class.php +++ b/question/type/essay/backup/moodle2/restore_qtype_essay_plugin.class.php @@ -61,6 +61,12 @@ class restore_qtype_essay_plugin extends restore_qtype_plugin { if (!isset($data->responserequired)) { $data->responserequired = 1; } + if (!isset($data->minwordlimit)) { + $data->minwordlimit = null; + } + if (!isset($data->maxwordlimit)) { + $data->maxwordlimit = null; + } if (!isset($data->attachmentsrequired)) { $data->attachmentsrequired = 0; } @@ -111,6 +117,8 @@ class restore_qtype_essay_plugin extends restore_qtype_plugin { $defaultoptions->responseformat = 'editor'; $defaultoptions->responserequired = 1; $defaultoptions->responsefieldlines = 15; + $defaultoptions->minwordlimit = null; + $defaultoptions->maxwordlimit = null; $defaultoptions->attachments = 0; $defaultoptions->attachmentsrequired = 0; $defaultoptions->graderinfo = ''; diff --git a/question/type/essay/db/install.xml b/question/type/essay/db/install.xml index 4177509d6fe..ea3ab5c066e 100644 --- a/question/type/essay/db/install.xml +++ b/question/type/essay/db/install.xml @@ -11,6 +11,8 @@ + + diff --git a/question/type/essay/db/upgrade.php b/question/type/essay/db/upgrade.php index 6ee1f49d5e1..480d0970aaa 100644 --- a/question/type/essay/db/upgrade.php +++ b/question/type/essay/db/upgrade.php @@ -63,5 +63,30 @@ function xmldb_qtype_essay_upgrade($oldversion) { // Essay savepoint reached. upgrade_plugin_savepoint(true, 2021052501, 'qtype', 'essay'); } + + if ($oldversion < 2021052502) { + + // Define field minwordlimit to be added to qtype_essay_options. + $table = new xmldb_table('qtype_essay_options'); + $field = new xmldb_field('minwordlimit', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'responsefieldlines'); + + // Conditionally launch add field minwordlimit. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Define field maxwordlimit to be added to qtype_essay_options. + $table = new xmldb_table('qtype_essay_options'); + $field = new xmldb_field('maxwordlimit', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'minwordlimit'); + + // Conditionally launch add field maxwordlimit. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Essay savepoint reached. + upgrade_plugin_savepoint(true, 2021052502, 'qtype', 'essay'); + } + return true; } diff --git a/question/type/essay/edit_essay_form.php b/question/type/essay/edit_essay_form.php index 68f16e83e6d..d86cb78fb18 100644 --- a/question/type/essay/edit_essay_form.php +++ b/question/type/essay/edit_essay_form.php @@ -55,6 +55,26 @@ class qtype_essay_edit_form extends question_edit_form { $mform->setDefault('responsefieldlines', 15); $mform->disabledIf('responsefieldlines', 'responseformat', 'eq', 'noinline'); + // Create a text box that can be enabled/disabled for max/min word limits options. + $wordlimitoptions = ['size' => '6', 'maxlength' => '6']; + $mingrp[] = $mform->createElement('text', 'minwordlimit', '', $wordlimitoptions); + $mform->setType('minwordlimit', PARAM_INT); + $mingrp[] = $mform->createElement('checkbox', 'minwordenabled', '', get_string('enable')); + $mform->setDefault('minwordenabled', 0); + $mform->addGroup($mingrp, 'mingroup', get_string('minwordlimit', 'qtype_essay'), ' ', false); + $mform->addHelpButton('mingroup', 'minwordlimit', 'qtype_essay'); + $mform->disabledIf('minwordlimit', 'minwordenabled', 'notchecked'); + $mform->hideIf('mingroup', 'responserequired', '0'); + + $maxgrp[] = $mform->createElement('text', 'maxwordlimit', '', $wordlimitoptions); + $mform->setType('maxwordlimit', PARAM_INT); + $maxgrp[] = $mform->createElement('checkbox', 'maxwordenabled', '', get_string('enable')); + $mform->setDefault('maxwordenabled', 0); + $mform->addGroup($maxgrp, 'maxgroup', get_string('maxwordlimit', 'qtype_essay'), ' ', false); + $mform->addHelpButton('maxgroup', 'maxwordlimit', 'qtype_essay'); + $mform->disabledIf('maxwordlimit', 'maxwordenabled', 'notchecked'); + $mform->hideIf('maxgroup', 'responserequired', '0'); + $mform->addElement('select', 'attachments', get_string('allowattachments', 'qtype_essay'), $qtype->attachment_options()); $mform->setDefault('attachments', 0); @@ -94,6 +114,10 @@ class qtype_essay_edit_form extends question_edit_form { $question->responseformat = $question->options->responseformat; $question->responserequired = $question->options->responserequired; $question->responsefieldlines = $question->options->responsefieldlines; + $question->minwordenabled = $question->options->minwordlimit ? 1 : 0; + $question->minwordlimit = $question->options->minwordlimit; + $question->maxwordenabled = $question->options->maxwordlimit ? 1 : 0; + $question->maxwordlimit = $question->options->maxwordlimit; $question->attachments = $question->options->attachments; $question->attachmentsrequired = $question->options->attachmentsrequired; $question->filetypeslist = $question->options->filetypeslist; @@ -142,6 +166,36 @@ class qtype_essay_edit_form extends question_edit_form { $errors['attachmentsrequired'] = get_string('mustrequirefewer', 'qtype_essay'); } + if ($fromform['responserequired']) { + if (isset($fromform['minwordenabled'])) { + if (!is_numeric($fromform['minwordlimit'])) { + $errors['mingroup'] = get_string('err_numeric', 'form'); + } + if ($fromform['minwordlimit'] < 0) { + $errors['mingroup'] = get_string('err_minwordlimitnegative', 'qtype_essay'); + } + if (!$fromform['minwordlimit']) { + $errors['mingroup'] = get_string('err_minwordlimit', 'qtype_essay'); + } + } + if (isset($fromform['maxwordenabled'])) { + if (!is_numeric($fromform['maxwordlimit'])) { + $errors['maxgroup'] = get_string('err_numeric', 'form'); + } + if ($fromform['maxwordlimit'] < 0) { + $errors['maxgroup'] = get_string('err_maxwordlimitnegative', 'qtype_essay'); + } + if (!$fromform['maxwordlimit']) { + $errors['maxgroup'] = get_string('err_maxwordlimit', 'qtype_essay'); + } + } + if (isset($fromform['maxwordenabled']) && isset($fromform['minwordenabled'])) { + if ($fromform['maxwordlimit'] < $fromform['minwordlimit'] && + $fromform['maxwordlimit'] > 0 && $fromform['minwordlimit'] > 0) { + $errors['maxgroup'] = get_string('err_maxminmismatch', 'qtype_essay'); + } + } + } return $errors; } diff --git a/question/type/essay/lang/en/qtype_essay.php b/question/type/essay/lang/en/qtype_essay.php index 1ee63782c9a..39cdf85f0e5 100644 --- a/question/type/essay/lang/en/qtype_essay.php +++ b/question/type/essay/lang/en/qtype_essay.php @@ -29,6 +29,11 @@ $string['allowattachments'] = 'Allow attachments'; $string['attachmentsoptional'] = 'Attachments are optional'; $string['attachmentsrequired'] = 'Require attachments'; $string['attachmentsrequired_help'] = 'This option specifies the minimum number of attachments required for a response to be considered gradable.'; +$string['err_maxminmismatch'] = 'Maximum world limit must be greater than minimum word limit'; +$string['err_maxwordlimit'] = 'Maximum word limit is enabled but is not set'; +$string['err_maxwordlimitnegative'] = 'Maximum word limit cannot be a negative number'; +$string['err_minwordlimit'] = 'Minimum word limit is enabled but is not set'; +$string['err_minwordlimitnegative'] = 'Minimum word limit cannot be a negative number'; $string['formateditor'] = 'HTML editor'; $string['formateditorfilepicker'] = 'HTML editor with file picker'; $string['formatmonospaced'] = 'Plain text, monospaced font'; @@ -37,6 +42,12 @@ $string['formatplain'] = 'Plain text'; $string['graderinfo'] = 'Information for graders'; $string['graderinfoheader'] = 'Grader Information'; $string['maxbytes'] = 'Maximum file size'; +$string['maxwordlimit'] = 'Maximum word limit'; +$string['maxwordlimit_help'] = 'If the response requires that students enter text, this is the maximum number of words that each student will be allowed to submit.'; +$string['maxwordlimitboundary'] = 'The required maximum word limit ({$a} words) has been exceeded for this essay. Please amend your response and try again.'; +$string['minwordlimit'] = 'Minimum word limit'; +$string['minwordlimit_help'] = 'If the response requires that students enter text, this is the minimum number of words that each student will be allowed to submit.'; +$string['minwordlimitboundary'] = 'The required minimum word limit ({$a} words) has not been reached for this essay. Please amend your response and try again.'; $string['mustattach'] = 'When "No online text" is selected, or responses are optional, you must allow at least one attachment.'; $string['mustrequire'] = 'When "No online text" is selected, or responses are optional, you must require at least one attachment.'; $string['mustrequirefewer'] = 'You cannot require more attachments than you allow.'; diff --git a/question/type/essay/question.php b/question/type/essay/question.php index 8f1f03a2dda..c14af97a8d3 100644 --- a/question/type/essay/question.php +++ b/question/type/essay/question.php @@ -42,6 +42,13 @@ class qtype_essay_question extends question_with_responses { public $responserequired; public $responsefieldlines; + + /** @var int indicates whether the minimum number of words required */ + public $minwordlimit; + + /** @var int indicates whether the maximum number of words required */ + public $maxwordlimit; + public $attachments; /** @var int maximum file size in bytes */ @@ -107,6 +114,13 @@ class qtype_essay_question extends question_with_responses { public function is_complete_response(array $response) { // Determine if the given response has online text and attachments. $hasinlinetext = array_key_exists('answer', $response) && ($response['answer'] !== ''); + + // If there is a response and min/max word limit is set in the form then validate the number of words in response. + if ($hasinlinetext) { + if ($this->check_input_word_count($response['answer'])) { + return false; + } + } $hasattachments = array_key_exists('attachments', $response) && $response['attachments'] instanceof question_response_files; @@ -140,6 +154,20 @@ class qtype_essay_question extends question_with_responses { return $hascontent && $meetsinlinereq && $meetsattachmentreq; } + /** + * Return null if is_complete_response() returns true + * otherwise, return the minmax-limit error message + * + * @param array $response + * @return string + */ + public function get_validation_error(array $response) { + if ($this->is_complete_response($response)) { + return ''; + } + return $this->check_input_word_count($response['answer']); + } + public function is_gradable_response(array $response) { // Determine if the given response has online text and attachments. if (array_key_exists('answer', $response) && ($response['answer'] !== '')) { @@ -212,4 +240,29 @@ class qtype_essay_question extends question_with_responses { return $settings; } + + /** + * Check the input word count and return a message to user + * when the number of words are outside the boundary settings. + * + * @param string $responsestring + * @return string|null + .*/ + private function check_input_word_count($responsestring) { + if (!$this->responserequired) { + return null; + } + if ((isset($this->minwordlimit) && $this->minwordlimit > 0) || + (isset($this->maxwordlimit) && $this->maxwordlimit > 0)) { + // Count the number of words in the response string. + $responsewords = count_words($responsestring); + if (isset($this->minwordlimit) && $this->minwordlimit > $responsewords) { + return get_string('minwordlimitboundary', 'qtype_essay', $this->minwordlimit); + } + if (isset($this->maxwordlimit) && $this->maxwordlimit < $responsewords) { + return get_string('maxwordlimitboundary', 'qtype_essay', $this->maxwordlimit); + } + } + return null; + } } diff --git a/question/type/essay/questiontype.php b/question/type/essay/questiontype.php index 5420a249e25..4851b29fe0c 100644 --- a/question/type/essay/questiontype.php +++ b/question/type/essay/questiontype.php @@ -65,6 +65,8 @@ class qtype_essay extends question_type { $options->responseformat = $formdata->responseformat; $options->responserequired = $formdata->responserequired; $options->responsefieldlines = $formdata->responsefieldlines; + $options->minwordlimit = isset($formdata->minwordenabled) ? $formdata->minwordlimit : 0; + $options->maxwordlimit = isset($formdata->maxwordenabled) ? $formdata->maxwordlimit : 0; $options->attachments = $formdata->attachments; $options->attachmentsrequired = $formdata->attachmentsrequired; if (!isset($formdata->filetypeslist)) { @@ -86,6 +88,8 @@ class qtype_essay extends question_type { $question->responseformat = $questiondata->options->responseformat; $question->responserequired = $questiondata->options->responserequired; $question->responsefieldlines = $questiondata->options->responsefieldlines; + $question->minwordlimit = $questiondata->options->minwordlimit; + $question->maxwordlimit = $questiondata->options->maxwordlimit; $question->attachments = $questiondata->options->attachments; $question->attachmentsrequired = $questiondata->options->attachmentsrequired; $question->graderinfo = $questiondata->options->graderinfo; diff --git a/question/type/essay/renderer.php b/question/type/essay/renderer.php index 9aa0099c837..58ba2179a53 100644 --- a/question/type/essay/renderer.php +++ b/question/type/essay/renderer.php @@ -73,6 +73,12 @@ class qtype_essay_renderer extends qtype_renderer { $result .= html_writer::start_tag('div', array('class' => 'ablock')); $result .= html_writer::tag('div', $answer, array('class' => 'answer')); + + // If there is a response and min/max word limit is set in the form then check the response word count. + if ($qa->get_state() == question_state::$invalid) { + $result .= html_writer::nonempty_tag('div', + $question->get_validation_error(['answer' => $answer]), ['class' => 'validationerror']); + } $result .= html_writer::tag('div', $files, array('class' => 'attachments')); $result .= html_writer::end_tag('div'); diff --git a/question/type/essay/tests/behat/min_max_text_input.feature b/question/type/essay/tests/behat/min_max_text_input.feature new file mode 100644 index 00000000000..44105c59a41 --- /dev/null +++ b/question/type/essay/tests/behat/min_max_text_input.feature @@ -0,0 +1,58 @@ +@qtype @qtype_essay +Feature: In an essay question, let the question author choose the min/max number of words for input text +In order to constrain student submissions for marking +As a teacher +I need to choose the appropriate minimum and/or maximum number of words for input text + Background: + Given the following "users" exist: + | username | firstname | lastname | email | + | teacher1 | T1 | Teacher1 | teacher1@moodle.com | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | teacher1 | C1 | editingteacher | + And the following "question categories" exist: + | contextlevel | reference | name | + | Course | C1 | Test questions | + And the following "questions" exist: + | questioncategory | qtype | name | template | minwordlimit | maxwordlimit | + | Test questions | essay | essay-min-max | editor | null | null | + Given I log in as "teacher1" + And I am on "Course 1" course homepage + And I navigate to "Question bank" in current page administration + + @javascript + Scenario: Minimum/Maximum word limit are enabled but not set. + Given I choose "Edit question" action for "essay-min-max" in the question bank + When I set the field "minwordenabled" to "1" + And I click on "Save changes" "button" + Then I should see "Minimum word limit is enabled but is not set" + + @javascript + Scenario: Minimum/Maximum word limit cannot be set to a negative number. + Given I choose "Edit question" action for "essay-min-max" in the question bank + And I set the field "minwordenabled" to "1" + When I set the field "id_minwordlimit" to "-10" + And I click on "Save changes" "button" + Then I should see "Minimum word limit cannot be a negative number" + + @javascript + Scenario: Maximum word limit cannot be greater than minimum word limit. + Given I choose "Edit question" action for "essay-min-max" in the question bank + And I set the field "minwordenabled" to "1" + And I set the field "id_minwordlimit" to "500" + And I set the field "maxwordenabled" to "1" + When I set the field "id_maxwordlimit" to "450" + And I click on "Save changes" "button" + Then I should see "Maximum world limit must be greater than minimum word limit" + + @javascript + Scenario: Modify the question to see 'Minimum word limit' and 'Maximum word limit' are hidden when 'Require text' field is set to 'Text input is optional' + Given I choose "Edit question" action for "essay-min-max" in the question bank + And I should see "Minimum word limit" + And I should see "Maximum word limit" + When I set the field "Require text" to "Text input is optional" + Then I should not see "Minimum word limit" + And I should not see "Minimum word limit" diff --git a/question/type/essay/tests/fixtures/testquestion.moodle.xml b/question/type/essay/tests/fixtures/testquestion.moodle.xml index d925ffb130e..b67846339de 100644 --- a/question/type/essay/tests/fixtures/testquestion.moodle.xml +++ b/question/type/essay/tests/fixtures/testquestion.moodle.xml @@ -25,6 +25,8 @@ editor 1 15 + 0 + 0 0 0 diff --git a/question/type/essay/tests/helper.php b/question/type/essay/tests/helper.php index 984e5b7c83a..269562f85ab 100644 --- a/question/type/essay/tests/helper.php +++ b/question/type/essay/tests/helper.php @@ -51,6 +51,8 @@ class qtype_essay_test_helper extends question_test_helper { $q->responseformat = 'editor'; $q->responserequired = 1; $q->responsefieldlines = 10; + $q->minwordlimit = 0; + $q->maxwordlimit = 0; $q->attachments = 0; $q->attachmentsrequired = 0; $q->filetypeslist = ''; @@ -86,6 +88,8 @@ class qtype_essay_test_helper extends question_test_helper { $fromform->responseformat = 'editor'; $fromform->responserequired = 1; $fromform->responsefieldlines = 10; + $fromform->minwordlimit = 0; + $fromform->maxwordlimit = 0; $fromform->attachments = 0; $fromform->attachmentsrequired = 0; $fromform->filetypeslist = ''; @@ -138,6 +142,8 @@ class qtype_essay_test_helper extends question_test_helper { $fromform->responseformat = 'editorfilepicker'; $fromform->responserequired = 1; $fromform->responsefieldlines = 10; + $fromform->minwordlimit = 0; + $fromform->maxwordlimit = 0; $fromform->attachments = 3; $fromform->attachmentsrequired = 0; $fromform->filetypeslist = ''; @@ -175,6 +181,8 @@ class qtype_essay_test_helper extends question_test_helper { $fromform->responseformat = 'plain'; $fromform->responserequired = 1; $fromform->responsefieldlines = 10; + $fromform->minwordlimit = 0; + $fromform->maxwordlimit = 0; $fromform->attachments = 0; $fromform->attachmentsrequired = 0; $fromform->filetypeslist = ''; diff --git a/question/type/essay/tests/question_test.php b/question/type/essay/tests/question_test.php index 9467ecb9b45..ab047e17d48 100644 --- a/question/type/essay/tests/question_test.php +++ b/question/type/essay/tests/question_test.php @@ -170,6 +170,25 @@ class qtype_essay_question_test extends advanced_testcase { $this->assertTrue($essay->is_complete_response(array('answer' => '0 times.'))); $this->assertTrue($essay->is_complete_response(array('answer' => '0'))); + // Test case for minimum and/or maximum word limit. + $response = []; + $response['answer'] = 'In this essay, I will be testing a function called check_input_word_count().'; + + $essay->minwordlimit = 50; // The answer is shorter than the required minimum word limit. + $this->assertFalse($essay->is_complete_response($response)); + + $essay->minwordlimit = 10; // The word count meets the required minimum word limit. + $this->assertTrue($essay->is_complete_response($response)); + + // The word count meets the required minimum and maximum word limit. + $essay->minwordlimit = 10; + $essay->maxwordlimit = 15; + $this->assertTrue($essay->is_complete_response($response)); + + // Unset the minwordlimit/maxwordlimit variables to avoid the extra check in is_complete_response() for further tests. + unset($essay->minwordlimit); + unset($essay->maxwordlimit); + // Test the case where two files are required. $essay->attachmentsrequired = 2; @@ -236,7 +255,6 @@ class qtype_essay_question_test extends advanced_testcase { $essay->reponserequired = 1; $this->assertTrue($essay->is_complete_response( array('attachments' => $attachments[1]))); - } /** @@ -262,4 +280,39 @@ class qtype_essay_question_test extends advanced_testcase { $this->assertEquals('', $options['responsetemplate']); $this->assertEquals(FORMAT_MOODLE, $options['responsetemplateformat']); } + + /** + * Test get_validation_error when users submit their input text. + * + * @dataProvider get_min_max_wordlimit_test_cases() + * @param int $responserequired whether reponse required (yes = 1, no = 0) + * @param int $minwordlimit minimum word limit + * @param int $maxwordlimit maximum word limit + * @param string $expected error message | null + */ + public function test_get_validation_error(int $responserequired, + int $minwordlimit, int $maxwordlimit, string $expected): void { + $question = test_question_maker::make_an_essay_question(); + $response = ['answer' => 'In this essay, I will be testing a function called check_input_word_count().']; + $question->responserequired = $responserequired; + $question->minwordlimit = $minwordlimit; + $question->maxwordlimit = $maxwordlimit; + $actual = $question->get_validation_error($response); + $this->assertEquals($expected, $actual); + } + + /** + * Data provider for get_validation_error test. + */ + public function get_min_max_wordlimit_test_cases() { + return [ + 'text input required, min/max word limit not set' => [1, 0, 0, ''], + 'text input required, min/max word limit valid (within the boundaries)' => [1, 10, 25, ''], + 'text input required, max word limit not reached' => [1, 15, 25, + get_string('minwordlimitboundary', 'qtype_essay', 15)], + 'text input required, max word limit is exceeded' => [1, 5, 12, + get_string('maxwordlimitboundary', 'qtype_essay', 12)], + 'text input not required, min/max word limit not set' => [0, 5, 12, ''], + ]; + } } diff --git a/question/type/essay/version.php b/question/type/essay/version.php index 34029cdc909..218fc3a7af4 100644 --- a/question/type/essay/version.php +++ b/question/type/essay/version.php @@ -26,7 +26,7 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'qtype_essay'; -$plugin->version = 2021052501; +$plugin->version = 2021052502; $plugin->requires = 2021052500;