MDL-66173 login: Added form injection, validation and post action hooks
author[Peter Burnett] <[peterburnett@catalyst-au.net]>
Fri, 2 Aug 2019 00:34:19 +0000 (10:34 +1000)
committerburnetp1 <p.burnett@cqu.edu.au>
Wed, 16 Oct 2019 05:01:56 +0000 (15:01 +1000)
login/change_password.php
login/change_password_form.php
login/forgot_password_form.php
login/lib.php
login/set_password_form.php
login/signup.php
login/signup_form.php

index f5ce3e9..66840eb 100644 (file)
@@ -29,6 +29,7 @@ require_once($CFG->dirroot.'/user/lib.php');
 require_once('change_password_form.php');
 require_once($CFG->libdir.'/authlib.php');
 require_once($CFG->dirroot.'/webservice/lib.php');
+require_once('lib.php');
 
 $id     = optional_param('id', SITEID, PARAM_INT); // current course
 $return = optional_param('return', 0, PARAM_BOOL); // redirect after password change
@@ -133,6 +134,9 @@ if ($mform->is_cancelled()) {
 
     $strpasswordchanged = get_string('passwordchanged');
 
+    // Plugins can perform post password change actions once data has been validated.
+    core_login_post_change_password_requests($data);
+
     $fullname = fullname($USER, true);
 
     $PAGE->set_title($strpasswordchanged);
index 9f2b77d..d1c978a 100644 (file)
@@ -28,6 +28,7 @@ defined('MOODLE_INTERNAL') || die();
 
 require_once($CFG->libdir.'/formslib.php');
 require_once($CFG->dirroot.'/user/lib.php');
+require_once('lib.php');
 
 class login_change_password_form extends moodleform {
 
@@ -75,6 +76,9 @@ class login_change_password_form extends moodleform {
         $mform->addElement('hidden', 'id', 0);
         $mform->setType('id', PARAM_INT);
 
+        // Hook for plugins to extend form definition.
+        core_login_extend_change_password_form($mform, $USER);
+
         // buttons
         if (get_user_preferences('auth_forcepasswordchange')) {
             $this->add_action_buttons(false);
@@ -89,6 +93,9 @@ class login_change_password_form extends moodleform {
         $errors = parent::validation($data, $files);
         $reason = null;
 
+        // Extend validation for any form extensions from plugins.
+        $errors = array_merge($errors, core_login_validate_extend_change_password_form($data, $USER));
+
         // ignore submitted username
         if (!$user = authenticate_user_login($USER->username, $data['password'], true, $reason, false)) {
             $errors['password'] = get_string('invalidlogin');
index 67a4d9f..4ad2447 100644 (file)
@@ -26,6 +26,7 @@ defined('MOODLE_INTERNAL') || die();
 
 require_once($CFG->libdir.'/formslib.php');
 require_once($CFG->dirroot.'/user/lib.php');
+require_once('lib.php');
 
 /**
  * Reset forgotten password form definition.
@@ -46,6 +47,9 @@ class login_forgot_password_form extends moodleform {
         $mform    = $this->_form;
         $mform->setDisableShortforms(true);
 
+        // Hook for plugins to extend form definition.
+        core_login_extend_forgot_password_form($mform);
+
         $mform->addElement('header', 'searchbyusername', get_string('searchbyusername'), '');
 
         $purpose = user_edit_map_field_purpose($USER->id, 'username');
@@ -74,6 +78,10 @@ class login_forgot_password_form extends moodleform {
     function validation($data, $files) {
 
         $errors = parent::validation($data, $files);
+
+        // Extend validation for any form extensions from plugins.
+        $errors = array_merge($errors, core_login_validate_extend_forgot_password_form($data));
+
         $errors += core_login_validate_forgot_password_data($data);
 
         return $errors;
index 4264333..b391ea7 100644 (file)
@@ -51,6 +51,9 @@ function core_login_process_password_reset_request() {
         }
         list($status, $notice, $url) = core_login_process_password_reset($username, $email);
 
+        // Plugins can perform post forgot password actions once data has been validated.
+        core_login_post_forgot_password_requests($data);
+
         // Any email has now been sent.
         // Next display results to requesting user if settings permit.
         echo $OUTPUT->header();
@@ -283,6 +286,10 @@ function core_login_process_password_set($token) {
 
         $urltogo = core_login_get_return_url();
         unset($SESSION->wantsurl);
+
+        // Plugins can perform post set password actions once data has been validated.
+        core_login_post_set_password_requests($data, $user);
+
         redirect($urltogo, get_string('passwordset'), 1);
     }
 }
@@ -399,3 +406,181 @@ function core_login_pre_signup_requests() {
         }
     }
 }
+
+/**
+ * Plugins can extend forms.
+ */
+
+ /** Inject form elements into change_password_form.
+  * @param mform $mform the form to inject elements into.
+  * @param stdClass $user the user object to use for context.
+  */
+function core_login_extend_change_password_form($mform, $user) {
+    $callbacks = get_plugins_with_function('extend_change_password_form');
+    foreach ($callbacks as $type => $plugins) {
+        foreach ($plugins as $plugin => $pluginfunction) {
+            $pluginfunction($mform, $user);
+        }
+    }
+}
+
+ /** Inject form elements into set_password_form.
+  * @param mform $mform the form to inject elements into.
+  * @param stdClass $user the user object to use for context.
+  */
+function core_login_extend_set_password_form($mform, $user) {
+    $callbacks = get_plugins_with_function('extend_set_password_form');
+    foreach ($callbacks as $type => $plugins) {
+        foreach ($plugins as $plugin => $pluginfunction) {
+            $pluginfunction($mform, $user);
+        }
+    }
+}
+
+ /** Inject form elements into forgot_password_form.
+  * @param mform $mform the form to inject elements into.
+  */
+function core_login_extend_forgot_password_form($mform) {
+    $callbacks = get_plugins_with_function('extend_forgot_password_form');
+    foreach ($callbacks as $type => $plugins) {
+        foreach ($plugins as $plugin => $pluginfunction) {
+            $pluginfunction($mform);
+        }
+    }
+}
+
+ /** Inject form elements into signup_form.
+  * @param mform $mform the form to inject elements into.
+  */
+function core_login_extend_signup_form($mform) {
+    $callbacks = get_plugins_with_function('extend_signup_form');
+    foreach ($callbacks as $type => $plugins) {
+        foreach ($plugins as $plugin => $pluginfunction) {
+            $pluginfunction($mform);
+        }
+    }
+}
+
+/**
+ * Plugins can add additional validation to forms.
+ */
+
+/** Inject validation into change_password_form.
+ * @param array $data the data array from submitted form values.
+ * @param stdClass $user the user object to use for context.
+ * @return array $errors the updated array of errors from validation.
+ */
+function core_login_validate_extend_change_password_form($data, $user) {
+    $pluginsfunction = get_plugins_with_function('validate_extend_change_password_form');
+    $errors = array();
+    foreach ($pluginsfunction as $plugintype => $plugins) {
+        foreach ($plugins as $pluginfunction) {
+            $pluginerrors = $pluginfunction($data, $user);
+            $errors = array_merge($errors, $pluginerrors);
+        }
+    }
+    return $errors;
+}
+
+/** Inject validation into set_password_form.
+ * @param array $data the data array from submitted form values.
+ * @param stdClass $user the user object to use for context.
+ * @return array $errors the updated array of errors from validation.
+ */
+function core_login_validate_extend_set_password_form($data, $user) {
+    $pluginsfunction = get_plugins_with_function('validate_extend_set_password_form');
+    $errors = array();
+    foreach ($pluginsfunction as $plugintype => $plugins) {
+        foreach ($plugins as $pluginfunction) {
+            $pluginerrors = $pluginfunction($data, $user);
+            $errors = array_merge($errors, $pluginerrors);
+        }
+    }
+    return $errors;
+}
+
+/** Inject validation into forgot_password_form.
+ * @param array $data the data array from submitted form values.
+ * @return array $errors the updated array of errors from validation.
+ */
+function core_login_validate_extend_forgot_password_form($data) {
+    $pluginsfunction = get_plugins_with_function('validate_extend_forgot_password_form');
+    $errors = array();
+    foreach ($pluginsfunction as $plugintype => $plugins) {
+        foreach ($plugins as $pluginfunction) {
+            $pluginerrors = $pluginfunction($data);
+            $errors = array_merge($errors, $pluginerrors);
+        }
+    }
+    return $errors;
+}
+
+/** Inject validation into signup_form.
+ * @param array $data the data array from submitted form values.
+ * @return array $errors the updated array of errors from validation.
+ */
+function core_login_validate_extend_signup_form($data) {
+    $pluginsfunction = get_plugins_with_function('validate_extend_signup_form');
+    $errors = array();
+    foreach ($pluginsfunction as $plugintype => $plugins) {
+        foreach ($plugins as $pluginfunction) {
+            $pluginerrors = $pluginfunction($data);
+            $errors = array_merge($errors, $pluginerrors);
+        }
+    }
+    return $errors;
+}
+
+/**
+ * Plugins can perform post submission actions.
+ */
+
+/** Post change_password_form submission actions.
+ * @param stdClass $data the data object from the submitted form.
+ */
+function core_login_post_change_password_requests($data) {
+    $pluginsfunction = get_plugins_with_function('post_change_password_requests');
+    foreach ($pluginsfunction as $plugintype => $plugins) {
+        foreach ($plugins as $pluginfunction) {
+            $pluginfunction($data);
+        }
+    }
+}
+
+/** Post set_password_form submission actions.
+ * @param stdClass $data the data object from the submitted form.
+ * @param stdClass $user the user object for set_password context.
+ */
+function core_login_post_set_password_requests($data, $user) {
+    $pluginsfunction = get_plugins_with_function('post_set_password_requests');
+    foreach ($pluginsfunction as $plugintype => $plugins) {
+        foreach ($plugins as $pluginfunction) {
+            $pluginfunction($data, $user);
+        }
+    }
+}
+
+/** Post forgot_password_form submission actions.
+ * @param stdClass $data the data object from the submitted form.
+ */
+function core_login_post_forgot_password_requests($data) {
+    $pluginsfunction = get_plugins_with_function('post_forgot_password_requests');
+    foreach ($pluginsfunction as $plugintype => $plugins) {
+        foreach ($plugins as $pluginfunction) {
+            $pluginfunction($data);
+        }
+    }
+}
+
+/** Post signup_form submission actions.
+ * @param stdClass $data the data object from the submitted form.
+ */
+function core_login_post_signup_requests($data) {
+    $pluginsfunction = get_plugins_with_function('post_signup_requests');
+    foreach ($pluginsfunction as $plugintype => $plugins) {
+        foreach ($plugins as $pluginfunction) {
+            $pluginfunction($data);
+        }
+    }
+}
+
index 6cee4e9..1b29fb5 100644 (file)
@@ -27,6 +27,7 @@ defined('MOODLE_INTERNAL') || die();
 
 require_once($CFG->libdir.'/formslib.php');
 require_once($CFG->dirroot.'/user/lib.php');
+require_once('lib.php');
 
 /**
  * Set forgotten password form definition.
@@ -78,6 +79,10 @@ class login_set_password_form extends moodleform {
         $mform->addRule('password2', get_string('required'), 'required', null, 'client');
         $mform->setType('password2', PARAM_RAW);
 
+        // Hook for plugins to extend form definition.
+        $user = $this->_customdata;
+        core_login_extend_set_password_form($mform, $user);
+
         $this->add_action_buttons(true);
     }
 
@@ -92,6 +97,9 @@ class login_set_password_form extends moodleform {
 
         $errors = parent::validation($data, $files);
 
+        // Extend validation for any form extensions from plugins.
+        $errors = array_merge($errors, core_login_validate_extend_set_password_form($data, $user));
+
         // Ignore submitted username.
         if ($data['password'] !== $data['password2']) {
             $errors['password'] = get_string('passwordsdiffer');
index dd2e2ce..d46f453 100644 (file)
@@ -86,6 +86,9 @@ if ($mform_signup->is_cancelled()) {
     // Add missing required fields.
     $user = signup_setup_new_user($user);
 
+    // Plugins can perform post sign up actions once data has been validated.
+    core_login_post_signup_requests($user);
+
     $authplugin->user_signup($user, true); // prints notice and link to login/index.php
     exit; //never reached
 }
index ca975aa..8dc5354 100644 (file)
@@ -28,6 +28,7 @@ defined('MOODLE_INTERNAL') || die();
 require_once($CFG->libdir.'/formslib.php');
 require_once($CFG->dirroot.'/user/profile/lib.php');
 require_once($CFG->dirroot . '/user/editlib.php');
+require_once('lib.php');
 
 class login_signup_form extends moodleform implements renderable, templatable {
     function definition() {
@@ -97,6 +98,9 @@ class login_signup_form extends moodleform implements renderable, templatable {
             $mform->closeHeaderBefore('recaptcha_element');
         }
 
+        // Hook for plugins to extend form definition.
+        core_login_extend_signup_form($mform);
+
         // Add "Agree to sitepolicy" controls. By default it is a link to the policy text and a checkbox but
         // it can be implemented differently in custom sitepolicy handlers.
         $manager = new \core_privacy\local\sitepolicy\manager();
@@ -128,6 +132,9 @@ class login_signup_form extends moodleform implements renderable, templatable {
     public function validation($data, $files) {
         $errors = parent::validation($data, $files);
 
+        // Extend validation for any form extensions from plugins.
+        $errors = array_merge($errors, core_login_validate_extend_signup_form($data));
+
         if (signup_captcha_enabled()) {
             $recaptchaelement = $this->_form->getElement('recaptcha_element');
             if (!empty($this->_form->_submitValues['g-recaptcha-response'])) {