diff --git a/README.md b/README.md index 95c67922..6c5de17f 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ GNU Version 2 or Any Later Version ## Releases -[Official Release Version: 2.6.6](https://github.com/ultimatemember/ultimatemember/releases/tag/2.6.6). +[Official Release Version: 2.6.7](https://github.com/ultimatemember/ultimatemember/releases/tag/2.6.7). ## Changelog diff --git a/includes/admin/class-admin.php b/includes/admin/class-admin.php index 7a848412..d9131416 100644 --- a/includes/admin/class-admin.php +++ b/includes/admin/class-admin.php @@ -760,10 +760,10 @@ if ( ! class_exists( 'um\admin\Admin' ) ) { 'sanitize' => 'bool', ), '_max_selections' => array( - 'sanitize' => 'absint', + 'sanitize' => 'empty_int', ), '_min_selections' => array( - 'sanitize' => 'absint', + 'sanitize' => 'empty_int', ), '_max_entries' => array( 'sanitize' => 'absint', diff --git a/includes/core/class-fields.php b/includes/core/class-fields.php index 511d8568..687e940a 100644 --- a/includes/core/class-fields.php +++ b/includes/core/class-fields.php @@ -2556,7 +2556,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { } if ( ! empty( $data['label_confirm_pass'] ) ) { - $placeholder = __( $data['label_confirm_pass'], 'ultimate-member' );; + $placeholder = __( $data['label_confirm_pass'], 'ultimate-member' ); } elseif ( ! empty( $placeholder ) && ! isset( $data['label'] ) ) { /* translators: 1: placeholder. */ $placeholder = sprintf( __( 'Confirm %s', 'ultimate-member' ), $placeholder ); @@ -2637,7 +2637,12 @@ if ( ! class_exists( 'um\core\Fields' ) ) { $field_name = $key . $form_suffix; - $output .= ' + $disabled_weekdays = ''; + if ( isset( $data['disabled_weekdays'] ) ) { + $disabled_weekdays = '[' . implode( ',', $data['disabled_weekdays'] ) . ']'; + } + + $output .= ' '; @@ -2990,9 +2995,9 @@ if ( ! class_exists( 'um\core\Fields' ) ) { $output .= ''; /* modal hidden */ if ( empty( $disabled ) ) { - if ( ! isset( $allowed_types ) ) { + if ( ! isset( $data['allowed_types'] ) ) { $allowed_types = 'pdf,txt'; - } elseif ( is_array( $allowed_types ) ) { + } elseif ( is_array( $data['allowed_types'] ) ) { $allowed_types = implode( ',', $data['allowed_types'] ); } else { $allowed_types = $data['allowed_types']; diff --git a/includes/core/class-form.php b/includes/core/class-form.php index 76ce15f8..e5b07c09 100644 --- a/includes/core/class-form.php +++ b/includes/core/class-form.php @@ -55,6 +55,15 @@ if ( ! class_exists( 'um\core\Form' ) ) { */ public $all_fields = array(); + /** + * Whitelisted usermeta that can be stored when UM Form is submitted. + * + * @since 2.6.7 + * + * @var array + */ + public $usermeta_whitelist = array(); + /** * Form constructor. */ @@ -384,7 +393,7 @@ if ( ! class_exists( 'um\core\Form' ) ) { */ public function clean_submitted_data( $submitted ) { foreach ( $submitted as $metakey => $value ) { - if ( UM()->user()->is_metakey_banned( $metakey ) ) { + if ( UM()->user()->is_metakey_banned( $metakey/*, 'submission'*/ ) ) { unset( $submitted[ $metakey ] ); } } @@ -401,7 +410,7 @@ if ( ! class_exists( 'um\core\Form' ) ) { } else { $http_post = 'POST'; } - + // Handles Register, Profile and Login forms. if ( $http_post && ! is_admin() && isset( $_POST['form_id'] ) && is_numeric( $_POST['form_id'] ) ) { $this->form_id = absint( $_POST['form_id'] ); @@ -414,185 +423,272 @@ if ( ! class_exists( 'um\core\Form' ) ) { return; } - $this->form_data = UM()->query()->post_data( $this->form_id ); + // Verified that form_id is right and UM form is published. Then get form data. + + $this->form_data = UM()->query()->post_data( $this->form_id ); + + // Checking the form custom fields. Form without custom fields is invalid. + if ( ! array_key_exists( 'mode', $this->form_data ) ) { + return; + } + + // Checking the form custom fields. Form without custom fields is invalid. + if ( ! array_key_exists( 'custom_fields', $this->form_data ) ) { + return; + } + + $custom_fields = maybe_unserialize( $this->form_data['custom_fields'] ); + if ( ! is_array( $custom_fields ) || empty( $custom_fields ) ) { + return; + } + + $ignore_keys = array(); + + $field_types_without_metakey = UM()->builtin()->get_fields_without_metakey(); + foreach ( $custom_fields as $cf_k => $cf_data ) { + if ( ! array_key_exists( 'type', $cf_data ) || in_array( $cf_data['type'], $field_types_without_metakey, true ) ) { + unset( $custom_fields[ $cf_k ] ); + } + + if ( array_key_exists( 'type', $cf_data ) && 'password' === $cf_data['type'] ) { + $ignore_keys[] = $cf_k; + $ignore_keys[] = 'confirm_' . $cf_k; + } + + if ( 'profile' === $this->form_data['mode'] ) { + if ( ! empty( $cf_data['edit_forbidden'] ) ) { + $ignore_keys[] = $cf_k; + } + + if ( ! um_can_edit_field( $cf_data ) || ! um_can_view_field( $cf_data ) ) { + $ignore_keys[] = $cf_k; + } + } + + if ( ! array_key_exists( 'metakey', $cf_data ) || empty( $cf_data['metakey'] ) ) { + unset( $custom_fields[ $cf_k ] ); + } + + if ( isset( $cf_data['required_opt'] ) ) { + $opt = $cf_data['required_opt']; + if ( UM()->options()->get( $opt[0] ) !== $opt[1] ) { + $ignore_keys[] = $cf_k; + } + } + } + $cf_metakeys = array_column( $custom_fields, 'metakey' ); + $all_cf_metakeys = $cf_metakeys; + + // The '_um_last_login' cannot be updated through UM form. + $cf_metakeys = array_values( array_diff( $cf_metakeys, array( 'role_select', 'role_radio', 'role', '_um_last_login', 'user_pass', 'user_password', 'confirm_user_password' ) ) ); + if ( ! empty( $ignore_keys ) ) { + $cf_metakeys = array_values( array_diff( $cf_metakeys, $ignore_keys ) ); + } + // Remove restricted fields when edit profile. + if ( 'profile' === $this->form_data['mode'] ) { + // Column names from wp_users table. + $cf_metakeys = array_values( array_diff( $cf_metakeys, array( 'user_login' ) ) ); + // Hidden for edit fields + $cf_metakeys = array_values( array_diff( $cf_metakeys, UM()->fields()->get_restricted_fields_for_edit() ) ); + + $cf_metakeys[] = 'profile_photo'; + $cf_metakeys[] = 'cover_photo'; + } + // Add required usermeta for register. + if ( 'register' === $this->form_data['mode'] ) { + $cf_metakeys[] = 'form_id'; + $cf_metakeys[] = 'timestamp'; + } /** - * UM hook + * Filters whitelisted usermeta keys that can be stored inside DB after UM Form submission. * - * @type action - * @title um_before_submit_form_post - * @description Before submit form - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_before_submit_form_post', 'function_name', 10, 1 ); - * @example - * Extends whitelisted usermeta keys. + * function my_um_whitelisted_metakeys( $metakeys, $form_data ) { + * $metakeys[] = 'some_key'; + * return $metakeys; + * } + * add_filter( 'um_whitelisted_metakeys', 'my_um_whitelisted_metakeys', 10, 2 ); + */ + $cf_metakeys = apply_filters( 'um_whitelisted_metakeys', $cf_metakeys, $this->form_data ); + + // Important variable to prevent save unnecessary data to wp_usermeta. + $this->usermeta_whitelist = $cf_metakeys; + + /** + * Fires before UM login, registration or profile form submission. + * + * @since 1.3.x + * @hook um_before_submit_form_post + * + * @param {array} $post $_POST submission array. Deprecated since 2.0. + * @param {object} $this UM()->form() class instance. Since 2.6.7 + * + * @example Make any custom action before UM login, registration or profile form submission. + * function my_custom_before_submit_form_post( $um_form_obj ) { * // your code here * } - * ?> + * add_action( 'um_before_submit_form_post', 'my_custom_before_submit_form_post' ); */ - do_action( 'um_before_submit_form_post' ); + do_action( 'um_before_submit_form_post', $this ); /* save entire form as global */ /** - * UM hook + * Filters $_POST submitted data by the UM login, registration or profile form. * - * @type filter - * @title um_submit_post_form - * @description Change submitted data on form submit - * @input_vars - * [{"var":"$data","type":"array","desc":"Submitted data"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * Extends $_POST data. + * function my_submit_post_form( $_post ) { + * $_post['some_key'] = 'some value'; + * return $_post; * } - * ?> + * add_filter( 'um_submit_post_form', 'my_submit_post_form' ); */ $this->post_form = apply_filters( 'um_submit_post_form', wp_unslash( $_POST ) ); + // Validate form submission by honeypot. if ( isset( $this->post_form[ UM()->honeypot ] ) && '' !== $this->post_form[ UM()->honeypot ] ) { + // High level escape if hacking. wp_die( esc_html__( 'Hello, spam bot!', 'ultimate-member' ) ); } - $this->post_form = $this->beautify( $this->post_form ); - $this->post_form = $this->sanitize( $this->post_form ); - $this->post_form['submitted'] = $this->post_form; - - $this->post_form = array_merge( $this->form_data, $this->post_form ); + $this->post_form = $this->beautify( $this->post_form ); + // Validate and filter 'role' submitted data to avoid handling roles with admin privileges. // Remove role from post_form at first if role ! empty and there aren't custom fields with role name - if ( ! empty( $_POST['role'] ) ) { - if ( ! isset( $this->form_data['custom_fields'] ) || ! strstr( $this->form_data['custom_fields'], 'role_' ) ) { + $maybe_set_default_role = true; + if ( array_key_exists( 'role', $this->post_form ) ) { + if ( 'login' === $this->form_data['mode'] ) { unset( $this->post_form['role'] ); - unset( $this->post_form['submitted']['role'] ); - } - } - - // Secure sanitize of the submitted data - if ( ! empty( $this->post_form ) ) { - $this->post_form = $this->clean_submitted_data( $this->post_form ); - } - if ( ! empty( $this->post_form['submitted'] ) ) { - $this->post_form['submitted'] = $this->clean_submitted_data( $this->post_form['submitted'] ); - } - - // set default role from settings on registration form - if ( isset( $this->post_form['mode'] ) && 'register' === $this->post_form['mode'] ) { - $role = $this->assigned_role( $this->form_id ); - $this->post_form['role'] = $role; - } - - if ( isset( $this->form_data['custom_fields'] ) && strstr( $this->form_data['custom_fields'], 'role_' ) ) { // Secure selected role - - if ( ! empty( $_POST['role'] ) ) { - $custom_field_roles = $this->custom_field_roles( $this->form_data['custom_fields'] ); - - if ( ! empty( $custom_field_roles ) ) { - if ( is_array( $_POST['role'] ) ) { - $role = current( $_POST['role'] ); - $role = sanitize_key( $role ); - } else { - $role = sanitize_key( $_POST['role'] ); - } - - global $wp_roles; - $exclude_roles = array_diff( array_keys( $wp_roles->roles ), UM()->roles()->get_editable_user_roles() ); - - if ( ! empty( $role ) && - ( ! in_array( $role, $custom_field_roles, true ) || in_array( $role, $exclude_roles, true ) ) ) { - wp_die( esc_html__( 'This is not possible for security reasons.', 'ultimate-member' ) ); - } - - $this->post_form['role'] = $role; - $this->post_form['submitted']['role'] = $role; - } else { + } else { + $form_has_role_field = count( array_intersect( $all_cf_metakeys, array( 'role_select', 'role_radio' ) ) ) > 0; + if ( ! $form_has_role_field ) { unset( $this->post_form['role'] ); - unset( $this->post_form['submitted']['role'] ); + } else { + $custom_field_roles = $this->custom_field_roles( $this->form_data['custom_fields'] ); + if ( ! empty( $custom_field_roles ) ) { + if ( is_array( $this->post_form['role'] ) ) { + $role = current( $this->post_form['role'] ); + $role = sanitize_key( $role ); + } else { + $role = sanitize_key( $this->post_form['role'] ); + } + + global $wp_roles; + $exclude_roles = array_diff( array_keys( $wp_roles->roles ), UM()->roles()->get_editable_user_roles() ); + + if ( ! empty( $role ) && + ( ! in_array( $role, $custom_field_roles, true ) || in_array( $role, $exclude_roles, true ) ) ) { + // High level escape if hacking. + wp_die( esc_html__( 'This is not possible for security reasons.', 'ultimate-member' ) ); + } - // set default role for registration form if custom field hasn't proper value - if ( isset( $this->post_form['mode'] ) && 'register' === $this->post_form['mode'] ) { - $role = $this->assigned_role( $this->form_id ); $this->post_form['role'] = $role; + $maybe_set_default_role = false; } } } } - /** - * UM hook - * - * @type filter - * @title um_submit_form_data - * @description Change submitted data on form submit - * @input_vars - * [{"var":"$data","type":"array","desc":"Submitted data"}, - * {"var":"$mode","type":"string","desc":"Form mode"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $this->post_form = apply_filters( 'um_submit_form_data', $this->post_form, $this->post_form['mode'] ); + $this->post_form = $this->sanitize( $this->post_form ); + $this->post_form['submitted'] = $this->post_form; + // Set default role from settings on registration form. It has been made after defined 'submitted' because predefined role isn't a submitted field. + if ( $maybe_set_default_role && 'register' === $this->form_data['mode'] ) { + $role = $this->assigned_role( $this->form_id ); + $this->post_form['role'] = $role; + } + + /** + * Filters $_POST submitted data by the UM login, registration or profile form. + * It's un-slashed by `wp_unslash()`, beautified and sanitized. `role` attribute is filtered by possible role. + * `submitted` key is added by code and contains summary of submission. + * + * Internal Ultimate Member callbacks (Priority -> Callback name -> Excerpt): + * 9 - `um_submit_form_data_trim_fields()` maybe over-functionality and can be removed. + * 10 - `um_submit_form_data_role_fields()` important for conditional logic based on role fields in form. + * + * @param {array} $_post Submitted data. + * @param {string} $mode Form mode. login||register||profile + * @param {array} $all_cf_metakeys Form's metakeys. Since 2.6.7. + * + * @return {array} Submitted data. + * + * @since 1.3.x + * @hook um_submit_form_data + * + * @example Extends UM form submitted data. + * function my_submit_form_data( $_post, $mode, $all_cf_metakeys ) { + * $_post['some_key'] = 'some value'; + * return $_post; + * } + * add_filter( 'um_submit_form_data', 'my_submit_form_data', 10, 3 ); + */ + $this->post_form = apply_filters( 'um_submit_form_data', $this->post_form, $this->form_data['mode'], $all_cf_metakeys ); /* Continue based on form mode - pre-validation */ - /** - * UM hook + * Fires for validation UM login, registration or profile form submission. * - * @type action - * @title um_submit_form_errors_hook - * @description Action on submit form - * @input_vars - * [{"var":"$post","type":"int","desc":"Post data"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_errors_hook', 'function_name', 10, 1 ); - * @example - * Callback name -> Excerpt): + * 10 - `um_submit_form_errors_hook()` All form validation handlers. + * 20 - `um_recaptcha_validate()` reCAPTCHA form validation handlers. um-recaptcha extension. + * + * @since 1.3.x + * @hook um_submit_form_errors_hook + * + * @param {array} $post $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any common validation action here. + * function my_custom_before_submit_form_post( $post, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_submit_form_errors_hook', 'my_custom_submit_form_errors_hook', 10, 2 ); */ - do_action( 'um_submit_form_errors_hook', $this->post_form ); + do_action( 'um_submit_form_errors_hook', $this->post_form, $this->form_data ); + /* Continue based on form mode - store data. */ /** - * UM hook + * Fires for make main actions on UM login, registration or profile form submission. * - * @type action - * @title um_submit_form_{$mode} - * @description Action on submit form - * @input_vars - * [{"var":"$post","type":"int","desc":"Post data"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_{$mode}', 'function_name', 10, 1 ); - * @example - * Callback name -> Excerpt): + * ### um_submit_form_login: + * * 1 - `UM()->login()->verify_nonce()` Verify nonce. + * * 10 - `um_submit_form_login()` Login form main handler. + * ### um_submit_form_register: + * * 1 - `UM()->register()->verify_nonce()` Verify nonce. + * * 9 - `UM()->agreement_validation()` GDPR Agreement. + * * 9 - `UM()->terms_conditions()->agreement_validation()` Terms & Conditions Agreement. + * * 10 - `um_submit_form_register()` Register form main handler. + * ### um_submit_form_profile: + * * 10 - `um_submit_form_profile()` Profile form main handler. + * + * @since 1.3.x + * @hook um_submit_form_errors_hook + * + * @param {array} $post $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any custom action. + * function my_custom_before_submit_form_post( $post, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_submit_form_errors_hook', 'my_custom_submit_form_errors_hook', 10, 2 ); */ - do_action( "um_submit_form_{$this->post_form['mode']}", $this->post_form ); + do_action( "um_submit_form_{$this->form_data['mode']}", $this->post_form, $this->form_data ); } } @@ -716,7 +812,7 @@ if ( ! class_exists( 'um\core\Form' ) ) { ) ), ' /' - ); + ); } } } diff --git a/includes/core/class-gdpr.php b/includes/core/class-gdpr.php index 28be93ca..21397af4 100644 --- a/includes/core/class-gdpr.php +++ b/includes/core/class-gdpr.php @@ -1,71 +1,78 @@ form()->add_error( 'use_gdpr_agreement', isset( $args['use_gdpr_error_text'] ) ? $args['use_gdpr_error_text'] : '' ); + if ( $gdpr_enabled && ! isset( $submitted_data['submitted']['use_gdpr_agreement'] ) ) { + UM()->form()->add_error( 'use_gdpr_agreement', $use_gdpr_error_text ); } } + /** + * @param array $metakeys + * @param array $form_data + */ + public function extend_whitelisted( $metakeys, $form_data ) { + $gdpr_enabled = get_post_meta( $form_data['form_id'], '_um_register_use_gdpr', true ); + if ( ! empty( $gdpr_enabled ) ) { + $metakeys[] = 'use_gdpr_agreement'; + } + return $metakeys; + } /** * @param $submitted - * @param $args * * @return mixed */ - function add_agreement_date( $submitted, $args ) { + public function add_agreement_date( $submitted ) { if ( isset( $submitted['use_gdpr_agreement'] ) ) { $submitted['use_gdpr_agreement'] = time(); } @@ -73,21 +80,18 @@ if ( ! class_exists( 'um\core\GDPR' ) ) { return $submitted; } - /** * @param $submitted * * @return mixed */ - function email_registration_data( $submitted ) { + public function email_registration_data( $submitted ) { if ( ! empty( $submitted['use_gdpr_agreement'] ) ) { - $submitted['GDPR Applied'] = date( "d M Y H:i", $submitted['use_gdpr_agreement'] ); + $submitted['GDPR Applied'] = wp_date( get_option( 'date_format', 'Y-m-d' ) . ' ' . get_option( 'time_format', 'H:i:s' ), $submitted['use_gdpr_agreement'] ); unset( $submitted['use_gdpr_agreement'] ); } return $submitted; } - } - -} \ No newline at end of file +} diff --git a/includes/core/class-login.php b/includes/core/class-login.php index b825c759..10e857f7 100644 --- a/includes/core/class-login.php +++ b/includes/core/class-login.php @@ -1,13 +1,12 @@ - * @example - * + * @param {bool} $allow_nonce Is allowed verify nonce on login. By default, allowed = `true`. + * @param {array} $form_data Form's metakeys. Since 2.6.7. + * + * @return {bool} Is allowed verify. + * + * @since 2.0 + * @hook um_login_allow_nonce_verification + * + * @example Disable verifying nonce on the login page. + * add_filter( 'um_login_allow_nonce_verification', '__return_false' ); */ - $allow_nonce_verification = apply_filters( 'um_login_allow_nonce_verification', true ); - - if ( ! $allow_nonce_verification ) { - return $args; + $allow_nonce_verification = apply_filters( 'um_login_allow_nonce_verification', true, $form_data ); + if ( ! $allow_nonce_verification ) { + return; } - if ( ! wp_verify_nonce( $args['_wpnonce'], 'um_login_form' ) || empty( $args['_wpnonce'] ) || ! isset( $args['_wpnonce'] ) ) { - $url = apply_filters( 'um_login_invalid_nonce_redirect_url', add_query_arg( [ 'err' => 'invalid_nonce' ] ) ); - exit( wp_redirect( $url ) ); + if ( empty( $args['_wpnonce'] ) || ! wp_verify_nonce( $args['_wpnonce'], 'um_login_form' ) ) { + // @todo add hookdocs + $url = apply_filters( 'um_login_invalid_nonce_redirect_url', add_query_arg( array( 'err' => 'invalid_nonce' ) ) ); + wp_safe_redirect( $url ); + exit; } - - return $args; } - } - -} \ No newline at end of file +} diff --git a/includes/core/class-member-directory.php b/includes/core/class-member-directory.php index ec104cd9..3d8211cc 100644 --- a/includes/core/class-member-directory.php +++ b/includes/core/class-member-directory.php @@ -1458,11 +1458,12 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { // phpcs:ignore WordPress.Security.NonceVerification -- already verified here $sorting = sanitize_text_field( $_POST['sorting'] ); $sorting_fields = maybe_serialize( $directory_data['sorting_fields'] ); - - foreach ( $sorting_fields as $field ) { - if ( isset( $field[ $sorting ] ) ) { - $custom_sort_type = ! empty( $field['type'] ) ? $meta_query->get_cast_for_type( $field['type'] ) : 'CHAR'; - $custom_sort_order = $field['order']; + if ( ! empty( $sorting_fields ) && is_array( $sorting_fields ) ) { + foreach ( $sorting_fields as $field ) { + if ( isset( $field[ $sorting ] ) ) { + $custom_sort_type = ! empty( $field['type'] ) ? $meta_query->get_cast_for_type( $field['type'] ) : 'CHAR'; + $custom_sort_order = $field['order']; + } } } } diff --git a/includes/core/class-register.php b/includes/core/class-register.php index 4e42938c..833c2b28 100644 --- a/includes/core/class-register.php +++ b/includes/core/class-register.php @@ -1,29 +1,26 @@ - * @example - * + * @param {bool} $allow_nonce Is allowed verify nonce on register. By default, allowed = `true`. + * @param {array} $form_data Form's metakeys. Since 2.6.7. + * + * @return {bool} Is allowed verify. + * + * @since 2.0 + * @hook um_register_allow_nonce_verification + * + * @example Disable verifying nonce on the register page. + * add_filter( 'um_login_allow_nonce_verification', '__return_false' ); */ - $allow_nonce_verification = apply_filters( 'um_register_allow_nonce_verification', true ); - - if ( ! $allow_nonce_verification ) { - return $args; + $allow_nonce_verification = apply_filters( 'um_register_allow_nonce_verification', true, $form_data ); + if ( ! $allow_nonce_verification ) { + return; } - if ( ! wp_verify_nonce( $args['_wpnonce'], 'um_register_form' ) || empty( $args['_wpnonce'] ) || ! isset( $args['_wpnonce'] ) ) { - $url = apply_filters( 'um_register_invalid_nonce_redirect_url', add_query_arg( [ 'err' => 'invalid_nonce' ] ) ); - exit( wp_redirect( $url ) ); + if ( empty( $args['_wpnonce'] ) || ! wp_verify_nonce( $args['_wpnonce'], 'um_register_form' ) ) { + // @todo add hookdocs + $url = apply_filters( 'um_register_invalid_nonce_redirect_url', add_query_arg( array( 'err' => 'invalid_nonce' ) ) ); + wp_safe_redirect( $url ); + exit; } - - return $args; } - } -} \ No newline at end of file +} diff --git a/includes/core/class-user.php b/includes/core/class-user.php index 926433e5..914f1814 100644 --- a/includes/core/class-user.php +++ b/includes/core/class-user.php @@ -175,7 +175,7 @@ if ( ! class_exists( 'um\core\User' ) ) { * @param string $meta_key Usermeta key. * @return bool */ - public function is_metakey_banned( $meta_key ) { + public function is_metakey_banned( $meta_key, $context = '' ) { $is_banned = false; foreach ( $this->banned_keys as $ban ) { if ( is_numeric( $meta_key ) || false !== stripos( $meta_key, $ban ) || false !== stripos( remove_accents( $meta_key ), $ban ) ) { @@ -184,6 +184,10 @@ if ( ! class_exists( 'um\core\User' ) ) { } } + if ( ! $is_banned && 'submission' === $context && ! in_array( $meta_key, UM()->form()->usermeta_whitelist, true ) ) { + $is_banned = true; + } + return $is_banned; } @@ -192,9 +196,9 @@ if ( ! class_exists( 'um\core\User' ) ) { * * @since 2.6.4 * - * @param null|bool $check Whether to allow updating metadata for the given type. - * @param int $object_id ID of the object metadata is for. - * @param string $meta_key Metadata key. + * @param null|bool $check Whether to allow updating metadata for the given type. + * @param int $object_id ID of the object metadata is for. + * @param string $meta_key Metadata key. * * @return null|bool */ @@ -203,7 +207,7 @@ if ( ! class_exists( 'um\core\User' ) ) { return $check; } - if ( $this->is_metakey_banned( $meta_key ) ) { + if ( $this->is_metakey_banned( $meta_key, 'submission' ) ) { $check = false; } @@ -854,28 +858,8 @@ if ( ! class_exists( 'um\core\User' ) ) { UM()->user()->profile['role'] = sanitize_key( $_POST['um-role'] ); UM()->user()->update_usermeta_info( 'role' ); } - - /** - * UM hook - * - * @type action - * @title um_user_register - * @description Action on user registration - * @input_vars - * [{"var":"$user_id","type":"int","desc":"User ID"}, - * {"var":"$submitted","type":"array","desc":"Registration form submitted"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_user_register', 'function_name', 10, 2 ); - * @example - * - */ - do_action( 'um_user_register', $user_id, $_POST ); + /** This action is documented in ultimate-member/includes/common/um-actions-register.php */ + do_action( 'um_user_register', $user_id, $_POST, null ); } delete_transient( 'um_count_users_unassigned' ); @@ -1363,15 +1347,14 @@ if ( ! class_exists( 'um\core\User' ) ) { } - /** * Set user's registration details * * @param array $submitted * @param array $args + * @param array $form_data */ - function set_registration_details( $submitted, $args ) { - + public function set_registration_details( $submitted, $args, $form_data ) { if ( isset( $submitted['user_pass'] ) ) { unset( $submitted['user_pass'] ); } @@ -1387,7 +1370,7 @@ if ( ! class_exists( 'um\core\User' ) ) { //remove all password field values from submitted details $password_fields = array(); foreach ( $submitted as $k => $v ) { - if ( UM()->fields()->get_field_type( $k ) == 'password' ) { + if ( 'password' === UM()->fields()->get_field_type( $k ) ) { $password_fields[] = $k; $password_fields[] = 'confirm_' . $k; } @@ -1397,81 +1380,67 @@ if ( ! class_exists( 'um\core\User' ) ) { unset( $submitted[ $pw_field ] ); } - /** - * UM hook + * Filters submitted data before save usermeta "submitted" on registration process. * - * @type filter - * @title um_before_save_filter_submitted - * @description Change submitted data before save usermeta "submitted" on registration process - * @input_vars - * [{"var":"$submitted","type":"array","desc":"Submitted data"}, - * {"var":"$args","type":"array","desc":"Form Args"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * Change submitted data before save usermeta "submitted" on registration process. + * function my_before_save_filter_submitted( $submitted, $form_submitted_data, $form_data ) { * // your code here * return $submitted; * } - * ?> + * add_filter( 'um_before_save_filter_submitted', 'my_before_save_filter_submitted', 10, 3 ); */ - $submitted = apply_filters( 'um_before_save_filter_submitted', $submitted, $args ); + $submitted = apply_filters( 'um_before_save_filter_submitted', $submitted, $args, $form_data ); /** - * UM hook + * Fires before save registration details to the user. * - * @type action - * @title um_before_save_registration_details - * @description Action on user registration before save details - * @input_vars - * [{"var":"$user_id","type":"int","desc":"User ID"}, - * {"var":"$submitted","type":"array","desc":"Registration form submitted"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_before_save_registration_details', 'function_name', 10, 2 ); - * @example - * Make any custom action before save registration details to the user. + * function my_before_save_registration_details( $user_id, $submitted_data ) { * // your code here * } - * ?> + * add_action( 'um_before_save_registration_details', 'my_before_save_registration_details', 10, 2 ); */ do_action( 'um_before_save_registration_details', $this->id, $submitted ); update_user_meta( $this->id, 'submitted', $submitted ); $this->update_profile( $submitted ); + /** - * UM hook + * Fires after save registration details to the user. * - * @type action - * @title um_after_save_registration_details - * @description Action on user registration after save details - * @input_vars - * [{"var":"$user_id","type":"int","desc":"User ID"}, - * {"var":"$submitted","type":"array","desc":"Registration form submitted"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_after_save_registration_details', 'function_name', 10, 2 ); - * @example - * Make any custom action after save registration details to the user. + * function my_after_save_registration_details( $user_id, $submitted_data, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_after_save_registration_details', 'my_after_save_registration_details', 10, 3 ); */ - do_action( 'um_after_save_registration_details', $this->id, $submitted ); - + do_action( 'um_after_save_registration_details', $this->id, $submitted, $form_data ); } - /** * Set last login for new registered users */ @@ -2150,11 +2119,15 @@ if ( ! class_exists( 'um\core\User' ) ) { /** * Update profile * - * @param $changes + * @param array $changes + * @param string $context */ - public function update_profile( $changes ) { - $this->updating_process = true; - $args['ID'] = $this->id; + public function update_profile( $changes, $context = '' ) { + if ( 'account' !== $context ) { + $this->updating_process = true; + } + + $args['ID'] = $this->id; /** * Filters the update profile changes data. @@ -2177,9 +2150,8 @@ if ( ! class_exists( 'um\core\User' ) ) { * add_filter( 'um_before_update_profile', 'my_custom_before_update_profile', 10, 2 ); */ $changes = apply_filters( 'um_before_update_profile', $changes, $args['ID'] ); - foreach ( $changes as $key => $value ) { - if ( $this->is_metakey_banned( $key ) ) { + if ( $this->is_metakey_banned( $key, ( 'account' !== $context ) ? 'submission' : '' ) ) { continue; } @@ -2194,9 +2166,11 @@ if ( ! class_exists( 'um\core\User' ) ) { } } + $this->updating_process = false; + // update user if ( count( $args ) > 1 ) { - //if isset roles argument validate role to properly for security reasons + // If isset roles argument validate role to properly for security reasons if ( isset( $args['role'] ) ) { global $wp_roles; @@ -2208,10 +2182,8 @@ if ( ! class_exists( 'um\core\User' ) ) { wp_update_user( $args ); } - $this->updating_process = false; } - /** * User exists by meta key and value * diff --git a/includes/core/class-validation.php b/includes/core/class-validation.php index 9a5c54b2..b835b009 100644 --- a/includes/core/class-validation.php +++ b/includes/core/class-validation.php @@ -1,8 +1,9 @@ $value ) { if ( ! isset( $fields[ $key ] ) ) { @@ -70,7 +66,7 @@ if ( ! class_exists( 'um\core\Validation' ) ) { } //rating field validation - if ( isset( $fields[ $key ]['type'] ) && $fields[ $key ]['type'] == 'rating' ) { + if ( isset( $fields[ $key ]['type'] ) && 'rating' === $fields[ $key ]['type'] ) { if ( ! is_numeric( $value ) ) { unset( $changes[ $key ] ); } else { @@ -124,13 +120,11 @@ if ( ! class_exists( 'um\core\Validation' ) ) { $value = array_map( 'stripslashes', array_map( 'trim', $value ) ); $changes[ $key ] = array_intersect( $value, array_map( 'trim', $fields[ $key ]['options'] ) ); } - } return $changes; } - /** * Removes html from any string * diff --git a/includes/core/um-actions-account.php b/includes/core/um-actions-account.php index 44ef426d..2bd2366f 100644 --- a/includes/core/um-actions-account.php +++ b/includes/core/um-actions-account.php @@ -413,7 +413,7 @@ function um_submit_account_details( $args ) { } } - UM()->user()->update_profile( $changes ); + UM()->user()->update_profile( $changes, 'account' ); if ( UM()->account()->is_secure_enabled() ) { update_user_meta( $user_id, 'um_account_secure_fields', array() ); @@ -540,6 +540,7 @@ add_action( 'um_before_account_notifications', 'um_before_account_notifications' */ function um_after_user_account_updated_permalink( $user_id, $changes ) { if ( isset( $changes['first_name'] ) || isset( $changes['last_name'] ) ) { + /** This action is documented in ultimate-member/includes/core/um-actions-register.php */ do_action( 'um_update_profile_full_name', $user_id, $changes ); } } diff --git a/includes/core/um-actions-form.php b/includes/core/um-actions-form.php index 25c2a3e2..ab08f406 100644 --- a/includes/core/um-actions-form.php +++ b/includes/core/um-actions-form.php @@ -1,12 +1,14 @@ -options()->get( 'blocked_emails' ); if ( ! $emails ) { return; @@ -15,41 +17,39 @@ function um_submit_form_errors_hook__blockedemails( $args ) { $emails = strtolower( $emails ); $emails = array_map( 'rtrim', explode( "\n", $emails ) ); - if ( isset( $args['user_email'] ) && is_email( $args['user_email'] ) ) { - if ( in_array( strtolower( $args['user_email'] ), $emails ) ) { + if ( isset( $submitted_data['user_email'] ) && is_email( $submitted_data['user_email'] ) ) { + if ( in_array( strtolower( $submitted_data['user_email'] ), $emails ) ) { exit( wp_redirect( esc_url( add_query_arg( 'err', 'blocked_email' ) ) ) ); } - $domain = explode( '@', $args['user_email'] ); - $check_domain = str_replace( $domain[0], '*', $args['user_email'] ); + $domain = explode( '@', $submitted_data['user_email'] ); + $check_domain = str_replace( $domain[0], '*', $submitted_data['user_email'] ); if ( in_array( strtolower( $check_domain ), $emails ) ) { exit( wp_redirect( esc_url( add_query_arg( 'err', 'blocked_domain' ) ) ) ); } } - if ( isset( $args['username'] ) && is_email( $args['username'] ) ) { - if ( in_array( strtolower( $args['username'] ), $emails ) ) { + if ( isset( $submitted_data['username'] ) && is_email( $submitted_data['username'] ) ) { + if ( in_array( strtolower( $submitted_data['username'] ), $emails ) ) { exit( wp_redirect( esc_url( add_query_arg( 'err', 'blocked_email' ) ) ) ); } - $domain = explode( '@', $args['username'] ); - $check_domain = str_replace( $domain[0], '*', $args['username'] ); + $domain = explode( '@', $submitted_data['username'] ); + $check_domain = str_replace( $domain[0], '*', $submitted_data['username'] ); if ( in_array( strtolower( $check_domain ), $emails ) ) { exit( wp_redirect( esc_url( add_query_arg( 'err', 'blocked_domain' ) ) ) ); } } } -add_action( 'um_submit_form_errors_hook__blockedemails', 'um_submit_form_errors_hook__blockedemails', 10 ); +add_action( 'um_submit_form_errors_hook__blockedemails', 'um_submit_form_errors_hook__blockedemails' ); /** - * Error handling: blocked IPs - * - * @param $args + * Error handling: blocked IPs. */ -function um_submit_form_errors_hook__blockedips( $args ) { +function um_submit_form_errors_hook__blockedips() { $ips = UM()->options()->get( 'blocked_ips' ); if ( ! $ips ) { return; @@ -65,237 +65,214 @@ function um_submit_form_errors_hook__blockedips( $args ) { } } } -add_action( 'um_submit_form_errors_hook__blockedips', 'um_submit_form_errors_hook__blockedips', 10 ); - +add_action( 'um_submit_form_errors_hook__blockedips', 'um_submit_form_errors_hook__blockedips' ); /** * Error handling: blocked words during sign up * - * @param $args + * @todo change the hook after checking that conditions inside this callback can be run only while registration. + * + * @param array $submitted_data + * @param array $form_data */ -function um_submit_form_errors_hook__blockedwords( $args ) { +function um_submit_form_errors_hook__blockedwords( $submitted_data, $form_data ) { $words = UM()->options()->get( 'blocked_words' ); if ( empty( $words ) ) { return; } - $form_id = $args['form_id']; - $mode = $args['mode']; - $fields = unserialize( $args['custom_fields'] ); + $fields = maybe_unserialize( $form_data['custom_fields'] ); + if ( empty( $fields ) || ! is_array( $fields ) ) { + return; + } $words = strtolower( $words ); $words = array_map( 'rtrim', explode( "\n", $words ) ); - if ( ! empty( $fields ) && is_array( $fields ) ) { - foreach ( $fields as $key => $array ) { - if ( isset( $array['validate'] ) && in_array( $array['validate'], array( 'unique_username', 'unique_email', 'unique_username_or_email' ) ) ) { - if ( ! UM()->form()->has_error( $key ) && isset( $args[ $key ] ) && in_array( strtolower( $args[ $key ] ), $words ) ) { - UM()->form()->add_error( $key, __( 'You are not allowed to use this word as your username.', 'ultimate-member' ) ); - } + foreach ( $fields as $key => $array ) { + if ( isset( $array['validate'] ) && in_array( $array['validate'], array( 'unique_username', 'unique_email', 'unique_username_or_email' ), true ) ) { + if ( UM()->form()->has_error( $key ) ) { + continue; + } + + if ( array_key_exists( $key, $submitted_data ) && in_array( strtolower( $submitted_data[ $key ] ), $words, true ) ) { + UM()->form()->add_error( $key, __( 'You are not allowed to use this word as your username.', 'ultimate-member' ) ); } } } } -add_action( 'um_submit_form_errors_hook__blockedwords', 'um_submit_form_errors_hook__blockedwords', 10 ); - +add_action( 'um_submit_form_errors_hook__blockedwords', 'um_submit_form_errors_hook__blockedwords', 10, 2 ); /** - * Error handling + * UM login|register|profile form error handling. * - * @param $args + * @param array $submitted_data + * @param array $form_data */ -function um_submit_form_errors_hook( $args ) { - $mode = $args['mode']; +function um_submit_form_errors_hook( $submitted_data, $form_data ) { + $mode = $form_data['mode']; /** - * UM hook + * Fires for validation blocked IPs when UM login, registration or profile form has been submitted. * - * @type action - * @title um_submit_form_errors_hook__blockedips - * @description Submit form validation - * @input_vars - * [{"var":"$args","type":"array","desc":"Form Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_errors_hook__blockedips', 'function_name', 10, 1 ); - * @example - * Callback name -> Excerpt): + * 10 - `um_submit_form_errors_hook__blockedips()` Native validation handlers. + * + * @since 1.3.x + * @hook um_submit_form_errors_hook__blockedips + * + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any common validation action when login, registation or profile form is submitted. + * function my_submit_form_errors_hook__blockedips( $post, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_submit_form_errors_hook__blockedips', 'my_submit_form_errors_hook__blockedips', 10, 2 ); */ - do_action( 'um_submit_form_errors_hook__blockedips', $args ); - - + do_action( 'um_submit_form_errors_hook__blockedips', $submitted_data, $form_data ); /** - * UM hook + * Fires for validation blocked email addresses when UM login, registration or profile form has been submitted. * - * @type action - * @title um_submit_form_errors_hook__blockedemails - * @description Submit form validation - * @input_vars - * [{"var":"$args","type":"array","desc":"Form Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_errors_hook__blockedemails', 'function_name', 10, 1 ); - * @example - * Callback name -> Excerpt): + * 10 - `um_submit_form_errors_hook__blockedemails()` Native validation handlers. + * + * @since 1.3.x + * @hook um_submit_form_errors_hook__blockedemails + * + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any common validation action when login, registation or profile form is submitted. + * function my_submit_form_errors_hook__blockedemails( $post, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_submit_form_errors_hook__blockedemails', 'my_submit_form_errors_hook__blockedemails', 10, 2 ); */ - do_action( 'um_submit_form_errors_hook__blockedemails', $args ); - - if ( $mode == 'register' ) { - + do_action( 'um_submit_form_errors_hook__blockedemails', $submitted_data, $form_data ); + if ( 'login' === $mode ) { /** - * UM hook + * Fires for login form validation when it has been submitted. * - * @type action - * @title um_submit_form_errors_hook__registration - * @description Submit registration form validation - * @input_vars - * [{"var":"$args","type":"array","desc":"Form Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_errors_hook__registration', 'function_name', 10, 1 ); - * @example - * Callback name -> Excerpt): + * 10 - `um_submit_form_errors_hook_login()` Native login validation handlers. + * + * @since 1.3.x + * @hook um_submit_form_errors_hook_login + * + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any validation action when login form is submitted. + * function my_submit_form_errors_hook_login( $post, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_submit_form_errors_hook_login', 'my_submit_form_errors_hook_login', 10, 2 ); */ - do_action( 'um_submit_form_errors_hook__registration', $args ); - - } elseif ( $mode == 'profile' ) { - - + do_action( 'um_submit_form_errors_hook_login', $submitted_data, $form_data ); /** - * UM hook + * Fires for login form validation when it has been submitted. * - * @type action - * @title um_submit_form_errors_hook__registration - * @description Submit registration form validation - * @input_vars - * [{"var":"$args","type":"array","desc":"Form Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_errors_hook__registration', 'function_name', 10, 1 ); - * @example - * Callback name -> Excerpt): + * 9999 - `um_submit_form_errors_hook_logincheck()` Native login validation handlers. + * + * @since 1.3.x + * @hook um_submit_form_errors_hook_logincheck + * + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any validation action when login form is submitted. + * function my_submit_form_errors_hook_logincheck( $post, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_submit_form_errors_hook_logincheck', 'my_submit_form_errors_hook_logincheck', 10, 2 ); */ - do_action( 'um_submit_form_errors_hook__profile', $args ); - - } elseif ( $mode == 'login' ) { - + do_action( 'um_submit_form_errors_hook_logincheck', $submitted_data, $form_data ); + } else { + if ( 'register' === $mode ) { + /** + * Fires for registration form validation when it has been submitted. + * + * Internal Ultimate Member callbacks (Priority -> Callback name -> Excerpt): + * 10 - `um_submit_form_errors_hook__registration()` Native registration validation handlers. + * + * @since 1.3.x + * @hook um_submit_form_errors_hook__registration + * + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any validation action when registration form submitted. + * function my_submit_form_errors_hook__registration( $submitted_data, $form_data ) { + * // your code here + * } + * add_action( 'um_submit_form_errors_hook__registration', 'my_submit_form_errors_hook__registration', 10, 2 ); + */ + do_action( 'um_submit_form_errors_hook__registration', $submitted_data, $form_data ); + } elseif ( 'profile' === $mode ) { + /** + * Fires for profile form validation when it has been submitted. + * + * Internal Ultimate Member callbacks (Priority -> Callback name -> Excerpt): + * 1 - `um_profile_validate_nonce()` Validate nonce. + * + * @since 2.0 + * @hook um_submit_form_errors_hook__profile + * + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any validation action when profile form submitted. + * function my_submit_form_errors_hook__profile( $submitted_data, $form_data ) { + * // your code here + * } + * add_action( 'um_submit_form_errors_hook__profile', 'my_submit_form_errors_hook__profile', 10, 2 ); + */ + do_action( 'um_submit_form_errors_hook__profile', $submitted_data, $form_data ); + } /** - * UM hook + * Fires for registration and profile forms validation when it has been submitted. * - * @type action - * @title um_submit_form_errors_hook_login - * @description Submit login form validation - * @input_vars - * [{"var":"$args","type":"array","desc":"Form Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_errors_hook_login', 'function_name', 10, 1 ); - * @example - * Callback name -> Excerpt): + * 10 - `um_submit_form_errors_hook__blockedwords()` Validate username and email from blocked words. + * + * @since 1.3.x + * @hook um_submit_form_errors_hook__blockedwords + * + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any validation action when registration or profile form submitted. + * function my_submit_form_errors_hook__blockedwords( $submitted_data, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_submit_form_errors_hook__blockedwords', 'my_submit_form_errors_hook__blockedwords', 10, 2 ); */ - do_action( 'um_submit_form_errors_hook_login', $args ); - - + do_action( 'um_submit_form_errors_hook__blockedwords', $submitted_data, $form_data ); /** - * UM hook + * Fires for registration and profile forms validation when it has been submitted. * - * @type action - * @title um_submit_form_errors_hook_logincheck - * @description Submit login form validation - * @input_vars - * [{"var":"$args","type":"array","desc":"Form Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_errors_hook_logincheck', 'function_name', 10, 1 ); - * @example - * Callback name -> Excerpt): + * 10 - `um_submit_form_errors_hook_()` Run field validations. + * + * @since 1.3.x + * @hook um_submit_form_errors_hook_ + * + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any validation action when registration or profile form submitted. + * function my_submit_form_errors_hook( $submitted_data, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_submit_form_errors_hook_', 'my_submit_form_errors_hook', 10, 2 ); */ - do_action( 'um_submit_form_errors_hook_logincheck', $args ); - + do_action( 'um_submit_form_errors_hook_', $submitted_data, $form_data ); } - - - if ( $mode != 'login' ) { - - - /** - * UM hook - * - * @type action - * @title um_submit_form_errors_hook__blockedwords - * @description Submit form validation - * @input_vars - * [{"var":"$args","type":"array","desc":"Form Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_errors_hook__blockedwords', 'function_name', 10, 1 ); - * @example - * - */ - do_action( 'um_submit_form_errors_hook__blockedwords', $args ); - - - /** - * UM hook - * - * @type action - * @title um_submit_form_errors_hook_ - * @description Submit form validation - * @input_vars - * [{"var":"$args","type":"array","desc":"Form Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_submit_form_errors_hook_', 'function_name', 10, 1 ); - * @example - * - */ - do_action( 'um_submit_form_errors_hook_', $args ); - - } - } -add_action( 'um_submit_form_errors_hook', 'um_submit_form_errors_hook', 10 ); +add_action( 'um_submit_form_errors_hook', 'um_submit_form_errors_hook', 10, 2 ); /** @@ -303,12 +280,12 @@ add_action( 'um_submit_form_errors_hook', 'um_submit_form_errors_hook', 10 ); * @staticvar int $counter * @param array $condition * @param array $fields - * @param array $args + * @param array $submitted_data * @param boolean $reset * @return boolean * @throws Exception */ -function um_check_conditions_on_submit( $condition, $fields, $args, $reset = false ) { +function um_check_conditions_on_submit( $condition, $fields, $submitted_data, $reset = false ) { static $counter = 0; if ( $reset ) { $counter = 0; @@ -317,7 +294,7 @@ function um_check_conditions_on_submit( $condition, $fields, $args, $reset = fal list( $visibility, $parent_key, $op, $parent_value ) = $condition; - if ( ! isset( $args[ $parent_key ] ) ) { + if ( ! isset( $submitted_data[ $parent_key ] ) ) { $continue = true; return $continue; } @@ -325,7 +302,7 @@ function um_check_conditions_on_submit( $condition, $fields, $args, $reset = fal if ( ! empty( $fields[ $parent_key ]['conditions'] ) ) { foreach ( $fields[ $parent_key ]['conditions'] as $parent_condition ) { if ( 64 > $counter++ ) { - $continue = um_check_conditions_on_submit( $parent_condition, $fields, $args ); + $continue = um_check_conditions_on_submit( $parent_condition, $fields, $submitted_data ); } else { throw new Exception( 'Endless recursion in the function ' . __FUNCTION__, 512 ); } @@ -335,7 +312,7 @@ function um_check_conditions_on_submit( $condition, $fields, $args, $reset = fal } } - $cond_value = ( $fields[ $parent_key ]['type'] == 'radio' ) ? $args[ $parent_key ][0] : $args[ $parent_key ]; + $cond_value = ( $fields[ $parent_key ]['type'] == 'radio' ) ? $submitted_data[ $parent_key ][0] : $submitted_data[ $parent_key ]; if ( $visibility == 'hide' ) { if ( $op == 'empty' ) { @@ -408,540 +385,539 @@ function um_check_conditions_on_submit( $condition, $fields, $args, $reset = fal return $continue; } - /** * Error processing hook : standard * - * @param $args + * @param array $submitted_data + * @param array $form_data */ -function um_submit_form_errors_hook_( $args ) { - $form_id = $args['form_id']; - $mode = $args['mode']; - $fields = unserialize( $args['custom_fields'] ); +function um_submit_form_errors_hook_( $submitted_data, $form_data ) { + $form_id = $form_data['form_id']; + $mode = $form_data['mode']; - $um_profile_photo = um_profile('profile_photo'); - if ( get_post_meta( $form_id, '_um_profile_photo_required', true ) && ( empty( $args['profile_photo'] ) && empty( $um_profile_photo ) ) ) { - UM()->form()->add_error('profile_photo', __( 'Profile Photo is required.', 'ultimate-member' ) ); + $fields = maybe_unserialize( $form_data['custom_fields'] ); + if ( empty( $fields ) || ! is_array( $fields ) ) { + return; } - if ( ! empty( $fields ) ) { - $can_edit = false; - $current_user_roles = array(); - if ( is_user_logged_in() ) { - if ( array_key_exists( 'user_id', $args ) ) { - $can_edit = UM()->roles()->um_current_user_can( 'edit', $args['user_id'] ); - } + $um_profile_photo = um_profile( 'profile_photo' ); + if ( empty( $submitted_data['profile_photo'] ) && empty( $um_profile_photo ) && get_post_meta( $form_id, '_um_profile_photo_required', true ) ) { + UM()->form()->add_error( 'profile_photo', __( 'Profile Photo is required.', 'ultimate-member' ) ); + } - um_fetch_user( get_current_user_id() ); - $current_user_roles = um_user( 'roles' ); - um_reset_user(); + $can_edit = false; + $current_user_roles = array(); + if ( is_user_logged_in() ) { + if ( array_key_exists( 'user_id', $submitted_data ) ) { + $can_edit = UM()->roles()->um_current_user_can( 'edit', $submitted_data['user_id'] ); } - foreach ( $fields as $key => $array ) { + um_fetch_user( get_current_user_id() ); + $current_user_roles = um_user( 'roles' ); + um_reset_user(); + } - if ( 'profile' === $mode ) { - $restricted_fields = UM()->fields()->get_restricted_fields_for_edit(); - if ( is_array( $restricted_fields ) && in_array( $key, $restricted_fields ) ) { - continue; - } - } + foreach ( $fields as $key => $array ) { - $can_view = true; - if ( isset( $array['public'] ) && 'register' !== $mode ) { - - switch ( $array['public'] ) { - case '1': // Everyone - break; - case '2': // Members - if ( ! is_user_logged_in() ) { - $can_view = false; - } - break; - case '-1': // Only visible to profile owner and admins - if ( ! is_user_logged_in() ) { - $can_view = false; - } elseif ( $args['user_id'] != get_current_user_id() && ! $can_edit ) { - $can_view = false; - } - break; - case '-2': // Only specific member roles - if ( ! is_user_logged_in() ) { - $can_view = false; - } elseif ( ! empty( $array['roles'] ) && count( array_intersect( $current_user_roles, $array['roles'] ) ) <= 0 ) { - $can_view = false; - } - break; - case '-3': // Only visible to profile owner and specific roles - if ( ! is_user_logged_in() ) { - $can_view = false; - } elseif ( $args['user_id'] != get_current_user_id() && ! empty( $array['roles'] ) && count( array_intersect( $current_user_roles, $array['roles'] ) ) <= 0 ) { - $can_view = false; - } - break; - default: - $can_view = apply_filters( 'um_can_view_field_custom', $can_view, $array ); - break; - } - - } - - $can_view = apply_filters( 'um_can_view_field', $can_view, $array ); - - if ( ! $can_view ) { + if ( 'profile' === $mode ) { + $restricted_fields = UM()->fields()->get_restricted_fields_for_edit(); + if ( is_array( $restricted_fields ) && in_array( $key, $restricted_fields, true ) ) { continue; } + } - /** - * UM hook - * - * @type filter - * @title um_get_custom_field_array - * @description Extend custom field data on submit form error - * @input_vars - * [{"var":"$array","type":"array","desc":"Field data"}, - * {"var":"$fields","type":"array","desc":"All fields"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $array = apply_filters( 'um_get_custom_field_array', $array, $fields ); + $can_view = true; + if ( isset( $array['public'] ) && 'register' !== $mode ) { - if ( ! empty( $array['conditions'] ) ) { - try { - foreach ( $array['conditions'] as $condition ) { - $continue = um_check_conditions_on_submit( $condition, $fields, $args, true ); - if ( $continue === true ) { - continue 2; - } + switch ( $array['public'] ) { + case '1': // Everyone + break; + case '2': // Members + if ( ! is_user_logged_in() ) { + $can_view = false; } - } catch ( Exception $e ) { - UM()->form()->add_error( $key, sprintf( __( '%s - wrong conditions.', 'ultimate-member' ), $array['title'] ) ); - $notice = '
' . sprintf( __( '%s - wrong conditions.', 'ultimate-member' ), $array['title'] ) . '
'; - add_action( 'um_after_profile_fields', function() use ( $notice ) { - echo $notice; - }, 900 ); + break; + case '-1': // Only visible to profile owner and admins + if ( ! is_user_logged_in() ) { + $can_view = false; + } elseif ( $submitted_data['user_id'] != get_current_user_id() && ! $can_edit ) { + $can_view = false; + } + break; + case '-2': // Only specific member roles + if ( ! is_user_logged_in() ) { + $can_view = false; + } elseif ( ! empty( $array['roles'] ) && count( array_intersect( $current_user_roles, $array['roles'] ) ) <= 0 ) { + $can_view = false; + } + break; + case '-3': // Only visible to profile owner and specific roles + if ( ! is_user_logged_in() ) { + $can_view = false; + } elseif ( $submitted_data['user_id'] != get_current_user_id() && ! empty( $array['roles'] ) && count( array_intersect( $current_user_roles, $array['roles'] ) ) <= 0 ) { + $can_view = false; + } + break; + default: + $can_view = apply_filters( 'um_can_view_field_custom', $can_view, $array ); + break; + } + } + + $can_view = apply_filters( 'um_can_view_field', $can_view, $array ); + + if ( ! $can_view ) { + continue; + } + + /** + * UM hook + * + * @type filter + * @title um_get_custom_field_array + * @description Extend custom field data on submit form error + * @input_vars + * [{"var":"$array","type":"array","desc":"Field data"}, + * {"var":"$fields","type":"array","desc":"All fields"}] + * @change_log + * ["Since: 2.0"] + * @usage + * + * @example + * + */ + $array = apply_filters( 'um_get_custom_field_array', $array, $fields ); + + if ( ! empty( $array['conditions'] ) ) { + try { + foreach ( $array['conditions'] as $condition ) { + $continue = um_check_conditions_on_submit( $condition, $fields, $submitted_data, true ); + if ( $continue === true ) { + continue 2; + } + } + } catch ( Exception $e ) { + UM()->form()->add_error( $key, sprintf( __( '%s - wrong conditions.', 'ultimate-member' ), $array['title'] ) ); + $notice = '
' . sprintf( __( '%s - wrong conditions.', 'ultimate-member' ), $array['title'] ) . '
'; + add_action( 'um_after_profile_fields', function() use ( $notice ) { + echo $notice; + }, 900 ); + } + } + + if ( isset( $array['type'] ) && $array['type'] == 'checkbox' && isset( $array['required'] ) && $array['required'] == 1 && ! isset( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, sprintf( __( '%s is required.', 'ultimate-member' ), $array['title'] ) ); + } + + if ( isset( $array['type'] ) && $array['type'] == 'radio' && isset( $array['required'] ) && $array['required'] == 1 && ! isset( $submitted_data[ $key ] ) && ! in_array( $key, array( 'role_radio', 'role_select' ) ) ) { + UM()->form()->add_error( $key, sprintf( __( '%s is required.', 'ultimate-member'), $array['title'] ) ); + } + + if ( isset( $array['type'] ) && $array['type'] == 'multiselect' && isset( $array['required'] ) && $array['required'] == 1 && ! isset( $submitted_data[ $key ] ) && ! in_array( $key, array( 'role_radio', 'role_select' ) ) ) { + UM()->form()->add_error( $key, sprintf( __( '%s is required.', 'ultimate-member' ), $array['title'] ) ); + } + + /* WordPress uses the default user role if the role wasn't chosen in the registration form. That is why we should use submitted data to validate fields Roles (Radio) and Roles (Dropdown). */ + if ( in_array( $key, array( 'role_radio', 'role_select' ) ) && isset( $array['required'] ) && $array['required'] == 1 && empty( UM()->form()->post_form['submitted']['role'] ) ) { + UM()->form()->add_error( 'role', __( 'Please specify account type.', 'ultimate-member' ) ); + UM()->form()->post_form[ $key ] = ''; + } + + /** + * UM hook + * + * @type action + * @title um_add_error_on_form_submit_validation + * @description Submit form validation + * @input_vars + * [{"var":"$field","type":"array","desc":"Field Data"}, + * {"var":"$key","type":"string","desc":"Field Key"}, + * {"var":"$args","type":"array","desc":"Form Arguments"}] + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_add_error_on_form_submit_validation', 'function_name', 10, 3 ); + * @example + * + */ + do_action( 'um_add_error_on_form_submit_validation', $array, $key, $submitted_data ); + + if ( ! empty( $array['required'] ) ) { + if ( ! isset( $submitted_data[ $key ] ) || $submitted_data[ $key ] == '' || $submitted_data[ $key ] == 'empty_file' ) { + if ( empty( $array['label'] ) ) { + UM()->form()->add_error( $key, __( 'This field is required', 'ultimate-member' ) ); + } else { + UM()->form()->add_error( $key, sprintf( __( '%s is required', 'ultimate-member' ), $array['label'] ) ); } } + } - if ( isset( $array['type'] ) && $array['type'] == 'checkbox' && isset( $array['required'] ) && $array['required'] == 1 && ! isset( $args[ $key ] ) ) { - UM()->form()->add_error( $key, sprintf( __( '%s is required.', 'ultimate-member' ), $array['title'] ) ); + if ( ! isset( $submitted_data[ $key ] ) ) { + continue; + } + + if ( isset( $array['max_words'] ) && $array['max_words'] > 0 ) { + if ( str_word_count( $submitted_data[ $key ], 0, "éèàôù" ) > $array['max_words'] ) { + UM()->form()->add_error( $key, sprintf( __( 'You are only allowed to enter a maximum of %s words', 'ultimate-member' ), $array['max_words'] ) ); } + } - if ( isset( $array['type'] ) && $array['type'] == 'radio' && isset( $array['required'] ) && $array['required'] == 1 && ! isset( $args[ $key ] ) && ! in_array( $key, array( 'role_radio', 'role_select' ) ) ) { - UM()->form()->add_error( $key, sprintf( __( '%s is required.', 'ultimate-member'), $array['title'] ) ); - } - - if ( isset( $array['type'] ) && $array['type'] == 'multiselect' && isset( $array['required'] ) && $array['required'] == 1 && ! isset( $args[ $key ] ) && ! in_array( $key, array( 'role_radio', 'role_select' ) ) ) { - UM()->form()->add_error( $key, sprintf( __( '%s is required.', 'ultimate-member' ), $array['title'] ) ); - } - - /* WordPress uses the default user role if the role wasn't chosen in the registration form. That is why we should use submitted data to validate fields Roles (Radio) and Roles (Dropdown). */ - if ( in_array( $key, array( 'role_radio', 'role_select' ) ) && isset( $array['required'] ) && $array['required'] == 1 && empty( UM()->form()->post_form['submitted']['role'] ) ) { - UM()->form()->add_error( 'role', __( 'Please specify account type.', 'ultimate-member' ) ); - UM()->form()->post_form[ $key ] = ''; - } - - /** - * UM hook - * - * @type action - * @title um_add_error_on_form_submit_validation - * @description Submit form validation - * @input_vars - * [{"var":"$field","type":"array","desc":"Field Data"}, - * {"var":"$key","type":"string","desc":"Field Key"}, - * {"var":"$args","type":"array","desc":"Form Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_add_error_on_form_submit_validation', 'function_name', 10, 3 ); - * @example - * - */ - do_action( 'um_add_error_on_form_submit_validation', $array, $key, $args ); - - if ( ! empty( $array['required'] ) ) { - if ( ! isset( $args[ $key ] ) || $args[ $key ] == '' || $args[ $key ] == 'empty_file' ) { - if ( empty( $array['label'] ) ) { - UM()->form()->add_error( $key, __( 'This field is required', 'ultimate-member' ) ); - } else { - UM()->form()->add_error( $key, sprintf( __( '%s is required', 'ultimate-member' ), $array['label'] ) ); - } + if ( isset( $array['min_chars'] ) && $array['min_chars'] > 0 ) { + if ( $submitted_data[ $key ] && mb_strlen( $submitted_data[ $key ] ) < $array['min_chars'] ) { + if ( empty( $array['label'] ) ) { + UM()->form()->add_error( $key, sprintf( __( 'This field must contain at least %s characters', 'ultimate-member' ), $array['min_chars'] ) ); + } else { + UM()->form()->add_error( $key, sprintf( __( 'Your %s must contain at least %s characters', 'ultimate-member' ), $array['label'], $array['min_chars'] ) ); } } + } - if ( isset( $args[ $key ] ) ) { + if ( isset( $array['max_chars'] ) && $array['max_chars'] > 0 ) { + if ( $submitted_data[ $key ] && mb_strlen( $submitted_data[ $key ] ) > $array['max_chars'] ) { + if ( empty( $array['label'] ) ) { + UM()->form()->add_error( $key, sprintf( __( 'This field must contain less than %s characters', 'ultimate-member' ), $array['max_chars'] ) ); + } else { + UM()->form()->add_error( $key, sprintf( __( 'Your %s must contain less than %s characters', 'ultimate-member' ), $array['label'], $array['max_chars'] ) ); + } + } + } - if ( isset( $array['max_words'] ) && $array['max_words'] > 0 ) { - if ( str_word_count( $args[ $key ], 0, "éèàôù" ) > $array['max_words'] ) { - UM()->form()->add_error( $key, sprintf( __( 'You are only allowed to enter a maximum of %s words', 'ultimate-member' ), $array['max_words'] ) ); - } + if ( isset( $array['type'] ) && $array['type'] == 'textarea' && UM()->profile()->get_show_bio_key( $submitted_data ) !== $key ) { + if ( ! isset( $array['html'] ) || $array['html'] == 0 ) { + if ( wp_strip_all_tags( $submitted_data[ $key ] ) != trim( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'You can not use HTML tags here', 'ultimate-member' ) ); + } + } + } + + if ( isset( $array['force_good_pass'] ) && $array['force_good_pass'] && ! empty( $submitted_data['user_password'] ) ) { + if ( isset( $submitted_data['user_login'] ) && strpos( strtolower( $submitted_data['user_login'] ), strtolower( $submitted_data['user_password'] ) ) > -1 ) { + UM()->form()->add_error( 'user_password', __( 'Your password cannot contain the part of your username', 'ultimate-member' )); + } + + if ( isset( $submitted_data['user_email'] ) && strpos( strtolower( $submitted_data['user_email'] ), strtolower( $submitted_data['user_password'] ) ) > -1 ) { + UM()->form()->add_error( 'user_password', __( 'Your password cannot contain the part of your email address', 'ultimate-member' )); + } + + if ( ! UM()->validation()->strong_pass( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'Your password must contain at least one lowercase letter, one capital letter and one number', 'ultimate-member' ) ); + } + } + + if ( ! empty( $array['force_confirm_pass'] ) ) { + if ( ! array_key_exists( 'confirm_' . $key, $submitted_data ) && ! UM()->form()->has_error( $key ) ) { + UM()->form()->add_error( 'confirm_' . $key, __( 'Please confirm your password', 'ultimate-member' ) ); + } else { + if ( '' === $submitted_data[ 'confirm_' . $key ] && ! UM()->form()->has_error( $key ) ) { + UM()->form()->add_error( 'confirm_' . $key, __( 'Please confirm your password', 'ultimate-member' ) ); + } + if ( $submitted_data[ 'confirm_' . $key ] !== $submitted_data[ $key ] && ! UM()->form()->has_error( $key ) ) { + UM()->form()->add_error( 'confirm_' . $key, __( 'Your passwords do not match', 'ultimate-member' ) ); + } + } + } + + if ( isset( $array['min_selections'] ) && $array['min_selections'] > 0 ) { + if ( ( ! isset( $submitted_data[ $key ] ) ) || ( isset( $submitted_data[ $key ] ) && is_array( $submitted_data[ $key ] ) && count( $submitted_data[ $key ] ) < $array['min_selections'] ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please select at least %s choices', 'ultimate-member' ), $array['min_selections'] ) ); + } + } + + if ( isset( $array['max_selections'] ) && $array['max_selections'] > 0 ) { + if ( isset( $submitted_data[ $key ] ) && is_array( $submitted_data[ $key ] ) && count( $submitted_data[ $key ] ) > $array['max_selections'] ) { + UM()->form()->add_error( $key, sprintf( __( 'You can only select up to %s choices', 'ultimate-member' ), $array['max_selections'] ) ); + } + } + + if ( isset( $array['min'] ) && is_numeric( $submitted_data[ $key ] ) ) { + if ( isset( $submitted_data[ $key ] ) && $submitted_data[ $key ] < $array['min'] ) { + UM()->form()->add_error( $key, sprintf( __( 'Minimum number limit is %s', 'ultimate-member' ), $array['min'] ) ); + } + } + + if ( isset( $array['max'] ) && is_numeric( $submitted_data[ $key ] ) ) { + if ( isset( $submitted_data[ $key ] ) && $submitted_data[ $key ] > $array['max'] ) { + UM()->form()->add_error( $key, sprintf( __( 'Maximum number limit is %s', 'ultimate-member' ), $array['max'] ) ); + } + } + + if ( empty( $array['validate'] ) ) { + continue; + } + + switch ( $array['validate'] ) { + + case 'custom': + $custom = $array['custom_validate']; + /** + * UM hook + * + * @type action + * @title um_custom_field_validation_{$custom} + * @description Submit form validation for custom field + * @input_vars + * [{"var":"$key","type":"string","desc":"Field Key"}, + * {"var":"$field","type":"array","desc":"Field Data"}, + * {"var":"$args","type":"array","desc":"Form Arguments"}] + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_custom_field_validation_{$custom}', 'function_name', 10, 3 ); + * @example + * + */ + do_action( "um_custom_field_validation_{$custom}", $key, $array, $submitted_data ); + break; + + case 'numeric': + if ( $submitted_data[ $key ] && ! is_numeric( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'Please enter numbers only in this field', 'ultimate-member' ) ); + } + break; + + case 'phone_number': + if ( ! UM()->validation()->is_phone_number( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'Please enter a valid phone number', 'ultimate-member' ) ); + } + break; + + case 'youtube_url': + if ( ! UM()->validation()->is_url( $submitted_data[ $key ], 'youtube.com' ) && ! UM()->validation()->is_url( $submitted_data[ $key ], 'youtu.be' ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL', 'ultimate-member' ), $array['label'] ) ); + } + break; + + case 'spotify_url': + if ( ! UM()->validation()->is_url( $submitted_data[ $key ], 'open.spotify.com' ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s URL', 'ultimate-member' ), $array['label'] ) ); + } + break; + + case 'telegram_url': + if ( ! UM()->validation()->is_url( $submitted_data[ $key ], 't.me' ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL', 'ultimate-member' ), $array['label'] ) ); + } + break; + + case 'soundcloud_url': + if ( ! UM()->validation()->is_url( $submitted_data[ $key ], 'soundcloud.com' ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL','ultimate-member'), $array['label'] ) ); + } + break; + + case 'facebook_url': + if ( ! UM()->validation()->is_url( $submitted_data[ $key ], 'facebook.com' ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL', 'ultimate-member' ), $array['label'] ) ); + } + break; + + case 'twitter_url': + if ( ! UM()->validation()->is_url( $submitted_data[ $key ], 'twitter.com' ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL', 'ultimate-member' ), $array['label'] ) ); + } + break; + + case 'instagram_url': + + if ( ! UM()->validation()->is_url( $submitted_data[ $key ], 'instagram.com' ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s profile URL', 'ultimate-member' ), $array['label'] ) ); + } + break; + + case 'linkedin_url': + if ( ! UM()->validation()->is_url( $submitted_data[ $key ], 'linkedin.com' ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL', 'ultimate-member' ), $array['label'] ) ); + } + break; + + case 'discord': + if ( ! UM()->validation()->is_discord_id( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'Please enter a valid Discord ID', 'ultimate-member' ) ); + } + break; + + case 'tiktok_url': + + if ( ! UM()->validation()->is_url( $submitted_data[ $key ], 'tiktok.com' ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s profile URL', 'ultimate-member' ), $array['label'] ) ); + } + break; + + case 'twitch_url': + + if ( ! UM()->validation()->is_url( $submitted_data[ $key ], 'twitch.tv' ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s profile URL', 'ultimate-member' ), $array['label'] ) ); + } + break; + + case 'reddit_url': + + if ( ! UM()->validation()->is_url( $submitted_data[ $key ], 'reddit.com' ) ) { + UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s profile URL', 'ultimate-member' ), $array['label'] ) ); + } + break; + + case 'url': + if ( ! UM()->validation()->is_url( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'Please enter a valid URL', 'ultimate-member' ) ); + } + break; + + case 'unique_username': + + if ( $submitted_data[ $key ] == '' ) { + UM()->form()->add_error( $key, __( 'You must provide a username', 'ultimate-member' ) ); + } elseif ( $mode == 'register' && username_exists( sanitize_user( $submitted_data[ $key ] ) ) ) { + UM()->form()->add_error( $key, __( 'The username you entered is incorrect', 'ultimate-member' ) ); + } elseif ( is_email( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'Username cannot be an email', 'ultimate-member' ) ); + } elseif ( ! UM()->validation()->safe_username( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'Your username contains invalid characters', 'ultimate-member' ) ); } - if ( isset( $array['min_chars'] ) && $array['min_chars'] > 0 ) { - if ( $args[ $key ] && mb_strlen( $args[ $key ] ) < $array['min_chars'] ) { - if ( empty( $array['label'] ) ) { - UM()->form()->add_error( $key, sprintf( __( 'This field must contain at least %s characters', 'ultimate-member' ), $array['min_chars'] ) ); - } else { - UM()->form()->add_error( $key, sprintf( __( 'Your %s must contain at least %s characters', 'ultimate-member' ), $array['label'], $array['min_chars'] ) ); - } - } + break; + + case 'unique_username_or_email': + + if ( $submitted_data[ $key ] == '' ) { + UM()->form()->add_error( $key, __( 'You must provide a username or email', 'ultimate-member' ) ); + } elseif ( $mode == 'register' && username_exists( sanitize_user( $submitted_data[ $key ] ) ) ) { + UM()->form()->add_error( $key, __( 'The username you entered is incorrect', 'ultimate-member' ) ); + } elseif ( $mode == 'register' && email_exists( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) ); + } elseif ( ! UM()->validation()->safe_username( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'Your username contains invalid characters', 'ultimate-member' ) ); } - if ( isset( $array['max_chars'] ) && $array['max_chars'] > 0 ) { - if ( $args[ $key ] && mb_strlen( $args[ $key ] ) > $array['max_chars'] ) { - if ( empty( $array['label'] ) ) { - UM()->form()->add_error( $key, sprintf( __( 'This field must contain less than %s characters', 'ultimate-member' ), $array['max_chars'] ) ); - } else { - UM()->form()->add_error( $key, sprintf( __( 'Your %s must contain less than %s characters', 'ultimate-member' ), $array['label'], $array['max_chars'] ) ); - } - } - } + break; - if ( isset( $array['type'] ) && $array['type'] == 'textarea' && UM()->profile()->get_show_bio_key( $args ) !== $key ) { - if ( ! isset( $array['html'] ) || $array['html'] == 0 ) { - if ( wp_strip_all_tags( $args[ $key ] ) != trim( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'You can not use HTML tags here', 'ultimate-member' ) ); - } - } - } + case 'unique_email': - if ( isset( $array['force_good_pass'] ) && $array['force_good_pass'] && ! empty( $args['user_password'] ) ) { - if ( isset( $args['user_login'] ) && strpos( strtolower( $args['user_login'] ), strtolower( $args['user_password'] ) ) > -1 ) { - UM()->form()->add_error( 'user_password', __( 'Your password cannot contain the part of your username', 'ultimate-member' )); + $submitted_data[ $key ] = trim( $submitted_data[ $key ] ); + + if ( in_array( $key, array( 'user_email' ) ) ) { + + if ( ! isset( $submitted_data['user_id'] ) ){ + $submitted_data['user_id'] = um_get_requested_user(); } - if ( isset( $args['user_email'] ) && strpos( strtolower( $args['user_email'] ), strtolower( $args['user_password'] ) ) > -1 ) { - UM()->form()->add_error( 'user_password', __( 'Your password cannot contain the part of your email address', 'ultimate-member' )); + $email_exists = email_exists( $submitted_data[ $key ] ); + + if ( $submitted_data[ $key ] == '' && in_array( $key, array( 'user_email' ) ) ) { + UM()->form()->add_error( $key, __( 'You must provide your email', 'ultimate-member' ) ); + } elseif ( in_array( $mode, array( 'register' ) ) && $email_exists ) { + UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) ); + } elseif ( in_array( $mode, array( 'profile' ) ) && $email_exists && $email_exists != $submitted_data['user_id'] ) { + UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) ); + } elseif ( ! is_email( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member') ); + } elseif ( ! UM()->validation()->safe_username( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'Your email contains invalid characters', 'ultimate-member' ) ); } - if ( ! UM()->validation()->strong_pass( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'Your password must contain at least one lowercase letter, one capital letter and one number', 'ultimate-member' ) ); - } - } + } else { - if ( ! empty( $array['force_confirm_pass'] ) ) { - if ( ! array_key_exists( 'confirm_' . $key, $args ) && ! UM()->form()->has_error( $key ) ) { - UM()->form()->add_error( 'confirm_' . $key, __( 'Please confirm your password', 'ultimate-member' ) ); - } else { - if ( '' === $args[ 'confirm_' . $key ] && ! UM()->form()->has_error( $key ) ) { - UM()->form()->add_error( 'confirm_' . $key, __( 'Please confirm your password', 'ultimate-member' ) ); - } - if ( $args[ 'confirm_' . $key ] !== $args[ $key ] && ! UM()->form()->has_error( $key ) ) { - UM()->form()->add_error( 'confirm_' . $key, __( 'Your passwords do not match', 'ultimate-member' ) ); - } - } - } + if ( $submitted_data[ $key ] != '' && ! is_email( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) ); + } elseif ( $submitted_data[ $key ] != '' && email_exists( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) ); + } elseif ( $submitted_data[ $key ] != '' ) { - if ( isset( $array['min_selections'] ) && $array['min_selections'] > 0 ) { - if ( ( ! isset( $args[ $key ] ) ) || ( isset( $args[ $key ] ) && is_array( $args[ $key ] ) && count( $args[ $key ] ) < $array['min_selections'] ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please select at least %s choices', 'ultimate-member' ), $array['min_selections'] ) ); - } - } + $users = get_users( 'meta_value=' . $submitted_data[ $key ] ); - if ( isset( $array['max_selections'] ) && $array['max_selections'] > 0 ) { - if ( isset( $args[ $key ] ) && is_array( $args[ $key ] ) && count( $args[ $key ] ) > $array['max_selections'] ) { - UM()->form()->add_error( $key, sprintf( __( 'You can only select up to %s choices', 'ultimate-member' ), $array['max_selections'] ) ); - } - } - - if ( isset( $array['min'] ) && is_numeric( $args[ $key ] ) ) { - if ( isset( $args[ $key ] ) && $args[ $key ] < $array['min'] ) { - UM()->form()->add_error( $key, sprintf( __( 'Minimum number limit is %s', 'ultimate-member' ), $array['min'] ) ); - } - } - - if ( isset( $array['max'] ) && is_numeric( $args[ $key ] ) ) { - if ( isset( $args[ $key ] ) && $args[ $key ] > $array['max'] ) { - UM()->form()->add_error( $key, sprintf( __( 'Maximum number limit is %s', 'ultimate-member' ), $array['max'] ) ); - } - } - - if ( ! empty( $array['validate'] ) ) { - - switch( $array['validate'] ) { - - case 'custom': - $custom = $array['custom_validate']; - /** - * UM hook - * - * @type action - * @title um_custom_field_validation_{$custom} - * @description Submit form validation for custom field - * @input_vars - * [{"var":"$key","type":"string","desc":"Field Key"}, - * {"var":"$field","type":"array","desc":"Field Data"}, - * {"var":"$args","type":"array","desc":"Form Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_custom_field_validation_{$custom}', 'function_name', 10, 3 ); - * @example - * - */ - do_action( "um_custom_field_validation_{$custom}", $key, $array, $args ); - break; - - case 'numeric': - if ( $args[ $key ] && ! is_numeric( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'Please enter numbers only in this field', 'ultimate-member' ) ); - } - break; - - case 'phone_number': - if ( ! UM()->validation()->is_phone_number( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'Please enter a valid phone number', 'ultimate-member' ) ); - } - break; - - case 'youtube_url': - if ( ! UM()->validation()->is_url( $args[ $key ], 'youtube.com' ) && ! UM()->validation()->is_url( $args[ $key ], 'youtu.be' ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL', 'ultimate-member' ), $array['label'] ) ); - } - break; - - case 'spotify_url': - if ( ! UM()->validation()->is_url( $args[ $key ], 'open.spotify.com' ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s URL', 'ultimate-member' ), $array['label'] ) ); - } - break; - - case 'telegram_url': - if ( ! UM()->validation()->is_url( $args[ $key ], 't.me' ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL', 'ultimate-member' ), $array['label'] ) ); - } - break; - - case 'soundcloud_url': - if ( ! UM()->validation()->is_url( $args[ $key ], 'soundcloud.com' ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL','ultimate-member'), $array['label'] ) ); - } - break; - - case 'facebook_url': - if ( ! UM()->validation()->is_url( $args[ $key ], 'facebook.com' ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL', 'ultimate-member' ), $array['label'] ) ); - } - break; - - case 'twitter_url': - if ( ! UM()->validation()->is_url( $args[ $key ], 'twitter.com' ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL', 'ultimate-member' ), $array['label'] ) ); - } - break; - - case 'instagram_url': - - if ( ! UM()->validation()->is_url( $args[ $key ], 'instagram.com' ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s profile URL', 'ultimate-member' ), $array['label'] ) ); - } - break; - - case 'linkedin_url': - if ( ! UM()->validation()->is_url( $args[ $key ], 'linkedin.com' ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s username or profile URL', 'ultimate-member' ), $array['label'] ) ); - } - break; - - case 'discord': - if ( ! UM()->validation()->is_discord_id( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'Please enter a valid Discord ID', 'ultimate-member' ) ); - } - break; - - case 'tiktok_url': - - if ( ! UM()->validation()->is_url( $args[ $key ], 'tiktok.com' ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s profile URL', 'ultimate-member' ), $array['label'] ) ); - } - break; - - case 'twitch_url': - - if ( ! UM()->validation()->is_url( $args[ $key ], 'twitch.tv' ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s profile URL', 'ultimate-member' ), $array['label'] ) ); - } - break; - - case 'reddit_url': - - if ( ! UM()->validation()->is_url( $args[ $key ], 'reddit.com' ) ) { - UM()->form()->add_error( $key, sprintf( __( 'Please enter a valid %s profile URL', 'ultimate-member' ), $array['label'] ) ); - } - break; - - case 'url': - if ( ! UM()->validation()->is_url( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'Please enter a valid URL', 'ultimate-member' ) ); - } - break; - - case 'unique_username': - - if ( $args[ $key ] == '' ) { - UM()->form()->add_error( $key, __( 'You must provide a username', 'ultimate-member' ) ); - } elseif ( $mode == 'register' && username_exists( sanitize_user( $args[ $key ] ) ) ) { - UM()->form()->add_error( $key, __( 'The username you entered is incorrect', 'ultimate-member' ) ); - } elseif ( is_email( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'Username cannot be an email', 'ultimate-member' ) ); - } elseif ( ! UM()->validation()->safe_username( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'Your username contains invalid characters', 'ultimate-member' ) ); - } - - break; - - case 'unique_username_or_email': - - if ( $args[ $key ] == '' ) { - UM()->form()->add_error( $key, __( 'You must provide a username or email', 'ultimate-member' ) ); - } elseif ( $mode == 'register' && username_exists( sanitize_user( $args[ $key ] ) ) ) { - UM()->form()->add_error( $key, __( 'The username you entered is incorrect', 'ultimate-member' ) ); - } elseif ( $mode == 'register' && email_exists( $args[ $key ] ) ) { + foreach ( $users as $user ) { + if ( $user->ID != $submitted_data['user_id'] ) { UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) ); - } elseif ( ! UM()->validation()->safe_username( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'Your username contains invalid characters', 'ultimate-member' ) ); } - - break; - - case 'unique_email': - - $args[ $key ] = trim( $args[ $key ] ); - - if ( in_array( $key, array( 'user_email' ) ) ) { - - if ( ! isset( $args['user_id'] ) ){ - $args['user_id'] = um_get_requested_user(); - } - - $email_exists = email_exists( $args[ $key ] ); - - if ( $args[ $key ] == '' && in_array( $key, array( 'user_email' ) ) ) { - UM()->form()->add_error( $key, __( 'You must provide your email', 'ultimate-member' ) ); - } elseif ( in_array( $mode, array( 'register' ) ) && $email_exists ) { - UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) ); - } elseif ( in_array( $mode, array( 'profile' ) ) && $email_exists && $email_exists != $args['user_id'] ) { - UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) ); - } elseif ( ! is_email( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member') ); - } elseif ( ! UM()->validation()->safe_username( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'Your email contains invalid characters', 'ultimate-member' ) ); - } - - } else { - - if ( $args[ $key ] != '' && ! is_email( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) ); - } elseif ( $args[ $key ] != '' && email_exists( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) ); - } elseif ( $args[ $key ] != '' ) { - - $users = get_users( 'meta_value=' . $args[ $key ] ); - - foreach ( $users as $user ) { - if ( $user->ID != $args['user_id'] ) { - UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) ); - } - } - - } - - } - - break; - - case 'is_email': - - $args[ $key ] = trim( $args[ $key ] ); - - if ( $args[ $key ] != '' && ! is_email( $args[ $key ] ) ) { - UM()->form()->add_error( $key, __( 'This is not a valid email', 'ultimate-member' ) ); - } - - break; - - case 'unique_value': - - if ( $args[ $key ] != '' ) { - - $args_unique_meta = array( - 'meta_key' => $key, - 'meta_value' => $args[ $key ], - 'compare' => '=', - 'exclude' => array( $args['user_id'] ), - ); - - $meta_key_exists = get_users( $args_unique_meta ); - - if ( $meta_key_exists ) { - UM()->form()->add_error( $key , __( 'You must provide a unique value', 'ultimate-member' ) ); - } - } - break; - - case 'alphabetic': - - if ( $args[ $key ] != '' ) { - - if ( ! preg_match( '/^\p{L}+$/u', str_replace( ' ', '', $args[ $key ] ) ) ) { - UM()->form()->add_error( $key, __( 'You must provide alphabetic letters', 'ultimate-member' ) ); - } - - } - - break; - - case 'lowercase': - - if ( $args[ $key ] != '' ) { - - if ( ! ctype_lower( str_replace(' ', '', $args[ $key ] ) ) ) { - UM()->form()->add_error( $key , __( 'You must provide lowercase letters.', 'ultimate-member' ) ); - } - } - - break; + } } } - } + break; - if ( isset( $args['description'] ) ) { - $max_chars = UM()->options()->get( 'profile_bio_maxchars' ); - $profile_show_bio = UM()->options()->get( 'profile_show_bio' ); + case 'is_email': - if ( $profile_show_bio ) { - if ( mb_strlen( str_replace( array( "\r\n", "\n", "\r\t", "\t" ), ' ', $args['description'] ) ) > $max_chars && $max_chars ) { - UM()->form()->add_error( 'description', sprintf( __( 'Your user description must contain less than %s characters', 'ultimate-member' ), $max_chars ) ); + $submitted_data[ $key ] = trim( $submitted_data[ $key ] ); + + if ( $submitted_data[ $key ] != '' && ! is_email( $submitted_data[ $key ] ) ) { + UM()->form()->add_error( $key, __( 'This is not a valid email', 'ultimate-member' ) ); + } + + break; + + case 'unique_value': + + if ( $submitted_data[ $key ] != '' ) { + + $args_unique_meta = array( + 'meta_key' => $key, + 'meta_value' => $submitted_data[ $key ], + 'compare' => '=', + 'exclude' => array( $submitted_data['user_id'] ), + ); + + $meta_key_exists = get_users( $args_unique_meta ); + + if ( $meta_key_exists ) { + UM()->form()->add_error( $key , __( 'You must provide a unique value', 'ultimate-member' ) ); + } + } + break; + + case 'alphabetic': + + if ( $submitted_data[ $key ] != '' ) { + + if ( ! preg_match( '/^\p{L}+$/u', str_replace( ' ', '', $submitted_data[ $key ] ) ) ) { + UM()->form()->add_error( $key, __( 'You must provide alphabetic letters', 'ultimate-member' ) ); + } + + } + + break; + + case 'lowercase': + + if ( $submitted_data[ $key ] != '' ) { + + if ( ! ctype_lower( str_replace(' ', '', $submitted_data[ $key ] ) ) ) { + UM()->form()->add_error( $key , __( 'You must provide lowercase letters.', 'ultimate-member' ) ); } } - } + break; - } // end if ( isset in args array ) - } + } + + if ( isset( $submitted_data['description'] ) ) { + $max_chars = UM()->options()->get( 'profile_bio_maxchars' ); + $profile_show_bio = UM()->options()->get( 'profile_show_bio' ); + + if ( $profile_show_bio ) { + if ( mb_strlen( str_replace( array( "\r\n", "\n", "\r\t", "\t" ), ' ', $submitted_data['description'] ) ) > $max_chars && $max_chars ) { + UM()->form()->add_error( 'description', sprintf( __( 'Your user description must contain less than %s characters', 'ultimate-member' ), $max_chars ) ); + } + } + } + } // end if ( isset in args array ) } -add_action( 'um_submit_form_errors_hook_', 'um_submit_form_errors_hook_', 10 ); +add_action( 'um_submit_form_errors_hook_', 'um_submit_form_errors_hook_', 10, 2 ); /** diff --git a/includes/core/um-actions-login.php b/includes/core/um-actions-login.php index dbf019ea..de777c93 100644 --- a/includes/core/um-actions-login.php +++ b/includes/core/um-actions-login.php @@ -4,57 +4,51 @@ if ( ! defined( 'ABSPATH' ) ) { } /** - * Error procesing hook for login + * Error processing hook for login. * - * @param $args + * @param $submitted_data */ -function um_submit_form_errors_hook_login( $args ) { - $is_email = false; +function um_submit_form_errors_hook_login( $submitted_data ) { + $user_password = $submitted_data['user_password']; - $form_id = $args['form_id']; - $mode = $args['mode']; - $user_password = $args['user_password']; - - if ( isset( $args['username'] ) && $args['username'] == '' ) { + if ( isset( $submitted_data['username'] ) && $submitted_data['username'] == '' ) { UM()->form()->add_error( 'username', __( 'Please enter your username or email', 'ultimate-member' ) ); } - if ( isset( $args['user_login'] ) && $args['user_login'] == '' ) { + if ( isset( $submitted_data['user_login'] ) && $submitted_data['user_login'] == '' ) { UM()->form()->add_error( 'user_login', __( 'Please enter your username', 'ultimate-member' ) ); } - if ( isset( $args['user_email'] ) && $args['user_email'] == '' ) { + if ( isset( $submitted_data['user_email'] ) && $submitted_data['user_email'] == '' ) { UM()->form()->add_error( 'user_email', __( 'Please enter your email', 'ultimate-member' ) ); } - if ( isset( $args['username'] ) ) { - $authenticate = $args['username']; + if ( isset( $submitted_data['username'] ) ) { + $authenticate = $submitted_data['username']; $field = 'username'; - if ( is_email( $args['username'] ) ) { - $is_email = true; - $data = get_user_by('email', $args['username'] ); + if ( is_email( $submitted_data['username'] ) ) { + $data = get_user_by('email', $submitted_data['username'] ); $user_name = isset( $data->user_login ) ? $data->user_login : null; } else { - $user_name = $args['username']; + $user_name = $submitted_data['username']; } - } elseif ( isset( $args['user_email'] ) ) { - $authenticate = $args['user_email']; + } elseif ( isset( $submitted_data['user_email'] ) ) { + $authenticate = $submitted_data['user_email']; $field = 'user_email'; - $is_email = true; - $data = get_user_by('email', $args['user_email'] ); + $data = get_user_by('email', $submitted_data['user_email'] ); $user_name = isset( $data->user_login ) ? $data->user_login : null; } else { $field = 'user_login'; - $user_name = $args['user_login']; - $authenticate = $args['user_login']; + $user_name = $submitted_data['user_login']; + $authenticate = $submitted_data['user_login']; } - if ( $args['user_password'] == '' ) { + if ( $submitted_data['user_password'] == '' ) { UM()->form()->add_error( 'user_password', __( 'Please enter your password', 'ultimate-member' ) ); } $user = get_user_by( 'login', $user_name ); - if ( $user && wp_check_password( $args['user_password'], $user->data->user_pass, $user->ID ) ) { + if ( $user && wp_check_password( $submitted_data['user_password'], $user->data->user_pass, $user->ID ) ) { UM()->login()->auth_id = username_exists( $user_name ); } else { UM()->form()->add_error( 'user_password', __( 'Password is incorrect. Please try again.', 'ultimate-member' ) ); @@ -67,7 +61,7 @@ function um_submit_form_errors_hook_login( $args ) { // see WP function wp_authenticate() $ignore_codes = array( 'empty_username', 'empty_password' ); - $user = apply_filters( 'authenticate', null, $authenticate, $args['user_password'] ); + $user = apply_filters( 'authenticate', null, $authenticate, $submitted_data['user_password'] ); if ( is_wp_error( $user ) && ! in_array( $user->get_error_code(), $ignore_codes ) ) { if ( ! empty( $third_party_codes ) && in_array( $user->get_error_code(), $third_party_codes ) ) { UM()->form()->add_error( $user->get_error_code(), $user->get_error_message() ); @@ -76,7 +70,7 @@ function um_submit_form_errors_hook_login( $args ) { } } - $user = apply_filters( 'wp_authenticate_user', $user, $args['user_password'] ); + $user = apply_filters( 'wp_authenticate_user', $user, $submitted_data['user_password'] ); if ( is_wp_error( $user ) && ! in_array( $user->get_error_code(), $ignore_codes ) ) { if ( ! empty( $third_party_codes ) && in_array( $user->get_error_code(), $third_party_codes ) ) { UM()->form()->add_error( $user->get_error_code(), $user->get_error_message() ); @@ -90,7 +84,7 @@ function um_submit_form_errors_hook_login( $args ) { do_action( 'wp_login_failed', $user_name, UM()->form()->get_wp_error() ); } } -add_action( 'um_submit_form_errors_hook_login', 'um_submit_form_errors_hook_login', 10 ); +add_action( 'um_submit_form_errors_hook_login', 'um_submit_form_errors_hook_login' ); /** @@ -123,13 +117,13 @@ function um_display_login_errors( $args ) { } add_action( 'um_before_login_fields', 'um_display_login_errors' ); - /** - * Login checks thru the frontend login + * Login checks through the frontend login * - * @param $args + * @param array $submitted_data + * @param array $form_data */ -function um_submit_form_errors_hook_logincheck( $args ) { +function um_submit_form_errors_hook_logincheck( $submitted_data, $form_data ) { // Logout if logged in if ( is_user_logged_in() ) { wp_logout(); @@ -140,25 +134,23 @@ function um_submit_form_errors_hook_logincheck( $args ) { $status = um_user( 'account_status' ); // account status switch ( $status ) { - - // If user can't login to site... + // If user can't log in to site... case 'inactive': case 'awaiting_admin_review': case 'awaiting_email_confirmation': case 'rejected': - um_reset_user(); - exit( wp_redirect( add_query_arg( 'err', esc_attr( $status ), UM()->permalinks()->get_current_url() ) ) ); - break; - + um_reset_user(); + wp_safe_redirect( add_query_arg( 'err', esc_attr( $status ), UM()->permalinks()->get_current_url() ) ); + exit; } - if ( isset( $args['form_id'] ) && $args['form_id'] == UM()->shortcodes()->core_login_form() && UM()->form()->errors && ! isset( $_POST[ UM()->honeypot ] ) ) { - exit( wp_redirect( um_get_core_page( 'login' ) ) ); + if ( isset( $form_data['form_id'] ) && absint( $form_data['form_id'] ) === absint( UM()->shortcodes()->core_login_form() ) && UM()->form()->errors && ! isset( $_POST[ UM()->honeypot ] ) ) { + wp_safe_redirect( um_get_core_page( 'login' ) ); + exit; } } -add_action( 'um_submit_form_errors_hook_logincheck', 'um_submit_form_errors_hook_logincheck', 9999 ); - +add_action( 'um_submit_form_errors_hook_logincheck', 'um_submit_form_errors_hook_logincheck', 9999, 2 ); /** * Store last login timestamp @@ -192,13 +184,13 @@ function um_store_lastlogin_timestamp_( $login ) { add_action( 'wp_login', 'um_store_lastlogin_timestamp_' ); /** - * Login user process + * Login user process. * - * @param array $args + * @param array $submitted_data */ -function um_user_login( $args ) { +function um_user_login( $submitted_data ) { // phpcs:disable WordPress.Security.NonceVerification -- already verified here - $rememberme = ( isset( $_REQUEST['rememberme'], $args['rememberme'] ) && 1 === (int) $args['rememberme'] ) ? 1 : 0; + $rememberme = ( isset( $_REQUEST['rememberme'], $submitted_data['rememberme'] ) && 1 === (int) $submitted_data['rememberme'] ) ? 1 : 0; // @todo check using the 'deny_admin_frontend_login' option if ( false !== strrpos( um_user( 'wp_roles' ), 'administrator' ) && ( ! isset( $_GET['provider'] ) && UM()->options()->get( 'deny_admin_frontend_login' ) ) ) { @@ -224,8 +216,8 @@ function um_user_login( $args ) { do_action( 'um_on_login_before_redirect', um_user( 'ID' ) ); // Priority redirect from $_GET attribute. - if ( ! empty( $args['redirect_to'] ) ) { - wp_safe_redirect( $args['redirect_to'] ); + if ( ! empty( $submitted_data['redirect_to'] ) ) { + wp_safe_redirect( $submitted_data['redirect_to'] ); exit; } @@ -277,56 +269,52 @@ add_action( 'um_user_login', 'um_user_login' ); /** * Form processing * - * @param $args + * @param array $submitted_data + * @param array $form_data */ -function um_submit_form_login( $args ) { - +function um_submit_form_login( $submitted_data, $form_data ) { if ( ! isset( UM()->form()->errors ) ) { /** - * UM hook + * Fires after successful submit login form. * - * @type action - * @title um_user_login - * @description Hook that runs after successful submit login form - * @input_vars - * [{"var":"$args","type":"array","desc":"Form data"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_user_login', 'function_name', 10, 1 ); - * @example - * Callback name -> Excerpt): + * * 10 - `um_user_login()` Login form main handler. + * + * @since 1.3.x + * @hook um_user_login + * + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any custom login action if submission is valid. + * function my_user_login( $submitted_data, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_user_login', 'my_user_login', 10, 2 ); */ - do_action( 'um_user_login', $args ); + do_action( 'um_user_login', $submitted_data, $form_data ); } - /** - * UM hook + * Fires after submit login form. * - * @type action - * @title um_user_login_extra_hook - * @description Hook that runs after successful submit login form - * @input_vars - * [{"var":"$args","type":"array","desc":"Form data"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_user_login_extra_hook', 'function_name', 10, 1 ); - * @example - * Callback name -> Excerpt): + * * 10 - um-messaging. + * + * @since 1.3.x + * @hook um_user_login_extra_hook + * + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any custom login action. + * function my_user_login_extra( $submitted_data, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_user_login_extra_hook', 'my_user_login_extra', 10, 2 ); */ - do_action( 'um_user_login_extra_hook', $args ); + do_action( 'um_user_login_extra_hook', $submitted_data, $form_data ); } -add_action( 'um_submit_form_login', 'um_submit_form_login', 10 ); - +add_action( 'um_submit_form_login', 'um_submit_form_login', 10, 2 ); /** * Show the submit button diff --git a/includes/core/um-actions-profile.php b/includes/core/um-actions-profile.php index 5d3328c5..b7b63ecf 100644 --- a/includes/core/um-actions-profile.php +++ b/includes/core/um-actions-profile.php @@ -181,13 +181,14 @@ function um_profile_content_main( $args ) { add_action( 'um_profile_content_main', 'um_profile_content_main' ); /** - * Update user's profile + * Update user's profile (frontend). * * @param array $args + * @param array $form_data */ -function um_user_edit_profile( $args ) { +function um_user_edit_profile( $args, $form_data ) { $to_update = null; - $files = array(); + $files = array(); $user_id = null; if ( isset( $args['user_id'] ) ) { @@ -199,41 +200,33 @@ function um_user_edit_profile( $args ) { if ( UM()->roles()->um_current_user_can( 'edit', $user_id ) ) { UM()->user()->set( $user_id ); } else { - wp_die( __( 'You are not allowed to edit this user.', 'ultimate-member' ) ); + wp_die( esc_html__( 'You are not allowed to edit this user.', 'ultimate-member' ) ); } $userinfo = UM()->user()->profile; /** - * UM hook + * Fires before collecting data to update on profile form submit. * - * @type action - * @title um_user_before_updating_profile - * @description Some actions before profile submit - * @input_vars - * [{"var":"$userinfo","type":"array","desc":"User Data"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_user_before_updating_profile', 'function_name', 10, 1 ); - * @example - * Make any custom action before collecting data to update on profile form submit. + * function my_user_before_updating_profile( $role_key, $role_meta ) { * // your code here * } - * ?> + * add_action( 'um_user_before_updating_profile', 'my_user_before_updating_profile', 10, 2 ); */ do_action( 'um_user_before_updating_profile', $userinfo ); - if ( ! empty( $args['custom_fields'] ) ) { - $fields = apply_filters( 'um_user_edit_profile_fields', unserialize( $args['custom_fields'] ), $args ); - } + $fields = maybe_unserialize( $form_data['custom_fields'] ); + $fields = apply_filters( 'um_user_edit_profile_fields', $fields, $args, $form_data ); // loop through fields if ( ! empty( $fields ) ) { - foreach ( $fields as $key => $array ) { - if ( ! isset( $array['type'] ) ) { continue; } @@ -243,16 +236,17 @@ function um_user_edit_profile( $args ) { } // required option? 'required_opt' - it's field attribute predefined in the field data in code + // @todo can be unnecessary. it's used in 1 place (user account). if ( isset( $array['required_opt'] ) ) { $opt = $array['required_opt']; - if ( UM()->options()->get( $opt[0] ) != $opt[1] ) { + if ( UM()->options()->get( $opt[0] ) !== $opt[1] ) { continue; } } // fields that need to be disabled in edit mode (profile) (email, username, etc.) $arr_restricted_fields = UM()->fields()->get_restricted_fields_for_edit( $user_id ); - if ( in_array( $key, $arr_restricted_fields ) ) { + if ( in_array( $key, $arr_restricted_fields, true ) ) { continue; } @@ -261,13 +255,13 @@ function um_user_edit_profile( $args ) { } // skip saving role here - if ( in_array( $key, array( 'role', 'role_select', 'role_radio' ) ) ) { + if ( in_array( $key, array( 'role', 'role_select', 'role_radio' ), true ) ) { continue; } //the same code in class-validation.php validate_fields_values for registration form //rating field validation - if ( $array['type'] == 'rating' && isset( $args['submitted'][ $key ] ) ) { + if ( 'rating' === $array['type'] && isset( $args['submitted'][ $key ] ) ) { if ( ! is_numeric( $args['submitted'][ $key ] ) ) { continue; } else { @@ -283,13 +277,12 @@ function um_user_edit_profile( $args ) { } } - /** * Returns dropdown/multi-select options keys from a callback function * @since 2019-05-30 */ $has_custom_source = apply_filters( "um_has_dropdown_options_source__{$key}", false ); - if ( isset( $array['options'] ) && in_array( $array['type'], array( 'select', 'multiselect' ) ) ) { + if ( isset( $array['options'] ) && in_array( $array['type'], array( 'select', 'multiselect' ), true ) ) { $options = array(); if ( ! empty( $array['custom_dropdown_options_source'] ) && function_exists( $array['custom_dropdown_options_source'] ) && ! $has_custom_source ) { @@ -302,112 +295,89 @@ function um_user_edit_profile( $args ) { } $array['options'] = apply_filters( "um_custom_dropdown_options__{$key}", $options ); - } - //validation of correct values from options in wp-admin $stripslashes = ''; if ( isset( $args['submitted'][ $key ] ) && is_string( $args['submitted'][ $key ] ) ) { $stripslashes = stripslashes( $args['submitted'][ $key ] ); } - if ( in_array( $array['type'], array( 'select' ) ) ) { + if ( 'select' === $array['type'] ) { if ( ! empty( $array['options'] ) && ! empty( $stripslashes ) && ! in_array( $stripslashes, array_map( 'trim', $array['options'] ) ) && ! $has_custom_source ) { continue; } //update empty user meta - if ( ! isset( $args['submitted'][ $key ] ) || $args['submitted'][ $key ] == '' ) { + if ( ! isset( $args['submitted'][ $key ] ) || '' === $args['submitted'][ $key ] ) { update_user_meta( $user_id, $key, '' ); } } //validation of correct values from options in wp-admin //the user cannot set invalid value in the hidden input at the page - if ( in_array( $array['type'], array( 'multiselect', 'checkbox', 'radio' ) ) ) { + if ( in_array( $array['type'], array( 'multiselect', 'checkbox', 'radio' ), true ) ) { if ( ! empty( $args['submitted'][ $key ] ) && ! empty( $array['options'] ) ) { $args['submitted'][ $key ] = array_map( 'stripslashes', array_map( 'trim', $args['submitted'][ $key ] ) ); $args['submitted'][ $key ] = array_intersect( $args['submitted'][ $key ], array_map( 'trim', $array['options'] ) ); } // update empty user meta - if ( ! isset( $args['submitted'][ $key ] ) || $args['submitted'][ $key ] == '' ) { + if ( ! isset( $args['submitted'][ $key ] ) || '' === $args['submitted'][ $key ] ) { update_user_meta( $user_id, $key, array() ); } } if ( isset( $args['submitted'][ $key ] ) ) { - - if ( isset( $array['type'] ) && in_array( $array['type'], array( 'image', 'file' ) ) ) { - - if ( um_is_temp_file( $args['submitted'][ $key ] ) || $args['submitted'][ $key ] == 'empty_file' ) { + if ( in_array( $array['type'], array( 'image', 'file' ), true ) ) { + if ( um_is_temp_file( $args['submitted'][ $key ] ) || 'empty_file' === $args['submitted'][ $key ] ) { $files[ $key ] = $args['submitted'][ $key ]; } elseif( um_is_file_owner( UM()->uploader()->get_upload_base_url() . $user_id . '/' . $args['submitted'][ $key ], $user_id ) ) { } else { $files[ $key ] = 'empty_file'; } - } else { - if ( $array['type'] == 'password' ) { - $to_update[ $key ] = wp_hash_password( $args['submitted'][ $key ] ); + if ( 'password' === $array['type'] ) { + $to_update[ $key ] = wp_hash_password( $args['submitted'][ $key ] ); $args['submitted'][ $key ] = sprintf( __( 'Your choosed %s', 'ultimate-member' ), $array['title'] ); } else { if ( isset( $userinfo[ $key ] ) && $args['submitted'][ $key ] != $userinfo[ $key ] ) { $to_update[ $key ] = $args['submitted'][ $key ]; - } elseif ( $args['submitted'][ $key ] != '' ) { + } elseif ( '' !== $args['submitted'][ $key ] ) { $to_update[ $key ] = $args['submitted'][ $key ]; } } - } - // use this filter after all validations has been completed and we can extends data based on key + // use this filter after all validations has been completed, and we can extend data based on key $to_update = apply_filters( 'um_change_usermeta_for_update', $to_update, $args, $fields, $key ); - } } } $description_key = UM()->profile()->get_show_bio_key( $args ); - if ( isset( $args['submitted'][ $description_key ] ) ) { - $to_update[ $description_key ] = $args['submitted'][ $description_key ]; + if ( ! isset( $to_update[ $description_key ] ) && ! empty( $form_data['show_bio'] ) ) { + if ( isset( $args['submitted'][ $description_key ] ) ) { + $to_update[ $description_key ] = $args['submitted'][ $description_key ]; + } } - // Secure selected role - if ( is_admin() ) { + if ( ( isset( $fields['role'] ) && ! empty( $fields['role']['editable'] ) && um_can_view_field( $fields['role'] ) ) || + ( isset( $fields['role_select'] ) && ! empty( $fields['role_select']['editable'] ) && um_can_view_field( $fields['role_select'] ) ) || + ( isset( $fields['role_radio'] ) && ! empty( $fields['role_radio']['editable'] ) && um_can_view_field( $fields['role_radio'] ) ) ) { - if ( ! empty( $args['submitted']['role'] ) && current_user_can( 'promote_users' ) ) { + if ( ! empty( $args['submitted']['role'] ) ) { global $wp_roles; $exclude_roles = array_diff( array_keys( $wp_roles->roles ), UM()->roles()->get_editable_user_roles() ); - if ( ! in_array( $args['submitted']['role'], $exclude_roles ) ) { + if ( ! in_array( $args['submitted']['role'], $exclude_roles, true ) ) { $to_update['role'] = $args['submitted']['role']; } $args['roles_before_upgrade'] = UM()->roles()->get_all_user_roles( $user_id ); } - - } else { - - if ( ( isset( $fields['role'] ) && $fields['role']['editable'] != 0 && um_can_view_field( $fields['role'] ) ) || - ( isset( $fields['role_select'] ) && $fields['role_select']['editable'] != 0 && um_can_view_field( $fields['role_select'] ) ) || - ( isset( $fields['role_radio'] ) ) && $fields['role_radio']['editable'] != 0 && um_can_view_field( $fields['role_radio'] ) ) { - - if ( ! empty( $args['submitted']['role'] ) ) { - global $wp_roles; - $exclude_roles = array_diff( array_keys( $wp_roles->roles ), UM()->roles()->get_editable_user_roles() ); - - if ( ! in_array( $args['submitted']['role'], $exclude_roles ) ) { - $to_update['role'] = $args['submitted']['role']; - } - - $args['roles_before_upgrade'] = UM()->roles()->get_all_user_roles( $user_id ); - } - } - } /** @@ -430,7 +400,7 @@ function um_user_edit_profile( $args ) { * } * ?> */ - do_action( 'um_user_pre_updating_profile', $to_update, $user_id ); + do_action( 'um_user_pre_updating_profile', $to_update, $user_id, $form_data ); /** * UM hook @@ -454,10 +424,9 @@ function um_user_edit_profile( $args ) { * } * ?> */ - $to_update = apply_filters( 'um_user_pre_updating_profile_array', $to_update, $user_id ); + $to_update = apply_filters( 'um_user_pre_updating_profile_array', $to_update, $user_id, $form_data ); if ( is_array( $to_update ) ) { - if ( isset( $to_update['first_name'] ) || isset( $to_update['last_name'] ) || isset( $to_update['nickname'] ) ) { $user = get_userdata( $user_id ); if ( ! empty( $user ) && ! is_wp_error( $user ) ) { @@ -502,36 +471,17 @@ function um_user_edit_profile( $args ) { do_action( 'um_after_user_updated', $user_id, $args, $to_update ); } - /** - * UM hook - * - * @type filter - * @title um_user_pre_updating_files_array - * @description Change submitted files before update profile - * @input_vars - * [{"var":"$files","type":"array","desc":"Profile data files"}, - * {"var":"$user_id","type":"int","desc":"User ID"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ + /** This action is documented in ultimate-member/includes/core/um-actions-register.php */ $files = apply_filters( 'um_user_pre_updating_files_array', $files, $user_id ); - if ( ! empty( $files ) && is_array( $files ) ) { UM()->uploader()->replace_upload_dir = true; UM()->uploader()->move_temporary_files( $user_id, $files ); UM()->uploader()->replace_upload_dir = false; } + /** This action is documented in ultimate-member/includes/core/um-actions-register.php */ + do_action( 'um_update_profile_full_name', $user_id, $to_update ); + /** * UM hook * @@ -554,52 +504,33 @@ function um_user_edit_profile( $args ) { */ do_action( 'um_user_after_updating_profile', $to_update, $user_id, $args ); - /** - * UM hook - * - * @type action - * @title um_update_profile_full_name - * @description On update user profile change full name - * @input_vars - * [{"var":"$user_id","type":"int","desc":"User ID"}, - * {"var":"$args","type":"array","desc":"Form data"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_update_profile_full_name', 'function_name', 10, 2 ); - * @example - * - */ - do_action( 'um_update_profile_full_name', $user_id, $to_update ); - - if ( ! isset( $args['is_signup'] ) ) { - $url = um_user_profile_url( $user_id ); - $url = apply_filters( 'um_update_profile_redirect_after', $url, $user_id, $args ); - exit( wp_redirect( um_edit_my_profile_cancel_uri( $url ) ) ); - } + // Finally redirect to profile. + $url = um_user_profile_url( $user_id ); + $url = apply_filters( 'um_update_profile_redirect_after', $url, $user_id, $args ); + wp_safe_redirect( um_edit_my_profile_cancel_uri( $url ) ); + exit; } -add_action( 'um_user_edit_profile', 'um_user_edit_profile', 10 ); +add_action( 'um_user_edit_profile', 'um_user_edit_profile', 10, 2 ); /** - * @param array $post_form + * Validate nonce when profile form submit. + * + * @param array $submitted_data */ -function um_profile_validate_nonce( $post_form ) { - $user_id = isset( $post_form['user_id'] ) ? $post_form['user_id'] : ''; - $nonce = isset( $post_form['profile_nonce'] ) ? $post_form['profile_nonce'] : ''; +function um_profile_validate_nonce( $submitted_data ) { + $user_id = isset( $submitted_data['user_id'] ) ? $submitted_data['user_id'] : ''; + $nonce = isset( $submitted_data['profile_nonce'] ) ? $submitted_data['profile_nonce'] : ''; if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'um-profile-nonce' . $user_id ) ) { - wp_die( __( 'This is not possible for security reasons.', 'ultimate-member' ) ); + wp_die( esc_html__( 'This is not possible for security reasons.', 'ultimate-member' ) ); } } -add_action( 'um_submit_form_errors_hook__profile', 'um_profile_validate_nonce', 10, 1 ); +add_action( 'um_submit_form_errors_hook__profile', 'um_profile_validate_nonce', 1 ); - -add_filter( 'um_user_pre_updating_files_array', array( UM()->validation(), 'validate_files' ), 10, 1 ); -add_filter( 'um_before_save_filter_submitted', array( UM()->validation(), 'validate_fields_values' ), 10, 2 ); +// @todo maybe remove that because double validate +add_filter( 'um_user_pre_updating_files_array', array( UM()->validation(), 'validate_files' ) ); +// @todo maybe remove that because double validate +add_filter( 'um_before_save_filter_submitted', array( UM()->validation(), 'validate_fields_values' ), 10, 3 ); /** * Leave roles for User, which are not in the list of update profile (are default WP or 3rd plugins roles) @@ -1540,43 +1471,42 @@ add_action( 'um_main_profile_fields', 'um_add_profile_fields', 100 ); /** * Form processing * - * @param $args + * @param array $args + * @param array $form_data */ -function um_submit_form_profile( $args ) { +function um_submit_form_profile( $args, $form_data ) { if ( isset( UM()->form()->errors ) ) { return; } - UM()->fields()->set_mode = 'profile'; - UM()->fields()->editing = true; + UM()->fields()->set_mode = 'profile'; + UM()->fields()->editing = true; if ( ! empty( $args['submitted'] ) ) { $args['submitted'] = UM()->form()->clean_submitted_data( $args['submitted'] ); } /** - * UM hook + * Fires on successful submit profile form. * - * @type action - * @title um_user_edit_profile - * @description Run on successful submit profile form - * @input_vars - * [{"var":"$args","type":"array","desc":"Form Arguments"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_user_edit_profile', 'function_name', 10, 1 ); - * @example - * Callback name -> Excerpt): + * * 10 - `um_user_edit_profile()` Profile form main handler. + * + * @since 1.3.x + * @hook um_user_edit_profile + * + * @param {array} $post $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any custom action on successful submit profile form. + * function my_user_edit_profile( $post, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_user_edit_profile', 'my_user_edit_profile', 10, 2 ); */ - do_action( 'um_user_edit_profile', $args ); + do_action( 'um_user_edit_profile', $args, $form_data ); } -add_action( 'um_submit_form_profile', 'um_submit_form_profile', 10 ); - +add_action( 'um_submit_form_profile', 'um_submit_form_profile', 10, 2 ); /** * Show the submit button (highest priority) diff --git a/includes/core/um-actions-register.php b/includes/core/um-actions-register.php index 3bf016ce..b4d750c2 100644 --- a/includes/core/um-actions-register.php +++ b/includes/core/um-actions-register.php @@ -6,124 +6,121 @@ if ( ! defined( 'ABSPATH' ) ) { /** * Account automatically approved. * - * @param int $user_id - * @param array $args + * @param int $user_id */ -function um_post_registration_approved_hook( $user_id, $args ) { +function um_post_registration_approved_hook( $user_id ) { um_fetch_user( $user_id ); UM()->user()->approve(); } -add_action( 'um_post_registration_approved_hook', 'um_post_registration_approved_hook', 10, 2 ); +add_action( 'um_post_registration_approved_hook', 'um_post_registration_approved_hook' ); /** * Account needs email validation. * - * @param int $user_id - * @param array $args + * @param int $user_id */ -function um_post_registration_checkmail_hook( $user_id, $args ) { +function um_post_registration_checkmail_hook( $user_id ) { um_fetch_user( $user_id ); UM()->user()->email_pending(); } -add_action( 'um_post_registration_checkmail_hook', 'um_post_registration_checkmail_hook', 10, 2 ); +add_action( 'um_post_registration_checkmail_hook', 'um_post_registration_checkmail_hook' ); /** * Account needs admin review. * - * @param int $user_id - * @param array $args + * @param int $user_id */ -function um_post_registration_pending_hook( $user_id, $args ) { +function um_post_registration_pending_hook( $user_id ) { um_fetch_user( $user_id ); UM()->user()->pending(); } -add_action( 'um_post_registration_pending_hook', 'um_post_registration_pending_hook', 10, 2 ); +add_action( 'um_post_registration_pending_hook', 'um_post_registration_pending_hook' ); /** - * After insert a new user - * run at frontend and backend + * After insert a new user run at frontend and backend. * - * @param $user_id - * @param $args + * @param int|WP_Error $user_id + * @param array $args + * @param null|array $form_data It's null in case when posted from wp-admin > Add user */ -function um_after_insert_user( $user_id, $args ) { - if ( empty( $user_id ) || ( is_object( $user_id ) && is_a( $user_id, 'WP_Error' ) ) ) { +function um_after_insert_user( $user_id, $args, $form_data = null ) { + if ( empty( $user_id ) || is_wp_error( $user_id ) ) { return; } + // Set usermeta from submission. um_fetch_user( $user_id ); if ( ! empty( $args['submitted'] ) ) { - UM()->user()->set_registration_details( $args['submitted'], $args ); + // It's only frontend case. + UM()->user()->set_registration_details( $args['submitted'], $args, $form_data ); } + // Set user status. $status = um_user( 'status' ); if ( empty( $status ) ) { um_fetch_user( $user_id ); $status = um_user( 'status' ); } - - /* save user status */ UM()->user()->set_status( $status ); - /* create user uploads directory */ + // Create user uploads directory. UM()->uploader()->get_upload_user_base_dir( $user_id, true ); /** - * UM hook + * Fires after insert user to DB and there you can set any extra details. * - * @type action - * @title um_registration_set_extra_data - * @description Hook that runs after insert user to DB and there you can set any extra details - * @input_vars - * [{"var":"$user_id","type":"int","desc":"User ID"}, - * {"var":"$args","type":"array","desc":"Form data"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_registration_set_extra_data', 'function_name', 10, 2 ); - * @example - * Callback name -> Excerpt): + * 10 - `um_registration_save_files()` Save registration files. + * 100 - `um_registration_set_profile_full_name()` Set user's full name. + * + * @since 2.0 + * @hook um_registration_set_extra_data + * + * @param {int} $user_id User ID. + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any custom action after insert user to DB. + * function my_registration_set_extra_data( $user_id, $submitted_data, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_registration_set_extra_data', 'my_registration_set_extra_data', 10, 3 ); */ - do_action( 'um_registration_set_extra_data', $user_id, $args ); - + do_action( 'um_registration_set_extra_data', $user_id, $args, $form_data ); /** - * UM hook + * Fires after complete UM user registration. + * Note: Native redirects handlers at 100 priority, you can add some info before redirects. * - * @type action - * @title um_registration_complete - * @description After complete UM user registration. Redirects handlers at 100 priority, you can add some info before redirects - * @input_vars - * [{"var":"$user_id","type":"int","desc":"User ID"}, - * {"var":"$args","type":"array","desc":"Form data"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_registration_complete', 'function_name', 10, 2 ); - * @example - * Callback name -> Excerpt): + * 10 - `um_send_registration_notification()` Send notifications. + * 100 - `um_check_user_status()` Redirect after registration based on user status. + * + * @since 2.0 + * @hook um_registration_complete + * + * @param {int} $user_id User ID. + * @param {array} $submitted_data $_POST Submission array. + * @param {array} $form_data UM form data. Since 2.6.7 + * + * @example Make any common action after complete UM user registration. + * function my_registration_complete( $user_id, $submitted_data, $form_data ) { * // your code here * } - * ?> + * add_action( 'um_registration_complete', 'my_registration_complete', 10, 3 ); */ - do_action( 'um_registration_complete', $user_id, $args ); + do_action( 'um_registration_complete', $user_id, $args, $form_data ); } -add_action( 'um_user_register', 'um_after_insert_user', 1, 2 ); +add_action( 'um_user_register', 'um_after_insert_user', 1, 3 ); /** * Send notification about registration * * @param $user_id - * @param $args */ -function um_send_registration_notification( $user_id, $args ) { +function um_send_registration_notification( $user_id ) { um_fetch_user( $user_id ); $emails = um_multi_admin_email(); @@ -137,17 +134,17 @@ function um_send_registration_notification( $user_id, $args ) { } } } -add_action( 'um_registration_complete', 'um_send_registration_notification', 10, 2 ); +add_action( 'um_registration_complete', 'um_send_registration_notification' ); /** * Check user status and redirect it after registration * - * @param $user_id - * @param $args + * @param int $user_id + * @param array $args + * @param null|array $form_data */ -function um_check_user_status( $user_id, $args ) { +function um_check_user_status( $user_id, $args, $form_data = null ) { $status = um_user( 'account_status' ); - /** * UM hook * @@ -170,117 +167,123 @@ function um_check_user_status( $user_id, $args ) { */ do_action( "um_post_registration_{$status}_hook", $user_id, $args ); - if ( ! is_admin() ) { + if ( is_null( $form_data ) || is_admin() ) { + return; + } - do_action( "track_{$status}_user_registration" ); + do_action( "track_{$status}_user_registration" ); - if ( $status == 'approved' ) { - // Check if user is logged in because there can be the customized way when through 'um_registration_for_loggedin_users' hook the registration is enabled for the logged in users (e.g. Administrator). - if ( ! is_user_logged_in() ) { - // Custom way if 'um_registration_for_loggedin_users' hook after custom callbacks returns true. Then don't make auto-login because user is already logged-in. - UM()->user()->auto_login( $user_id ); - } - UM()->user()->generate_profile_slug( $user_id ); + if ( 'approved' === $status ) { + // Check if user is logged in because there can be the customized way when through 'um_registration_for_loggedin_users' hook the registration is enabled for the logged-in users (e.g. Administrator). + if ( ! is_user_logged_in() ) { + // Custom way if 'um_registration_for_loggedin_users' hook after custom callbacks returns true. Then don't make auto-login because user is already logged-in. + UM()->user()->auto_login( $user_id ); + } + UM()->user()->generate_profile_slug( $user_id ); + /** + * UM hook + * + * @type action + * @title um_registration_after_auto_login + * @description After complete UM user registration and autologin. + * @input_vars + * [{"var":"$user_id","type":"int","desc":"User ID"}] + * @change_log + * ["Since: 2.0"] + * @usage add_action( 'um_registration_after_auto_login', 'function_name', 10, 1 ); + * @example + * + */ + do_action( 'um_registration_after_auto_login', $user_id ); + + // Priority redirect + if ( isset( $args['redirect_to'] ) ) { + wp_safe_redirect( urldecode( $args['redirect_to'] ) ); + exit; + } + + um_fetch_user( $user_id ); + + if ( 'redirect_url' === um_user( 'auto_approve_act' ) && '' !== um_user( 'auto_approve_url' ) ) { + wp_safe_redirect( um_user( 'auto_approve_url' ) ); + exit; + } + + if ( 'redirect_profile' === um_user( 'auto_approve_act' ) ) { + wp_safe_redirect( um_user_profile_url() ); + exit; + } + } else { + if ( 'redirect_url' === um_user( $status . '_action' ) && '' !== um_user( $status . '_url' ) ) { /** * UM hook * - * @type action - * @title um_registration_after_auto_login - * @description After complete UM user registration and autologin. + * @type filter + * @title um_registration_pending_user_redirect + * @description Change redirect URL for pending user after registration * @input_vars - * [{"var":"$user_id","type":"int","desc":"User ID"}] + * [{"var":"$url","type":"string","desc":"Redirect URL"}, + * {"var":"$status","type":"string","desc":"User status"}, + * {"var":"$user_id","type":"int","desc":"User ID"}] * @change_log * ["Since: 2.0"] - * @usage add_action( 'um_registration_after_auto_login', 'function_name', 10, 1 ); + * @usage + * * @example * */ - do_action( 'um_registration_after_auto_login', $user_id ); - - // Priority redirect - if ( isset( $args['redirect_to'] ) ) { - exit( wp_safe_redirect( urldecode( $args['redirect_to'] ) ) ); - } - - um_fetch_user( $user_id ); - - if ( um_user( 'auto_approve_act' ) == 'redirect_url' && um_user( 'auto_approve_url' ) !== '' ) { - exit( wp_redirect( um_user( 'auto_approve_url' ) ) ); - } - - if ( um_user( 'auto_approve_act' ) == 'redirect_profile' ) { - exit( wp_redirect( um_user_profile_url() ) ); - } - - } else { - - if ( um_user( $status . '_action' ) == 'redirect_url' && um_user( $status . '_url' ) != '' ) { - /** - * UM hook - * - * @type filter - * @title um_registration_pending_user_redirect - * @description Change redirect URL for pending user after registration - * @input_vars - * [{"var":"$url","type":"string","desc":"Redirect URL"}, - * {"var":"$status","type":"string","desc":"User status"}, - * {"var":"$user_id","type":"int","desc":"User ID"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * - */ - $redirect_url = apply_filters( 'um_registration_pending_user_redirect', um_user( $status . '_url' ), $status, um_user( 'ID' ) ); - - exit( wp_redirect( $redirect_url ) ); - } - - if ( um_user( $status . '_action' ) == 'show_message' && um_user( $status . '_message' ) != '' ) { - - $url = UM()->permalinks()->get_current_url(); - $url = add_query_arg( 'message', esc_attr( $status ), $url ); - //add only priority role to URL - $url = add_query_arg( 'um_role', esc_attr( um_user( 'role' ) ), $url ); - $url = add_query_arg( 'um_form_id', esc_attr( $args['form_id'] ), $url ); - - exit( wp_redirect( $url ) ); - } + $redirect_url = apply_filters( 'um_registration_pending_user_redirect', um_user( $status . '_url' ), $status, um_user( 'ID' ) ); + wp_safe_redirect( $redirect_url ); + exit; } + if ( 'show_message' === um_user( $status . '_action' ) && '' !== um_user( $status . '_message' ) ) { + $url = UM()->permalinks()->get_current_url(); + $url = add_query_arg( 'message', esc_attr( $status ), $url ); + // Add only priority role to URL. + $url = add_query_arg( 'um_role', esc_attr( um_user( 'role' ) ), $url ); + $url = add_query_arg( 'um_form_id', esc_attr( $form_data['form_id'] ), $url ); + + wp_safe_redirect( $url ); + exit; + } } - } -add_action( 'um_registration_complete', 'um_check_user_status', 100, 2 ); +add_action( 'um_registration_complete', 'um_check_user_status', 100, 3 ); -function um_submit_form_errors_hook__registration( $args ) { +/** + * Validate user password field on registration. + * + * @param array $submitted_data + */ +function um_submit_form_errors_hook__registration( $submitted_data ) { // Check for "\" in password. - if ( array_key_exists( 'user_password', $args ) && false !== strpos( wp_unslash( trim( $args['user_password'] ) ), '\\' ) ) { + if ( array_key_exists( 'user_password', $submitted_data ) && false !== strpos( wp_unslash( trim( $submitted_data['user_password'] ) ), '\\' ) ) { UM()->form()->add_error( 'user_password', __( 'Passwords may not contain the character "\\".', 'ultimate-member' ) ); } } -add_action( 'um_submit_form_errors_hook__registration', 'um_submit_form_errors_hook__registration', 10, 1 ); +add_action( 'um_submit_form_errors_hook__registration', 'um_submit_form_errors_hook__registration' ); /** * Registration form submit handler. * * @param array $args + * @param array $form_data */ -function um_submit_form_register( $args ) { +function um_submit_form_register( $args, $form_data ) { if ( isset( UM()->form()->errors ) ) { return; } @@ -294,17 +297,18 @@ function um_submit_form_register( $args ) { * @hook um_add_user_frontend_submitted * * @param {array} $submitted Submitted registration data. + * @param {array} $form_data UM form data. Since 2.6.7 * * @return {array} Extended registration data. * * @example Extends registration data. - * function my_add_user_frontend_submitted( $submitted ) { + * function my_add_user_frontend_submitted( $submitted, $form_data ) { * // your code here * return $submitted; * } - * add_filter( 'um_add_user_frontend_submitted', 'my_add_user_frontend_submitted' ); + * add_filter( 'um_add_user_frontend_submitted', 'my_add_user_frontend_submitted', 10, 2 ); */ - $args = apply_filters( 'um_add_user_frontend_submitted', $args ); + $args = apply_filters( 'um_add_user_frontend_submitted', $args, $form_data ); if ( ! empty( $args['user_login'] ) ) { $user_login = $args['user_login']; @@ -406,6 +410,7 @@ function um_submit_form_register( $args ) { 'user_email' => trim( $user_email ), ); + // @todo test when ready maybe remove if ( ! empty( $args['submitted'] ) ) { $args['submitted'] = UM()->form()->clean_submitted_data( $args['submitted'] ); } @@ -441,17 +446,18 @@ function um_submit_form_register( $args ) { * * @param {string} $user_role User role. * @param {array} $args Registration data. + * @param {array} $form_data UM form data. Since 2.6.7 * * @return {string} User role. * * @example Change user role on registration process. - * function my_registration_user_role( $user_role, $args ) { + * function my_registration_user_role( $user_role, $args, $form_data ) { * // your code here * return $user_role; * } - * add_filter( 'um_registration_user_role', 'my_registration_user_role', 10, 2 ); + * add_filter( 'um_registration_user_role', 'my_registration_user_role', 10, 3 ); */ - $user_role = apply_filters( 'um_registration_user_role', $user_role, $args ); + $user_role = apply_filters( 'um_registration_user_role', $user_role, $args, $form_data ); $userdata = array( 'user_login' => $user_login, @@ -461,25 +467,32 @@ function um_submit_form_register( $args ) { ); $user_id = wp_insert_user( $userdata ); + if ( is_wp_error( $user_id ) ) { + return; + } /** * Fires after complete UM user registration. * + * Internal Ultimate Member callbacks (Priority -> Callback name -> Excerpt): + * 1 - `um_after_insert_user()` Make all Ultimate Member data set and actions after user registration|added via wp-admin. + * * @since 2.0 * @hook um_user_register * - * @param {int} $user_id User ID. - * @param {array} $args Form data. + * @param {int} $user_id User ID. + * @param {array} $args Form data. + * @param {array} $form_data UM form data. Since 2.6.7 * * @example Make any custom action after complete UM user registration. - * function my_um_user_register( $user_id, $args ) { + * function my_um_user_register( $user_id, $args, $form_data ) { * // your code here * } - * add_action( 'um_user_register', 'my_um_user_register', 10, 2 ); + * add_action( 'um_user_register', 'my_um_user_register', 10, 3 ); */ - do_action( 'um_user_register', $user_id, $args ); + do_action( 'um_user_register', $user_id, $args, $form_data ); } -add_action( 'um_submit_form_register', 'um_submit_form_register' ); +add_action( 'um_submit_form_register', 'um_submit_form_register', 10, 2 ); /** * Show the submit button @@ -610,71 +623,60 @@ function um_add_register_fields( $args ){ } add_action( 'um_main_register_fields', 'um_add_register_fields', 100 ); - /** - * Saving files to register a new user, if there are fields with files + * Saving files to register a new user, if there are fields with files. * * @param $user_id * @param $args + * @param $form_data */ -function um_registration_save_files( $user_id, $args ) { - - if ( empty( $args['custom_fields'] ) ) { +function um_registration_save_files( $user_id, $args, $form_data ) { + if ( empty( $args['submitted'] ) ) { + // It's only frontend case. return; } $files = array(); - $fields = unserialize( $args['custom_fields'] ); - - // loop through fields - if ( isset( $fields ) && is_array( $fields ) ) { - + $fields = maybe_unserialize( $form_data['custom_fields'] ); + if ( ! empty( $fields ) && is_array( $fields ) ) { foreach ( $fields as $key => $array ) { - if ( isset( $args['submitted'][ $key ] ) ) { - - if ( isset( $fields[ $key ]['type'] ) && in_array( $fields[ $key ]['type'], array( 'image', 'file' ) ) && - ( um_is_temp_file( $args['submitted'][ $key ] ) || $args['submitted'][ $key ] == 'empty_file' ) + if ( isset( $array['type'] ) && in_array( $array['type'], array( 'image', 'file' ), true ) && + ( um_is_temp_file( $args['submitted'][ $key ] ) || 'empty_file' === $args['submitted'][ $key ] ) ) { - $files[ $key ] = $args['submitted'][ $key ]; - } } } } /** - * UM hook + * Filters files submitted by the UM registration or profile form. * - * @type filter - * @title um_user_pre_updating_files_array - * @description Change submitted files before register new user - * @input_vars - * [{"var":"$files","type":"array","desc":"Profile data files"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * Extends submitted files. + * function my_user_pre_updating_files( $files, $user_id ) { + * $files[] = 'some file'; * return $files; * } - * ?> + * add_filter( 'um_user_pre_updating_files_array', 'my_user_pre_updating_files', 10, 2 ); */ - $files = apply_filters( 'um_user_pre_updating_files_array', $files ); - - if ( ! empty( $files ) ) { + $files = apply_filters( 'um_user_pre_updating_files_array', $files, $user_id ); + if ( ! empty( $files ) && is_array( $files ) ) { UM()->uploader()->replace_upload_dir = true; UM()->uploader()->move_temporary_files( $user_id, $files ); UM()->uploader()->replace_upload_dir = false; } } -add_action( 'um_registration_set_extra_data', 'um_registration_save_files', 10, 2 ); +add_action( 'um_registration_set_extra_data', 'um_registration_save_files', 10, 3 ); /** @@ -687,35 +689,29 @@ add_action( 'um_registration_set_extra_data', 'um_registration_save_files', 10, */ function um_registration_set_profile_full_name( $user_id, $args ) { /** - * UM hook + * Fires for updating user profile full name. * - * @type action - * @title um_update_profile_full_name - * @description On update user profile change full name - * @input_vars - * [{"var":"$user_id","type":"int","desc":"User ID"}, - * {"var":"$args","type":"array","desc":"Form data"}] - * @change_log - * ["Since: 2.0"] - * @usage add_action( 'um_update_profile_full_name', 'function_name', 10, 2 ); - * @example - * Make any custom action when updating user profile full name. + * function my_registration_set_extra_data( $user_id, $submitted_data ) { * // your code here * } - * ?> + * add_action( 'um_update_profile_full_name', 'my_update_profile_full_name', 10, 2 ); */ do_action( 'um_update_profile_full_name', $user_id, $args ); } add_action( 'um_registration_set_extra_data', 'um_registration_set_profile_full_name', 10, 2 ); - /** * Redirect from default registration to UM registration page */ function um_form_register_redirect() { - $page_id = UM()->options()->get( UM()->options()->get_core_page_id( 'register' ) ); + $page_id = UM()->options()->get( UM()->options()->get_core_page_id( 'register' ) ); $register_post = get_post( $page_id ); if ( ! empty( $register_post ) ) { wp_safe_redirect( get_permalink( $page_id ) ); diff --git a/includes/core/um-filters-fields.php b/includes/core/um-filters-fields.php index 2bf8bb6d..12101d31 100644 --- a/includes/core/um-filters-fields.php +++ b/includes/core/um-filters-fields.php @@ -898,12 +898,13 @@ add_filter( 'um_profile_field_filter_hook__', 'um_profile_field_filter_xss_valid /** * Trim All form POST submitted data * + * @todo Maybe deprecate because data is sanitized in earlier code and trim included to `sanitize_text_field()`. Need testing and confirmation. + * * @param $post_form - * @param $mode * * @return mixed */ -function um_submit_form_data_trim_fields( $post_form, $mode ) { +function um_submit_form_data_trim_fields( $post_form ) { foreach ( $post_form as $key => $field ) { if ( is_string( $field ) ) { $post_form[ $key ] = trim( $field ); @@ -912,30 +913,44 @@ function um_submit_form_data_trim_fields( $post_form, $mode ) { return $post_form; } -add_filter( 'um_submit_form_data', 'um_submit_form_data_trim_fields', 9, 2 ); +add_filter( 'um_submit_form_data', 'um_submit_form_data_trim_fields', 9, 1 ); /** - * add role_select and role_radio to the $post_form - * It is necessary for that if on these fields the conditional logic - * @param $post_form array - * @param $mode + * Add `role_select` and `role_radio` to the $post_form + * It is necessary for that if on these fields the conditional logic. * - * @return $post_form - * @uses hook filters: um_submit_form_data + * @param array $post_form + * @param string $mode + * @param array $all_cf_metakeys + * + * @return array */ -function um_submit_form_data_role_fields( $post_form, $mode ) { - $custom_fields = unserialize( $post_form['custom_fields'] ); - if ( ! empty( $post_form['role'] ) && array_key_exists( 'role_select', $custom_fields ) ) { - $post_form['role_select'] = $post_form['role']; +function um_submit_form_data_role_fields( $post_form, $mode, $all_cf_metakeys ) { + if ( 'login' === $mode ) { + return $post_form; } - if (! empty( $post_form['role'] ) && array_key_exists( 'role_radio', $custom_fields ) ) { - $post_form['role_radio'] = $post_form['role']; + + if ( ! array_key_exists( 'role', $post_form ) ) { + return $post_form; + } + + $role_fields = array( 'role_select', 'role_radio' ); + + $form_has_role_field = count( array_intersect( $all_cf_metakeys, $role_fields ) ) > 0; + if ( ! $form_has_role_field ) { + return $post_form; + } + + foreach ( $role_fields as $role_field ) { + if ( in_array( $role_field, $all_cf_metakeys, true ) ) { + $post_form[ $role_field ] = $post_form['role']; + } } return $post_form; } -add_filter( 'um_submit_form_data', 'um_submit_form_data_role_fields', 10, 2 ); +add_filter( 'um_submit_form_data', 'um_submit_form_data_role_fields', 10, 3 ); /** diff --git a/includes/core/um-filters-login.php b/includes/core/um-filters-login.php index 185ad9b8..18af141c 100644 --- a/includes/core/um-filters-login.php +++ b/includes/core/um-filters-login.php @@ -43,8 +43,10 @@ add_filter( 'login_message', 'um_custom_wp_err_messages' ); */ function um_wp_form_errors_hook_ip_test( $user, $username, $password ) { if ( ! empty( $username ) ) { - do_action( 'um_submit_form_errors_hook__blockedips', array() ); - do_action( 'um_submit_form_errors_hook__blockedemails', array( 'username' => $username ) ); + /** This action is documented in includes/core/um-actions-form.php */ + do_action( 'um_submit_form_errors_hook__blockedips', array(), null ); + /** This action is documented in includes/core/um-actions-form.php */ + do_action( 'um_submit_form_errors_hook__blockedemails', array( 'username' => $username ), null ); } return $user; @@ -53,7 +55,7 @@ add_filter( 'authenticate', 'um_wp_form_errors_hook_ip_test', 10, 3 ); /** - * Login checks thru the wordpress admin login + * Login checks through the WordPress admin login. * * @param $user * @param $username @@ -93,8 +95,8 @@ add_filter( 'authenticate', 'um_wp_form_errors_hook_logincheck', 50, 3 ); /** * Change lost password url in UM Login form - * @param string $lostpassword_url - * @return string + * @param string $lostpassword_url + * @return string */ function um_lostpassword_url( $lostpassword_url ) { diff --git a/readme.txt b/readme.txt index 06f8c613..bccf43b9 100644 --- a/readme.txt +++ b/readme.txt @@ -160,8 +160,15 @@ No, you do not need to use our plugin’s login or registration pages and can us = Important: = -* To learn more about version 2.1 please see this [docs](https://docs.ultimatemember.com/article/1512-upgrade-2-1-0) -* UM2.1+ is a significant update to the Member Directories' code base from 2.0.x. Please make sure you take a full-site backup with restore point before updating the plugin +IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSION 2.6.7 PATCHES SECURITY PRIVILEGE ESCALATION VULNERABILITY. + += 2.6.7: July 1, 2023 = + +* Bugfixes: + + - Fixed: A privilege escalation vulnerability used through UM Forms. Known in the wild that vulnerability allowed strangers to create administrator-level WordPress users. Please update immediately and check all administrator-level users on your website. + - Fixed: Displaying fields on Account page > Privacy > Member directory settings + - Fixed: Allowed types for the file field = 2.6.6: June 29, 2023 = diff --git a/ultimate-member.php b/ultimate-member.php index 11466c42..032244b2 100644 --- a/ultimate-member.php +++ b/ultimate-member.php @@ -3,7 +3,7 @@ Plugin Name: Ultimate Member Plugin URI: http://ultimatemember.com/ Description: The easiest way to create powerful online communities and beautiful user profiles with WordPress -Version: 2.6.6 +Version: 2.6.7 Author: Ultimate Member Author URI: http://ultimatemember.com/ Text Domain: ultimate-member