response[$plugin_file])) { unset($value->response[$plugin_file]); } return $value; }); /** * Main Plugin Class */ class Plugin_Name_Login_URL_Changer { /** * Option name for storing custom login URL */ const OPTION_NAME = 'plugin_name_custom_login_url'; /** * Default login slug */ const DEFAULT_SLUG = 'wp-login.php'; /** * Instance of this class */ private static $instance = null; /** * Get instance of this class */ public static function get_instance() { if (null === self::$instance) { self::$instance = new self(); } return self::$instance; } /** * Constructor */ private function __construct() { $this->init(); } /** * Initialize plugin */ private function init() { // Admin hooks add_action('admin_menu', array($this, 'add_admin_menu')); add_action('admin_init', array($this, 'register_settings')); add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets')); add_action('admin_notices', array($this, 'display_admin_notices')); // Frontend hooks - URL rewriting and blocking add_action('init', array($this, 'handle_custom_login_url'), 1); add_action('login_init', array($this, 'block_default_login'), 1); add_filter('site_url', array($this, 'filter_login_url'), 10, 4); add_filter('network_site_url', array($this, 'filter_login_url'), 10, 3); add_filter('wp_redirect', array($this, 'filter_wp_redirect'), 10, 2); add_filter('lostpassword_url', array($this, 'filter_lostpassword_url'), 10, 2); add_filter('register_url', array($this, 'filter_register_url'), 10, 2); // Rewrite rules add_action('init', array($this, 'add_rewrite_rules'), 2); add_filter('query_vars', array($this, 'add_query_vars')); } /** * Get custom login slug */ public function get_custom_slug() { $slug = get_option(self::OPTION_NAME, ''); return sanitize_text_field($slug); } /** * Check if custom URL is enabled */ public function is_custom_url_enabled() { $slug = $this->get_custom_slug(); return !empty($slug) && $slug !== self::DEFAULT_SLUG; } /** * Get full custom login URL */ public function get_custom_login_url() { if (!$this->is_custom_url_enabled()) { return wp_login_url(); } $slug = $this->get_custom_slug(); return home_url('/' . $slug); } /** * Add admin menu page */ public function add_admin_menu() { add_options_page( __('Login URL Settings', 'plugin-name'), __('Login URL', 'plugin-name'), 'manage_options', 'plugin-name-login-url', array($this, 'render_settings_page') ); } /** * Register settings */ public function register_settings() { register_setting( 'plugin_name_login_url_settings', self::OPTION_NAME, array( 'type' => 'string', 'sanitize_callback' => array($this, 'sanitize_login_slug'), 'default' => '' ) ); } /** * Sanitize login slug */ public function sanitize_login_slug($slug) { // Check nonce if (!isset($_POST['plugin_name_login_url_nonce']) || !wp_verify_nonce($_POST['plugin_name_login_url_nonce'], 'plugin_name_save_login_url')) { add_settings_error( 'plugin_name_login_url', 'invalid_nonce', __('Security check failed. Please try again.', 'plugin-name'), 'error' ); return get_option(self::OPTION_NAME, ''); } // Check capabilities if (!current_user_can('manage_options')) { add_settings_error( 'plugin_name_login_url', 'insufficient_permissions', __('You do not have permission to change this setting.', 'plugin-name'), 'error' ); return get_option(self::OPTION_NAME, ''); } $slug = sanitize_text_field($slug); $slug = trim($slug, '/'); // If empty or default, clear the custom URL if (empty($slug) || $slug === 'wp-login.php' || $slug === 'wp-login') { add_settings_error( 'plugin_name_login_url', 'settings_updated', __('Login URL has been reset to default.', 'plugin-name'), 'success' ); return ''; } // Validate slug format if (!preg_match('/^[a-z0-9-]+$/', $slug)) { add_settings_error( 'plugin_name_login_url', 'invalid_slug', __('The login URL can only contain lowercase letters, numbers, and hyphens.', 'plugin-name'), 'error' ); return get_option(self::OPTION_NAME, ''); } // Check for reserved slugs $reserved_slugs = array( 'wp-admin', 'wp-content', 'wp-includes', 'admin', 'login', 'logout', 'register', 'wp-json', 'feed', 'comments', 'trackback', 'xmlrpc', 'wp-login', 'wp-signup', 'wp-activate' ); if (in_array($slug, $reserved_slugs, true)) { add_settings_error( 'plugin_name_login_url', 'reserved_slug', __('This URL is reserved and cannot be used.', 'plugin-name'), 'error' ); return get_option(self::OPTION_NAME, ''); } // Check for conflicts with existing pages/posts $existing = get_page_by_path($slug, OBJECT, array('page', 'post')); if ($existing) { add_settings_error( 'plugin_name_login_url', 'slug_conflict', __('This URL conflicts with an existing page or post.', 'plugin-name'), 'error' ); return get_option(self::OPTION_NAME, ''); } // Success message add_settings_error( 'plugin_name_login_url', 'settings_updated', sprintf( __('Login URL has been changed to: %s', 'plugin-name'), '' . esc_url(home_url('/' . $slug)) . '' ), 'success' ); return $slug; } /** * Render settings page */ public function render_settings_page() { if (!current_user_can('manage_options')) { return; } $current_slug = $this->get_custom_slug(); $custom_url = $this->get_custom_login_url(); $is_custom = $this->is_custom_url_enabled(); ?>


id !== 'settings_page_plugin-name-login-url') { return; } // Only show on the settings page if settings_errors hasn't already shown } /** * Add rewrite rules for custom login URL */ public function add_rewrite_rules() { $slug = $this->get_custom_slug(); if (empty($slug)) { return; } add_rewrite_rule( '^' . $slug . '/?$', 'index.php?plugin_name_login=1', 'top' ); add_rewrite_rule( '^' . $slug . '/([^/]+)/?$', 'index.php?plugin_name_login=1&action=$matches[1]', 'top' ); } /** * Add custom query vars */ public function add_query_vars($vars) { $vars[] = 'plugin_name_login'; return $vars; } /** * Handle custom login URL */ public function handle_custom_login_url() { // Check query var (for when rewrite rules work) $has_query_var = get_query_var('plugin_name_login'); // Fallback: check REQUEST_URI directly (for when rewrite rules don't work) $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field($_SERVER['REQUEST_URI']) : ''; $custom_slug = $this->get_custom_slug(); // Remove query string for comparison $request_path = strtok($request_uri, '?'); $request_path = trim($request_path, '/'); // Check if we're accessing the custom slug directly $is_custom_url = !empty($custom_slug) && ($request_path === $custom_slug || preg_match('#^' . preg_quote($custom_slug, '#') . '(/.*)?$#', $request_path)); if (!$has_query_var && !$is_custom_url) { return; } // Set the query var for compatibility if ($is_custom_url && !$has_query_var) { set_query_var('plugin_name_login', 1); // Extract action from URL if present $action = 'login'; if (preg_match('#^' . preg_quote($custom_slug, '#') . '/([^/]+)#', $request_path, $matches)) { $action = $matches[1]; } set_query_var('action', $action); } // Prevent caching nocache_headers(); $action = get_query_var('action') ? get_query_var('action') : 'login'; // Set up login globals that wp-login.php expects global $error, $interim_login, $action; // Parse any login errors from query string $error = ''; if (!empty($_GET['login'])) { $login = sanitize_text_field($_GET['login']); switch ($login) { case 'failed': $error = __('Error: Invalid username or password.', 'plugin-name'); break; case 'empty': $error = __('Error: Username and password are required.', 'plugin-name'); break; case 'loggedout': $error = __('You are now logged out.', 'plugin-name'); break; case 'expired': $error = __('Your session has expired. Please log in again.', 'plugin-name'); break; } } // Re-login for interim login $interim_login = isset($_REQUEST['interim-login']); // Handle POST requests (form submissions) if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['log'])) { $this->handle_login_post(); return; } // Display the login form $this->render_login_form($action, $error); exit; } /** * Handle login form POST submission */ private function handle_login_post() { $user_login = isset($_POST['log']) ? sanitize_user($_POST['log']) : ''; $user_pass = isset($_POST['pwd']) ? $_POST['pwd'] : ''; $remember = isset($_POST['rememberme']) ? true : false; $credentials = array( 'user_login' => $user_login, 'user_password' => $user_pass, 'remember' => $remember ); $user = wp_signon($credentials, is_ssl()); if (is_wp_error($user)) { // Redirect back to custom login with error $redirect_to = $this->get_custom_login_url(); wp_redirect(add_query_arg('login', 'failed', $redirect_to)); exit; } // Successful login - redirect to admin or requested location $redirect_to = isset($_POST['redirect_to']) ? esc_url_raw($_POST['redirect_to']) : admin_url(); wp_redirect($redirect_to); exit; } /** * Render the login form */ private function render_login_form($action, $error) { $custom_slug = $this->get_custom_slug(); $login_url = $this->get_custom_login_url(); $redirect_to = isset($_REQUEST['redirect_to']) ? esc_url_raw($_REQUEST['redirect_to']) : admin_url(); // Output login form ?> > <?php bloginfo('name'); ?> › Log In

← Back to

is_custom_url_enabled()) { return; } // Allow access for certain actions that need wp-login.php $allowed_actions = array('logout', 'postpass', 'rp', 'resetpass'); $action = isset($_REQUEST['action']) ? sanitize_text_field($_REQUEST['action']) : 'login'; if (in_array($action, $allowed_actions, true)) { return; } // Check if this is the real wp-login.php file (not our custom URL) $request_uri = isset($_SERVER['REQUEST_URI']) ? sanitize_text_field($_SERVER['REQUEST_URI']) : ''; $custom_slug = $this->get_custom_slug(); if (strpos($request_uri, 'wp-login.php') !== false && strpos($request_uri, $custom_slug) === false) { // Return 404 or redirect to custom URL wp_redirect(home_url('/404'), 404); exit; } } /** * Filter login URL */ public function filter_login_url($url, $path, $scheme = null, $blog_id = null) { if (!$this->is_custom_url_enabled()) { return $url; } // Only filter wp-login.php URLs if (strpos($url, 'wp-login.php') === false) { return $url; } $custom_slug = $this->get_custom_slug(); $custom_url = str_replace('wp-login.php', $custom_slug, $url); return $custom_url; } /** * Filter wp_redirect */ public function filter_wp_redirect($location, $status) { if (!$this->is_custom_url_enabled()) { return $location; } // Replace wp-login.php with custom slug in redirects if (strpos($location, 'wp-login.php') !== false) { $custom_slug = $this->get_custom_slug(); $location = str_replace('wp-login.php', $custom_slug, $location); } return $location; } /** * Filter lostpassword URL */ public function filter_lostpassword_url($url, $redirect) { if (!$this->is_custom_url_enabled()) { return $url; } $custom_slug = $this->get_custom_slug(); return str_replace('wp-login.php', $custom_slug, $url); } /** * Filter register URL */ public function filter_register_url($url) { if (!$this->is_custom_url_enabled()) { return $url; } $custom_slug = $this->get_custom_slug(); return str_replace('wp-login.php', $custom_slug, $url); } } // Initialize plugin add_action('plugins_loaded', array('Plugin_Name_Login_URL_Changer', 'get_instance')); // Activation hook - must be outside class register_activation_hook(__FILE__, 'plugin_name_activate'); function plugin_name_activate() { // Make sure rewrite rules are regenerated global $wp_rewrite; if ($wp_rewrite) { $wp_rewrite->flush_rules(true); } else { flush_rewrite_rules(true); } } // Deactivation hook - must be outside class register_deactivation_hook(__FILE__, 'plugin_name_deactivate'); function plugin_name_deactivate() { // Flush rewrite rules to remove custom rules flush_rewrite_rules(); } // Flush rewrite rules after option is updated add_action('update_option_plugin_name_custom_login_url', 'plugin_name_flush_after_update', 10, 2); function plugin_name_flush_after_update($old_value, $new_value) { // Only flush if value actually changed if ($old_value !== $new_value) { // Use a transient to delay the flush until after the page loads set_transient('plugin_name_needs_flush', true, 60); } } // Perform the actual flush on the next admin load add_action('admin_init', 'plugin_name_perform_flush'); function plugin_name_perform_flush() { if (get_transient('plugin_name_needs_flush')) { delete_transient('plugin_name_needs_flush'); flush_rewrite_rules(true); } }