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 842d10a487c73..b491217316ecd 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
@@ -51,7 +51,8 @@ protected function define_question_plugin_structure() {
$essay = new backup_nested_element('essay', array('id'), array(
'responseformat', 'responserequired', 'responsefieldlines',
'attachments', 'attachmentsrequired', 'graderinfo',
- 'graderinfoformat', 'responsetemplate', 'responsetemplateformat', 'filetypeslist'));
+ 'graderinfoformat', 'responsetemplate', 'responsetemplateformat',
+ 'filetypeslist', 'maxbytes'));
// Now the own qtype tree.
$pluginwrapper->add_child($essay);
diff --git a/question/type/essay/db/install.xml b/question/type/essay/db/install.xml
index 88314abefbda3..4177509d6fedf 100644
--- a/question/type/essay/db/install.xml
+++ b/question/type/essay/db/install.xml
@@ -17,6 +17,7 @@
+
diff --git a/question/type/essay/db/upgrade.php b/question/type/essay/db/upgrade.php
index 2022579ea6e54..6ee1f49d5e1a3 100644
--- a/question/type/essay/db/upgrade.php
+++ b/question/type/essay/db/upgrade.php
@@ -30,7 +30,7 @@
* @param int $oldversion the version we are upgrading from.
*/
function xmldb_qtype_essay_upgrade($oldversion) {
- global $CFG;
+ global $CFG, $DB;
// Automatically generated Moodle v3.5.0 release upgrade line.
// Put any upgrade step following this.
@@ -47,5 +47,21 @@ function xmldb_qtype_essay_upgrade($oldversion) {
// Automatically generated Moodle v3.9.0 release upgrade line.
// Put any upgrade step following this.
+ $dbman = $DB->get_manager();
+ if ($oldversion < 2021052501) {
+
+ // Define field maxbytes to be added to qtype_essay_options.
+ $table = new xmldb_table('qtype_essay_options');
+ $field = new xmldb_field('maxbytes', XMLDB_TYPE_INTEGER, '10', null,
+ XMLDB_NOTNULL, null, '0', 'responsetemplateformat');
+
+ // Conditionally launch add field maxbytes.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ // Essay savepoint reached.
+ upgrade_plugin_savepoint(true, 2021052501, 'qtype', 'essay');
+ }
return true;
}
diff --git a/question/type/essay/edit_essay_form.php b/question/type/essay/edit_essay_form.php
index 3f97bd3591439..68f16e83e6dea 100644
--- a/question/type/essay/edit_essay_form.php
+++ b/question/type/essay/edit_essay_form.php
@@ -69,6 +69,10 @@ protected function definition_inner($mform) {
$mform->addHelpButton('filetypeslist', 'acceptedfiletypes', 'qtype_essay');
$mform->disabledIf('filetypeslist', 'attachments', 'eq', 0);
+ $mform->addElement('select', 'maxbytes', get_string('maxbytes', 'qtype_essay'), $qtype->max_file_size_options());
+ $mform->setDefault('maxbytes', '0');
+ $mform->disabledIf('maxbytes', 'attachments', 'eq', 0);
+
$mform->addElement('header', 'responsetemplateheader', get_string('responsetemplateheader', 'qtype_essay'));
$mform->addElement('editor', 'responsetemplate', get_string('responsetemplate', 'qtype_essay'),
array('rows' => 10), array_merge($this->editoroptions, array('maxfiles' => 0)));
@@ -93,6 +97,7 @@ protected function data_preprocessing($question) {
$question->attachments = $question->options->attachments;
$question->attachmentsrequired = $question->options->attachmentsrequired;
$question->filetypeslist = $question->options->filetypeslist;
+ $question->maxbytes = $question->options->maxbytes;
$draftid = file_get_submitted_draft_itemid('graderinfo');
$question->graderinfo = array();
diff --git a/question/type/essay/lang/en/qtype_essay.php b/question/type/essay/lang/en/qtype_essay.php
index 424ae8f8ef780..1ee63782c9afc 100644
--- a/question/type/essay/lang/en/qtype_essay.php
+++ b/question/type/essay/lang/en/qtype_essay.php
@@ -36,6 +36,7 @@
$string['formatplain'] = 'Plain text';
$string['graderinfo'] = 'Information for graders';
$string['graderinfoheader'] = 'Grader Information';
+$string['maxbytes'] = 'Maximum file size';
$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 73466bff99af7..aa8cbf45b815d 100644
--- a/question/type/essay/question.php
+++ b/question/type/essay/question.php
@@ -44,6 +44,9 @@ class qtype_essay_question extends question_with_responses {
public $responsefieldlines;
public $attachments;
+ /** @var int maximum file size in bytes */
+ public $maxbytes;
+
/** @var int The number of attachments required for a response to be complete. */
public $attachmentsrequired;
diff --git a/question/type/essay/questiontype.php b/question/type/essay/questiontype.php
index 71f03d80514ed..5420a249e25b3 100644
--- a/question/type/essay/questiontype.php
+++ b/question/type/essay/questiontype.php
@@ -72,6 +72,7 @@ public function save_question_options($formdata) {
} else {
$options->filetypeslist = $formdata->filetypeslist;
}
+ $options->maxbytes = $formdata->maxbytes ?? 0;
$options->graderinfo = $this->import_or_save_files($formdata->graderinfo,
$context, 'qtype_essay', 'graderinfo', $formdata->id);
$options->graderinfoformat = $formdata->graderinfo['format'];
@@ -93,6 +94,7 @@ protected function initialise_question_instance(question_definition $question, $
$question->responsetemplateformat = $questiondata->options->responsetemplateformat;
$filetypesutil = new \core_form\filetypes_util();
$question->filetypeslist = $filetypesutil->normalize_file_types($questiondata->options->filetypeslist);
+ $question->maxbytes = $questiondata->options->maxbytes;
}
public function delete_question($questionid, $contextid) {
@@ -162,6 +164,15 @@ public function attachments_required_options() {
);
}
+ /**
+ * Return array of the choices that should be offered for the maximum file sizes.
+ * @return array|lang_string[]|string[]
+ */
+ public function max_file_size_options() {
+ global $CFG, $COURSE;
+ return get_max_upload_sizes($CFG->maxbytes, $COURSE->maxbytes);
+ }
+
public function move_files($questionid, $oldcontextid, $newcontextid) {
parent::move_files($questionid, $oldcontextid, $newcontextid);
$fs = get_file_storage();
diff --git a/question/type/essay/renderer.php b/question/type/essay/renderer.php
index 06116ea58014d..a0cb56969ebe9 100644
--- a/question/type/essay/renderer.php
+++ b/question/type/essay/renderer.php
@@ -45,7 +45,7 @@ public function formulation_and_controls(question_attempt $qa,
if (!$step->has_qt_var('answer') && empty($options->readonly)) {
// Question has never been answered, fill it with response template.
- $step = new question_attempt_step(array('answer'=>$question->responsetemplate));
+ $step = new question_attempt_step(array('answer' => $question->responsetemplate));
}
if (empty($options->readonly)) {
@@ -122,6 +122,7 @@ public function files_input(question_attempt $qa, $numallowed,
$pickeroptions->accepted_types = $qa->get_question()->filetypeslist;
$fm = new form_filemanager($pickeroptions);
+ $fm->options->maxbytes = $qa->get_question()->maxbytes;;
$filesrenderer = $this->page->get_renderer('core', 'files');
$text = '';
diff --git a/question/type/essay/styles.css b/question/type/essay/styles.css
index a531afc4e375c..9b8357b1ff297 100644
--- a/question/type/essay/styles.css
+++ b/question/type/essay/styles.css
@@ -23,3 +23,7 @@
.que.essay div.qtype_essay_response textarea {
width: 100%;
}
+
+.que.essay .ablock .filemanager .fp-restrictions {
+ margin-top: 1em;
+}
diff --git a/question/type/essay/tests/behat/max_file_size.feature b/question/type/essay/tests/behat/max_file_size.feature
new file mode 100644
index 0000000000000..943bae1119554
--- /dev/null
+++ b/question/type/essay/tests/behat/max_file_size.feature
@@ -0,0 +1,32 @@
+@qtype @qtype_essay
+Feature: In an essay question, let the question author choose the maxbytes for attachments
+In order to constrain student submissions for marking
+As a teacher
+I need to choose the appropriate maxbytes for attachments
+ 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 | attachments | maxbytes |
+ | Test questions | essay | essay-1-20MB | editor | 1 | 20971520 |
+ 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 @_switch_window
+ Scenario: Preview an Essay question and see the allowed maximum file sizes and number of attachments.
+ When I choose "Preview" action for "essay-1-20MB" in the question bank
+ And I switch to "questionpreview" window
+ And I should see "Please write a story about a frog."
+ And I should see "Maximum file size: 20MB, maximum number of files: 1"
+ And I switch to the main window
diff --git a/question/type/essay/tests/helper.php b/question/type/essay/tests/helper.php
index c759bbdb17219..984e5b7c83a54 100644
--- a/question/type/essay/tests/helper.php
+++ b/question/type/essay/tests/helper.php
@@ -89,6 +89,7 @@ public function get_essay_question_form_data_editor() {
$fromform->attachments = 0;
$fromform->attachmentsrequired = 0;
$fromform->filetypeslist = '';
+ $fromform->maxbytes = 0;
$fromform->graderinfo = array('text' => '', 'format' => FORMAT_HTML);
$fromform->responsetemplate = array('text' => '', 'format' => FORMAT_HTML);
@@ -140,6 +141,7 @@ public function get_essay_question_form_data_editorfilepicker() {
$fromform->attachments = 3;
$fromform->attachmentsrequired = 0;
$fromform->filetypeslist = '';
+ $fromform->maxbytes = 0;
$fromform->graderinfo = array('text' => '', 'format' => FORMAT_HTML);
$fromform->responsetemplate = array('text' => '', 'format' => FORMAT_HTML);
@@ -176,6 +178,7 @@ public function get_essay_question_form_data_plain() {
$fromform->attachments = 0;
$fromform->attachmentsrequired = 0;
$fromform->filetypeslist = '';
+ $fromform->maxbytes = 0;
$fromform->graderinfo = array('text' => '', 'format' => FORMAT_HTML);
$fromform->responsetemplate = array('text' => '', 'format' => FORMAT_HTML);
@@ -209,6 +212,7 @@ public function make_essay_question_noinline() {
$q->attachments = 3;
$q->attachmentsrequired = 1;
$q->filetypeslist = '';
+ $q->maxbytes = 0;
return $q;
}
diff --git a/question/type/essay/version.php b/question/type/essay/version.php
index c9e0316d60ea4..34029cdc90961 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 = 2021052500;
+$plugin->version = 2021052501;
$plugin->requires = 2021052500;