diff --git a/mod/workshop/backup/moodle2/backup_workshop_stepslib.php b/mod/workshop/backup/moodle2/backup_workshop_stepslib.php
index 8f2868ba1d7..3e9d8d10b5d 100644
--- a/mod/workshop/backup/moodle2/backup_workshop_stepslib.php
+++ b/mod/workshop/backup/moodle2/backup_workshop_stepslib.php
@@ -53,11 +53,11 @@ class backup_workshop_activity_structure_step extends backup_activity_structure_
'instructauthorsformat', 'instructreviewers',
'instructreviewersformat', 'timemodified', 'phase', 'useexamples',
'usepeerassessment', 'useselfassessment', 'grade', 'gradinggrade',
- 'strategy', 'evaluation', 'gradedecimals', 'nattachments',
+ 'strategy', 'evaluation', 'gradedecimals', 'nattachments', 'submissionfiletypes',
'latesubmissions', 'maxbytes', 'examplesmode', 'submissionstart',
'submissionend', 'assessmentstart', 'assessmentend',
'conclusion', 'conclusionformat', 'overallfeedbackmode',
- 'overallfeedbackfiles', 'overallfeedbackmaxbytes'));
+ 'overallfeedbackfiles', 'overallfeedbackfiletypes', 'overallfeedbackmaxbytes'));
// assessment forms definition
$this->add_subplugin_structure('workshopform', $workshop, true);
diff --git a/mod/workshop/db/install.xml b/mod/workshop/db/install.xml
index 260787f700d..3dc972f4583 100644
--- a/mod/workshop/db/install.xml
+++ b/mod/workshop/db/install.xml
@@ -26,6 +26,7 @@
+
@@ -38,6 +39,7 @@
+
diff --git a/mod/workshop/db/upgrade.php b/mod/workshop/db/upgrade.php
index 99acfbd7eae..4c76794c07e 100644
--- a/mod/workshop/db/upgrade.php
+++ b/mod/workshop/db/upgrade.php
@@ -35,7 +35,7 @@ defined('MOODLE_INTERNAL') || die();
* @return bool result
*/
function xmldb_workshop_upgrade($oldversion) {
- global $CFG;
+ global $CFG, $DB;
// Moodle v2.8.0 release upgrade line.
// Put any upgrade step following this.
@@ -46,5 +46,30 @@ function xmldb_workshop_upgrade($oldversion) {
// Moodle v3.0.0 release upgrade line.
// Put any upgrade step following this.
+ $dbman = $DB->get_manager();
+
+ if ($oldversion < 2016022200) {
+
+ // Define field submissionfiletypes to be added to workshop.
+ $table = new xmldb_table('workshop');
+ $field = new xmldb_field('submissionfiletypes', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'nattachments');
+
+ // Conditionally launch add field submissionfiletypes.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ // Define field overallfeedbackfiletypes to be added to workshop.
+ $field = new xmldb_field('overallfeedbackfiletypes',
+ XMLDB_TYPE_CHAR, '255', null, null, null, null, 'overallfeedbackfiles');
+
+ // Conditionally launch add field overallfeedbackfiletypes.
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ // Workshop savepoint reached.
+ upgrade_mod_savepoint(true, 2016022200, 'workshop');
+ }
return true;
}
diff --git a/mod/workshop/exsubmission.php b/mod/workshop/exsubmission.php
index 327ea2e8482..ecb7f98a923 100644
--- a/mod/workshop/exsubmission.php
+++ b/mod/workshop/exsubmission.php
@@ -121,6 +121,7 @@ if ($edit and $canmanage) {
'trusttext' => true,
'subdirs' => false,
'maxfiles' => $maxfiles,
+ 'filetypes' => $workshop->submissionfiletypes,
'maxbytes' => $maxbytes,
'context' => $workshop->context
);
diff --git a/mod/workshop/form/assessment_form.php b/mod/workshop/form/assessment_form.php
index 56128dcf5b3..809c0ef133d 100644
--- a/mod/workshop/form/assessment_form.php
+++ b/mod/workshop/form/assessment_form.php
@@ -120,4 +120,52 @@ class workshop_assessment_form extends moodleform {
public function is_editable() {
return !$this->_form->isFrozen();
}
+
+ /**
+ * Validate incoming data.
+ *
+ * @param array $data
+ * @param array $files
+ * @return array
+ */
+ public function validation($data, $files) {
+ $errors = parent::validation($data, $files);
+
+ if (isset($data['feedbackauthorattachment_filemanager'])) {
+ $draftitemid = $data['feedbackauthorattachment_filemanager'];
+
+ // If we have draft files, then make sure they are the correct ones.
+ if ($draftfiles = file_get_drafarea_files($draftitemid)) {
+
+ if (!$validfileextensions = workshop::get_array_of_file_extensions($this->workshop->overallfeedbackfiletypes)) {
+ return $errors;
+ }
+ $wrongfileextensions = null;
+ $bigfiles = null;
+
+ // Check the size of each file.
+ foreach ($draftfiles->list as $file) {
+ $a = new stdClass();
+ $a->maxbytes = $this->workshop->overallfeedbackmaxbytes;
+ $a->currentbytes = $file->size;
+ $a->filename = $file->filename;
+ $a->validfileextensions = implode(',', $validfileextensions);
+
+ // Check whether the extension of uploaded file is in the list.
+ $thisextension = substr(strrchr($file->filename, '.'), 1);
+ if (!in_array($thisextension, $validfileextensions)) {
+ $wrongfileextensions .= get_string('err_wrongfileextension', 'workshop', $a) . '
';
+ }
+ if ($file->size > $this->workshop->overallfeedbackmaxbytes) {
+ $bigfiles .= get_string('err_maxbytes', 'workshop', $a) . '
';
+ }
+ }
+ if ($bigfiles || $wrongfileextensions) {
+ $errors['feedbackauthorattachment_filemanager'] = $bigfiles . $wrongfileextensions;
+ }
+ }
+ }
+ return $errors;
+ }
+
}
diff --git a/mod/workshop/lang/en/workshop.php b/mod/workshop/lang/en/workshop.php
index 4477b2bde5d..a0dd09ec9c0 100644
--- a/mod/workshop/lang/en/workshop.php
+++ b/mod/workshop/lang/en/workshop.php
@@ -30,6 +30,10 @@ $string['allocation'] = 'Submission allocation';
$string['allocationdone'] = 'Allocation done';
$string['allocationerror'] = 'Allocation error';
$string['allocationconfigured'] = 'Allocation configured';
+$string['allowedfiletypesforoverallfeedback'] = 'Feedback attachment allowed file types';
+$string['allowedfiletypesforoverallfeedback_help'] = 'Feedback attachment allowed file types can be restricted by entering a comma-separated list of file extensions, for example \'mp4, mp3, jpg, jpeg\'. If the field is left empty, then all file types are allowed.';
+$string['allowedfiletypesforsubmission'] = 'Submission attachment allowed file types';
+$string['allowedfiletypesforsubmission_help'] = 'Submission attachment allowed file types can be restricted by entering a comma-separated list of file extensions, for example \'mp4, mp3, jpg, jpeg\'. If the field is left empty, then all file types are allowed.';
$string['allsubmissions'] = 'All submissions ({$a})';
$string['alreadygraded'] = 'Already graded';
$string['areaconclusion'] = 'Conclusion text';
@@ -100,6 +104,9 @@ $string['editingsubmission'] = 'Editing submission';
$string['editsubmission'] = 'Edit submission';
$string['err_multiplesubmissions'] = 'While editing this form, another version of the submission has been saved. Multiple submissions per user are not allowed.';
$string['err_removegrademappings'] = 'Unable to remove the unused grade mappings';
+$string['err_maxbytes'] = 'The attachment "{$a->filename} ({$a->currentbytes} bytes)" exeeds the maximum allowed file size ({$a->maxbytes} bytes)';
+$string['err_notallowedfiletype'] = 'The file extension "{$a}" is not allowed';
+$string['err_wrongfileextension'] = 'The file "{$a->filename}" cannot be uploaded, only file types "{$a->validfileextensions}" are allowed';
$string['evaluategradeswait'] = 'Please wait until the assessments are evaluated and the grades are calculated';
$string['evaluation'] = 'Grading evaluation';
$string['evaluationmethod'] = 'Grading evaluation method';
diff --git a/mod/workshop/locallib.php b/mod/workshop/locallib.php
index 4f98583aa54..eb7199b9cfe 100644
--- a/mod/workshop/locallib.php
+++ b/mod/workshop/locallib.php
@@ -1,5 +1,4 @@
0,
'maxbytes' => $this->overallfeedbackmaxbytes,
+ 'filetypes' => $this->overallfeedbackfiletypes,
'maxfiles' => $this->overallfeedbackfiles,
'changeformat' => 1,
'context' => $this->context,
@@ -2386,6 +2426,7 @@ class workshop {
return array(
'subdirs' => 1,
'maxbytes' => $this->overallfeedbackmaxbytes,
+ 'filetypes' => $this->overallfeedbackfiletypes,
'maxfiles' => $this->overallfeedbackfiles,
'return_types' => FILE_INTERNAL,
);
diff --git a/mod/workshop/mod_form.php b/mod/workshop/mod_form.php
index f5a2f9f4023..6dbbf2da6d0 100644
--- a/mod/workshop/mod_form.php
+++ b/mod/workshop/mod_form.php
@@ -1,5 +1,4 @@
addElement('text', 'name', $label, array('size'=>'64'));
+ $mform->addElement('text', 'name', $label, array('size' => '64'));
if (!empty($CFG->formatstringstriptags)) {
$mform->setType('name', PARAM_TEXT);
} else {
@@ -118,7 +117,7 @@ class mod_workshop_mod_form extends moodleform_mod {
$mform->addRule('gradinggradepass', null, 'numeric', null, 'client');
$options = array();
- for ($i=5; $i>=0; $i--) {
+ for ($i = 5; $i >= 0; $i--) {
$options[$i] = $i;
}
$label = get_string('gradedecimals', 'workshop');
@@ -133,16 +132,24 @@ class mod_workshop_mod_form extends moodleform_mod {
workshop::instruction_editors_options($this->context));
$options = array();
- for ($i=7; $i>=0; $i--) {
+ for ($i = 7; $i >= 0; $i--) {
$options[$i] = $i;
}
$label = get_string('nattachments', 'workshop');
$mform->addElement('select', 'nattachments', $label, $options);
$mform->setDefault('nattachments', 1);
+ $label = get_string('allowedfiletypesforsubmission', 'workshop');
+ $mform->addElement('text', 'submissionfiletypes', $label, array('maxlength' => 255, 'size' => 64));
+ $mform->addHelpButton('submissionfiletypes', 'allowedfiletypesforsubmission', 'workshop');
+ $mform->setType('submissionfiletypes', PARAM_TEXT);
+ $mform->addRule('submissionfiletypes', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
+ $mform->disabledIf('submissionfiletypes', 'nattachments', 'eq', 0);
+
$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);
$label = get_string('latesubmissions', 'workshop');
$text = get_string('latesubmissions_desc', 'workshop');
@@ -179,6 +186,13 @@ class mod_workshop_mod_form extends moodleform_mod {
$mform->setDefault('overallfeedbackfiles', 0);
$mform->disabledIf('overallfeedbackfiles', 'overallfeedbackmode', 'eq', 0);
+ $label = get_string('allowedfiletypesforoverallfeedback', 'workshop');
+ $mform->addElement('text', 'overallfeedbackfiletypes', $label, array('maxlength' => 255, 'size' => 64));
+ $mform->addHelpButton('overallfeedbackfiletypes', 'allowedfiletypesforoverallfeedback', 'workshop');
+ $mform->setType('overallfeedbackfiletypes', PARAM_TEXT);
+ $mform->addRule('overallfeedbackfiletypes', get_string('maximumchars', '', 255), 'maxlength', 255, 'client');
+ $mform->disabledIf('overallfeedbackfiletypes', 'overallfeedbackfiles', 'eq', 0);
+
$options = get_max_upload_sizes($CFG->maxbytes, $this->course->maxbytes);
$mform->addElement('select', 'overallfeedbackmaxbytes', get_string('overallfeedbackmaxbytes', 'workshop'), $options);
$mform->setDefault('overallfeedbackmaxbytes', $workshopconfig->maxbytes);
@@ -229,7 +243,7 @@ class mod_workshop_mod_form extends moodleform_mod {
// Common module settings, Restrict availability, Activity completion etc. ----
$features = array('groups' => true, 'groupings' => true,
- 'outcomes'=>true, 'gradecat'=>false, 'idnumber'=>false);
+ 'outcomes' => true, 'gradecat' => false, 'idnumber' => false);
$this->standard_coursemodule_elements();
@@ -347,6 +361,22 @@ class mod_workshop_mod_form extends moodleform_mod {
public function validation($data, $files) {
$errors = parent::validation($data, $files);
+ // Check the input of submissionfiletypes field.
+ if ($data['submissionfiletypes']) {
+ $invalidextension = workshop::check_allowed_file_types($data['submissionfiletypes']);
+ if ($invalidextension) {
+ $errors['submissionfiletypes'] = $invalidextension;
+ }
+ }
+
+ // Check the input of overallfeedbackfiletypes field.
+ if ($data['overallfeedbackfiletypes']) {
+ $invalidextension = workshop::check_allowed_file_types($data['overallfeedbackfiletypes']);
+ if ($invalidextension) {
+ $errors['overallfeedbackfiletypes'] = $invalidextension;
+ }
+ }
+
// check the phases borders are valid
if ($data['submissionstart'] > 0 and $data['submissionend'] > 0 and $data['submissionstart'] >= $data['submissionend']) {
$errors['submissionend'] = get_string('submissionendbeforestart', 'mod_workshop');
diff --git a/mod/workshop/submission.php b/mod/workshop/submission.php
index 02997122536..d67dfd0aa2e 100644
--- a/mod/workshop/submission.php
+++ b/mod/workshop/submission.php
@@ -184,17 +184,20 @@ if ($edit) {
require_once(dirname(__FILE__).'/submission_form.php');
$maxfiles = $workshop->nattachments;
+ $filetypes = $workshop->submissionfiletypes;
$maxbytes = $workshop->maxbytes;
$contentopts = array(
'trusttext' => true,
'subdirs' => false,
'maxfiles' => $maxfiles,
+ 'filetypes' => $filetypes,
'maxbytes' => $maxbytes,
'context' => $workshop->context,
'return_types' => FILE_INTERNAL | FILE_EXTERNAL
);
- $attachmentopts = array('subdirs' => true, 'maxfiles' => $maxfiles, 'maxbytes' => $maxbytes, 'return_types' => FILE_INTERNAL);
+ $attachmentopts = array('subdirs' => true, 'maxfiles' => $maxfiles, 'filetypes' => $filetypes, 'maxbytes' => $maxbytes,
+ 'return_types' => FILE_INTERNAL);
$submission = file_prepare_standard_editor($submission, 'content', $contentopts, $workshop->context,
'mod_workshop', 'submission_content', $submission->id);
$submission = file_prepare_standard_filemanager($submission, 'attachment', $attachmentopts, $workshop->context,
diff --git a/mod/workshop/submission_form.php b/mod/workshop/submission_form.php
index 144e5363276..f411f4e82a3 100644
--- a/mod/workshop/submission_form.php
+++ b/mod/workshop/submission_form.php
@@ -37,6 +37,8 @@ class workshop_submission_form extends moodleform {
$contentopts = $this->_customdata['contentopts'];
$attachmentopts = $this->_customdata['attachmentopts'];
+ $this->attachmentopts = $attachmentopts;
+
$mform->addElement('header', 'general', get_string('submission', 'workshop'));
$mform->addElement('text', 'title', get_string('submissiontitle', 'workshop'));
@@ -88,6 +90,42 @@ class workshop_submission_form extends moodleform {
}
}
+ if (isset ($data['attachment_filemanager'])) {
+ $draftitemid = $data['attachment_filemanager'];
+
+ // If we have draft files, then make sure they are the correct ones.
+ if ($draftfiles = file_get_drafarea_files($draftitemid)) {
+
+ if (!$validfileextensions = workshop::get_array_of_file_extensions($this->attachmentopts['filetypes'])) {
+ return $errors;
+ }
+ $wrongfileextensions = null;
+ $bigfiles = null;
+
+ // Check the size and type of each file.
+ foreach ($draftfiles->list as $file) {
+ $a = new stdClass();
+ $a->maxbytes = $this->attachmentopts['maxbytes'];
+ $a->currentbytes = $file->size;
+ $a->filename = $file->filename;
+ $a->validfileextensions = implode(',', $validfileextensions);
+
+ // Check whether the extension of uploaded file is in the list.
+ $thisextension = substr(strrchr($file->filename, '.'), 1);
+ if (!in_array($thisextension, $validfileextensions)) {
+ $wrongfileextensions .= get_string('err_wrongfileextension', 'workshop', $a) . '
';
+ }
+
+ // Check whether the file size exceeds the maximum submission attachment size.
+ if ($file->size > $this->attachmentopts['maxbytes']) {
+ $bigfiles .= get_string('err_maxbytes', 'workshop', $a) . '
';
+ }
+ }
+ if ($bigfiles || $wrongfileextensions) {
+ $errors['attachment_filemanager'] = $bigfiles . $wrongfileextensions;
+ }
+ }
+ }
return $errors;
}
}
diff --git a/mod/workshop/tests/generator/lib.php b/mod/workshop/tests/generator/lib.php
index 3774b8c96c9..0f893a05c96 100644
--- a/mod/workshop/tests/generator/lib.php
+++ b/mod/workshop/tests/generator/lib.php
@@ -48,11 +48,13 @@ class mod_workshop_generator extends testing_module_generator {
'gradinggrade' => $workshopconfig->gradinggrade,
'gradedecimals' => $workshopconfig->gradedecimals,
'nattachments' => 1,
+ 'submissionfiletypes' => null,
'maxbytes' => $workshopconfig->maxbytes,
'latesubmissions' => 0,
'useselfassessment' => 0,
'overallfeedbackmode' => 1,
'overallfeedbackfiles' => 0,
+ 'overallfeedbackfiletypes' => null,
'overallfeedbackmaxbytes' => $workshopconfig->maxbytes,
'useexamples' => 0,
'examplesmode' => $workshopconfig->examplesmode,
diff --git a/mod/workshop/tests/locallib_test.php b/mod/workshop/tests/locallib_test.php
index 70900ec8d42..13b5979b069 100644
--- a/mod/workshop/tests/locallib_test.php
+++ b/mod/workshop/tests/locallib_test.php
@@ -622,4 +622,92 @@ class mod_workshop_internal_api_testcase extends advanced_testcase {
$this->assertEquals(0, $DB->count_records('workshop_submissions', array('workshopid' => $this->workshop->id)));
$this->assertEquals(0, $DB->count_records('workshop_assessments'));
}
+
+ /**
+ * Test converting the string to array.
+ */
+ public function test_get_array_of_file_extensions() {
+ $this->resetAfterTest(true);
+
+ $listofextensions = 'doc, jpg, mp3';
+ $actual = workshop::get_array_of_file_extensions($listofextensions);
+ $expected = array('doc', 'jpg', 'mp3');
+ $this->assertEquals($expected, $actual);
+
+ $listofextensions = 'mp4,; docx,; gif';
+ $actual = workshop::get_array_of_file_extensions($listofextensions);
+ $expected = array('mp4', 'docx', 'gif');
+ $this->assertEquals($expected, $actual);
+
+ $listofextensions = 'mp4 docx gif';
+ $actual = workshop::get_array_of_file_extensions($listofextensions);
+ $expected = array('mp4', 'docx', 'gif');
+ $this->assertEquals($expected, $actual);
+
+ $listofextensions = 'MP4 DOCx Gif';
+ $actual = workshop::get_array_of_file_extensions($listofextensions);
+ $expected = array('mp4', 'docx', 'gif');
+ $this->assertEquals($expected, $actual);
+
+ $listofextensions = '.doc; .jpg; Mp4 "mp3"';
+ $actual = workshop::get_array_of_file_extensions($listofextensions);
+ $expected = array('.doc', '.jpg', 'mp4', 'mp3');
+ $this->assertEquals($expected, $actual);
+
+ $listofextensions = '.doc,;.jpg; .Mp3, ".Avi"';
+ $actual = workshop::get_array_of_file_extensions($listofextensions);
+ $expected = array('.doc', '.jpg', '.mp3', '.avi');
+ $this->assertEquals($expected, $actual);
+ }
+
+ /**
+ * Test the list of allowed file extensions.
+ */
+ public function test_check_allowed_file_types() {
+ $this->resetAfterTest(true);
+
+ // Valid file extensions.
+ $listofextensions = '';
+ $expected = '';
+ // The function returns '' when file extensions are valid or the input field is empty.
+ $actual = workshop::check_allowed_file_types($listofextensions);
+ $this->assertEquals($expected, $actual);
+
+ $listofextensions = 'doc, jpg, mp3';
+ $expected = '';
+ $actual = workshop::check_allowed_file_types($listofextensions);
+ $this->assertEquals($expected, $actual);
+
+ $listofextensions = 'doc; ".jpg"; mp4 ...mp3';
+ $expected = '';
+ $actual = workshop::check_allowed_file_types($listofextensions);
+ $this->assertEquals($expected, $actual);
+
+ // Error handling.
+ $listofextensions = 'doc.jpg .mp3 .avi';
+ $expected = get_string('err_notallowedfiletype', 'workshop', 'doc.jpg');
+ // The function returns and error on the form-field: 'The file extension "doc.jpg" is not allowed'.
+ $actual = workshop::check_allowed_file_types($listofextensions);
+ $this->assertEquals($expected, $actual);
+
+ $listofextensions = 'doc, jpg, mp3, unusual';
+ $expected = get_string('err_notallowedfiletype', 'workshop', 'unusual');
+ $actual = workshop::check_allowed_file_types($listofextensions);
+ $this->assertEquals($expected, $actual);
+
+ $listofextensions = 'doc,; unusual1, unusual2';
+ $expected = get_string('err_notallowedfiletype', 'workshop', 'unusual1');
+ $actual = workshop::check_allowed_file_types($listofextensions);
+ $this->assertEquals($expected, $actual);
+
+ $listofextensions = 'unusual1,; unsusual2, doc, jpg';
+ $expected = get_string('err_notallowedfiletype', 'workshop', 'unusual1');
+ $actual = workshop::check_allowed_file_types($listofextensions);
+ $this->assertEquals($expected, $actual);
+
+ $listofextensions = 'unusual1; unusual2; mp4';
+ $expected = get_string('err_notallowedfiletype', 'workshop', 'unusual1');
+ $actual = workshop::check_allowed_file_types($listofextensions);
+ $this->assertEquals($expected, $actual);
+ }
}
diff --git a/mod/workshop/version.php b/mod/workshop/version.php
index 5f8e1963c54..2eaa821efa2 100644
--- a/mod/workshop/version.php
+++ b/mod/workshop/version.php
@@ -24,7 +24,7 @@
defined('MOODLE_INTERNAL') || die();
-$plugin->version = 2016012101; // The current module version (YYYYMMDDXX)
+$plugin->version = 2016022200; // The current module version (YYYYMMDDXX)
$plugin->requires = 2015111000; // Requires this Moodle version.
$plugin->component = 'mod_workshop';
$plugin->cron = 60; // Give as a chance every minute.