'support-access', 'menu_label' => __( 'Support Access', $this->textdomain ), 'parent_slug' => 'users.php', 'textdomain' => 'support-access', 'defaults' => array(), ) ); $this->menu_slug = $args['menu_slug']; $this->menu_label = $args['menu_label']; $this->parent_slug = $args['parent_slug']; $this->textdomain = $args['textdomain']; // Set default settings with fallbacks $this->default_settings = wp_parse_args( $args['defaults'], array( 'duration' => 1, 'duration_unit' => 'weeks', 'usage_limit' => '', 'role' => 'administrator', 'locale' => '', ) ); // Schedule cron job on plugin activation. register_activation_hook( __FILE__, array( $this, 'schedule_access_expiration_check' ) ); // Clear the scheduled cron job on plugin deactivation. register_deactivation_hook( __FILE__, array( $this, 'clear_access_expiration_check' ) ); // Schedule the cron event to check for expired admins. add_action( 'check_access_expiration_event', array( $this, 'check_access_expiration' ) ); // Handle temp admin login by checking the URL parameters. add_action( 'init', array( $this, 'check_access_login' ) ); // Add admin menu page. add_action( 'admin_menu', array( $this, 'add_support_access_menu' ) ); // Handle form submission to create temp admin users. add_action( 'admin_post_create_access_user', array( $this, 'handle_access_form_submission' ) ); // Handle deletion of temporary admins. add_action( 'admin_post_delete_access_user', array( $this, 'handle_access_deletion' ) ); // Handle generating new access URLs. add_action( 'admin_init', array( $this, 'handle_url_generation' ) ); } /** * Prevent cloning of the instance */ protected function __clone() {} /** * Prevent unserializing of the instance */ public function __wakeup() { throw new \Exception( 'Cannot unserialize singleton' ); } /** * Schedule the cron job when the plugin is activated. */ public function schedule_access_expiration_check() { if ( ! wp_next_scheduled( 'check_access_expiration_event' ) ) { wp_schedule_event( time(), 'hourly', 'check_access_expiration_event' ); } } /** * Clear the scheduled cron job on plugin deactivation. */ public function clear_access_expiration_check() { $timestamp = wp_next_scheduled( 'check_access_expiration_event' ); if ( $timestamp ) { wp_unschedule_event( $timestamp, 'check_access_expiration_event' ); } } /** * Check for expired admins. */ public function check_access_expiration() { $args = array( 'meta_key' => 'support_access_token', 'meta_query' => array( 'relation' => 'AND', array( 'key' => 'support_access_expiration', 'compare' => 'EXISTS', ), ), ); $user_query = new WP_User_Query( $args ); if ( ! empty( $user_query->results ) ) { foreach ( $user_query->results as $user ) { $expiration_time = get_user_meta( $user->ID, 'support_access_expiration', true ); if ( $expiration_time && time() > $expiration_time ) { wp_delete_user( $user->ID ); } } } } /** * Add a menu item to the specified parent menu (default: Users). */ public function add_support_access_menu() { add_submenu_page( $this->parent_slug, // Parent menu slug. $this->menu_label, // Page title. $this->menu_label, // Menu title. 'manage_options', // Capability. $this->menu_slug, // Menu slug. array( $this, 'support_access_page' ) // Callback function for the page content. ); } /** * Admin page content for Support Access. */ public function support_access_page() { ?>

textdomain ); ?>

$user_id . '|' . $token, ), home_url() ); } ?>

%s

%s

%s

', esc_html__( 'Support user access created successfully', $this->textdomain ), $access_url ? sprintf( '

%s: %s

', esc_html__( 'Access URL', $this->textdomain ), esc_url( $access_url ), esc_js( $access_url ), esc_html__( 'Copy URL', $this->textdomain ) ) : '', esc_html__( 'Important: Copy this URL now. For security reasons it cannot be displayed again.', $this->textdomain ) ); } ?>

textdomain ); ?>

textdomain ); ?>

textdomain ); ?>

sprintf( /* translators: %s: Current site language name */ __( 'Site Default - %s', $this->textdomain ), $translations[ get_locale() ]['native_name'] ?? 'English (United States)' ), ); // Add installed languages $installed_languages = get_available_languages(); foreach ( $installed_languages as $locale ) { if ( isset( $translations[ $locale ] ) ) { $languages[ $locale ] = $translations[ $locale ]['native_name']; } } // Always include English (US) if not already added if ( ! isset( $languages['en_US'] ) ) { $languages['en_US'] = 'English (United States)'; } $current_locale = get_locale(); ?>

textdomain ); ?>

