From 5de4986d2eff41dad686a0dbfbb21b274005383b Mon Sep 17 00:00:00 2001 From: Mykyta Synelnikov Date: Wed, 30 Apr 2025 13:04:55 +0300 Subject: [PATCH] Update to version 2.10.4 with bug fixes and improved user handling This update fixes issues related to handling empty user statuses, ensuring proper account status checks and admin notice resets. It also updates plugin assets, documentation, and test scripts to reflect the new version (2.10.4). Additional improvements include enhanced error logging for more reliable diagnostics. --- .wordpress-org/blueprints/blueprint.json | 2 +- README.md | 2 +- includes/common/actions/class-users.php | 19 +++++- includes/common/class-users.php | 15 +++-- readme.txt | 74 +++--------------------- tests/generate-empty-status-users.php | 34 +++++++++-- ultimate-member.php | 2 +- 7 files changed, 67 insertions(+), 81 deletions(-) diff --git a/.wordpress-org/blueprints/blueprint.json b/.wordpress-org/blueprints/blueprint.json index 75651f33..617fcdfc 100644 --- a/.wordpress-org/blueprints/blueprint.json +++ b/.wordpress-org/blueprints/blueprint.json @@ -15,7 +15,7 @@ "step": "installPlugin", "pluginZipFile": { "resource": "url", - "url": "https:\/\/downloads.wordpress.org\/plugin\/ultimate-member.2.10.3.zip" + "url": "https:\/\/downloads.wordpress.org\/plugin\/ultimate-member.2.10.4.zip" }, "options": { "activate": true diff --git a/README.md b/README.md index 45927cc6..a7a83c83 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.10.3](https://github.com/ultimatemember/ultimatemember/releases/tag/2.10.3). +[Official Release Version: 2.10.4](https://github.com/ultimatemember/ultimatemember/releases/tag/2.10.4). ## Changelog diff --git a/includes/common/actions/class-users.php b/includes/common/actions/class-users.php index e3309b6a..d3430d80 100644 --- a/includes/common/actions/class-users.php +++ b/includes/common/actions/class-users.php @@ -45,6 +45,8 @@ if ( ! class_exists( 'um\common\actions\Users' ) ) { } public function status_check() { + // Make the control checking of the empty user statuses inside the function `get_empty_status_users`. + // Maybe some users were approved manually or deleted and we need to reset the admin notice. $total_users = UM()->common()->users()::get_empty_status_users(); if ( empty( $total_users ) ) { return; @@ -114,8 +116,11 @@ if ( ! class_exists( 'um\common\actions\Users' ) ) { foreach ( $results as $user_id ) { $res = UM()->common()->users()->approve( $user_id, true, true ); - if ( $res ) { + if ( $res || UM()->common()->users()->has_status( $user_id, 'approved' ) ) { ++$um_empty_status_users[0]; + } else { + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log + error_log( 'Cannot set `approved` status for the user with ID:' . $user_id ); } } @@ -135,7 +140,19 @@ if ( ! class_exists( 'um\common\actions\Users' ) ) { 'pages' => $pages, ) ); + } else { + // Make the control checking of the empty user statuses. + // Maybe some users were approved manually or deleted and we need to reset the admin notice. + $total_users = UM()->common()->users()::get_empty_status_users(); + if ( empty( $total_users ) ) { + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log + error_log( 'There aren\'t users with empty `account_status`. Maybe some users were approved manually or deleted.' ); + } } + } else { + // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log + error_log( 'There aren\'t users with empty `account_status`. Maybe some users were approved manually or deleted.' ); + delete_option( '_um_log_empty_status_users' ); } } } diff --git a/includes/common/class-users.php b/includes/common/class-users.php index 392c29d2..1701b913 100644 --- a/includes/common/class-users.php +++ b/includes/common/class-users.php @@ -840,18 +840,23 @@ class Users { global $wpdb; $total_users = $wpdb->get_var( - "SELECT COUNT(u.ID) + "SELECT COUNT(DISTINCT u.ID) FROM {$wpdb->users} u LEFT JOIN {$wpdb->usermeta} um ON u.ID = um.user_id AND um.meta_key = 'account_status' LEFT JOIN {$wpdb->usermeta} um2 ON u.ID = um2.user_id AND um2.meta_key = '_um_registration_in_progress' WHERE ( um.meta_value IS NULL OR um.meta_value = '' ) AND - um2.meta_value IS NULL OR um2.meta_value != '1'" + ( um2.meta_value IS NULL OR um2.meta_value != '1' )" ); $total_users = absint( $total_users ); - // In WordPress, an underscore prefix before the option name (e.g., _my_option_name) is commonly used to indicate that the option is private. - // This option has a format: {updated_users}/{total_users_for_update}. - update_option( '_um_log_empty_status_users', array( 0, $total_users ) ); + if ( $total_users > 0 ) { + // In WordPress, an underscore prefix before the option name (e.g., _my_option_name) is commonly used to indicate that the option is private. + // This option has a format: {updated_users}/{total_users_for_update}. + update_option( '_um_log_empty_status_users', array( 0, $total_users ) ); + } else { + // Delete option for the cases when there aren't empty `account_status` users. But admin notice is still displayed. + delete_option( '_um_log_empty_status_users' ); + } return $total_users; } diff --git a/readme.txt b/readme.txt index 53fa0b0c..60ee643c 100644 --- a/readme.txt +++ b/readme.txt @@ -6,7 +6,7 @@ Tags: community, member, membership, user-profile, user-registration Requires PHP: 7.0 Requires at least: 6.2 Tested up to: 6.8 -Stable tag: 2.10.2 +Stable tag: 2.10.3 License: GPLv3 License URI: http://www.gnu.org/licenses/gpl-3.0.txt @@ -167,6 +167,12 @@ 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.10.4 2025-05-xx = + +**Bugfixes** + +* Fixed: The Action Scheduler action `um_set_default_account_status`. Case when some users were approved manually or deleted, and we need to reset the admin notice. Added `error_log()` to the wrong conditions. + = 2.10.3 2025-04-24 = **Enhancements** @@ -237,72 +243,6 @@ IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSI **Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade** -= 2.9.2 2025-01-14 = - -**Enhancements** - -* Added: Compatibility with the new [Ultimate Member - Zapier](https://ultimatemember.com/extensions/zapier/) extension -* Added: Only approved user Reset Password setting defined as true by default -* Added: `UM()->is_new_ui()` function for future enhancements related to new UI -* Added: Filter hook `um_before_user_submitted_registration_data` -* Tweak: Changed hook's priority for initialization of email templates paths -* Tweak: Removed `load_plugin_textdomain` due to (article)[https://make.wordpress.org/core/2024/10/21/i18n-improvements-6-7/#Enhanced-support-for-only-using-PHP-translation-files] - -**Bugfixes** - -* Fixed: Security issue CVE ID: CVE-2025-0308 -* Fixed: Security issue CVE ID: CVE-2025-0318 -* Fixed: Using placeholders in email templates when Action Scheduler is active. Using `fetch_user_id` attribute for fetching necessary user before sending email -* Fixed: PHP 8.4 compatibility. Using WordPress native `wp_is_mobile()` instead of MobileDetect library -* Fixed: PHP errors related to `UM()->localize()` function -* Fixed: PHP errors in user meta header when `last_update` meta is empty -* Fixed: Small CSS changes and avoid duplicates -* Fixed: Removed ms-native show password button for type="password" field in UM forms -* Fixed: Define scalable attribute for cropper - -**Deprecated** - -* Fully deprecated `UM()->mobile()` function -* Fully deprecated `UM()->localize()` function -* Fully deprecated `um_language_textdomain` filter hook - -**Templates required update** - -* account.php - -**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade** - -= 2.9.1 2024-11-15 = - -**Enhancements** - -* Added: `um_image_upload_validation` hook for 3rd-party validation during upload images - -**Bugfixes** - -* Fixed: "Load textdomain just in time" issue -* Fixed: Capabilities checking in the wp-admin > Users list table -* Fixed: File/image upload on the role specific profile form -* Fixed: Issues when the form's custom fields meta has a wrong format -* Fixed: Validation of the "Registration Default Role" slug -* Fixed: Allowed query variables via registered REST API class only when REST_REQUEST is defined - -= 2.9.0 2024-11-12 = - -**Enhancements** - -* Added: Action Scheduler (version 3.8.1) for email sending. More info is [here](https://actionscheduler.org/). -* Added: Supporting new `wp_register_block_metadata_collection()` function for registering WP Blocks - -**Bugfixes** - -* Fixed: `ajax_image_upload()` and `ajax_resize_image()` handlers vulnerability. CVE ID: CVE-2024-10528 -* Fixed: Disabling user status column wp-admin > Users screen -* Fixed: User status filter on wp-admin > Users on mobile devices -* Fixed: Extra unwrapping of the WP Editor field's value - -**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade** - [See changelog for all versions](https://plugins.svn.wordpress.org/ultimate-member/trunk/changelog.txt). == Upgrade Notice == diff --git a/tests/generate-empty-status-users.php b/tests/generate-empty-status-users.php index 55e26ae2..65b6a90b 100644 --- a/tests/generate-empty-status-users.php +++ b/tests/generate-empty-status-users.php @@ -5,12 +5,36 @@ function um_test_generate_random_string( $length = 10 ) { return substr( str_shuffle( str_repeat( $x = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', ceil( $length / strlen( $x ) ) ) ), 1, $length ); } +function api_call() { + $response = wp_remote_get( 'https://randomuser.me/api/?results=1000' ); + + if ( is_wp_error( $response ) ) { + return 'Something went wrong!'; + } + + $body = wp_remote_retrieve_body( $response ); + + $data = json_decode( $body ); + + $users = array(); + foreach ( $data->results as $user ) { + $users[] = array( + 'first' => $user->name->first, + 'last' => $user->name->last, + 'email' => $user->email, + 'username' => $user->login->username, + ); + } + + return $users; +} + +$users = api_call(); for ( $i = 0; $i < 1000; $i++ ) { - $random_user_name = um_test_generate_random_string( 8 ); // Generate a random user name - $random_user_email = $random_user_name . '@example.com'; // Append the user name to a dummy email domain - $random_user_pass = um_test_generate_random_string( 12 ); // Generate a random user password - $random_first_name = um_test_generate_random_string( 5 ); // Generate a random first name - $random_last_name = um_test_generate_random_string( 8 ); // Generate a random last name + $random_user_name = $users[ $i ]['username'] ?? um_test_generate_random_string( 8 ); + $random_user_email = $users[ $i ]['email'] ?? $random_user_name . '@example.com'; + $random_first_name = $users[ $i ]['first'] ?? um_test_generate_random_string( 5 ); + $random_last_name = $users[ $i ]['last'] ?? um_test_generate_random_string( 8 ); $userdata = array( 'user_login' => $random_user_name, diff --git a/ultimate-member.php b/ultimate-member.php index 66b8d5dd..8de11987 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.10.3 + * Version: 2.10.4-alpha * Author: Ultimate Member * Author URI: http://ultimatemember.com/ * Text Domain: ultimate-member