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;