diff --git a/.upgradenotes/MDL-83440-2024101111263005.yml b/.upgradenotes/MDL-83440-2024101111263005.yml new file mode 100644 index 00000000000..1cf9a36e08e --- /dev/null +++ b/.upgradenotes/MDL-83440-2024101111263005.yml @@ -0,0 +1,8 @@ +issueNumber: MDL-83440 +notes: + mod_assign: + - message: >- + Assign sub-plugins have a new method assign_plugin::settings_validation + which can be overridden to validate the data when the assignments form + is saved. + type: improved diff --git a/mod/assign/assignmentplugin.php b/mod/assign/assignmentplugin.php index 2fc74e4ffaf..a1c126e2194 100644 --- a/mod/assign/assignmentplugin.php +++ b/mod/assign/assignmentplugin.php @@ -107,6 +107,20 @@ abstract class assign_plugin { return; } + /** + * This method is called when the mod_assign_mod_form is submitted. + * + * It is an opportunity to validate the settings form fields added by {@see get_settings()}. + * + * @param array $data as passed to mod_assign_mod_form::validation(). + * @param array $files as passed to mod_assign_mod_form::validation(). + * @return array and validation errors that should be displayed. + * This is array_merged with any other validation errors from the form. + */ + public function settings_validation(array $data, array $files): array { + return []; + } + /** * The assignment subtype is responsible for saving it's own settings as the database table for the * standard type cannot be modified. diff --git a/mod/assign/locallib.php b/mod/assign/locallib.php index d00b198eb0a..d3a1674388d 100644 --- a/mod/assign/locallib.php +++ b/mod/assign/locallib.php @@ -150,10 +150,10 @@ class assign { */ private $cache; - /** @var array list of the installed submission plugins */ + /** @var assign_submission_plugin[] list of the installed submission plugins */ private $submissionplugins; - /** @var array list of the installed feedback plugins */ + /** @var assign_feedback_plugin[] list of the installed feedback plugins */ private $feedbackplugins; /** @var string action to be used to return to this page @@ -1746,6 +1746,31 @@ class assign { } } + /** + * Allow each plugin to validiate the data from the assignments settings form. + * + * @param array $data as passed to mod_assign_mod_form::validation(). + * @param array $files as passed to mod_assign_mod_form::validation(). + * @return array and validation errors that should be displayed. + */ + public function plugin_settings_validation(array $data, array $files): array { + $errors = []; + + foreach ($this->submissionplugins as $plugin) { + if ($plugin->is_visible()) { + $errors = array_merge($errors, $plugin->settings_validation($data, $files)); + } + } + + foreach ($this->feedbackplugins as $plugin) { + if ($plugin->is_visible()) { + $errors = array_merge($errors, $plugin->settings_validation($data, $files)); + } + } + + return $errors; + } + /** * Get the name of the current module. * diff --git a/mod/assign/mod_form.php b/mod/assign/mod_form.php index 475f929639e..48365ab997d 100644 --- a/mod/assign/mod_form.php +++ b/mod/assign/mod_form.php @@ -42,7 +42,7 @@ class mod_assign_mod_form extends moodleform_mod { * @return void */ public function definition() { - global $CFG, $COURSE, $DB; + global $CFG, $COURSE; $mform = $this->_form; $mform->addElement('header', 'general', get_string('general', 'form')); @@ -73,19 +73,7 @@ class mod_assign_mod_form extends moodleform_mod { $mform->addElement('advcheckbox', 'submissionattachments', get_string('submissionattachments', 'assign')); $mform->addHelpButton('submissionattachments', 'submissionattachments', 'assign'); - $ctx = null; - if ($this->current && $this->current->coursemodule) { - $cm = get_coursemodule_from_instance('assign', $this->current->id, 0, false, MUST_EXIST); - $ctx = context_module::instance($cm->id); - } - $assignment = new assign($ctx, null, null); - if ($this->current && $this->current->course) { - if (!$ctx) { - $ctx = context_course::instance($this->current->course); - } - $course = $DB->get_record('course', array('id'=>$this->current->course), '*', MUST_EXIST); - $assignment->set_course($course); - } + [$assignment] = $this->get_assign(); $mform->addElement('header', 'availability', get_string('availability', 'assign')); $mform->setExpanded('availability', true); @@ -287,6 +275,9 @@ class mod_assign_mod_form extends moodleform_mod { $errors['attemptreopenmethod'] = get_string('reopenuntilpassincompatiblewithblindmarking', 'assign'); } + [$assignment] = $this->get_assign(); + $errors = array_merge($errors, $assignment->plugin_settings_validation($data, $files)); + return $errors; } @@ -296,21 +287,7 @@ class mod_assign_mod_form extends moodleform_mod { * @param array $defaultvalues */ public function data_preprocessing(&$defaultvalues) { - global $DB; - - $ctx = null; - if ($this->current && $this->current->coursemodule) { - $cm = get_coursemodule_from_instance('assign', $this->current->id, 0, false, MUST_EXIST); - $ctx = context_module::instance($cm->id); - } - $assignment = new assign($ctx, null, null); - if ($this->current && $this->current->course) { - if (!$ctx) { - $ctx = context_course::instance($this->current->course); - } - $course = $DB->get_record('course', array('id'=>$this->current->course), '*', MUST_EXIST); - $assignment->set_course($course); - } + [$assignment, $ctx] = $this->get_assign(); $draftitemid = file_get_submitted_draft_itemid('introattachments'); file_prepare_draft_area($draftitemid, $ctx->id, 'mod_assign', ASSIGN_INTROATTACHMENT_FILEAREA, @@ -406,4 +383,30 @@ class mod_assign_mod_form extends moodleform_mod { } } } + + /** + * Get a relevant assign instance for this form, and the context. + * + * If we are editing an existing assign, it is that assignment and context, otherwise it is for the course context. + * + * @return array [$assignment, $ctx] the assignment object and the context. + */ + protected function get_assign(): array { + global $DB; + + $ctx = null; + if ($this->current && $this->current->coursemodule) { + $cm = get_coursemodule_from_instance('assign', $this->current->id, 0, false, MUST_EXIST); + $ctx = context_module::instance($cm->id); + } + $assignment = new assign($ctx, null, null); + if ($this->current && $this->current->course) { + if (!$ctx) { + $ctx = context_course::instance($this->current->course); + } + $course = $DB->get_record('course', ['id' => $this->current->course], '*', MUST_EXIST); + $assignment->set_course($course); + } + return [$assignment, $ctx]; + } }