mirror of
https://github.com/10h30/ultimatemember.git
synced 2026-07-16 21:23:39 +09:00
Merge pull request #1661 from ultimatemember/development/2.9.x
Version 2.10.2
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
"step": "installPlugin",
|
||||
"pluginZipFile": {
|
||||
"resource": "url",
|
||||
"url": "https:\/\/downloads.wordpress.org\/plugin\/ultimate-member.2.10.1.zip"
|
||||
"url": "https:\/\/downloads.wordpress.org\/plugin\/ultimate-member.2.10.2.zip"
|
||||
},
|
||||
"options": {
|
||||
"activate": true
|
||||
|
||||
@@ -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.1](https://github.com/ultimatemember/ultimatemember/releases/tag/2.10.1).
|
||||
[Official Release Version: 2.10.2](https://github.com/ultimatemember/ultimatemember/releases/tag/2.10.2).
|
||||
|
||||
## Changelog
|
||||
|
||||
|
||||
@@ -1,5 +1,16 @@
|
||||
== Changelog ==
|
||||
|
||||
= 2.10.2 April 02, 2025 =
|
||||
|
||||
* Enhancements:
|
||||
|
||||
- Added: `UM()->common()-filesystem()::maybe_init_wp_filesystem();` method.
|
||||
- Added: `UM()->common()-filesystem()::remove_dir();` method.
|
||||
|
||||
* Bugfixes:
|
||||
|
||||
- Fixed: Security issue CVE ID: CVE-2025-1702. Reviewed general search scripts and suggested another solution that uses only `$wpdb->prepare()`.
|
||||
|
||||
= 2.10.1 March 03, 2025 =
|
||||
|
||||
* Bugfixes:
|
||||
|
||||
@@ -151,7 +151,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) {
|
||||
}
|
||||
|
||||
$skip_fields = UM()->builtin()->get_fields_without_metakey();
|
||||
$skip_fields = array_merge( $skip_fields, UM()->member_directory()->core_search_fields );
|
||||
$skip_fields = array_merge( $skip_fields, UM()->member_directory()::$core_search_fields );
|
||||
|
||||
$real_usermeta = $wpdb->get_col( "SELECT DISTINCT meta_key FROM {$wpdb->usermeta}" );
|
||||
$real_usermeta = ! empty( $real_usermeta ) ? $real_usermeta : array();
|
||||
|
||||
@@ -59,6 +59,13 @@ class Filesystem {
|
||||
$this->temp_upload_url = $this->get_upload_url( 'ultimatemember/temp' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Files Age in the temp folder. By default, it's 24 hours.
|
||||
*
|
||||
* @return int Temp file age in seconds.
|
||||
* @since 2.8.7
|
||||
*
|
||||
*/
|
||||
public function files_age() {
|
||||
/**
|
||||
* Filters the maximum file age in the temp folder. By default, it's 24 hours.
|
||||
@@ -73,6 +80,17 @@ class Filesystem {
|
||||
return apply_filters( 'um_filesystem_max_file_age', 24 * HOUR_IN_SECONDS ); // Temp file age in seconds
|
||||
}
|
||||
|
||||
/**
|
||||
* Image MIME Types
|
||||
*
|
||||
* Retrieves a list of image MIME types based on the context.
|
||||
*
|
||||
* @param string $context The context in which the MIME types are needed ('list' or 'allowed').
|
||||
*
|
||||
* @return array List of image MIME types based on the context.
|
||||
*
|
||||
* @since 2.8.7
|
||||
*/
|
||||
public static function image_mimes( $context = 'list' ) {
|
||||
$mimes = array();
|
||||
|
||||
@@ -148,12 +166,7 @@ class Filesystem {
|
||||
public function clear_temp_dir() {
|
||||
global $wp_filesystem;
|
||||
|
||||
if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
|
||||
$credentials = request_filesystem_credentials( site_url() );
|
||||
WP_Filesystem( $credentials );
|
||||
}
|
||||
self::maybe_init_wp_filesystem();
|
||||
|
||||
if ( ! $wp_filesystem->is_dir( $this->temp_upload_dir ) ) {
|
||||
return;
|
||||
@@ -197,12 +210,7 @@ class Filesystem {
|
||||
// Please add define('FS_METHOD', 'direct'); to avoid question about FTP.
|
||||
global $wp_filesystem;
|
||||
|
||||
if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
|
||||
$credentials = request_filesystem_credentials( site_url() );
|
||||
WP_Filesystem( $credentials );
|
||||
}
|
||||
self::maybe_init_wp_filesystem();
|
||||
|
||||
if ( ! $blog_id ) {
|
||||
$blog_id = get_current_blog_id();
|
||||
@@ -290,4 +298,46 @@ class Filesystem {
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Probably define global $wp_filesystem.
|
||||
*
|
||||
* @since 2.10.2
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function maybe_init_wp_filesystem() {
|
||||
global $wp_filesystem;
|
||||
|
||||
// If you need to fix this issue on the localhost
|
||||
// https://stackoverflow.com/questions/30688431/wordpress-needs-the-ftp-credentials-to-update-plugins
|
||||
// Please add define('FS_METHOD', 'direct'); to avoid question about FTP.
|
||||
if ( ! $wp_filesystem instanceof WP_Filesystem_Base ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||
|
||||
$credentials = request_filesystem_credentials( site_url() );
|
||||
WP_Filesystem( $credentials );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a directory using WP Filesystem.
|
||||
*
|
||||
* @param string $dir The directory path to be removed. Should end with DIRECTORY_SEPARATOR.
|
||||
*
|
||||
* @return bool True on success, false on failure or if directory doesn't exist.
|
||||
*
|
||||
* @since 2.10.2
|
||||
*/
|
||||
public static function remove_dir( $dir ) {
|
||||
global $wp_filesystem;
|
||||
|
||||
self::maybe_init_wp_filesystem();
|
||||
|
||||
if ( ! $wp_filesystem->is_dir( $dir ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $wp_filesystem->delete( $dir, true );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,6 +216,8 @@ class Users {
|
||||
/**
|
||||
* Reset User cache
|
||||
*
|
||||
* @since 2.8.7
|
||||
*
|
||||
* @param int $user_id User ID.
|
||||
*/
|
||||
public function remove_cache( $user_id ) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace um\core;
|
||||
|
||||
use Exception;
|
||||
use WP_User_Query;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
@@ -70,7 +71,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
var $core_search_fields = array(
|
||||
public static $core_search_fields = array(
|
||||
'user_login',
|
||||
'user_url',
|
||||
'display_name',
|
||||
@@ -127,9 +128,35 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
|
||||
/**
|
||||
* Get the WordPress core searching fields in wp_users query.
|
||||
* @since 2.6.10
|
||||
* @version 2.10.2
|
||||
* @param array|null $qv WP_User_Query variables.
|
||||
* @param string|null $search Search line value.
|
||||
* @return array
|
||||
*/
|
||||
protected function get_core_search_fields() {
|
||||
protected function get_core_search_fields( $qv = null, $search = null ) {
|
||||
$search_columns = array();
|
||||
if ( ! is_null( $qv ) && ! empty( $search ) ) {
|
||||
// WordPress native code from wp-includes/class-wp-user-query.php is below in this condition.
|
||||
if ( $qv['search_columns'] ) {
|
||||
$search_columns = array_intersect( $qv['search_columns'], array( 'ID', 'user_login', 'user_email', 'user_url', 'user_nicename', 'display_name' ) );
|
||||
}
|
||||
if ( ! $search_columns ) {
|
||||
if ( str_contains( $search, '@' ) ) {
|
||||
$search_columns = array( 'user_email' );
|
||||
} elseif ( is_numeric( $search ) ) {
|
||||
$search_columns = array( 'user_login', 'ID' );
|
||||
} elseif ( preg_match( '|^https?://|', $search ) && ! ( is_multisite() && wp_is_large_network( 'users' ) ) ) {
|
||||
$search_columns = array( 'user_url' );
|
||||
} else {
|
||||
$search_columns = array( 'user_login', 'user_url', 'user_email', 'user_nicename', 'display_name' );
|
||||
}
|
||||
}
|
||||
/** This filter is documented in wp-includes/class-wp-user-query.php */
|
||||
$search_columns = apply_filters( 'user_search_columns', $search_columns, $search, $this );
|
||||
} else {
|
||||
$search_columns = self::$core_search_fields;
|
||||
}
|
||||
/**
|
||||
* Filters the WordPress core searching fields in wp_users query for UM Member directory query.
|
||||
*
|
||||
@@ -149,7 +176,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
* }
|
||||
* 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 apply_filters( 'um_member_directory_core_search_fields', $search_columns );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -456,7 +483,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
if ( ! empty( UM()->builtin()->all_user_fields() ) ) {
|
||||
foreach ( UM()->builtin()->all_user_fields() as $key => $data ) {
|
||||
if ( in_array( $key, $core_search_keys, true ) ) {
|
||||
if ( isset( $data['title'] ) && array_search( $data['title'], $this->searching_fields, true ) !== false ) {
|
||||
if ( isset( $data['title'] ) && in_array( $data['title'], $this->searching_fields, true ) ) {
|
||||
$data['title'] = $data['title'] . ' (' . $key . ')';
|
||||
}
|
||||
|
||||
@@ -1705,27 +1732,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
if ( empty( $search ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Make the search line empty if it contains the mySQL query statements.
|
||||
$regexp_map = array(
|
||||
'/select(.*?)from/im',
|
||||
'/select(.*?)sleep/im',
|
||||
"/sleep\(\d+\)/im", // avoid any sleep injections
|
||||
'/select(.*?)database/im',
|
||||
'/select(.*?)where/im',
|
||||
'/update(.*?)set/im',
|
||||
'/delete(.*?)from/im',
|
||||
);
|
||||
|
||||
foreach ( $regexp_map as $regexp ) {
|
||||
preg_match( $regexp, $search, $matches );
|
||||
if ( ! empty( $matches ) ) {
|
||||
$search = '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Early escape of the search line. The same as `$wpdb->prepare()`.
|
||||
return esc_sql( $search );
|
||||
return $search;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1737,155 +1744,18 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
// complex using with change_meta_sql function
|
||||
$search = $this->prepare_search( $_POST['search'] );
|
||||
if ( ! empty( $search ) ) {
|
||||
$meta_query = array(
|
||||
'relation' => 'OR',
|
||||
array(
|
||||
'value' => $search,
|
||||
'compare' => '=',
|
||||
),
|
||||
array(
|
||||
'value' => $search,
|
||||
'compare' => 'LIKE',
|
||||
),
|
||||
array(
|
||||
'value' => serialize( (string) $search ),
|
||||
'compare' => 'LIKE',
|
||||
),
|
||||
);
|
||||
|
||||
$meta_query = array();
|
||||
$meta_query = apply_filters( 'um_member_directory_general_search_meta_query', $meta_query, $search );
|
||||
|
||||
$this->query_args['meta_query'][] = $meta_query;
|
||||
if ( ! empty( $meta_query ) ) {
|
||||
$this->query_args['meta_query'][] = $meta_query;
|
||||
}
|
||||
|
||||
$this->is_search = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change mySQL meta query join attribute
|
||||
* for search only by UM user meta fields and WP core fields in WP Users table
|
||||
*
|
||||
* @param array $sql Array containing the query's JOIN and WHERE clauses.
|
||||
* @param $queries
|
||||
* @param $type
|
||||
* @param $primary_table
|
||||
* @param $primary_id_column
|
||||
* @param WP_User_Query $context
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function change_meta_sql( $sql, $queries, $type, $primary_table, $primary_id_column, $context ) {
|
||||
if ( ! empty( $_POST['search'] ) ) {
|
||||
$search = $this->prepare_search( $_POST['search'] );
|
||||
if ( ! empty( $search ) ) {
|
||||
global $wpdb;
|
||||
|
||||
$meta_value = '%' . $wpdb->esc_like( $search ) . '%';
|
||||
$search_meta = $wpdb->prepare( '%s', $meta_value );
|
||||
|
||||
preg_match( '~(?<=\{)(.*?)(?=\})~', $search_meta, $matches, PREG_OFFSET_CAPTURE, 0 );
|
||||
|
||||
// workaround for standard mySQL hashes which are used by $wpdb->prepare instead of the %symbol
|
||||
// sometimes it breaks error for strings like that wp_postmeta.meta_value LIKE '{12f209b48a89eeab33424902879d05d503f251ca8812dde03b59484a2991dc74}AMS{12f209b48a89eeab33424902879d05d503f251ca8812dde03b59484a2991dc74}'
|
||||
// {12f209b48a89eeab33424902879d05d503f251ca8812dde03b59484a2991dc74} isn't applied by the `preg_replace()` below
|
||||
if ( $matches[0][0] ) {
|
||||
$search_meta = str_replace( '{' . $matches[0][0] . '}', '#%&', $search_meta );
|
||||
$sql['where'] = str_replace( '{' . $matches[0][0] . '}', '#%&', $sql['where'] );
|
||||
}
|
||||
|
||||
// str_replace( '/', '\/', wp_slash( $search_meta ) ) means that we add backslashes to special symbols + add backslash to slash(/) symbol for proper regular pattern.
|
||||
preg_match(
|
||||
'/^(.*).meta_value LIKE ' . str_replace( '/', '\/', wp_slash( $search_meta ) ) . '[^\)]/im',
|
||||
$sql['where'],
|
||||
$join_matches
|
||||
);
|
||||
|
||||
$sql['where'] = str_replace( '#%&', '{' . $matches[0][0] . '}', $sql['where'] );
|
||||
|
||||
$directory_id = $this->get_directory_by_hash( sanitize_key( $_POST['directory_id'] ) );
|
||||
$exclude_fields = get_post_meta( $directory_id, '_um_search_exclude_fields', true );
|
||||
$include_fields = get_post_meta( $directory_id, '_um_search_include_fields', true );
|
||||
|
||||
if ( isset( $join_matches[1] ) ) {
|
||||
$meta_join_for_search = trim( $join_matches[1] );
|
||||
|
||||
// skip private invisible fields
|
||||
$custom_fields = array();
|
||||
if ( empty( $include_fields ) ) {
|
||||
foreach ( array_keys( UM()->builtin()->all_user_fields ) as $field_key ) {
|
||||
if ( empty( $field_key ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = UM()->fields()->get_field( $field_key );
|
||||
if ( ! um_can_view_field( $data ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$custom_fields[] = $field_key;
|
||||
}
|
||||
} else {
|
||||
foreach ( $include_fields as $field_key ) {
|
||||
if ( empty( $field_key ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = UM()->fields()->get_field( $field_key );
|
||||
if ( ! um_can_view_field( $data ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$custom_fields[] = $field_key;
|
||||
}
|
||||
}
|
||||
|
||||
$custom_fields = apply_filters( 'um_general_search_custom_fields', $custom_fields );
|
||||
|
||||
if ( ! empty( $custom_fields ) ) {
|
||||
if ( ! empty( $exclude_fields ) ) {
|
||||
$custom_fields = array_diff( $custom_fields, $exclude_fields );
|
||||
}
|
||||
|
||||
$sql['join'] = preg_replace(
|
||||
'/(' . $meta_join_for_search . ' ON \( ' . $wpdb->users . '\.ID = ' . $meta_join_for_search . '\.user_id )(\))/im',
|
||||
"$1 AND " . $meta_join_for_search . ".meta_key IN( '" . implode( "','", $custom_fields ) . "' ) $2",
|
||||
$sql['join']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$core_search = $this->get_core_search_fields();
|
||||
if ( ! empty( $include_fields ) ) {
|
||||
$core_search = array_intersect( $core_search, $include_fields );
|
||||
}
|
||||
if ( ! empty( $exclude_fields ) ) {
|
||||
$core_search = array_diff( $core_search, $exclude_fields );
|
||||
}
|
||||
|
||||
if ( ! empty( $core_search ) ) {
|
||||
// Add OR instead AND to search in WP core fields user_email, user_login, user_display_name
|
||||
$search_where = $context->get_search_sql( $search, $core_search, 'both' );
|
||||
|
||||
$search_where = preg_replace( '/ AND \((.*?)\)/im', "$1 OR", $search_where );
|
||||
|
||||
// str_replace( '/', '\/', wp_slash( $search ) ) means that we add backslashes to special symbols + add backslash to slash(/) symbol for proper regular pattern.
|
||||
$pattern = $wpdb->prepare( $meta_join_for_search . '.meta_value = %s', $search );
|
||||
$pattern = '/(' . str_replace( '/', '\/', wp_slash( $pattern ) ) . ')/im';
|
||||
|
||||
$sql['where'] = preg_replace(
|
||||
$pattern,
|
||||
trim( $search_where ) . " $1",
|
||||
$sql['where'],
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle filters request
|
||||
*/
|
||||
@@ -2778,16 +2648,15 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
return $data_array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update limit query
|
||||
*
|
||||
* @param $user_query
|
||||
* @param WP_User_Query $user_query
|
||||
*/
|
||||
function pagination_changes( $user_query ) {
|
||||
public function pagination_changes( $user_query ) {
|
||||
global $wpdb;
|
||||
|
||||
$directory_id = $this->get_directory_by_hash( sanitize_key( $_POST['directory_id'] ) );
|
||||
$directory_id = $this->get_directory_by_hash( sanitize_key( $_POST['directory_id'] ) );
|
||||
$directory_data = UM()->query()->post_data( $directory_id );
|
||||
|
||||
$qv = $user_query->query_vars;
|
||||
@@ -2807,6 +2676,102 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update search query
|
||||
*
|
||||
* @param WP_User_Query $user_query
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function search_changes( $user_query ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( ! empty( $_POST['search'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification -- already verified here
|
||||
$search = $this->prepare_search( $_POST['search'] ); // phpcs:ignore WordPress.Security.NonceVerification -- already verified here
|
||||
if ( empty( $search ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$directory_id = null;
|
||||
if ( ! empty( $_POST['directory_id'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification -- already verified here
|
||||
$directory_id = $this->get_directory_by_hash( sanitize_key( $_POST['directory_id'] ) ); // phpcs:ignore WordPress.Security.NonceVerification -- already verified here
|
||||
}
|
||||
|
||||
$qv = $user_query->query_vars;
|
||||
|
||||
$exclude_fields = array();
|
||||
$include_fields = array_keys( UM()->builtin()->all_user_fields );
|
||||
if ( ! empty( $directory_id ) ) {
|
||||
$exclude_fields = get_post_meta( $directory_id, '_um_search_exclude_fields', true );
|
||||
$include_fields = get_post_meta( $directory_id, '_um_search_include_fields', true );
|
||||
|
||||
$exclude_fields = ! empty( $exclude_fields ) && is_array( $exclude_fields ) ? $exclude_fields : array();
|
||||
$include_fields = ! empty( $include_fields ) && is_array( $include_fields ) ? $include_fields : array_keys( UM()->builtin()->all_user_fields );
|
||||
}
|
||||
|
||||
$custom_fields = array();
|
||||
foreach ( $include_fields as $field_key ) {
|
||||
if ( empty( $field_key ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = UM()->fields()->get_field( $field_key );
|
||||
if ( isset( $data['type'] ) && 'password' === $data['type'] ) {
|
||||
continue;
|
||||
}
|
||||
if ( isset( $data['metakey'] ) && in_array( $data['metakey'], array( 'role_select', 'role_radio' ), true ) ) {
|
||||
continue;
|
||||
}
|
||||
if ( ! empty( $data['account_only'] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! um_can_view_field( $data ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$custom_fields[] = $field_key;
|
||||
}
|
||||
|
||||
if ( ! empty( $custom_fields ) && ! empty( $exclude_fields ) ) {
|
||||
$custom_fields = array_diff( $custom_fields, $exclude_fields );
|
||||
}
|
||||
|
||||
$custom_fields = apply_filters( 'um_general_search_custom_fields', $custom_fields );
|
||||
$custom_fields = array_values( array_unique( $custom_fields ) );
|
||||
|
||||
$search_columns = $this->get_core_search_fields( $qv, $search );
|
||||
|
||||
if ( ! empty( $directory_id ) ) {
|
||||
$include_fields = get_post_meta( $directory_id, '_um_search_include_fields', true );
|
||||
if ( ! empty( $include_fields ) ) {
|
||||
$search_columns = array_intersect( $search_columns, $include_fields );
|
||||
}
|
||||
}
|
||||
if ( ! empty( $exclude_fields ) ) {
|
||||
$search_columns = array_diff( $search_columns, $exclude_fields );
|
||||
}
|
||||
|
||||
if ( ! empty( $custom_fields ) ) {
|
||||
$search_columns[] = 'um_search.meta_value';
|
||||
|
||||
$user_query->query_from .= " INNER JOIN {$wpdb->usermeta} AS um_search ON ( {$wpdb->users}.ID = um_search.user_id AND um_search.meta_key IN('" . implode( "','", $custom_fields ) . "'))";
|
||||
}
|
||||
|
||||
if ( ! empty( $search_columns ) ) {
|
||||
$search_where = $user_query->get_search_sql( $search, $search_columns, 'both' );
|
||||
$search_where = apply_filters( 'um_general_search_custom_search_where', $search_where, $user_query, $search );
|
||||
|
||||
$user_query->query_where .= $search_where;
|
||||
}
|
||||
|
||||
// Required `DISTINCT` if not exists, because we add `OR` condition manually.
|
||||
if ( ( ! empty( $custom_fields ) || ! empty( $search_columns ) ) && false === strpos( $user_query->query_fields, 'DISTINCT' ) ) {
|
||||
$user_query->query_fields = 'DISTINCT ' . $user_query->query_fields;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function predefined_no_caps( $directory_data ) {
|
||||
//predefined result for user without capabilities to see other members
|
||||
@@ -2939,16 +2904,13 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
*/
|
||||
do_action( 'um_user_before_query', $this->query_args, $this );
|
||||
|
||||
add_filter( 'get_meta_sql', array( &$this, 'change_meta_sql' ), 10, 6 );
|
||||
|
||||
add_filter( 'pre_user_query', array( &$this, 'pagination_changes' ), 10, 1 );
|
||||
add_action( 'pre_user_query', array( &$this, 'search_changes' ) );
|
||||
add_action( 'pre_user_query', array( &$this, 'pagination_changes' ) );
|
||||
|
||||
$user_query = new WP_User_Query( $this->query_args );
|
||||
|
||||
remove_filter( 'pre_user_query', array( &$this, 'pagination_changes' ), 10 );
|
||||
|
||||
remove_filter( 'get_meta_sql', array( &$this, 'change_meta_sql' ), 10 );
|
||||
|
||||
remove_action( 'pre_user_query', array( &$this, 'search_changes' ) );
|
||||
remove_action( 'pre_user_query', array( &$this, 'pagination_changes' ) );
|
||||
/**
|
||||
* Fires just after the users query for getting users in member directory.
|
||||
*
|
||||
|
||||
+15
-1
@@ -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.7
|
||||
Stable tag: 2.10.1
|
||||
Stable tag: 2.10.2
|
||||
License: GPLv3
|
||||
License URI: http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
|
||||
@@ -167,6 +167,17 @@ 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.2 2025-04-02 =
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Added: `UM()->common()-filesystem()::maybe_init_wp_filesystem();` method.
|
||||
* Added: `UM()->common()-filesystem()::remove_dir();` method.
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: Security issue CVE ID: CVE-2025-1702. Reviewed general search scripts and suggested another solution that uses only `$wpdb->prepare()`.
|
||||
|
||||
= 2.10.1 2025-03-03 =
|
||||
|
||||
**Bugfixes**
|
||||
@@ -278,6 +289,9 @@ IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSI
|
||||
|
||||
== Upgrade Notice ==
|
||||
|
||||
= 2.10.2 =
|
||||
This version fixes a security related bug. Upgrade immediately.
|
||||
|
||||
= 2.10.1 =
|
||||
This version fixes a security related bug. Upgrade immediately.
|
||||
|
||||
|
||||
+1
-1
@@ -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.1
|
||||
* Version: 2.10.2
|
||||
* Author: Ultimate Member
|
||||
* Author URI: http://ultimatemember.com/
|
||||
* Text Domain: ultimate-member
|
||||
|
||||
Reference in New Issue
Block a user