From 3f473806db3ac705516d448f68e0faeed6c6ce43 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Tue, 25 Jul 2023 13:52:24 +0300 Subject: [PATCH 01/28] - updated versions; --- readme.txt | 4 ++++ ultimate-member.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index 8f51d06a..1cac921f 100644 --- a/readme.txt +++ b/readme.txt @@ -166,6 +166,10 @@ No specific extensions are needed. But we highly recommended keep active these P IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSION 2.6.7 PATCHES SECURITY PRIVILEGE ESCALATION VULNERABILITY. PLEASE SEE [THIS ARTICLE](https://docs.ultimatemember.com/article/1866-security-incident-update-and-recommended-actions) FOR MORE INFORMATION += 2.6.10: August xx, 2023 = + + + = 2.6.9: July 26, 2023 = * Enhancements: diff --git a/ultimate-member.php b/ultimate-member.php index 1366a2b5..b9ba49ad 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.9 + * Version: 2.6.10-alpha * Author: Ultimate Member * Author URI: http://ultimatemember.com/ * Text Domain: ultimate-member From c9789b8462e02c64685856e383ecbc7caa08938b Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Thu, 27 Jul 2023 13:37:01 +0300 Subject: [PATCH 02/28] - standardize the condition for checking not editable fields to `empty( $data['editable']` --- includes/core/class-fields.php | 4 ++-- includes/um-short-functions.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/includes/core/class-fields.php b/includes/core/class-fields.php index c901eeec..6c3670f4 100644 --- a/includes/core/class-fields.php +++ b/includes/core/class-fields.php @@ -3597,7 +3597,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { $class = 'um-icon-android-radio-button-off'; } - if ( isset( $data['editable'] ) && 0 === $data['editable'] ) { + if ( empty( $data['editable'] ) ) { $col_class .= ' um-field-radio-state-disabled'; } @@ -3716,7 +3716,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { $class = 'um-icon-android-checkbox-outline-blank'; } - if ( isset( $data['editable'] ) && 0 === $data['editable'] ) { + if ( empty( $data['editable'] ) ) { $col_class .= ' um-field-radio-state-disabled'; } diff --git a/includes/um-short-functions.php b/includes/um-short-functions.php index 3ad24c9b..07f4b354 100644 --- a/includes/um-short-functions.php +++ b/includes/um-short-functions.php @@ -1663,7 +1663,7 @@ function um_can_edit_field( $data ) { $can_edit = false; } else { if ( ! UM()->roles()->um_user_can( 'can_edit_everyone' ) ) { - if ( isset( $data['editable'] ) && $data['editable'] == 0 ) { + if ( empty( $data['editable'] ) ) { $can_edit = false; } else { if ( ! um_is_user_himself() ) { From 9cb4d5fa8fb561266e3ffee041628efe5ac8b639 Mon Sep 17 00:00:00 2001 From: ashubawork Date: Thu, 27 Jul 2023 14:39:08 +0300 Subject: [PATCH 03/28] - fix count of words and letters for the bio field --- assets/js/um-profile.js | 7 +++- includes/core/um-actions-form.php | 54 ++++++++++++++++++++-------- includes/core/um-actions-profile.php | 1 + 3 files changed, 47 insertions(+), 15 deletions(-) diff --git a/assets/js/um-profile.js b/assets/js/um-profile.js index 5929df97..8f0f3381 100644 --- a/assets/js/um-profile.js +++ b/assets/js/um-profile.js @@ -110,7 +110,12 @@ jQuery(document).ready(function() { jQuery( document.body ).on( 'change keyup', '#um-meta-bio', function() { if ( typeof jQuery(this).val() !== 'undefined' ) { var um_bio_limit = jQuery(this).data( 'character-limit' ); - var remaining = um_bio_limit - jQuery(this).val().length; + var bio_html = jQuery(this).attr('data-html'); + if ( parseInt( bio_html ) === 1 ){ + var remaining = um_bio_limit - jQuery(this).val().replace(/(<([^>]+)>)/ig,'').length; + } else { + var remaining = um_bio_limit - jQuery(this).val().length; + } jQuery( 'span.um-meta-bio-character span.um-bio-limit' ).text( remaining ); if ( remaining < 5 ) { diff --git a/includes/core/um-actions-form.php b/includes/core/um-actions-form.php index 0d847b2e..3222faa1 100644 --- a/includes/core/um-actions-form.php +++ b/includes/core/um-actions-form.php @@ -573,9 +573,14 @@ function um_submit_form_errors_hook_( $submitted_data, $form_data ) { } if ( isset( $array['max_words'] ) && $array['max_words'] > 0 ) { - // count words without html tags - $without_tags = wp_strip_all_tags( $submitted_data[ $key ] ); - if ( str_word_count( $without_tags, 0, 'éèàôù' ) > $array['max_words'] ) { + if ( array_key_exists( 'html', $array ) && 1 === (int) $array['html'] ) { + $text_value = wp_strip_all_tags( $submitted_data[ $key ] ); + } else { + // count words without html tags + $text_value = $submitted_data[ $key ]; + } + + if ( str_word_count( $text_value, 0, '0123456789éèàôù' ) > $array['max_words'] ) { // translators: %s: max words. UM()->form()->add_error( $key, sprintf( __( 'You are only allowed to enter a maximum of %s words', 'ultimate-member' ), $array['max_words'] ) ); } @@ -668,6 +673,23 @@ function um_submit_form_errors_hook_( $submitted_data, $form_data ) { } } + if ( isset( $submitted_data['description'] ) ) { + $max_chars = UM()->options()->get( 'profile_bio_maxchars' ); + $profile_show_bio = UM()->options()->get( 'profile_show_bio' ); + if ( ! UM()->options()->get( 'profile_show_html_bio' ) ) { + $description_value = $submitted_data['description']; + } else { + $description_value = wp_strip_all_tags( $submitted_data['description'] ); + } + + if ( $profile_show_bio ) { + if ( mb_strlen( str_replace( array( "\r\n", "\n", "\r\t", "\t" ), ' ', $description_value ) ) > $max_chars && $max_chars ) { + // translators: %s: max chars. + UM()->form()->add_error( 'description', sprintf( __( 'Your user description must contain less than %s characters', 'ultimate-member' ), $max_chars ) ); + } + } + } + if ( empty( $array['validate'] ) ) { continue; } @@ -933,17 +955,21 @@ function um_submit_form_errors_hook_( $submitted_data, $form_data ) { } - 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 ) { - // translators: %s: max chars. - UM()->form()->add_error( 'description', sprintf( __( 'Your user description must contain less than %s characters', 'ultimate-member' ), $max_chars ) ); - } - } - } +// if ( isset( $submitted_data['description'] ) ) { +// echo '
';
+//			print_r($submitted_data);
+//			echo '
'; +// exit(); +// $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 ) { +// // translators: %s: 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, 2 ); diff --git a/includes/core/um-actions-profile.php b/includes/core/um-actions-profile.php index 625994b4..b2a99eae 100644 --- a/includes/core/um-actions-profile.php +++ b/includes/core/um-actions-profile.php @@ -1241,6 +1241,7 @@ function um_profile_header( $args ) {
From bb4139e514659365488c66604a787e79a8caeb42 Mon Sep 17 00:00:00 2001 From: ashubawork Date: Fri, 28 Jul 2023 10:49:36 +0300 Subject: [PATCH 04/28] - fix bio conflict --- includes/core/class-fields.php | 17 ++++++++++++++++- includes/core/um-actions-profile.php | 18 ++++++++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/includes/core/class-fields.php b/includes/core/class-fields.php index 6c3670f4..71f3384e 100644 --- a/includes/core/class-fields.php +++ b/includes/core/class-fields.php @@ -2767,7 +2767,22 @@ if ( ! class_exists( 'um\core\Fields' ) ) { } else { $textarea_field_value = ''; if ( ! empty( $field_value ) ) { - $textarea_field_value = ! empty( $data['html'] ) ? $field_value : wp_strip_all_tags( $field_value ); + $profile_custom_settings = get_post_meta( $this->global_args['form_id'], '_um_profile_use_custom_settings', true ); + if ( 1 === $profile_custom_settings ) { + $bio_html = get_post_meta( $this->global_args['form_id'], '_um_profile_show_bio', true ); + } else { + if ( UM()->options()->get( 'profile_show_html_bio' ) ) { + $bio_html = 1; + } else { + $bio_html = 0; + } + } + + if ( 1 === (int) $bio_html && array_key_exists( 'html', $data ) && 1 === (int) $data['html'] ) { + $textarea_field_value = $field_value; + } else { + $textarea_field_value = wp_strip_all_tags( $field_value ); + } } $output .= ''; } diff --git a/includes/core/um-actions-profile.php b/includes/core/um-actions-profile.php index b2a99eae..1c548ec0 100644 --- a/includes/core/um-actions-profile.php +++ b/includes/core/um-actions-profile.php @@ -1237,14 +1237,28 @@ function um_profile_header( $args ) { } ?>
- fields()->editing == true && $args['show_bio'] ) { ?> + fields()->editing == true && $args['show_bio'] ) { + if ( ! empty( $args['custom_fields']['description'] ) ) { + if ( array_key_exists( 'html', $args['custom_fields']['description'] ) && 1 === (int) $args['custom_fields']['description']['html'] && 1 === (int) UM()->options()->get( 'profile_show_html_bio' ) ) { + $description_value = UM()->fields()->field_value( $description_key ); + } else { + $description_value = wp_strip_all_tags( UM()->fields()->field_value( $description_key ) ); + } + } else { + if ( 1 === (int) UM()->options()->get( 'profile_show_html_bio' ) ) { + $description_value = UM()->fields()->field_value( $description_key ); + } else { + $description_value = wp_strip_all_tags( UM()->fields()->field_value( $description_key ) ); + } + } + ?>
+ name=""> options()->get( 'profile_bio_maxchars' ); ?> From 82d574b93b14133a07bf102015bf994a4c0c3ecc Mon Sep 17 00:00:00 2001 From: ashubawork Date: Fri, 28 Jul 2023 15:25:55 +0300 Subject: [PATCH 05/28] - fix limit chars for bio --- includes/core/um-actions-profile.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/includes/core/um-actions-profile.php b/includes/core/um-actions-profile.php index 1c548ec0..93b33ed2 100644 --- a/includes/core/um-actions-profile.php +++ b/includes/core/um-actions-profile.php @@ -1251,16 +1251,22 @@ function um_profile_header( $args ) { $description_value = wp_strip_all_tags( UM()->fields()->field_value( $description_key ) ); } } + if ( array_key_exists( 'max_chars', $args['custom_fields']['description'] ) ) { + $limit = $args['custom_fields']['description']['max_chars']; + } else { + $limit = UM()->options()->get( 'profile_bio_maxchars' ); + } ?>
- options()->get( 'profile_bio_maxchars' ); ?> + + + fields()->is_error( $description_key ) ) { echo UM()->fields()->field_error( UM()->fields()->show_error( $description_key ), true ); From b31006a143efc986b13ff878388804c6b87b0943 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Sun, 30 Jul 2023 22:59:49 +0300 Subject: [PATCH 06/28] - fixed templates version; --- includes/core/class-access.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/includes/core/class-access.php b/includes/core/class-access.php index 9c24d7f2..765fc357 100644 --- a/includes/core/class-access.php +++ b/includes/core/class-access.php @@ -1843,12 +1843,16 @@ if ( ! class_exists( 'um\core\Access' ) ) { * @param \WP_Post|int $post Post ID or object * @return bool|array */ - function get_post_privacy_settings( $post ) { + public function get_post_privacy_settings( $post ) { // break for incorrect post if ( empty( $post ) ) { return false; } + if ( ! is_numeric( $post ) && ! is_a( $post, \WP_Post::class ) ) { + return false; + } + static $cache = array(); $cache_key = is_numeric( $post ) ? $post : $post->ID; From ba2cc1cd9407cd887233cab257d74a1aa26c17d0 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Sun, 30 Jul 2023 22:59:49 +0300 Subject: [PATCH 07/28] - fixed PHP notices in some cases when WP query is not canonical; --- includes/core/class-access.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/includes/core/class-access.php b/includes/core/class-access.php index 9c24d7f2..765fc357 100644 --- a/includes/core/class-access.php +++ b/includes/core/class-access.php @@ -1843,12 +1843,16 @@ if ( ! class_exists( 'um\core\Access' ) ) { * @param \WP_Post|int $post Post ID or object * @return bool|array */ - function get_post_privacy_settings( $post ) { + public function get_post_privacy_settings( $post ) { // break for incorrect post if ( empty( $post ) ) { return false; } + if ( ! is_numeric( $post ) && ! is_a( $post, \WP_Post::class ) ) { + return false; + } + static $cache = array(); $cache_key = is_numeric( $post ) ? $post : $post->ID; From 7f7556719b8a895643917a0b19d280f3a2fa6fde Mon Sep 17 00:00:00 2001 From: ashubawork Date: Mon, 31 Jul 2023 09:11:05 +0300 Subject: [PATCH 08/28] - fix description length error --- includes/core/um-actions-form.php | 41 ++++++++++++++++--------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/includes/core/um-actions-form.php b/includes/core/um-actions-form.php index 3222faa1..57b62730 100644 --- a/includes/core/um-actions-form.php +++ b/includes/core/um-actions-form.php @@ -673,16 +673,33 @@ function um_submit_form_errors_hook_( $submitted_data, $form_data ) { } } - if ( isset( $submitted_data['description'] ) ) { + $description_key = UM()->profile()->get_show_bio_key( $array ); + if ( isset( $submitted_data['description'] ) && $description_key === $array['metakey'] ) { $max_chars = UM()->options()->get( 'profile_bio_maxchars' ); $profile_show_bio = UM()->options()->get( 'profile_show_bio' ); - if ( ! UM()->options()->get( 'profile_show_html_bio' ) ) { - $description_value = $submitted_data['description']; + $description_key = UM()->profile()->get_show_bio_key( $array ); + + if ( array_key_exists( $description_key, $submitted_data['submitted'] ) ) { + + if ( array_key_exists( 'max_chars', $array ) && ! empty( $array['max_chars'] ) ) { + $max_chars = $array['max_chars']; + } + + if ( array_key_exists( 'html', $array ) && 1 === (int) $array['html'] && 1 === (int) UM()->options()->get( 'profile_show_html_bio' ) ) { + $description_value = wp_strip_all_tags( $submitted_data[ $description_key ] ); + } else { + $description_value = $submitted_data[ $description_key ]; + } } else { - $description_value = wp_strip_all_tags( $submitted_data['description'] ); + if ( ! UM()->options()->get( 'profile_show_html_bio' ) ) { + $description_value = $submitted_data['description']; + } else { + $description_value = wp_strip_all_tags( $submitted_data['description'] ); + } } if ( $profile_show_bio ) { + if ( mb_strlen( str_replace( array( "\r\n", "\n", "\r\t", "\t" ), ' ', $description_value ) ) > $max_chars && $max_chars ) { // translators: %s: max chars. UM()->form()->add_error( 'description', sprintf( __( 'Your user description must contain less than %s characters', 'ultimate-member' ), $max_chars ) ); @@ -954,22 +971,6 @@ function um_submit_form_errors_hook_( $submitted_data, $form_data ) { break; } - -// if ( isset( $submitted_data['description'] ) ) { -// echo '
';
-//			print_r($submitted_data);
-//			echo '
'; -// exit(); -// $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 ) { -// // translators: %s: 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, 2 ); From 60a71ec983f0205ce9d4baccd7322fad65a10c37 Mon Sep 17 00:00:00 2001 From: ashubawork Date: Mon, 31 Jul 2023 10:02:48 +0300 Subject: [PATCH 09/28] - small wpcs fix --- includes/core/um-actions-form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/core/um-actions-form.php b/includes/core/um-actions-form.php index 57b62730..32873e64 100644 --- a/includes/core/um-actions-form.php +++ b/includes/core/um-actions-form.php @@ -673,7 +673,7 @@ function um_submit_form_errors_hook_( $submitted_data, $form_data ) { } } - $description_key = UM()->profile()->get_show_bio_key( $array ); + $description_key = UM()->profile()->get_show_bio_key( $array ); if ( isset( $submitted_data['description'] ) && $description_key === $array['metakey'] ) { $max_chars = UM()->options()->get( 'profile_bio_maxchars' ); $profile_show_bio = UM()->options()->get( 'profile_show_bio' ); From c0a0fc475c94537ddeca4b50b2e3bf6d2e220ea7 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Thu, 3 Aug 2023 01:21:23 +0300 Subject: [PATCH 10/28] - added 'um_can_view_profile' hook; --- includes/um-short-functions.php | 71 ++++++++++++++++++++------------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/includes/um-short-functions.php b/includes/um-short-functions.php index 07f4b354..6c1e3538 100644 --- a/includes/um-short-functions.php +++ b/includes/um-short-functions.php @@ -1592,50 +1592,67 @@ function um_can_view_field( $data ) { return apply_filters( 'um_can_view_field', $can_view, $data ); } - /** * Checks if user can view profile * - * @param $user_id + * @param int $user_id * * @return bool */ function um_can_view_profile( $user_id ) { + $can_view = true; + $user_id = absint( $user_id ); if ( ! is_user_logged_in() ) { - return ! UM()->user()->is_private_profile( $user_id ); - } + $can_view = ! UM()->user()->is_private_profile( $user_id ); + } else { + $temp_id = um_user( 'ID' ); + um_fetch_user( get_current_user_id() ); - $temp_id = um_user('ID'); - um_fetch_user( get_current_user_id() ); + if ( get_current_user_id() !== $user_id ) { + if ( ! um_user( 'can_view_all' ) ) { + um_fetch_user( $temp_id ); + $can_view = false; + } elseif ( ! um_user( 'can_access_private_profile' ) && UM()->user()->is_private_profile( $user_id ) ) { + um_fetch_user( $temp_id ); + $can_view = false; + } elseif ( um_user( 'can_view_roles' ) ) { + $can_view_roles = um_user( 'can_view_roles' ); - if ( ! um_user( 'can_view_all' ) && $user_id != get_current_user_id() && is_user_logged_in() ) { - um_fetch_user( $temp_id ); - return false; - } + if ( ! is_array( $can_view_roles ) ) { + $can_view_roles = array(); + } - if ( ! um_user( 'can_access_private_profile' ) && UM()->user()->is_private_profile( $user_id ) ) { - um_fetch_user( $temp_id ); - return false; - } - - if ( um_user( 'can_view_roles' ) && $user_id != get_current_user_id() ) { - $can_view_roles = um_user( 'can_view_roles' ); - - if ( ! is_array( $can_view_roles ) ) { - $can_view_roles = array(); + if ( count( $can_view_roles ) && count( array_intersect( UM()->roles()->get_all_user_roles( $user_id ), $can_view_roles ) ) <= 0 ) { + um_fetch_user( $temp_id ); + $can_view = false; + } + } } - if ( count( $can_view_roles ) && count( array_intersect( UM()->roles()->get_all_user_roles( $user_id ), $can_view_roles ) ) <= 0 ) { - um_fetch_user( $temp_id ); - return false; - } + um_fetch_user( $temp_id ); } - um_fetch_user( $temp_id ); - return true; + /** + * Filters the marker for user capabilities to view other profile + * + * @param {bool} $can_view Can view profile marker. + * @param {int} $user_id User ID requested from profile page. + * + * @return {bool} Can view profile marker. + * + * @since 2.6.10 + * @hook um_can_view_profile + * + * @example Set that only user with ID=5 can be viewed on Profile page. + * function my_um_can_view_profile( $can_view, $user_id ) { + * $can_view = 5 === $user_id; + * return $can_view; + * } + * add_filter( 'um_can_view_profile', 'my_um_can_view_profile', 10, 2 ); + */ + return apply_filters( 'um_can_view_profile', $can_view, $user_id ); } - /** * boolean check for not same user * From 24e79c37af2a1c7d74a58662a189443a5cf632c9 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Wed, 9 Aug 2023 16:24:22 +0300 Subject: [PATCH 11/28] - wpcs; - hookdocs for `um_setup_predefined_page_content`, `um_core_pages`; --- includes/class-config.php | 46 ++++++++++++++++---------------- includes/core/class-setup.php | 49 +++++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/includes/class-config.php b/includes/class-config.php index d7ce85bb..5049a341 100644 --- a/includes/class-config.php +++ b/includes/class-config.php @@ -95,38 +95,36 @@ if ( ! class_exists( 'um\Config' ) ) { 'members', ); - /** - * UM hook + * Filters Ultimate Member predefined pages. * - * @type filter - * @title um_core_pages - * @description Extend UM core pages - * @input_vars - * [{"var":"$pages","type":"array","desc":"UM core pages"}] - * @change_log - * ["Since: 2.0"] - * @usage - * - * @example - * Extend UM core pages. * function my_core_pages( $pages ) { * // your code here * $pages['my_page_key'] = array( 'title' => __( 'My Page Title', 'my-translate-key' ) ); * return $pages; * } - * ?> + * add_filter( 'um_core_pages', 'my_core_pages' ); */ - $this->core_pages = apply_filters( 'um_core_pages', array( - 'user' => array( 'title' => __( 'User', 'ultimate-member' ) ), - 'login' => array( 'title' => __( 'Login', 'ultimate-member' ) ), - 'register' => array( 'title' => __( 'Register', 'ultimate-member' ) ), - 'members' => array( 'title' => __( 'Members', 'ultimate-member' ) ), - 'logout' => array( 'title' => __( 'Logout', 'ultimate-member' ) ), - 'account' => array( 'title' => __( 'Account', 'ultimate-member' ) ), - 'password-reset' => array( 'title' => __( 'Password Reset', 'ultimate-member' ) ), - ) ); + $this->core_pages = apply_filters( + 'um_core_pages', + array( + 'user' => array( 'title' => __( 'User', 'ultimate-member' ) ), + 'login' => array( 'title' => __( 'Login', 'ultimate-member' ) ), + 'register' => array( 'title' => __( 'Register', 'ultimate-member' ) ), + 'members' => array( 'title' => __( 'Members', 'ultimate-member' ) ), + 'logout' => array( 'title' => __( 'Logout', 'ultimate-member' ) ), + 'account' => array( 'title' => __( 'Account', 'ultimate-member' ) ), + 'password-reset' => array( 'title' => __( 'Password Reset', 'ultimate-member' ) ), + ) + ); $this->core_directory_meta['members'] = array( '_um_core' => 'members', diff --git a/includes/core/class-setup.php b/includes/core/class-setup.php index 3981cff6..a1eec114 100644 --- a/includes/core/class-setup.php +++ b/includes/core/class-setup.php @@ -177,12 +177,12 @@ KEY meta_value_indx (um_value(191)) /** * Install Pre-defined pages with shortcodes */ - function install_default_pages() { + public function install_default_pages() { if ( ! current_user_can( 'manage_options' ) ) { return; } - $core_forms = get_option( 'um_core_forms', array() ); + $core_forms = get_option( 'um_core_forms', array() ); $core_directories = get_option( 'um_core_directories', array() ); $setup_shortcodes = array_merge( $core_forms, $core_directories ); @@ -198,28 +198,49 @@ KEY meta_value_indx (um_value(191)) } //If page does not exist - create it - if ( $slug == 'logout' ) { + if ( 'logout' === $slug ) { $content = ''; - } elseif ( $slug == 'account' ) { + } elseif ( 'account' === $slug ) { $content = '[ultimatemember_account]'; - } elseif ( $slug == 'password-reset' ) { + } elseif ( 'password-reset' === $slug ) { $content = '[ultimatemember_password]'; - } elseif ( $slug == 'user' ) { + } elseif ( 'user' === $slug ) { $content = '[ultimatemember form_id="' . $setup_shortcodes['profile'] . '"]'; } else { $content = '[ultimatemember form_id="' . $setup_shortcodes[ $slug ] . '"]'; } + /** + * Filters Ultimate Member predefined pages content when set up the predefined page. + * + * @param {string} $content Predefined page content. + * @param {string} $slug Predefined page slug (key). + * + * @return {string} Predefined page content. + * + * @since 2.1.0 + * @hook um_setup_predefined_page_content + * + * @example Set Ultimate Member predefined pages content with key = 'my_page_key'. + * function my_um_setup_predefined_page_content( $content, $slug ) { + * // your code here + * if ( 'my_page_key' === $slug ) { + * $content = __( 'My Page content', 'my-translate-key' ); + * } + * return $pages; + * } + * add_filter( 'um_setup_predefined_page_content', 'my_um_setup_predefined_page_content' ); + */ $content = apply_filters( 'um_setup_predefined_page_content', $content, $slug ); $user_page = array( - 'post_title' => $array['title'], - 'post_content' => $content, - 'post_name' => $slug, - 'post_type' => 'page', - 'post_status' => 'publish', - 'post_author' => get_current_user_id(), - 'comment_status' => 'closed' + 'post_title' => $array['title'], + 'post_content' => $content, + 'post_name' => $slug, + 'post_type' => 'page', + 'post_status' => 'publish', + 'post_author' => get_current_user_id(), + 'comment_status' => 'closed', ); $post_id = wp_insert_post( $user_page ); @@ -231,7 +252,7 @@ KEY meta_value_indx (um_value(191)) $options = get_option( 'um_options', array() ); foreach ( $core_pages as $slug => $page_id ) { - $key = UM()->options()->get_core_page_id( $slug ); + $key = UM()->options()->get_core_page_id( $slug ); $options[ $key ] = $page_id; } From 05b6f412574854f78dc1d1a036392095358c4b4e Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Thu, 10 Aug 2023 16:14:31 +0300 Subject: [PATCH 12/28] - added hook to operate with core searching fields in member directory search; --- includes/core/class-member-directory.php | 34 +++++++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/includes/core/class-member-directory.php b/includes/core/class-member-directory.php index 032cc862..dc37cee8 100644 --- a/includes/core/class-member-directory.php +++ b/includes/core/class-member-directory.php @@ -95,12 +95,38 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { /** * Member_Directory constructor. */ - function __construct() { + public function __construct() { add_filter( 'init', array( &$this, 'init_variables' ) ); add_action( 'template_redirect', array( &$this, 'access_members' ), 555 ); } + /** + * Get the WordPress core searching fields in wp_users query. + * @return array + */ + private function get_core_search_fields() { + /** + * Filters the WordPress core searching fields in wp_users query for UM Member directory query. + * + * @param {array} $core_search_fields Core search fields in wp_users query. + * + * @return {array} Core search fields in wp_users query. + * + * @since 2.6.10 + * @hook um_member_directory_core_search_fields + * + * @example Extends or remove wp_users core search fields. + * function my_um_member_directory_core_search_fields( $core_search_fields ) { + * $core_search_fields = array_flip( $core_search_fields ); + * unset( $core_search_fields['user_email'] ); + * $core_search_fields = array_flip( $core_search_fields ); + * return $core_search_fields; + * } + * add_filter( 'um_member_directory_core_search_fields', 'my_um_member_directory_core_search_fields' ); + */ + return apply_filters( 'um_member_directory_core_search_fields', $this->core_search_fields ); + } /** * @return bool @@ -587,8 +613,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) { $filter_from_url = ! empty( $_GET[ 'filter_' . $filter . '_' . $unique_hash ] ) ? sanitize_text_field( $_GET[ 'filter_' . $filter . '_' . $unique_hash ] ) : $default_value; ?> + value="" class="um-form-field" + aria-label="" /> get_search_sql( $search, $this->core_search_fields, 'both' ); + $search_where = $context->get_search_sql( $search, $this->get_core_search_fields(), 'both' ); $search_where = preg_replace( '/ AND \((.*?)\)/im', "$1 OR", $search_where ); From c540ff56cd9aec7fb864b1763311a2516ad4d94e Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Fri, 11 Aug 2023 11:36:53 +0300 Subject: [PATCH 13/28] - fixed #1272; --- includes/admin/class-secure.php | 41 ++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/includes/admin/class-secure.php b/includes/admin/class-secure.php index 65f8ec79..5c35cb43 100644 --- a/includes/admin/class-secure.php +++ b/includes/admin/class-secure.php @@ -73,28 +73,20 @@ if ( ! class_exists( 'um\admin\Secure' ) ) { */ public function filter_users_by_date_registered( $query ) { global $pagenow; - if ( is_admin() && 'users.php' === $pagenow ) { + if ( 'users.php' === $pagenow && is_admin() ) { // phpcs:disable WordPress.Security.NonceVerification $date_from = isset( $_GET['um_secure_date_from'] ) ? $_GET['um_secure_date_from'] : null; $date_to = isset( $_GET['um_secure_date_to'] ) ? $_GET['um_secure_date_to'] : null; // phpcs:enable WordPress.Security.NonceVerification - if ( ! $date_to ) { - $query->set( - 'date_query', - array( - 'after' => human_time_diff( $date_from, strtotime( current_time( 'mysql' ) ) ) . ' ago', - 'inclusive' => true, - ) - ); - } elseif ( $date_from && $date_to ) { - $query->set( - 'date_query', - array( - 'after' => human_time_diff( $date_from, strtotime( current_time( 'mysql' ) ) ) . ' ago', - 'before' => human_time_diff( $date_to, strtotime( current_time( 'mysql' ) ) ) . ' ago', - 'inclusive' => true, - ) + if ( $date_from ) { + $date_query_attr = array( + 'after' => human_time_diff( $date_from, strtotime( current_time( 'mysql' ) ) ) . ' ago', + 'inclusive' => true, ); + if ( $date_to ) { + $date_query_attr['before'] = human_time_diff( $date_to, strtotime( current_time( 'mysql' ) ) ) . ' ago'; + } + $query->set( 'date_query', $date_query_attr ); } } @@ -123,13 +115,24 @@ if ( ! class_exists( 'um\admin\Secure' ) ) { /** * Destroy all user sessions except the current logged-in user. */ - $wpdb->query( $wpdb->prepare( 'DELETE FROM ' . $wpdb->usermeta . ' WHERE meta_key="session_tokens" AND user_id != %d', get_current_user_id() ) ); + $wpdb->query( + $wpdb->prepare( + "DELETE + FROM {$wpdb->usermeta} + WHERE meta_key='session_tokens' AND + user_id != %d", + get_current_user_id() + ) + ); if ( UM()->options()->get( 'display_login_form_notice' ) ) { global $wpdb; $wpdb->query( $wpdb->prepare( - "DELETE FROM {$wpdb->usermeta} WHERE user_id != %d AND ( meta_key = 'um_secure_has_reset_password' OR meta_key = 'um_secure_has_reset_password__timestamp' )", + "DELETE + FROM {$wpdb->usermeta} + WHERE user_id != %d AND + ( meta_key = 'um_secure_has_reset_password' OR meta_key = 'um_secure_has_reset_password__timestamp' )", get_current_user_id() ) ); From 1f3ebdcdd0bc89d28bed560b592f3141a1e6d6df Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Fri, 11 Aug 2023 11:57:43 +0300 Subject: [PATCH 14/28] - reviewed #1275; - fixed #1274; --- assets/js/um-modal.js | 56 +++++++++++----------- includes/admin/assets/js/um-admin-modal.js | 2 +- includes/um-short-functions.php | 17 +------ 3 files changed, 31 insertions(+), 44 deletions(-) diff --git a/assets/js/um-modal.js b/assets/js/um-modal.js index 01e6fb4b..5708f467 100644 --- a/assets/js/um-modal.js +++ b/assets/js/um-modal.js @@ -1,10 +1,10 @@ jQuery(document).ready(function() { - + jQuery(document).on('click', '.um-popup-overlay', function(){ remove_Modal(); }); - + jQuery(document).on('click', '.um-modal-overlay, a[data-action="um_remove_modal"]', function(){ um_remove_modal(); }); @@ -13,7 +13,7 @@ jQuery(document).ready(function() { e.preventDefault(); return false; }); - + jQuery(document).on('click', '.um-modal .um-single-file-preview a.cancel', function(e){ e.preventDefault(); @@ -37,10 +37,10 @@ jQuery(document).ready(function() { um_modal_responsive(); } }); - + return false; }); - + jQuery(document).on('click', '.um-modal .um-single-image-preview a.cancel', function(e){ e.preventDefault(); @@ -67,30 +67,30 @@ jQuery(document).ready(function() { um_modal_responsive(); } }); - + return false; }); - + jQuery(document).on('click', '.um-finish-upload.file:not(.disabled)', function(){ - + var key = jQuery(this).attr('data-key'); - + var preview = jQuery(this).parents('.um-modal-body').find('.um-single-file-preview').html(); - + um_remove_modal(); - + jQuery('.um-single-file-preview[data-key='+key+']').fadeIn().html( preview ); var file = jQuery('.um-field[data-key='+key+']').find('.um-single-fileinfo a').data('file'); - + jQuery('.um-single-file-preview[data-key='+key+']').parents('.um-field').find('.um-btn-auto-width').html( jQuery(this).attr('data-change') ); - + jQuery('.um-single-file-preview[data-key='+key+']').parents('.um-field').find('input[type="hidden"]').val( file ); - + }); jQuery(document).on('click', '.um-finish-upload.image:not(.disabled)', function(){ - + var elem = jQuery(this); var key = jQuery(this).attr('data-key'); var img_c = jQuery(this).parents('.um-modal-body').find('.um-single-image-preview'); @@ -112,7 +112,7 @@ jQuery(document).ready(function() { } if ( coord ) { - + jQuery(this).html( jQuery(this).attr('data-processing') ).addClass('disabled'); jQuery.ajax({ @@ -157,23 +157,23 @@ jQuery(document).ready(function() { } }); - + } else { d = new Date(); jQuery('.um-single-image-preview[data-key='+key+']').fadeIn().find('img').attr('src', src + "?"+d.getTime()); - + um_remove_modal(); - + jQuery('.um-single-image-preview[data-key='+key+']').parents('.um-field').find('.um-btn-auto-width').html( elem.attr('data-change') ); - + jQuery('.um-single-image-preview[data-key='+key+']').parents('.um-field').find('input[type=hidden]').val( file ); - + } }); - + jQuery(document.body).on('click', 'a[data-modal^="um_"], span[data-modal^="um_"]', function(e){ var modal_id = jQuery(this).attr('data-modal'); @@ -183,19 +183,19 @@ jQuery(document).ready(function() { if ( jQuery(this).data('modal-size') ) { size = jQuery(this).data('modal-size'); } - + if ( jQuery(this).data('modal-copy') ) { - + jQuery('#' + modal_id).html( jQuery(this).parents('.um-field').find('.um-modal-hidden-content').html() ); - + if ( jQuery(this).parents('.um-profile-photo').attr('data-user_id') ) { jQuery('#' + modal_id).attr('data-user_id', jQuery(this).parents('.um-profile-photo').attr('data-user_id') ); } - + if ( jQuery(this).parents('.um-cover').attr('data-ratio') ) { jQuery('#' + modal_id).attr('data-ratio', jQuery(this).parents('.um-cover').attr('data-ratio') ); } - + if ( jQuery(this).parents('.um-cover').attr('data-user_id') ) { jQuery('#' + modal_id).attr('data-user_id', jQuery(this).parents('.um-cover').attr('data-user_id') ); } @@ -209,4 +209,4 @@ jQuery(document).ready(function() { um_new_modal( modal_id, size ); }); -}); \ No newline at end of file +}); diff --git a/includes/admin/assets/js/um-admin-modal.js b/includes/admin/assets/js/um-admin-modal.js index ead883f7..7b1717b0 100644 --- a/includes/admin/assets/js/um-admin-modal.js +++ b/includes/admin/assets/js/um-admin-modal.js @@ -234,7 +234,7 @@ jQuery(document).ready(function() { /** disable link **/ - jQuery(document.body).on('click', '.um-admin-builder a, .um-admin-modal a', function(e){ + jQuery(document.body).on('click', '.um-admin-builder a, .um-admin-modal a:not(.um-preview-upload)', function(e){ e.preventDefault(); return false; }); diff --git a/includes/um-short-functions.php b/includes/um-short-functions.php index 6c1e3538..5aac9dd3 100644 --- a/includes/um-short-functions.php +++ b/includes/um-short-functions.php @@ -709,7 +709,7 @@ function um_user_submitted_registration_formatted( $style = false ) { UM()->fields()->get_fields = $fields; foreach ( $fields as $key => $array ) { - if ( isset( $array['type'] ) && $array['type'] == 'row' ) { + if ( isset( $array['type'] ) && 'row' === $array['type'] ) { $rows[ $key ] = $array; unset( UM()->fields()->get_fields[ $key ] ); // not needed now } @@ -747,7 +747,6 @@ function um_user_submitted_registration_formatted( $style = false ) { $cols_num = $col_split[ $c ]; // sub row fields - $subrow_fields = null; $subrow_fields = UM()->fields()->get_fields_in_subrow( $row_fields, $c ); if ( is_array( $subrow_fields ) ) { @@ -766,7 +765,6 @@ function um_user_submitted_registration_formatted( $style = false ) { $output .= um_user_submited_display( $key, $data['title'] ); } } - } elseif ( $cols_num == 2 ) { $col1_fields = UM()->fields()->get_fields_in_column( $subrow_fields, 1 ); @@ -782,7 +780,6 @@ function um_user_submitted_registration_formatted( $style = false ) { $output .= um_user_submited_display( $key, $data['title'] ); } } - } else { $col1_fields = UM()->fields()->get_fields_in_column( $subrow_fields, 1 ); @@ -805,29 +802,19 @@ function um_user_submitted_registration_formatted( $style = false ) { $output .= um_user_submited_display( $key, $data['title'] ); } } - } - } - } - } - - } // endfor - } } - if ( $style ) { $output .= '
'; } - return $output; - } /** @@ -882,7 +869,7 @@ function um_user_submited_display( $k, $title, $data = array(), $style = true ) } if ( ! empty( $filedata['original_name'] ) ) { - $v = '' . esc_html( $filedata['original_name'] ) . ''; + $v = '' . esc_html( $filedata['original_name'] ) . ''; } else { $v = $baseurl . um_user( 'ID' ) . '/' . $file; } From bfef1f9dc70f45a495a0edcc63e41799ba6da21c Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Tue, 15 Aug 2023 03:49:13 +0300 Subject: [PATCH 15/28] - reviewed #1269; - unified `UM()->fields()->editing` and `UM()->fields()->viewing` to bool variables use true|false in conditions to make `===` or `!==` comparing; --- assets/js/um-profile.js | 40 ++------ assets/js/um-profile.min.js | 2 +- includes/core/class-account.php | 4 +- includes/core/class-fields.php | 69 ++++++++----- includes/core/class-password.php | 4 +- includes/core/class-profile.php | 23 +++-- includes/core/class-shortcodes.php | 4 +- includes/core/um-actions-form.php | 83 ++++++++++------ includes/core/um-actions-profile.php | 142 +++++++++++++++------------ includes/core/um-filters-fields.php | 10 +- includes/um-short-functions.php | 2 +- 11 files changed, 222 insertions(+), 161 deletions(-) diff --git a/assets/js/um-profile.js b/assets/js/um-profile.js index 8f0f3381..5a95598d 100644 --- a/assets/js/um-profile.js +++ b/assets/js/um-profile.js @@ -88,41 +88,22 @@ jQuery(document).ready(function() { return false; }); - /*function um_update_bio_countdown() { - // - jQuery(this) - if ( typeof jQuery('textarea[id="um-meta-bio"]').val() !== 'undefined' ){ - var um_bio_limit = jQuery('textarea[id="um-meta-bio"]').attr( "data-character-limit" ); - var remaining = um_bio_limit - jQuery('textarea[id="um-meta-bio"]').val().length; - jQuery('span.um-meta-bio-character span.um-bio-limit').text( remaining ); - if ( remaining < 5 ) { - jQuery('span.um-meta-bio-character').css('color','red'); - } else { - jQuery('span.um-meta-bio-character').css('color',''); - } - } - }*/ - - //um_update_bio_countdown(); - //jQuery( 'textarea[id="um-meta-bio"]' ).on('change', um_update_bio_countdown ).keyup( um_update_bio_countdown ).trigger('change'); - // Bio characters limit jQuery( document.body ).on( 'change keyup', '#um-meta-bio', function() { if ( typeof jQuery(this).val() !== 'undefined' ) { - var um_bio_limit = jQuery(this).data( 'character-limit' ); - var bio_html = jQuery(this).attr('data-html'); - if ( parseInt( bio_html ) === 1 ){ - var remaining = um_bio_limit - jQuery(this).val().replace(/(<([^>]+)>)/ig,'').length; - } else { - var remaining = um_bio_limit - jQuery(this).val().length; + let um_bio_limit = jQuery(this).data( 'character-limit' ); + let bio_html = jQuery(this).data( 'html' ); + + let remaining = um_bio_limit - jQuery(this).val().length; + if ( parseInt( bio_html ) === 1 ) { + remaining = um_bio_limit - jQuery(this).val().replace(/(<([^>]+)>)/ig,'').length; } + remaining = remaining < 0 ? 0 : remaining; + jQuery( 'span.um-meta-bio-character span.um-bio-limit' ).text( remaining ); - if ( remaining < 5 ) { - jQuery('span.um-meta-bio-character').css('color','red'); - } else { - jQuery('span.um-meta-bio-character').css('color',''); - } + let color = remaining < 5 ? 'red' : ''; + jQuery('span.um-meta-bio-character').css( 'color', color ); } }); jQuery( '#um-meta-bio' ).trigger('change'); @@ -158,5 +139,4 @@ jQuery(document).ready(function() { jQuery( '.um-profile-nav a' ).on( 'touchend', function(e) { jQuery( e.currentTarget).trigger( "click" ); }); - }); diff --git a/assets/js/um-profile.min.js b/assets/js/um-profile.min.js index f965ed66..557d45b8 100644 --- a/assets/js/um-profile.min.js +++ b/assets/js/um-profile.min.js @@ -1 +1 @@ -jQuery(document).ready(function(){jQuery(".um-profile.um-viewing .um-profile-body .um-row").each(function(){var e=jQuery(this);0==e.find(".um-field").length&&(e.prev(".um-row-heading").remove(),e.remove())}),jQuery(".um-profile.um-viewing .um-profile-body").length&&0==jQuery(".um-profile.um-viewing .um-profile-body").find(".um-field").length&&(jQuery(".um-profile.um-viewing .um-profile-body").find(".um-row-heading,.um-row").remove(),jQuery(".um-profile-note").show()),jQuery(document.body).on("click",".um-profile-save",function(e){return e.preventDefault(),jQuery(this).parents(".um").find("form").trigger("submit"),!1}),jQuery(document.body).on("click",".um-profile-edit-a",function(e){jQuery(this).addClass("active")}),jQuery(document.body).on("click",".um-cover a.um-cover-add, .um-photo a",function(e){e.preventDefault()}),jQuery(document.body).on("click",".um-photo-modal",function(e){e.preventDefault();e=jQuery(this).attr("data-src");return um_new_modal("um_view_photo","fit",!0,e),!1}),jQuery(document.body).on("click",".um-reset-profile-photo",function(e){return jQuery(".um-profile-photo-img img").attr("src",jQuery(this).attr("data-default_src")),user_id=jQuery(this).attr("data-user_id"),metakey="profile_photo",UM.dropdown.hideAll(),jQuery.ajax({url:wp.ajax.settings.url,type:"post",data:{action:"um_delete_profile_photo",metakey:metakey,user_id:user_id,nonce:um_scripts.nonce}}),jQuery(this).parents("li").hide(),!1}),jQuery(document.body).on("click",".um-reset-cover-photo",function(e){var r=jQuery(this);return jQuery(".um-cover-overlay").hide(),jQuery(".um-cover-e").html(''),um_responsive(),user_id=jQuery(this).attr("data-user_id"),metakey="cover_photo",jQuery.ajax({url:wp.ajax.settings.url,type:"post",data:{action:"um_delete_cover_photo",metakey:metakey,user_id:user_id,nonce:um_scripts.nonce},success:function(e){r.hide()}}),UM.dropdown.hideAll(),!1}),jQuery(document.body).on("change keyup","#um-meta-bio",function(){var e;void 0!==jQuery(this).val()&&(e=jQuery(this).data("character-limit")-jQuery(this).val().length,jQuery("span.um-meta-bio-character span.um-bio-limit").text(e),e<5?jQuery("span.um-meta-bio-character").css("color","red"):jQuery("span.um-meta-bio-character").css("color",""))}),jQuery("#um-meta-bio").trigger("change"),jQuery(".um-profile form").each(function(){let r=jQuery(this).data("description_key");jQuery(this).find('textarea[name="'+r+'"]').length&&jQuery(document.body).on("change input",'textarea[name="'+r+'"]',function(e){jQuery(this).parents("form").find('textarea[name="'+r+'"]').each(function(){jQuery(this).val(e.currentTarget.value),jQuery("#um-meta-bio")[0]!==e.currentTarget&&jQuery("#um-meta-bio")[0]===jQuery(this)[0]&&jQuery(this).trigger("change")})})}),jQuery(".um-profile-edit a.um_delete-item").on("click",function(e){if(e.preventDefault(),!confirm(wp.i18n.__("Are you sure that you want to delete this user?","ultimate-member")))return!1}),jQuery(".um-profile-nav a").on("touchend",function(e){jQuery(e.currentTarget).trigger("click")})}); \ No newline at end of file +jQuery(document).ready(function(){jQuery(".um-profile.um-viewing .um-profile-body .um-row").each(function(){var e=jQuery(this);0==e.find(".um-field").length&&(e.prev(".um-row-heading").remove(),e.remove())}),jQuery(".um-profile.um-viewing .um-profile-body").length&&0==jQuery(".um-profile.um-viewing .um-profile-body").find(".um-field").length&&(jQuery(".um-profile.um-viewing .um-profile-body").find(".um-row-heading,.um-row").remove(),jQuery(".um-profile-note").show()),jQuery(document.body).on("click",".um-profile-save",function(e){return e.preventDefault(),jQuery(this).parents(".um").find("form").trigger("submit"),!1}),jQuery(document.body).on("click",".um-profile-edit-a",function(e){jQuery(this).addClass("active")}),jQuery(document.body).on("click",".um-cover a.um-cover-add, .um-photo a",function(e){e.preventDefault()}),jQuery(document.body).on("click",".um-photo-modal",function(e){e.preventDefault();e=jQuery(this).attr("data-src");return um_new_modal("um_view_photo","fit",!0,e),!1}),jQuery(document.body).on("click",".um-reset-profile-photo",function(e){return jQuery(".um-profile-photo-img img").attr("src",jQuery(this).attr("data-default_src")),user_id=jQuery(this).attr("data-user_id"),metakey="profile_photo",UM.dropdown.hideAll(),jQuery.ajax({url:wp.ajax.settings.url,type:"post",data:{action:"um_delete_profile_photo",metakey:metakey,user_id:user_id,nonce:um_scripts.nonce}}),jQuery(this).parents("li").hide(),!1}),jQuery(document.body).on("click",".um-reset-cover-photo",function(e){var t=jQuery(this);return jQuery(".um-cover-overlay").hide(),jQuery(".um-cover-e").html(''),um_responsive(),user_id=jQuery(this).attr("data-user_id"),metakey="cover_photo",jQuery.ajax({url:wp.ajax.settings.url,type:"post",data:{action:"um_delete_cover_photo",metakey:metakey,user_id:user_id,nonce:um_scripts.nonce},success:function(e){t.hide()}}),UM.dropdown.hideAll(),!1}),jQuery(document.body).on("change keyup","#um-meta-bio",function(){if(void 0!==jQuery(this).val()){var t=jQuery(this).data("character-limit"),r=jQuery(this).data("html");let e=t-jQuery(this).val().length;e=(e=1===parseInt(r)?t-jQuery(this).val().replace(/(<([^>]+)>)/gi,"").length:e)<0?0:e,jQuery("span.um-meta-bio-character span.um-bio-limit").text(e);r=e<5?"red":"";jQuery("span.um-meta-bio-character").css("color",r)}}),jQuery("#um-meta-bio").trigger("change"),jQuery(".um-profile form").each(function(){let t=jQuery(this).data("description_key");jQuery(this).find('textarea[name="'+t+'"]').length&&jQuery(document.body).on("change input",'textarea[name="'+t+'"]',function(e){jQuery(this).parents("form").find('textarea[name="'+t+'"]').each(function(){jQuery(this).val(e.currentTarget.value),jQuery("#um-meta-bio")[0]!==e.currentTarget&&jQuery("#um-meta-bio")[0]===jQuery(this)[0]&&jQuery(this).trigger("change")})})}),jQuery(".um-profile-edit a.um_delete-item").on("click",function(e){if(e.preventDefault(),!confirm(wp.i18n.__("Are you sure that you want to delete this user?","ultimate-member")))return!1}),jQuery(".um-profile-nav a").on("touchend",function(e){jQuery(e.currentTarget).trigger("click")})}); \ No newline at end of file diff --git a/includes/core/class-account.php b/includes/core/class-account.php index 1b016584..6668d2ba 100644 --- a/includes/core/class-account.php +++ b/includes/core/class-account.php @@ -908,11 +908,11 @@ if ( ! class_exists( 'um\core\Account' ) ) { $classes .= ' um-in-admin'; } - if ( UM()->fields()->editing == true ) { + if ( true === UM()->fields()->editing ) { $classes .= ' um-editing'; } - if ( UM()->fields()->viewing == true ) { + if ( true === UM()->fields()->viewing ) { $classes .= ' um-viewing'; } diff --git a/includes/core/class-fields.php b/includes/core/class-fields.php index 71f3384e..c4f61134 100644 --- a/includes/core/class-fields.php +++ b/includes/core/class-fields.php @@ -625,11 +625,11 @@ if ( ! class_exists( 'um\core\Fields' ) ) { $output = null; $output .= '
'; - if ( isset( $data['icon'] ) && $data['icon'] != '' && isset( $this->field_icons ) && $this->field_icons != 'off' && ( $this->field_icons == 'label' || $this->viewing == true ) ) { + if ( isset( $data['icon'] ) && $data['icon'] != '' && isset( $this->field_icons ) && $this->field_icons != 'off' && ( $this->field_icons == 'label' || true === $this->viewing ) ) { $output .= '
'; } - if ( $this->viewing == true ) { + if ( true === $this->viewing ) { /** * UM hook * @@ -705,7 +705,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { $output .= '' . __( $label, 'ultimate-member' ) . ''; - if ( ! empty( $data['help'] ) && $this->viewing == false && ! strstr( $key, 'confirm_user_pass' ) ) { + if ( ! empty( $data['help'] ) && false === $this->viewing && ! strstr( $key, 'confirm_user_pass' ) ) { if ( ! UM()->mobile()->isMobile() ) { if ( false === $this->disable_tooltips ) { $output .= ''; @@ -836,7 +836,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { return stripslashes_deep( UM()->form()->post_form[ $key ] ); - } elseif ( um_user( $key ) && $this->editing == true ) { + } elseif ( um_user( $key ) && true === $this->editing ) { //show empty value for password fields if ( strstr( $key, 'user_pass' ) || $type == 'password' ) { @@ -889,7 +889,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { */ $value = apply_filters( "um_edit_{$type}_field_value", $value, $key ); - } elseif ( ( um_user( $key ) || isset( $data['show_anyway'] ) ) && $this->viewing == true ) { + } elseif ( ( um_user( $key ) || isset( $data['show_anyway'] ) ) && true === $this->viewing ) { return um_filtered_value( $key, $data ); @@ -993,7 +993,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { } // Default Value for Registration Form and Profile Form editing - if ( ! isset( $value ) && ( $this->set_mode == 'register' || $this->editing == true ) ) { + if ( ! isset( $value ) && ( $this->set_mode == 'register' || true === $this->editing ) ) { /** * UM hook @@ -1173,7 +1173,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { */ $data = apply_filters( 'um_is_selected_filter_data', $data, $key, $field_value ); - if ( ! $this->editing || 'custom' == $this->set_mode ) { + if ( false === $this->editing || 'custom' === $this->set_mode ) { // show default on register screen if there is default if ( isset( $data['default'] ) ) { @@ -1258,7 +1258,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { } } else { - if ( $this->editing && 'custom' !== $this->set_mode ) { + if ( true === $this->editing && 'custom' !== $this->set_mode ) { if ( um_user( $key ) ) { $um_user_value = um_user( $key ); @@ -1611,7 +1611,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { $array['default'] = null; } - if ( isset( $array['conditions'] ) && is_array( $array['conditions'] ) && ! $this->viewing ) { + if ( isset( $array['conditions'] ) && is_array( $array['conditions'] ) && false === $this->viewing ) { $array['conditional'] = ''; foreach ( $array['conditions'] as $cond_id => $cond ) { @@ -2178,7 +2178,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) { } } - if ( ! empty( $this->editing ) && 'profile' === $this->set_mode ) { + if ( true === $this->editing && 'profile' === $this->set_mode ) { if ( ! UM()->roles()->um_user_can( 'can_edit_everyone' ) ) { if ( empty( $data['editable'] ) ) { $disabled = ' disabled="disabled" '; @@ -2716,10 +2716,11 @@ if ( ! class_exists( 'um\core\Fields' ) ) { $field_name = $key; $field_value = $this->field_value( $key, $default, $data ); + $bio_key = UM()->profile()->get_show_bio_key( $this->global_args ); + $output .= '
'; - if ( isset( $data['html'] ) && 0 !== $data['html'] && 'description' !== $key ) { - + if ( ! empty( $data['html'] ) && $bio_key !== $key ) { $textarea_settings = array( 'media_buttons' => false, 'wpautop' => false, @@ -2761,24 +2762,29 @@ if ( ! class_exists( 'um\core\Fields' ) ) { // echo the editor to the buffer wp_editor( $field_value, $key, $textarea_settings ); - // add the contents of the buffer to the output variable + // Add the contents of the buffer to the output variable. $output .= ob_get_clean(); $output .= '
' . esc_html( $placeholder ) . ''; } else { + // User 'description' field uses ` - - - + if ( $show_bio ) { + $description_key = UM()->profile()->get_show_bio_key( $args ); - fields()->is_error( $description_key ) ) { - echo UM()->fields()->field_error( UM()->fields()->show_error( $description_key ), true ); - } ?> + if ( true === UM()->fields()->viewing && um_user( $description_key ) ) { + ?> +
+ + if ( $bio_html ) { + echo wp_kses_post( nl2br( make_clickable( wpautop( $description ) ) ) ); + } else { + echo nl2br( esc_html( $description ) ); + } + ?> +
+ fields()->editing ) { + if ( ! empty( $args['custom_fields'][ $description_key ] ) ) { + if ( ! empty( $args['custom_fields'][ $description_key ]['html'] ) && $bio_html ) { + $description_value = UM()->fields()->field_value( $description_key ); + } else { + $description_value = wp_strip_all_tags( UM()->fields()->field_value( $description_key ) ); + } + } else { + if ( $bio_html ) { + $description_value = UM()->fields()->field_value( $description_key ); + } else { + $description_value = wp_strip_all_tags( UM()->fields()->field_value( $description_key ) ); + } + } - + if ( ! empty( $args['custom_fields'][ $description_key ]['max_chars'] ) ) { + $limit = $args['custom_fields'][ $description_key ]['max_chars']; + } else { + $limit = UM()->options()->get( 'profile_bio_maxchars' ); + } + ?> + +
+ + + + + fields()->is_error( $description_key ) ) { + echo UM()->fields()->field_error( UM()->fields()->show_error( $description_key ), true ); + } + ?> +
+
@@ -1306,8 +1326,8 @@ function um_profile_header( $args ) { * } * ?> */ - do_action( 'um_after_header_meta', um_user( 'ID' ), $args ); ?> - + do_action( 'um_after_header_meta', um_user( 'ID' ), $args ); + ?>
@@ -1354,7 +1374,7 @@ function um_pre_profile_shortcode( $args ) { return; } - if ( UM()->fields()->editing ) { + if ( true === UM()->fields()->editing ) { if ( um_get_requested_user() ) { if ( ! UM()->roles()->um_current_user_can( 'edit', um_get_requested_user() ) ) { um_redirect_home( um_get_requested_user(), um_is_myprofile() ); @@ -1362,7 +1382,7 @@ function um_pre_profile_shortcode( $args ) { um_fetch_user( um_get_requested_user() ); } } else { - UM()->fields()->viewing = 1; + UM()->fields()->viewing = true; if ( um_get_requested_user() ) { if ( ! um_is_myprofile() && ! um_can_view_profile( um_get_requested_user() ) ) { @@ -1400,7 +1420,7 @@ function um_add_edit_icon( $args ) { // do not proceed if user cannot edit - if ( UM()->fields()->editing == true ) { ?> + if ( true === UM()->fields()->editing ) { ?>
@@ -1501,7 +1521,7 @@ add_action( 'um_pre_header_editprofile', 'um_add_edit_icon' ); * @param $args */ function um_add_profile_fields( $args ) { - if ( UM()->fields()->editing == true ) { + if ( true === UM()->fields()->editing ) { echo UM()->fields()->display( 'profile', $args ); @@ -1569,7 +1589,7 @@ function um_add_submit_button_to_profile( $args ) { } // only when editing - if ( UM()->fields()->editing == false ) { + if ( false === UM()->fields()->editing ) { return; } diff --git a/includes/core/um-filters-fields.php b/includes/core/um-filters-fields.php index 32ce1b96..b4b7e41d 100644 --- a/includes/core/um-filters-fields.php +++ b/includes/core/um-filters-fields.php @@ -248,16 +248,18 @@ function um_profile_field_filter_hook__textarea( $value, $data ) { if ( ! $value ) { return ''; } - if ( isset( $data['html'] ) && $data['html'] == 1 ) { + if ( ! empty( $data['html'] ) ) { return $value; } + $description_key = UM()->profile()->get_show_bio_key( UM()->fields()->global_args ); + $value = wp_kses( $value, 'strip' ); $value = html_entity_decode( $value ); - $value = preg_replace('$(https?://[a-z0-9_./?=&#-]+)(?![^<>]*>)$i', ' $1 ', $value." "); - $value = preg_replace('$(www\.[a-z0-9_./?=&#-]+)(?![^<>]*>)$i', '$1 ', $value." "); + $value = preg_replace( '$(https?://[a-z0-9_./?=&#-]+)(?![^<>]*>)$i', ' $1 ', $value . ' ' ); + $value = preg_replace( '$(www\.[a-z0-9_./?=&#-]+)(?![^<>]*>)$i', '$1 ', $value . ' ' ); - if ( ! ( isset( $data['metakey'] ) && 'description' === $data['metakey'] ) ) { + if ( ! ( isset( $data['metakey'] ) && $description_key === $data['metakey'] ) ) { $value = wpautop( $value ); } diff --git a/includes/um-short-functions.php b/includes/um-short-functions.php index 5aac9dd3..7f82e9ff 100644 --- a/includes/um-short-functions.php +++ b/includes/um-short-functions.php @@ -1662,7 +1662,7 @@ function um_is_user_himself() { function um_can_edit_field( $data ) { $can_edit = true; - if ( ! empty( UM()->fields()->editing ) && isset( UM()->fields()->set_mode ) && UM()->fields()->set_mode == 'profile' ) { + if ( true === UM()->fields()->editing && isset( UM()->fields()->set_mode ) && UM()->fields()->set_mode == 'profile' ) { if ( ! is_user_logged_in() ) { $can_edit = false; } else { From 427437ff6902a53277b9061461896e6174f58743 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Tue, 15 Aug 2023 04:07:26 +0300 Subject: [PATCH 16/28] - fixed #1277 --- includes/core/class-fields.php | 45 ++++++++++++++++------------------ 1 file changed, 21 insertions(+), 24 deletions(-) diff --git a/includes/core/class-fields.php b/includes/core/class-fields.php index c4f61134..e730a65c 100644 --- a/includes/core/class-fields.php +++ b/includes/core/class-fields.php @@ -1544,38 +1544,35 @@ if ( ! class_exists( 'um\core\Fields' ) ) { return __( 'Custom Field', 'ultimate-member' ); } - /** * Get form fields * * @return array */ - function get_fields() { - /** - * UM hook - * - * @type filter - * @title um_get_form_fields - * @description Extend form fields - * @input_vars - * [{"var":"$fields","type":"array","desc":"Selected filter value"}] - * @change_log - * ["Since: 2.0"] - * @usage add_filter( 'um_get_form_fields', 'function_name', 10, 1 ); - * @example - * - */ - $this->fields = apply_filters( 'um_get_form_fields', array() ); + public function get_fields() { + if ( empty( $this->fields ) ) { + /** + * Filters the form fields. + * + * @param {array} $fields Form fields. + * + * @return {array} Form fields. + * + * @since 1.3.x + * @hook um_get_form_fields + * + * @example Extend form fields. + * function my_form_fields( $fields ) { + * // your code here + * return $fields; + * } + * add_filter( 'um_get_form_fields', 'my_form_fields' ); + */ + $this->fields = apply_filters( 'um_get_form_fields', $this->fields ); + } return $this->fields; } - /** * Get specific field * From c70d67a82916209791146d436ea3439b96e6bf3c Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Tue, 15 Aug 2023 04:22:50 +0300 Subject: [PATCH 17/28] - fixed #1273 --- includes/core/um-actions-register.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/includes/core/um-actions-register.php b/includes/core/um-actions-register.php index d8617175..a0aaa51a 100644 --- a/includes/core/um-actions-register.php +++ b/includes/core/um-actions-register.php @@ -494,6 +494,14 @@ function um_submit_form_register( $args, $form_data ) { $user_id = wp_insert_user( $userdata ); if ( is_wp_error( $user_id ) ) { + // Default WordPress validation if there aren't any Ultimate Member native for the registration fields. + if ( 'existing_user_login' === $user_id->get_error_code() ) { + UM()->form()->add_error( 'user_login', $user_id->get_error_message() ); + } elseif ( 'existing_user_email' === $user_id->get_error_code() ) { + UM()->form()->add_error( 'user_email', $user_id->get_error_message() ); + } else { + UM()->form()->add_error( 'user_login', $user_id->get_error_message() ); + } return; } From 092092e3a5c4c7b6fad61c2b40d4e855e2390fd7 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Tue, 15 Aug 2023 04:59:51 +0300 Subject: [PATCH 18/28] - updated version; --- README.md | 2 +- readme.txt | 23 ++++++++++++++++++++--- ultimate-member.php | 2 +- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 1c66fd5b..8aa62665 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ GNU Version 2 or Any Later Version ### IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSION 2.6.7 PATCHES SECURITY PRIVILEGE ESCALATION VULNERABILITY. PLEASE SEE [THIS ARTICLE](https://docs.ultimatemember.com/article/1866-security-incident-update-and-recommended-actions) FOR MORE INFORMATION -[Official Release Version: 2.6.9](https://github.com/ultimatemember/ultimatemember/releases/tag/2.6.9). +[Official Release Version: 2.6.10](https://github.com/ultimatemember/ultimatemember/releases/tag/2.6.10). ## Changelog diff --git a/readme.txt b/readme.txt index 1cac921f..abd4f6ef 100644 --- a/readme.txt +++ b/readme.txt @@ -6,8 +6,8 @@ Donate link: Tags: community, member, membership, user-profile, user-registration Requires PHP: 5.6 Requires at least: 5.5 -Tested up to: 6.2 -Stable tag: 2.6.9 +Tested up to: 6.3 +Stable tag: 2.6.10 License: GNU Version 2 or Any Later Version License URI: http://www.gnu.org/licenses/gpl-3.0.txt @@ -166,9 +166,26 @@ No specific extensions are needed. But we highly recommended keep active these P IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSION 2.6.7 PATCHES SECURITY PRIVILEGE ESCALATION VULNERABILITY. PLEASE SEE [THIS ARTICLE](https://docs.ultimatemember.com/article/1866-security-incident-update-and-recommended-actions) FOR MORE INFORMATION -= 2.6.10: August xx, 2023 = += 2.6.10: August 16, 2023 = +* Enhancements: + - Added: 'um_can_view_profile' hook to operate with profile privacy + - Added: 'um_member_directory_core_search_fields' hook to operate with core searching fields in member directory search + - Tweak: Standardize the condition for checking not editable fields to `empty( $data['editable'] )` + - Tweak: Unified `UM()->fields()->editing` and `UM()->fields()->viewing` to bool variables use true|false in conditions to make `===` or `!==` comparing + - Updated: [Hooks Documentation v2](https://ultimatemember.github.io/ultimatemember/hooks/) + +* Bugfixes: + + - Fixed: Restriction settings handler when there isn't a WP_Post in query. PHP notices in some cases when WP query is not canonical + - Fixed: User description (Biography) field conflict with validation (max chars) in both cases when HTML can be used or not. Case when there are 2 biography fields are displayed on the profile (header + form field) + - Fixed: Displaying WordPress native registration errors when unique username|email validation is disabled + - Fixed: Make links clickable in the Registration Details + - Fixed: WP_Users_Query on wp-admin > Users screen + - Fixed: Performance for `um_get_form_fields` hook + +* Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade = 2.6.9: July 26, 2023 = diff --git a/ultimate-member.php b/ultimate-member.php index b9ba49ad..e93c957c 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.10-alpha + * Version: 2.6.10 * Author: Ultimate Member * Author URI: http://ultimatemember.com/ * Text Domain: ultimate-member From 89ec90dd777a139e7d97a4f662faf0530e6a2567 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Tue, 15 Aug 2023 15:56:41 +0300 Subject: [PATCH 19/28] - fixed max chars validation for user description field in header; --- includes/core/um-actions-form.php | 48 +++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/includes/core/um-actions-form.php b/includes/core/um-actions-form.php index bc220796..9ed569e3 100644 --- a/includes/core/um-actions-form.php +++ b/includes/core/um-actions-form.php @@ -997,6 +997,54 @@ function um_submit_form_errors_hook_( $submitted_data, $form_data ) { } } // end if ( isset in args array ) + + // Description in header + if ( isset( $form_data['mode'] ) && 'profile' === $form_data['mode'] ) { + $description_key = UM()->profile()->get_show_bio_key( $form_data ); + if ( ! UM()->form()->has_error( $description_key ) ) { + if ( ! empty( $submitted_data[ $description_key ] ) ) { + $field_exists = false; + if ( ! empty( $form_data['custom_fields'] ) ) { + $custom_fields = maybe_unserialize( $form_data['custom_fields'] ); + if ( array_key_exists( $description_key, $custom_fields ) ) { + $field_exists = true; + } + } + + if ( ! $field_exists ) { + $show_bio = false; + $bio_html = false; + $global_setting = UM()->options()->get( 'profile_show_html_bio' ); + if ( ! empty( $form_data['use_custom_settings'] ) ) { + if ( ! empty( $form_data['show_bio'] ) ) { + $show_bio = true; + $bio_html = ! empty( $global_setting ); + } + } else { + $global_show_bio = UM()->options()->get( 'profile_show_bio' ); + if ( ! empty( $global_show_bio ) ) { + $show_bio = true; + $bio_html = ! empty( $global_setting ); + } + } + + if ( $show_bio ) { + $max_chars = UM()->options()->get( 'profile_bio_maxchars' ); + if ( $bio_html ) { + $description_value = wp_strip_all_tags( $submitted_data[ $description_key ] ); + } else { + $description_value = $submitted_data[ $description_key ]; + } + } + + if ( ! empty( $description_value ) && ! empty( $max_chars ) && mb_strlen( str_replace( array( "\r\n", "\n", "\r\t", "\t" ), ' ', $description_value ) ) > $max_chars ) { + // translators: %s: max chars. + UM()->form()->add_error( $description_key, sprintf( __( 'Your user description must contain less than %s characters', 'ultimate-member' ), $max_chars ) ); + } + } + } + } + } } add_action( 'um_submit_form_errors_hook_', 'um_submit_form_errors_hook_', 10, 2 ); From d20adc7cb3f28656a7ead601d2cd82d3a9e19e7d Mon Sep 17 00:00:00 2001 From: yuriinalivaiko Date: Tue, 15 Aug 2023 17:34:43 +0300 Subject: [PATCH 20/28] - fixed a conflict with the bootstrap.min.js script in admin modal --- includes/admin/assets/js/um-admin-modal.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/admin/assets/js/um-admin-modal.js b/includes/admin/assets/js/um-admin-modal.js index 7b1717b0..52278298 100644 --- a/includes/admin/assets/js/um-admin-modal.js +++ b/includes/admin/assets/js/um-admin-modal.js @@ -199,7 +199,7 @@ function um_admin_remove_modal() { jQuery('.um_tiny_placeholder').replaceWith( jQuery( $um_tiny_editor ).html() ); } - if ( 'undefined' !== typeof window.UM.admin.allTooltips && window.UM.admin.allTooltips.length > 0 ) { + if ( 'undefined' !== typeof window.UM.admin.allTooltips && window.UM.admin.allTooltips.length > 0 && 'function' === typeof window.UM.admin.allTooltips.tooltip ) { window.UM.admin.allTooltips.tooltip('close'); } jQuery('.tipsy').hide(); From 4e1fcbd90bdb1e1bf0a307f7b973d0d74c66598c Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Tue, 15 Aug 2023 17:39:28 +0300 Subject: [PATCH 21/28] - fixed max chars validation for user description field in header; --- includes/core/um-actions-form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/includes/core/um-actions-form.php b/includes/core/um-actions-form.php index 9ed569e3..44e72695 100644 --- a/includes/core/um-actions-form.php +++ b/includes/core/um-actions-form.php @@ -598,7 +598,7 @@ function um_submit_form_errors_hook_( $submitted_data, $form_data ) { } } - if ( isset( $array['max_chars'] ) && $array['max_chars'] > 0 ) { + if ( ! empty( $array['max_chars'] ) && UM()->profile()->get_show_bio_key( $submitted_data ) !== $key ) { if ( ! empty( $array['html'] ) ) { // Count words without html tags when HTML is enabled. $text_value = wp_strip_all_tags( $submitted_data[ $key ] ); From d99b011380234dce09eb4c54b8ce46d8a9eec7ac Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Tue, 15 Aug 2023 22:39:18 +0300 Subject: [PATCH 22/28] - fixed HTML validation for user description field in header; --- includes/core/class-form.php | 76 +++++++++++++++++++++++++++++++++++- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/includes/core/class-form.php b/includes/core/class-form.php index 7106e3ae..66ff637e 100644 --- a/includes/core/class-form.php +++ b/includes/core/class-form.php @@ -733,7 +733,6 @@ if ( ! class_exists( 'um\core\Form' ) ) { * @return array $form */ public function sanitize( $form ) { - if ( isset( $form['form_id'] ) ) { if ( isset( $this->form_data['custom_fields'] ) ) { $custom_fields = maybe_unserialize( $this->form_data['custom_fields'] ); @@ -862,12 +861,85 @@ if ( ! class_exists( 'um\core\Form' ) ) { } } } + + $show_bio = false; + $bio_html = false; + $global_setting = UM()->options()->get( 'profile_show_html_bio' ); + if ( ! empty( $form_data['use_custom_settings'] ) ) { + if ( ! empty( $form_data['show_bio'] ) ) { + $show_bio = true; + $bio_html = ! empty( $global_setting ); + } + } else { + $global_show_bio = UM()->options()->get( 'profile_show_bio' ); + if ( ! empty( $global_show_bio ) ) { + $show_bio = true; + $bio_html = ! empty( $global_setting ); + } + } + + $description_key = UM()->profile()->get_show_bio_key( $this->form_data ); + if ( $show_bio && ! empty( $form[ $description_key ] ) ) { + $field_exists = false; + if ( ! empty( $this->form_data['custom_fields'] ) ) { + $custom_fields = maybe_unserialize( $this->form_data['custom_fields'] ); + if ( array_key_exists( $description_key, $custom_fields ) ) { + $field_exists = true; + if ( ! empty( $custom_fields[ $description_key ]['html'] ) && $bio_html ) { + $allowed_html = UM()->get_allowed_html( 'templates' ); + if ( empty( $allowed_html['iframe'] ) ) { + $allowed_html['iframe'] = array( + 'allow' => true, + 'frameborder' => true, + 'loading' => true, + 'name' => true, + 'referrerpolicy' => true, + 'sandbox' => true, + 'src' => true, + 'srcdoc' => true, + 'title' => true, + 'width' => true, + 'height' => true, + 'allowfullscreen' => true, + ); + } + $form[ $description_key ] = wp_kses( $form[ $description_key ], $allowed_html ); + } else { + $form[ $description_key ] = sanitize_textarea_field( $form[ $description_key ] ); + } + } + } + + if ( ! $field_exists ) { + if ( $bio_html ) { + $allowed_html = UM()->get_allowed_html( 'templates' ); + if ( empty( $allowed_html['iframe'] ) ) { + $allowed_html['iframe'] = array( + 'allow' => true, + 'frameborder' => true, + 'loading' => true, + 'name' => true, + 'referrerpolicy' => true, + 'sandbox' => true, + 'src' => true, + 'srcdoc' => true, + 'title' => true, + 'width' => true, + 'height' => true, + 'allowfullscreen' => true, + ); + } + $form[ $description_key ] = wp_kses( $form[ $description_key ], $allowed_html ); + } else { + $form[ $description_key ] = sanitize_textarea_field( $form[ $description_key ] ); + } + } + } } return $form; } - /** * Display form type as Title * @param string $mode From 999deb6145b10ff79ab2f99c9967585ad1fb324a Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Tue, 15 Aug 2023 23:04:46 +0300 Subject: [PATCH 23/28] - fixed HTML validation for user description field in header; --- includes/core/class-form.php | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/includes/core/class-form.php b/includes/core/class-form.php index 66ff637e..8821984f 100644 --- a/includes/core/class-form.php +++ b/includes/core/class-form.php @@ -770,6 +770,7 @@ if ( ! class_exists( 'um\core\Form' ) ) { ); } $form[ $k ] = wp_kses( $form[ $k ], $allowed_html ); + add_filter( 'wp_kses_allowed_html', array( &$this, 'wp_kses_user_desc' ), 10, 2 ); } else { $form[ $k ] = sanitize_textarea_field( $form[ $k ] ); } @@ -904,6 +905,8 @@ if ( ! class_exists( 'um\core\Form' ) ) { ); } $form[ $description_key ] = wp_kses( $form[ $description_key ], $allowed_html ); + + add_filter( 'wp_kses_allowed_html', array( &$this, 'wp_kses_user_desc' ), 10, 2 ); } else { $form[ $description_key ] = sanitize_textarea_field( $form[ $description_key ] ); } @@ -930,6 +933,8 @@ if ( ! class_exists( 'um\core\Form' ) ) { ); } $form[ $description_key ] = wp_kses( $form[ $description_key ], $allowed_html ); + + add_filter( 'wp_kses_allowed_html', array( &$this, 'wp_kses_user_desc' ), 10, 2 ); } else { $form[ $description_key ] = sanitize_textarea_field( $form[ $description_key ] ); } @@ -940,6 +945,30 @@ if ( ! class_exists( 'um\core\Form' ) ) { return $form; } + public function wp_kses_user_desc( $tags, $context ) { + if ( 'user_description' === $context || 'pre_user_description' === $context ) { + $allowed_html = UM()->get_allowed_html( 'templates' ); + if ( empty( $allowed_html['iframe'] ) ) { + $allowed_html['iframe'] = array( + 'allow' => true, + 'frameborder' => true, + 'loading' => true, + 'name' => true, + 'referrerpolicy' => true, + 'sandbox' => true, + 'src' => true, + 'srcdoc' => true, + 'title' => true, + 'width' => true, + 'height' => true, + 'allowfullscreen' => true, + ); + } + $tags = $allowed_html; + } + return $tags; + } + /** * Display form type as Title * @param string $mode From 11c0a8ebf9837fd3a0b88d5068bd9bb21e3ad334 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Tue, 15 Aug 2023 23:52:40 +0300 Subject: [PATCH 24/28] - fixed HTML validation for user description field in header; - fixed escaping HTML in user description field; --- includes/core/class-fields.php | 34 +++++++++++++++++++++++++------ includes/core/class-profile.php | 2 ++ includes/core/um-actions-form.php | 14 ++++++++++--- 3 files changed, 41 insertions(+), 9 deletions(-) diff --git a/includes/core/class-fields.php b/includes/core/class-fields.php index e730a65c..c7171e38 100644 --- a/includes/core/class-fields.php +++ b/includes/core/class-fields.php @@ -2766,25 +2766,36 @@ if ( ! class_exists( 'um\core\Fields' ) ) { // User 'description' field uses `'; @@ -4276,25 +4287,36 @@ if ( ! class_exists( 'um\core\Fields' ) ) { $bio_key = UM()->profile()->get_show_bio_key( $this->global_args ); if ( $bio_key === $data['metakey'] ) { + $show_bio = false; $bio_html = false; $global_setting = UM()->options()->get( 'profile_show_html_bio' ); if ( 'profile' === $this->global_args['mode'] ) { if ( ! empty( $this->global_args['use_custom_settings'] ) ) { if ( ! empty( $this->global_args['show_bio'] ) ) { + $show_bio = true; $bio_html = ! empty( $global_setting ); } } else { $global_show_bio = UM()->options()->get( 'profile_show_bio' ); if ( ! empty( $global_show_bio ) ) { + $show_bio = true; $bio_html = ! empty( $global_setting ); } } } - if ( true === $bio_html && ! empty( $data['html'] ) ) { - $res = make_clickable( wpautop( wp_kses_post( $res ) ) ); + if ( $show_bio ) { + if ( true === $bio_html && ! empty( $data['html'] ) ) { + $res = wp_kses_post( make_clickable( wpautop( $res ) ) ); + } else { + $res = esc_html( $res ); + } } else { - $res = esc_html( $res ); + if ( ! empty( $data['html'] ) ) { + $res = wp_kses_post( make_clickable( wpautop( $res ) ) ); + } else { + $res = esc_html( $res ); + } } $res = nl2br( $res ); diff --git a/includes/core/class-profile.php b/includes/core/class-profile.php index c47b99b7..ca698a96 100644 --- a/includes/core/class-profile.php +++ b/includes/core/class-profile.php @@ -439,6 +439,8 @@ if ( ! class_exists( 'um\core\Profile' ) ) { } if ( $bio_html ) { + $data['html'] = true; + $value = um_filtered_value( $key, $data ); $res = wp_kses_post( make_clickable( wpautop( $value ) ) ); } else { $res = esc_html( $value ); diff --git a/includes/core/um-actions-form.php b/includes/core/um-actions-form.php index 44e72695..cc5d9526 100644 --- a/includes/core/um-actions-form.php +++ b/includes/core/um-actions-form.php @@ -710,10 +710,18 @@ function um_submit_form_errors_hook_( $submitted_data, $form_data ) { $max_chars = $array['max_chars']; } - if ( ! empty( $array['html'] ) && $bio_html ) { - $description_value = wp_strip_all_tags( $submitted_data[ $description_key ] ); + if ( $show_bio ) { + if ( ! empty( $array['html'] ) && $bio_html ) { + $description_value = wp_strip_all_tags( $submitted_data[ $description_key ] ); + } else { + $description_value = $submitted_data[ $description_key ]; + } } else { - $description_value = $submitted_data[ $description_key ]; + if ( ! empty( $array['html'] ) ) { + $description_value = wp_strip_all_tags( $submitted_data[ $description_key ] ); + } else { + $description_value = $submitted_data[ $description_key ]; + } } } } From 93bc108bda286b7cc10a1b6860b0cbc2ea17fa4a Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Wed, 16 Aug 2023 00:23:00 +0300 Subject: [PATCH 25/28] - updated readme; --- readme.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.txt b/readme.txt index abd4f6ef..c363a892 100644 --- a/readme.txt +++ b/readme.txt @@ -184,6 +184,7 @@ IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSI - Fixed: Make links clickable in the Registration Details - Fixed: WP_Users_Query on wp-admin > Users screen - Fixed: Performance for `um_get_form_fields` hook + - Fixed: Admin Modal JS library conflict with bootstrap.js * Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade From 332332295711fd0e7dc1ee0db531fc9447df6d69 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Thu, 17 Aug 2023 01:14:47 +0300 Subject: [PATCH 26/28] - added required child-theme admin notice; --- includes/admin/core/class-admin-notices.php | 31 +++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/includes/admin/core/class-admin-notices.php b/includes/admin/core/class-admin-notices.php index 72dd29eb..33ee01f4 100644 --- a/includes/admin/core/class-admin-notices.php +++ b/includes/admin/core/class-admin-notices.php @@ -53,6 +53,8 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { $this->template_version(); + $this->child_theme_required(); + // removed for now to avoid the bad reviews //$this->reviews_notice(); @@ -801,6 +803,35 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { } } + /** + * Check if there isn't installed child-theme. Child theme is required for safely saved customizations. + */ + public function child_theme_required() { + if ( ! is_child_theme() ) { + ob_start(); + ?> + +

+ child-theme for Ultimate Member customization, which hasn\'t dependencies with the official themes repo, so your custom files cannot be rewritten after a theme upgrade.
Otherwise, the customization files may be deleted after every theme upgrade.', 'ultimate-member' ), 'https://developer.wordpress.org/themes/advanced-topics/child-themes/' ), UM()->get_allowed_html( 'admin_notice' ) ); + ?> +

+ + admin()->notices()->add_notice( + 'um_is_not_child_theme', + array( + 'class' => 'notice-warning', + 'message' => $message, + 'dismissible' => true, + ), + 10 + ); + } + } + /** * First time installed Secure settings. */ From cf6836330f3351eb4e5e511d74effea64810f947 Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Thu, 17 Aug 2023 01:16:58 +0300 Subject: [PATCH 27/28] - updated readme; --- readme.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.txt b/readme.txt index c363a892..d096b04c 100644 --- a/readme.txt +++ b/readme.txt @@ -166,7 +166,7 @@ No specific extensions are needed. But we highly recommended keep active these P IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSION 2.6.7 PATCHES SECURITY PRIVILEGE ESCALATION VULNERABILITY. PLEASE SEE [THIS ARTICLE](https://docs.ultimatemember.com/article/1866-security-incident-update-and-recommended-actions) FOR MORE INFORMATION -= 2.6.10: August 16, 2023 = += 2.6.10: August 17, 2023 = * Enhancements: From 8bbcc4479a0f7077407b66b45279bd1bf6215dcf Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Thu, 17 Aug 2023 12:13:19 +0300 Subject: [PATCH 28/28] - added condition for templates customizations exists; --- includes/admin/core/class-admin-notices.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/includes/admin/core/class-admin-notices.php b/includes/admin/core/class-admin-notices.php index 33ee01f4..257db6e7 100644 --- a/includes/admin/core/class-admin-notices.php +++ b/includes/admin/core/class-admin-notices.php @@ -808,6 +808,10 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) { */ public function child_theme_required() { if ( ! is_child_theme() ) { + if ( ! is_dir( get_stylesheet_directory() . DIRECTORY_SEPARATOR . 'ultimate-member' ) ) { + return; + } + ob_start(); ?>