mirror of
https://github.com/10h30/ultimatemember.git
synced 2026-07-11 18:56:10 +09:00
Merge pull request #1580 from ultimatemember/development/2.9.x
Version 2.9.1
This commit is contained in:
@@ -15,7 +15,7 @@
|
||||
"step": "installPlugin",
|
||||
"pluginZipFile": {
|
||||
"resource": "url",
|
||||
"url": "https:\/\/downloads.wordpress.org\/plugin\/ultimate-member.2.9.0.zip"
|
||||
"url": "https:\/\/downloads.wordpress.org\/plugin\/ultimate-member.2.9.1.zip"
|
||||
},
|
||||
"options": {
|
||||
"activate": true
|
||||
|
||||
@@ -44,7 +44,7 @@ GNU Version 2 or Any Later Version
|
||||
|
||||
### IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSION 2.6.7 PATCHES SECURITY PRIVILEGE ESCALATION VULNERABILITY. PLEASE SEE [THIS ARTICLE](https://docs.ultimatemember.com/article/1866-security-incident-update-and-recommended-actions) FOR MORE INFORMATION
|
||||
|
||||
[Official Release Version: 2.9.0](https://github.com/ultimatemember/ultimatemember/releases/tag/2.9.0).
|
||||
[Official Release Version: 2.9.1](https://github.com/ultimatemember/ultimatemember/releases/tag/2.9.1).
|
||||
|
||||
## Changelog
|
||||
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
== Changelog ==
|
||||
|
||||
= 2.9.1 November 15, 2024 =
|
||||
|
||||
* Enhancements:
|
||||
|
||||
- Added: `um_image_upload_validation` hook for 3rd-party validation during upload images
|
||||
|
||||
* Bugfixes:
|
||||
|
||||
- Fixed: "Load textdomain just in time" issue
|
||||
- Fixed: Capabilities checking in the wp-admin > Users list table
|
||||
- Fixed: File/image upload on the role specific profile form
|
||||
- Fixed: Issues when the form's custom fields meta has a wrong format
|
||||
- Fixed: Validation of the "Registration Default Role" slug
|
||||
- Fixed: Allowed query variables via registered REST API class only when REST_REQUEST is defined
|
||||
|
||||
= 2.9.0 November 12, 2024 =
|
||||
|
||||
* Enhancements:
|
||||
|
||||
@@ -42,14 +42,7 @@ if ( ! class_exists( 'um\action_scheduler\Init' ) ) {
|
||||
*/
|
||||
public function __construct() {
|
||||
if ( ! $this->can_be_active() ) {
|
||||
UM()->admin()->notices()->add_notice(
|
||||
'um-action-scheduler',
|
||||
array(
|
||||
'class' => 'notice-warning is-dismissible',
|
||||
// translators: %1$s - Plugin name, %1$s - Plugin Version
|
||||
'message' => '<p>' . sprintf( __( '<strong>%1$s %2$s</strong> The file needed to enable the Action Scheduler is missing. The plugin will continue to function as it did before, but without the new benefits offered by the Action Scheduler.', 'ultimate-member' ), UM_PLUGIN_NAME, UM_VERSION ) . '</p>',
|
||||
)
|
||||
);
|
||||
add_action( 'init', array( $this, 'add_notice' ) );
|
||||
} else {
|
||||
add_filter( 'um_settings_structure', array( $this, 'add_setting' ) );
|
||||
|
||||
@@ -60,6 +53,17 @@ if ( ! class_exists( 'um\action_scheduler\Init' ) ) {
|
||||
}
|
||||
}
|
||||
|
||||
public function add_notice() {
|
||||
UM()->admin()->notices()->add_notice(
|
||||
'um-action-scheduler',
|
||||
array(
|
||||
'class' => 'notice-warning is-dismissible',
|
||||
// translators: %1$s - Plugin name, %1$s - Plugin Version
|
||||
'message' => '<p>' . sprintf( __( '<strong>%1$s %2$s</strong> The file needed to enable the Action Scheduler is missing. The plugin will continue to function as it did before, but without the new benefits offered by the Action Scheduler.', 'ultimate-member' ), UM_PLUGIN_NAME, UM_VERSION ) . '</p>',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the Action Scheduler setting to Ultimate Member feature settings
|
||||
*
|
||||
|
||||
@@ -366,8 +366,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Builder' ) ) {
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function get_fields_by_row( $row_id ) {
|
||||
|
||||
public function get_fields_by_row( $row_id ) {
|
||||
if ( empty( $this->global_fields ) || ! is_array( $this->global_fields ) ) {
|
||||
$this->global_fields = array();
|
||||
}
|
||||
@@ -379,10 +378,9 @@ if ( ! class_exists( 'um\admin\core\Admin_Builder' ) ) {
|
||||
}
|
||||
}
|
||||
|
||||
return ( isset ( $results ) ) ? $results : '';
|
||||
return isset( $results ) ? $results : '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get fields by sub row
|
||||
*
|
||||
|
||||
@@ -23,10 +23,7 @@ if ( ! class_exists( 'um\admin\core\Admin_Navmenu' ) ) {
|
||||
* Admin_Navmenu constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
self::$fields = array(
|
||||
'um_nav_public' => __( 'Display Mode', 'ultimate-member' ),
|
||||
'um_nav_roles' => __( 'By Role', 'ultimate-member' ),
|
||||
);
|
||||
add_action( 'init', array( &$this, 'set_variables' ) );
|
||||
|
||||
add_action( 'customize_controls_print_footer_scripts', array( &$this, '_wp_template' ) );
|
||||
add_action( 'wp_update_nav_menu_item', array( &$this, '_save' ), 10, 3 );
|
||||
@@ -36,6 +33,12 @@ if ( ! class_exists( 'um\admin\core\Admin_Navmenu' ) ) {
|
||||
// add_action( 'wp_nav_menu_item_custom_fields_customize_template', array( $this, 'wp_nav_menu_item_custom_fields_customize_template' ), 20, 5 );
|
||||
}
|
||||
|
||||
public function set_variables() {
|
||||
self::$fields = array(
|
||||
'um_nav_public' => __( 'Display Mode', 'ultimate-member' ),
|
||||
'um_nav_roles' => __( 'By Role', 'ultimate-member' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fires just before the move buttons of a nav menu item in the menu editor.
|
||||
|
||||
+35
-35
@@ -204,8 +204,8 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
$this->is_filtering = 0;
|
||||
$this->honeypot = 'um_request';
|
||||
|
||||
// textdomain loading
|
||||
add_action( 'init', array( &$this, 'localize' ), 0 );
|
||||
// @todo investigate permanently delete https://make.wordpress.org/core/2024/10/21/i18n-improvements-6-7/#Enhanced-support-for-only-using-PHP-translation-files
|
||||
add_action( 'init', array( &$this, 'localize' ), 0 ); // textdomain loading
|
||||
|
||||
// include UM classes
|
||||
$this->includes();
|
||||
@@ -243,33 +243,33 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
*
|
||||
* @since 2.8.5 WordPress native functions are used to make this function clear.
|
||||
*/
|
||||
public function localize() {
|
||||
$default_domain = dirname( plugin_basename( UM_PLUGIN ) );
|
||||
/**
|
||||
* Filters the plugin's textdomain.
|
||||
*
|
||||
* @param {string} $domain Plugin's textdomain.
|
||||
*
|
||||
* @return {string} Maybe changed plugin's textdomain.
|
||||
*
|
||||
* @since 1.3.x
|
||||
* @hook um_language_textdomain
|
||||
*
|
||||
* @example <caption>Change UM language locale.</caption>
|
||||
* function my_um_language_textdomain( $domain ) {
|
||||
* $domain = 'ultimate-member-custom';
|
||||
* return $domain;
|
||||
* }
|
||||
* add_filter( 'um_language_textdomain', 'my_um_language_textdomain' );
|
||||
*/
|
||||
$domain = apply_filters( 'um_language_textdomain', $default_domain );
|
||||
|
||||
// Unload textdomain if it has already loaded.
|
||||
if ( is_textdomain_loaded( $domain ) ) {
|
||||
unload_textdomain( $domain, true );
|
||||
}
|
||||
load_plugin_textdomain( $domain, false, $default_domain . '/languages' );
|
||||
}
|
||||
// public function localize() {
|
||||
// $default_domain = dirname( plugin_basename( UM_PLUGIN ) );
|
||||
// /**
|
||||
// * Filters the plugin's textdomain.
|
||||
// *
|
||||
// * @param {string} $domain Plugin's textdomain.
|
||||
// *
|
||||
// * @return {string} Maybe changed plugin's textdomain.
|
||||
// *
|
||||
// * @since 1.3.x
|
||||
// * @hook um_language_textdomain
|
||||
// *
|
||||
// * @example <caption>Change UM language locale.</caption>
|
||||
// * function my_um_language_textdomain( $domain ) {
|
||||
// * $domain = 'ultimate-member-custom';
|
||||
// * return $domain;
|
||||
// * }
|
||||
// * add_filter( 'um_language_textdomain', 'my_um_language_textdomain' );
|
||||
// */
|
||||
// $domain = apply_filters( 'um_language_textdomain', $default_domain );
|
||||
//
|
||||
// // Unload textdomain if it has already loaded.
|
||||
// if ( is_textdomain_loaded( $domain ) ) {
|
||||
// unload_textdomain( $domain, true );
|
||||
// }
|
||||
// load_plugin_textdomain( $domain, false, $default_domain . '/languages' );
|
||||
// }
|
||||
|
||||
/**
|
||||
* 1.3.x active extensions deactivate for properly running 2.0.x AJAX upgrades
|
||||
@@ -548,7 +548,6 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
$this->password();
|
||||
$this->rewrite();
|
||||
$this->mail();
|
||||
$this->rest_api();
|
||||
$this->shortcodes();
|
||||
$this->roles();
|
||||
$this->user();
|
||||
@@ -565,11 +564,15 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
$this->blocks();
|
||||
$this->secure();
|
||||
|
||||
//if multisite networks active
|
||||
// If multisite networks active
|
||||
if ( is_multisite() ) {
|
||||
$this->multisite();
|
||||
}
|
||||
|
||||
// Call only when REST_API request
|
||||
if ( defined( 'REST_REQUEST' ) && REST_REQUEST ) {
|
||||
$this->rest_api();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1001,14 +1004,12 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
return $this->classes['config'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.0
|
||||
*
|
||||
* @return um\core\rest\API_v1|um\core\rest\API_v2
|
||||
*/
|
||||
function rest_api() {
|
||||
|
||||
public function rest_api() {
|
||||
$api_version = $this->options()->get( 'rest_api_version' );
|
||||
|
||||
if ( empty( $this->classes['rest_api'] ) ) {
|
||||
@@ -1024,7 +1025,6 @@ if ( ! class_exists( 'UM' ) ) {
|
||||
return $this->classes['rest_api'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @since 2.0
|
||||
*
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<?php
|
||||
namespace um\core;
|
||||
|
||||
use Exception;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
@@ -441,10 +443,14 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
* @param array $position
|
||||
*/
|
||||
private function add_field_from_predefined( $global_id, $form_id, $position = array() ) {
|
||||
$fields = UM()->query()->get_attr( 'custom_fields', $form_id );
|
||||
$field_scope = UM()->builtin()->predefined_fields;
|
||||
$fields = UM()->query()->get_attr( 'custom_fields', $form_id );
|
||||
if ( empty( $fields ) || ! is_array( $fields ) ) {
|
||||
$fields = array();
|
||||
}
|
||||
|
||||
if ( ! isset( $fields[ $global_id ] ) ) {
|
||||
$field_scope = UM()->builtin()->predefined_fields;
|
||||
|
||||
$count = 1;
|
||||
if ( ! empty( $fields ) ) {
|
||||
$count = count( $fields ) + 1;
|
||||
@@ -1624,7 +1630,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
* @param $key
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get_field( $key ) {
|
||||
$fields = $this->get_fields();
|
||||
@@ -2161,7 +2167,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
* @param array $args
|
||||
*
|
||||
* @return string|null
|
||||
* @throws \Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function edit_field( $key, $data, $rule = false, $args = array() ) {
|
||||
global $_um_profile_id;
|
||||
@@ -4030,7 +4036,6 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
return $arr;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get fields in row
|
||||
*
|
||||
@@ -4038,8 +4043,8 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function get_fields_by_row( $row_id ) {
|
||||
if ( ! isset( $this->get_fields ) ) {
|
||||
public function get_fields_by_row( $row_id ) {
|
||||
if ( ! isset( $this->get_fields ) || ! is_array( $this->get_fields ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
@@ -4049,10 +4054,9 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
}
|
||||
}
|
||||
|
||||
return ( isset ( $results ) ) ? $results : '';
|
||||
return isset( $results ) ? $results : '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get fields by sub row
|
||||
*
|
||||
@@ -4119,7 +4123,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
* @param array $args
|
||||
*
|
||||
* @return string|null
|
||||
* @throws \Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function display( $mode, $args ) {
|
||||
$output = null;
|
||||
@@ -4289,7 +4293,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
* @param bool $rule
|
||||
*
|
||||
* @return string|null
|
||||
* @throws \Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function view_field( $key, $data, $rule = false ) {
|
||||
if ( '_um_last_login' === $key ) {
|
||||
@@ -4644,7 +4648,6 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
return apply_filters( "um_view_field_output_" . $data['type'], $data );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display fields ( view mode )
|
||||
*
|
||||
@@ -4652,7 +4655,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
* @param array $args
|
||||
*
|
||||
* @return string|null
|
||||
* @throws \Exception
|
||||
* @throws Exception
|
||||
*/
|
||||
public function display_view( $mode, $args ) {
|
||||
$output = null;
|
||||
@@ -4664,7 +4667,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
$this->set_mode = $mode;
|
||||
$this->set_id = absint( $this->global_args['form_id'] );
|
||||
|
||||
$this->field_icons = ( isset( $this->global_args['icons'] ) ) ? $this->global_args['icons'] : 'label';
|
||||
$this->field_icons = isset( $this->global_args['icons'] ) ? $this->global_args['icons'] : 'label';
|
||||
|
||||
// start output here
|
||||
$this->get_fields = $this->get_fields();
|
||||
@@ -4694,8 +4697,7 @@ if ( ! class_exists( 'um\core\Fields' ) ) {
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $this->get_fields ) ) {
|
||||
|
||||
if ( ! empty( $this->get_fields ) && is_array( $this->get_fields ) ) {
|
||||
// find rows
|
||||
foreach ( $this->get_fields as $key => $array ) {
|
||||
if ( isset( $array['type'] ) && 'row' === $array['type'] ) {
|
||||
|
||||
+152
-117
@@ -376,6 +376,8 @@ if ( ! class_exists( 'um\core\Files' ) ) {
|
||||
wp_send_json_error( esc_js( __( 'You have no permission to edit this user through this form', 'ultimate-member' ) ) );
|
||||
}
|
||||
|
||||
$post_data['role'] = maybe_unserialize( $post_data['role'] );
|
||||
|
||||
if ( is_array( $post_data['role'] ) ) {
|
||||
if ( ! count( array_intersect( $post_data['role'], $current_user_roles ) ) ) {
|
||||
wp_send_json_error( esc_js( __( 'You have no permission to edit this user through this form', 'ultimate-member' ) ) );
|
||||
@@ -448,141 +450,172 @@ if ( ! class_exists( 'um\core\Files' ) ) {
|
||||
$ret['error'] = null;
|
||||
$ret = array();
|
||||
|
||||
/**
|
||||
* Filters image upload checking nonce.
|
||||
*
|
||||
* @param {bool} $verify_nonce Verify nonce marker. Default true.
|
||||
*
|
||||
* @return {bool} Verify nonce marker.
|
||||
*
|
||||
* @since 1.3.x
|
||||
* @hook um_image_upload_nonce
|
||||
*
|
||||
* @example <caption>Disable checking nonce on image upload.</caption>
|
||||
* function my_image_upload_nonce( $verify_nonce ) {
|
||||
* // your code here
|
||||
* $verify_nonce = false;
|
||||
* return $verify_nonce;
|
||||
* }
|
||||
* add_filter( 'um_image_upload_nonce', 'my_image_upload_nonce' );
|
||||
*/
|
||||
$um_image_upload_nonce = apply_filters( 'um_image_upload_nonce', true );
|
||||
if ( $um_image_upload_nonce ) {
|
||||
$timestamp = absint( $_POST['timestamp'] );
|
||||
$nonce = sanitize_text_field( $_POST['_wpnonce'] );
|
||||
if ( ! wp_verify_nonce( $nonce, "um_upload_nonce-{$timestamp}" ) && is_user_logged_in() ) {
|
||||
// This nonce is not valid.
|
||||
$ret['error'] = esc_html__( 'Invalid nonce', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
if ( empty( $_POST['key'] ) ) {
|
||||
$ret['error'] = esc_html__( 'Invalid image key', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
$id = sanitize_text_field( $_POST['key'] );
|
||||
$user_id = empty( $_POST['user_id'] ) ? null : absint( $_POST['user_id'] );
|
||||
if ( $user_id && is_user_logged_in() && ! UM()->roles()->um_current_user_can( 'edit', $user_id ) ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this user', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
if ( $user_id && ! is_user_logged_in() ) {
|
||||
$ret['error'] = esc_html__( 'Please login to edit this user', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
/**
|
||||
* Filters the custom validation marker for 3rd-party uploader.
|
||||
*
|
||||
* @param {bool} $custom_validation Custom validation marker. Is null by default. Keep null for UM core validation.
|
||||
* @param {string} $id Uploader field key.
|
||||
* @param {int} $user_id User ID.
|
||||
*
|
||||
* @return {bool} Custom validation marker.
|
||||
*
|
||||
* @since 2.9.1
|
||||
* @hook um_image_upload_validation
|
||||
*
|
||||
* @example <caption>Custom validation.</caption>
|
||||
* function my_um_image_upload_validation( $custom_validation, $id, $user_id ) {
|
||||
* // your code here
|
||||
* $ret['error'] = esc_html__( 'Error code', 'ultimate-member' );
|
||||
* wp_send_json_error( $ret );
|
||||
* return true;
|
||||
* }
|
||||
* add_filter( 'um_image_upload_validation', 'my_um_image_upload_validation', 10, 3 );
|
||||
*/
|
||||
$custom_validation = apply_filters( 'um_image_upload_validation', null, $id, $user_id );
|
||||
if ( is_null( $custom_validation ) ) {
|
||||
/**
|
||||
* Filters image upload checking nonce.
|
||||
*
|
||||
* @param {bool} $verify_nonce Verify nonce marker. Default true.
|
||||
*
|
||||
* @return {bool} Verify nonce marker.
|
||||
*
|
||||
* @since 1.3.x
|
||||
* @hook um_image_upload_nonce
|
||||
*
|
||||
* @example <caption>Disable checking nonce on image upload.</caption>
|
||||
* function my_image_upload_nonce( $verify_nonce ) {
|
||||
* // your code here
|
||||
* $verify_nonce = false;
|
||||
* return $verify_nonce;
|
||||
* }
|
||||
* add_filter( 'um_image_upload_nonce', 'my_image_upload_nonce' );
|
||||
*/
|
||||
$um_image_upload_nonce = apply_filters( 'um_image_upload_nonce', true );
|
||||
if ( $um_image_upload_nonce ) {
|
||||
$timestamp = absint( $_POST['timestamp'] );
|
||||
$nonce = sanitize_text_field( $_POST['_wpnonce'] );
|
||||
if ( ! wp_verify_nonce( $nonce, "um_upload_nonce-{$timestamp}" ) && is_user_logged_in() ) {
|
||||
// This nonce is not valid.
|
||||
$ret['error'] = esc_html__( 'Invalid nonce', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
}
|
||||
|
||||
$form_id = absint( $_POST['set_id'] );
|
||||
$mode = sanitize_key( $_POST['set_mode'] );
|
||||
|
||||
UM()->fields()->set_id = $form_id;
|
||||
UM()->fields()->set_mode = $mode;
|
||||
|
||||
if ( ! is_user_logged_in() && 'profile' === $mode ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit user profile', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
if ( null !== $user_id && 'register' === $mode ) {
|
||||
$ret['error'] = esc_html__( 'User has to be empty on registration', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
$form_post = get_post( $form_id );
|
||||
// Invalid post ID. Maybe post doesn't exist.
|
||||
if ( empty( $form_post ) ) {
|
||||
$ret['error'] = esc_html__( 'Invalid form ID', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
if ( 'um_form' !== $form_post->post_type ) {
|
||||
$ret['error'] = esc_html__( 'Invalid form post type', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
$form_status = get_post_status( $form_id );
|
||||
if ( 'publish' !== $form_status ) {
|
||||
$ret['error'] = esc_html__( 'Invalid form status', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
$post_data = UM()->query()->post_data( $form_id );
|
||||
if ( ! array_key_exists( 'mode', $post_data ) || $mode !== $post_data['mode'] ) {
|
||||
$ret['error'] = esc_html__( 'Invalid form type', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
// For profiles only.
|
||||
if ( 'profile' === $mode && ! empty( $post_data['use_custom_settings'] ) && ! empty( $post_data['role'] ) ) {
|
||||
// Option "Apply custom settings to this form". Option "Make this profile form role-specific".
|
||||
// Show the first Profile Form with role selected, don't show profile forms below the page with other role-specific setting.
|
||||
$current_user_roles = UM()->roles()->get_all_user_roles( $user_id );
|
||||
if ( empty( $current_user_roles ) ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this user through this form', 'ultimate-member' );
|
||||
if ( $user_id && is_user_logged_in() && ! UM()->roles()->um_current_user_can( 'edit', $user_id ) ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this user', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
if ( is_array( $post_data['role'] ) ) {
|
||||
if ( ! count( array_intersect( $post_data['role'], $current_user_roles ) ) ) {
|
||||
if ( $user_id && ! is_user_logged_in() ) {
|
||||
$ret['error'] = esc_html__( 'Please login to edit this user', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
$form_id = absint( $_POST['set_id'] );
|
||||
$mode = sanitize_key( $_POST['set_mode'] );
|
||||
|
||||
UM()->fields()->set_id = $form_id;
|
||||
UM()->fields()->set_mode = $mode;
|
||||
|
||||
if ( ! is_user_logged_in() && 'profile' === $mode ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit user profile', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
if ( null !== $user_id && 'register' === $mode ) {
|
||||
$ret['error'] = esc_html__( 'User has to be empty on registration', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
$form_post = get_post( $form_id );
|
||||
// Invalid post ID. Maybe post doesn't exist.
|
||||
if ( empty( $form_post ) ) {
|
||||
$ret['error'] = esc_html__( 'Invalid form ID', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
if ( 'um_form' !== $form_post->post_type ) {
|
||||
$ret['error'] = esc_html__( 'Invalid form post type', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
$form_status = get_post_status( $form_id );
|
||||
if ( 'publish' !== $form_status ) {
|
||||
$ret['error'] = esc_html__( 'Invalid form status', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
$post_data = UM()->query()->post_data( $form_id );
|
||||
if ( ! array_key_exists( 'mode', $post_data ) || $mode !== $post_data['mode'] ) {
|
||||
$ret['error'] = esc_html__( 'Invalid form type', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
// For profiles only.
|
||||
if ( 'profile' === $mode && ! empty( $post_data['use_custom_settings'] ) && ! empty( $post_data['role'] ) ) {
|
||||
// Option "Apply custom settings to this form". Option "Make this profile form role-specific".
|
||||
// Show the first Profile Form with role selected, don't show profile forms below the page with other role-specific setting.
|
||||
$current_user_roles = UM()->roles()->get_all_user_roles( $user_id );
|
||||
if ( empty( $current_user_roles ) ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this user through this form', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
} elseif ( ! in_array( $post_data['role'], $current_user_roles, true ) ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this user through this form', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
}
|
||||
|
||||
$id = sanitize_text_field( $_POST['key'] );
|
||||
$post_data['role'] = maybe_unserialize( $post_data['role'] );
|
||||
|
||||
if ( ! array_key_exists( 'custom_fields', $post_data ) || empty( $post_data['custom_fields'] ) ) {
|
||||
$ret['error'] = esc_html__( 'Invalid form fields', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
$custom_fields = maybe_unserialize( $post_data['custom_fields'] );
|
||||
if ( ! is_array( $custom_fields ) || ! array_key_exists( $id, $custom_fields ) ) {
|
||||
if ( ! ( 'profile' === $mode && in_array( $id, array( 'cover_photo', 'profile_photo' ), true ) ) ) {
|
||||
$ret['error'] = esc_html__( 'Invalid field metakey', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'profile' === $mode ) {
|
||||
if ( in_array( $id, array( 'cover_photo', 'profile_photo' ), true ) ) {
|
||||
if ( 'profile_photo' === $id ) {
|
||||
$disable_photo_uploader = empty( $post_data['use_custom_settings'] ) ? UM()->options()->get( 'disable_profile_photo_upload' ) : $post_data['disable_photo_upload'];
|
||||
if ( $disable_photo_uploader ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this field', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
} else {
|
||||
$cover_enabled_uploader = empty( $post_data['use_custom_settings'] ) ? UM()->options()->get( 'profile_cover_enabled' ) : $post_data['cover_enabled'];
|
||||
if ( ! $cover_enabled_uploader ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this field', 'ultimate-member' );
|
||||
if ( is_array( $post_data['role'] ) ) {
|
||||
if ( ! count( array_intersect( $post_data['role'], $current_user_roles ) ) ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this user through this form', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
} elseif ( ! in_array( $post_data['role'], $current_user_roles, true ) ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this user through this form', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
} elseif ( ! um_can_edit_field( $custom_fields[ $id ] ) ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this field', 'ultimate-member' );
|
||||
}
|
||||
|
||||
if ( ! array_key_exists( 'custom_fields', $post_data ) || empty( $post_data['custom_fields'] ) ) {
|
||||
$ret['error'] = esc_html__( 'Invalid form fields', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
$custom_fields = maybe_unserialize( $post_data['custom_fields'] );
|
||||
if ( ! is_array( $custom_fields ) || ! array_key_exists( $id, $custom_fields ) ) {
|
||||
if ( ! ( 'profile' === $mode && in_array( $id, array( 'cover_photo', 'profile_photo' ), true ) ) ) {
|
||||
$ret['error'] = esc_html__( 'Invalid field metakey', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'profile' === $mode ) {
|
||||
if ( in_array( $id, array( 'cover_photo', 'profile_photo' ), true ) ) {
|
||||
if ( 'profile_photo' === $id ) {
|
||||
$disable_photo_uploader = empty( $post_data['use_custom_settings'] ) ? UM()->options()->get( 'disable_profile_photo_upload' ) : $post_data['disable_photo_upload'];
|
||||
if ( $disable_photo_uploader ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this field', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
} else {
|
||||
$cover_enabled_uploader = empty( $post_data['use_custom_settings'] ) ? UM()->options()->get( 'profile_cover_enabled' ) : $post_data['cover_enabled'];
|
||||
if ( ! $cover_enabled_uploader ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this field', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
}
|
||||
} elseif ( ! um_can_edit_field( $custom_fields[ $id ] ) ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this field', 'ultimate-member' );
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( isset( $_FILES[ $id ]['name'] ) ) {
|
||||
@@ -706,6 +739,8 @@ if ( ! class_exists( 'um\core\Files' ) ) {
|
||||
wp_send_json_error( $ret );
|
||||
}
|
||||
|
||||
$post_data['role'] = maybe_unserialize( $post_data['role'] );
|
||||
|
||||
if ( is_array( $post_data['role'] ) ) {
|
||||
if ( ! count( array_intersect( $post_data['role'], $current_user_roles ) ) ) {
|
||||
$ret['error'] = esc_html__( 'You have no permission to edit this user through this form', 'ultimate-member' );
|
||||
|
||||
@@ -1075,7 +1075,9 @@ if ( ! class_exists( 'um\core\Form' ) ) {
|
||||
$global_role = get_option( 'default_role' ); // WP Global settings
|
||||
|
||||
$um_global_role = UM()->options()->get( 'register_role' ); // UM Settings Global settings
|
||||
if ( ! empty( $um_global_role ) ) {
|
||||
|
||||
$existing_roles = array_keys( wp_roles()->roles );
|
||||
if ( ! empty( $um_global_role ) && in_array( $um_global_role, $existing_roles, true ) ) {
|
||||
$global_role = $um_global_role; // Form Global settings
|
||||
}
|
||||
|
||||
@@ -1089,7 +1091,7 @@ if ( ! class_exists( 'um\core\Form' ) ) {
|
||||
$role = get_post_meta( $post_id, "_um_{$mode}_role", true );
|
||||
}
|
||||
|
||||
if ( empty( $role ) ) { // custom role is default, return default role's slug
|
||||
if ( empty( $role ) || ! in_array( $role, $existing_roles, true ) ) { // custom role is default, return default role's slug
|
||||
$role = $global_role;
|
||||
}
|
||||
|
||||
|
||||
@@ -687,7 +687,6 @@ if ( ! class_exists( 'um\core\Roles_Capabilities' ) ) {
|
||||
return $roles;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Current user can
|
||||
*
|
||||
@@ -696,55 +695,48 @@ if ( ! class_exists( 'um\core\Roles_Capabilities' ) ) {
|
||||
*
|
||||
* @return bool|int
|
||||
*/
|
||||
function um_current_user_can( $cap, $user_id ) {
|
||||
public function um_current_user_can( $cap, $user_id ) {
|
||||
if ( ! is_user_logged_in() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$user_id = absint( $user_id ); // typecast
|
||||
|
||||
$return = 1;
|
||||
|
||||
um_fetch_user( get_current_user_id() );
|
||||
if ( get_current_user_id() !== um_user( 'ID' ) ) {
|
||||
$temp_id = um_user( 'ID' );
|
||||
um_fetch_user( get_current_user_id() );
|
||||
}
|
||||
|
||||
$current_user_roles = $this->get_all_user_roles( $user_id );
|
||||
|
||||
switch( $cap ) {
|
||||
case 'edit':
|
||||
|
||||
if ( get_current_user_id() == $user_id ) {
|
||||
if ( um_user( 'can_edit_profile' ) ) {
|
||||
$return = 1;
|
||||
} else {
|
||||
$return = 0;
|
||||
}
|
||||
} else {
|
||||
|
||||
if ( ! um_user( 'can_access_private_profile' ) && UM()->user()->is_private_profile( $user_id ) ) {
|
||||
$return = 0;
|
||||
} else {
|
||||
if ( ! um_user( 'can_edit_everyone' ) ) {
|
||||
$return = 0;
|
||||
} else {
|
||||
if ( um_user( 'can_edit_roles' ) && ( empty( $current_user_roles ) || count( array_intersect( $current_user_roles, um_user( 'can_edit_roles' ) ) ) <= 0 ) ) {
|
||||
$return = 0;
|
||||
} else {
|
||||
$return = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( get_current_user_id() === $user_id && ! um_user( 'can_edit_profile' ) ) {
|
||||
$return = 0;
|
||||
} elseif ( ! um_user( 'can_access_private_profile' ) && UM()->user()->is_private_profile( $user_id ) ) {
|
||||
$return = 0;
|
||||
} elseif ( ! um_user( 'can_edit_everyone' ) ) {
|
||||
$return = 0;
|
||||
} elseif ( um_user( 'can_edit_roles' ) && ( empty( $current_user_roles ) || count( array_intersect( $current_user_roles, um_user( 'can_edit_roles' ) ) ) <= 0 ) ) {
|
||||
$return = 0;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'delete':
|
||||
if ( ! um_user( 'can_delete_everyone' ) )
|
||||
if ( ! um_user( 'can_delete_everyone' ) ) {
|
||||
$return = 0;
|
||||
elseif ( um_user( 'can_delete_roles' ) && ( empty( $current_user_roles ) || count( array_intersect( $current_user_roles, um_user( 'can_delete_roles' ) ) ) <= 0 ) )
|
||||
} elseif ( um_user( 'can_delete_roles' ) && ( empty( $current_user_roles ) || count( array_intersect( $current_user_roles, um_user( 'can_delete_roles' ) ) ) <= 0 ) ) {
|
||||
$return = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
um_fetch_user( $user_id );
|
||||
if ( ! empty( $temp_id ) ) {
|
||||
um_fetch_user( $temp_id );
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
@@ -1188,8 +1188,8 @@ function um_profile_header( $args ) {
|
||||
* }
|
||||
* ?>
|
||||
*/
|
||||
do_action( 'um_after_profile_name_inline', $args ); ?>
|
||||
|
||||
do_action( 'um_after_profile_name_inline', $args, um_user( 'ID' ) );
|
||||
?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
@@ -1215,7 +1215,7 @@ function um_profile_header( $args ) {
|
||||
* }
|
||||
* ?>
|
||||
*/
|
||||
do_action( 'um_after_profile_header_name_args', $args );
|
||||
do_action( 'um_after_profile_header_name_args', $args, um_user( 'ID' ) );
|
||||
/**
|
||||
* UM hook
|
||||
*
|
||||
|
||||
@@ -14,37 +14,44 @@ function um_avatar_defaults( $avatar_defaults ) {
|
||||
}
|
||||
add_filter( 'avatar_defaults', 'um_avatar_defaults', 99999 );
|
||||
|
||||
|
||||
/**
|
||||
* Get user UM avatars
|
||||
* Get user UM avatars.
|
||||
* @param string $avatar
|
||||
* @param string $id_or_email
|
||||
* @param string $size
|
||||
* @param string $avatar_class
|
||||
* @param string $default
|
||||
* @param string $alt
|
||||
* @hooks filter `get_avatar`
|
||||
* @return string returns avatar in image html elements
|
||||
*/
|
||||
function um_get_avatar( $avatar = '', $id_or_email='', $size = '96', $avatar_class = '', $default = '', $alt = '' ) {
|
||||
if ( is_numeric($id_or_email) )
|
||||
if ( is_numeric( $id_or_email ) ) {
|
||||
$user_id = (int) $id_or_email;
|
||||
elseif ( is_string( $id_or_email ) && ( $user = get_user_by( 'email', $id_or_email ) ) )
|
||||
} elseif ( is_string( $id_or_email ) && ( $user = get_user_by( 'email', $id_or_email ) ) ) {
|
||||
$user_id = $user->ID;
|
||||
elseif ( is_object( $id_or_email ) && ! empty( $id_or_email->user_id ) )
|
||||
} elseif ( is_object( $id_or_email ) && ! empty( $id_or_email->user_id ) ) {
|
||||
$user_id = (int) $id_or_email->user_id;
|
||||
if ( empty( $user_id ) )
|
||||
return $avatar;
|
||||
}
|
||||
|
||||
um_fetch_user( $user_id );
|
||||
if ( empty( $user_id ) ) {
|
||||
return $avatar;
|
||||
}
|
||||
|
||||
if ( $user_id !== um_user( 'ID' ) ) {
|
||||
$temp_id = um_user( 'ID' );
|
||||
um_fetch_user( $user_id );
|
||||
}
|
||||
|
||||
$avatar = um_user( 'profile_photo', $size );
|
||||
|
||||
if ( ! empty( $temp_id ) ) {
|
||||
um_fetch_user( $temp_id );
|
||||
}
|
||||
|
||||
return $avatar;
|
||||
}
|
||||
add_filter( 'get_avatar', 'um_get_avatar', 99999, 5 );
|
||||
|
||||
|
||||
if ( ! function_exists( 'um_filter_get_avatar_url' ) ) {
|
||||
|
||||
/**
|
||||
@@ -69,4 +76,4 @@ if ( ! function_exists( 'um_filter_get_avatar_url' ) ) {
|
||||
|
||||
// hooked in the get_avatar_data function
|
||||
add_filter( 'get_avatar_url', 'um_filter_get_avatar_url', 20, 3 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2169,7 +2169,10 @@ function um_get_default_avatar_uri() {
|
||||
function um_get_user_avatar_data( $user_id = '', $size = '96' ) {
|
||||
if ( empty( $user_id ) ) {
|
||||
$user_id = um_user( 'ID' );
|
||||
} else {
|
||||
}
|
||||
|
||||
if ( $user_id !== um_user( 'ID' ) ) {
|
||||
$temp_id = um_user( 'ID' );
|
||||
um_fetch_user( $user_id );
|
||||
}
|
||||
|
||||
@@ -2198,12 +2201,12 @@ function um_get_user_avatar_data( $user_id = '', $size = '96' ) {
|
||||
}
|
||||
|
||||
$gravatar_type = UM()->options()->get( 'use_um_gravatar_default_builtin_image' );
|
||||
if ( $gravatar_type == 'default' ) {
|
||||
if ( 'default' === $gravatar_type ) {
|
||||
if ( UM()->options()->get( 'use_um_gravatar_default_image' ) ) {
|
||||
$data['url'] = add_query_arg( 'd', $data['default'], $data['url'] );
|
||||
} else {
|
||||
$default = get_option( 'avatar_default', 'mystery' );
|
||||
if ( $default == 'gravatar_default' ) {
|
||||
if ( 'gravatar_default' === $default ) {
|
||||
$default = '';
|
||||
}
|
||||
$data['url'] = add_query_arg( 'd', $default, $data['url'] );
|
||||
@@ -2212,63 +2215,63 @@ function um_get_user_avatar_data( $user_id = '', $size = '96' ) {
|
||||
$data['url'] = add_query_arg( 'd', $gravatar_type, $data['url'] );
|
||||
}
|
||||
|
||||
$data['type'] = 'gravatar';
|
||||
$data['type'] = 'gravatar';
|
||||
$data['class'] .= ' um-avatar-gravatar';
|
||||
} else {
|
||||
$data['url'] = $data['default'];
|
||||
$data['type'] = 'default';
|
||||
$data['url'] = $data['default'];
|
||||
$data['type'] = 'default';
|
||||
$data['class'] .= ' um-avatar-default';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* UM hook
|
||||
* Filters the user avatar URL.
|
||||
*
|
||||
* @type filter
|
||||
* @title um_user_avatar_url_filter
|
||||
* @description Change user avatar URL
|
||||
* @input_vars
|
||||
* [{"var":"$avatar_uri","type":"string","desc":"Avatar URL"},
|
||||
* {"var":"$user_id","type":"int","desc":"User ID"}]
|
||||
* @change_log
|
||||
* ["Since: 2.0"]
|
||||
* @usage add_filter( 'um_user_avatar_url_filter', 'function_name', 10, 2 );
|
||||
* @example
|
||||
* <?php
|
||||
* add_filter( 'um_user_avatar_url_filter', 'my_user_avatar_url', 10, 2 );
|
||||
* function my_user_avatar_url( $avatar_uri ) {
|
||||
* @since 1.3.x
|
||||
* @hook um_user_avatar_url_filter
|
||||
*
|
||||
* @param {string} $url Avatar URL.
|
||||
* @param {int} $user_id User ID.
|
||||
* @param {array} $data Avatar data.
|
||||
*
|
||||
* @return {string} Avatar URL.
|
||||
*
|
||||
* @example <caption>Change the user avatar URL.</caption>
|
||||
* function my_um_user_avatar_url_filter( $url, $user_id, $data ) {
|
||||
* // your code here
|
||||
* return $avatar_uri;
|
||||
* $url = 'some_url';
|
||||
* return $url;
|
||||
* }
|
||||
* ?>
|
||||
* add_filter( 'um_user_avatar_url_filter', 'my_um_user_avatar_url_filter', 10, 3 );
|
||||
*/
|
||||
$data['url'] = apply_filters( 'um_user_avatar_url_filter', $data['url'], $user_id, $data );
|
||||
/**
|
||||
* UM hook
|
||||
* Filters the user avatar image `alt` argument.
|
||||
*
|
||||
* @type filter
|
||||
* @title um_avatar_image_alternate_text
|
||||
* @description Change user display name on um_user function profile photo
|
||||
* @input_vars
|
||||
* [{"var":"$display_name","type":"string","desc":"User Display Name"}]
|
||||
* @change_log
|
||||
* ["Since: 2.0"]
|
||||
* @usage add_filter( 'um_avatar_image_alternate_text', 'function_name', 10, 1 );
|
||||
* @example
|
||||
* <?php
|
||||
* add_filter( 'um_avatar_image_alternate_text', 'my_avatar_image_alternate_text', 10, 1 );
|
||||
* function my_avatar_image_alternate_text( $display_name ) {
|
||||
* @since 1.3.x
|
||||
* @hook um_avatar_image_alternate_text
|
||||
*
|
||||
* @param {string} $alt Avatar `alt` text.
|
||||
* @param {array} $data Avatar data.
|
||||
*
|
||||
* @return {string} Avatar URL.
|
||||
*
|
||||
* @example <caption>Change the user avatar URL.</caption>
|
||||
* function my_um_avatar_image_alternate_text( $alt, $data ) {
|
||||
* // your code here
|
||||
* return $display_name;
|
||||
* $alt = 'some_alt';
|
||||
* return $alt;
|
||||
* }
|
||||
* ?>
|
||||
* add_filter( 'um_avatar_image_alternate_text', 'my_um_avatar_image_alternate_text', 10, 2 );
|
||||
*/
|
||||
$data['alt'] = apply_filters( "um_avatar_image_alternate_text", um_user( "display_name" ), $data );
|
||||
$data['alt'] = apply_filters( 'um_avatar_image_alternate_text', um_user( 'display_name' ), $data );
|
||||
|
||||
if ( ! empty( $temp_id ) ) {
|
||||
um_fetch_user( $temp_id );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get user avatar url
|
||||
*
|
||||
@@ -2282,7 +2285,6 @@ function um_get_user_avatar_url( $user_id = '', $size = '96' ) {
|
||||
return $data['url'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* default cover
|
||||
*
|
||||
|
||||
+16
-287
@@ -6,7 +6,7 @@ Tags: community, member, membership, user-profile, user-registration
|
||||
Requires PHP: 5.6
|
||||
Requires at least: 5.5
|
||||
Tested up to: 6.7
|
||||
Stable tag: 2.9.0
|
||||
Stable tag: 2.9.1
|
||||
License: GPLv3
|
||||
License URI: http://www.gnu.org/licenses/gpl-3.0.txt
|
||||
|
||||
@@ -166,6 +166,21 @@ No specific extensions are needed. But we highly recommended keep active these P
|
||||
|
||||
IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSION 2.6.7 PATCHES SECURITY PRIVILEGE ESCALATION VULNERABILITY. PLEASE SEE [THIS ARTICLE](https://docs.ultimatemember.com/article/1866-security-incident-update-and-recommended-actions) FOR MORE INFORMATION
|
||||
|
||||
= 2.9.1 2024-11-15 =
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Added: `um_image_upload_validation` hook for 3rd-party validation during upload images
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: "Load textdomain just in time" issue
|
||||
* Fixed: Capabilities checking in the wp-admin > Users list table
|
||||
* Fixed: File/image upload on the role specific profile form
|
||||
* Fixed: Issues when the form's custom fields meta has a wrong format
|
||||
* Fixed: Validation of the "Registration Default Role" slug
|
||||
* Fixed: Allowed query variables via registered REST API class only when REST_REQUEST is defined
|
||||
|
||||
= 2.9.0 2024-11-12 =
|
||||
|
||||
**Enhancements**
|
||||
@@ -182,292 +197,6 @@ IMPORTANT: PLEASE UPDATE THE PLUGIN TO AT LEAST VERSION 2.6.7 IMMEDIATELY. VERSI
|
||||
|
||||
**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade**
|
||||
|
||||
= 2.8.9 2024-10-14 =
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Added: Using PHP tidy extension (if it's active) to make HTML textarea value clear
|
||||
* Added: `um_tidy_config` filter hook for setting PHP tidy config
|
||||
* Tweak: Avoid using force `set_status()` function.
|
||||
* Tweak: Properly using `UM()->common()->users()->get_status( $user_id )` instead of `um_user( 'account_status' )`
|
||||
* Tweak: Properly using `UM()->common()->users()->get_status( $user_id, 'formatted' )` instead of `um_user( 'account_status_name' )`
|
||||
* Tweak: Properly using `um_user( 'status' )` for getting user role setting while registration
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: UM tipsy removing inside .um-page selector (e.g. tipsy init from um-modal)
|
||||
* Fixed: Rollback using `<iframe>` for displaying HTML formatted textarea value
|
||||
* Fixed: Capability to edit user profile for Administrator when user doesn't have a capability to edit its profile
|
||||
* Fixed: Sending email notifications based on user status after registration
|
||||
* Fixed: PHP error when meta `um_member_directory_data` has a wrong format
|
||||
|
||||
**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade**
|
||||
|
||||
= 2.8.8 2024-10-04 =
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: Download routing initialization
|
||||
* Fixed: Textarea height and HTML formatted textarea field height isolated via `<iframe>` on view mode
|
||||
* Fixed: User registration if email activation or admin review are required
|
||||
* Fixed: First installation errors
|
||||
|
||||
**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade**
|
||||
|
||||
= 2.8.7 2024-10-01 =
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Added: Single user actions on WP Users list table
|
||||
* Updated: User status filter on WP Users list table
|
||||
* Updated: User bulk actions on WP Users list table
|
||||
* Updated: User actions on User Profile and Member Directory card
|
||||
* Added: Applying shortcodes in the post restriction message
|
||||
* Added: ProfilePage Structured Data
|
||||
* Added: Ability to use HTML tags (allowed in `wp_kses_post`) in the global block restriction message
|
||||
* Changed: Some wp-admin fields descriptions
|
||||
* Updated: Data format in `um_admin_bulk_user_actions_hook` filter hook. Changed format from `$action_slug => array( 'label' => $action_title )` to `$action_slug => $action_title`
|
||||
* Added: `$old_status` param to `um_after_user_status_is_changed` action hook
|
||||
* Added: `$user_id` param to `um_before_user_hash_is_changed` action hook
|
||||
* Added: `$user_id, $hash, $expiration` params to `um_after_user_hash_is_changed` action hook
|
||||
* Added: `um_restricted_post_content` filter hook
|
||||
* Added: `um_loggedin_inner_content` filter hook
|
||||
* Added: `um_profile_dynamic_meta_profile_schema` filter hook
|
||||
* Removed: `UM()->fields()->get_restricted_fields_for_edit()` function from a fields loop
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: Single user action on User Profile security vulnerability. CVE ID: CVE-2024-8520
|
||||
* Fixed: [um_loggedin] shortcode security vulnerability. CVE ID: CVE-2024-8519
|
||||
* Fixed: Performance issue related to Settings > Secure tab
|
||||
* Fixed: The "Clear All" button in the member directory did not reset all dependent dropdowns
|
||||
* Fixed: Telegram and Discord social links in profile header
|
||||
* Fixed: UM links to empty phone numbers
|
||||
* Fixed: Email changing via User Account flush session. Security enhancement because email can be used for login
|
||||
* Fixed: User Profile image URL in meta tags
|
||||
* Fixed: Empty User Profile and PHP Fatal error when cannot get profile field data
|
||||
* Fixed: Parsing /modal/ templates and parsing templates on the Windows hosting
|
||||
* Fixed: Validation `form_id` attribute in the `ultimatemember` shortcode
|
||||
|
||||
**Templates required update**
|
||||
|
||||
* login-to-view.php
|
||||
|
||||
**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade**
|
||||
|
||||
**Deprecated**
|
||||
|
||||
* Hook: Action hook `um_after_user_status_is_changed_hook`. Use action hook `um_after_user_status_is_changed` instead.
|
||||
* Hook: Action hook `um_when_status_is_set`. Use action hook `um_before_user_status_is_set` instead.
|
||||
* Hook: Action hook `um_admin_user_action_hook`. Use filter hook `um_handle_bulk_actions-users-{$current_action}` for custom user bulk actions instead.
|
||||
* Hook: Action hook `um_admin_user_action_{$bulk_action}_hook`. Use filter hook `um_handle_bulk_actions-users-{$current_action}` for custom user bulk actions instead.
|
||||
* Hook: Action hook `um_admin_custom_hook_{$action}`. Use filter hook `um_handle_bulk_actions-users-{$current_action}` for custom user bulk actions instead.
|
||||
* Hook: Filter hook `um_admin_views_users`. Use filter 'um_user_statuses_admin_filter_options' hook instead.
|
||||
* Function: `UM()->user()->set_status( $status )`. Use function `UM()->common()->users()->set_status( $status, $user_id )` instead.
|
||||
* Function: `UM()->user()->assign_secretkey()`. Use function `UM()->common()->users()->assign_secretkey( $user_id )` instead.
|
||||
* Function: `UM()->user()->approve( $repeat )`. Use function `UM()->common()->users()->approve( $user_id, $force )` instead.
|
||||
* Function: `UM()->user()->email_pending()`. Use function `UM()->common()->users()->send_activation( $user_id, $force )` instead.
|
||||
* Function: `UM()->user()->pending()`. Use function `UM()->common()->users()->set_as_pending( $user_id, $force )` instead.
|
||||
* Function: `UM()->user()->reject()`. Use function `UM()->common()->users()->reject( $user_id )` instead.
|
||||
* Function: `UM()->user()->deactivate()`. Use function `UM()->common()->users()->deactivate( $user_id )` instead.
|
||||
* Function: `UM()->user()->user_exists_by_id( $user_id )`. Use function `UM()->common()->users()::user_exists( $user_id )` instead.
|
||||
* Function: `UM()->files()->format_bytes( $size )`. Use function `UM()->common()->filesystem()::format_bytes( $size )` instead.
|
||||
|
||||
= 2.8.6 2024-05-22 =
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Added: Member Directory > Admin Filtering supports datepicker and timepicker filter-types with only "From" or "To" filled value
|
||||
* Added: Ability to customize modal templates upload-single.php and view-photo.php
|
||||
* Added: New FontAwesome library. Version 6.5.2
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: Using HTML in the block restriction message. Replaced escaper to wp_kses sanitize while saving
|
||||
* Fixed: Getting user capabilities without role
|
||||
* Fixed: YouTube validation when field value is empty
|
||||
* Fixed: Social URLs sanitizing where user can put his social username (e.g. Instagram, Facebook)
|
||||
* Fixed: Using only published forms and member directories IDs on predefined pages installation
|
||||
* Fixed: Member Directory before query hook when custom meta table is active
|
||||
* Fixed: Unique email validation
|
||||
* Fixed: Displaying asterisk on the Profile > View Mode
|
||||
* Fixed: PHP errors while upgrade from 1.3.x version
|
||||
* Fixed: Rating field view
|
||||
* Fixed: Sorting by last login value when "Hide my last login" is set
|
||||
* Fixed: PHP errors while uploading files
|
||||
* Fixed: Parsing error on the license activation
|
||||
* Fixed: Saving field value when type is textarea and using HTML is enabled
|
||||
|
||||
**Templates required update**
|
||||
|
||||
* Renamed templates/modal/um_upload_single.php → templates/modal/upload-single.php
|
||||
* Renamed templates/modal/um_view_photo.php → templates/modal/view-photo.php
|
||||
|
||||
**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade**
|
||||
|
||||
= 2.8.5 2024-04-09 =
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Added: "Hide my last login" via the Account > Privacy setting
|
||||
* Added: Exclude and Include fields for member directory searching
|
||||
* Tweak: Compatibility with WordPress 6.5
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: URL attributes escaping (CVE-2024-2765)
|
||||
* Fixed: wp-admin Ultimate Member > Dashboard layouts
|
||||
* Fixed: Required fields labels
|
||||
* Fixed: Change password and update account email notifications duplicates
|
||||
* Fixed: Reset Password urlencoded username
|
||||
* Fixed: Clear media JS in wp-admin settings
|
||||
|
||||
**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade**
|
||||
|
||||
= 2.8.4 2024-03-06 =
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Tweak: Added separate file for full changelog. readme.txt shows only a few latest versions
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: Member directory data sanitizing (CVE-2024-2123)
|
||||
* Fixed: Activation link time changed from seconds to days
|
||||
* Fixed: Password validation error
|
||||
* Fixed: Password reset url for the approved user who didn't set their password after registration without password
|
||||
* Fixed: Conflict with WebP Uploads
|
||||
|
||||
**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade**
|
||||
|
||||
= 2.8.3 2024-02-19 =
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Added: Link to the Ultimate Member docs
|
||||
* Tweak: Ultimate Member > Settings redesign. More details about setting up. Tooltips changed to descriptions.
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: Member directory queries to custom usermeta table properly escaped and validated
|
||||
* Fixed: Member directory custom sorting when wp_usermeta table is used
|
||||
* Fixed: aria-invalid attribute for the user description field
|
||||
* Fixed: wp_kses protocols for email notifications content
|
||||
* Fixed: PHP notice while registration form validation
|
||||
* Fixed: Field validations (English letters, Alpha-numeric types)
|
||||
* Fixed: Hidden buttons in the modal when uploading profile and cover photo
|
||||
* Fixed: Theme updater log message
|
||||
* Fixed: Search line shortcode layout
|
||||
* Fixed: PHP notice while login form submission
|
||||
* Fixed: Email notifications HTML layout
|
||||
* Fixed: Default email notification body color
|
||||
* Fixed: Ignore username slug when custom meta slug exists when parse user from query
|
||||
|
||||
**Templates required update**
|
||||
|
||||
* email/notification_deletion.php
|
||||
* email/notification_new_user.php
|
||||
* email/notification_review.php
|
||||
* email/welcome_email.php
|
||||
* password-change.php
|
||||
|
||||
**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade**
|
||||
|
||||
= 2.8.2 2024-01-15 =
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Added: The `data` protocol for embedding base64 encoded logos in emails
|
||||
* Added: Hook `um_access_restricted_post_instance` for filtering the restricted post instance
|
||||
* Added: Shortcode `[um_author_profile_link]` for getting user Profile URL
|
||||
* Updated: Using underscore.js native debounce method for resize handler
|
||||
* Updated: Texts spelling
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: AJAX requests conflict with `um_current_locale` attribute
|
||||
* Fixed: Pickadate styling (Date & Time fields) in wp-admin screen
|
||||
* Fixed: RTL styling and removed `um` class from UM frontend predefined pages
|
||||
* Fixed: select2 conflict with Impreza theme
|
||||
* Fixed: cropper conflict with Avada theme and active Fusion Image lazyload
|
||||
* Fixed: MegaMenu conflict with nav menu items conditional settings (e.g. Newsletter theme)
|
||||
* Fixed: PHP Fatal error when there isn't a proper WP_Post object in UM User Profile > Posts loop
|
||||
* Fixed: Account styles
|
||||
* Fixed: Saving `um_form_version` postmeta
|
||||
|
||||
**Templates required update**
|
||||
|
||||
* profile/posts-single.php
|
||||
|
||||
**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade**
|
||||
|
||||
= 2.8.1: 2023-12-20 =
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Updated: Twitter texts to X
|
||||
* Added: Safeguards against clickjacking attacks on UM Forms
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: Displaying notice to avoid using wrong symbols
|
||||
* Fixed: UM > Settings button styles
|
||||
* Fixed: Error notice when creating page via extensions
|
||||
* Fixed: Workaround for Cropper.JS if UM.frontend.cropper.obj undefined (Cropper hasn't been properly inited for UM objects)
|
||||
* Fixed: The visibility of sub-items of hidden menu items
|
||||
|
||||
= 2.8.0: 2023-12-11 =
|
||||
|
||||
**Enhancements**
|
||||
|
||||
* Refactored: wp-admin assets. Separated or merged some file based on the wp-admin screens
|
||||
* Tweak: SASS pre-processor is used for wp-admin styles.
|
||||
* Tweak: Using minified JS and CSS in wp-admin and frontend assets
|
||||
* Tweak: Added PHP class UM()->admin()->screen() for screen control in wp-admin
|
||||
* Updated: jquery-ui styles to 1.13.2 version. Prefixed with .um class.
|
||||
* Updated: Cropper.JS to 1.6.1 version
|
||||
* Note: Select2.JS version 4.0.13
|
||||
* Refreshed: Tipsy.JS to 1.0.0a version. Removed custom changes and restored library base code
|
||||
* Refreshed: Raty.JS to 2.6.0 version. Restored library base code
|
||||
* Refreshed: Pickadate.JS to 3.6.2 version. Restored library base code
|
||||
* Updated: Used `um-tip-{x}` classes to make Tipsy.JS initialization commonly for wp-admin and frontend.
|
||||
* Updated: wp-admin forms class and render icon type field
|
||||
* Updated: Using `custom_submitdiv` on the UM Form and UM Member Directory screen to avoid custom styling for unnecessary metabox functionality. Just to render the necessary metabox content with only submission tools.
|
||||
|
||||
**Bugfixes**
|
||||
|
||||
* Fixed: Using fields with numeric keys in Form Builder
|
||||
* Fixed: Pickadate.JS (datetime picker) localizations using
|
||||
* Fixed: PHP notices on the SiteHealth and Form Builder pages
|
||||
* Fixed: Using 'um_user_permissions_filter' hook and it's arguments.
|
||||
|
||||
**Deprecated**
|
||||
|
||||
* Removed Simplebar.JS library in Ultimate Member core. It's used only in extensions.
|
||||
* Removed outdated styles and scripts for 1.3.x first install page
|
||||
* `UM()->admin()->enqueue()->js_url` param. Please use `UM()->admin()->enqueue()::get_url( 'js' );` or `self::get_url( 'js' );` instead
|
||||
* `UM()->admin()->enqueue()->css_url` param. Please use `UM()->admin()->enqueue()::get_url( 'css' );` or `self::get_url( 'js' );` instead
|
||||
* `UM()->frontend()->enqueue()->js_url` param. Please use `UM()->frontend()->enqueue()::get_url( 'js' );` or `self::get_url( 'js' );` instead
|
||||
* `UM()->frontend()->enqueue()->css_url` param. Please use `UM()->frontend()->enqueue()::get_url( 'css' );` or `self::get_url( 'js' );` instead
|
||||
* Fully `UM()->permalinks()->um_rel_canonical_()` function. Because since version 2.1.7 there is used `um_profile_remove_wpseo();` alternative
|
||||
* Fully `UM()->permalinks()->admin_act_url()` function. Since update for wp-admin links when there is nonce this function isn't used
|
||||
* Fully `UM()->admin()->enqueue()->front_js_baseurl` param.
|
||||
* Fully `UM()->admin()->enqueue()->front_css_baseurl` param.
|
||||
* Fully `UM()->admin()->enqueue()->post_page` param.
|
||||
* Fully `UM()->frontend()->enqueue()->load_google_charts()` function. Outdated.
|
||||
* Fully `UM()->frontend()->enqueue()->load_fileupload()` function. Used scripts/styles dependencies to load script in the necessary place.
|
||||
* Fully `UM()->frontend()->enqueue()->load_datetimepicker()` function. Used scripts/styles dependencies to load script in the necessary place.
|
||||
* Fully `UM()->frontend()->enqueue()->load_scrollbar()` function. Outdated
|
||||
* Fully `UM()->frontend()->enqueue()->load_imagecrop()` function. Used scripts/styles dependencies to load script in the necessary place.
|
||||
* `UM()->is_um_screen()` function. Please use `UM()->admin()->screen()->is_own_screen()` instead
|
||||
* `UM()->is_plugin_post_type()` function. Please use `UM()->admin()->screen()->is_own_post_type()` instead
|
||||
* `UM()->is_restricted_entity()` function. Please use `UM()->admin()->screen()->is_restricted_entity()` instead
|
||||
* `UM()->cpt_list()` function. Please use `UM()->common()->cpt()->get_list()` instead
|
||||
* `um-admin-clear` CSS class. It duplicates WordPress native `clear`. Using WordPress native instead.
|
||||
* `um-admin-tipsy-{x}` classes to make Tipsy.JS initialization commonly for wp-admin and frontend by `um-tip-{x}` class.
|
||||
|
||||
**Cached and optimized/minified assets(JS/CSS) must be flushed/re-generated after upgrade**
|
||||
|
||||
[See changelog for all versions](https://plugins.svn.wordpress.org/ultimate-member/trunk/changelog.txt).
|
||||
|
||||
== Upgrade Notice ==
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
* Plugin Name: Ultimate Member
|
||||
* Plugin URI: http://ultimatemember.com/
|
||||
* Description: The easiest way to create powerful online communities and beautiful user profiles with WordPress
|
||||
* Version: 2.9.0
|
||||
* Version: 2.9.1
|
||||
* Author: Ultimate Member
|
||||
* Author URI: http://ultimatemember.com/
|
||||
* Text Domain: ultimate-member
|
||||
|
||||
Reference in New Issue
Block a user