2019-08-14 10:54:16 +03:00
< ? php
namespace um\core ;
2025-03-25 23:31:13 +02:00
use Exception ;
2025-12-11 17:36:42 +02:00
use WP_Post ;
2025-02-28 12:13:15 +02:00
use WP_User_Query ;
2023-06-12 13:20:00 +03:00
if ( ! defined ( 'ABSPATH' ) ) {
exit ;
}
2019-08-14 10:54:16 +03:00
if ( ! class_exists ( 'um\core\Member_Directory' ) ) {
/**
* Class Member_Directory
* @package um\core
*/
class Member_Directory {
/**
* Member Directory Views
*
* @var array
*/
var $view_types = array ();
/**
* @var array
*/
var $sort_fields = array ();
2023-06-12 13:20:00 +03:00
/**
* @var array
*/
var $sort_data_types = array ();
2019-08-14 10:54:16 +03:00
/**
* @var array
*/
var $default_sorting = array ();
/**
* @var array
*/
var $filter_fields = array ();
2024-04-09 13:55:39 +03:00
/**
* @var array
*/
public $searching_fields = array ();
2019-08-14 10:54:16 +03:00
2019-10-01 11:53:34 +03:00
/**
* @var array
*/
var $custom_filters_in_query = array ();
2019-08-14 10:54:16 +03:00
var $filter_supported_fields = array ();
2022-06-09 17:17:15 +03:00
var $sorting_supported_fields = array ();
2019-11-20 17:07:38 +02:00
var $filter_types = array ();
2019-09-02 16:35:10 +03:00
2024-02-14 17:12:35 +02:00
/**
* Fields used for searching from wp_users table.
*
* @var string[]
*/
2025-03-25 23:31:13 +02:00
public static $core_search_fields = array (
2019-09-02 16:35:10 +03:00
'user_login' ,
'user_url' ,
'display_name' ,
'user_email' ,
'user_nicename' ,
2019-08-14 10:54:16 +03:00
);
2024-02-14 17:12:35 +02:00
/**
* Fields used for sorting from wp_users table.
*
* @var string[]
*/
var $core_users_fields = array (
'user_login' ,
'user_url' ,
'display_name' ,
'user_email' ,
'user_nicename' ,
'user_registered' ,
);
2019-08-14 10:54:16 +03:00
2019-08-16 19:42:18 +03:00
/**
* @var
*/
var $query_args ;
2019-09-02 16:35:10 +03:00
/**
* @var User Card cover size
*/
var $cover_size ;
/**
* @var User Avatar size
*/
var $avatar_size ;
2019-11-20 17:07:38 +02:00
/**
* @var bool Searching marker
*/
var $is_search = false ;
2019-08-14 10:54:16 +03:00
/**
* Member_Directory constructor.
*/
2023-08-10 16:14:31 +03:00
public function __construct () {
2022-06-09 17:31:49 +03:00
add_filter ( 'init' , array ( & $this , 'init_variables' ) );
2019-09-02 16:35:10 +03:00
2025-12-11 17:36:42 +02:00
add_action ( 'wp_insert_post' , array ( & $this , 'set_token' ), 10 , 3 );
2019-09-02 16:35:10 +03:00
add_action ( 'template_redirect' , array ( & $this , 'access_members' ), 555 );
}
2025-12-11 17:36:42 +02:00
/**
* Set member directory token as soon as it's created.
*
* @param int $post_ID
* @param WP_Post $post
* @param bool $update
*
* @return void
*/
public function set_token ( $post_ID , $post , $update ) {
if ( 'um_directory' === $post -> post_type && ! $update ) {
$this -> set_directory_hash ( $post_ID );
}
}
/**
* Check if the user can view the member directory.
*
* @param int $directory_id
* @param int|null $user_id
*
* @return bool
*/
public function can_view_directory ( $directory_id , $user_id = null ) {
if ( is_null ( $user_id ) && is_user_logged_in () ) {
$user_id = get_current_user_id ();
}
$can_view = false ;
$privacy = get_post_meta ( $directory_id , '_um_privacy' , true );
if ( '' === $privacy ) {
$can_view = true ;
} else {
$privacy = absint ( $privacy );
switch ( $privacy ) {
case 0 :
$can_view = true ;
break ;
case 1 :
if ( ! is_user_logged_in () ) {
$can_view = true ;
}
break ;
case 2 :
if ( is_user_logged_in () ) {
$can_view = true ;
}
break ;
case 3 :
if ( is_user_logged_in () ) {
$privacy_roles = get_post_meta ( $directory_id , '_um_privacy_roles' , true );
$privacy_roles = ! empty ( $privacy_roles ) && is_array ( $privacy_roles ) ? $privacy_roles : array ();
$current_user_roles = um_user ( 'roles' );
if ( ! empty ( $current_user_roles ) && count ( array_intersect ( $current_user_roles , $privacy_roles ) ) > 0 ) {
$can_view = true ;
}
}
break ;
}
}
return apply_filters ( 'um_directory_user_can_view' , $can_view , $directory_id , $user_id );
}
2023-08-10 16:14:31 +03:00
/**
* Get the WordPress core searching fields in wp_users query.
2025-12-11 17:36:42 +02:00
*
2025-03-25 23:31:13 +02:00
* @since 2.6.10
* @version 2.10.2
* @param array|null $qv WP_User_Query variables.
* @param string|null $search Search line value.
2023-08-10 16:14:31 +03:00
* @return array
*/
2025-03-25 23:31:13 +02:00
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 ;
}
2023-08-10 16:14:31 +03:00
/**
* Filters the WordPress core searching fields in wp_users query for UM Member directory query.
*
* @param {array} $core_search_fields Core search fields in wp_users query.
*
* @return {array} Core search fields in wp_users query.
*
* @since 2.6.10
* @hook um_member_directory_core_search_fields
*
* @example <caption>Extends or remove wp_users core search fields.</caption>
* function my_um_member_directory_core_search_fields( $core_search_fields ) {
* $core_search_fields = array_flip( $core_search_fields );
* unset( $core_search_fields['user_email'] );
* $core_search_fields = array_flip( $core_search_fields );
* return $core_search_fields;
* }
* add_filter( 'um_member_directory_core_search_fields', 'my_um_member_directory_core_search_fields' );
*/
2025-03-25 23:31:13 +02:00
return apply_filters ( 'um_member_directory_core_search_fields' , $search_columns );
2023-08-10 16:14:31 +03:00
}
2019-09-02 16:35:10 +03:00
2020-01-14 22:22:11 +02:00
/**
* @return bool
*/
function get_hide_in_members_default () {
2020-01-14 23:48:33 +02:00
$default = false ;
$option = UM () -> options () -> get ( 'account_hide_in_directory_default' );
if ( $option == 'Yes' ) {
$default = true ;
}
$default = apply_filters ( 'um_member_directory_hide_in_members_default' , $default );
2020-01-14 22:22:11 +02:00
return $default ;
}
2019-09-02 16:35:10 +03:00
/**
* Getting member directory post ID via hash
* Hash is unique attr, which we use visible at frontend
*
* @param string $hash
*
* @return bool|int
*/
2025-12-11 17:36:42 +02:00
public function get_directory_by_hash ( $hash ) {
2019-09-02 16:35:10 +03:00
global $wpdb ;
2025-12-11 17:36:42 +02:00
$directory_id = $wpdb -> get_var (
$wpdb -> prepare (
" SELECT post_id
FROM { $wpdb -> postmeta }
WHERE meta_key = '_um_directory_token' AND
meta_value = %s
LIMIT 1 " ,
$hash
)
);
2019-09-02 16:35:10 +03:00
if ( empty ( $directory_id ) ) {
2025-12-11 17:36:42 +02:00
// Fallback, use old value.
$directory_id = $wpdb -> get_var (
$wpdb -> prepare (
" SELECT ID
FROM { $wpdb -> posts }
WHERE SUBSTRING( MD5( ID ), 11, 5 ) = %s " ,
$hash
)
);
if ( empty ( $directory_id ) ) {
return false ;
}
2019-09-02 16:35:10 +03:00
}
return ( int ) $directory_id ;
}
2025-12-11 17:36:42 +02:00
/**
* Generate a secure random token for each directory
*
* @param int $id
*
* @return false|string
*/
public function set_directory_hash ( $id ) {
2025-12-16 17:05:51 +02:00
$unique_hash = wp_generate_password ( 5 , false );
2025-12-11 17:36:42 +02:00
$result = update_post_meta ( $id , '_um_directory_token' , $unique_hash );
if ( false === $result ) {
return false ;
}
return $unique_hash ;
}
2019-09-02 16:35:10 +03:00
2019-10-18 13:01:40 +03:00
/**
* @param $id
*
* @return bool|string
*/
2025-12-11 17:36:42 +02:00
public function get_directory_hash ( $id ) {
$hash = get_post_meta ( $id , '_um_directory_token' , true );
if ( '' === $hash ) {
// Set the hash if empty.
$hash = $this -> set_directory_hash ( $id );
}
if ( empty ( $hash ) ) {
// Fallback, use old value.
$hash = substr ( md5 ( $id ), 10 , 5 );
}
2019-10-18 13:01:40 +03:00
return $hash ;
}
2025-12-16 17:05:51 +02:00
/**
* Generate a secure random token for each user card
*
* @param int $id
*
* @return false|string
*/
public function set_user_hash ( $id ) {
$unique_hash = wp_generate_password ( 5 , false );
$result = update_user_meta ( $id , '_um_card_anchor_token' , $unique_hash );
if ( false === $result ) {
return false ;
}
return $unique_hash ;
}
/**
* @param $id
*
* @return bool|string
*/
public function get_user_hash ( $id ) {
$hash = get_user_meta ( $id , '_um_card_anchor_token' , true );
if ( '' === $hash ) {
// Set the hash if empty.
$hash = $this -> set_user_hash ( $id );
}
if ( empty ( $hash ) ) {
// Fallback, use old value.
$hash = substr ( md5 ( $id ), 10 , 5 );
}
return $hash ;
}
2019-09-02 16:35:10 +03:00
/**
* Get view Type template
* @param string $type
*
* @return string
*/
function get_type_basename ( $type ) {
return apply_filters ( " um_member_directory_ { $type } _type_template_basename " , '' );
}
/**
* Tag conversion for member directory
*
* @param string $string
* @param array $array
*
* @return string
*/
function convert_tags ( $string , $array ) {
$search = array (
'{total_users}' ,
);
$replace = array (
$array [ 'total_users' ],
);
$string = str_replace ( $search , $replace , $string );
return $string ;
}
/**
* Members page allowed?
*
* can be disabled by "Enable Members Directory" option
*
*/
2024-04-15 17:58:18 +03:00
public function access_members () {
if ( um_is_predefined_page ( 'members' ) && ! UM () -> options () -> get ( 'members_page' ) ) {
2019-09-02 16:35:10 +03:00
um_redirect_home ();
}
2019-08-14 10:54:16 +03:00
}
/**
* @param $value
* @param $key
* @param $post_id
*
* @return array
*/
2021-06-29 02:51:54 +03:00
public function before_save_data ( $value , $key , $post_id ) {
2019-08-14 10:54:16 +03:00
$post = get_post ( $post_id );
2024-04-15 17:58:18 +03:00
if ( 'um_directory' !== $post -> post_type ) {
return $value ;
}
2021-06-29 21:15:48 +03:00
2024-04-15 17:58:18 +03:00
if ( ! empty ( $value ) && in_array ( $key , array ( '_um_view_types' , '_um_roles' , '_um_roles_can_search' , '_um_roles_can_filter' ), true ) ) {
$value = array_keys ( $value );
} elseif ( '_um_search_filters' === $key ) {
$temp_value = array ();
// phpcs:disable WordPress.Security.NonceVerification -- already verified here
if ( ! empty ( $value ) ) {
foreach ( $value as $k ) {
$filter_type = $this -> filter_types [ $k ];
if ( ! empty ( $filter_type ) ) {
if ( 'slider' === $filter_type ) {
if ( ! empty ( $_POST [ $k ] ) ) {
if ( count ( $_POST [ $k ] ) > 1 ) {
$temp_value [ $k ] = array_map ( 'intval' , $_POST [ $k ] );
} else {
$temp_value [ $k ] = ( int ) $_POST [ $k ];
2020-01-10 17:31:55 +02:00
}
2024-04-15 17:58:18 +03:00
}
} elseif ( 'datepicker' === $filter_type ) {
if ( ! empty ( $_POST [ $k . '_from' ] ) ) {
$temp_value [ $k ][ 0 ] = sanitize_text_field ( $_POST [ $k . '_from' ] );
}
if ( ! empty ( $_POST [ $k . '_to' ] ) ) {
$temp_value [ $k ][ 1 ] = sanitize_text_field ( $_POST [ $k . '_to' ] );
}
} elseif ( 'timepicker' === $filter_type ) {
2024-04-16 13:24:08 +03:00
if ( ! empty ( $_POST [ $k . '_from' ] ) ) {
$temp_value [ $k ][ 0 ] = sanitize_text_field ( $_POST [ $k . '_from' ] );
}
if ( ! empty ( $_POST [ $k . '_to' ] ) ) {
$temp_value [ $k ][ 1 ] = sanitize_text_field ( $_POST [ $k . '_to' ] );
2024-04-15 17:58:18 +03:00
}
} elseif ( 'select' === $filter_type ) {
if ( ! empty ( $_POST [ $k ] ) ) {
if ( is_array ( $_POST [ $k ] ) ) {
$temp_value [ $k ] = array_map ( 'trim' , $_POST [ $k ] );
} else {
$temp_value [ $k ] = array ( trim ( $_POST [ $k ] ) );
2020-01-10 14:30:17 +02:00
}
2024-04-15 17:58:18 +03:00
$temp_value [ $k ] = array_map ( 'sanitize_text_field' , $temp_value [ $k ] );
}
} else {
if ( ! empty ( $_POST [ $k ] ) ) {
$temp_value [ $k ] = trim ( sanitize_text_field ( $_POST [ $k ] ) );
2019-10-01 11:53:34 +03:00
}
}
}
}
2024-04-15 17:58:18 +03:00
}
2019-10-01 11:53:34 +03:00
2024-04-15 17:58:18 +03:00
$value = $temp_value ;
// phpcs:enable WordPress.Security.NonceVerification -- already verified here
} elseif ( '_um_sorting_fields' === $key ) {
if ( ! empty ( $value [ 'other_data' ] ) ) {
$other_data = $value [ 'other_data' ];
unset ( $value [ 'other_data' ] );
foreach ( $value as $k => & $row ) {
if ( ! empty ( $other_data [ $k ][ 'meta_key' ] ) ) {
$metakey = sanitize_text_field ( $other_data [ $k ][ 'meta_key' ] );
if ( ! empty ( $metakey ) ) {
if ( ! empty ( $other_data [ $k ][ 'label' ] ) ) {
$metalabel = wp_strip_all_tags ( $other_data [ $k ][ 'label' ] );
}
if ( ! empty ( $other_data [ $k ][ 'data_type' ] ) ) {
$data_type = sanitize_text_field ( $other_data [ $k ][ 'data_type' ] );
2020-01-13 11:21:54 +02:00
}
2024-04-15 17:58:18 +03:00
if ( ! empty ( $other_data [ $k ][ 'order' ] ) ) {
$order = sanitize_text_field ( $other_data [ $k ][ 'order' ] );
}
$row = array (
$metakey => $metakey ,
'label' => ! empty ( $metalabel ) ? $metalabel : $metakey ,
'type' => ! empty ( $data_type ) ? $data_type : '' ,
'order' => ! empty ( $order ) ? $order : '' ,
);
2020-01-13 10:18:30 +02:00
}
}
}
2024-04-15 17:58:18 +03:00
unset ( $row );
2019-08-14 10:54:16 +03:00
}
2024-04-15 17:58:18 +03:00
} elseif ( '_um_sortby_custom' === $key ) {
$value = sanitize_text_field ( $value );
} elseif ( '_um_sortby_custom_label' === $key ) {
$value = wp_strip_all_tags ( $value );
} elseif ( '_um_sortby_custom_type' === $key ) {
$value = sanitize_text_field ( $value );
} elseif ( '_um_sortby_custom_order' === $key ) {
$value = sanitize_text_field ( $value );
2019-08-14 10:54:16 +03:00
}
return $value ;
}
/**
*
*/
function init_variables () {
// Types
$this -> view_types = apply_filters ( 'um_member_directory_views' , array (
'grid' => array ( 'title' => __ ( 'Grid' , 'ultimate-member' ), 'icon' => 'um-faicon-th' ),
'list' => array ( 'title' => __ ( 'List' , 'ultimate-member' ), 'icon' => 'um-faicon-list' ),
) );
// Sort
$this -> sort_fields = apply_filters ( 'um_members_directory_sort_fields' , array (
2019-09-23 13:34:25 +03:00
'user_registered_desc' => __ ( 'New users first' , 'ultimate-member' ),
'user_registered_asc' => __ ( 'Old users first' , 'ultimate-member' ),
2019-08-14 10:54:16 +03:00
'username' => __ ( 'Username' , 'ultimate-member' ),
2019-11-28 15:35:27 +02:00
'nickname' => __ ( 'Nickname' , 'ultimate-member' ),
2019-09-23 13:34:25 +03:00
'first_name' => __ ( 'First name' , 'ultimate-member' ),
'last_name' => __ ( 'Last name' , 'ultimate-member' ),
'display_name' => __ ( 'Display name' , 'ultimate-member' ),
2019-12-05 11:19:49 +02:00
'last_first_name' => __ ( 'Last & First name' , 'ultimate-member' ),
2019-09-23 13:34:25 +03:00
'last_login' => __ ( 'Last login' , 'ultimate-member' ),
2019-08-14 10:54:16 +03:00
) );
2022-06-09 17:17:15 +03:00
$this -> sorting_supported_fields = apply_filters ( 'um_members_directory_custom_field_types_supported_sorting' , array ( 'number' ) );
2023-06-12 13:20:00 +03:00
$this -> sort_data_types = array (
'CHAR' => __ ( 'CHAR' , 'ultimate-member' ),
'NUMERIC' => __ ( 'NUMERIC' , 'ultimate-member' ),
'BINARY' => __ ( 'BINARY' , 'ultimate-member' ),
'DATE' => __ ( 'DATE' , 'ultimate-member' ),
'DATETIME' => __ ( 'DATETIME' , 'ultimate-member' ),
'DECIMAL' => __ ( 'DECIMAL' , 'ultimate-member' ),
'SIGNED' => __ ( 'SIGNED' , 'ultimate-member' ),
'TIME' => __ ( 'TIME' , 'ultimate-member' ),
'UNSIGNED' => __ ( 'UNSIGNED' , 'ultimate-member' ),
);
$this -> sort_data_types = apply_filters ( 'um_members_directory_sort_data_types' , $this -> sort_data_types );
2022-06-09 17:17:15 +03:00
if ( ! empty ( UM () -> builtin () -> saved_fields ) ) {
foreach ( UM () -> builtin () -> saved_fields as $key => $data ) {
2023-12-01 02:17:37 +02:00
if ( '_um_last_login' === $key ) {
2022-06-09 17:17:15 +03:00
continue ;
}
if ( isset ( $data [ 'type' ] ) && in_array ( $data [ 'type' ], $this -> sorting_supported_fields ) ) {
2023-07-13 11:36:29 +03:00
// translators: %s: title.
2022-06-09 17:17:15 +03:00
if ( isset ( $data [ 'title' ] ) && array_search ( sprintf ( __ ( '%s DESC' , 'ultimate-member' ), $data [ 'title' ] ), $this -> sort_fields ) !== false ) {
$data [ 'title' ] = $data [ 'title' ] . ' (' . $key . ')' ;
}
$title = isset ( $data [ 'title' ] ) ? $data [ 'title' ] : ( isset ( $data [ 'label' ] ) ? $data [ 'label' ] : '' );
if ( empty ( $title ) ) {
continue ;
}
2023-07-13 11:36:29 +03:00
// translators: %s: title.
2022-06-09 17:17:15 +03:00
$this -> sort_fields [ $key . '_desc' ] = sprintf ( __ ( '%s DESC' , 'ultimate-member' ), $title );
2023-07-13 11:36:29 +03:00
// translators: %s: title.
2022-06-09 17:17:15 +03:00
$this -> sort_fields [ $key . '_asc' ] = sprintf ( __ ( '%s ASC' , 'ultimate-member' ), $title );
}
}
}
2019-08-14 10:54:16 +03:00
asort ( $this -> sort_fields );
$this -> default_sorting = apply_filters ( 'um_members_directory_default_sort' , array_merge ( $this -> sort_fields , array (
'random' => __ ( 'Random' , 'ultimate-member' ),
'other' => __ ( 'Other (Custom Field)' , 'ultimate-member' ),
) ) );
asort ( $this -> default_sorting );
// Filters
$this -> filter_fields = array (
2019-11-20 17:07:38 +02:00
'country' => __ ( 'Country' , 'ultimate-member' ),
'gender' => __ ( 'Gender' , 'ultimate-member' ),
'languages' => __ ( 'Languages' , 'ultimate-member' ),
'role' => __ ( 'Roles' , 'ultimate-member' ),
'birth_date' => __ ( 'Age' , 'ultimate-member' ),
'last_login' => __ ( 'Last Login' , 'ultimate-member' ),
'user_registered' => __ ( 'User Registered' , 'ultimate-member' ),
'first_name' => __ ( 'First Name' , 'ultimate-member' ),
'last_name' => __ ( 'Last Name' , 'ultimate-member' ),
'nickname' => __ ( 'Nickname' , 'ultimate-member' ),
2024-02-16 15:12:21 +02:00
'secondary_user_email' => __ ( 'Secondary Email Address' , 'ultimate-member' ),
2019-11-20 17:07:38 +02:00
'description' => __ ( 'Biography' , 'ultimate-member' ),
'phone_number' => __ ( 'Phone Number' , 'ultimate-member' ),
'mobile_number' => __ ( 'Mobile Number' , 'ultimate-member' ),
2019-08-14 10:54:16 +03:00
);
2020-02-20 10:31:55 +02:00
$this -> filter_supported_fields = apply_filters ( 'um_members_directory_custom_field_types_supported_filter' , array ( 'date' , 'time' , 'select' , 'multiselect' , 'radio' , 'checkbox' , 'rating' , 'text' , 'textarea' , 'number' ) );
2019-08-14 10:54:16 +03:00
2024-04-09 13:55:39 +03:00
$core_search_keys = $this -> get_core_search_fields ();
$this -> searching_fields = array ();
if ( ! empty ( UM () -> builtin () -> all_user_fields () ) ) {
foreach ( UM () -> builtin () -> all_user_fields () as $key => $data ) {
if ( in_array ( $key , $core_search_keys , true ) ) {
2025-03-25 23:31:13 +02:00
if ( isset ( $data [ 'title' ] ) && in_array ( $data [ 'title' ], $this -> searching_fields , true ) ) {
2024-04-09 13:55:39 +03:00
$data [ 'title' ] = $data [ 'title' ] . ' (' . $key . ')' ;
}
$title = isset ( $data [ 'title' ] ) ? $data [ 'title' ] : ( isset ( $data [ 'label' ] ) ? $data [ 'label' ] : '' );
if ( empty ( $title ) ) {
continue ;
}
$this -> searching_fields [ $key ] = $title ;
}
}
}
2019-09-05 13:00:54 +03:00
if ( ! empty ( UM () -> builtin () -> saved_fields ) ) {
2019-09-04 16:09:55 +03:00
foreach ( UM () -> builtin () -> saved_fields as $key => $data ) {
2019-11-20 17:07:38 +02:00
2023-12-01 02:17:37 +02:00
if ( '_um_last_login' === $key ) {
2019-11-20 17:07:38 +02:00
continue ;
}
2019-09-04 16:09:55 +03:00
if ( isset ( $data [ 'type' ] ) && in_array ( $data [ 'type' ], $this -> filter_supported_fields ) ) {
if ( isset ( $data [ 'title' ] ) && array_search ( $data [ 'title' ], $this -> filter_fields ) !== false ) {
$data [ 'title' ] = $data [ 'title' ] . ' (' . $key . ')' ;
}
2019-10-23 17:20:01 +03:00
$title = isset ( $data [ 'title' ] ) ? $data [ 'title' ] : ( isset ( $data [ 'label' ] ) ? $data [ 'label' ] : '' );
if ( empty ( $title ) ) {
continue ;
}
$this -> filter_fields [ $key ] = $title ;
2019-08-14 10:54:16 +03:00
}
}
}
$this -> filter_fields = apply_filters ( 'um_members_directory_filter_fields' , $this -> filter_fields );
ksort ( $this -> filter_fields );
2019-08-16 19:42:18 +03:00
2024-04-09 13:55:39 +03:00
$this -> searching_fields = array_merge ( $this -> searching_fields , $this -> filter_fields );
asort ( $this -> searching_fields );
2019-09-02 16:35:10 +03:00
$this -> filter_types = apply_filters ( 'um_members_directory_filter_types' , array (
2019-11-20 17:07:38 +02:00
'country' => 'select' ,
'gender' => 'select' ,
'languages' => 'select' ,
'role' => 'select' ,
'birth_date' => 'slider' ,
'last_login' => 'datepicker' ,
'user_registered' => 'datepicker' ,
'first_name' => 'text' ,
'last_name' => 'text' ,
'nickname' => 'text' ,
'secondary_user_email' => 'text' ,
'description' => 'text' ,
'phone_number' => 'text' ,
'mobile_number' => 'text' ,
2019-08-16 19:42:18 +03:00
) );
$fields = UM () -> builtin () -> all_user_fields ;
$custom_fields_types = array_flip ( array_keys ( $this -> filter_fields ) );
foreach ( $custom_fields_types as $key => & $value ) {
if ( ! isset ( $fields [ $key ] ) ) {
unset ( $custom_fields_types [ $key ] );
} else {
switch ( $fields [ $key ][ 'type' ] ) {
default :
$value = apply_filters ( 'um_custom_field_filter_type' , 'select' , $fields [ $key ] );
break ;
2019-11-20 17:07:38 +02:00
case 'text' :
case 'textarea' :
$value = 'text' ;
break ;
2019-08-16 19:42:18 +03:00
case 'date' :
$value = 'datepicker' ;
break ;
case 'time' :
$value = 'timepicker' ;
break ;
case 'select' :
case 'multiselect' :
case 'radio' :
case 'checkbox' :
$value = 'select' ;
break ;
2020-02-20 10:31:55 +02:00
case 'number' :
2019-08-16 19:42:18 +03:00
case 'rating' :
$value = 'slider' ;
break ;
}
}
}
2019-09-02 16:35:10 +03:00
$this -> filter_types = array_merge ( $custom_fields_types , $this -> filter_types );
}
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
/**
* Render member's directory
* filters selectboxes
*
* @param string $filter
2019-09-04 14:54:03 +03:00
* @param array $directory_data
2019-10-01 11:53:34 +03:00
* @param mixed $default_value
2020-01-10 17:31:55 +02:00
* @param bool $admin
2019-09-04 14:54:03 +03:00
*
2019-09-02 16:35:10 +03:00
* @return string $filter
*/
2024-04-15 17:58:18 +03:00
public function show_filter ( $filter , $directory_data , $default_value = false , $admin = false ) {
2019-09-02 16:35:10 +03:00
if ( empty ( $this -> filter_types [ $filter ] ) ) {
2019-08-16 19:42:18 +03:00
return '' ;
}
2024-04-17 01:46:48 +03:00
if ( false === $default_value ) {
2020-01-10 17:31:55 +02:00
$default_filters = array ();
if ( ! empty ( $directory_data [ 'search_filters' ] ) ) {
$default_filters = maybe_unserialize ( $directory_data [ 'search_filters' ] );
}
2024-04-17 01:46:48 +03:00
if ( ! empty ( $default_filters [ $filter ] ) && 'select' !== $this -> filter_types [ $filter ] ) {
2020-01-10 17:31:55 +02:00
return '' ;
}
}
2019-09-02 16:35:10 +03:00
$field_key = $filter ;
2023-12-01 02:17:37 +02:00
if ( 'last_login' === $filter ) {
2019-09-02 16:35:10 +03:00
$field_key = '_um_last_login' ;
2023-12-01 02:17:37 +02:00
} elseif ( 'role' === $filter ) {
2019-09-02 16:35:10 +03:00
$field_key = 'role_select' ;
}
$fields = UM () -> builtin () -> all_user_fields ;
2019-08-16 19:42:18 +03:00
if ( isset ( $fields [ $field_key ] ) ) {
$attrs = $fields [ $field_key ];
} else {
/**
* UM hook
*
* @type filter
* @title um_custom_search_field_{$filter}
* @description Custom search settings by $filter
* @input_vars
* [{"var":"$settings","type":"array","desc":"Search Settings"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_custom_search_field_{$filter}', 'function_name', 10, 1 ); ?>
* @example
* <?php
* add_filter( 'um_custom_search_field_{$filter}', 'my_custom_search_field', 10, 1 );
* function my_change_email_template_file( $settings ) {
* // your code here
* return $settings;
* }
* ?>
*/
2019-09-30 01:27:01 +03:00
$attrs = apply_filters ( " um_custom_search_field_ { $filter } " , array (), $field_key );
2019-08-16 19:42:18 +03:00
}
2019-11-21 09:44:58 +02:00
// skip private invisible fields
if ( ! um_can_view_field ( $attrs ) ) {
return '' ;
}
2019-08-16 19:42:18 +03:00
/**
* UM hook
*
* @type filter
* @title um_search_fields
* @description Filter all search fields
* @input_vars
* [{"var":"$settings","type":"array","desc":"Search Fields"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_search_fields', 'function_name', 10, 1 ); ?>
* @example
* <?php
* add_filter( 'um_search_fields', 'my_search_fields', 10, 1 );
* function my_search_fields( $settings ) {
* // your code here
* return $settings;
* }
* ?>
*/
2019-12-21 10:59:09 +08:00
$attrs = apply_filters ( 'um_search_fields' , $attrs , $field_key , $directory_data [ 'form_id' ] );
2019-09-11 13:01:44 +03:00
2025-12-11 17:36:42 +02:00
$unique_hash = $this -> get_directory_hash ( $directory_data [ 'form_id' ] );
2019-09-11 13:01:44 +03:00
2019-08-16 19:42:18 +03:00
ob_start ();
2019-09-02 16:35:10 +03:00
switch ( $this -> filter_types [ $filter ] ) {
2024-04-15 17:58:18 +03:00
default :
2020-01-29 13:22:03 +02:00
do_action ( " um_member_directory_filter_type_ { $this -> filter_types [ $filter ] } " , $filter , $directory_data , $unique_hash , $attrs , $default_value );
2019-08-16 19:42:18 +03:00
break ;
2024-04-15 17:58:18 +03:00
case 'text' :
2022-08-17 18:54:12 +03:00
$label = '' ;
if ( isset ( $attrs [ 'label' ] ) ) {
$label = $attrs [ 'label' ];
2024-04-15 17:58:18 +03:00
} elseif ( isset ( $attrs [ 'title' ] ) ) {
2022-08-17 18:54:12 +03:00
$label = $attrs [ 'title' ];
}
2024-04-15 17:58:18 +03:00
$label = stripslashes ( $label );
$filter_from_url = ! empty ( $_GET [ 'filter_' . $filter . '_' . $unique_hash ] ) ? sanitize_text_field ( $_GET [ 'filter_' . $filter . '_' . $unique_hash ] ) : $default_value ;
?>
<input type="text" autocomplete="off" id="<?php echo esc_attr( $filter ); ?>" name="<?php echo esc_attr( $filter ); ?>"
placeholder="<?php echo esc_attr( $label ); ?>"
value="<?php echo esc_attr( $filter_from_url ); ?>" class="um-form-field"
aria-label="<?php echo esc_attr( $label ); ?>" />
2020-01-10 17:31:55 +02:00
<?php
2020-01-10 14:30:17 +02:00
break;
2024-04-15 17:58:18 +03:00
2019-08-16 19:42:18 +03:00
case 'select': {
2019-09-11 13:01:44 +03:00
// getting value from GET line
$filter_from_url = ! empty( $_GET[ 'filter_' . $filter . '_' . $unique_hash ] ) ? explode( '||', sanitize_text_field( $_GET[ 'filter_' . $filter . '_' . $unique_hash ] ) ) : array();
2019-11-20 17:07:38 +02:00
// new
global $wpdb;
if ( $attrs['metakey'] != 'role_select' ) {
$values_array = $wpdb->get_col(
$wpdb->prepare(
2020-02-26 13:43:08 +02:00
"SELECT DISTINCT meta_value
FROM $wpdb->usermeta
WHERE meta_key = %s AND
2020-01-14 11:58:25 +02:00
meta_value != ''",
2019-11-20 17:07:38 +02:00
$attrs['metakey']
)
);
} else {
$users_roles = count_users();
$values_array = ( ! empty( $users_roles['avail_roles'] ) && is_array( $users_roles['avail_roles'] ) ) ? array_keys( array_filter( $users_roles['avail_roles'] ) ) : array();
}
2023-10-13 15:35:39 +03:00
if ( ! empty( $values_array ) && in_array( $attrs['type'], array( 'select', 'multiselect', 'checkbox', 'radio' ), true ) ) {
2019-11-20 17:07:38 +02:00
$values_array = array_map( 'maybe_unserialize', $values_array );
2023-10-13 15:35:39 +03:00
$temp_values = array();
2019-11-20 17:07:38 +02:00
foreach ( $values_array as $values ) {
if ( is_array( $values ) ) {
$temp_values = array_merge( $temp_values, $values );
} else {
$temp_values[] = $values;
}
}
$values_array = array_unique( $temp_values );
}
2023-10-13 15:35:39 +03:00
if ( 'online_status' !== $attrs['metakey'] && empty( $values_array ) ) {
2019-11-26 19:05:07 +02:00
ob_get_clean();
2019-11-20 17:07:38 +02:00
return '';
}
2019-08-16 19:42:18 +03:00
if ( isset( $attrs['metakey'] ) && strstr( $attrs['metakey'], 'role_' ) ) {
2019-11-07 16:16:11 +02:00
$shortcode_roles = get_post_meta( $directory_data['form_id'], '_um_roles', true );
2019-08-16 19:42:18 +03:00
$um_roles = UM()->roles()->get_roles( false );
if ( ! empty( $shortcode_roles ) && is_array( $shortcode_roles ) ) {
$attrs['options'] = array();
foreach ( $um_roles as $key => $value ) {
if ( in_array( $key, $shortcode_roles ) ) {
$attrs['options'][ $key ] = $value;
}
}
2019-12-20 15:06:58 +02:00
} else {
$attrs['options'] = array();
foreach ( $um_roles as $key => $value ) {
$attrs['options'][ $key ] = $value;
}
2019-08-16 19:42:18 +03:00
}
}
2019-11-20 17:07:38 +02:00
$custom_dropdown = '';
2019-08-16 19:42:18 +03:00
if ( ! empty( $attrs['custom_dropdown_options_source'] ) ) {
$attrs['custom'] = true;
2019-11-21 11:41:52 +02:00
if ( ! empty( $attrs['parent_dropdown_relationship'] ) ) {
2019-11-21 18:41:47 +02:00
2019-11-21 11:41:52 +02:00
$custom_dropdown .= ' data-member-directory="yes"';
$custom_dropdown .= ' data-um-parent="' . esc_attr( $attrs['parent_dropdown_relationship'] ) . '"';
if ( isset( $_GET[ 'filter_' . $attrs['parent_dropdown_relationship'] . '_' . $unique_hash ] ) ) {
$_POST['parent_option_name'] = $attrs['parent_dropdown_relationship'];
2023-04-24 03:30:56 +03:00
$parent_option_value = sanitize_text_field( $_GET[ 'filter_' . $attrs['parent_dropdown_relationship'] . '_' . $unique_hash ] );
$_POST['parent_option'] = explode( '||', $parent_option_value );
2019-11-21 11:41:52 +02:00
}
}
2022-06-08 21:24:23 +03:00
$attrs['custom_dropdown_options_source'] = wp_unslash( $attrs['custom_dropdown_options_source'] );
2019-11-21 11:41:52 +02:00
$ajax_source = apply_filters( "um_custom_dropdown_options_source__{$filter}", $attrs['custom_dropdown_options_source'], $attrs );
2023-04-24 03:30:56 +03:00
2019-11-21 11:41:52 +02:00
$custom_dropdown .= ' data-um-ajax-source="' . esc_attr( $ajax_source ) . '" ';
2019-11-21 18:41:47 +02:00
$attrs['options'] = UM()->fields()->get_options_from_callback( $attrs, $attrs['type'] );
2020-02-06 14:54:13 +02:00
} else {
2023-07-02 13:39:42 +03:00
/** This filter is documented in includes/core/class-fields.php */
2020-02-06 14:54:13 +02:00
$option_pairs = apply_filters( 'um_select_options_pair', null, $attrs );
2019-08-16 19:42:18 +03:00
}
2020-01-10 12:53:30 +02:00
if ( $attrs['metakey'] != 'online_status' ) {
2020-02-06 14:54:13 +02:00
if ( $attrs['metakey'] != 'role_select' && $attrs['metakey'] != 'mycred_rank' && empty( $custom_dropdown ) && empty( $option_pairs ) ) {
2020-01-21 15:13:33 +02:00
$attrs['options'] = array_intersect( array_map( 'stripslashes', array_map( 'trim', $attrs['options'] ) ), $values_array );
2020-01-10 12:53:30 +02:00
} elseif ( ! empty( $custom_dropdown ) ) {
2020-01-21 15:13:33 +02:00
$attrs['options'] = array_intersect_key( array_map( 'trim', $attrs['options'] ), array_flip( $values_array ) );
2020-01-10 12:53:30 +02:00
} else {
2020-01-21 15:13:33 +02:00
$attrs['options'] = array_intersect_key( array_map( 'trim', $attrs['options'] ), array_flip( $values_array ) );
2020-01-10 12:53:30 +02:00
}
2019-08-16 19:42:18 +03:00
}
2019-11-20 17:07:38 +02:00
$attrs['options'] = apply_filters( 'um_member_directory_filter_select_options', $attrs['options'], $values_array, $attrs );
2019-08-16 19:42:18 +03:00
2023-10-13 15:35:39 +03:00
if ( ( empty( $attrs['options'] ) || ! is_array( $attrs['options'] ) ) && ! ( ! empty( $attrs['custom_dropdown_options_source'] ) && ! empty( $attrs['parent_dropdown_relationship'] ) ) ) {
2019-11-26 19:05:07 +02:00
ob_get_clean();
2019-11-20 17:07:38 +02:00
return '';
}
2019-08-16 19:42:18 +03:00
2019-11-21 18:41:47 +02:00
if ( ! empty( $attrs['custom_dropdown_options_source'] ) && ! empty( $attrs['parent_dropdown_relationship'] ) ) {
$attrs['options'] = array();
}
2019-11-20 17:07:38 +02:00
if ( isset( $attrs['label'] ) ) {
$attrs['label'] = strip_tags( $attrs['label'] );
}
2019-08-16 19:42:18 +03:00
2020-01-10 17:31:55 +02:00
if ( ! empty( $default_filters[ $filter ] ) ) {
$attrs['options'] = array_intersect( $attrs['options'], $default_filters[ $filter ] );
}
2019-12-12 11:42:40 +02:00
ksort( $attrs['options'] );
2020-10-12 16:19:03 +03:00
$attrs['options'] = apply_filters( 'um_member_directory_filter_select_options_sorted', $attrs['options'], $attrs );
2022-07-25 22:09:39 +03:00
$label = '';
if ( isset( $attrs['label'] ) ) {
$label = $attrs['label'];
} elseif ( ! isset( $attrs['label'] ) && isset( $attrs['title'] ) ) {
$label = $attrs['title'];
}
?>
2019-08-16 19:42:18 +03:00
2020-01-10 17:31:55 +02:00
<select class="um-s1" id="<?php echo esc_attr( $filter ); ?>" name="<?php echo esc_attr( $filter ); ?><?php if ( $admin && count( $attrs['options'] ) > 1 ) { ?>[]<?php } ?>"
2020-10-12 16:19:03 +03:00
data-placeholder="<?php esc_attr_e( stripslashes( $label ), 'ultimate-member' ); ?>"
aria-label="<?php esc_attr_e( stripslashes( $label ), 'ultimate-member' ); ?>"
2020-01-14 11:58:25 +02:00
<?php if ( $admin && count( $attrs['options'] ) > 1 ) { ?>multiple<?php } ?>
2019-11-20 17:07:38 +02:00
<?php echo $custom_dropdown; ?>>
2019-08-16 19:42:18 +03:00
2019-11-20 17:07:38 +02:00
<option></option>
2019-08-16 19:42:18 +03:00
2019-11-20 17:07:38 +02:00
<?php if ( ! empty( $attrs['options'] ) ) {
foreach ( $attrs['options'] as $k => $v ) {
2019-08-16 19:42:18 +03:00
2019-11-20 17:07:38 +02:00
$v = stripslashes( $v );
2019-08-16 19:42:18 +03:00
2019-11-20 17:07:38 +02:00
$opt = $v;
2019-08-16 19:42:18 +03:00
2019-11-20 18:22:09 +02:00
if ( strstr( $filter, 'role_' ) || $filter == 'role' ) {
2019-11-20 17:07:38 +02:00
$opt = $k;
}
2019-08-16 19:42:18 +03:00
2019-11-20 17:07:38 +02:00
if ( isset( $attrs['custom'] ) ) {
$opt = $k;
2020-02-06 14:54:13 +02:00
}
if ( ! empty( $option_pairs ) ) {
$opt = $k;
2019-11-20 17:07:38 +02:00
} ?>
2019-08-16 19:42:18 +03:00
2019-11-20 17:07:38 +02:00
<option value="<?php echo esc_attr( $opt ); ?>" data-value_label="<?php esc_attr_e( $v, 'ultimate-member' ); ?>"
2020-01-10 17:31:55 +02:00
<?php disabled( ! empty( $filter_from_url ) && in_array( $opt, $filter_from_url ) );
if ( $admin ) {
2021-03-12 03:18:42 +02:00
if ( ! is_array( $default_value ) ) {
2020-01-10 17:31:55 +02:00
$default_value = array( $default_value );
}
selected( in_array( $opt, $default_value ) );
} else {
selected( $opt === $default_value );
} ?>>
2019-11-20 17:07:38 +02:00
<?php _e( $v, 'ultimate-member' ); ?>
</option>
2019-08-16 19:42:18 +03:00
2019-11-20 17:07:38 +02:00
<?php }
} ?>
2019-08-16 19:42:18 +03:00
2019-11-20 17:07:38 +02:00
</select>
2019-08-16 19:42:18 +03:00
2019-11-20 17:07:38 +02:00
<?php break;
2019-08-16 19:42:18 +03:00
}
case 'slider': {
2019-09-04 14:54:03 +03:00
$range = $this->slider_filters_range( $filter, $directory_data );
2020-02-24 16:27:26 +02:00
if ( $range ) {
list( $single_placeholder, $plural_placeholder ) = $this->slider_range_placeholder( $filter, $attrs ); ?>
2020-01-02 17:21:02 +02:00
2019-10-01 11:53:34 +03:00
<input type="hidden" id="<?php echo $filter; ?>_min" name="<?php echo $filter; ?>[]" class="um_range_min" value="<?php echo ! empty( $default_value ) ? esc_attr( min( $default_value ) ) : '' ?>" />
<input type="hidden" id="<?php echo $filter; ?>_max" name="<?php echo $filter; ?>[]" class="um_range_max" value="<?php echo ! empty( $default_value ) ? esc_attr( max( $default_value ) ) : '' ?>" />
2021-03-03 17:17:54 +02:00
<div class="um-slider" data-field_name="<?php echo $filter; ?>" data-min="<?php echo esc_attr( $range[0] ); ?>" data-max="<?php echo esc_attr( $range[1] ); ?>"></div>
2020-01-02 17:21:02 +02:00
<div class="um-slider-range" data-placeholder-s="<?php echo esc_attr( $single_placeholder ); ?>" data-placeholder-p="<?php echo esc_attr( $plural_placeholder ); ?>" data-label="<?php echo ( ! empty( $attrs['label'] ) ) ? esc_attr__( stripslashes( $attrs['label'] ), 'ultimate-member' ) : ''; ?>"></div>
2019-08-16 19:42:18 +03:00
<?php }
break;
}
2023-12-01 02:17:37 +02:00
case 'datepicker':
2019-08-16 19:42:18 +03:00
$range = $this->datepicker_filters_range( $filter );
$label = ! empty( $attrs['label'] ) ? $attrs['label'] : $attrs['title'];
2024-04-15 17:58:18 +03:00
$label = stripslashes( $label );
$default_value_min = '';
$default_value_max = '';
if ( ! empty( $default_value[0] ) ) {
$default_value_min = $default_value[0];
}
if ( ! empty( $default_value[1] ) ) {
$default_value_max = $default_value[1];
}
2019-08-16 19:42:18 +03:00
2023-12-01 02:17:37 +02:00
if ( $range ) {
2024-04-15 17:58:18 +03:00
list( $min, $max ) = $range;
2023-12-01 02:17:37 +02:00
?>
2024-04-15 17:58:18 +03:00
<input type="text" id="<?php echo esc_attr( $filter ); ?>_from" name="<?php echo esc_attr( $filter ); ?>_from" class="um-datepicker-filter"
<?php // translators: %s: Datetime filter label. ?>
placeholder="<?php echo esc_attr( sprintf( __( '%s From', 'ultimate-member' ), $label ) ); ?>"
data-filter-label="<?php echo esc_attr( $label ); ?>"
data-date_min="<?php echo esc_attr( $min ); ?>" data-date_max="<?php echo esc_attr( $max ); ?>"
data-filter_name="<?php echo esc_attr( $filter ); ?>" data-range="from" data-value="<?php echo ! empty( $default_value_min ) ? esc_attr( strtotime( $default_value_min ) ) : ''; ?>" />
<input type="text" id="<?php echo esc_attr( $filter ); ?>_to" name="<?php echo esc_attr( $filter ); ?>_to" class="um-datepicker-filter"
<?php // translators: %s: Datetime filter label. ?>
placeholder="<?php echo esc_attr( sprintf( __( '%s To', 'ultimate-member' ), $label ) ); ?>"
data-filter-label="<?php echo esc_attr( $label ); ?>"
data-date_min="<?php echo esc_attr( $min ); ?>" data-date_max="<?php echo esc_attr( $max ); ?>"
data-filter_name="<?php echo esc_attr( $filter ); ?>" data-range="to" data-value="<?php echo ! empty( $default_value_max ) ? esc_attr( strtotime( $default_value_max ) ) : ''; ?>" />
2023-12-01 02:17:37 +02:00
<?php
}
2019-08-16 19:42:18 +03:00
break;
2024-04-15 17:58:18 +03:00
case 'timepicker':
2019-08-16 19:42:18 +03:00
$range = $this->timepicker_filters_range( $filter );
$label = ! empty( $attrs['label'] ) ? $attrs['label'] : $attrs['title'];
2024-04-15 17:58:18 +03:00
$label = stripslashes( $label );
2019-08-16 19:42:18 +03:00
switch ( $attrs['format'] ) {
case 'g:i a':
2024-04-17 01:46:48 +03:00
default:
2019-08-16 19:42:18 +03:00
$js_format = 'h:i a';
break;
case 'g:i A':
$js_format = 'h:i A';
break;
case 'H:i':
$js_format = 'HH:i';
break;
}
2024-04-17 01:46:48 +03:00
$default_value_min = '';
$default_value_max = '';
2024-04-16 13:24:08 +03:00
if ( ! empty( $default_value[0] ) ) {
$default_value_min = $default_value[0];
}
if ( ! empty( $default_value[1] ) ) {
$default_value_max = $default_value[1];
}
2024-04-15 17:58:18 +03:00
if ( $range ) {
?>
<input type="text" id="<?php echo esc_attr( $filter ); ?>_from" name="<?php echo esc_attr( $filter ); ?>_from" class="um-timepicker-filter"
<?php // translators: %s: Timepicker filter label. ?>
placeholder="<?php echo esc_attr( sprintf( __( '%s From', 'ultimate-member' ), $label ) ); ?>"
data-filter-label="<?php echo esc_attr( $label ); ?>"
data-min="<?php echo esc_attr( $range[0] ); ?>" data-max="<?php echo esc_attr( $range[1] ); ?>"
data-format="<?php echo esc_attr( $js_format ); ?>" data-intervals="<?php echo esc_attr( $attrs['intervals'] ); ?>"
2024-04-16 13:24:08 +03:00
data-filter_name="<?php echo esc_attr( $filter ); ?>" data-range="from" data-value="<?php echo ! empty( $default_value_min ) ? esc_attr( $default_value_min ) : ''; ?>" />
2024-04-15 17:58:18 +03:00
<input type="text" id="<?php echo esc_attr( $filter ); ?>_to" name="<?php echo esc_attr( $filter ); ?>_to" class="um-timepicker-filter"
<?php // translators: %s: Timepicker filter label. ?>
placeholder="<?php echo esc_attr( sprintf( __( '%s To', 'ultimate-member' ), $label ) ); ?>"
data-filter-label="<?php echo esc_attr( $label ); ?>"
data-min="<?php echo esc_attr( $range[0] ); ?>" data-max="<?php echo esc_attr( $range[1] ); ?>"
data-format="<?php echo esc_attr( $js_format ); ?>" data-intervals="<?php echo esc_attr( $attrs['intervals'] ); ?>"
2024-04-16 13:24:08 +03:00
data-filter_name="<?php echo esc_attr( $filter ); ?>" data-range="to" data-value="<?php echo ! empty( $default_value_max ) ? esc_attr( $default_value_max ) : ''; ?>" />
2024-04-15 17:58:18 +03:00
<?php
}
2019-08-16 19:42:18 +03:00
break;
}
$filter = ob_get_clean();
return $filter;
}
/**
2019-09-04 14:54:03 +03:00
* @param string $filter
* @param array $directory_data
2019-08-16 19:42:18 +03:00
*
* @return mixed
*/
2019-09-04 14:54:03 +03:00
function slider_filters_range( $filter, $directory_data ) {
2020-03-31 12:35:09 +03:00
global $wpdb;
2019-08-16 19:42:18 +03:00
2021-03-08 16:59:11 +02:00
$range = false;
2019-08-16 19:42:18 +03:00
switch ( $filter ) {
2025-06-27 14:24:08 +03:00
default:
2025-02-03 16:17:37 +02:00
$meta = $wpdb->get_row(
$wpdb->prepare(
"SELECT MIN( CONVERT( meta_value, DECIMAL ) ) as min_meta,
MAX( CONVERT( meta_value, DECIMAL ) ) as max_meta,
COUNT( DISTINCT meta_value ) as amount
FROM {$wpdb->usermeta}
2025-06-27 14:24:08 +03:00
WHERE meta_key = %s AND
meta_value != ''",
2025-02-03 16:17:37 +02:00
$filter
),
ARRAY_A
);
2020-01-14 11:58:25 +02:00
2021-03-08 16:59:11 +02:00
if ( isset( $meta['min_meta'] ) && isset( $meta['max_meta'] ) && isset( $meta['amount'] ) && $meta['amount'] > 1 ) {
2021-03-03 17:17:54 +02:00
$range = array( (float) $meta['min_meta'], (float) $meta['max_meta'] );
2019-08-16 19:42:18 +03:00
}
2020-02-24 16:27:26 +02:00
$range = apply_filters( 'um_member_directory_filter_slider_common', $range, $directory_data, $filter );
2019-09-04 14:54:03 +03:00
$range = apply_filters( "um_member_directory_filter_{$filter}_slider", $range, $directory_data );
2019-08-16 19:42:18 +03:00
break;
2025-06-27 14:24:08 +03:00
case 'birth_date':
2020-01-14 11:58:25 +02:00
$meta = $wpdb->get_row(
2020-02-26 13:43:08 +02:00
"SELECT MIN( meta_value ) as min_meta,
MAX( meta_value ) as max_meta,
COUNT( DISTINCT meta_value ) as amount
FROM {$wpdb->usermeta}
2020-10-21 10:27:15 +03:00
WHERE meta_key = 'birth_date' AND
2020-10-29 18:54:15 +02:00
meta_value != ''",
2025-02-03 16:17:37 +02:00
ARRAY_A
);
2019-08-16 19:42:18 +03:00
2021-03-08 16:59:11 +02:00
if ( isset( $meta['min_meta'] ) && isset( $meta['max_meta'] ) && isset( $meta['amount'] ) && $meta['amount'] > 1 ) {
2020-01-13 17:31:25 +02:00
$range = array( $this->borndate( strtotime( $meta['max_meta'] ) ), $this->borndate( strtotime( $meta['min_meta'] ) ) );
2019-08-16 19:42:18 +03:00
}
break;
}
return $range;
}
/**
* @param $filter
*
* @return mixed
*/
2019-09-04 14:54:03 +03:00
function slider_range_placeholder( $filter, $attrs ) {
2019-08-16 19:42:18 +03:00
switch ( $filter ) {
default: {
2021-12-11 02:55:42 +02:00
$label = ! empty( $attrs['label'] ) ? $attrs['label'] : $filter;
$label = ucwords( str_replace( array( 'um_', '_' ), array( '', ' ' ), $label ) );
2020-01-02 17:21:02 +02:00
$placeholders = apply_filters( 'um_member_directory_filter_slider_range_placeholder', false, $filter );
2019-09-04 14:54:03 +03:00
2020-01-02 17:21:02 +02:00
if ( ! $placeholders ) {
2019-09-04 14:54:03 +03:00
switch ( $attrs['type'] ) {
default:
2020-01-02 17:21:02 +02:00
$placeholders = array(
"<strong>$label:</strong> {value}",
"<strong>$label:</strong> {min_range} - {max_range}",
);
2019-09-04 14:54:03 +03:00
break;
case 'rating':
2020-01-02 17:21:02 +02:00
$placeholders = array(
"<strong>$label:</strong> {value}" . __( ' stars', 'ultimate-member' ),
"<strong>$label:</strong> {min_range} - {max_range}" . __( ' stars', 'ultimate-member' )
);
2019-09-04 14:54:03 +03:00
break;
}
}
2019-08-16 19:42:18 +03:00
break;
}
case 'birth_date': {
2020-01-02 17:21:02 +02:00
$placeholders = array(
__( '<strong>Age:</strong> {value} years old', 'ultimate-member' ),
__( '<strong>Age:</strong> {min_range} - {max_range} years old', 'ultimate-member' )
);
2019-08-16 19:42:18 +03:00
break;
}
}
2020-01-02 17:21:02 +02:00
return $placeholders;
2019-08-16 19:42:18 +03:00
}
/**
* @param $filter
*
* @return mixed
*/
2023-12-01 02:17:37 +02:00
public function datepicker_filters_range( $filter ) {
2019-08-16 19:42:18 +03:00
global $wpdb;
switch ( $filter ) {
2023-12-01 02:17:37 +02:00
default:
2019-08-16 19:42:18 +03:00
global $wpdb;
2025-02-03 16:17:37 +02:00
$meta = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT meta_value
FROM {$wpdb->usermeta}
2025-06-23 12:45:55 +03:00
WHERE meta_key = %s AND
meta_value != ''
2025-02-03 16:17:37 +02:00
ORDER BY meta_value DESC",
$filter
)
);
2019-08-16 19:42:18 +03:00
if ( empty( $meta ) || count( $meta ) === 1 ) {
$range = false;
} elseif ( ! empty( $meta ) ) {
$range = array( strtotime( min( $meta ) ), strtotime( max( $meta ) ) );
}
$range = apply_filters( "um_member_directory_filter_{$filter}_datepicker", $range );
break;
2023-12-01 02:17:37 +02:00
case 'last_login':
$meta = $wpdb->get_row(
"SELECT DISTINCT COUNT(*) AS total,
MIN(meta_value) AS min,
MAX(meta_value) AS max
2019-08-16 19:42:18 +03:00
FROM {$wpdb->usermeta}
2025-06-23 12:45:55 +03:00
WHERE meta_key = '_um_last_login' AND
meta_value != ''",
2023-12-01 02:17:37 +02:00
ARRAY_A
);
if ( empty( $meta['total'] ) || 1 === absint( $meta['total'] ) ) {
2019-08-16 19:42:18 +03:00
$range = false;
2023-12-01 02:17:37 +02:00
} elseif ( array_key_exists( 'min', $meta ) && array_key_exists( 'max', $meta ) ) {
2024-01-09 10:44:26 +02:00
$range = array( strtotime( $meta['min'] ), strtotime( $meta['max'] ) );
2019-08-16 19:42:18 +03:00
}
break;
2023-12-01 02:17:37 +02:00
case 'user_registered':
2019-08-16 19:42:18 +03:00
$meta = $wpdb->get_col(
"SELECT DISTINCT user_registered
FROM {$wpdb->users}
ORDER BY user_registered DESC"
);
if ( empty( $meta ) || count( $meta ) === 1 ) {
$range = false;
} elseif ( ! empty( $meta ) ) {
$range = array( strtotime( min( $meta ) ), strtotime( max( $meta ) ) );
}
break;
}
return $range;
}
/**
* @param $filter
*
* @return mixed
*/
2024-04-17 01:46:48 +03:00
protected function timepicker_filters_range( $filter ) {
global $wpdb;
$meta = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT meta_value
FROM {$wpdb->usermeta}
2025-06-23 12:45:55 +03:00
WHERE meta_key = %s AND
meta_value != ''
2024-04-17 01:46:48 +03:00
ORDER BY meta_value DESC",
$filter
)
);
2019-08-16 19:42:18 +03:00
2024-04-17 01:46:48 +03:00
$meta = array_filter( $meta );
2019-08-16 19:42:18 +03:00
2024-04-17 01:46:48 +03:00
if ( empty( $meta ) || count( $meta ) === 1 ) {
$range = false;
} elseif ( ! empty( $meta ) ) {
$range = array( min( $meta ), max( $meta ) );
2019-08-16 19:42:18 +03:00
}
2024-04-17 01:46:48 +03:00
return apply_filters( "um_member_directory_filter_{$filter}_timepicker", $range );
2019-08-16 19:42:18 +03:00
}
/**
* @param $borndate
*
* @return false|string
*/
function borndate( $borndate ) {
if ( date('m', $borndate) > date('m') || date('m', $borndate) == date('m') && date('d', $borndate ) > date('d')) {
return (date('Y') - date('Y', $borndate ) - 1);
}
return (date('Y') - date('Y', $borndate));
}
/**
2019-09-02 16:35:10 +03:00
* Handle members can view restrictions
2019-08-16 19:42:18 +03:00
*/
2019-09-02 16:35:10 +03:00
function restriction_options() {
$this->hide_not_approved();
$this->hide_by_role();
$this->hide_by_account_settings();
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
do_action( 'um_member_directory_restrictions_handle_extend' );
2019-08-16 19:42:18 +03:00
}
/**
*
*/
function hide_not_approved() {
if ( UM()->roles()->um_user_can( 'can_edit_everyone' ) ) {
return;
}
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( array(
2020-01-06 11:05:32 +02:00
'key' => 'um_member_directory_data',
'value' => 's:14:"account_status";s:8:"approved";',
'compare' => 'LIKE'
2019-08-16 19:42:18 +03:00
) ) );
}
/**
*
*/
function hide_by_role() {
2020-07-23 16:06:59 +03:00
if ( ! is_user_logged_in() ) {
return;
}
2019-08-16 19:42:18 +03:00
$roles = um_user( 'can_view_roles' );
$roles = maybe_unserialize( $roles );
2020-07-23 16:06:59 +03:00
if ( UM()->roles()->um_user_can( 'can_view_all' ) && empty( $roles ) ) {
2019-08-16 19:42:18 +03:00
return;
}
if ( ! empty( $this->query_args['role__in'] ) ) {
$this->query_args['role__in'] = is_array( $this->query_args['role__in'] ) ? $this->query_args['role__in'] : array( $this->query_args['role__in'] );
$this->query_args['role__in'] = array_intersect( $this->query_args['role__in'], $roles );
} else {
$this->query_args['role__in'] = $roles;
}
}
/**
*
*/
function hide_by_account_settings() {
if ( ! UM()->options()->get( 'account_hide_in_directory' ) ) {
return;
}
if ( UM()->roles()->um_user_can( 'can_edit_everyone' ) ) {
return;
}
2020-01-06 11:05:32 +02:00
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( array(
'key' => 'um_member_directory_data',
'value' => 's:15:"hide_in_members";b:0;',
'compare' => 'LIKE'
) ) );
2019-08-16 19:42:18 +03:00
}
/**
2019-09-02 16:35:10 +03:00
* Handle "General Options" metabox settings
*
* @param array $directory_data
*/
function general_options( $directory_data ) {
$this->show_selected_roles( $directory_data );
$this->show_only_with_avatar( $directory_data );
$this->show_only_with_cover( $directory_data );
$this->show_only_these_users( $directory_data );
2020-03-31 14:42:24 +03:00
$this->exclude_these_users( $directory_data );
2019-09-02 16:35:10 +03:00
do_action( 'um_member_directory_general_options_handle_extend', $directory_data );
}
/**
* Handle "User Roles to Display" option
*
* @param array $directory_data
*/
function show_selected_roles( $directory_data ) {
// add roles to appear in directory
if ( ! empty( $directory_data['roles'] ) ) {
//since WP4.4 use 'role__in' argument
2019-12-12 14:22:14 +02:00
if ( ! empty( $this->query_args['role__in'] ) ) {
$this->query_args['role__in'] = is_array( $this->query_args['role__in'] ) ? $this->query_args['role__in'] : array( $this->query_args['role__in'] );
$this->query_args['role__in'] = array_intersect( $this->query_args['role__in'], maybe_unserialize( $directory_data['roles'] ) );
} else {
$this->query_args['role__in'] = maybe_unserialize( $directory_data['roles'] );
}
2019-09-02 16:35:10 +03:00
}
}
/**
* Handle "Only show members who have uploaded a profile photo" option
*
* @param array $directory_data
*/
function show_only_with_avatar( $directory_data ) {
if ( $directory_data['has_profile_photo'] == 1 ) {
2020-01-06 11:05:32 +02:00
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( array(
'key' => 'um_member_directory_data',
'value' => 's:13:"profile_photo";b:1;',
'compare' => 'LIKE'
) ) );
2019-09-02 16:35:10 +03:00
}
}
/**
* Handle "Only show members who have uploaded a cover photo" option
*
* @param array $directory_data
2019-08-16 19:42:18 +03:00
*/
2019-09-02 16:35:10 +03:00
function show_only_with_cover( $directory_data ) {
if ( $directory_data['has_cover_photo'] == 1 ) {
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( array(
2020-01-06 11:05:32 +02:00
'key' => 'um_member_directory_data',
'value' => 's:11:"cover_photo";b:1;',
'compare' => 'LIKE'
2019-09-02 16:35:10 +03:00
) ) );
}
}
/**
* Handle "Only show specific users (Enter one username per line)" option
*
* @param array $directory_data
*/
function show_only_these_users( $directory_data ) {
2019-09-11 16:07:51 +03:00
if ( ! empty( $directory_data['show_these_users'] ) ) {
$show_these_users = maybe_unserialize( $directory_data['show_these_users'] );
2019-09-02 16:35:10 +03:00
2019-09-11 16:07:51 +03:00
if ( is_array( $show_these_users ) && ! empty( $show_these_users ) ) {
$users_array = array();
foreach ( $show_these_users as $username ) {
if ( false !== ( $exists_id = username_exists( $username ) ) ) {
$users_array[] = $exists_id;
}
}
if ( ! empty( $users_array ) ) {
$this->query_args['include'] = $users_array;
2019-09-02 16:35:10 +03:00
}
}
}
}
2020-03-31 14:42:24 +03:00
/**
* Handle "Exclude specific users (Enter one username per line)" option
*
* @param array $directory_data
*/
function exclude_these_users( $directory_data ) {
if ( ! empty( $directory_data['exclude_these_users'] ) ) {
$exclude_these_users = maybe_unserialize( $directory_data['exclude_these_users'] );
if ( is_array( $exclude_these_users ) && ! empty( $exclude_these_users ) ) {
$users_array = array();
foreach ( $exclude_these_users as $username ) {
if ( false !== ( $exists_id = username_exists( $username ) ) ) {
$users_array[] = $exists_id;
}
}
if ( ! empty( $users_array ) ) {
$this->query_args['exclude'] = $users_array;
}
}
}
}
2019-09-02 16:35:10 +03:00
/**
* Handle "Pagination Options" metabox settings
*
* @param array $directory_data
*/
function pagination_options( $directory_data ) {
// number of profiles for mobile
$profiles_per_page = $directory_data['profiles_per_page'];
2024-12-17 21:53:18 +02:00
if ( wp_is_mobile() && isset( $directory_data['profiles_per_page_mobile'] ) ) {
2019-09-02 16:35:10 +03:00
$profiles_per_page = $directory_data['profiles_per_page_mobile'];
}
$this->query_args['number'] = ( ! empty( $directory_data['max_users'] ) && $directory_data['max_users'] <= $profiles_per_page ) ? $directory_data['max_users'] : $profiles_per_page;
2021-06-29 02:51:54 +03:00
$this->query_args['paged'] = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1;
2019-09-02 16:35:10 +03:00
}
/**
* Add sorting attributes for \WP_Users_Query
*
* @param array $directory_data Member Directory options
*/
2024-02-08 13:47:15 +02:00
public function sorting_query( $directory_data ) {
2019-08-16 19:42:18 +03:00
// sort members by
$this->query_args['order'] = 'ASC';
2024-02-08 13:47:15 +02:00
2021-06-29 02:51:54 +03:00
$sortby = ! empty( $_POST['sorting'] ) ? sanitize_text_field( $_POST['sorting'] ) : $directory_data['sortby'];
2024-02-08 13:47:15 +02:00
$sortby = ( 'other' === $sortby ) ? $directory_data['sortby_custom'] : $sortby;
2019-08-16 19:42:18 +03:00
2020-01-13 10:18:30 +02:00
$custom_sort = array();
2020-01-29 13:22:03 +02:00
if ( ! empty( $directory_data['sorting_fields'] ) ) {
$sorting_fields = maybe_unserialize( $directory_data['sorting_fields'] );
foreach ( $sorting_fields as $field ) {
if ( is_array( $field ) ) {
2024-02-08 13:47:15 +02:00
$field_keys = array_keys( $field );
2020-01-29 13:22:03 +02:00
$custom_sort[] = $field_keys[0];
}
2020-01-13 10:18:30 +02:00
}
}
2022-06-09 17:17:15 +03:00
$numeric_sorting_keys = array();
if ( ! empty( UM()->builtin()->saved_fields ) ) {
foreach ( UM()->builtin()->saved_fields as $key => $data ) {
2023-12-01 02:17:37 +02:00
if ( '_um_last_login' === $key ) {
2022-06-09 17:17:15 +03:00
continue;
}
if ( isset( $data['type'] ) && 'number' === $data['type'] ) {
if ( array_key_exists( $key . '_desc', $this->sort_fields ) ) {
$numeric_sorting_keys[] = $key . '_desc';
}
if ( array_key_exists( $key . '_asc', $this->sort_fields ) ) {
$numeric_sorting_keys[] = $key . '_asc';
}
}
}
}
2021-07-02 17:36:01 +03:00
if ( 'username' == $sortby ) {
$this->query_args['orderby'] = 'user_login';
$this->query_args['order'] = 'ASC';
} elseif ( 'display_name' == $sortby ) {
2019-08-16 19:42:18 +03:00
$display_name = UM()->options()->get( 'display_name' );
if ( $display_name == 'username' ) {
$this->query_args['orderby'] = 'user_login';
$this->query_args['order'] = 'ASC';
} else {
$this->query_args['meta_query'][] = array(
'relation' => 'OR',
'full_name' => array(
'key' => 'full_name',
'compare' => 'EXISTS'
),
array(
'key' => 'full_name',
'compare' => 'NOT EXISTS'
)
);
$this->query_args['orderby'] = 'full_name, display_name';
$this->query_args['order'] = 'ASC';
}
2024-02-08 13:47:15 +02:00
} elseif ( in_array( $sortby, array( 'last_name', 'first_name', 'nickname' ), true ) ) {
2019-08-16 19:42:18 +03:00
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $sortby . '_c' => array(
'key' => $sortby,
'compare' => 'EXISTS',
), ) );
$this->query_args['orderby'] = array( $sortby . '_c' => 'ASC' );
unset( $this->query_args['order'] );
2023-12-01 02:17:37 +02:00
} elseif ( 'last_login' === $sortby ) {
2024-04-24 02:43:59 +03:00
$this->query_args['orderby'] = array( 'um_last_login' => 'DESC' );
// Please use custom meta table for better results and sorting. Here we only hide the users without visible last login date.
2019-08-16 19:42:18 +03:00
$this->query_args['meta_query'][] = array(
2024-04-24 16:04:07 +03:00
'relation' => 'OR',
2019-08-16 19:42:18 +03:00
array(
2024-04-24 16:04:07 +03:00
'key' => '_um_last_login',
'compare' => 'EXISTS',
'type' => 'DATETIME',
2019-08-16 19:42:18 +03:00
),
2024-04-24 16:04:07 +03:00
'um_last_login' => array(
'key' => '_um_last_login',
'compare' => 'NOT EXISTS',
'type' => 'DATETIME',
2019-08-16 19:42:18 +03:00
),
);
unset( $this->query_args['order'] );
2024-04-24 16:04:07 +03:00
2024-04-25 01:30:22 +03:00
add_filter( 'pre_user_query', array( &$this, 'sortby_last_login' ) );
2019-12-05 11:19:49 +02:00
} elseif ( $sortby == 'last_first_name' ) {
$this->query_args['meta_query'][] = array(
'last_name_c' => array(
'key' => 'last_name',
'compare' => 'EXISTS',
),
'first_name_c' => array(
'key' => 'first_name',
'compare' => 'EXISTS',
),
);
$this->query_args['orderby'] = array( 'last_name_c' => 'ASC', 'first_name_c' => 'ASC' );
unset( $this->query_args['order'] );
2024-02-08 13:47:15 +02:00
} elseif ( count( $numeric_sorting_keys ) && in_array( $sortby, $numeric_sorting_keys, true ) ) {
2022-06-09 17:17:15 +03:00
$order = 'DESC';
if ( strstr( $sortby, '_desc' ) ) {
$sortby = str_replace( '_desc', '', $sortby );
$order = 'DESC';
}
if ( strstr( $sortby, '_asc' ) ) {
$sortby = str_replace( '_asc', '', $sortby );
$order = 'ASC';
}
$this->query_args['meta_query'] = array_merge(
$this->query_args['meta_query'],
array(
array(
'relation' => 'OR',
array(
'key' => $sortby,
'compare' => 'EXISTS',
'type' => 'NUMERIC',
),
$sortby . '_ns' => array(
'key' => $sortby,
'compare' => 'NOT EXISTS',
'type' => 'NUMERIC',
),
),
)
);
2024-02-08 13:47:15 +02:00
$this->query_args['orderby'] = array(
$sortby . '_ns' => $order,
'user_registered' => 'DESC',
);
2022-06-09 17:17:15 +03:00
unset( $this->query_args['order'] );
2024-02-08 13:47:15 +02:00
} elseif ( ( ! empty( $directory_data['sortby_custom'] ) && $sortby === $directory_data['sortby_custom'] ) || in_array( $sortby, $custom_sort, true ) ) {
2023-06-12 13:20:00 +03:00
$custom_sort_order = ! empty( $directory_data['sortby_custom_order'] ) ? $directory_data['sortby_custom_order'] : 'ASC';
2020-10-14 11:42:59 +03:00
2023-06-12 13:20:00 +03:00
$meta_query = new \WP_Meta_Query();
$custom_sort_type = ! empty( $directory_data['sortby_custom_type'] ) ? $meta_query->get_cast_for_type( $directory_data['sortby_custom_type'] ) : 'CHAR';
2024-02-08 13:47:15 +02:00
2023-05-24 15:24:29 +03:00
if ( ! empty( $directory_data['sorting_fields'] ) ) {
2023-06-12 13:20:00 +03:00
// phpcs:ignore WordPress.Security.NonceVerification -- already verified here
2023-05-24 15:24:29 +03:00
$sorting = sanitize_text_field( $_POST['sorting'] );
2024-02-08 13:47:15 +02:00
$sorting_fields = maybe_unserialize( $directory_data['sorting_fields'] );
2023-07-01 12:46:43 +03:00
if ( ! empty( $sorting_fields ) && is_array( $sorting_fields ) ) {
foreach ( $sorting_fields as $field ) {
if ( isset( $field[ $sorting ] ) ) {
$custom_sort_type = ! empty( $field['type'] ) ? $meta_query->get_cast_for_type( $field['type'] ) : 'CHAR';
$custom_sort_order = $field['order'];
}
2023-05-24 15:24:29 +03:00
}
}
}
2023-06-12 13:20:00 +03:00
/**
* Filters the sorting MySQL type in member directory custom sorting query.
*
* Note: Possible MySQL types are BINARY|CHAR|DATE|DATETIME|SIGNED|UNSIGNED|TIME|DECIMAL
*
* @since 2.1.3
* @hook um_member_directory_custom_sorting_type
*
* @param {string} $custom_sort_type MySQL type to cast meta_value. 'CHAR' is default.
* @param {string} $sortby meta_key used for sorting.
* @param {array} $directory_data Member directory data.
*
* @return {string} MySQL type to cast meta_value.
* @example <caption>Change type to DATE by the directory ID and mete_key.</caption>
* function my_um_member_directory_custom_sorting_type( $custom_sort_type, $sortby, $directory_data ) {
* if ( '{selected member directory ID}' == $directory_data['form_id'] && '{custom_date_key}' === $sortby ) {
* $custom_sort_type = 'DATE';
* }
*
* return $custom_sort_type;
* }
* add_filter( 'um_member_directory_custom_sorting_type', 'my_um_member_directory_custom_sorting_type', 10, 3 );
*/
2023-05-23 18:25:53 +03:00
$custom_sort_type = apply_filters( 'um_member_directory_custom_sorting_type', $custom_sort_type, $sortby, $directory_data );
2020-10-14 11:42:59 +03:00
$this->query_args['meta_query'][] = array(
2023-05-24 15:24:29 +03:00
'relation' => 'OR',
2020-10-14 11:42:59 +03:00
$sortby . '_cs' => array(
2023-05-24 15:24:29 +03:00
'key' => $sortby,
'compare' => 'EXISTS',
'type' => $custom_sort_type,
2020-10-14 11:42:59 +03:00
),
array(
2023-05-24 15:24:29 +03:00
'key' => $sortby,
'compare' => 'NOT EXISTS',
),
2020-10-14 11:42:59 +03:00
);
2023-05-24 15:24:29 +03:00
$this->query_args['orderby'] = array(
$sortby . '_cs' => $custom_sort_order,
'user_login' => 'ASC',
);
2020-10-14 11:42:59 +03:00
2019-08-16 19:42:18 +03:00
} else {
if ( strstr( $sortby, '_desc' ) ) {
$sortby = str_replace( '_desc', '', $sortby );
2023-12-01 02:17:37 +02:00
$order = 'DESC';
2019-08-16 19:42:18 +03:00
}
if ( strstr( $sortby, '_asc' ) ) {
$sortby = str_replace( '_asc', '', $sortby );
2023-12-01 02:17:37 +02:00
$order = 'ASC';
2019-08-16 19:42:18 +03:00
}
$this->query_args['orderby'] = $sortby;
if ( isset( $order ) ) {
$this->query_args['order'] = $order;
}
add_filter( 'pre_user_query', array( &$this, 'sortby_randomly' ), 10, 1 );
}
/**
* UM hook
*
* @type filter
* @title um_modify_sortby_parameter
* @description Change query sort by attributes for search at Members Directory
* @input_vars
* [{"var":"$query_args","type":"array","desc":"Query Arguments"},
* {"var":"$sortby","type":"string","desc":"Sort by"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_modify_sortby_parameter', 'function_name', 10, 2 ); ?>
* @example
* <?php
* add_filter( 'um_modify_sortby_parameter', 'my_modify_sortby_parameter', 10, 2 );
* function my_modify_sortby_parameter( $query_args, $sortby ) {
* // your code here
* return $query_args;
* }
* ?>
*/
$this->query_args = apply_filters( 'um_modify_sortby_parameter', $this->query_args, $sortby );
}
/**
* Sorting random
*
* @param object $query
*
* @return mixed
*/
function sortby_randomly( $query ) {
if ( 'random' == $query->query_vars['orderby'] ) {
if ( um_is_session_started() === false ) {
@session_start();
}
// Reset seed on load of initial
2019-11-26 01:07:17 +02:00
if ( empty( $_REQUEST['directory_id'] ) && isset( $_SESSION['um_member_directory_seed'] ) ) {
unset( $_SESSION['um_member_directory_seed'] );
2019-08-16 19:42:18 +03:00
}
// Get seed from session variable if it exists
$seed = false;
2019-11-26 01:07:17 +02:00
if ( isset( $_SESSION['um_member_directory_seed'] ) ) {
$seed = $_SESSION['um_member_directory_seed'];
2019-08-16 19:42:18 +03:00
}
// Set new seed if none exists
if ( ! $seed ) {
$seed = rand();
2019-11-26 01:07:17 +02:00
$_SESSION['um_member_directory_seed'] = $seed;
2019-08-16 19:42:18 +03:00
}
$query->query_orderby = 'ORDER by RAND(' . $seed . ')';
}
return $query;
}
2024-04-24 16:04:07 +03:00
/**
* Sorting by last login
*
* @param object $query
*
* @return mixed
*/
public function sortby_last_login( $query ) {
if ( array_key_exists( 'um_last_login', $query->query_vars['orderby'] ) ) {
global $wpdb;
2024-04-25 01:30:22 +03:00
$query->query_from .= " LEFT JOIN {$wpdb->prefix}usermeta AS umm_sort ON ( umm_sort.user_id = {$wpdb->prefix}users.ID AND umm_sort.meta_key = '_um_last_login' ) ";
$query->query_from .= " LEFT JOIN {$wpdb->prefix}usermeta AS umm_show_login ON ( umm_show_login.user_id = {$wpdb->prefix}users.ID AND umm_show_login.meta_key = 'um_show_last_login' ) ";
2024-04-24 16:04:07 +03:00
$query->query_orderby = " ORDER BY CASE ISNULL(NULLIF(umm_show_login.meta_value,'a:1:{i:0;s:3:\"yes\";}')) WHEN 0 THEN '1970-01-01 00:00:00' ELSE CAST( umm_sort.meta_value AS DATETIME ) END DESC ";
}
return $query;
}
2023-09-20 21:31:50 +03:00
/**
* Prepare the search line. Avoid the using mySQL statement.
*
* @param string $search
*
* @return string
*/
protected function prepare_search( $search ) {
// unslash, sanitize, trim - necessary prepare.
$search = trim( sanitize_text_field( wp_unslash( $search ) ) );
if ( empty( $search ) ) {
return '';
}
2025-03-25 23:31:13 +02:00
return $search;
2023-09-20 21:31:50 +03:00
}
2019-09-02 16:35:10 +03:00
/**
* Handle general search line request
*/
2023-09-20 21:31:50 +03:00
public function general_search() {
2025-01-08 12:20:35 +02:00
// General search
2019-08-16 19:42:18 +03:00
if ( ! empty( $_POST['search'] ) ) {
2019-09-02 16:35:10 +03:00
// complex using with change_meta_sql function
2023-09-20 21:31:50 +03:00
$search = $this->prepare_search( $_POST['search'] );
if ( ! empty( $search ) ) {
2025-03-25 23:31:13 +02:00
$meta_query = array();
2023-09-20 21:31:50 +03:00
$meta_query = apply_filters( 'um_member_directory_general_search_meta_query', $meta_query, $search );
2019-09-23 13:34:25 +03:00
2025-03-25 23:31:13 +02:00
if ( ! empty( $meta_query ) ) {
$this->query_args['meta_query'][] = $meta_query;
2023-03-29 11:57:42 +03:00
}
2025-03-25 23:31:13 +02:00
$this->is_search = true;
2019-08-16 19:42:18 +03:00
}
}
}
/**
2019-09-02 16:35:10 +03:00
* Handle filters request
2019-08-16 19:42:18 +03:00
*/
2019-09-02 16:35:10 +03:00
function filters( $directory_data ) {
2024-03-28 12:24:29 +02:00
global $wpdb;
2019-08-16 19:42:18 +03:00
//filters
2019-08-20 15:40:00 +03:00
$filter_query = array();
2019-09-02 16:35:10 +03:00
if ( ! empty( $directory_data['search_fields'] ) ) {
$search_filters = maybe_unserialize( $directory_data['search_fields'] );
2021-07-02 17:36:01 +03:00
2019-08-16 19:42:18 +03:00
if ( ! empty( $search_filters ) && is_array( $search_filters ) ) {
2019-08-20 15:40:00 +03:00
$filter_query = array_intersect_key( $_POST, array_flip( $search_filters ) );
2019-08-16 19:42:18 +03:00
}
}
2019-11-04 21:17:13 +02:00
// added for user tags extension integration on individual tag page
2019-09-30 01:27:01 +03:00
$ignore_empty_filters = apply_filters( 'um_member_directory_ignore_empty_filters', false );
if ( empty( $filter_query ) && ! $ignore_empty_filters ) {
2019-08-20 15:40:00 +03:00
return;
}
2019-08-16 19:42:18 +03:00
2019-11-20 17:07:38 +02:00
$this->is_search = true;
2019-08-20 15:40:00 +03:00
foreach ( $filter_query as $field => $value ) {
2021-06-29 02:51:54 +03:00
$field = sanitize_text_field( $field );
2021-07-02 17:36:01 +03:00
if ( is_array( $value ) ) {
$value = array_map( 'sanitize_text_field', $value );
} else {
$value = sanitize_text_field( $value );
}
2019-08-16 19:42:18 +03:00
2019-11-21 09:44:58 +02:00
$attrs = UM()->fields()->get_field( $field );
// skip private invisible fields
if ( ! um_can_view_field( $attrs ) ) {
continue;
}
2024-03-28 12:24:29 +02:00
/** This filter is documented in includes/core/class-member-directory-meta.php */
$relation = apply_filters( 'um_members_directory_select_filter_relation', 'OR', $field );
2019-08-20 15:40:00 +03:00
switch ( $field ) {
default:
2019-09-02 16:35:10 +03:00
$filter_type = $this->filter_types[ $field ];
2019-08-16 19:42:18 +03:00
2019-08-20 15:40:00 +03:00
/**
* UM hook
*
* @type filter
* @title um_query_args_{$field}__filter
* @description Change field's query for search at Members Directory
* @input_vars
* [{"var":"$field_query","type":"array","desc":"Field query"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_query_args_{$field}__filter', 'function_name', 10, 1 ); ?>
* @example
* <?php
* add_filter( 'um_query_args_{$field}__filter', 'my_query_args_filter', 10, 1 );
* function my_query_args_filter( $field_query ) {
* // your code here
* return $field_query;
* }
* ?>
*/
2019-09-02 16:35:10 +03:00
$field_query = apply_filters( "um_query_args_{$field}__filter", false, $field, $value, $filter_type );
2020-02-21 09:01:18 +02:00
$field_query = apply_filters( 'um_query_args_filter_global', $field_query, $field, $value, $filter_type );
2019-09-02 16:35:10 +03:00
if ( ! $field_query ) {
switch ( $filter_type ) {
default:
$field_query = apply_filters( "um_query_args_{$field}_{$filter_type}__filter", false, $field, $value, $filter_type );
break;
2019-11-20 17:07:38 +02:00
case 'text':
$value = stripslashes( $value );
$field_query = array(
'relation' => 'OR',
array(
'key' => $field,
'value' => trim( $value ),
2021-04-02 14:52:24 +03:00
'compare' => apply_filters( 'um_members_directory_filter_text', 'LIKE', $field )
2019-11-20 17:07:38 +02:00
),
);
$this->custom_filters_in_query[ $field ] = $value;
break;
2019-09-02 16:35:10 +03:00
case 'select':
if ( is_array( $value ) ) {
2024-03-28 12:24:29 +02:00
$field_query = array( 'relation' => esc_sql( $relation ) );
2019-09-02 16:35:10 +03:00
foreach ( $value as $single_val ) {
2020-11-24 12:55:22 +02:00
$single_val = trim( stripslashes( $single_val ) );
2019-11-20 17:07:38 +02:00
2019-09-02 16:35:10 +03:00
$arr_meta_query = array(
array(
2024-03-13 11:25:41 +02:00
'key' => $field,
'value' => $single_val,
'compare' => '=',
2019-09-02 16:35:10 +03:00
),
array(
2024-03-13 11:25:41 +02:00
'key' => $field,
'value' => serialize( (string) $single_val ),
'compare' => 'LIKE',
2019-09-02 16:35:10 +03:00
),
array(
2024-03-13 11:25:41 +02:00
'key' => $field,
'value' => '"' . $single_val . '"',
'compare' => 'LIKE',
),
2019-09-02 16:35:10 +03:00
);
if ( is_numeric( $single_val ) ) {
$arr_meta_query[] = array(
2024-03-13 11:25:41 +02:00
'key' => $field,
'value' => serialize( absint( $single_val ) ),
'compare' => 'LIKE',
2019-09-02 16:35:10 +03:00
);
}
$field_query = array_merge( $field_query, $arr_meta_query );
}
}
2019-10-01 11:53:34 +03:00
$this->custom_filters_in_query[ $field ] = $value;
2019-09-02 16:35:10 +03:00
break;
case 'slider':
2019-10-01 11:53:34 +03:00
$this->custom_filters_in_query[ $field ] = $value;
2019-09-02 16:35:10 +03:00
$field_query = array(
2019-09-04 14:54:03 +03:00
'key' => $field,
'value' => $value,
'compare' => 'BETWEEN',
'inclusive' => true,
2021-05-03 14:30:51 +08:00
'type' => 'NUMERIC',
2019-09-02 16:35:10 +03:00
);
break;
case 'datepicker':
$offset = 0;
if ( isset( $_POST['gmt_offset'] ) && is_numeric( $_POST['gmt_offset'] ) ) {
$offset = (int) $_POST['gmt_offset'];
}
$from_date = (int) min( $value ) + ( $offset * HOUR_IN_SECONDS ); // client time zone offset
$to_date = (int) max( $value ) + ( $offset * HOUR_IN_SECONDS ) + DAY_IN_SECONDS - 1; // time 23:59
2019-11-22 11:55:21 +02:00
$from_date = date( 'Y/m/d', $from_date );
$to_date = date( 'Y/m/d', $to_date );
2019-11-22 10:32:23 +02:00
2019-09-02 16:35:10 +03:00
$field_query = array(
2019-09-04 14:54:03 +03:00
'key' => $field,
'value' => array( $from_date, $to_date ),
'compare' => 'BETWEEN',
2019-09-16 16:06:47 +03:00
'inclusive' => true,
2019-09-02 16:35:10 +03:00
);
2019-10-01 11:53:34 +03:00
$this->custom_filters_in_query[ $field ] = array( $from_date, $to_date );
2019-09-02 16:35:10 +03:00
break;
case 'timepicker':
2019-09-16 17:06:17 +03:00
if ( $value[0] == $value[1] ) {
$field_query = array(
'key' => $field,
'value' => $value[0],
);
} else {
$field_query = array(
'key' => $field,
'value' => $value,
'compare' => 'BETWEEN',
'type' => 'TIME',
'inclusive' => true,
);
}
2019-09-02 16:35:10 +03:00
2019-10-01 11:53:34 +03:00
$this->custom_filters_in_query[ $field ] = $value;
2019-09-02 16:35:10 +03:00
break;
}
2019-09-04 14:54:03 +03:00
2019-09-02 16:35:10 +03:00
}
2019-09-04 14:54:03 +03:00
if ( ! empty( $field_query ) && $field_query !== true ) {
2019-09-02 16:35:10 +03:00
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $field_query ) );
}
2019-08-20 15:40:00 +03:00
break;
case 'role':
$value = array_map( 'strtolower', $value );
2024-03-28 12:24:29 +02:00
if ( 'OR' !== $relation ) {
$role__in_clauses = array( 'relation' => $relation );
foreach ( $value as $role ) {
$role__in_clauses[] = array(
'key' => $wpdb->get_blog_prefix() . 'capabilities',
'value' => '"' . $role . '"',
'compare' => 'LIKE',
);
2019-08-20 15:40:00 +03:00
}
2024-03-28 12:24:29 +02:00
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $role__in_clauses ) );
$this->custom_filters_in_query[ $field ] = $value;
2019-08-20 15:40:00 +03:00
} else {
2024-03-28 12:24:29 +02:00
if ( ! empty( $this->query_args['role__in'] ) ) {
$this->query_args['role__in'] = is_array( $this->query_args['role__in'] ) ? $this->query_args['role__in'] : array( $this->query_args['role__in'] );
$default_role = array_intersect( $this->query_args['role__in'], $value );
$um_role = array_diff( $value, $default_role );
2019-08-16 19:42:18 +03:00
2024-03-28 12:24:29 +02:00
foreach ( $um_role as $key => &$val ) {
$val = 'um_' . str_replace( ' ', '-', $val );
}
$this->query_args['role__in'] = array_merge( $default_role, $um_role );
} else {
$this->query_args['role__in'] = $value;
}
2019-10-01 11:53:34 +03:00
2024-03-28 12:24:29 +02:00
$this->custom_filters_in_query[ $field ] = $this->query_args['role__in'];
}
2019-08-20 15:40:00 +03:00
break;
2019-09-02 16:35:10 +03:00
case 'birth_date':
$from_date = date( 'Y/m/d', mktime( 0,0,0, date( 'm', time() ), date( 'd', time() ), date( 'Y', time() - min( $value ) * YEAR_IN_SECONDS ) ) );
2023-12-01 02:17:37 +02:00
$to_date = date( 'Y/m/d', mktime( 0,0,0, date( 'm', time() ), date( 'd', time() ) + 1, date( 'Y', time() - ( max( $value ) + 1 ) * YEAR_IN_SECONDS ) ) );
2019-09-02 16:35:10 +03:00
$meta_query = array(
array(
'key' => 'birth_date',
2020-01-02 17:21:02 +02:00
'value' => array( $to_date, $from_date ),
2019-09-02 16:35:10 +03:00
'compare' => 'BETWEEN',
'type' => 'DATE',
'inclusive' => true,
2023-12-01 02:17:37 +02:00
),
2019-09-02 16:35:10 +03:00
);
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $meta_query ) );
2020-01-02 17:21:02 +02:00
$this->custom_filters_in_query[ $field ] = array( $to_date, $from_date );
2019-10-01 11:53:34 +03:00
2019-09-02 16:35:10 +03:00
break;
case 'user_registered':
$offset = 0;
if ( isset( $_POST['gmt_offset'] ) && is_numeric( $_POST['gmt_offset'] ) ) {
$offset = (int) $_POST['gmt_offset'];
}
2019-08-16 19:42:18 +03:00
2023-12-01 02:17:37 +02:00
$from_date = date( 'Y-m-d H:i:s', strtotime( date( 'Y-m-d H:i:s', min( $value ) ) . "+$offset hours" ) );
$to_date = date( 'Y-m-d H:i:s', strtotime( date( 'Y-m-d H:i:s', max( $value ) ) . "+$offset hours" ) );
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
$date_query = array(
array(
'column' => 'user_registered',
'before' => $to_date,
'after' => $from_date,
'inclusive' => true,
),
);
if ( empty( $this->query_args['date_query'] ) ) {
$this->query_args['date_query'] = $date_query;
} else {
$this->query_args['date_query'] = array_merge( $this->query_args['date_query'], array( $date_query ) );
}
2019-10-01 11:53:34 +03:00
$this->custom_filters_in_query[ $field ] = $value;
2019-09-02 16:35:10 +03:00
break;
case 'last_login':
$offset = 0;
if ( isset( $_POST['gmt_offset'] ) && is_numeric( $_POST['gmt_offset'] ) ) {
$offset = (int) $_POST['gmt_offset'];
}
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
$from_date = (int) min( $value ) + ( $offset * HOUR_IN_SECONDS ); // client time zone offset
$to_date = (int) max( $value ) + ( $offset * HOUR_IN_SECONDS ) + DAY_IN_SECONDS - 1; // time 23:59
$meta_query = array(
2024-04-02 17:28:54 +03:00
'relation' => 'AND',
2019-09-02 16:35:10 +03:00
array(
'key' => '_um_last_login',
2023-12-01 02:17:37 +02:00
'value' => array( gmdate( 'Y-m-d H:i:s', $from_date ), gmdate( 'Y-m-d H:i:s', $to_date ) ),
2019-09-02 16:35:10 +03:00
'compare' => 'BETWEEN',
2019-09-16 16:06:47 +03:00
'inclusive' => true,
2023-12-01 02:17:37 +02:00
'type' => 'DATETIME',
),
2024-04-02 17:28:54 +03:00
array(
'relation' => 'OR',
array(
'key' => 'um_show_last_login',
'compare' => 'NOT EXISTS',
),
array(
'key' => 'um_show_last_login',
'value' => 'a:1:{i:0;s:2:"no";}',
'compare' => '!=',
),
),
2019-09-02 16:35:10 +03:00
);
2019-10-01 11:53:34 +03:00
$this->custom_filters_in_query[ $field ] = $value;
2019-09-02 16:35:10 +03:00
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $meta_query ) );
break;
2024-03-26 00:47:40 +02:00
case 'gender':
if ( is_array( $value ) ) {
2024-03-28 12:24:29 +02:00
$field_query = array( 'relation' => $relation );
2024-03-26 00:47:40 +02:00
foreach ( $value as $single_val ) {
$single_val = trim( stripslashes( $single_val ) );
$arr_meta_query = array(
array(
'key' => $field,
'value' => $single_val,
'compare' => '=',
),
array(
'key' => $field,
'value' => '"' . $single_val . '"',
'compare' => 'LIKE',
),
);
$field_query = array_merge( $field_query, $arr_meta_query );
}
}
if ( ! empty( $field_query ) ) {
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $field_query ) );
$this->custom_filters_in_query[ $field ] = $value;
}
break;
2019-09-02 16:35:10 +03:00
}
2019-08-16 19:42:18 +03:00
}
}
2019-10-01 11:53:34 +03:00
/**
* Set default filters
*
* @param $directory_data
*/
2024-04-15 17:58:18 +03:00
public function default_filters( $directory_data ) {
2019-10-01 11:53:34 +03:00
$default_filters = array();
if ( ! empty( $directory_data['search_filters'] ) ) {
$default_filters = maybe_unserialize( $directory_data['search_filters'] );
}
$gmt_offset = get_post_meta( $directory_data['form_id'], '_um_search_filters_gmt', true );
if ( empty( $default_filters ) ) {
return;
}
foreach ( $default_filters as $field => $value ) {
switch ( $field ) {
default:
$filter_type = $this->filter_types[ $field ];
/**
* UM hook
*
* @type filter
* @title um_query_args_{$field}__filter
* @description Change field's query for search at Members Directory
* @input_vars
* [{"var":"$field_query","type":"array","desc":"Field query"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_query_args_{$field}__filter', 'function_name', 10, 1 ); ?>
* @example
* <?php
* add_filter( 'um_query_args_{$field}__filter', 'my_query_args_filter', 10, 1 );
* function my_query_args_filter( $field_query ) {
* // your code here
* return $field_query;
* }
* ?>
*/
$field_query = apply_filters( "um_query_args_{$field}__filter", false, $field, $value, $filter_type );
if ( ! $field_query ) {
switch ( $filter_type ) {
default:
$field_query = apply_filters( "um_query_args_{$field}_{$filter_type}__filter", false, $field, $value, $filter_type );
break;
2020-01-10 15:24:55 +02:00
case 'text':
$field_query = array(
2024-04-15 17:58:18 +03:00
'key' => $field,
'value' => $value,
'compare' => apply_filters( 'um_members_directory_filter_text', '=', $field ),
2020-01-10 15:24:55 +02:00
);
break;
2019-10-01 11:53:34 +03:00
case 'select':
if ( ! is_array( $value ) ) {
$value = array( $value );
}
2024-03-13 11:25:41 +02:00
/** This filter is documented in includes/core/class-member-directory.php */
$field_query = apply_filters( 'um_members_directory_filter_select', array( 'relation' => 'OR' ), $field );
2019-10-01 11:53:34 +03:00
foreach ( $value as $single_val ) {
2020-11-24 12:55:22 +02:00
$single_val = trim( $single_val );
2019-10-01 11:53:34 +03:00
$arr_meta_query = array(
array(
2024-03-13 11:25:41 +02:00
'key' => $field,
'value' => $single_val,
'compare' => '=',
2019-10-01 11:53:34 +03:00
),
array(
2024-03-13 11:25:41 +02:00
'key' => $field,
'value' => serialize( (string) $single_val ),
'compare' => 'LIKE',
2019-10-01 11:53:34 +03:00
),
array(
2024-03-13 11:25:41 +02:00
'key' => $field,
'value' => '"' . $single_val . '"',
'compare' => 'LIKE',
),
2019-10-01 11:53:34 +03:00
);
if ( is_numeric( $single_val ) ) {
$arr_meta_query[] = array(
2024-03-13 11:25:41 +02:00
'key' => $field,
'value' => serialize( absint( $single_val ) ),
'compare' => 'LIKE',
2019-10-01 11:53:34 +03:00
);
}
$field_query = array_merge( $field_query, $arr_meta_query );
}
break;
case 'slider':
$field_query = array(
'key' => $field,
'value' => $value,
'compare' => 'BETWEEN',
'inclusive' => true,
);
break;
2024-04-15 17:58:18 +03:00
case 'datepicker':
2019-10-01 11:53:34 +03:00
$offset = 0;
if ( is_numeric( $gmt_offset ) ) {
$offset = $gmt_offset;
}
2024-04-15 17:58:18 +03:00
if ( ! empty( $value[0] ) ) {
$min = $value[0];
} else {
$range = $this->datepicker_filters_range( $field );
$min = strtotime( gmdate( 'Y/m/d', $range[0] ) );
}
if ( ! empty( $value[1] ) ) {
$max = $value[1];
} else {
$max = strtotime( gmdate( 'Y/m/d' ) );
}
$from_date = (int) $min + ( $offset * HOUR_IN_SECONDS ); // client time zone offset
$to_date = (int) $max + ( $offset * HOUR_IN_SECONDS ) + DAY_IN_SECONDS - 1; // time 23:59
2019-10-01 11:53:34 +03:00
$field_query = array(
'key' => $field,
2024-04-15 17:58:18 +03:00
'value' => array( $from_date, $to_date ),
2019-10-01 11:53:34 +03:00
'compare' => 'BETWEEN',
'inclusive' => true,
);
break;
case 'timepicker':
2024-04-16 13:24:08 +03:00
if ( ! empty( $value[0] ) ) {
$value[0] = $value[0] . ':00';
} else {
$range = $this->timepicker_filters_range( $field );
$value[0] = $range[0] . ':00';
}
if ( ! empty( $value[1] ) ) {
$value[1] = $value[1] . ':00';
} else {
$range = $this->timepicker_filters_range( $field );
$value[1] = $range[1] . ':00';
}
if ( $value[0] === $value[1] ) {
2019-10-01 11:53:34 +03:00
$field_query = array(
2024-04-16 13:24:08 +03:00
'key' => $field,
'value' => $value[0],
2019-10-01 11:53:34 +03:00
);
} else {
$field_query = array(
'key' => $field,
'value' => $value,
'compare' => 'BETWEEN',
'type' => 'TIME',
'inclusive' => true,
);
}
break;
}
}
if ( ! empty( $field_query ) && $field_query !== true ) {
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $field_query ) );
}
break;
case 'role':
2020-05-13 15:57:23 +03:00
$value = is_array( $value ) ? $value : explode( '||', $value );
2019-10-01 11:53:34 +03:00
$value = array_map( 'strtolower', $value );
if ( ! empty( $this->query_args['role__in'] ) ) {
$this->query_args['role__in'] = is_array( $this->query_args['role__in'] ) ? $this->query_args['role__in'] : array( $this->query_args['role__in'] );
$default_role = array_intersect( $this->query_args['role__in'], $value );
$um_role = array_diff( $value, $default_role );
foreach ( $um_role as $key => &$val ) {
$val = 'um_' . str_replace( ' ', '-', $val );
}
$this->query_args['role__in'] = array_merge( $default_role, $um_role );
} else {
$this->query_args['role__in'] = $value;
2024-04-15 17:58:18 +03:00
}
2019-10-01 11:53:34 +03:00
break;
case 'birth_date':
$from_date = date( 'Y/m/d', mktime( 0,0,0, date( 'm', time() ), date( 'd', time() ), date( 'Y', time() - min( $value ) * YEAR_IN_SECONDS ) ) );
2024-04-15 17:58:18 +03:00
$to_date = date( 'Y/m/d', mktime( 0,0,0, date( 'm', time() ), date( 'd', time() ) + 1, date( 'Y', time() - ( max( $value ) + 1 ) * YEAR_IN_SECONDS ) ) );
2019-10-01 11:53:34 +03:00
$meta_query = array(
array(
'key' => 'birth_date',
'value' => array( $to_date, $from_date ),
'compare' => 'BETWEEN',
'type' => 'DATE',
'inclusive' => true,
2024-04-15 17:58:18 +03:00
),
2019-10-01 11:53:34 +03:00
);
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $meta_query ) );
break;
case 'user_registered':
$offset = 0;
if ( is_numeric( $gmt_offset ) ) {
$offset = $gmt_offset;
}
2023-12-01 02:17:37 +02:00
$from_date = date( 'Y-m-d H:i:s', strtotime( date( 'Y-m-d H:i:s', min( $value ) ) . "+$offset hours" ) );
2024-04-15 17:58:18 +03:00
$to_date = date( 'Y-m-d H:i:s', strtotime( date( 'Y-m-d H:i:s', max( $value ) ) . "+$offset hours" ) );
2019-10-01 11:53:34 +03:00
$date_query = array(
array(
'column' => 'user_registered',
'before' => $to_date,
'after' => $from_date,
'inclusive' => true,
),
);
if ( empty( $this->query_args['date_query'] ) ) {
$this->query_args['date_query'] = $date_query;
} else {
$this->query_args['date_query'] = array_merge( $this->query_args['date_query'], array( $date_query ) );
}
break;
case 'last_login':
$offset = 0;
if ( is_numeric( $gmt_offset ) ) {
$offset = $gmt_offset;
}
2024-04-02 17:28:54 +03:00
$value = array_map(
function( $date ) {
return is_numeric( $date ) ? $date : strtotime( $date );
},
$value
);
2024-04-15 17:58:18 +03:00
if ( ! empty( $value[0] ) ) {
$min = $value[0];
} else {
$range = $this->datepicker_filters_range( 'last_login' );
$min = strtotime( gmdate( 'Y/m/d', $range[0] ) );
}
if ( ! empty( $value[1] ) ) {
$max = $value[1];
} else {
$max = strtotime( gmdate( 'Y/m/d' ) );
}
$from_date = gmdate( 'Y-m-d H:i:s', (int) $min + ( $offset * HOUR_IN_SECONDS ) ); // client time zone offset
$to_date = gmdate( 'Y-m-d H:i:s', (int) $max + ( $offset * HOUR_IN_SECONDS ) + DAY_IN_SECONDS - 1 ); // time 23:59
2024-04-02 17:28:54 +03:00
2019-10-01 11:53:34 +03:00
$meta_query = array(
2024-04-02 17:28:54 +03:00
'relation' => 'AND',
2019-10-01 11:53:34 +03:00
array(
'key' => '_um_last_login',
2023-12-01 02:17:37 +02:00
'value' => array( $from_date, $to_date ),
2019-10-01 11:53:34 +03:00
'compare' => 'BETWEEN',
'inclusive' => true,
2023-12-01 02:17:37 +02:00
'type' => 'DATETIME',
),
2024-04-02 17:28:54 +03:00
array(
'relation' => 'OR',
array(
'key' => 'um_show_last_login',
'compare' => 'NOT EXISTS',
),
array(
'key' => 'um_show_last_login',
'value' => 'a:1:{i:0;s:2:"no";}',
'compare' => '!=',
),
),
2019-10-01 11:53:34 +03:00
);
$this->query_args['meta_query'] = array_merge( $this->query_args['meta_query'], array( $meta_query ) );
break;
}
}
}
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
/**
* Get data array for pagination
*
*
* @param array $directory_data
2020-01-08 15:19:24 +02:00
* @param int $total_users
2019-09-02 16:35:10 +03:00
*
* @return array
*/
2020-01-08 15:19:24 +02:00
function calculate_pagination( $directory_data, $total_users ) {
2019-08-16 19:42:18 +03:00
2021-06-29 02:51:54 +03:00
$current_page = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 1;
2019-09-02 16:35:10 +03:00
2020-01-08 15:19:24 +02:00
$total_users = ( ! empty( $directory_data['max_users'] ) && $directory_data['max_users'] <= $total_users ) ? $directory_data['max_users'] : $total_users;
2019-11-20 17:07:38 +02:00
// number of profiles for mobile
$profiles_per_page = $directory_data['profiles_per_page'];
2024-12-17 21:53:18 +02:00
if ( wp_is_mobile() && isset( $directory_data['profiles_per_page_mobile'] ) ) {
2019-11-20 17:07:38 +02:00
$profiles_per_page = $directory_data['profiles_per_page_mobile'];
}
$total_pages = 1;
if ( ! empty( $profiles_per_page ) ) {
$total_pages = ceil( $total_users / $profiles_per_page );
}
2019-09-02 16:35:10 +03:00
if ( ! empty( $total_pages ) ) {
$index1 = 0 - ( $current_page - 2 ) + 1;
$to = $current_page + 2;
if ( $index1 > 0 ) {
$to += $index1;
}
$index2 = $total_pages - ( $current_page + 2 );
$from = $current_page - 2;
if ( $index2 < 0 ) {
$from += $index2;
}
$pages_to_show = range(
( $from > 0 ) ? $from : 1,
( $to <= $total_pages ) ? $to : $total_pages
);
2019-08-16 19:42:18 +03:00
}
2019-09-02 16:35:10 +03:00
$pagination_data = array(
'pages_to_show' => ( ! empty( $pages_to_show ) && count( $pages_to_show ) > 1 ) ? array_values( $pages_to_show ) : array(),
'current_page' => $current_page,
'total_pages' => $total_pages,
'total_users' => $total_users,
);
$pagination_data['header'] = $this->convert_tags( $directory_data['header'], $pagination_data );
$pagination_data['header_single'] = $this->convert_tags( $directory_data['header_single'], $pagination_data );
return $pagination_data;
2019-08-16 19:42:18 +03:00
}
2019-09-23 13:34:25 +03:00
/**
* @param int $user_id
*
* @return array
*/
2024-09-24 13:18:48 +03:00
private function build_user_actions_list( $user_id ) {
2019-09-23 13:34:25 +03:00
$actions = array();
if ( ! is_user_logged_in() ) {
return $actions;
}
2024-09-24 13:18:48 +03:00
if ( get_current_user_id() !== $user_id ) {
2019-09-23 13:34:25 +03:00
if ( UM()->roles()->um_current_user_can( 'edit', $user_id ) ) {
$actions['um-editprofile'] = array(
2024-03-04 12:27:41 +02:00
'title' => esc_html__( 'Edit Profile', 'ultimate-member' ),
'url' => um_edit_profile_url(),
2019-09-23 13:34:25 +03:00
);
}
2024-09-24 13:18:48 +03:00
$admin_actions = UM()->frontend()->users()->get_actions_list( $user_id );
2019-09-23 13:34:25 +03:00
if ( ! empty( $admin_actions ) ) {
foreach ( $admin_actions as $id => $arr ) {
2024-09-24 13:18:48 +03:00
$url = add_query_arg(
array(
'um_action' => $id,
'uid' => $user_id,
'nonce' => wp_create_nonce( $id . $user_id ),
),
um_user_profile_url( $user_id )
);
2019-09-23 13:34:25 +03:00
$actions[ $id ] = array(
2024-03-04 12:27:41 +02:00
'title' => esc_html( $arr['label'] ),
'url' => esc_url( $url ),
2019-09-23 13:34:25 +03:00
);
}
}
$actions = apply_filters( 'um_member_directory_users_card_actions', $actions, $user_id );
} else {
if ( empty( UM()->user()->cannot_edit ) ) {
$actions['um-editprofile'] = array(
2024-03-04 12:27:41 +02:00
'title' => esc_html__( 'Edit Profile', 'ultimate-member' ),
2019-09-23 13:34:25 +03:00
'url' => um_edit_profile_url(),
);
}
$actions['um-myaccount'] = array(
2024-03-04 12:27:41 +02:00
'title' => esc_html__( 'My Account', 'ultimate-member' ),
2019-09-23 13:34:25 +03:00
'url' => um_get_core_page( 'account' ),
);
$actions['um-logout'] = array(
2024-03-04 12:27:41 +02:00
'title' => esc_html__( 'Logout', 'ultimate-member' ),
2019-09-23 13:34:25 +03:00
'url' => um_get_core_page( 'logout' ),
);
$actions = apply_filters( 'um_member_directory_my_user_card_actions', $actions, $user_id );
}
return $actions;
}
2019-09-02 16:35:10 +03:00
/**
* @param int $user_id
* @param array $directory_data
*
* @return array
*/
2024-09-24 13:18:48 +03:00
public function build_user_card_data( $user_id, $directory_data ) {
2019-09-02 16:35:10 +03:00
um_fetch_user( $user_id );
2019-09-23 13:34:25 +03:00
$dropdown_actions = $this->build_user_actions_list( $user_id );
2019-09-02 16:35:10 +03:00
2024-03-04 12:27:41 +02:00
$actions = array();
2021-04-07 02:43:33 +03:00
$can_edit = UM()->roles()->um_current_user_can( 'edit', $user_id );
2019-09-02 16:35:10 +03:00
// Replace hook 'um_members_just_after_name'
ob_start();
do_action( 'um_members_just_after_name', $user_id, $directory_data );
$hook_just_after_name = ob_get_clean();
// Replace hook 'um_members_after_user_name'
ob_start();
do_action( 'um_members_after_user_name', $user_id, $directory_data );
$hook_after_user_name = ob_get_clean();
$data_array = array(
2025-12-16 17:05:51 +02:00
'card_anchor' => esc_html( $this->get_user_hash( $user_id ) ),
2025-12-11 17:36:42 +02:00
'role' => is_user_logged_in() ? esc_html( um_user( 'role' ) ) : 'undefined', // make the role hidden for the nopriv requests.
'account_status' => is_user_logged_in() ? esc_html( UM()->common()->users()->get_status( $user_id ) ) : 'undefined', // make the status hidden for the nopriv requests.
'account_status_name' => is_user_logged_in() ? esc_html( UM()->common()->users()->get_status( $user_id, 'formatted' ) ) : __( 'Undefined', 'ultimate-member' ), // make the status hidden for the nopriv requests.
2024-03-04 12:27:41 +02:00
'cover_photo' => wp_kses( um_user( 'cover_photo', $this->cover_size ), UM()->get_allowed_html( 'templates' ) ),
'display_name' => esc_html( um_user( 'display_name' ) ),
'profile_url' => esc_url( um_user_profile_url() ),
'can_edit' => (bool) $can_edit,
2025-12-11 17:36:42 +02:00
'edit_profile_url' => $can_edit ? esc_url( um_edit_profile_url() ) : '',
2024-03-04 12:27:41 +02:00
'avatar' => wp_kses( get_avatar( $user_id, $this->avatar_size ), UM()->get_allowed_html( 'templates' ) ),
'display_name_html' => wp_kses( um_user( 'display_name', 'html' ), UM()->get_allowed_html( 'templates' ) ),
'dropdown_actions' => $dropdown_actions,
'hook_just_after_name' => wp_kses( preg_replace( '/^\s+/im', '', $hook_just_after_name ), UM()->get_allowed_html( 'templates' ) ),
'hook_after_user_name' => wp_kses( preg_replace( '/^\s+/im', '', $hook_after_user_name ), UM()->get_allowed_html( 'templates' ) ),
2019-09-02 16:35:10 +03:00
);
2020-02-06 14:54:13 +02:00
if ( ! empty( $directory_data['show_tagline'] ) ) {
2019-09-04 14:54:03 +03:00
2020-02-06 14:54:13 +02:00
if ( ! empty( $directory_data['tagline_fields'] ) ) {
$directory_data['tagline_fields'] = maybe_unserialize( $directory_data['tagline_fields'] );
if ( is_array( $directory_data['tagline_fields'] ) ) {
foreach ( $directory_data['tagline_fields'] as $key ) {
if ( ! $key ) {
continue;
}
2019-09-02 16:35:10 +03:00
2024-04-02 17:28:54 +03:00
if ( '_um_last_login' === $key ) {
$show_last_login = get_user_meta( $user_id, 'um_show_last_login', true );
if ( ! empty( $show_last_login ) && 'no' === $show_last_login[0] ) {
continue;
}
}
2020-02-06 14:54:13 +02:00
$value = um_filtered_value( $key );
2019-09-04 14:54:03 +03:00
2020-02-06 14:54:13 +02:00
if ( ! $value ) {
continue;
}
2019-09-02 16:35:10 +03:00
2024-03-04 12:27:41 +02:00
$data_array[ $key ] = wp_kses( $value, UM()->get_allowed_html( 'templates' ) );
2020-02-06 14:54:13 +02:00
}
}
2019-09-02 16:35:10 +03:00
}
}
2020-02-06 14:54:13 +02:00
if ( ! empty( $directory_data['show_userinfo'] ) ) {
2019-09-02 16:35:10 +03:00
2020-02-06 14:54:13 +02:00
if ( ! empty( $directory_data['reveal_fields'] ) ) {
2019-09-02 16:35:10 +03:00
2020-02-06 14:54:13 +02:00
$directory_data['reveal_fields'] = maybe_unserialize( $directory_data['reveal_fields'] );
2019-09-02 16:35:10 +03:00
2020-02-06 14:54:13 +02:00
if ( is_array( $directory_data['reveal_fields'] ) ) {
foreach ( $directory_data['reveal_fields'] as $key ) {
if ( ! $key ) {
continue;
}
2024-04-02 17:28:54 +03:00
if ( '_um_last_login' === $key ) {
$show_last_login = get_user_meta( $user_id, 'um_show_last_login', true );
if ( ! empty( $show_last_login ) && 'no' === $show_last_login[0] ) {
continue;
}
}
2020-02-06 14:54:13 +02:00
$value = um_filtered_value( $key );
if ( ! $value ) {
continue;
}
$label = UM()->fields()->get_label( $key );
if ( $key == 'role_select' || $key == 'role_radio' ) {
$label = strtr( $label, array(
' (Dropdown)' => '',
' (Radio)' => ''
) );
}
2019-09-04 14:54:03 +03:00
2024-03-04 12:27:41 +02:00
$data_array[ "label_{$key}" ] = esc_html__( $label, 'ultimate-member' );
$data_array[ $key ] = wp_kses( $value, UM()->get_allowed_html( 'templates' ) );
2020-02-06 14:54:13 +02:00
}
2019-09-04 14:54:03 +03:00
}
2019-09-02 16:35:10 +03:00
}
if ( ! empty( $directory_data['show_social'] ) ) {
ob_start();
UM()->fields()->show_social_urls();
$social_urls = ob_get_clean();
2024-03-04 12:27:41 +02:00
$data_array['social_urls'] = wp_kses( $social_urls, UM()->get_allowed_html( 'templates' ) );
2019-09-02 16:35:10 +03:00
}
}
2019-09-09 12:39:45 +03:00
$data_array = apply_filters( 'um_ajax_get_members_data', $data_array, $user_id, $directory_data );
2019-12-20 15:06:58 +02:00
2019-09-02 16:35:10 +03:00
um_reset_user_clean();
return $data_array;
2019-08-16 19:42:18 +03:00
}
2019-12-11 12:34:17 +02:00
/**
* Update limit query
*
2025-03-25 23:31:13 +02:00
* @param WP_User_Query $user_query
2019-12-11 12:34:17 +02:00
*/
2025-03-25 23:31:13 +02:00
public function pagination_changes( $user_query ) {
2019-12-11 12:34:17 +02:00
global $wpdb;
2025-03-25 23:31:13 +02:00
$directory_id = $this->get_directory_by_hash( sanitize_key( $_POST['directory_id'] ) );
2019-12-11 12:34:17 +02:00
$directory_data = UM()->query()->post_data( $directory_id );
$qv = $user_query->query_vars;
$number = $qv['number'];
if ( ! empty( $directory_data['max_users'] ) && $qv['paged']*$qv['number'] > $directory_data['max_users'] ) {
$number = ( $qv['paged']*$qv['number'] - ( $qv['paged']*$qv['number'] - $directory_data['max_users'] ) ) % $qv['number'];
}
// limit
if ( isset( $qv['number'] ) && $qv['number'] > 0 ) {
if ( $qv['offset'] ) {
$user_query->query_limit = $wpdb->prepare( 'LIMIT %d, %d', $qv['offset'], $number );
} else {
$user_query->query_limit = $wpdb->prepare( 'LIMIT %d, %d', $qv['number'] * ( $qv['paged'] - 1 ), $number );
}
}
}
2025-03-25 23:31:13 +02:00
/**
* Update search query
*
* @param WP_User_Query $user_query
*
* @throws Exception
*/
public function search_changes( $user_query ) {
global $wpdb;
2025-03-26 00:20:45 +02:00
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;
}
2025-03-26 00:18:52 +02:00
$directory_id = null;
2025-03-26 00:20:45 +02:00
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
2025-03-26 00:18:52 +02:00
}
$qv = $user_query->query_vars;
2025-03-25 23:31:13 +02:00
2025-03-26 00:18:52 +02:00
$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 );
}
2025-03-25 23:31:13 +02:00
$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 );
2025-03-26 00:18:52 +02:00
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 );
}
2025-03-25 23:31:13 +02:00
}
if ( ! empty( $exclude_fields ) ) {
$search_columns = array_diff( $search_columns, $exclude_fields );
}
if ( ! empty( $custom_fields ) ) {
$search_columns[] = 'um_search.meta_value';
2025-03-26 00:20:45 +02:00
2025-03-25 23:31:13 +02:00
$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 );
2025-03-26 00:20:45 +02:00
2025-03-25 23:31:13 +02:00
$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;
}
}
}
2019-12-11 12:34:17 +02:00
2019-12-20 15:06:58 +02:00
function predefined_no_caps( $directory_data ) {
2019-09-02 16:35:10 +03:00
//predefined result for user without capabilities to see other members
if ( is_user_logged_in() && ! UM()->roles()->um_user_can( 'can_view_all' ) ) {
$pagination_data = array(
'pages_to_show' => array(),
'current_page' => 1,
'total_pages' => 0,
'total_users' => 0,
);
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
$pagination_data['header'] = $this->convert_tags( $directory_data['header'], $pagination_data );
$pagination_data['header_single'] = $this->convert_tags( $directory_data['header_single'], $pagination_data );
2019-08-16 19:42:18 +03:00
2019-09-27 12:38:14 +03:00
wp_send_json_success( array( 'users' => array(), 'pagination' => $pagination_data ) );
2019-09-02 16:35:10 +03:00
}
2019-12-20 15:06:58 +02:00
}
/**
* Main Query function for getting members via AJAX
*/
2025-12-11 17:36:42 +02:00
public function ajax_get_members() {
2019-12-20 15:06:58 +02:00
UM()->check_ajax_nonce();
2025-12-11 17:36:42 +02:00
if ( UM()->is_rate_limited( 'member_directory' ) ) {
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
}
2019-12-20 15:06:58 +02:00
global $wpdb;
2022-07-07 14:30:10 +03:00
if ( empty( $_POST['directory_id'] ) ) {
wp_send_json_error( __( 'Wrong member directory data', 'ultimate-member' ) );
}
2021-06-29 02:51:54 +03:00
$directory_id = $this->get_directory_by_hash( sanitize_key( $_POST['directory_id'] ) );
2022-07-07 14:30:10 +03:00
if ( empty( $directory_id ) ) {
wp_send_json_error( __( 'Wrong member directory data', 'ultimate-member' ) );
}
2025-12-11 17:36:42 +02:00
if ( ! $this->can_view_directory( $directory_id ) ) {
wp_send_json_error( __( 'You cannot see this member directory', 'ultimate-member' ) );
}
2019-12-20 15:06:58 +02:00
$directory_data = UM()->query()->post_data( $directory_id );
//predefined result for user without capabilities to see other members
$this->predefined_no_caps( $directory_data );
2019-08-16 19:42:18 +03:00
2019-09-30 01:27:01 +03:00
do_action( 'um_member_directory_before_query' );
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
// Prepare for BIG SELECT query
$wpdb->query( 'SET SQL_BIG_SELECTS=1' );
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
// Prepare default user query values
2019-08-16 19:42:18 +03:00
$this->query_args = array(
2024-02-08 13:47:15 +02:00
'fields' => 'ids',
'number' => 0,
'meta_query' => array(
'relation' => 'AND',
2019-08-16 19:42:18 +03:00
),
);
2019-09-02 16:35:10 +03:00
// handle different restrictions
$this->restriction_options();
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
// handle general options
$this->general_options( $directory_data );
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
// handle pagination options
$this->pagination_options( $directory_data );
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
// handle sorting options
$this->sorting_query( $directory_data );
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
// handle general search line
2019-08-16 19:42:18 +03:00
$this->general_search();
2019-09-02 16:35:10 +03:00
// handle filters
$this->filters( $directory_data );
2019-08-16 19:42:18 +03:00
2019-10-01 11:53:34 +03:00
$this->default_filters( $directory_data );
2019-08-16 19:42:18 +03:00
/**
* UM hook
*
* @type filter
* @title um_prepare_user_query_args
* @description Extend member directory query arguments
* @input_vars
* [{"var":"$query_args","type":"array","desc":"Members Query Arguments"},
* {"var":"$directory_settings","type":"array","desc":"Member Directory Settings"}]
* @change_log
* ["Since: 2.0"]
* @usage
* <?php add_filter( 'um_prepare_user_query_args', 'function_name', 10, 2 ); ?>
* @example
* <?php
* add_filter( 'um_prepare_user_query_args', 'my_prepare_user_query_args', 10, 2 );
* function my_prepare_user_query_args( $query_args, $directory_settings ) {
* // your code here
* return $query_args;
* }
* ?>
*/
2019-09-02 16:35:10 +03:00
$this->query_args = apply_filters( 'um_prepare_user_query_args', $this->query_args, $directory_data );
2019-08-16 19:42:18 +03:00
//unset empty meta_query attribute
if ( isset( $this->query_args['meta_query']['relation'] ) && count( $this->query_args['meta_query'] ) == 1 ) {
unset( $this->query_args['meta_query'] );
}
2020-07-23 16:06:59 +03:00
if ( isset( $this->query_args['role__in'] ) && empty( $this->query_args['role__in'] ) ) {
$member_directory_response = apply_filters( 'um_ajax_get_members_response', array(
'pagination' => $this->calculate_pagination( $directory_data, 0 ),
'users' => array(),
'is_search' => $this->is_search,
), $directory_data );
wp_send_json_success( $member_directory_response );
}
2019-08-16 19:42:18 +03:00
/**
2023-07-10 11:14:02 +03:00
* Fires just before the users query for getting users in member directory.
2019-08-16 19:42:18 +03:00
*
2023-07-10 11:14:02 +03:00
* @since 1.3.x
* @since 2.1.0 Added `$member_directory_class` variable.
* @hook um_user_before_query
*
* @param {array} $args Query arguments.
* @param {object} $member_directory_class Member Directory class. Since 2.1.0 version.
*
* @example <caption>Add custom arguments for query.</caption>
* function my_user_before_query( $query_args, $md_class ) {
* $query_args['{custom_key}'] = 'custom_value';
2019-08-16 19:42:18 +03:00
* }
2023-07-10 11:14:02 +03:00
* add_action( 'um_user_before_query', 'my_user_before_query', 10, 2 );
2019-08-16 19:42:18 +03:00
*/
2019-11-27 17:28:04 +02:00
do_action( 'um_user_before_query', $this->query_args, $this );
2019-08-16 19:42:18 +03:00
2025-03-25 23:31:13 +02:00
add_action( 'pre_user_query', array( &$this, 'search_changes' ) );
add_action( 'pre_user_query', array( &$this, 'pagination_changes' ) );
2023-06-12 13:20:00 +03:00
2025-02-28 12:13:15 +02:00
$user_query = new WP_User_Query( $this->query_args );
2019-08-16 19:42:18 +03:00
2025-03-25 23:31:13 +02:00
remove_action( 'pre_user_query', array( &$this, 'search_changes' ) );
remove_action( 'pre_user_query', array( &$this, 'pagination_changes' ) );
2019-08-16 19:42:18 +03:00
/**
2023-07-10 11:14:02 +03:00
* Fires just after the users query for getting users in member directory.
2019-08-16 19:42:18 +03:00
*
2023-07-10 11:14:02 +03:00
* @since 1.3.x
* @hook um_user_after_query
*
* @param {array} $query_args Query arguments.
* @param {object} $user_query Query results.
*
* @example <caption>Make some custom action after getting the users in member directory.</caption>
2019-09-02 16:35:10 +03:00
* function my_user_after_query( $query_args, $user_query ) {
2019-08-16 19:42:18 +03:00
* // your code here
* }
2023-07-10 11:14:02 +03:00
* add_action( 'um_user_after_query', 'my_user_after_query', 10, 2 );
2019-08-16 19:42:18 +03:00
*/
2019-09-02 16:35:10 +03:00
do_action( 'um_user_after_query', $this->query_args, $user_query );
2019-08-16 19:42:18 +03:00
2020-01-08 15:19:24 +02:00
$pagination_data = $this->calculate_pagination( $directory_data, $user_query->total_users );
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
$user_ids = ! empty( $user_query->results ) ? array_unique( $user_query->results ) : array();
2019-08-16 19:42:18 +03:00
/**
2023-06-12 15:22:35 +03:00
* Filters the member directory query result.
2019-08-16 19:42:18 +03:00
*
2023-06-12 15:22:35 +03:00
* @since 2.0
* @hook um_prepare_user_results_array
*
* @param {array} $user_ids Members Query Result.
* @param {array} $query_args Query arguments.
*
* @return {array} Query result.
*
* @example <caption>Remove some users where ID equals 10 and 12 from query.</caption>
* function my_custom_um_prepare_user_results_array( $user_ids, $query_args ) {
* $user_ids = array_diff( $user_ids, array( 10, 12 ) );
2019-08-16 19:42:18 +03:00
* return $user_ids;
* }
2023-06-12 15:22:35 +03:00
* add_filter( 'um_prepare_user_results_array', 'my_custom_um_prepare_user_results_array', 10, 2 );
2019-08-16 19:42:18 +03:00
*/
2021-03-03 16:43:57 +02:00
$user_ids = apply_filters( 'um_prepare_user_results_array', $user_ids, $this->query_args );
2019-08-16 19:42:18 +03:00
2019-09-02 16:35:10 +03:00
$sizes = UM()->options()->get( 'cover_thumb_sizes' );
2025-09-06 14:42:15 +03:00
// Ensure we have valid sizes array and handle case when only one size is defined
if ( ! is_array( $sizes ) || empty( $sizes ) ) {
$sizes = array( 300 ); // fallback to default
}
2019-11-21 17:43:17 +08:00
2025-09-06 14:42:15 +03:00
// For mobile, use second size if available, otherwise use first size
$available_mobile = isset( $sizes[1] ) ? $sizes[1] : $sizes[0];
$this->cover_size = wp_is_mobile() ? $available_mobile : end( $sizes );
2019-08-16 19:42:18 +03:00
2020-11-18 16:56:01 +02:00
$this->cover_size = apply_filters( 'um_member_directory_cover_image_size', $this->cover_size, $directory_data );
2024-02-08 13:47:15 +02:00
$avatar_size = UM()->options()->get( 'profile_photosize' );
2019-09-02 16:35:10 +03:00
$this->avatar_size = str_replace( 'px', '', $avatar_size );
2020-12-04 16:52:17 +02:00
$this->avatar_size = apply_filters( 'um_member_directory_avatar_image_size', $this->avatar_size, $directory_data );
2019-09-02 16:35:10 +03:00
$users = array();
foreach ( $user_ids as $user_id ) {
$users[] = $this->build_user_card_data( $user_id, $directory_data );
}
um_reset_user();
// end of user card
2019-12-03 20:50:39 +02:00
$member_directory_response = apply_filters( 'um_ajax_get_members_response', array(
'pagination' => $pagination_data,
'users' => $users,
'is_search' => $this->is_search,
), $directory_data );
wp_send_json_success( $member_directory_response );
2019-08-16 19:42:18 +03:00
}
2019-09-23 13:34:25 +03:00
/**
* New menu
*
* @param string $element
* @param string $trigger
* @param array $items
2022-02-04 17:19:01 +02:00
* @param string $parent
2019-09-23 13:34:25 +03:00
*/
2022-02-04 17:19:01 +02:00
function dropdown_menu( $element, $trigger, $items = array(), $parent = '' ) {
2021-05-14 13:58:02 +03:00
// !!!!Important: all links in the dropdown items must have "class" attribute
2019-09-23 13:34:25 +03:00
?>
2022-02-04 17:19:01 +02:00
<div class="um-new-dropdown" data-element="<?php echo $element; ?>" data-trigger="<?php echo $trigger; ?>" data-parent="<?php echo $parent; ?>">
2019-09-23 13:34:25 +03:00
<ul>
<?php foreach ( $items as $k => $v ) { ?>
<li><?php echo $v; ?></li>
<?php } ?>
</ul>
</div>
<?php
}
/**
* New menu JS
*
* @param string $element
* @param string $trigger
* @param string $item
2021-05-14 13:58:02 +03:00
* @param string $additional_attributes
2022-02-04 17:19:01 +02:00
* @param string $parent
2019-09-23 13:34:25 +03:00
*/
2022-02-04 17:19:01 +02:00
function dropdown_menu_js( $element, $trigger, $item, $additional_attributes = '', $parent = '' ) {
2019-09-23 13:34:25 +03:00
?>
2022-02-04 17:19:01 +02:00
<div class="um-new-dropdown" data-element="<?php echo $element; ?>" data-trigger="<?php echo $trigger; ?>" data-parent="<?php echo $parent; ?>">
2019-09-23 13:34:25 +03:00
<ul>
<# _.each( <?php echo $item; ?>.dropdown_actions, function( action, key, list ) { #>
2021-05-14 13:58:02 +03:00
<li><a href="<# if ( typeof action.url != 'undefined' ) { #>{{{action.url}}}<# } else { #>javascript:void(0);<# }#>" class="{{{key}}}"<?php echo $additional_attributes ? " $additional_attributes" : '' ?>>{{{action.title}}}</a></li>
2019-09-23 13:34:25 +03:00
<# }); #>
</ul>
</div>
<?php
}
2019-10-01 11:53:34 +03:00
2020-10-21 10:27:15 +03:00
/**
* AJAX handler - Get options for the member directory "Admin filtering"
* @version 2.1.12
*/
2019-10-01 11:53:34 +03:00
function default_filter_settings() {
UM()->admin()->check_ajax_nonce();
2020-10-21 10:27:15 +03:00
// we can't use function "sanitize_key" because it changes uppercase to lowercase
2020-10-29 18:54:15 +02:00
$filter_key = sanitize_text_field( $_REQUEST['key'] );
$directory_id = absint( $_REQUEST['directory_id'] );
2019-10-01 11:53:34 +03:00
2020-01-10 17:31:55 +02:00
$html = $this->show_filter( $filter_key, array( 'form_id' => $directory_id ), false, true );
2019-10-01 11:53:34 +03:00
wp_send_json_success( array( 'field_html' => $html ) );
}
2023-06-12 15:22:35 +03:00
/**
* Get member directory id by page id.
*
* @param int $page_id Page ID.
*
* @return array Member directories ID.
*/
public function get_member_directory_id( $page_id ) {
$members_page = get_post( $page_id );
if ( ! empty( $members_page ) && ! is_wp_error( $members_page ) ) {
if ( ! empty( $members_page->post_content ) ) {
preg_match_all( '/\[ultimatemember[^\]]*?form_id\=[\'"]*?(\d+)[\'"]*?/i', $members_page->post_content, $matches );
if ( ! empty( $matches[1] ) && is_array( $matches[1] ) ) {
$member_directory_ids = array_map( 'absint', $matches[1] );
return $member_directory_ids;
}
}
}
return array();
}
2019-08-14 10:54:16 +03:00
}
2021-06-29 02:51:54 +03:00
}