Merge pull request #1696 from ultimatemember/development/2.9.x

Version 2.10.5
This commit is contained in:
Mykyta Synelnikov
2025-06-25 13:27:31 +03:00
committed by GitHub
33 changed files with 2275 additions and 1632 deletions
+1 -1
View File
@@ -15,7 +15,7 @@
"step": "installPlugin",
"pluginZipFile": {
"resource": "url",
"url": "https:\/\/downloads.wordpress.org\/plugin\/ultimate-member.2.10.4.zip"
"url": "https:\/\/downloads.wordpress.org\/plugin\/ultimate-member.2.10.5.zip"
},
"options": {
"activate": true
+1 -1
View File
@@ -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.4](https://github.com/ultimatemember/ultimatemember/releases/tag/2.10.4).
[Official Release Version: 2.10.5](https://github.com/ultimatemember/ultimatemember/releases/tag/2.10.5).
## Changelog
+1 -1
View File
@@ -1249,4 +1249,4 @@ body #content .um-directory a:hover, body #content .um-directory a:focus {
.select2-container .select2-results li.select2-results__option[aria-disabled=true] {
display: none;
}
}
+1 -1
View File
File diff suppressed because one or more lines are too long
+34
View File
@@ -8,6 +8,40 @@ var um_components = wp.components,
function um_admin_blocks_custom_fields( um_condition_fields, props ) {
return wp.hooks.applyFilters( 'um_admin_blocks_custom_fields', [], um_condition_fields, props );
}
function um_add_restriction_attributes( settings, name ) {
// add attributes for all blocks
const restrictionAttributes = {
um_is_restrict: {
type: 'boolean',
default: false,
},
um_who_access: {
type: 'string',
default: '0',
},
um_roles_access: {
type: 'array',
default: [],
},
um_message_type: {
type: 'string',
default: '0',
},
um_message_content: {
type: 'string',
default: '',
},
};
settings.attributes = Object.assign( settings.attributes, restrictionAttributes );
return settings;
}
wp.hooks.addFilter(
'blocks.registerBlockType',
'um-block/add-restriction-attributes',
um_add_restriction_attributes
);
var um_block_restriction = wp.compose.createHigherOrderComponent(
function( BlockEdit ) {
+1 -1
View File
@@ -1 +1 @@
var um_components=wp.components,umSelectControl=um_components.SelectControl,umTextareaControl=um_components.TextareaControl;function um_admin_blocks_custom_fields(e,t){return wp.hooks.applyFilters("um_admin_blocks_custom_fields",[],e,t)}var um_block_restriction=wp.compose.createHigherOrderComponent(function(s){var _={um_who_access:"um_block_settings_hide",um_roles_access:"um_block_settings_hide",um_message_type:"um_block_settings_hide",um_message_content:"um_block_settings_hide"},_=wp.hooks.applyFilters("um_admin_blocks_condition_fields_default",_);return function(t){var e=void 0!==t.attributes.um_is_restrict&&t.attributes.um_is_restrict;return!0!==t.attributes.um_is_restrict?(_.um_who_access="um_block_settings_hide",_.um_roles_access="um_block_settings_hide",_.um_message_type="um_block_settings_hide",_.um_message_content="um_block_settings_hide"):(_.um_who_access="",0===parseInt(t.attributes.um_who_access)||void 0===t.attributes.um_who_access?(_.um_roles_access="um_block_settings_hide",_.um_message_type="um_block_settings_hide",_.um_message_content="um_block_settings_hide"):(1===parseInt(t.attributes.um_who_access)&&(_.um_roles_access=""),_.um_message_type="",2===parseInt(t.attributes.um_message_type)?_.um_message_content="":_.um_message_content="um_block_settings_hide")),_=wp.hooks.applyFilters("um_admin_blocks_condition_fields",_,t),wp.element.createElement(wp.element.Fragment,{},wp.element.createElement(s,t),wp.element.createElement(wp.blockEditor.InspectorControls,{},wp.element.createElement(wp.components.PanelBody,{title:wp.i18n.__("Ultimate Member: Content Restriction","ultimate-member"),className:"um_block_settings"},wp.element.createElement(wp.components.ToggleControl,{label:wp.i18n.__("Restrict access?","ultimate-member"),checked:e,onChange:function(e){t.setAttributes({um_is_restrict:e}),!1===e?(_.um_who_access="um_block_settings_hide",_.um_roles_access="um_block_settings_hide",_.um_message_type="um_block_settings_hide",_.um_message_content="um_block_settings_hide"):_.um_who_access="",_=wp.hooks.applyFilters("um_admin_blocks_condition_fields_on_change",_,"um_is_restrict",e)}}),wp.element.createElement(umSelectControl,{type:"number",className:_.um_who_access,label:wp.i18n.__("Who can access this block?","ultimate-member"),value:t.attributes.um_who_access,options:[{label:wp.i18n.__("Everyone","ultimate-member"),value:0},{label:wp.i18n.__("Logged in users","ultimate-member"),value:1},{label:wp.i18n.__("Logged out users","ultimate-member"),value:2}],onChange:function(e){t.setAttributes({um_who_access:e}),0===parseInt(e)?(_.um_message_type="um_block_settings_hide",_.um_message_content="um_block_settings_hide",_.um_roles_access="um_block_settings_hide"):1===parseInt(e)?(_.um_message_type="",_.um_roles_access=""):(_.um_message_type="",_.um_roles_access="um_block_settings_hide"),_=wp.hooks.applyFilters("um_admin_blocks_condition_fields_on_change",_,"um_who_access",e)}}),wp.element.createElement(umSelectControl,{multiple:!0,className:_.um_roles_access,label:wp.i18n.__("What roles can access this block?","ultimate-member"),value:t.attributes.um_roles_access,options:um_restrict_roles,onChange:function(e){t.setAttributes({um_roles_access:e})}}),wp.element.createElement(umSelectControl,{type:"number",className:_.um_message_type,label:wp.i18n.__("Restriction action","ultimate-member"),value:t.attributes.um_message_type,options:[{label:wp.i18n.__("Hide block","ultimate-member"),value:0},{label:wp.i18n.__("Show global default message","ultimate-member"),value:1},{label:wp.i18n.__("Show custom message","ultimate-member"),value:2}],onChange:function(e){t.setAttributes({um_message_type:e}),2===parseInt(e)?_.um_message_content="":_.um_message_content="um_block_settings_hide"}}),wp.element.createElement(umTextareaControl,{type:"number",className:_.um_message_content,label:wp.i18n.__("Custom restricted access message","ultimate-member"),value:t.attributes.um_message_content,onChange:function(e){t.setAttributes({um_message_content:e})}}),um_admin_blocks_custom_fields(_,t))))}},"um_block_restriction");wp.hooks.addFilter("editor.BlockEdit","um-block/um_block_restriction",um_block_restriction);
var um_components=wp.components,umSelectControl=um_components.SelectControl,umTextareaControl=um_components.TextareaControl;function um_admin_blocks_custom_fields(e,t){return wp.hooks.applyFilters("um_admin_blocks_custom_fields",[],e,t)}function um_add_restriction_attributes(e,t){return e.attributes=Object.assign(e.attributes,{um_is_restrict:{type:"boolean",default:!1},um_who_access:{type:"string",default:"0"},um_roles_access:{type:"array",default:[]},um_message_type:{type:"string",default:"0"},um_message_content:{type:"string",default:""}}),e}wp.hooks.addFilter("blocks.registerBlockType","um-block/add-restriction-attributes",um_add_restriction_attributes);var um_block_restriction=wp.compose.createHigherOrderComponent(function(s){var _={um_who_access:"um_block_settings_hide",um_roles_access:"um_block_settings_hide",um_message_type:"um_block_settings_hide",um_message_content:"um_block_settings_hide"},_=wp.hooks.applyFilters("um_admin_blocks_condition_fields_default",_);return function(t){var e=void 0!==t.attributes.um_is_restrict&&t.attributes.um_is_restrict;return!0!==t.attributes.um_is_restrict?(_.um_who_access="um_block_settings_hide",_.um_roles_access="um_block_settings_hide",_.um_message_type="um_block_settings_hide",_.um_message_content="um_block_settings_hide"):(_.um_who_access="",0===parseInt(t.attributes.um_who_access)||void 0===t.attributes.um_who_access?(_.um_roles_access="um_block_settings_hide",_.um_message_type="um_block_settings_hide",_.um_message_content="um_block_settings_hide"):(1===parseInt(t.attributes.um_who_access)&&(_.um_roles_access=""),_.um_message_type="",2===parseInt(t.attributes.um_message_type)?_.um_message_content="":_.um_message_content="um_block_settings_hide")),_=wp.hooks.applyFilters("um_admin_blocks_condition_fields",_,t),wp.element.createElement(wp.element.Fragment,{},wp.element.createElement(s,t),wp.element.createElement(wp.blockEditor.InspectorControls,{},wp.element.createElement(wp.components.PanelBody,{title:wp.i18n.__("Ultimate Member: Content Restriction","ultimate-member"),className:"um_block_settings"},wp.element.createElement(wp.components.ToggleControl,{label:wp.i18n.__("Restrict access?","ultimate-member"),checked:e,onChange:function(e){t.setAttributes({um_is_restrict:e}),!1===e?(_.um_who_access="um_block_settings_hide",_.um_roles_access="um_block_settings_hide",_.um_message_type="um_block_settings_hide",_.um_message_content="um_block_settings_hide"):_.um_who_access="",_=wp.hooks.applyFilters("um_admin_blocks_condition_fields_on_change",_,"um_is_restrict",e)}}),wp.element.createElement(umSelectControl,{type:"number",className:_.um_who_access,label:wp.i18n.__("Who can access this block?","ultimate-member"),value:t.attributes.um_who_access,options:[{label:wp.i18n.__("Everyone","ultimate-member"),value:0},{label:wp.i18n.__("Logged in users","ultimate-member"),value:1},{label:wp.i18n.__("Logged out users","ultimate-member"),value:2}],onChange:function(e){t.setAttributes({um_who_access:e}),0===parseInt(e)?(_.um_message_type="um_block_settings_hide",_.um_message_content="um_block_settings_hide",_.um_roles_access="um_block_settings_hide"):1===parseInt(e)?(_.um_message_type="",_.um_roles_access=""):(_.um_message_type="",_.um_roles_access="um_block_settings_hide"),_=wp.hooks.applyFilters("um_admin_blocks_condition_fields_on_change",_,"um_who_access",e)}}),wp.element.createElement(umSelectControl,{multiple:!0,className:_.um_roles_access,label:wp.i18n.__("What roles can access this block?","ultimate-member"),value:t.attributes.um_roles_access,options:um_restrict_roles,onChange:function(e){t.setAttributes({um_roles_access:e})}}),wp.element.createElement(umSelectControl,{type:"number",className:_.um_message_type,label:wp.i18n.__("Restriction action","ultimate-member"),value:t.attributes.um_message_type,options:[{label:wp.i18n.__("Hide block","ultimate-member"),value:0},{label:wp.i18n.__("Show global default message","ultimate-member"),value:1},{label:wp.i18n.__("Show custom message","ultimate-member"),value:2}],onChange:function(e){t.setAttributes({um_message_type:e}),2===parseInt(e)?_.um_message_content="":_.um_message_content="um_block_settings_hide"}}),wp.element.createElement(umTextareaControl,{type:"number",className:_.um_message_content,label:wp.i18n.__("Custom restricted access message","ultimate-member"),value:t.attributes.um_message_content,onChange:function(e){t.setAttributes({um_message_content:e})}}),um_admin_blocks_custom_fields(_,t))))}},"um_block_restriction");wp.hooks.addFilter("editor.BlockEdit","um-block/um_block_restriction",um_block_restriction);
+25
View File
@@ -1,5 +1,30 @@
== Changelog ==
= 2.10.5 June 25, 2025 =
* Enhancements:
- Added: Filter hooks for primary button classes in UM forms.
- Tweak: Refactored Site Health data, added hooks for 3rd-party integration.
* Bugfixes:
- Fixed: Stripped shortcodes in the user data during the Account, Registration and Profile forms submission. (Thanks to [MissVeronica](https://github.com/MissVeronica))
- Fixed: Email placeholders values.
- Fixed: Refactor deactivation logic to un-schedule Action Scheduler actions.
- Fixed: Action Scheduler library errors. Updated to the recent 3.9.2 version.
- Fixed: Secondary email field validation.
- Fixed: Action Scheduler batch actions with users who have Undefined status.
- Fixed: Restrictions for 3rd-party Gutenberg Blocks.
- Fixed: Date/time picker filter-types range query on Member Directories.
- Fixed: Renamed "Macedonia, the former Yugoslav Republic of" to the official "North Macedonia".
* Templates required update:
- password-reset.php
* Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade *
= 2.10.4 May 15, 2025 =
* Bugfixes:
+1 -1
View File
@@ -24,7 +24,7 @@
"ext-iconv": "*",
"ext-tidy": "*",
"composer/installers": "^2.3",
"woocommerce/action-scheduler": "3.9.0"
"woocommerce/action-scheduler": "3.9.2"
},
"require-dev": {
"wp-cli/wp-cli": "*",
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,8 @@
<?php
namespace um\admin\core;
use um\common\actions\Users;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@@ -261,6 +263,13 @@ if ( ! class_exists( 'um\admin\core\Admin_Notices' ) ) {
return;
}
// Alternative method of checking and maybe schedule a batch action if it has not been scheduled previously.
// Avoid case when the option with the empty user statuses isn't empty.
// We need to recalculate option value and re-schedule the Batch action.
if ( ! UM()->maybe_action_scheduler()->has_scheduled_action( Users::BATCH_ACTION ) ) {
do_action( Users::SCHEDULE_ACTION );
}
$allowed_html = array(
'a' => array(
'href' => array(),
@@ -1403,6 +1403,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) {
'args' => array(
'textarea_rows' => 6,
),
'conditional' => array( 'account_tab_delete', '=', '1' ),
),
array(
'id' => 'delete_account_no_pass_required_text',
@@ -1412,6 +1413,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) {
'args' => array(
'textarea_rows' => 6,
),
'conditional' => array( 'account_tab_delete', '=', '1' ),
),
),
),
+6 -3
View File
@@ -42,6 +42,7 @@ if ( ! class_exists( 'UM' ) ) {
* @method UM_Profile_Tabs Profile_Tabs()
* @method UM_JobBoardWP JobBoardWP()
* @method UM_Zapier Zapier()
* @method UM_Stripe_API Stripe_API()
* @method UM_Google_Authenticator Google_Authenticator()
*/
final class UM extends UM_Functions {
@@ -370,16 +371,18 @@ if ( ! class_exists( 'UM' ) ) {
}
}
/**
* Plugin Deactivation
*
* @since 2.3
*/
function deactivation() {
public function deactivation() {
$this->cron()->unschedule_events();
}
$this->maybe_action_scheduler()->unschedule_all_actions( 'um_dispatch_email' );
$this->maybe_action_scheduler()->unschedule_all_actions( 'um_schedule_empty_account_status_check' );
$this->maybe_action_scheduler()->unschedule_all_actions( 'um_set_default_account_status' );
}
/**
* Maybe need multisite activation process
-25
View File
@@ -19,7 +19,6 @@ if ( ! class_exists( 'um\common\actions\Emails' ) ) {
public function __construct() {
add_filter( 'um_action_scheduler_is_hook_enabled', array( $this, 'is_enabled' ), 10, 2 );
add_action( 'um_dispatch_email', array( $this, 'send' ), 10, 3 );
add_action( 'um_before_email_notification_sending', array( $this, 'before_email_send' ), 10, 2 );
}
public function is_enabled( $is_enabled, $hook ) {
@@ -52,29 +51,5 @@ if ( ! class_exists( 'um\common\actions\Emails' ) ) {
UM()->mail()->send( $user_email, $template, $args );
}
/**
* Add some custom placeholders when sending via Action Scheduler.
*
* @todo Workaround for now. Maybe we need to handle email placeholders in email class where $user_id is fetched everytime
*
* @param string $email
* @param string $template
*
* @return void
*/
public function before_email_send( $email, $template ) {
if ( ! UM()->maybe_action_scheduler()->is_hook_enabled( 'um_dispatch_email' ) ) {
return;
}
if ( 'checkmail_email' === $template ) {
add_filter( 'um_template_tags_patterns_hook', array( UM()->user(), 'add_activation_placeholder' ) );
add_filter( 'um_template_tags_replaces_hook', array( UM()->user(), 'add_activation_replace_placeholder' ) );
} elseif ( 'welcome_email' === $template || 'approved_email' === $template || 'resetpw_email' === $template ) {
add_filter( 'um_template_tags_patterns_hook', array( UM()->password(), 'add_placeholder' ) );
add_filter( 'um_template_tags_replaces_hook', array( UM()->password(), 'add_replace_placeholder' ) );
}
}
}
}
+177 -26
View File
@@ -384,15 +384,33 @@ class Users {
$userdata = get_userdata( $user_id );
$current_user_id = get_current_user_id();
um_fetch_user( $user_id );
$temp_id = null;
if ( um_user( 'ID' ) !== $user_id ) {
$temp_id = um_user( 'ID' );
um_fetch_user( $user_id );
}
add_filter( 'um_template_tags_patterns_hook', array( UM()->user(), 'add_activation_placeholder' ) );
add_filter( 'um_template_tags_replaces_hook', array( UM()->user(), 'add_activation_replace_placeholder' ) );
UM()->maybe_action_scheduler()->enqueue_async_action(
'um_dispatch_email',
array(
$userdata->user_email,
'checkmail_email',
array(
'fetch_user_id' => $user_id,
'tags' => array(
'{account_activation_link}',
),
'tags_replace' => array(
UM()->permalinks()->activate_url( $user_id ),
),
),
)
);
UM()->maybe_action_scheduler()->enqueue_async_action( 'um_dispatch_email', array( $userdata->user_email, 'checkmail_email', array( 'fetch_user_id' => $user_id ) ) );
if ( $temp_id ) {
um_fetch_user( $temp_id );
}
um_fetch_user( $current_user_id );
/**
* Fires after User has been set as pending email confirmation.
*
@@ -458,7 +476,25 @@ class Users {
$this->reset_activation_link( $user_id );
$userdata = get_userdata( $user_id );
UM()->maybe_action_scheduler()->enqueue_async_action( 'um_dispatch_email', array( $userdata->user_email, 'inactive_email', array( 'fetch_user_id' => $user_id ) ) );
$temp_id = null;
if ( um_user( 'ID' ) !== $user_id ) {
$temp_id = um_user( 'ID' );
um_fetch_user( $user_id );
}
UM()->maybe_action_scheduler()->enqueue_async_action(
'um_dispatch_email',
array(
$userdata->user_email,
'inactive_email',
array( 'fetch_user_id' => $user_id ),
)
);
if ( $temp_id ) {
um_fetch_user( $temp_id );
}
/**
* Fires after User has been deactivated.
@@ -530,7 +566,25 @@ class Users {
$this->reset_activation_link( $user_id );
$userdata = get_userdata( $user_id );
UM()->maybe_action_scheduler()->enqueue_async_action( 'um_dispatch_email', array( $userdata->user_email, 'rejected_email', array( 'fetch_user_id' => $user_id ) ) );
$temp_id = null;
if ( um_user( 'ID' ) !== $user_id ) {
$temp_id = um_user( 'ID' );
um_fetch_user( $user_id );
}
UM()->maybe_action_scheduler()->enqueue_async_action(
'um_dispatch_email',
array(
$userdata->user_email,
'rejected_email',
array( 'fetch_user_id' => $user_id ),
)
);
if ( $temp_id ) {
um_fetch_user( $temp_id );
}
/**
* Fires after User has been rejected.
@@ -608,7 +662,25 @@ class Users {
$this->reset_activation_link( $user_id );
$userdata = get_userdata( $user_id );
UM()->maybe_action_scheduler()->enqueue_async_action( 'um_dispatch_email', array( $userdata->user_email, 'pending_email', array( 'fetch_user_id' => $user_id ) ) );
$temp_id = null;
if ( um_user( 'ID' ) !== $user_id ) {
$temp_id = um_user( 'ID' );
um_fetch_user( $user_id );
}
UM()->maybe_action_scheduler()->enqueue_async_action(
'um_dispatch_email',
array(
$userdata->user_email,
'pending_email',
array( 'fetch_user_id' => $user_id ),
)
);
if ( $temp_id ) {
um_fetch_user( $temp_id );
}
/**
* Fires after User has been set as pending admin review.
@@ -689,21 +761,55 @@ class Users {
$this->reset_activation_link( $user_id );
$email_slug = 'welcome_email';
if ( 'awaiting_admin_review' === $old_status ) {
$email_slug = 'approved_email';
$this->maybe_generate_password_reset_key( $userdata );
$email_slug = 'awaiting_admin_review' === $old_status ? 'approved_email' : 'welcome_email';
$reset_pw_link = UM()->password()->reset_url( $user_id );
$tags = array(
'{password_reset_link}',
'{password}',
);
$tags_replace = array(
$reset_pw_link,
__( 'Your set password', 'ultimate-member' ),
);
if ( 'welcome_email' === $email_slug ) {
$tags[] = '{action_url}';
$tags[] = '{action_title}';
$set_password_required = get_user_meta( $user_id, 'um_set_password_required', true );
if ( empty( $set_password_required ) || $this->has_status( $user_id, 'pending' ) ) {
$tags_replace[] = um_get_core_page( 'login' );
$tags_replace[] = esc_html__( 'Login to our site', 'ultimate-member' );
} else {
$tags_replace[] = $reset_pw_link;
$tags_replace[] = esc_html__( 'Set your password', 'ultimate-member' );
}
}
$current_user_id = get_current_user_id();
um_fetch_user( $user_id );
$temp_id = null;
if ( um_user( 'ID' ) !== $user_id ) {
$temp_id = um_user( 'ID' );
um_fetch_user( $user_id );
}
add_filter( 'um_template_tags_patterns_hook', array( UM()->password(), 'add_placeholder' ) );
add_filter( 'um_template_tags_replaces_hook', array( UM()->password(), 'add_replace_placeholder' ) );
UM()->maybe_action_scheduler()->enqueue_async_action(
'um_dispatch_email',
array(
$userdata->user_email,
$email_slug,
array(
'fetch_user_id' => $user_id,
'tags' => $tags,
'tags_replace' => $tags_replace,
),
)
);
UM()->maybe_action_scheduler()->enqueue_async_action( 'um_dispatch_email', array( $userdata->user_email, $email_slug, array( 'fetch_user_id' => $user_id ) ) );
um_fetch_user( $current_user_id );
if ( $temp_id ) {
um_fetch_user( $temp_id );
}
}
/**
* Fires after User has been approved.
@@ -773,15 +879,49 @@ class Users {
$userdata = get_userdata( $user_id );
$current_user_id = get_current_user_id();
um_fetch_user( $user_id );
$temp_id = null;
if ( um_user( 'ID' ) !== $user_id ) {
$temp_id = um_user( 'ID' );
um_fetch_user( $user_id );
}
add_filter( 'um_template_tags_patterns_hook', array( UM()->password(), 'add_placeholder' ) );
add_filter( 'um_template_tags_replaces_hook', array( UM()->password(), 'add_replace_placeholder' ) );
$reset_pw_link = UM()->password()->reset_url( $user_id );
UM()->maybe_action_scheduler()->enqueue_async_action( 'um_dispatch_email', array( $userdata->user_email, 'welcome_email', array( 'fetch_user_id' => $user_id ) ) );
$tags_replace = array(
$reset_pw_link,
__( 'Your set password', 'ultimate-member' ),
);
um_fetch_user( $current_user_id );
$set_password_required = get_user_meta( $user_id, 'um_set_password_required', true );
if ( empty( $set_password_required ) || $this->has_status( $user_id, 'pending' ) ) {
$tags_replace[] = um_get_core_page( 'login' );
$tags_replace[] = esc_html__( 'Login to our site', 'ultimate-member' );
} else {
$tags_replace[] = $reset_pw_link;
$tags_replace[] = esc_html__( 'Set your password', 'ultimate-member' );
}
UM()->maybe_action_scheduler()->enqueue_async_action(
'um_dispatch_email',
array(
$userdata->user_email,
'welcome_email',
array(
'fetch_user_id' => $user_id,
'tags' => array(
'{password_reset_link}',
'{password}',
'{action_url}',
'{action_title}',
),
'tags_replace' => $tags_replace,
),
)
);
if ( $temp_id ) {
um_fetch_user( $temp_id );
}
/**
* Fires after User has been reactivated.
@@ -860,4 +1000,15 @@ class Users {
return $total_users;
}
/**
* Set last login timestamp.
*
* @param int $user_id User ID.
*/
public function set_last_login( $user_id ) {
update_user_meta( $user_id, '_um_last_login', current_time( 'mysql', true ) );
// Flush user cache after updating last_login timestamp.
UM()->user()->remove_cache( $user_id );
}
}
+11 -5
View File
@@ -37,27 +37,33 @@ if ( ! class_exists( 'um\core\Blocks' ) ) {
if ( empty( $settings['attributes']['um_is_restrict'] ) ) {
$settings['attributes']['um_is_restrict'] = array(
'type' => 'boolean',
'type' => 'boolean',
'default' => false,
);
}
if ( empty( $settings['attributes']['um_who_access'] ) ) {
$settings['attributes']['um_who_access'] = array(
'type' => 'string',
'type' => 'string',
'default' => 0,
);
}
if ( empty( $settings['attributes']['um_roles_access'] ) ) {
$settings['attributes']['um_roles_access'] = array(
'type' => 'array',
'type' => 'array',
'default' => array(),
'items' => array( 'type' => 'string' ),
);
}
if ( empty( $settings['attributes']['um_message_type'] ) ) {
$settings['attributes']['um_message_type'] = array(
'type' => 'string',
'type' => 'string',
'default' => 0,
);
}
if ( empty( $settings['attributes']['um_message_content'] ) ) {
$settings['attributes']['um_message_content'] = array(
'type' => 'string',
'type' => 'string',
'default' => '',
);
}
+1 -1
View File
@@ -1987,7 +1987,7 @@ if ( ! class_exists( 'um\core\Builtin' ) ) {
'LT' => __('Lithuania','ultimate-member'),
'LU' => __('Luxembourg','ultimate-member'),
'MO' => __('Macao','ultimate-member'),
'MK' => __('Macedonia, the former Yugoslav Republic of','ultimate-member'),
'MK' => __('North Macedonia','ultimate-member'),
'MG' => __('Madagascar','ultimate-member'),
'MW' => __('Malawi','ultimate-member'),
'MY' => __('Malaysia','ultimate-member'),
+10 -10
View File
@@ -857,10 +857,10 @@ if ( ! class_exists( 'um\core\Form' ) ) {
'allowfullscreen' => true,
);
}
$form[ $k ] = wp_kses( $form[ $k ], $allowed_html );
$form[ $k ] = wp_kses( strip_shortcodes( $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 ] );
$form[ $k ] = sanitize_textarea_field( strip_shortcodes( $form[ $k ] ) );
}
break;
case 'oembed':
@@ -915,9 +915,9 @@ if ( ! class_exists( 'um\core\Form' ) ) {
}
}
$form[ $k ] = esc_url_raw( $v );
$form[ $k ] = esc_url_raw( strip_shortcodes( $v ) );
} else {
$form[ $k ] = esc_url_raw( $form[ $k ] );
$form[ $k ] = esc_url_raw( strip_shortcodes( $form[ $k ] ) );
}
break;
case 'password':
@@ -939,12 +939,12 @@ if ( ! class_exists( 'um\core\Form' ) ) {
case 'soundcloud_track':
case 'spotify':
case 'tel':
$form[ $k ] = sanitize_text_field( $form[ $k ] );
$form[ $k ] = sanitize_text_field( strip_shortcodes( $form[ $k ] ) );
break;
case 'multiselect':
case 'radio':
case 'checkbox':
$form[ $k ] = is_array( $form[ $k ] ) ? array_map( 'sanitize_text_field', $form[ $k ] ) : sanitize_text_field( $form[ $k ] );
$form[ $k ] = is_array( $form[ $k ] ) ? array_map( 'sanitize_text_field', array_map( 'strip_shortcodes', $form[ $k ] ) ) : sanitize_text_field( strip_shortcodes( $form[ $k ] ) );
break;
}
}
@@ -997,11 +997,11 @@ if ( ! class_exists( 'um\core\Form' ) ) {
'allowfullscreen' => true,
);
}
$form[ $description_key ] = wp_kses( $form[ $description_key ], $allowed_html );
$form[ $description_key ] = wp_kses( strip_shortcodes( $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 ] );
$form[ $description_key ] = sanitize_textarea_field( strip_shortcodes( $form[ $description_key ] ) );
}
}
}
@@ -1025,11 +1025,11 @@ if ( ! class_exists( 'um\core\Form' ) ) {
'allowfullscreen' => true,
);
}
$form[ $description_key ] = wp_kses( $form[ $description_key ], $allowed_html );
$form[ $description_key ] = wp_kses( strip_shortcodes( $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 ] );
$form[ $description_key ] = sanitize_textarea_field( strip_shortcodes( $form[ $description_key ] ) );
}
}
}
-19
View File
@@ -348,9 +348,6 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
*/
$message = apply_filters( 'um_email_send_message_content', $message, $slug, $args );
// add_filter( 'um_template_tags_patterns_hook', array( &$this, 'add_placeholder' ) );
// add_filter( 'um_template_tags_replaces_hook', array( &$this, 'add_replace_placeholder' ) );
// Convert tags in email template.
return um_convert_tags( $message, $args );
}
@@ -616,12 +613,8 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
$placeholders[] = '{user_profile_link}';
$placeholders[] = '{site_url}';
$placeholders[] = '{admin_email}';
$placeholders[] = '{submitted_registration}';
$placeholders[] = '{login_url}';
$placeholders[] = '{password}';
$placeholders[] = '{account_activation_link}';
$placeholders[] = '{action_url}';
$placeholders[] = '{action_title}';
return $placeholders;
}
@@ -636,20 +629,8 @@ if ( ! class_exists( 'um\core\Mail' ) ) {
$replace_placeholders[] = um_user_profile_url();
$replace_placeholders[] = get_bloginfo( 'url' );
$replace_placeholders[] = um_admin_email();
$replace_placeholders[] = um_user_submitted_registration_formatted();
$replace_placeholders[] = um_get_core_page( 'login' );
$replace_placeholders[] = esc_html__( 'Your set password', 'ultimate-member' );
$replace_placeholders[] = um_user( 'account_activation_link' );
$set_password_required = get_user_meta( um_user( 'ID' ), 'um_set_password_required', true );
if ( empty( $set_password_required ) || 'pending' === um_user( 'status' ) ) {
$replace_placeholders[] = um_get_core_page( 'login' );
$replace_placeholders[] = esc_html__( 'Login to our site', 'ultimate-member' );
} else {
$replace_placeholders[] = um_user( 'password_reset_link' );
$replace_placeholders[] = esc_html__( 'Set your password', 'ultimate-member' );
}
return $replace_placeholders;
}
}
+6 -3
View File
@@ -1101,7 +1101,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$wpdb->prepare(
"SELECT DISTINCT meta_value
FROM {$wpdb->usermeta}
WHERE meta_key = %s
WHERE meta_key = %s AND
meta_value != ''
ORDER BY meta_value DESC",
$filter
)
@@ -1122,7 +1123,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
MIN(meta_value) AS min,
MAX(meta_value) AS max
FROM {$wpdb->usermeta}
WHERE meta_key = '_um_last_login'",
WHERE meta_key = '_um_last_login' AND
meta_value != ''",
ARRAY_A
);
if ( empty( $meta['total'] ) || 1 === absint( $meta['total'] ) ) {
@@ -1161,7 +1163,8 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
$wpdb->prepare(
"SELECT DISTINCT meta_value
FROM {$wpdb->usermeta}
WHERE meta_key = %s
WHERE meta_key = %s AND
meta_value != ''
ORDER BY meta_value DESC",
$filter
)
+9 -14
View File
@@ -57,11 +57,11 @@ if ( ! class_exists( 'um\core\Password' ) ) {
}
if ( empty( $reset_key ) ) {
$reset_key = UM()->user()->maybe_generate_password_reset_key( $user_data );
$reset_key = UM()->common()->users()->maybe_generate_password_reset_key( $user_data );
}
// this link looks like WordPress native link e.g. wp-login.php?action=rp&key={hash}&login={user_login}
$url = add_query_arg(
// This link looks like WordPress native link e.g. wp-login.php?action=rp&key={hash}&login={user_login}
return add_query_arg(
array(
'act' => 'reset_password',
'hash' => $reset_key,
@@ -69,7 +69,6 @@ if ( ! class_exists( 'um\core\Password' ) ) {
),
um_get_core_page( 'password-reset' )
);
return $url;
}
@@ -695,31 +694,27 @@ if ( ! class_exists( 'um\core\Password' ) ) {
setcookie( $name, $value, $expire, $path, COOKIE_DOMAIN, is_ssl(), true );
}
/**
* UM Placeholders for reset password
*
* @depreated 2.10.5
* @param $placeholders
*
* @return array
*/
function add_placeholder( $placeholders ) {
$placeholders[] = '{password_reset_link}';
$placeholders[] = '{password}';
public function add_placeholder( $placeholders ) {
_deprecated_function( __METHOD__, '2.10.5' );
return $placeholders;
}
/**
* UM Replace Placeholders for reset password
*
* @depreated 2.10.5
* @param $replace_placeholders
*
* @return array
*/
function add_replace_placeholder( $replace_placeholders ) {
$replace_placeholders[] = um_user( 'password_reset_link' );
$replace_placeholders[] = esc_html__( 'Your set password', 'ultimate-member' );
public function add_replace_placeholder( $replace_placeholders ) {
_deprecated_function( __METHOD__, '2.10.5' );
return $replace_placeholders;
}
}
+29 -26
View File
@@ -172,8 +172,7 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
$redirect = empty( $user_role_data['url_email_activate'] ) ? um_get_core_page( 'login', 'account_active' ) : trim( $user_role_data['url_email_activate'] );
} else {
// Redirect to the change password page if there is no password for this user.
um_fetch_user( $user_id );
$redirect = um_user( 'password_reset_link' );
$redirect = UM()->password()->reset_url( $user_id );
}
/**
* Filter to change the redirect URL after email confirmation.
@@ -204,40 +203,44 @@ if ( ! class_exists( 'um\core\Permalinks' ) ) {
/**
* Makes an activate link for any user
*
* @return bool|string
* @return string
*/
public function activate_url() {
if ( ! um_user( 'account_secret_hash' ) ) {
return false;
public function activate_url( $user_id = null ) {
if ( is_null( $user_id ) ) {
$user_id = um_user( 'ID' );
}
$account_secret_hash = get_user_meta( $user_id, 'account_secret_hash', true );
if ( empty( $account_secret_hash ) ) {
return '';
}
/**
* UM hook
* Filter to change the base URL for the user activation link.
*
* @type filter
* @title um_activate_url
* @description Change activate user URL
* @input_vars
* [{"var":"$url","type":"string","desc":"Activate URL"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_activate_url', 'function_name', 10, 1 ); ?>
* @example
* <?php
* add_filter( 'um_activate_url', 'my_activate_url', 10, 1 );
* function my_activate_url( $url ) {
* @hook um_activate_url
*
* @param {string} $url The base URL. `home_url()` by default
*
* @since 1.3.x
*
* @example <caption>Change activate user base URL.</caption>
* function my_after_email_confirmation_redirect( $url ) {
* // your code here
* return $url;
* }
* ?>
* add_filter( 'um_activate_url', 'my_um_activate_url' );
*/
$url = apply_filters( 'um_activate_url', home_url() );
$url = add_query_arg( 'act', 'activate_via_email', $url );
$url = add_query_arg( 'hash', um_user( 'account_secret_hash' ), $url );
$url = add_query_arg( 'user_id', um_user( 'ID' ), $url );
$base_url = apply_filters( 'um_activate_url', home_url() );
return $url;
return add_query_arg(
array(
'act' => 'activate_via_email',
'hash' => $account_secret_hash,
'user_id' => $user_id,
),
$base_url
);
}
/**
+51 -48
View File
@@ -103,7 +103,24 @@ if ( ! class_exists( 'um\core\Profile' ) ) {
* @return array
*/
public function tabs_privacy() {
$privacy = apply_filters(
/**
* Filters a privacy list extend.
*
* @since 2.7.0
* @hook um_profile_tabs_privacy_list
*
* @param {array} $privacy_option Add options for profile tabs' privacy.
*
* @return {array} Options for profile tabs' privacy.
*
* @example <caption>Add options for profile tabs' privacy.</caption>
* function um_profile_menu_link_attrs( $privacy_option ) {
* // your code here
* return $privacy_option;
* }
* add_filter( 'um_profile_tabs_privacy_list', 'um_profile_tabs_privacy_list', 10, 1 );
*/
return apply_filters(
'um_profile_tabs_privacy_list',
array(
0 => __( 'Anyone', 'ultimate-member' ),
@@ -114,53 +131,46 @@ if ( ! class_exists( 'um\core\Profile' ) ) {
5 => __( 'Owner and specific roles', 'ultimate-member' ),
)
);
return $privacy;
}
/**
* All tab data
*
* @return array
*/
function tabs() {
/**
* UM hook
*
* @type filter
* @title um_profile_tabs
* @description Extend user profile tabs
* @input_vars
* [{"var":"$tabs","type":"array","desc":"Profile tabs"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_profile_tabs', 'function_name', 10, 1 ); ?>
* @example
* <?php
* add_filter( 'um_profile_tabs', 'my_profile_tabs', 10, 1 );
* function my_profile_tabs( $tabs ) {
* // your code here
* return $tabs;
* }
* ?>
*/
$tabs = apply_filters( 'um_profile_tabs', array(
'main' => array(
public function tabs() {
$tabs = array(
'main' => array(
'name' => __( 'About', 'ultimate-member' ),
'icon' => 'um-faicon-user'
'icon' => 'um-faicon-user',
),
'posts' => array(
'posts' => array(
'name' => __( 'Posts', 'ultimate-member' ),
'icon' => 'um-faicon-pencil'
'icon' => 'um-faicon-pencil',
),
'comments' => array(
'name' => __( 'Comments', 'ultimate-member' ),
'icon' => 'um-faicon-comment'
)
) );
'icon' => 'um-faicon-comment',
),
);
/**
* Filters user profile tabs
*
* @since 1.3.x
* @hook um_profile_tabs
*
* @param {array} $tabs tabs list.
*
* @return {array} tabs list.
*
* @example <caption>Add user profile tabs.</caption>
* function um_profile_tabs( $tabs ) {
* // your code here
* return $tabs;
* }
* add_filter( 'um_profile_tabs', 'um_profile_tabs' );
*/
$tabs = apply_filters( 'um_profile_tabs', $tabs );
// disable private tabs
if ( ! is_admin() ) {
@@ -513,35 +523,28 @@ if ( ! class_exists( 'um\core\Profile' ) ) {
<?php
}
/**
* UM Placeholders for user link, avatar link
*
* @depreacated 2.10.5
* @param $placeholders
*
* @return array
*/
function add_placeholder( $placeholders ) {
$placeholders[] = '{user_profile_link}';
$placeholders[] = '{user_avatar_url}';
$placeholders[] = '{password}';
public function add_placeholder( $placeholders ) {
_deprecated_function( __METHOD__, '2.10.5' );
return $placeholders;
}
/**
* UM Replace Placeholders for user link, avatar link
*
* @deprecated 2.10.5
* @param $replace_placeholders
*
* @return array
*/
function add_replace_placeholder( $replace_placeholders ) {
$replace_placeholders[] = um_get_user_avatar_url();
$replace_placeholders[] = um_user_profile_url();
$replace_placeholders[] = esc_html__( 'Your set password', 'ultimate-member' );
public function add_replace_placeholder( $replace_placeholders ) {
_deprecated_function( __METHOD__, '2.10.5' );
return $replace_placeholders;
}
}
}
+2 -2
View File
@@ -316,9 +316,9 @@ KEY meta_value_indx (um_value(191))
}
// If there are some users without `account_status` then run the first async batch for update.
$batch_size = 50; // See the class constant value `\um\common\actions\Users::BATCH_ACTION`.
$batch_size = 50; // See the class constant value `\um\common\actions\Users::BATCH_SIZE`.
UM()->maybe_action_scheduler()->enqueue_async_action(
$batch_size,
'um_set_default_account_status', // See the class constant value `\um\common\actions\Users::BATCH_ACTION`.
array(
'page' => 1,
'total' => $total_users,
+1 -1
View File
@@ -403,7 +403,7 @@ if ( ! class_exists( 'um\core\Shortcodes' ) ) {
public function um_loggedin( $args = array(), $content = '' ) {
$args = shortcode_atts(
array(
'lock_text' => __( 'This content has been restricted to logged-in users only. Please <a href="{login_referrer}">login</a> to view this content.', 'ultimate-member' ),
'lock_text' => __( 'This content has been restricted to logged-in users only. Please <a href="{login_referrer}">log in</a> to view this content.', 'ultimate-member' ),
'show_lock' => 'yes',
),
$args,
+70 -56
View File
@@ -1,6 +1,9 @@
<?php
namespace um\core;
use WP_Error;
use WP_User;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
@@ -965,7 +968,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
* On wp_update_user function complete
*
* @param int $user_id
* @param \WP_User $old_data
* @param WP_User $old_data
*/
function profile_update( $user_id, $old_data ) {
// Bail if no user ID was passed
@@ -1018,7 +1021,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
/**
* Additional section for WP Profile page with UM data fields
*
* @param \WP_User $userdata User data
* @param WP_User $userdata User data
* @return void
*/
function profile_form_additional_section( $userdata ) {
@@ -1063,7 +1066,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
* Default interface for setting a ultimatemember role
*
* @param string $content Section HTML
* @param \WP_User $userdata User data
* @param WP_User $userdata User data
* @return string
*/
public function secondary_role_field( $content, $userdata ) {
@@ -1103,7 +1106,7 @@ if ( ! class_exists( 'um\core\User' ) ) {
}
}
$class = ( $userdata == 'add-existing-user' ) ? 'um_role_existing_selector_wrapper' : 'um_role_selector_wrapper';
$class = 'add-existing-user' === $userdata ? 'um_role_existing_selector_wrapper' : 'um_role_selector_wrapper';
ob_start();
?>
@@ -1468,22 +1471,6 @@ if ( ! class_exists( 'um\core\User' ) ) {
do_action( 'um_after_save_registration_details', $this->id, $submitted, $form_data );
}
/**
* Set last login for new registered users
*/
public function set_last_login() {
update_user_meta( $this->id, '_um_last_login', current_time( 'mysql', true ) );
}
/**
* @param \WP_User $userdata
*
* @return string|\WP_Error
*/
function maybe_generate_password_reset_key( $userdata ) {
return get_password_reset_key( $userdata );
}
/**
* Password reset email
*
@@ -1497,19 +1484,22 @@ if ( ! class_exists( 'um\core\User' ) ) {
}
$userdata = get_userdata( $user_id );
$this->maybe_generate_password_reset_key( $userdata );
$mail_args = array(
'fetch_user_id' => $user_id,
'tags' => array(
'{password_reset_link}',
),
'tags_replace' => array(
UM()->password()->reset_url( $user_id ),
),
UM()->maybe_action_scheduler()->enqueue_async_action(
'um_dispatch_email',
array(
$userdata->user_email,
'resetpw_email',
array(
'fetch_user_id' => $user_id,
'tags' => array(
'{password_reset_link}',
),
'tags_replace' => array(
UM()->password()->reset_url( $user_id ),
),
),
)
);
UM()->maybe_action_scheduler()->enqueue_async_action( 'um_dispatch_email', array( $userdata->user_email, 'resetpw_email', $mail_args ) );
}
/**
@@ -2121,30 +2111,6 @@ if ( ! class_exists( 'um\core\User' ) ) {
return $hash_email_address;
}
/**
* UM Placeholders for activation link in email
*
* @param $placeholders
*
* @return array
*/
public function add_activation_placeholder( $placeholders ) {
$placeholders[] = '{account_activation_link}';
return $placeholders;
}
/**
* UM Replace Placeholders for activation link in email
*
* @param $replace_placeholders
*
* @return array
*/
public function add_activation_replace_placeholder( $replace_placeholders ) {
$replace_placeholders[] = um_user( 'account_activation_link' );
return $replace_placeholders;
}
/**
* Set user's account status
*
@@ -2240,5 +2206,53 @@ if ( ! class_exists( 'um\core\User' ) ) {
_deprecated_function( __METHOD__, '2.8.7', 'UM()->common()->users()->deactivate()' );
UM()->common()->users()->deactivate( um_user( 'ID' ) );
}
/**
* @deprecated 2.10.5
*
* @param WP_User $userdata
*
* @return string|WP_Error
*/
public function maybe_generate_password_reset_key( $userdata ) {
_deprecated_function( __METHOD__, '2.10.5', 'UM()->common()->users()->maybe_generate_password_reset_key()' );
return UM()->common()->users()->maybe_generate_password_reset_key( $userdata );
}
/**
* Set last login for new registered users
*
* @deprecated 2.10.5
*
* @return void
*/
public function set_last_login() {
_deprecated_function( __METHOD__, '2.10.5', 'UM()->common()->users()->set_last_login()' );
UM()->common()->users()->set_last_login( $this->id );
}
/**
* UM Placeholders for activation link in email
* @deprecated 2.10.5
* @param $placeholders
*
* @return array
*/
public function add_activation_placeholder( $placeholders ) {
_deprecated_function( __METHOD__, '2.10.5' );
return $placeholders;
}
/**
* UM Replace Placeholders for activation link in email
* @deprecated 2.10.5
* @param $replace_placeholders
*
* @return array
*/
public function add_activation_replace_placeholder( $replace_placeholders ) {
_deprecated_function( __METHOD__, '2.10.5' );
return $replace_placeholders;
}
}
}
+3 -3
View File
@@ -329,11 +329,11 @@ function um_submit_account_details( $args ) {
}
if ( 'first_name' === $k || 'last_name' === $k || 'user_password' === $k ) {
$v = sanitize_text_field( $v );
$v = sanitize_text_field( strip_shortcodes( $v ) );
} elseif ( 'user_email' === $k ) {
$v = sanitize_email( $v );
$v = sanitize_email( strip_shortcodes( $v ) );
} elseif ( 'hide_in_members' === $k || 'um_show_last_login' === $k ) {
$v = array_map( 'sanitize_text_field', $v );
$v = array_map( 'sanitize_text_field', array_map( 'strip_shortcodes', $v ) );
}
$changes[ $k ] = $v;
+17 -4
View File
@@ -923,6 +923,7 @@ function um_submit_form_errors_hook_( $submitted_data, $form_data ) {
$email_exists = email_exists( $submitted_data[ $key ] );
if ( '' === $submitted_data[ $key ] ) {
// Primary email should be required everytime.
UM()->form()->add_error( $key, __( 'You must provide your email', 'ultimate-member' ) );
} elseif ( 'register' === $mode && $email_exists ) {
UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) );
@@ -936,16 +937,28 @@ function um_submit_form_errors_hook_( $submitted_data, $form_data ) {
break;
}
if ( '' === $submitted_data[ $key ] ) {
if ( ! empty( $array['required'] ) && '' === $submitted_data[ $key ] ) {
UM()->form()->add_error( $key, __( 'You must provide your email', 'ultimate-member' ) );
} elseif ( ! is_email( $submitted_data[ $key ] ) || email_exists( $submitted_data[ $key ] ) ) {
UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) );
} elseif ( 'secondary_user_email' === $key && ! empty( $submitted_data[ $key ] ) && ! empty( $submitted_data['user_email'] ) && $submitted_data[ $key ] === $submitted_data['user_email'] ) {
UM()->form()->add_error( $key, __( 'The secondary email cannot be the same as primary', 'ultimate-member' ) );
} else {
// There we have valid and unique user_email. But need to check in usermeta table for other users.
$users = get_users( 'meta_value=' . $submitted_data[ $key ] );
foreach ( $users as $user ) {
if ( $user->ID !== $submitted_data['user_id'] ) {
$args = array(
'meta_query' => array(
array(
'key' => $key,
'value' => sanitize_email( $submitted_data[ $key ] ),
),
),
);
$the_similar_users = get_users( $args );
foreach ( $the_similar_users as $user ) {
if ( empty( $submitted_data['user_id'] ) || absint( $user->ID ) !== absint( $submitted_data['user_id'] ) ) {
UM()->form()->add_error( $key, __( 'The email you entered is incorrect', 'ultimate-member' ) );
break;
}
}
}
+26 -7
View File
@@ -157,11 +157,9 @@ add_action( 'um_submit_form_errors_hook_logincheck', 'um_submit_form_errors_hook
* @param $user_id
*/
function um_store_lastlogin_timestamp( $user_id ) {
update_user_meta( $user_id, '_um_last_login', current_time( 'mysql', true ) );
// Flush user cache after updating last_login timestamp.
UM()->user()->remove_cache( $user_id );
UM()->common()->users()->set_last_login( $user_id );
}
add_action( 'um_on_login_before_redirect', 'um_store_lastlogin_timestamp', 10, 1 );
add_action( 'um_on_login_before_redirect', 'um_store_lastlogin_timestamp' );
/**
@@ -171,7 +169,7 @@ function um_store_lastlogin_timestamp_( $login ) {
$user = get_user_by( 'login', $login );
if ( false !== $user ) {
um_store_lastlogin_timestamp( $user->ID );
UM()->common()->users()->set_last_login( $user->ID );
$attempts = (int) get_user_meta( $user->ID, 'password_rst_attempts', true );
if ( $attempts ) {
@@ -362,6 +360,27 @@ function um_add_submit_button_to_login( $args ) {
if ( ! isset( $primary_btn_word ) || $primary_btn_word == '' ){
$primary_btn_word = UM()->options()->get( 'login_primary_btn_word' );
}
/**
* Filters the classes applied to the primary button on the login form.
*
* @hook um_login_form_primary_btn_classes
* @since 2.10.5
*
* @param {array} $classes An array of CSS classes applied to the primary button.
* @param {array} $args An array of arguments or configurations used in the login form.
*
* @return {array} Button CSS classes.
*
* @example <caption>Extend the classes applied to the primary button on the login form.</caption>
* function my_custom_classes( $classes, $args ) {
* // Add a new class to the button
* $classes[] = 'new-button-class';
*
* return $classes;
* }
* add_filter( 'um_login_form_primary_btn_classes', 'my_custom_classes', 10, 2 );
*/
$primary_btn_classes = apply_filters( 'um_login_form_primary_btn_classes', array( 'um-button' ), $args );
/**
* UM hook
@@ -426,7 +445,7 @@ function um_add_submit_button_to_login( $args ) {
if ( ! empty( $args['secondary_btn'] ) ) { ?>
<div class="um-left um-half">
<input type="submit" value="<?php esc_attr_e( wp_unslash( $primary_btn_word ), 'ultimate-member' ); ?>" class="um-button" id="um-submit-btn" />
<input type="submit" value="<?php esc_attr_e( wp_unslash( $primary_btn_word ), 'ultimate-member' ); ?>" class="<?php echo esc_attr( implode( ' ', $primary_btn_classes ) ); ?>" id="um-submit-btn" />
</div>
<div class="um-right um-half">
<a href="<?php echo esc_url( $secondary_btn_url ); ?>" class="um-button um-alt">
@@ -437,7 +456,7 @@ function um_add_submit_button_to_login( $args ) {
<?php } else { ?>
<div class="um-center">
<input type="submit" value="<?php esc_attr_e( wp_unslash( $primary_btn_word ), 'ultimate-member' ); ?>" class="um-button" id="um-submit-btn" />
<input type="submit" value="<?php esc_attr_e( wp_unslash( $primary_btn_word ), 'ultimate-member' ); ?>" class="<?php echo esc_attr( implode( ' ', $primary_btn_classes ) ); ?>" id="um-submit-btn" />
</div>
<?php } ?>
+41 -7
View File
@@ -120,15 +120,27 @@ function um_send_registration_notification( $user_id ) {
um_fetch_user( $user_id );
$registration_status = um_user( 'status' );
$email_template = 'pending' !== $registration_status ? 'notification_new_user' : 'notification_review';
$sending_args = array(
'admin' => true,
'fetch_user_id' => $user_id,
'tags' => array(
'{submitted_registration}',
),
'tags_replace' => um_user_submitted_registration_formatted(),
);
$emails = um_multi_admin_email();
if ( ! empty( $emails ) ) {
foreach ( $emails as $email ) {
if ( 'pending' !== $registration_status ) {
UM()->maybe_action_scheduler()->enqueue_async_action( 'um_dispatch_email', array( $email, 'notification_new_user', array( 'admin' => true, 'fetch_user_id' => $user_id ) ) );
} else {
UM()->maybe_action_scheduler()->enqueue_async_action( 'um_dispatch_email', array( $email, 'notification_review', array( 'admin' => true, 'fetch_user_id' => $user_id ) ) );
}
UM()->maybe_action_scheduler()->enqueue_async_action(
'um_dispatch_email',
array(
$email,
$email_template,
$sending_args,
)
);
}
}
}
@@ -597,6 +609,28 @@ function um_add_submit_button_to_register( $args ) {
$primary_btn_word = UM()->options()->get( 'register_primary_btn_word' );
}
/**
* Filters the classes applied to the primary button on the registration form.
*
* @hook um_register_form_primary_btn_classes
* @since 2.10.5
*
* @param {array} $classes An array of CSS classes applied to the primary button.
* @param {array} $args An array of arguments or configurations used in the registration form.
*
* @return {array} Button CSS classes.
*
* @example <caption>Extend the classes applied to the primary button on the registration form.</caption>
* function my_custom_classes( $classes, $args ) {
* // Add a new class to the button
* $classes[] = 'new-button-class';
*
* return $classes;
* }
* add_filter( 'um_register_form_primary_btn_classes', 'my_custom_classes', 10, 2 );
*/
$primary_btn_classes = apply_filters( 'um_register_form_primary_btn_classes', array( 'um-button' ), $args );
$secondary_btn_word = $args['secondary_btn_word'];
/**
* UM hook
@@ -656,7 +690,7 @@ function um_add_submit_button_to_register( $args ) {
<?php if ( ! empty( $args['secondary_btn'] ) ) { ?>
<div class="um-left um-half">
<input type="submit" value="<?php esc_attr_e( wp_unslash( $primary_btn_word ), 'ultimate-member' ) ?>" class="um-button" id="um-submit-btn" />
<input type="submit" value="<?php esc_attr_e( wp_unslash( $primary_btn_word ), 'ultimate-member' ) ?>" class="<?php echo esc_attr( implode( ' ', $primary_btn_classes ) ); ?>" id="um-submit-btn" />
</div>
<div class="um-right um-half">
<a href="<?php echo esc_url( $secondary_btn_url ); ?>" class="um-button um-alt">
@@ -667,7 +701,7 @@ function um_add_submit_button_to_register( $args ) {
<?php } else { ?>
<div class="um-center">
<input type="submit" value="<?php esc_attr_e( wp_unslash( $primary_btn_word ), 'ultimate-member' ) ?>" class="um-button" id="um-submit-btn" />
<input type="submit" value="<?php esc_attr_e( wp_unslash( $primary_btn_word ), 'ultimate-member' ) ?>" class="<?php echo esc_attr( implode( ' ', $primary_btn_classes ) ); ?>" id="um-submit-btn" />
</div>
<?php } ?>
+3 -29
View File
@@ -208,7 +208,7 @@ function um_convert_tags( $content, $args = array(), $with_kses = true ) {
// Support for all usermeta keys
if ( ! empty( $matches[1] ) && is_array( $matches[1] ) ) {
foreach ( $matches[1] as $match ) {
$key = str_replace( 'usermeta:', '', $match );
$key = str_replace( 'usermeta:', '', $match );
$value = um_user( $key );
if ( is_array( $value ) ) {
$value = implode( ', ', $value );
@@ -219,32 +219,6 @@ function um_convert_tags( $content, $args = array(), $with_kses = true ) {
return $content;
}
/**
* UM Placeholders for activation link in email
*
* @param $placeholders
*
* @return array
*/
function account_activation_link_tags_patterns( $placeholders ) {
$placeholders[] = '{account_activation_link}';
return $placeholders;
}
/**
* UM Replace Placeholders for activation link in email
*
* @param $replace_placeholders
*
* @return array
*/
function account_activation_link_tags_replaces( $replace_placeholders ) {
$replace_placeholders[] = um_user( 'account_activation_link' );
return $replace_placeholders;
}
/**
* @function um_user_ip()
*
@@ -2583,12 +2557,12 @@ function um_user( $data, $attrs = null ) {
break;
case 'password_reset_link':
// Avoid using and make it directly with `UM()->password()->reset_url( $user_id )`
return UM()->password()->reset_url();
break;
case 'account_activation_link':
// Avoid using and make it directly with `UM()->permalinks()->activate_url( $user_id )`
return UM()->permalinks()->activate_url();
break;
case 'profile_photo':
$data = um_get_user_avatar_data( um_user( 'ID' ), $attrs );
+26 -1
View File
@@ -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.4
Stable tag: 2.10.5
License: GPLv3
License URI: http://www.gnu.org/licenses/gpl-3.0.txt
@@ -167,6 +167,31 @@ 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.5 2025-06-25 =
**Enhancements**
* Added: Filter hooks for primary button classes in UM forms.
* Tweak: Refactored Site Health data, added hooks for 3rd-party integration.
**Bugfixes**
* Fixed: Stripped shortcodes in the user data during the Account, Registration and Profile forms submission. (Thanks to [MissVeronica](https://github.com/MissVeronica))
* Fixed: Email placeholders values.
* Fixed: Refactor deactivation logic to un-schedule Action Scheduler actions.
* Fixed: Action Scheduler library errors. Updated to the recent 3.9.2 version.
* Fixed: Secondary email field validation.
* Fixed: Action Scheduler batch actions with users who have Undefined status.
* Fixed: Restrictions for 3rd-party Gutenberg Blocks.
* Fixed: Date/time picker filter-types range query on Member Directories.
* Fixed: Renamed "Macedonia, the former Yugoslav Republic of" to the official "North Macedonia".
**Templates required update**
* password-reset.php
**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade**
= 2.10.4 2025-05-15 =
**Bugfixes**
+38 -13
View File
@@ -6,17 +6,18 @@
*
* Call: function ultimatemember_password()
*
* @version 2.7.0
* @version 2.10.5
*
* @var string $mode
* @var int $form_id
* @var array $args
*
* phpcs:disable WordPress.Security.NonceVerification
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
?>
<div class="um <?php echo esc_attr( $this->get_class( $mode ) ); ?> um-<?php echo esc_attr( $form_id ); ?>">
<div class="um-form">
<form method="post" action="">
@@ -62,19 +63,24 @@ if ( ! defined( 'ABSPATH' ) ) {
*/
do_action( 'um_reset_password_page_hidden_fields', $args );
if ( ! empty( $_GET['updated'] ) ) { ?>
if ( ! empty( $_GET['updated'] ) ) {
?>
<div class="um-field um-field-block um-field-type_block">
<div class="um-field-block">
<div style="text-align:center;">
<?php if ( 'expiredkey' === sanitize_key( $_GET['updated'] ) ) {
<?php
if ( 'expiredkey' === sanitize_key( $_GET['updated'] ) ) {
esc_html_e( 'Your password reset link has expired. Please request a new link below.', 'ultimate-member' );
} elseif ( 'invalidkey' === sanitize_key( $_GET['updated'] ) ) {
esc_html_e( 'Your password reset link appears to be invalid. Please request a new link below.', 'ultimate-member' );
} ?>
}
?>
</div>
</div>
</div>
<?php } else { ?>
<?php
} else {
?>
<div class="um-field um-field-block um-field-type_block">
<div class="um-field-block">
<div style="text-align:center;">
@@ -82,7 +88,8 @@ if ( ! defined( 'ABSPATH' ) ) {
</div>
</div>
</div>
<?php }
<?php
}
$fields = UM()->builtin()->get_specific_fields( 'username_b' );
@@ -111,18 +118,36 @@ if ( ! defined( 'ABSPATH' ) ) {
* }
* ?>
*/
do_action( 'um_after_password_reset_fields', $args ); ?>
do_action( 'um_after_password_reset_fields', $args );
/**
* Filters the classes applied to the primary button on the password reset form.
*
* @hook um_password_reset_form_primary_btn_classes
* @since 2.10.5
*
* @param {array} $classes An array of CSS classes applied to the primary button.
* @param {array} $args An array of arguments or configurations used in the password reset form.
*
* @return {array} Button CSS classes.
*
* @example <caption>Extend the classes applied to the primary button on the password reset form.</caption>
* function my_custom_classes( $classes, $args ) {
* // Add a new class to the button
* $classes[] = 'new-button-class';
*
* return $classes;
* }
* add_filter( 'um_password_reset_form_primary_btn_classes', 'my_custom_classes', 10, 2 );
*/
$primary_btn_classes = apply_filters( 'um_password_reset_form_primary_btn_classes', array( 'um-button' ), $args );
?>
<div class="um-col-alt um-col-alt-b">
<div class="um-center">
<input type="submit" value="<?php esc_attr_e( 'Reset password', 'ultimate-member' ); ?>" class="um-button" id="um-submit-btn" />
<input type="submit" value="<?php esc_attr_e( 'Reset password', 'ultimate-member' ); ?>" class="<?php echo esc_attr( implode( ' ', $primary_btn_classes ) ); ?>" id="um-submit-btn" />
</div>
<div class="um-clear"></div>
</div>
<?php
/**
* UM hook
+3 -1
View File
@@ -3,9 +3,11 @@
* 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.4
* Version: 2.10.5
* Author: Ultimate Member
* Author URI: http://ultimatemember.com/
* License: GPLv3
* License URI: http://www.gnu.org/licenses/gpl-3.0.txt
* Text Domain: ultimate-member
* Domain Path: /languages
* Requires at least: 6.2