Files
ultimatemember/includes/core/class-permalinks.php
T
Mykyta Synelnikov bcfdbb954d Refactor email placeholders and deprecate obsolete methods
Streamline placeholder handling for emails by introducing universal patterns and replacements, and update email dispatch functions for efficiency. Deprecated various redundant user and password-related methods, consolidating logic into common utility classes for better maintainability.
2025-05-19 14:26:39 +03:00

524 lines
16 KiB
PHP

<?php
namespace um\core;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! class_exists( 'um\core\Permalinks' ) ) {
/**
* Class Permalinks
* @package um\core
*/
class Permalinks {
/**
* @var
*/
var $core;
/**
* @var
*/
var $current_url;
/**
* Permalinks constructor.
*/
public function __construct() {
add_action( 'init', array( &$this, 'set_current_url' ), 0 );
add_action( 'init', array( &$this, 'check_for_querystrings' ), 1 );
// don't use lower than 2 priority because there is sending email inside, but Action Scheduler is init on 1st priority.
add_action( 'init', array( &$this, 'activate_account_via_email_link' ), 2 );
}
/**
* Set current URL variable
*/
public function set_current_url() {
$this->current_url = $this->get_current_url();
}
/**
* Get query as array
*
* @return array
*/
public function get_query_array() {
$parts = parse_url( $this->get_current_url() );
if ( isset( $parts['query'] ) ) {
parse_str( $parts['query'], $query );
return $query;
}
return array();
}
/**
* Get current URL anywhere
*
* @param bool $no_query_params
*
* @return string
*/
public function get_current_url( $no_query_params = false ) {
//use WP native function for fill $_SERVER variables by correct values
wp_fix_server_vars();
//check if WP-CLI there isn't set HTTP_HOST, use localhost instead
if ( defined( 'WP_CLI' ) && WP_CLI ) {
$host = isset( $_SERVER['HTTP_HOST'] ) ? $_SERVER['HTTP_HOST'] : 'localhost';
} else {
if ( isset( $_SERVER['HTTP_HOST'] ) ) {
$host = $_SERVER['HTTP_HOST'];
} else {
$host = 'localhost';
}
}
$page_url = ( is_ssl() ? 'https://' : 'http://' ) . $host . $_SERVER['REQUEST_URI'];
if ( false !== $no_query_params ) {
$page_url = strtok( $page_url, '?' );
}
/**
* Filters current page URL.
*
* @param {string} $page_url Current page URL.
* @param {bool} $no_query_params Ignore $_GET attributes in URL. false !== ignore.
*
* @return {string} Current page URL.
*
* @since 1.3.x
* @hook um_get_current_page_url
*
* @example <caption>Add your custom $_GET attribute to all links.</caption>
* function my_um_get_current_page_url( $page_url, $no_query_params ) {
* $page_url = add_query_arg( '{attr_value}', '{attr_key}', $page_url ); // replace to your custom value and key.
* return $page_url;
* }
* add_filter( 'um_get_current_page_url', 'my_um_get_current_page_url', 10, 2 );
*/
return apply_filters( 'um_get_current_page_url', $page_url, $no_query_params );
}
/**
* Activates an account via email
*/
public function activate_account_via_email_link() {
if ( isset( $_REQUEST['act'] ) && 'activate_via_email' === sanitize_key( $_REQUEST['act'] ) && isset( $_REQUEST['hash'] ) && is_string( $_REQUEST['hash'] ) && strlen( $_REQUEST['hash'] ) == 40 &&
isset( $_REQUEST['user_id'] ) && is_numeric( $_REQUEST['user_id'] ) ) { // valid token
$user_id = absint( $_REQUEST['user_id'] );
if ( is_user_logged_in() && get_current_user_id() !== $user_id ) {
// Cannot activate another user account. Please log out and try again.
wp_safe_redirect( um_user_profile_url( get_current_user_id() ) );
exit;
}
delete_option( "um_cache_userdata_{$user_id}" );
$account_secret_hash = get_user_meta( $user_id, 'account_secret_hash', true );
if ( empty( $account_secret_hash ) || strtolower( sanitize_text_field( $_REQUEST['hash'] ) ) !== strtolower( $account_secret_hash ) ) {
wp_safe_redirect( add_query_arg( 'err', 'activation_link_used', um_get_core_page( 'login' ) ) );
exit;
}
$account_secret_hash_expiry = get_user_meta( $user_id, 'account_secret_hash_expiry', true );
if ( ! empty( $account_secret_hash_expiry ) && time() > $account_secret_hash_expiry ) {
wp_safe_redirect( add_query_arg( 'err', 'activation_link_expired', um_get_core_page( 'login' ) ) );
exit;
}
// Activate account link is valid. Can be approved below.
um_fetch_user( $user_id ); // @todo maybe don't need to fetch.
UM()->common()->users()->approve( $user_id, true );
$user_role = UM()->roles()->get_priority_user_role( $user_id );
$user_role_data = UM()->roles()->role_data( $user_role );
// Log in automatically after activation.
$login = ! empty( $user_role_data['login_email_activate'] ); // Role setting "Login user after validating the activation link?"
if ( $login && ! is_user_logged_in() ) {
UM()->user()->auto_login( $user_id );
}
/**
* Fires on user activation after visit link for email confirmation.
*
* @hook um_after_email_confirmation
*
* @param {int} $user_id The user ID.
*
* @since 2.0
*
* @example <caption>Doing some code after email confirmation and approved $user_id.</caption>
* function my_after_email_confirmation( $user_id ) {
* // your code here
* }
* add_filter( 'um_after_email_confirmation', 'my_after_email_confirmation' );
*/
do_action( 'um_after_email_confirmation', $user_id );
// Prepare redirect link.
$set_password_required = get_user_meta( $user_id, 'um_set_password_required', true );
if ( empty( $set_password_required ) ) {
// Role setting "URL redirect after email activation".
$redirect = empty( $user_role_data['url_email_activate'] ) ? um_get_core_page( 'login', 'account_active' ) : trim( $user_role_data['url_email_activate'] );
} else {
// Redirect to the change password page if there is no password for this user.
$redirect = UM()->password()->reset_url( $user_id );
}
/**
* Filter to change the redirect URL after email confirmation.
*
* @hook um_after_email_confirmation_redirect
*
* @param {string} $redirect The redirect URL.
* @param {int} $user_id The user ID.
* @param {bool} $login Auto login has been applied and user currently is logged in.
*
* @since 2.0
*
* @example <caption>Change redirect after confirmation only for the user with ID=99.</caption>
* function my_after_email_confirmation_redirect( $redirect, $user_id, $login ) {
* // your code here
* if ( $user_id === 99 ) {
* $redirect = 'custom_url';
* }
* return $redirect;
* }
* add_filter( 'um_after_email_confirmation_redirect', 'my_after_email_confirmation_redirect', 10, 3 );
*/
$redirect = apply_filters( 'um_after_email_confirmation_redirect', $redirect, $user_id, $login );
um_safe_redirect( $redirect );
}
}
/**
* Makes an activate link for any user
*
* @return string
*/
public function activate_url( $user_id = null ) {
if ( is_null( $user_id ) ) {
$user_id = um_user( 'ID' );
}
$account_secret_hash = get_user_meta( $user_id, 'account_secret_hash', true );
if ( empty( $account_secret_hash ) ) {
return '';
}
/**
* Filter to change the base URL for the user activation link.
*
* @hook um_activate_url
*
* @param {string} $url The base URL. `home_url()` by default
*
* @since 1.3.x
*
* @example <caption>Change activate user base URL.</caption>
* function my_after_email_confirmation_redirect( $url ) {
* // your code here
* return $url;
* }
* add_filter( 'um_activate_url', 'my_um_activate_url' );
*/
$base_url = apply_filters( 'um_activate_url', home_url() );
return add_query_arg(
array(
'act' => 'activate_via_email',
'hash' => $account_secret_hash,
'user_id' => $user_id,
),
$base_url
);
}
/**
* Checks for UM query strings
*/
public function check_for_querystrings() {
if ( isset( $_REQUEST['message'] ) ) {
UM()->shortcodes()->message_mode = true;
}
}
/**
* Add a query param to url
*
* @param $key
* @param $value
*
* @return string
*/
public function add_query( $key, $value ) {
$this->current_url = add_query_arg( $key, $value, $this->get_current_url() );
return $this->current_url;
}
/**
* Remove a query param from url
*
* @param $key
* @param $value
*
* @return string
*/
public function remove_query( $key, $value ) {
$this->current_url = remove_query_arg( $key, $this->current_url );
return $this->current_url;
}
/**
* @param string $slug
*
* @return int|bool
*/
public function slug_exists_user_id( $slug ) {
global $wpdb;
$permalink_base = UM()->options()->get( 'permalink_base' );
if ( 'custom_meta' === $permalink_base ) {
$custom_meta = UM()->options()->get( 'permalink_base_custom_meta' );
if ( empty( $custom_meta ) ) {
// Set default permalink base if custom meta is empty.
$permalink_base = 'user_login';
$meta_key = 'um_user_profile_url_slug_' . $permalink_base;
} else {
$meta_key = $custom_meta;
}
} else {
$meta_key = 'um_user_profile_url_slug_' . $permalink_base;
}
$user_id = $wpdb->get_var(
$wpdb->prepare(
"SELECT user_id
FROM {$wpdb->usermeta}
WHERE meta_key = %s AND
meta_value = %s
ORDER BY umeta_id ASC
LIMIT 1",
$meta_key,
$slug
)
);
if ( ! empty( $user_id ) ) {
return absint( $user_id );
}
return false;
}
/**
* Get Profile Permalink
*
* @param string $slug
*
* @return string
*/
public function profile_permalink( $slug ) {
/**
* Filters user profile URL externally with own logic.
*
* @since 2.6.3
* @hook um_external_profile_url
*
* @param {bool|string} $profile_url Profile URL.
* @param {string} $slug User profile slug.
*
* @return {string} Profile URL.
*
* @example <caption>Change profile URL to your custom link and ignore native profile permalink handlers.</caption>
* function my_um_external_profile_url( $profile_url, $slug ) {
* $profile_url = '{some your custom URL}'; // replace to your custom link.
* return $profile_url;
* }
* add_filter( 'um_external_profile_url', 'my_um_external_profile_url', 10, 2 );
*/
$external_profile_url = apply_filters( 'um_external_profile_url', false, $slug );
if ( false !== $external_profile_url ) {
return ! empty( $external_profile_url ) ? $external_profile_url : '';
}
$page_id = UM()->config()->permalinks['user'];
$profile_url = get_permalink( $page_id );
/**
* Filters the base URL of the UM profile page.
*
* @since 1.3.x
* @deprecated 2.6.3 Use <a href="https://developer.wordpress.org/reference/hooks/post_link/" target="_blank" title="'post_link' hook article on developer.wordpress.org">'post_link'</a> instead.
* @hook um_localize_permalink_filter
* @todo fully remove since 2.7.0
*
* @param {string} $profile_url Profile URL.
* @param {int} $page_id Profile Page ID.
*
* @return {string} Profile URL.
*
* @example <caption>Change profile base URL to your custom link.</caption>
* function my_localize_permalink( $profile_url, $page_id ) {
* $profile_url = '{some your custom URL}'; // replace to your custom link.
* return $profile_url;
* }
* add_filter( 'um_localize_permalink_filter', 'my_localize_permalink', 10, 2 );
*/
$profile_url = apply_filters( 'um_localize_permalink_filter', $profile_url, $page_id );
if ( UM()->is_permalinks ) {
$profile_url = trailingslashit( untrailingslashit( $profile_url ) );
$profile_url .= trailingslashit( strtolower( $slug ) );
} else {
$profile_url = add_query_arg( 'um_user', strtolower( $slug ), $profile_url );
}
/**
* Filters user profile URL.
*
* @since 2.6.3
* @hook um_profile_permalink
*
* @param {string} $profile_url Profile URL.
* @param {int} $page_id Profile Page ID.
* @param {string} $slug User profile slug.
*
* @return {string} Profile URL.
*
* @example <caption>Change profile URL to your custom link.</caption>
* function my_um_profile_permalink( $profile_url, $page_id, $slug ) {
* $profile_url = '{some your custom URL}'; // replace to your custom link.
* return $profile_url;
* }
* add_filter( 'um_profile_permalink', 'my_um_profile_permalink', 10, 3 );
*/
$profile_url = apply_filters( 'um_profile_permalink', $profile_url, $page_id, $slug );
return ! empty( $profile_url ) ? $profile_url : '';
}
/**
* Generate profile slug
*
* @param string $full_name
* @param string $first_name
* @param string $last_name
* @return string
*/
public function profile_slug( $full_name, $first_name, $last_name ) {
$permalink_base = UM()->options()->get( 'permalink_base' );
$user_in_url = '';
$full_name = str_replace( array( "'", '&', '/' ), '', $full_name );
switch ( $permalink_base ) {
case 'name': // dotted
$full_name_slug = $full_name;
$difficulties = 0;
if ( strpos( $full_name, '.' ) > -1 ) {
$full_name = str_replace( ".", "_", $full_name );
$difficulties++;
}
$full_name = strtolower( str_replace( " ", ".", $full_name ) );
if ( strpos( $full_name, '_.' ) > -1 ) {
$full_name = str_replace( '_.', '_', $full_name );
$difficulties++;
}
$full_name_slug = str_replace( '-', '.', $full_name_slug );
$full_name_slug = str_replace( ' ', '.', $full_name_slug );
$full_name_slug = str_replace( '..', '.', $full_name_slug );
if ( strpos( $full_name, '.' ) > -1 ) {
$full_name = str_replace( '.', ' ', $full_name );
$difficulties++;
}
$user_in_url = rawurlencode( $full_name_slug );
break;
case 'name_dash': // dashed
$difficulties = 0;
$full_name_slug = strtolower( $full_name );
// if last name has dashed replace with underscore
if ( strpos( $last_name, '-' ) > -1 && strpos( $full_name, '-' ) > -1 ) {
$difficulties++;
$full_name = str_replace( '-', '_', $full_name );
}
// if first name has dashed replace with underscore
if ( strpos( $first_name, '-' ) > -1 && strpos( $full_name, '-' ) > -1 ) {
$difficulties++;
$full_name = str_replace( '-', '_', $full_name );
}
// if name has space, replace with dash
$full_name_slug = str_replace( ' ', '-', $full_name_slug );
// if name has period
if ( strpos( $last_name, '.' ) > -1 && strpos( $full_name, '.' ) > -1 ) {
$difficulties++;
}
$full_name_slug = str_replace( '.', '-', $full_name_slug );
$full_name_slug = str_replace( '--', '-', $full_name_slug );
$user_in_url = rawurlencode( $full_name_slug );
break;
case 'name_plus': // plus
$difficulties = 0;
$full_name_slug = strtolower( $full_name );
// if last name has dashed replace with underscore
if ( strpos( $last_name, '+' ) > -1 && strpos( $full_name, '+' ) > -1 ) {
$difficulties++;
$full_name = str_replace( '-', '_', $full_name );
}
// if first name has dashed replace with underscore
if ( strpos( $first_name, '+' ) > -1 && strpos( $full_name, '+' ) > -1 ) {
$difficulties++;
$full_name = str_replace( '-', '_', $full_name );
}
if ( strpos( $last_name, '-' ) > -1 || strpos( $first_name, '-' ) > -1 || strpos( $full_name, '-' ) > -1 ) {
$difficulties++;
}
// if name has space, replace with dash
$full_name_slug = str_replace( ' ', '+', $full_name_slug );
$full_name_slug = str_replace( '-', '+', $full_name_slug );
// if name has period
if ( strpos( $last_name, '.' ) > -1 && strpos( $full_name, '.' ) > -1 ) {
$difficulties++;
}
$full_name_slug = str_replace( '.', '+', $full_name_slug );
$full_name_slug = str_replace( '++', '+', $full_name_slug );
$user_in_url = $full_name_slug;
break;
}
return $user_in_url;
}
}
}