mirror of
https://github.com/10h30/ultimatemember.git
synced 2026-07-11 18:56:10 +09:00
Implement directory privacy settings and add rate limiting
Adds configurable privacy options for member directories, allowing restrictions on visibility based on roles or login status. Introduces rate limiting for unauthenticated AJAX requests to prevent brute-force attacks or abuse.
This commit is contained in:
@@ -284,6 +284,12 @@ if ( ! class_exists( 'um\admin\Admin' ) ) {
|
||||
'_um_mode' => array(
|
||||
'sanitize' => 'key',
|
||||
),
|
||||
'_um_privacy' => array(
|
||||
'sanitize' => 'absint',
|
||||
),
|
||||
'_um_privacy_roles' => array(
|
||||
'sanitize' => array( $this, 'sanitize_existed_role' ),
|
||||
),
|
||||
'_um_view_types' => array(
|
||||
'sanitize' => array( $this, 'sanitize_md_view_types' ),
|
||||
),
|
||||
|
||||
@@ -209,6 +209,13 @@ if ( ! class_exists( 'um\admin\Secure' ) ) {
|
||||
$scanner_content .= '</span>';
|
||||
|
||||
$secure_fields = array(
|
||||
array(
|
||||
'id' => 'ajax_nopriv_rate_limit',
|
||||
'type' => 'checkbox',
|
||||
'label' => __( 'Rate Limit', 'ultimate-member' ),
|
||||
'checkbox_label' => __( 'Enable Rate Limiting', 'ultimate-member' ),
|
||||
'description' => __( 'This prevents brute-force enumeration attempts in guest AJAX requests.', 'ultimate-member' ),
|
||||
),
|
||||
array(
|
||||
'id' => 'banned_capabilities',
|
||||
'type' => 'multi_checkbox',
|
||||
|
||||
@@ -728,7 +728,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) {
|
||||
* @param $object
|
||||
* @param $box
|
||||
*/
|
||||
function load_metabox_directory( $object, $box ) {
|
||||
public function load_metabox_directory( $object, $box ) {
|
||||
$box['id'] = str_replace( 'um-admin-form-', '', $box['id'] );
|
||||
|
||||
preg_match('#\{.*?\}#s', $box['id'], $matches );
|
||||
@@ -857,6 +857,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Metabox' ) ) {
|
||||
public function add_metabox_directory() {
|
||||
add_meta_box( 'submitdiv', __( 'Publish', 'ultimate-member' ), array( &$this, 'custom_submitdiv' ), 'um_directory', 'side', 'high' );
|
||||
add_meta_box( 'um-admin-form-general', __( 'General Options', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' );
|
||||
add_meta_box( 'um-admin-form-privacy', __( 'Privacy Options', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' );
|
||||
add_meta_box( 'um-admin-form-sorting', __( 'Sorting', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' );
|
||||
add_meta_box( 'um-admin-form-profile', __( 'Profile Card', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' );
|
||||
add_meta_box( 'um-admin-form-search', __( 'Search Options', 'ultimate-member' ), array( &$this, 'load_metabox_directory' ), 'um_directory', 'normal', 'default' );
|
||||
|
||||
@@ -1032,6 +1032,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Settings' ) ) {
|
||||
'display_login_form_notice' => array(
|
||||
'sanitize' => 'bool',
|
||||
),
|
||||
'ajax_nopriv_rate_limit' => array(
|
||||
'sanitize' => 'bool',
|
||||
),
|
||||
'banned_capabilities' => array(
|
||||
'sanitize' => array( UM()->admin(), 'sanitize_wp_capabilities_assoc' ),
|
||||
),
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$fields = array(
|
||||
array(
|
||||
'id' => '_um_privacy',
|
||||
'type' => 'select',
|
||||
'label' => __( 'Who can see this member directory', 'ultimate-member' ),
|
||||
'description' => __( 'Select which users can view this member directory. Minimum recommended visibility is `Members only`. Please pay attention that visible for guests (anyone) member directory can have sensitive information.', 'ultimate-member' ),
|
||||
'options' => array(
|
||||
0 => __( 'Anyone', 'ultimate-member' ),
|
||||
1 => __( 'Guests only', 'ultimate-member' ),
|
||||
2 => __( 'Members only', 'ultimate-member' ),
|
||||
3 => __( 'Only specific roles', 'ultimate-member' ),
|
||||
),
|
||||
'value' => UM()->query()->get_meta_value( '_um_privacy', null, 2 ),
|
||||
),
|
||||
array(
|
||||
'id' => '_um_privacy_roles',
|
||||
'type' => 'select',
|
||||
'multi' => true,
|
||||
'label' => __( 'Allowed roles', 'ultimate-member' ),
|
||||
'description' => __( 'Select the the user roles allowed to view this member directory.', 'ultimate-member' ),
|
||||
'options' => UM()->roles()->get_roles(),
|
||||
'placeholder' => __( 'Choose user roles...', 'ultimate-member' ),
|
||||
'conditional' => array( '_um_privacy', '=', '3' ),
|
||||
'value' => UM()->query()->get_meta_value( '_um_privacy_roles', null, 'na' ),
|
||||
),
|
||||
);
|
||||
|
||||
$fields = apply_filters( 'um_admin_extend_directory_options_privacy', $fields );
|
||||
?>
|
||||
|
||||
<div class="um-admin-metabox">
|
||||
<?php
|
||||
UM()->admin_forms(
|
||||
array(
|
||||
'class' => 'um-member-directory-privacy um-half-column',
|
||||
'prefix_id' => 'um_metadata',
|
||||
'fields' => $fields,
|
||||
)
|
||||
)->render_form();
|
||||
?>
|
||||
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
@@ -141,6 +141,8 @@ if ( ! class_exists( 'um\Config' ) ) {
|
||||
'_um_core' => 'members',
|
||||
'_um_template' => 'members',
|
||||
'_um_mode' => 'directory',
|
||||
'_um_privacy' => 2,
|
||||
'_um_privacy_roles' => array(),
|
||||
'_um_view_types' => array( 'grid' ),
|
||||
'_um_default_view' => 'grid',
|
||||
'_um_roles' => array(),
|
||||
@@ -729,6 +731,7 @@ if ( ! class_exists( 'um\Config' ) ) {
|
||||
'lock_register_forms' => false,
|
||||
'display_login_form_notice' => false,
|
||||
'secure_ban_admins_accounts' => false,
|
||||
'ajax_nopriv_rate_limit' => true,
|
||||
'banned_capabilities' => array( 'manage_options', 'promote_users', 'level_10' ),
|
||||
'secure_notify_admins_banned_accounts' => false,
|
||||
'secure_notify_admins_banned_accounts__interval' => 'instant',
|
||||
|
||||
@@ -47,6 +47,37 @@ if ( ! class_exists( 'UM_Functions' ) ) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user rate limit has been reached based on the provided context
|
||||
*
|
||||
* @param string $context The context for which the rate limit check is being performed
|
||||
* @param int|null $requests_num Number requests per minute. Default 10.
|
||||
*
|
||||
* @return bool True if the rate limit has been reached, false otherwise
|
||||
*/
|
||||
public function is_rate_limited( $context, $requests_num = 10 ) {
|
||||
if ( is_user_logged_in() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! UM()->options()->get( 'ajax_nopriv_rate_limit' ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$transient_name = 'um_ajax_nopriv_rate_limit_' . md5( $context . '_' . $_SERVER['REMOTE_ADDR'] );
|
||||
$rate_limit = get_transient( $transient_name );
|
||||
$requests_num = apply_filters( 'um_ajax_rate_limit_requests_num', $requests_num, $context ); // 10 requests per minute per IP
|
||||
|
||||
if ( false === $rate_limit ) {
|
||||
set_transient( $transient_name, 1, MINUTE_IN_SECONDS );
|
||||
} elseif ( $rate_limit < $requests_num ) {
|
||||
set_transient( $transient_name, $rate_limit + 1, MINUTE_IN_SECONDS );
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* What type of request is this?
|
||||
|
||||
@@ -1375,7 +1375,6 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
require_once 'core/um-actions-form.php';
|
||||
require_once 'core/um-actions-access.php';
|
||||
require_once 'core/um-actions-wpadmin.php';
|
||||
require_once 'core/um-actions-ajax.php';
|
||||
require_once 'core/um-actions-login.php';
|
||||
require_once 'core/um-actions-register.php';
|
||||
require_once 'core/um-actions-profile.php';
|
||||
|
||||
@@ -266,6 +266,10 @@ if ( ! class_exists( 'um\core\Files' ) ) {
|
||||
public function ajax_remove_file() {
|
||||
UM()->check_ajax_nonce();
|
||||
|
||||
if ( UM()->is_rate_limited( 'remove_file' ) ) {
|
||||
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
if ( empty( $_POST['src'] ) ) {
|
||||
wp_send_json_error( __( 'Wrong path', 'ultimate-member' ) );
|
||||
}
|
||||
@@ -314,6 +318,11 @@ if ( ! class_exists( 'um\core\Files' ) ) {
|
||||
*/
|
||||
public function ajax_resize_image() {
|
||||
UM()->check_ajax_nonce();
|
||||
|
||||
if ( UM()->is_rate_limited( 'resize_image' ) ) {
|
||||
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
// phpcs:disable WordPress.Security.NonceVerification -- verified by the `check_ajax_nonce()`
|
||||
if ( ! isset( $_REQUEST['src'], $_REQUEST['coord'], $_REQUEST['key'] ) ) {
|
||||
wp_send_json_error( esc_js( __( 'Invalid parameters', 'ultimate-member' ) ) );
|
||||
@@ -447,6 +456,10 @@ if ( ! class_exists( 'um\core\Files' ) ) {
|
||||
* @throws Exception
|
||||
*/
|
||||
public function ajax_image_upload() {
|
||||
if ( UM()->is_rate_limited( 'upload_image' ) ) {
|
||||
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
$ret['error'] = null;
|
||||
$ret = array();
|
||||
|
||||
@@ -645,6 +658,10 @@ if ( ! class_exists( 'um\core\Files' ) ) {
|
||||
* @throws Exception
|
||||
*/
|
||||
public function ajax_file_upload() {
|
||||
if ( UM()->is_rate_limited( 'upload_file' ) ) {
|
||||
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
$ret['error'] = null;
|
||||
$ret = array();
|
||||
|
||||
|
||||
@@ -116,6 +116,10 @@ if ( ! class_exists( 'um\core\Form' ) ) {
|
||||
public function ajax_select_options() {
|
||||
UM()->check_ajax_nonce();
|
||||
|
||||
if ( UM()->is_rate_limited( 'select_options' ) ) {
|
||||
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
// phpcs:disable WordPress.Security.NonceVerification
|
||||
|
||||
$arr_options = array();
|
||||
|
||||
@@ -595,6 +595,10 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
|
||||
public function ajax_get_members() {
|
||||
UM()->check_ajax_nonce();
|
||||
|
||||
if ( UM()->is_rate_limited( 'member_directory' ) ) {
|
||||
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
$blog_id = get_current_blog_id();
|
||||
@@ -609,6 +613,10 @@ if ( ! class_exists( 'um\core\Member_Directory_Meta' ) ) {
|
||||
}
|
||||
// phpcs:enable WordPress.Security.NonceVerification -- verified via `UM()->check_ajax_nonce();`.
|
||||
|
||||
if ( ! $this->can_view_directory( $directory_id ) ) {
|
||||
wp_send_json_error( __( 'You cannot see this member directory', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
$directory_data = UM()->query()->post_data( $directory_id );
|
||||
|
||||
// Predefined result for user without capabilities to see other members.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
namespace um\core;
|
||||
|
||||
use Exception;
|
||||
use WP_Post;
|
||||
use WP_User_Query;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
@@ -123,11 +124,79 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
public function __construct() {
|
||||
add_filter( 'init', array( &$this, 'init_variables' ) );
|
||||
|
||||
add_action( 'wp_insert_post', array( &$this, 'set_token' ), 10, 3 );
|
||||
add_action( 'template_redirect', array( &$this, 'access_members' ), 555 );
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the WordPress core searching fields in wp_users query.
|
||||
*
|
||||
* @since 2.6.10
|
||||
* @version 2.10.2
|
||||
* @param array|null $qv WP_User_Query variables.
|
||||
@@ -202,30 +271,71 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
*
|
||||
* @return bool|int
|
||||
*/
|
||||
function get_directory_by_hash( $hash ) {
|
||||
public function get_directory_by_hash( $hash ) {
|
||||
global $wpdb;
|
||||
|
||||
$directory_id = $wpdb->get_var( $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE SUBSTRING( MD5( ID ), 11, 5 ) = %s", $hash ) );
|
||||
|
||||
$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
|
||||
)
|
||||
);
|
||||
if ( empty( $directory_id ) ) {
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
return (int) $directory_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a secure random token for each directory
|
||||
*
|
||||
* @param int $id
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
public function set_directory_hash( $id ) {
|
||||
$unique_hash = wp_generate_password( 32, false );
|
||||
$result = update_post_meta( $id, '_um_directory_token', $unique_hash );
|
||||
if ( false === $result ) {
|
||||
return false;
|
||||
}
|
||||
return $unique_hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $id
|
||||
*
|
||||
* @return bool|string
|
||||
*/
|
||||
function get_directory_hash( $id ) {
|
||||
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 );
|
||||
}
|
||||
return $hash;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get view Type template
|
||||
* @param string $type
|
||||
@@ -673,7 +783,7 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
*/
|
||||
$attrs = apply_filters( 'um_search_fields', $attrs, $field_key, $directory_data['form_id'] );
|
||||
|
||||
$unique_hash = substr( md5( $directory_data['form_id'] ), 10, 5 );
|
||||
$unique_hash = $this->get_directory_hash( $directory_data['form_id'] );
|
||||
|
||||
ob_start();
|
||||
|
||||
@@ -2546,15 +2656,14 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
|
||||
$data_array = array(
|
||||
'card_anchor' => esc_html( substr( md5( $user_id ), 10, 5 ) ),
|
||||
'id' => absint( $user_id ),
|
||||
'role' => esc_html( um_user( 'role' ) ),
|
||||
'account_status' => esc_html( UM()->common()->users()->get_status( $user_id ) ),
|
||||
'account_status_name' => esc_html( UM()->common()->users()->get_status( $user_id, 'formatted' ) ),
|
||||
'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.
|
||||
'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,
|
||||
'edit_profile_url' => esc_url( um_edit_profile_url() ),
|
||||
'edit_profile_url' => $can_edit ? esc_url( um_edit_profile_url() ) : '',
|
||||
'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,
|
||||
@@ -2788,13 +2897,16 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Main Query function for getting members via AJAX
|
||||
*/
|
||||
function ajax_get_members() {
|
||||
public function ajax_get_members() {
|
||||
UM()->check_ajax_nonce();
|
||||
|
||||
if ( UM()->is_rate_limited( 'member_directory' ) ) {
|
||||
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
global $wpdb;
|
||||
|
||||
if ( empty( $_POST['directory_id'] ) ) {
|
||||
@@ -2807,6 +2919,10 @@ if ( ! class_exists( 'um\core\Member_Directory' ) ) {
|
||||
wp_send_json_error( __( 'Wrong member directory data', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
if ( ! $this->can_view_directory( $directory_id ) ) {
|
||||
wp_send_json_error( __( 'You cannot see this member directory', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
$directory_data = UM()->query()->post_data( $directory_id );
|
||||
|
||||
//predefined result for user without capabilities to see other members
|
||||
|
||||
@@ -794,6 +794,9 @@ if ( ! class_exists( 'um\core\Shortcodes' ) ) {
|
||||
}
|
||||
|
||||
if ( 'directory' === $args['mode'] ) {
|
||||
if ( ! UM()->member_directory()->can_view_directory( $this->form_id ) ) {
|
||||
return ''; // Checking for privacy settings of the member directory
|
||||
}
|
||||
wp_enqueue_script( 'um_members' );
|
||||
wp_enqueue_style( 'um_members' );
|
||||
}
|
||||
|
||||
@@ -105,6 +105,10 @@ if ( ! class_exists( 'um\core\User_posts' ) ) {
|
||||
function load_posts() {
|
||||
UM()->check_ajax_nonce();
|
||||
|
||||
if ( UM()->is_rate_limited( 'paginate_posts' ) ) {
|
||||
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
$author = ! empty( $_POST['author'] ) ? absint( $_POST['author'] ) : get_current_user_id();
|
||||
$page = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 0;
|
||||
|
||||
@@ -153,6 +157,10 @@ if ( ! class_exists( 'um\core\User_posts' ) ) {
|
||||
function load_comments() {
|
||||
UM()->check_ajax_nonce();
|
||||
|
||||
if ( UM()->is_rate_limited( 'paginate_comments' ) ) {
|
||||
wp_send_json_error( __( 'Too many requests', 'ultimate-member' ) );
|
||||
}
|
||||
|
||||
$user_id = ! empty( $_POST['user_id'] ) ? absint( $_POST['user_id'] ) : get_current_user_id();
|
||||
$page = ! empty( $_POST['page'] ) ? absint( $_POST['page'] ) : 0;
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
// Exit if accessed directly
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
/**
|
||||
* Run check if username exists
|
||||
* @uses action hooks: wp_ajax_nopriv_ultimatemember_check_username_exists, wp_ajax_ultimatemember_check_username_exists
|
||||
* @return boolean
|
||||
*/
|
||||
function ultimatemember_check_username_exists() {
|
||||
UM()->check_ajax_nonce();
|
||||
|
||||
$username = isset( $_REQUEST['username'] ) ? sanitize_user( $_REQUEST['username'] ) : '';
|
||||
$exists = username_exists( $username );
|
||||
|
||||
/**
|
||||
* UM hook
|
||||
*
|
||||
* @type filter
|
||||
* @title um_validate_username_exists
|
||||
* @description Change username exists validation
|
||||
* @input_vars
|
||||
* [{"var":"$exists","type":"bool","desc":"Exists?"},
|
||||
* {"var":"$username","type":"string","desc":"Username"}]
|
||||
* @change_log
|
||||
* ["Since: 2.0"]
|
||||
* @usage
|
||||
* <?php add_filter( 'um_validate_username_exists', 'function_name', 10, 2 ); ?>
|
||||
* @example
|
||||
* <?php
|
||||
* add_filter( 'um_validate_username_exists', 'my_validate_username_exists', 10, 2 );
|
||||
* function my_account_pre_updating_profile( $exists, $username ) {
|
||||
* // your code here
|
||||
* return $exists;
|
||||
* }
|
||||
* ?>
|
||||
*/
|
||||
$exists = apply_filters( 'um_validate_username_exists', $exists, $username );
|
||||
|
||||
if ( $exists ) {
|
||||
echo 1;
|
||||
} else {
|
||||
echo 0;
|
||||
}
|
||||
|
||||
die();
|
||||
}
|
||||
add_action('wp_ajax_nopriv_ultimatemember_check_username_exists', 'ultimatemember_check_username_exists');
|
||||
add_action('wp_ajax_ultimatemember_check_username_exists', 'ultimatemember_check_username_exists');
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* Page: "Members"
|
||||
*
|
||||
* @version 2.6.1
|
||||
* @version 2.11.1
|
||||
*
|
||||
* @var array $args
|
||||
* @var bool $cover_photos
|
||||
@@ -23,8 +23,8 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$unique_hash = substr( md5( $args['form_id'] ), 10, 5 ); ?>
|
||||
|
||||
$unique_hash = UM()->member_directory()->get_directory_hash( $args['form_id'] );
|
||||
?>
|
||||
<script type="text/template" id="tmpl-um-member-grid-<?php echo esc_attr( $unique_hash ) ?>">
|
||||
<div class="um-members um-members-grid">
|
||||
<div class="um-gutter-sizer"></div>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* Page: "Members"
|
||||
*
|
||||
* @version 2.6.1
|
||||
* @version 2.11.1
|
||||
*
|
||||
* @var array $args
|
||||
* @var bool $cover_photos
|
||||
@@ -19,10 +19,12 @@
|
||||
* @var array $reveal_fields
|
||||
* @var string $no_users
|
||||
*/
|
||||
if ( ! defined( 'ABSPATH' ) ) exit;
|
||||
|
||||
$unique_hash = substr( md5( $args['form_id'] ), 10, 5 ); ?>
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$unique_hash = UM()->member_directory()->get_directory_hash( $args['form_id'] );
|
||||
?>
|
||||
<script type="text/template" id="tmpl-um-member-list-<?php echo esc_attr( $unique_hash ) ?>">
|
||||
<div class="um-members um-members-list">
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*
|
||||
* Page: "Members"
|
||||
*
|
||||
* @version 2.6.8
|
||||
* @version 2.11.1
|
||||
*
|
||||
* @var array $args
|
||||
*/
|
||||
@@ -23,7 +23,7 @@ foreach ( UM()->config()->core_directory_meta['members'] as $k => $v ) {
|
||||
$def_args[ $key ] = $v;
|
||||
}
|
||||
|
||||
$unique_hash = substr( md5( $args['form_id'] ), 10, 5 );
|
||||
$unique_hash = UM()->member_directory()->get_directory_hash( $args['form_id'] );
|
||||
|
||||
$args = array_merge( $def_args, $args );
|
||||
|
||||
@@ -237,8 +237,8 @@ if ( ( ( $search && $show_search ) || ( $filters && $show_filters && count( $sea
|
||||
$postid = ! empty( $post->ID ) ? $post->ID : '';
|
||||
?>
|
||||
|
||||
<div class="um <?php echo esc_attr( $this->get_class( $mode ) ); ?> um-<?php echo esc_attr( substr( md5( $form_id ), 10, 5 ) ); ?>"
|
||||
data-hash="<?php echo esc_attr( substr( md5( $form_id ), 10, 5 ) ) ?>" data-base-post="<?php echo esc_attr( $postid ) ?>"
|
||||
<div class="um <?php echo esc_attr( $this->get_class( $mode ) ); ?> um-<?php echo esc_attr( $unique_hash ); ?>"
|
||||
data-hash="<?php echo esc_attr( $unique_hash ) ?>" data-base-post="<?php echo esc_attr( $postid ) ?>"
|
||||
data-must-search="<?php echo esc_attr( $must_search ); ?>" data-searched="<?php echo $not_searched ? '0' : '1'; ?>"
|
||||
data-view_type="<?php echo esc_attr( $current_view ) ?>" data-page="<?php echo esc_attr( $current_page ) ?>"
|
||||
data-sorting="<?php echo esc_attr( $sort_from_url ) ?>">
|
||||
@@ -313,7 +313,7 @@ $postid = ! empty( $post->ID ) ? $post->ID : '';
|
||||
<?php $items = array();
|
||||
|
||||
foreach ( $sorting_options as $value => $title ) {
|
||||
$items[] = '<a href="javascript:void(0);" data-directory-hash="' . esc_attr( substr( md5( $form_id ), 10, 5 ) ) . '" class="um-sortyng-by-' . esc_attr( $value ) . '" data-value="' . esc_attr( $value ) . '" data-selected="' . ( ( $sort_from_url == $value ) ? '1' : '0' ) . '" data-default="' . ( ( $default_sorting == $value ) ? '1' : '0' ) . '">' . $title . '</a>'; ?>
|
||||
$items[] = '<a href="javascript:void(0);" data-directory-hash="' . esc_attr( $unique_hash ) . '" class="um-sortyng-by-' . esc_attr( $value ) . '" data-value="' . esc_attr( $value ) . '" data-selected="' . ( ( $sort_from_url == $value ) ? '1' : '0' ) . '" data-default="' . ( ( $default_sorting == $value ) ? '1' : '0' ) . '">' . $title . '</a>'; ?>
|
||||
<?php }
|
||||
|
||||
UM()->member_directory()->dropdown_menu( '.um-member-directory-sorting-a', 'click', $items ); ?>
|
||||
|
||||
Reference in New Issue
Block a user