textdomain ) ); ?>
list_access_users(); ?> create_access_user( $role ); // Store user metadata. update_user_meta( $result['user_id'], 'support_access_login_count', 0 ); update_user_meta( $result['user_id'], 'support_access_expiration', $expiration_time ); update_user_meta( $result['user_id'], 'support_access_limit', $limit ); if ( ! empty( $locale ) ) { update_user_meta( $result['user_id'], 'locale', $locale ); } // Redirect with success message and access token. wp_redirect( add_query_arg( array( 'page' => 'support-access', 'message' => 'success', 'user_id' => $result['user_id'], 'token' => $result['access_token'], ), admin_url( 'users.php' ) ) ); exit; } /** * Create a temporary admin user. * * @param string $role The role to assign to the user. * @return array Array containing user ID and access token. */ private function create_access_user( $role = 'administrator' ) { $username = 'support_user_' . uniqid(); $password = wp_generate_password(); $email = $username . '@example.com'; $user_id = wp_create_user( $username, $password, $email ); $user = new WP_User( $user_id ); $user->set_role( $role ); // Generate random token and store its hash for verification $access_token = wp_generate_password( 32, false ); $token_hash = hash( 'sha256', $access_token ); update_user_meta( $user_id, 'support_access_token_hash', $token_hash ); return array( 'user_id' => $user_id, 'access_token' => $access_token, ); } /** * Check if the access token is valid and log in the user. */ public function check_access_login() { if ( ! isset( $_GET['support_access'] ) ) { return; } $parts = explode( '|', sanitize_text_field( wp_unslash( $_GET['support_access'] ) ) ); if ( count( $parts ) !== 2 ) { wp_safe_redirect( home_url() ); exit; } list( $user_id, $received_token ) = $parts; $user_id = absint( $user_id ); // Get stored hash. $stored_hash = get_user_meta( $user_id, 'support_access_token_hash', true ); if ( empty( $stored_hash ) ) { wp_safe_redirect( home_url() ); exit; } // Verify token. if ( ! hash_equals( $stored_hash, hash( 'sha256', $received_token ) ) ) { wp_safe_redirect( home_url() ); exit; } // Check expiration and limits. $expiration = get_user_meta( $user_id, 'support_access_expiration', true ); $limit = get_user_meta( $user_id, 'support_access_limit', true ); $login_count = get_user_meta( $user_id, 'support_access_login_count', true ); if ( time() > $expiration ) { wp_delete_user( $user_id ); wp_safe_redirect( home_url() ); exit; } if ( $limit > 0 && $login_count >= $limit ) { wp_safe_redirect( home_url() ); exit; } // Log the user in. wp_set_current_user( $user_id ); wp_set_auth_cookie( $user_id ); update_user_meta( $user_id, 'support_access_login_count', intval( $login_count ) + 1 ); wp_safe_redirect( admin_url() ); exit; } /** * List temporary admins with login count, expiration date, and delete option. */ private function list_access_users() { $args = array( 'meta_query' => array( 'relation' => 'AND', array( 'key' => 'support_access_token_hash', 'compare' => 'EXISTS', ), array( 'key' => 'support_access_expiration', 'compare' => 'EXISTS', ), ), ); $user_query = new WP_User_Query( $args ); if ( ! empty( $user_query->results ) ) { echo '

' . esc_html__( 'Temporary Users', $this->textdomain ) . '

'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; foreach ( $user_query->results as $user ) { $login_count = get_user_meta( $user->ID, 'support_access_login_count', true ); $user_profile_url = get_edit_user_link( $user->ID ); $expiration_time = get_user_meta( $user->ID, 'support_access_expiration', true ); $expiration_date = $expiration_time ? wp_date( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $expiration_time ) : ''; $limit = get_user_meta( $user->ID, 'support_access_limit', true ); $login_info = ( empty( $limit ) || '0' === $limit ) ? $login_count . ' / ∞' : $login_count . ' / ' . $limit; // Get user's role $user_roles = array_map( function( $role ) { return translate_user_role( wp_roles()->get_names()[ $role ] ); }, $user->roles ); ?> '; echo '
' . esc_html__( 'Username', $this->textdomain ) . '' . esc_html__( 'Role', $this->textdomain ) . '' . esc_html__( 'Login Count', $this->textdomain ) . '' . esc_html__( 'Expiration Date', $this->textdomain ) . '' . esc_html__( 'Access URL', $this->textdomain ) . '' . esc_html__( 'Actions', $this->textdomain ) . '
user_login ); ?> textdomain ); ?>
ID ); ?>
'; } } /** * Handle temporary admin deletion. */ public function handle_access_deletion() { if ( isset( $_POST['delete_access_user_id'] ) && current_user_can( 'manage_options' ) ) { $user_id = absint( $_POST['delete_access_user_id'] ); if ( wp_verify_nonce( $_POST['_wpnonce'], 'delete_access_user_' . $user_id ) ) { wp_delete_user( $user_id ); // Store deletion message in transient. set_transient( 'support_access_message_' . get_current_user_id(), array( 'type' => 'success', 'message' => __( 'Support access user deleted successfully.', $this->textdomain ), ), 30 ); wp_redirect( admin_url( 'users.php?page=support-access' ) ); exit; } } } /** * Handle generating new access URL. */ public function handle_url_generation() { if ( ! isset( $_GET['action'], $_GET['user_id'] ) || 'generate_access_url' !== $_GET['action'] ) { return; } if ( ! current_user_can( 'manage_options' ) ) { return; } $user_id = absint( $_GET['user_id'] ); if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'generate_access_url_' . $user_id ) ) { wp_die( 'Invalid nonce' ); } // Generate new token and hash $access_token = wp_generate_password( 32, false ); $token_hash = hash( 'sha256', $access_token ); update_user_meta( $user_id, 'support_access_token_hash', $token_hash ); // Redirect with success message and access token wp_redirect( add_query_arg( array( 'page' => 'support-access', 'message' => 'success', 'user_id' => $user_id, 'token' => $access_token, ), admin_url( 'users.php' ) ) ); exit; } } }