options()->get( 'profile_tab_main' ) ) {
return;
}
/**
* Filters user's ability to view a profile
*
* @since 1.3.x
* @hook um_profile_can_view_main
*
* @param {int} $can_view Can view profile. It's -1 by default.
* @param {int} $profile_id User Profile ID.
*
* @return {int} Can view profile. Set it to -1 for displaying and vice versa to hide.
*
* @example
Make profile hidden.
* function my_profile_can_view_main( $can_view, $profile_id ) {
* $can_view = 1; // make profile hidden.
* return $can_view;
* }
* add_filter( 'um_profile_can_view_main', 'my_profile_can_view_main', 10, 2 );
*/
$can_view = apply_filters( 'um_profile_can_view_main', -1, um_profile_id() );
if ( -1 === (int) $can_view ) {
/**
* Fires before UM Form content.
*
* @since 1.3.x
* @hook um_before_form
*
* @param {array} $args UM Form shortcode arguments.
*
* @example
Make any custom action before UM form.
* function my_before_form( $args ) {
* // your code here
* }
* add_action( 'um_before_form', 'my_before_form' );
*/
do_action( 'um_before_form', $args );
/**
* Fires before UM Form fields.
*
* Note: $mode can be equals to 'login', 'profile', 'register'.
*
* @since 1.3.x
* @hook um_before_{$mode}_fields
*
* @param {array} $args UM Form shortcode arguments.
*
* @example
Make any custom action before UM Profile form fields.
* function my_before_profile_fields( $args ) {
* // your code here
* }
* add_action( 'um_before_profile_fields', 'my_before_profile_fields' );
* @example
Make any custom action before UM Login form fields.
* function my_before_login_fields( $args ) {
* // your code here
* }
* add_action( 'um_before_login_fields', 'my_before_login_fields' );
* @example
Make any custom action before UM Register form fields.
* function my_before_register_fields( $args ) {
* // your code here
* }
* add_action( 'um_before_register_fields', 'my_before_register_fields' );
*/
do_action( "um_before_{$mode}_fields", $args );
/**
* Fires for rendering UM Form fields.
*
* Note: $mode can be equals to 'login', 'profile', 'register'.
*
* @since 1.3.x
* @hook um_main_{$mode}_fields
*
* @param {array} $args UM Form shortcode arguments.
*
* @example
Make any custom action when profile form fields are rendered.
* function my_main_profile_fields( $args ) {
* // your code here
* }
* add_action( 'um_main_profile_fields', 'my_main_profile_fields' );
* @example
Make any custom action when login form fields are rendered.
* function my_main_login_fields( $args ) {
* // your code here
* }
* add_action( 'um_main_login_fields', 'my_main_login_fields' );
* @example
Make any custom action when register form fields are rendered.
* function my_main_register_fields( $args ) {
* // your code here
* }
* add_action( 'um_main_register_fields', 'my_main_register_fields' );
*/
do_action( "um_main_{$mode}_fields", $args );
/**
* Fires after UM Form fields.
*
* @since 1.3.x
* @hook um_after_form_fields
*
* @param {array} $args UM Form shortcode arguments.
*
* @example
Make any custom action after UM Form fields.
* function my_after_form_fields( $args ) {
* // your code here
* }
* add_action( 'um_after_form_fields', 'my_after_form_fields' );
*/
do_action( 'um_after_form_fields', $args );
/**
* Fires after UM Form fields.
*
* Note: $mode can be equals to 'login', 'profile', 'register'.
*
* @since 1.3.x
* @hook um_after_{$mode}_fields
*
* @param {array} $args UM Form shortcode arguments.
*
* @example
Make any custom action after profile form fields.
* function my_after_profile_fields( $args ) {
* // your code here
* }
* add_action( 'um_after_profile_fields', 'my_after_profile_fields' );
* @example
Make any custom action after login form fields.
* function my_after_login_fields( $args ) {
* // your code here
* }
* add_action( 'um_after_login_fields', 'my_after_login_fields' );
* @example
Make any custom action after register form fields.
* function my_after_register_fields( $args ) {
* // your code here
* }
* add_action( 'um_after_register_fields', 'my_after_register_fields' );
*/
do_action( "um_after_{$mode}_fields", $args );
/**
* Fires after UM Form content.
*
* @since 1.3.x
* @hook um_after_form
*
* @param {array} $args UM Form shortcode arguments.
*
* @example
Make any custom action after UM Form content.
* function my_after_form( $args ) {
* // your code here
* }
* add_action( 'um_after_form', 'my_after_form' );
*/
do_action( 'um_after_form', $args );
} else {
?>
roles()->um_current_user_can( 'edit', $user_id ) ) {
UM()->user()->set( $user_id );
} else {
wp_die( esc_html__( 'You are not allowed to edit this user.', 'ultimate-member' ) );
}
$userinfo = UM()->user()->profile;
/**
* Fires before collecting data to update on profile form submit.
*
* @since 1.3.x
* @hook um_user_before_updating_profile
*
* @param {array} $userinfo Userdata.
*
* @example
Make any custom action before collecting data to update on profile form submit.
* function my_user_before_updating_profile( $role_key, $role_meta ) {
* // your code here
* }
* add_action( 'um_user_before_updating_profile', 'my_user_before_updating_profile', 10, 2 );
*/
do_action( 'um_user_before_updating_profile', $userinfo );
$fields = maybe_unserialize( $form_data['custom_fields'] );
$fields = apply_filters( 'um_user_edit_profile_fields', $fields, $args, $form_data );
// loop through fields
if ( ! empty( $fields ) ) {
$arr_restricted_fields = UM()->fields()->get_restricted_fields_for_edit( $user_id );
foreach ( $fields as $key => $array ) {
if ( ! isset( $array['type'] ) ) {
continue;
}
if ( isset( $array['edit_forbidden'] ) ) {
continue;
}
if ( is_array( $array ) ) {
$origin_data = UM()->fields()->get_field( $key );
if ( is_array( $origin_data ) ) {
// Merge data passed with original field data.
$array = array_merge( $origin_data, $array );
}
}
// required option? 'required_opt' - it's field attribute predefined in the field data in code
// @todo can be unnecessary. it's used in 1 place (user account).
if ( isset( $array['required_opt'] ) ) {
$opt = $array['required_opt'];
if ( UM()->options()->get( $opt[0] ) !== $opt[1] ) {
continue;
}
}
// fields that need to be disabled in edit mode (profile) (email, username, etc.)
if ( is_array( $arr_restricted_fields ) && in_array( $key, $arr_restricted_fields, true ) ) {
continue;
}
if ( ! um_can_edit_field( $array ) || ! um_can_view_field( $array ) ) {
continue;
}
// skip saving role here
if ( in_array( $key, array( 'role', 'role_select', 'role_radio' ), true ) ) {
continue;
}
//the same code in class-validation.php validate_fields_values for registration form
//rating field validation
if ( 'rating' === $array['type'] && isset( $args['submitted'][ $key ] ) ) {
if ( ! is_numeric( $args['submitted'][ $key ] ) ) {
continue;
} else {
if ( $array['number'] == 5 ) {
if ( ! in_array( $args['submitted'][ $key ], range( 1, 5 ) ) ) {
continue;
}
} elseif ( $array['number'] == 10 ) {
if ( ! in_array( $args['submitted'][ $key ], range( 1, 10 ) ) ) {
continue;
}
}
}
}
/**
* Returns dropdown/multi-select options keys from a callback function
* @since 2019-05-30
*/
$has_custom_source = apply_filters( "um_has_dropdown_options_source__{$key}", false );
if ( isset( $array['options'] ) && in_array( $array['type'], array( 'select', 'multiselect' ), true ) ) {
$options = $array['options'];
if ( ! empty( $array['custom_dropdown_options_source'] ) && function_exists( $array['custom_dropdown_options_source'] ) && ! $has_custom_source ) {
if ( ! UM()->fields()->is_source_blacklisted( $array['custom_dropdown_options_source'] ) ) {
$callback_result = call_user_func( $array['custom_dropdown_options_source'], $array['options'] );
if ( is_array( $callback_result ) ) {
$options = array_keys( $callback_result );
}
}
}
$array['options'] = apply_filters( "um_custom_dropdown_options__{$key}", $options );
}
//validation of correct values from options in wp-admin
$stripslashes = '';
if ( isset( $args['submitted'][ $key ] ) && is_string( $args['submitted'][ $key ] ) ) {
$stripslashes = wp_unslash( $args['submitted'][ $key ] );
}
if ( 'select' === $array['type'] ) {
if ( ! empty( $array['options'] ) && ! empty( $stripslashes ) && ! in_array( $stripslashes, array_map( 'trim', $array['options'] ) ) && ! $has_custom_source ) {
continue;
}
//update empty user meta
if ( ! isset( $args['submitted'][ $key ] ) || '' === $args['submitted'][ $key ] ) {
update_user_meta( $user_id, $key, '' );
}
}
//validation of correct values from options in wp-admin
//the user cannot set invalid value in the hidden input at the page
if ( in_array( $array['type'], array( 'multiselect', 'checkbox', 'radio' ), true ) ) {
if ( ! empty( $args['submitted'][ $key ] ) && ! empty( $array['options'] ) ) {
if ( is_array( $args['submitted'][ $key ] ) ) {
$args['submitted'][ $key ] = array_map( 'stripslashes', array_map( 'trim', $args['submitted'][ $key ] ) );
if ( is_array( $array['options'] ) ) {
$args['submitted'][ $key ] = array_intersect( $args['submitted'][ $key ], array_map( 'trim', $array['options'] ) );
} else {
$args['submitted'][ $key ] = array_intersect( $args['submitted'][ $key ], array( trim( $array['options'] ) ) );
}
} else {
if ( is_array( $array['options'] ) ) {
$args['submitted'][ $key ] = array_intersect( array( stripslashes( trim( $args['submitted'][ $key ] ) ) ), array_map( 'trim', $array['options'] ) );
} else {
$args['submitted'][ $key ] = array_intersect( array( stripslashes( trim( $args['submitted'][ $key ] ) ) ), array( trim( $array['options'] ) ) );
}
}
}
// update empty user meta
if ( ! isset( $args['submitted'][ $key ] ) || '' === $args['submitted'][ $key ] ) {
update_user_meta( $user_id, $key, array() );
}
}
if ( isset( $args['submitted'][ $key ] ) ) {
if ( in_array( $array['type'], array( 'image', 'file' ), true ) ) {
if ( um_is_temp_file( $args['submitted'][ $key ] ) || 'empty_file' === $args['submitted'][ $key ] ) {
$files[ $key ] = $args['submitted'][ $key ];
} elseif( um_is_file_owner( UM()->uploader()->get_upload_base_url() . $user_id . '/' . $args['submitted'][ $key ], $user_id ) ) {
} else {
$files[ $key ] = 'empty_file';
}
} else {
if ( 'password' === $array['type'] ) {
$to_update[ $key ] = wp_hash_password( $args['submitted'][ $key ] );
// translators: %s: title.
$args['submitted'][ $key ] = sprintf( __( 'Your choosed %s', 'ultimate-member' ), $array['title'] );
} else {
if ( isset( $userinfo[ $key ] ) && $args['submitted'][ $key ] !== $userinfo[ $key ] ) {
$to_update[ $key ] = $args['submitted'][ $key ];
} elseif ( '' !== $args['submitted'][ $key ] ) {
$to_update[ $key ] = $args['submitted'][ $key ];
}
}
}
// use this filter after all validations has been completed, and we can extend data based on key
$to_update = apply_filters( 'um_change_usermeta_for_update', $to_update, $args, $fields, $key );
}
}
}
$description_key = UM()->profile()->get_show_bio_key( $args );
if ( ! isset( $to_update[ $description_key ] ) && isset( $args['submitted'][ $description_key ] ) ) {
if ( ! empty( $form_data['use_custom_settings'] ) && ! empty( $form_data['show_bio'] ) ) {
$to_update[ $description_key ] = $args['submitted'][ $description_key ];
} else {
if ( UM()->options()->get( 'profile_show_bio' ) ) {
$to_update[ $description_key ] = $args['submitted'][ $description_key ];
}
}
}
// Secure selected role.
// It's for a legacy case `array_key_exists( 'editable', $fields['role'] )` and similar.
if ( ( isset( $fields['role'] ) && ( ! array_key_exists( 'editable', $fields['role'] ) || ! empty( $fields['role']['editable'] ) ) && um_can_view_field( $fields['role'] ) ) ||
( isset( $fields['role_select'] ) && ( ! array_key_exists( 'editable', $fields['role_select'] ) || ! empty( $fields['role_select']['editable'] ) ) && um_can_view_field( $fields['role_select'] ) ) ||
( isset( $fields['role_radio'] ) && ( ! array_key_exists( 'editable', $fields['role_radio'] ) || ! empty( $fields['role_radio']['editable'] ) ) && um_can_view_field( $fields['role_radio'] ) ) ) {
if ( ! empty( $args['submitted']['role'] ) ) {
global $wp_roles;
$exclude_roles = array_diff( array_keys( $wp_roles->roles ), UM()->roles()->get_editable_user_roles() );
if ( ! in_array( $args['submitted']['role'], $exclude_roles, true ) ) {
$to_update['role'] = $args['submitted']['role'];
}
$args['roles_before_upgrade'] = UM()->roles()->get_all_user_roles( $user_id );
}
}
/**
* UM hook
*
* @type action
* @title um_user_pre_updating_profile
* @description Some actions before profile submit
* @input_vars
* [{"var":"$userinfo","type":"array","desc":"Submitted User Data"},
* {"var":"$user_id","type":"int","desc":"User ID"}]
* @change_log
* ["Since: 2.0"]
* @usage add_action( 'um_user_pre_updating_profile', 'function_name', 10, 2 );
* @example
*
*/
do_action( 'um_user_pre_updating_profile', $to_update, $user_id, $form_data );
/**
* UM hook
*
* @type filter
* @title um_user_pre_updating_profile_array
* @description Change submitted data before update profile
* @input_vars
* [{"var":"$to_update","type":"array","desc":"Profile data upgrade"},
* {"var":"$user_id","type":"int","desc":"User ID"}]
* @change_log
* ["Since: 2.0"]
* @usage
*
* @example
*
*/
$to_update = apply_filters( 'um_user_pre_updating_profile_array', $to_update, $user_id, $form_data );
if ( is_array( $to_update ) ) {
if ( isset( $to_update['first_name'] ) || isset( $to_update['last_name'] ) || isset( $to_update['nickname'] ) ) {
$user = get_userdata( $user_id );
if ( ! empty( $user ) && ! is_wp_error( $user ) ) {
UM()->user()->previous_data['display_name'] = $user->display_name;
if ( isset( $to_update['first_name'] ) ) {
UM()->user()->previous_data['first_name'] = $user->first_name;
}
if ( isset( $to_update['last_name'] ) ) {
UM()->user()->previous_data['last_name'] = $user->last_name;
}
if ( isset( $to_update['nickname'] ) ) {
UM()->user()->previous_data['nickname'] = $user->nickname;
}
}
}
UM()->user()->update_profile( $to_update );
/**
* UM hook
*
* @type action
* @title um_after_user_updated
* @description Some actions after user profile updated
* @input_vars
* [{"var":"$user_id","type":"int","desc":"User ID"},
* {"var":"$args","type":"array","desc":"Form Data"},
* {"var":"$userinfo","type":"array","desc":"Submitted User Data"}]
* @change_log
* ["Since: 2.0"]
* @usage add_action( 'um_after_user_updated', 'function_name', 10, 33 );
* @example
*
*/
do_action( 'um_after_user_updated', $user_id, $args, $to_update );
}
/** This action is documented in ultimate-member/includes/core/um-actions-register.php */
$files = apply_filters( 'um_user_pre_updating_files_array', $files, $user_id );
if ( ! empty( $files ) && is_array( $files ) ) {
UM()->uploader()->replace_upload_dir = true;
UM()->uploader()->move_temporary_files( $user_id, $files );
UM()->uploader()->replace_upload_dir = false;
}
/** This action is documented in ultimate-member/includes/core/um-actions-register.php */
do_action( 'um_update_profile_full_name', $user_id, $to_update );
/**
* UM hook
*
* @type action
* @title um_user_after_updating_profile
* @description After upgrade user's profile
* @input_vars
* [{"var":"$submitted","type":"array","desc":"Form data"},
* {"var":"$user_id","type":"int","desc":"User Id"}]
* @change_log
* ["Since: 2.0"]
* @usage add_action( 'um_user_after_updating_profile', 'function_name', 10, 1 );
* @example
*
*/
do_action( 'um_user_after_updating_profile', $to_update, $user_id, $args );
// Finally redirect to profile.
$url = um_user_profile_url( $user_id );
$url = apply_filters( 'um_update_profile_redirect_after', $url, $user_id, $args );
// Not `um_safe_redirect()` because predefined user profile page is situated on the same host.
wp_safe_redirect( um_edit_my_profile_cancel_uri( $url ) );
exit;
}
add_action( 'um_user_edit_profile', 'um_user_edit_profile', 10, 2 );
/**
* Validate nonce when profile form submit.
*
* @param array $submitted_data
*/
function um_profile_validate_nonce( $submitted_data ) {
$user_id = isset( $submitted_data['user_id'] ) ? $submitted_data['user_id'] : '';
$nonce = isset( $submitted_data['profile_nonce'] ) ? $submitted_data['profile_nonce'] : '';
if ( empty( $nonce ) || ! wp_verify_nonce( $nonce, 'um-profile-nonce' . $user_id ) ) {
wp_die( esc_html__( 'This is not possible for security reasons.', 'ultimate-member' ) );
}
}
add_action( 'um_submit_form_errors_hook__profile', 'um_profile_validate_nonce', 1 );
// @todo maybe remove that because double validate
add_filter( 'um_user_pre_updating_files_array', array( UM()->validation(), 'validate_files' ) );
// @todo maybe remove that because double validate
add_filter( 'um_before_save_filter_submitted', array( UM()->validation(), 'validate_fields_values' ), 10, 3 );
/**
* Leave roles for User, which are not in the list of update profile (are default WP or 3rd plugins roles)
*
* @param $user_id
* @param $args
* @param $to_update
*/
function um_restore_default_roles( $user_id, $args, $to_update ) {
if ( ! empty( $args['submitted']['role'] ) && ! empty( $to_update['role'] ) ) {
$wp_user = new WP_User( $user_id );
$leave_roles = array_diff( $args['roles_before_upgrade'], UM()->roles()->get_editable_user_roles() );
if ( UM()->roles()->is_role_custom( $to_update['role'] ) ) {
$wp_user->remove_role( $to_update['role'] );
$roles = array_merge( $leave_roles, array( $to_update['role'] ) );
} else {
$roles = array_merge( array( $to_update['role'] ), $leave_roles );
}
foreach ( $roles as $role_k ) {
$wp_user->add_role( $role_k );
}
}
}
add_action( 'um_after_user_updated', 'um_restore_default_roles', 10, 3 );
/**
* If editing another user
*
* @param $args
*/
function um_editing_user_id_input( $args ) {
if ( true === UM()->fields()->editing && 'profile' === UM()->fields()->set_mode && UM()->user()->target_id ) {
?>
Settings > Reading]
* "Profile Privacy" in [Account > Privacy]
* "Avoid indexing my profile by search engines in [Account > Privacy]
* "Avoid indexing profile by search engines" in [wp-admin > Ultimate Member > User Roles > Edit Role]
* "Avoid indexing profile by search engines" in [wp-admin > Ultimate Member > Settings > General > Users]
*/
if ( UM()->user()->is_profile_noindex( $user_id ) ) {
echo '';
return;
}
$locale = get_user_locale( $user_id );
$site_name = get_bloginfo( 'name' );
$twitter = (string) um_user( 'twitter' );
if ( ! empty( $twitter ) ) {
$twitter = trim( str_replace( 'https://twitter.com/', '', $twitter ), "/ \n\r\t\v\0" );
}
$title = trim( um_user( 'display_name' ) );
$description = um_convert_tags( UM()->options()->get( 'profile_desc' ) );
$url = um_user_profile_url( $user_id );
/**
* Filters the profile SEO image type. Default 'profile_photo'. Available 'cover_photo', 'profile_photo'.
*
* @param {string} $image_type Image type - cover_photo or profile_photo.
* @param {int} $user_id User ID.
*
* @return {string} Changed image type
*
* @since 2.5.5
* @hook um_profile_dynamic_meta_image_type
*
* @example
Change meta image to cover photo `cover_photo`.
* function my_um_profile_dynamic_meta_image_type( $image_type, $user_id ) {
* return 'cover_photo';
* }
* add_filter( 'um_profile_dynamic_meta_image_type', 'my_um_profile_dynamic_meta_image_type', 10, 2 );
*/
$image_type = apply_filters( 'um_profile_dynamic_meta_image_type', 'profile_photo', $user_id );
// The minimum size is 200 x 200 px, however, we recommend keeping it to 600 x 315 px.
// If your image is smaller than 600 x 315 pixels, it will appear as a small image in the link preview.
$default_image_size = 'cover_photo' === $image_type ? 600 : 200;
/**
* Filters the profile SEO image size. Default 190. Available 'original'.
*
* @param {string} $image_size Image size.
* @param {int} $user_id User ID.
*
* @return {array} Changed image type
*
* @since 2.5.5
* @hook um_profile_dynamic_meta_image_size
*
* @example