diff --git a/mod/workshop/amd/build/modform.min.js b/mod/workshop/amd/build/modform.min.js new file mode 100644 index 00000000000..860dc019c59 --- /dev/null +++ b/mod/workshop/amd/build/modform.min.js @@ -0,0 +1 @@ +define(["jquery"],function(a){function b(a,b){a.available.prop("checked")||(a.required.prop("disabled",!0),a.required.prop("checked",!1),b.available.prop("checked")&&(b.required.prop("disabled",!0),b.required.prop("checked",!0),b.requiredHidden.val(1)))}function c(a){a.required.prop("disabled",!1),a.required.prop("checked",!1),a.requiredHidden.val(0)}function d(){b(e.file,e.text),b(e.text,e.file),e.text.available.prop("checked")&&e.file.available.prop("checked")&&(c(e.text),c(e.file))}var e={text:{available:null,required:null,requiredHidden:null},file:{available:null,required:null,requiredHidden:null}};return{init:function(){e.text.available=a("#id_submissiontypetextavailable"),e.text.required=a("#id_submissiontypetextrequired"),e.text.requiredHidden=a('input[name="submissiontypetextrequired"][type="hidden"]'),e.file.available=a("#id_submissiontypefileavailable"),e.file.required=a("#id_submissiontypefilerequired"),e.file.requiredHidden=a('input[name="submissiontypefilerequired"][type="hidden"]'),e.text.available.on("change",d),e.file.available.on("change",d),d()}}}); \ No newline at end of file diff --git a/mod/workshop/amd/src/modform.js b/mod/workshop/amd/src/modform.js new file mode 100644 index 00000000000..23523705c85 --- /dev/null +++ b/mod/workshop/amd/src/modform.js @@ -0,0 +1,99 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Additional javascript for the Workshop module form. + * + * @module mod_workshop/modform + * @copyright The Open University 2018 + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define(['jquery'], function($) { + + var submissionTypes = { + text: { + available: null, + required: null, + requiredHidden: null + }, + file: { + available: null, + required: null, + requiredHidden: null + } + }; + + /** + * Determine whether one of the submission types has been marked as not available. + * + * If it has been marked not available, clear and disable its required checkbox. Then determine if the other submission + * type is available, and if it is, check and disable its required checkbox. + * + * @param {Object} checkUnavailable + * @param {Object} checkAvailable + */ + function checkAvailability(checkUnavailable, checkAvailable) { + if (!checkUnavailable.available.prop('checked')) { + checkUnavailable.required.prop('disabled', true); + checkUnavailable.required.prop('checked', false); + if (checkAvailable.available.prop('checked')) { + checkAvailable.required.prop('disabled', true); + checkAvailable.required.prop('checked', true); + // Also set the checkbox's hidden field to 1 so a 'required' value is submitted for the submission type. + checkAvailable.requiredHidden.val(1); + } + } + } + + /** + * Enable the submission type's required checkbox and uncheck it. + * + * @param {Object} submissionType + */ + function enableRequired(submissionType) { + submissionType.required.prop('disabled', false); + submissionType.required.prop('checked', false); + submissionType.requiredHidden.val(0); + } + + /** + * Check which submission types have been marked as available, and disable required checkboxes as necessary. + */ + function submissionTypeChanged() { + checkAvailability(submissionTypes.file, submissionTypes.text); + checkAvailability(submissionTypes.text, submissionTypes.file); + if (submissionTypes.text.available.prop('checked') && submissionTypes.file.available.prop('checked')) { + enableRequired(submissionTypes.text); + enableRequired(submissionTypes.file); + } + } + + return /** @alias module:mod_workshop/modform */ { + /** + * Find all the required fields, set up event listeners, and set the initial state of required checkboxes. + */ + init: function() { + submissionTypes.text.available = $('#id_submissiontypetextavailable'); + submissionTypes.text.required = $('#id_submissiontypetextrequired'); + submissionTypes.text.requiredHidden = $('input[name="submissiontypetextrequired"][type="hidden"]'); + submissionTypes.file.available = $('#id_submissiontypefileavailable'); + submissionTypes.file.required = $('#id_submissiontypefilerequired'); + submissionTypes.file.requiredHidden = $('input[name="submissiontypefilerequired"][type="hidden"]'); + submissionTypes.text.available.on('change', submissionTypeChanged); + submissionTypes.file.available.on('change', submissionTypeChanged); + submissionTypeChanged(); + } + }; +}); diff --git a/mod/workshop/backup/moodle1/lib.php b/mod/workshop/backup/moodle1/lib.php index ddc4a01494f..587d276cefd 100644 --- a/mod/workshop/backup/moodle1/lib.php +++ b/mod/workshop/backup/moodle1/lib.php @@ -369,7 +369,14 @@ function workshop_upgrade_transform_instance(stdClass $old) { $new->name = $old->name; $new->intro = $old->description; $new->introformat = $old->format; - $new->nattachments = $old->nattachments; + if ($old->nattachments == 0) { + // Convert to the new method for disabling file submissions. + $new->submissiontypefile = WORKSHOP_SUBMISSION_TYPE_DISABLED; + $new->submissiontypetext = WORKSHOP_SUBMISSION_TYPE_REQUIRED; + $new->nattachments = 1; + } else { + $new->nattachments = $old->nattachments; + } $new->maxbytes = $old->maxbytes; $new->grade = $old->grade; $new->gradinggrade = $old->gradinggrade; @@ -409,4 +416,4 @@ function workshop_upgrade_transform_instance(stdClass $old) { } return $new; -} \ No newline at end of file +} diff --git a/mod/workshop/backup/moodle2/backup_workshop_stepslib.php b/mod/workshop/backup/moodle2/backup_workshop_stepslib.php index 3e9d8d10b5d..d357331356c 100644 --- a/mod/workshop/backup/moodle2/backup_workshop_stepslib.php +++ b/mod/workshop/backup/moodle2/backup_workshop_stepslib.php @@ -53,8 +53,8 @@ class backup_workshop_activity_structure_step extends backup_activity_structure_ 'instructauthorsformat', 'instructreviewers', 'instructreviewersformat', 'timemodified', 'phase', 'useexamples', 'usepeerassessment', 'useselfassessment', 'grade', 'gradinggrade', - 'strategy', 'evaluation', 'gradedecimals', 'nattachments', 'submissionfiletypes', - 'latesubmissions', 'maxbytes', 'examplesmode', 'submissionstart', + 'strategy', 'evaluation', 'gradedecimals', 'submissiontypetext', 'submissiontypefile', 'nattachments', + 'submissionfiletypes', 'latesubmissions', 'maxbytes', 'examplesmode', 'submissionstart', 'submissionend', 'assessmentstart', 'assessmentend', 'conclusion', 'conclusionformat', 'overallfeedbackmode', 'overallfeedbackfiles', 'overallfeedbackfiletypes', 'overallfeedbackmaxbytes')); diff --git a/mod/workshop/backup/moodle2/restore_workshop_stepslib.php b/mod/workshop/backup/moodle2/restore_workshop_stepslib.php index 1812f039275..7a2a5aee297 100644 --- a/mod/workshop/backup/moodle2/restore_workshop_stepslib.php +++ b/mod/workshop/backup/moodle2/restore_workshop_stepslib.php @@ -111,6 +111,13 @@ class restore_workshop_activity_structure_step extends restore_activity_structur $data->assessmentstart = $this->apply_date_offset($data->assessmentstart); $data->assessmentend = $this->apply_date_offset($data->assessmentend); + if ($data->nattachments == 0) { + // Convert to the new method for disabling file submissions. + $data->submissiontypefile = WORKSHOP_SUBMISSION_TYPE_DISABLED; + $data->submissiontypetext = WORKSHOP_SUBMISSION_TYPE_REQUIRED; + $data->nattachments = 1; + } + // insert the workshop record $newitemid = $DB->insert_record('workshop', $data); // immediately after inserting "activity" record, call this diff --git a/mod/workshop/classes/external/workshop_summary_exporter.php b/mod/workshop/classes/external/workshop_summary_exporter.php index bbacd5cf172..0b2de7f2e6f 100644 --- a/mod/workshop/classes/external/workshop_summary_exporter.php +++ b/mod/workshop/classes/external/workshop_summary_exporter.php @@ -145,10 +145,24 @@ class workshop_summary_exporter extends exporter { 'description' => 'Number of digits that should be shown after the decimal point when displaying grades.', 'optional' => true, ), + 'submissiontypetext' => array ( + 'type' => PARAM_INT, + 'default' => 1, + 'description' => 'Indicates whether text is required as part of each submission. ' . + '0 for no, 1 for optional, 2 for required.', + 'optional' => true + ), + 'submissiontypefile' => array ( + 'type' => PARAM_INT, + 'default' => 2, + 'description' => 'Indicates whether a file upload is required as part of each submission. ' . + '0 for no, 1 for optional, 2 for required.', + 'optional' => true + ), 'nattachments' => array( 'type' => PARAM_INT, - 'default' => 0, - 'description' => 'Number of required submission attachments.', + 'default' => 1, + 'description' => 'Maximum number of submission attachments.', 'optional' => true, ), 'submissionfiletypes' => array( diff --git a/mod/workshop/db/install.xml b/mod/workshop/db/install.xml index fb7e7ab72e5..d3ffcffcb7f 100644 --- a/mod/workshop/db/install.xml +++ b/mod/workshop/db/install.xml @@ -1,5 +1,5 @@ - @@ -25,7 +25,9 @@ - + + + @@ -133,4 +135,4 @@ - \ No newline at end of file + diff --git a/mod/workshop/db/upgrade.php b/mod/workshop/db/upgrade.php index 6c6e2c3b61f..0019f2b4058 100644 --- a/mod/workshop/db/upgrade.php +++ b/mod/workshop/db/upgrade.php @@ -68,5 +68,46 @@ function xmldb_workshop_upgrade($oldversion) { // Automatically generated Moodle v3.5.0 release upgrade line. // Put any upgrade step following this. + if ($oldversion < 2018062600) { + + // Define field submissiontypetext to be added to workshop. + $table = new xmldb_table('workshop'); + $field = new xmldb_field('submissiontypetext', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '1', 'gradedecimals'); + + // Conditionally launch add field submissiontypetext. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + $field = new xmldb_field('submissiontypefile', XMLDB_TYPE_INTEGER, '1', null, XMLDB_NOTNULL, null, '2', + 'submissiontypetext'); + + // Conditionally launch add field submissiontypefile. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Convert existing workshops with attachments disabled to use the new settings. + $workshops = $DB->get_records('workshop', ['nattachments' => 0]); + foreach ($workshops as $workshop) { + $update = (object) [ + 'id' => $workshop->id, + 'submissiontypefile' => 0, + 'submissiontypetext' => 2, + 'nattachments' => 1 + ]; + $DB->update_record('workshop', $update); + } + + // Changing the default of field nattachments on table workshop to 1. + $field = new xmldb_field('nattachments', XMLDB_TYPE_INTEGER, '3', null, null, null, '1', 'submissiontypefile'); + + // Launch change of default for field nattachments. + $dbman->change_field_default($table, $field); + + // Workshop savepoint reached. + upgrade_mod_savepoint(true, 2018062600, 'workshop'); + } + return true; } diff --git a/mod/workshop/lang/en/workshop.php b/mod/workshop/lang/en/workshop.php index f1f69aa2eb1..bf559e147e8 100644 --- a/mod/workshop/lang/en/workshop.php +++ b/mod/workshop/lang/en/workshop.php @@ -204,6 +204,7 @@ $string['mysubmission'] = 'My submission'; $string['nattachments'] = 'Maximum number of submission attachments'; $string['noexamples'] = 'No examples yet in this workshop'; $string['noexamplesformready'] = 'You must define the assessment form before providing example submissions'; +$string['nosubmissiontype'] = 'At least one submission type must be available'; $string['nogradeyet'] = 'No grade yet'; $string['nosubmissionfound'] = 'No submission found for this user'; $string['nosubmissions'] = 'No submissions yet in this workshop'; @@ -333,6 +334,12 @@ $string['submissionstart'] = 'Open for submissions from'; $string['submissionstartevent'] = '{$a} opens for submissions'; $string['submissionstartdatetime'] = 'Open for submissions from {$a->daydatetime} ({$a->distanceday})'; $string['submissiontitle'] = 'Title'; +$string['submissiontypefileavailable'] = 'File attachment available'; +$string['submissiontypefilerequired'] = 'File attachment Required'; +$string['submissiontypetextavailable'] = 'Online text available'; +$string['submissiontypetextrequired'] = 'Online text Required'; +$string['submissiontypedisabled'] = 'This submission type is disabled for this workshop.'; +$string['submissiontypes'] = 'Submission types'; $string['submissionsreport'] = 'Workshop submissions report'; $string['submittednotsubmitted'] = 'Submitted ({$a->submitted}) / not submitted ({$a->notsubmitted})'; $string['subplugintype_workshopallocation'] = 'Submissions allocation method'; diff --git a/mod/workshop/lib.php b/mod/workshop/lib.php index 3ef96128885..b4e3a411066 100644 --- a/mod/workshop/lib.php +++ b/mod/workshop/lib.php @@ -34,6 +34,9 @@ define('WORKSHOP_EVENT_TYPE_SUBMISSION_OPEN', 'opensubmission'); define('WORKSHOP_EVENT_TYPE_SUBMISSION_CLOSE', 'closesubmission'); define('WORKSHOP_EVENT_TYPE_ASSESSMENT_OPEN', 'openassessment'); define('WORKSHOP_EVENT_TYPE_ASSESSMENT_CLOSE', 'closeassessment'); +define('WORKSHOP_SUBMISSION_TYPE_DISABLED', 0); +define('WORKSHOP_SUBMISSION_TYPE_AVAILABLE', 1); +define('WORKSHOP_SUBMISSION_TYPE_REQUIRED', 2); //////////////////////////////////////////////////////////////////////////////// // Moodle core API // diff --git a/mod/workshop/locallib.php b/mod/workshop/locallib.php index 681eede6375..e928b3d3f80 100644 --- a/mod/workshop/locallib.php +++ b/mod/workshop/locallib.php @@ -171,6 +171,12 @@ class workshop { /** @var int maximum size of one file attached to the overall feedback */ public $overallfeedbackmaxbytes; + /** @var int Should the submission form show the text field? */ + public $submissiontypetext; + + /** @var int Should the submission form show the file attachment field? */ + public $submissiontypefile; + /** * @var workshop_strategy grading strategy instance * Do not use directly, get the instance using {@link workshop::grading_strategy_instance()} @@ -2870,9 +2876,39 @@ class workshop { $errors['title'] = get_string('err_multiplesubmissions', 'mod_workshop'); } } + // Get the workshop record by id or cmid, depending on whether we're creating or editing a submission. + if (empty($data['workshopid'])) { + $workshop = $DB->get_record_select('workshop', 'id = (SELECT instance FROM {course_modules} WHERE id = ?)', + [$data['cmid']]); + } else { + $workshop = $DB->get_record('workshop', ['id' => $data['workshopid']]); + } - $getfiles = file_get_drafarea_files($data['attachment_filemanager']); - if (empty($getfiles->list) and html_is_blank($data['content_editor']['text'])) { + if (isset($data['attachment_filemanager'])) { + $getfiles = file_get_drafarea_files($data['attachment_filemanager']); + $attachments = $getfiles->list; + } else { + $attachments = array(); + } + + if ($workshop->submissiontypefile == WORKSHOP_SUBMISSION_TYPE_REQUIRED) { + if (empty($attachments)) { + $errors['attachment_filemanager'] = get_string('err_required', 'form'); + } + } else if ($workshop->submissiontypefile == WORKSHOP_SUBMISSION_TYPE_DISABLED && !empty($data['attachment_filemanager'])) { + $errors['attachment_filemanager'] = get_string('submissiontypedisabled', 'mod_workshop'); + } + + if ($workshop->submissiontypetext == WORKSHOP_SUBMISSION_TYPE_REQUIRED && html_is_blank($data['content_editor']['text'])) { + $errors['content_editor'] = get_string('err_required', 'form'); + } else if ($workshop->submissiontypetext == WORKSHOP_SUBMISSION_TYPE_DISABLED && !empty($data['content_editor']['text'])) { + $errors['content_editor'] = get_string('submissiontypedisabled', 'mod_workshop'); + } + + // If neither type is explicitly required, one or the other must be submitted. + if ($workshop->submissiontypetext != WORKSHOP_SUBMISSION_TYPE_REQUIRED + && $workshop->submissiontypefile != WORKSHOP_SUBMISSION_TYPE_REQUIRED + && empty($attachments) && html_is_blank($data['content_editor']['text'])) { $errors['content_editor'] = get_string('submissionrequiredcontent', 'mod_workshop'); $errors['attachment_filemanager'] = get_string('submissionrequiredfile', 'mod_workshop'); } @@ -2939,8 +2975,10 @@ class workshop { $params['objectid'] = $submission->id; // Save and relink embedded images and save attachments. - $submission = file_postupdate_standard_editor($submission, 'content', $this->submission_content_options(), - $this->context, 'mod_workshop', 'submission_content', $submission->id); + if ($this->submissiontypetext != WORKSHOP_SUBMISSION_TYPE_DISABLED) { + $submission = file_postupdate_standard_editor($submission, 'content', $this->submission_content_options(), + $this->context, 'mod_workshop', 'submission_content', $submission->id); + } $submission = file_postupdate_standard_filemanager($submission, 'attachment', $this->submission_attachment_options(), $this->context, 'mod_workshop', 'submission_attachment', $submission->id); diff --git a/mod/workshop/mod_form.php b/mod/workshop/mod_form.php index a23e44a7c2b..12d0b672b82 100644 --- a/mod/workshop/mod_form.php +++ b/mod/workshop/mod_form.php @@ -54,7 +54,7 @@ class mod_workshop_mod_form extends moodleform_mod { * @return void */ public function definition() { - global $CFG; + global $CFG, $PAGE; $workshopconfig = get_config('workshop'); $mform = $this->_form; @@ -129,23 +129,39 @@ class mod_workshop_mod_form extends moodleform_mod { $mform->addElement('editor', 'instructauthorseditor', $label, null, workshop::instruction_editors_options($this->context)); + $typeelements = []; + foreach (['submissiontypetext', 'submissiontypefile'] as $type) { + $available = $type . 'available'; + $required = $type . 'required'; + $availablelabel = get_string($available, 'workshop'); + $requiredlabel = get_string($required, 'workshop'); + $typeelements[] = $mform->createElement('advcheckbox', $available, '', $availablelabel); + $typeelements[] = $mform->createElement('advcheckbox', $required, '', $requiredlabel); + $mform->setDefault($available, 1); + } + // We can't use
as the separator as it does not work well in this case with the Boost theme. + // Instead, separate both tuples with a full-width empty div. + $mform->addGroup($typeelements, 'submissiontypes', get_string('submissiontypes', 'workshop'), + array(' ', '
'), false); + $options = array(); - for ($i = 7; $i >= 0; $i--) { + for ($i = 7; $i >= 1; $i--) { $options[$i] = $i; } $label = get_string('nattachments', 'workshop'); $mform->addElement('select', 'nattachments', $label, $options); $mform->setDefault('nattachments', 1); + $mform->disabledIf('nattachments', 'submissiontypefileavailable'); $label = get_string('allowedfiletypesforsubmission', 'workshop'); $mform->addElement('filetypes', 'submissionfiletypes', $label); $mform->addHelpButton('submissionfiletypes', 'allowedfiletypesforsubmission', 'workshop'); - $mform->disabledIf('submissionfiletypes', 'nattachments', 'eq', 0); + $mform->disabledIf('submissionfiletypes', 'submissiontypefileavailable'); $options = get_max_upload_sizes($CFG->maxbytes, $this->course->maxbytes, 0, $workshopconfig->maxbytes); $mform->addElement('select', 'maxbytes', get_string('maxbytes', 'workshop'), $options); $mform->setDefault('maxbytes', $workshopconfig->maxbytes); - $mform->disabledIf('maxbytes', 'nattachments', 'eq', 0); + $mform->disabledIf('maxbytes', 'submissiontypefileavailable'); $label = get_string('latesubmissions', 'workshop'); $text = get_string('latesubmissions_desc', 'workshop'); @@ -243,6 +259,8 @@ class mod_workshop_mod_form extends moodleform_mod { // Standard buttons, common to all modules ------------------------------------ $this->add_action_buttons(); + + $PAGE->requires->js_call_amd('mod_workshop/modform', 'init'); } /** @@ -280,6 +298,16 @@ class mod_workshop_mod_form extends moodleform_mod { $data['conclusion']); $data['conclusioneditor']['format'] = $data['conclusionformat']; $data['conclusioneditor']['itemid'] = $draftitemid; + // Set submission type checkboxes. + foreach (['submissiontypetext', 'submissiontypefile'] as $type) { + $data[$type . 'available'] = 1; + $data[$type . 'required'] = 0; + if ($data[$type] == WORKSHOP_SUBMISSION_TYPE_DISABLED) { + $data[$type . 'available'] = 0; + } else if ($data[$type] == WORKSHOP_SUBMISSION_TYPE_REQUIRED) { + $data[$type . 'required'] = 1; + } + } } else { // adding a new workshop instance $draftitemid = file_get_submitted_draft_itemid('instructauthors'); @@ -296,6 +324,30 @@ class mod_workshop_mod_form extends moodleform_mod { } } + /** + * Combine submission type checkboxes into integer values for the database. + * + * @param stdClass $data The submitted form data. + */ + public function data_postprocessing($data) { + parent::data_postprocessing($data); + + foreach (['text', 'file'] as $type) { + $field = 'submissiontype' . $type; + $available = $field . 'available'; + $required = $field . 'required'; + if ($data->$required) { + $data->$field = WORKSHOP_SUBMISSION_TYPE_REQUIRED; + } else if ($data->$available) { + $data->$field = WORKSHOP_SUBMISSION_TYPE_AVAILABLE; + } else { + $data->$field = WORKSHOP_SUBMISSION_TYPE_DISABLED; + } + unset($data->$available); + unset($data->$required); + } + } + /** * Set the grade item categories when editing an instance */ @@ -341,6 +393,13 @@ class mod_workshop_mod_form extends moodleform_mod { } } } + $typevalues = $mform->getElementValue('submissiontypes'); + foreach (['submissiontypetext', 'submissiontypefile'] as $type) { + // Don't leave a disabled "required" checkbox checked. + if (!$typevalues[$type . 'available']) { + $mform->setDefault($type . 'required', 0); + } + } parent::definition_after_data(); } @@ -404,6 +463,11 @@ class mod_workshop_mod_form extends moodleform_mod { } } + if (!$data['submissiontypetextavailable'] && !$data['submissiontypefileavailable']) { + // One submission type must be available. + $errors['submissiontypes'] = get_string('nosubmissiontype', 'workshop'); + } + return $errors; } } diff --git a/mod/workshop/submission_form.php b/mod/workshop/submission_form.php index f8088a6a2dc..a2cbb845422 100644 --- a/mod/workshop/submission_form.php +++ b/mod/workshop/submission_form.php @@ -44,13 +44,21 @@ class workshop_submission_form extends moodleform { $mform->addRule('title', null, 'required', null, 'client'); $mform->addRule('title', get_string('maximumchars', '', 255), 'maxlength', 255, 'client'); - $mform->addElement('editor', 'content_editor', get_string('submissioncontent', 'workshop'), null, $contentopts); - $mform->setType('content', PARAM_RAW); + if ($workshop->submissiontypetext != WORKSHOP_SUBMISSION_TYPE_DISABLED) { + $mform->addElement('editor', 'content_editor', get_string('submissioncontent', 'workshop'), null, $contentopts); + $mform->setType('content_editor', PARAM_RAW); + if ($workshop->submissiontypetext == WORKSHOP_SUBMISSION_TYPE_REQUIRED) { + $mform->addRule('content_editor', null, 'required', null, 'client'); + } + } - if ($workshop->nattachments > 0) { + if ($workshop->submissiontypefile != WORKSHOP_SUBMISSION_TYPE_DISABLED) { $mform->addElement('static', 'filemanagerinfo', get_string('nattachments', 'workshop'), $workshop->nattachments); $mform->addElement('filemanager', 'attachment_filemanager', get_string('submissionattachment', 'workshop'), null, $attachmentopts); + if ($workshop->submissiontypefile == WORKSHOP_SUBMISSION_TYPE_REQUIRED) { + $mform->addRule('attachment_filemanager', null, 'required', null, 'client'); + } } $mform->addElement('hidden', 'id', $current->id); diff --git a/mod/workshop/tests/behat/delete_submission.feature b/mod/workshop/tests/behat/delete_submission.feature index 269a59a7d70..92be14c477a 100644 --- a/mod/workshop/tests/behat/delete_submission.feature +++ b/mod/workshop/tests/behat/delete_submission.feature @@ -21,8 +21,8 @@ Feature: Workshop submission removal | student3 | c1 | student | | teacher1 | c1 | editingteacher | And the following "activities" exist: - | activity | name | intro | course | idnumber | - | workshop | TestWorkshop | Test workshop description | c1 | workshop1 | + | activity | name | intro | course | idnumber | submissiontypefile | + | workshop | TestWorkshop | Test workshop description | c1 | workshop1 | 1 | # Teacher sets up assessment form and changes the phase to submission. And I log in as "teacher1" And I am on "Course1" course homepage diff --git a/mod/workshop/tests/behat/export_submission.feature b/mod/workshop/tests/behat/export_submission.feature index 852e542038e..861ef2d99d2 100644 --- a/mod/workshop/tests/behat/export_submission.feature +++ b/mod/workshop/tests/behat/export_submission.feature @@ -19,8 +19,8 @@ Feature: Exporting workshop submissions and assessments to a portfolio | student2 | c1 | student | | teacher1 | c1 | editingteacher | And the following "activities" exist: - | activity | name | intro | course | idnumber | - | workshop | TestWorkshop | Test workshop description | c1 | workshop1 | + | activity | name | intro | course | idnumber | submissiontypefile | + | workshop | TestWorkshop | Test workshop description | c1 | workshop1 | 1 | # Admin needs to enable portfolio API and set a portfolio instance first. And I log in as "admin" And the following config values are set as admin: diff --git a/mod/workshop/tests/behat/file_type_restriction.feature b/mod/workshop/tests/behat/file_type_restriction.feature index d709d7b210b..5ceedd9c22b 100644 --- a/mod/workshop/tests/behat/file_type_restriction.feature +++ b/mod/workshop/tests/behat/file_type_restriction.feature @@ -19,8 +19,8 @@ Feature: File types of the submission and feedback attachments can be limitted | student1 | c1 | student | | student2 | c1 | student | And the following "activities" exist: - | activity | name | intro | course | idnumber | - | workshop | TestWorkshop | Test workshop description | c1 | workshop1 | + | activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile | + | workshop | TestWorkshop | Test workshop description | c1 | workshop1 | 2 | 1 | @_file_upload @javascript Scenario: Student submission attachments obey the list of allowed file types diff --git a/mod/workshop/tests/behat/submission_types.feature b/mod/workshop/tests/behat/submission_types.feature new file mode 100644 index 00000000000..d5970f1383e --- /dev/null +++ b/mod/workshop/tests/behat/submission_types.feature @@ -0,0 +1,198 @@ +@mod @mod_workshop +Feature: Submission types + In order to Submit the correct type of materials + As a student + I want have a clear indication of which fields are accepted and required on the submission form + + Background: + Given the following "courses" exist: + | fullname | shortname | + | Test | TEST | + And I log in as "admin" + + @javascript + Scenario: Test workshop settings validation + Given I am on "Test" course homepage with editing mode on + And I add a "Workshop" to section "0" + When I set the following fields to these values: + | Workshop name | Test workshop | + | submissiontypetextavailable | 0 | + | submissiontypefileavailable | 0 | + And I press "Save and display" + Then I should see "At least one submission type must be available" + When I set the following fields to these values: + | submissiontypetextavailable | 1 | + Then the "submissiontypetextrequired" "field" should be disabled + Then the "submissiontypefilerequired" "field" should be disabled + And the field "submissiontypetextrequired" matches value "1" + And the field "submissiontypefilerequired" matches value "0" + When I set the following fields to these values: + | submissiontypetextavailable | 0 | + | submissiontypefileavailable | 1 | + Then the "submissiontypetextrequired" "field" should be disabled + Then the "submissiontypefilerequired" "field" should be disabled + And the field "submissiontypetextrequired" matches value "0" + And the field "submissiontypefilerequired" matches value "1" + When I set the following fields to these values: + | submissiontypetextavailable | 1 | + | submissiontypetextrequired | 1 | + | submissiontypefileavailable | 1 | + | submissiontypefilerequired | 1 | + And I press "Save and display" + Then I should see "Setup phase" in the "h3#mod_workshop-userplanheading" "css_element" + When I navigate to "Edit settings" in current page administration + And I set the following fields to these values: + | submissiontypetextrequired | 0 | + And I press "Save and display" + Then I should see "Setup phase" in the "h3#mod_workshop-userplanheading" "css_element" + When I navigate to "Edit settings" in current page administration + And I set the following fields to these values: + | submissiontypetextrequired | 1 | + | submissiontypefilerequired | 0 | + And I press "Save and display" + Then I should see "Setup phase" in the "h3#mod_workshop-userplanheading" "css_element" + When I navigate to "Edit settings" in current page administration + And I set the following fields to these values: + | submissiontypefileavailable | 0 | + And I press "Save and display" + Then I should see "Setup phase" in the "h3#mod_workshop-userplanheading" "css_element" + When I navigate to "Edit settings" in current page administration + And I set the following fields to these values: + | submissiontypefileavailable | 1 | + | submissiontypefilerequired | 1 | + | submissiontypetextavailable | 0 | + And I press "Save and display" + Then I should see "Setup phase" in the "h3#mod_workshop-userplanheading" "css_element" + + @javascript @_file_upload + Scenario: All submission fields required + Given the following "activities" exist: + | activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile | + | workshop | All required | Test workshop description | TEST | workshop1 | 2 | 2 | + And I am on "Test" course homepage + And I follow "All required" + And I follow "Switch to the submission phase" + And I press "Continue" + And I press "Start preparing your submission" + And I set the field "Title" to "Test submission" + When I press "Save changes" + Then I should see "You must supply a value here." in the "Submission content" "form_row" + And I set the field "Submission content" to "Lorem ipsum dolor" + And I press "Save changes" + And I should see "You must supply a value here." in the "Attachment" "form_row" + And I set the following fields to these values: + | Attachment | mod/workshop/tests/fixtures/moodlelogo.png | + And I press "Save changes" + And I should not see "You must supply a value here." + And I should see "My submission" + And "Edit submission" "button" should exist + + Scenario: Online text required, file attachment optional + Given the following "activities" exist: + | activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile | + | workshop | Optional file | Test workshop description | TEST | workshop1 | 2 | 1 | + And I am on "Test" course homepage + And I follow "Optional file" + And I follow "Switch to the submission phase" + And I press "Continue" + And I press "Start preparing your submission" + And I set the field "Title" to "Test submission" + When I press "Save changes" + Then I should see "You must supply a value here." in the "Submission content" "form_row" + And I set the following fields to these values: + | Submission content | Lorem ipsum dolor | + And I press "Save changes" + And I should not see "You must supply a value here." + And I should see "My submission" + And "Edit submission" "button" should exist + + @javascript @_file_upload + Scenario: Online text optional, file attachment required + Given the following "activities" exist: + | activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile | + | workshop | Optional text | Test workshop description | TEST | workshop1 | 1 | 2 | + And I am on "Test" course homepage + And I follow "Optional text" + And I follow "Switch to the submission phase" + And I press "Continue" + And I press "Start preparing your submission" + And I set the field "Title" to "Test submission" + When I press "Save changes" + Then I should see "You must supply a value here." in the "Attachment" "form_row" + And I set the following fields to these values: + | Attachment | mod/workshop/tests/fixtures/moodlelogo.png | + And I press "Save changes" + And I should not see "You must supply a value here." + And I should see "My submission" + And "Edit submission" "button" should exist + + Scenario: Online text only + Given the following "activities" exist: + | activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile | + | workshop | Only text | Test workshop description | TEST | workshop1 | 2 | 0 | + And I am on "Test" course homepage + And I follow "Only text" + And I follow "Switch to the submission phase" + And I press "Continue" + When I press "Start preparing your submission" + Then "Attachment" "field" should not exist + And I set the field "Title" to "Test submission" + And I press "Save changes" + And I should see "You must supply a value here." in the "Submission content" "form_row" + And I set the following fields to these values: + | Submission content | Lorem ipsum dolor | + And I press "Save changes" + And I should not see "You must supply a value here." + And I should see "My submission" + And "Edit submission" "button" should exist + + @javascript @_file_upload + Scenario: File attachment only + Given the following "activities" exist: + | activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile | + | workshop | Only file | Test workshop description | TEST | workshop1 | 0 | 2 | + And I am on "Test" course homepage + And I follow "Only file" + And I follow "Switch to the submission phase" + And I press "Continue" + When I press "Start preparing your submission" + Then "Submission content" "field" should not exist + And I set the field "Title" to "Test submission" + And I press "Save changes" + And I should see "You must supply a value here." in the "Attachment" "form_row" + And "Submission content" "form_row" should not exist + And I set the following fields to these values: + | Attachment | mod/workshop/tests/fixtures/moodlelogo.png | + And I press "Save changes" + And I should not see "You must supply a value here." + And I should see "My submission" + And "Edit submission" "button" should exist + + @javascript @_file_upload + Scenario: Neither submission type explicitly required + Given the following "activities" exist: + | activity | name | intro | course | idnumber | + | workshop | Neither required | Test workshop description | TEST | workshop1 | + And I am on "Test" course homepage + And I follow "Neither required" + And I follow "Switch to the submission phase" + And I press "Continue" + And I press "Start preparing your submission" + And I set the field "Title" to "Test submission" + When I press "Save changes" + Then I should see "You need to add a file or enter some text." in the "Attachment" "form_row" + And I should see "You need to enter some text or add a file." in the "Submission content" "form_row" + And I set the following fields to these values: + | Submission content | Lorem ipsum dolor | + And I press "Save changes" + And I should not see "You need to add a file or enter some text." + And I should not see "You need to enter some text or add a file." + And I should see "My submission" + And "Edit submission" "button" should exist + And I press "Edit submission" + And I set the following fields to these values: + | Submission content | | + | Attachment | mod/workshop/tests/fixtures/moodlelogo.png | + And I press "Save changes" + And I should not see "You need to add a file or enter some text." + And I should not see "You need to enter some text or add a file." diff --git a/mod/workshop/tests/behat/workshop_assessment.feature b/mod/workshop/tests/behat/workshop_assessment.feature index d434c9db878..d835dc19733 100644 --- a/mod/workshop/tests/behat/workshop_assessment.feature +++ b/mod/workshop/tests/behat/workshop_assessment.feature @@ -23,8 +23,8 @@ Feature: Workshop submission and assessment | student4 | c1 | student | | teacher1 | c1 | editingteacher | And the following "activities" exist: - | activity | name | intro | course | idnumber | - | workshop | TestWorkshop | Test workshop description | c1 | workshop1 | + | activity | name | intro | course | idnumber | submissiontypetext | submissiontypefile | + | workshop | TestWorkshop | Test workshop description | c1 | workshop1 | 2 | 1 | # teacher1 sets up assessment form and changes the phase to submission When I log in as "teacher1" And I am on "Course1" course homepage diff --git a/mod/workshop/tests/external_test.php b/mod/workshop/tests/external_test.php index e8e9f5dd49d..afb9a27afb6 100644 --- a/mod/workshop/tests/external_test.php +++ b/mod/workshop/tests/external_test.php @@ -162,6 +162,8 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { $workshop1->instructreviewersformat = 1; $workshop1->conclusionfiles = []; $workshop1->conclusionformat = 1; + $workshop1->submissiontypetext = 1; + $workshop1->submissiontypefile = 1; $workshop2->coursemodule = $workshop2->cmid; $workshop2->introformat = 1; @@ -172,6 +174,8 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { $workshop2->instructreviewersformat = 1; $workshop2->conclusionfiles = []; $workshop2->conclusionformat = 1; + $workshop2->submissiontypetext = 1; + $workshop2->submissiontypefile = 1; foreach ($expectedfields as $field) { if (!empty($properties[$field]) && $properties[$field]['type'] == PARAM_BOOL) { @@ -551,24 +555,35 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { public function test_add_submission_already_added() { $this->setUser($this->student); + $usercontext = context_user::instance($this->student->id); + $fs = get_file_storage(); + $draftidattach = file_get_unused_draft_itemid(); + $filerecordattach = [ + 'contextid' => $usercontext->id, + 'component' => 'user', + 'filearea' => 'draft', + 'itemid' => $draftidattach, + 'filepath' => '/', + 'filename' => 'attachement.txt' + ]; + $fs->create_file_from_string($filerecordattach, 'simple text attachment'); + // Switch to submission phase. $workshop = new workshop($this->workshop, $this->cm, $this->course); $workshop->switch_phase(workshop::PHASE_SUBMISSION); // Create the submission. - $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission'); + $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission', '', FORMAT_MOODLE, 0, $draftidattach); $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result); // Try to create it again. - $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission'); + $result = mod_workshop_external::add_submission($this->workshop->id, 'My submission', '', FORMAT_MOODLE, 0, $draftidattach); $result = external_api::clean_returnvalue(mod_workshop_external::add_submission_returns(), $result); $this->assertFalse($result['status']); $this->assertArrayNotHasKey('submissionid', $result); - $this->assertCount(2, $result['warnings']); + $this->assertCount(1, $result['warnings']); $this->assertEquals('fielderror', $result['warnings'][0]['warningcode']); - $this->assertEquals('content_editor', $result['warnings'][0]['item']); - $this->assertEquals('fielderror', $result['warnings'][1]['warningcode']); - $this->assertEquals('attachment_filemanager', $result['warnings'][1]['item']); + $this->assertEquals('title', $result['warnings'][0]['item']); } /** @@ -587,7 +602,7 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { // Create a file in a draft area for inline attachments. $fs = get_file_storage(); $draftidinlineattach = file_get_unused_draft_itemid(); - $usercontext = context_user::instance($this->student->id); + $usercontext = context_user::instance($user->id); $filenameimg = 'shouldbeanimage.txt'; $filerecordinline = array( 'contextid' => $usercontext->id, @@ -832,7 +847,7 @@ class mod_workshop_external_testcase extends externallib_advanced_testcase { // Create a couple of submissions with files. $firstsubmissionid = $this->create_test_submission($this->student); // Create submission with files. - $secondsubmissionid = $this->create_test_submission($this->anotherstudentg1->id); + $secondsubmissionid = $this->create_test_submission($this->anotherstudentg1); $this->setUser($this->student); $result = mod_workshop_external::get_submissions($this->workshop->id); diff --git a/mod/workshop/upgrade.txt b/mod/workshop/upgrade.txt index 4032b08cebf..8ccc0e6d58f 100644 --- a/mod/workshop/upgrade.txt +++ b/mod/workshop/upgrade.txt @@ -1,6 +1,11 @@ This files describes API changes in /mod/workshop - activity modules, information provided here is intended especially for developers. +=== 3.6 === + +* The external function get_workshops_by_courses now returns 2 additional fields: submissiontypetext and + submissiontypefile, indicating which submission types are available and required. + === 3.4 === * workshop_strategy::get_dimensions_info now returns also the scale items (if scales are being used). diff --git a/mod/workshop/version.php b/mod/workshop/version.php index 593d9aa3458..61d88c63701 100644 --- a/mod/workshop/version.php +++ b/mod/workshop/version.php @@ -24,7 +24,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2018051400; // The current module version (YYYYMMDDXX) +$plugin->version = 2018062600; // The current module version (YYYYMMDDXX) $plugin->requires = 2018050800; // Requires this Moodle version. $plugin->component = 'mod_workshop'; $plugin->cron = 60; // Give as a chance every minute.