settings = SettingsManager::get_instance(); $this->init_hooks(); } private function get_setting($key, $default = '') { return $this->settings->get('custom_login_url', $key, $default); } private function init_hooks() { // Only run if module is enabled if ($this->get_setting('enable_custom_login')) { // Check for slug match on init (PRIORITY 1) add_action('init', [$this, 'handle_custom_login_slug'], 1); // Rewrite URLs add_filter('site_url', [$this, 'rewrite_login_url'], 10, 4); add_filter('network_site_url', [$this, 'rewrite_login_url'], 10, 3); add_filter('wp_redirect', [$this, 'filter_wp_redirect'], 10, 2); // Block default wp-login.php and wp-admin redirection handling add_action('init', [$this, 'handle_prevent_default_access'], 10); } } public function handle_custom_login_slug() { $slug = $this->get_setting('custom_slug', 'login'); if (empty($slug)) return; // Check if current request matches the slug // We check REQUEST_URI safely. $request_uri = ''; if (isset($_SERVER['REQUEST_URI'])) { $request_uri = filter_var(wp_unslash($_SERVER['REQUEST_URI']), FILTER_SANITIZE_URL); } $path = wp_parse_url($request_uri, PHP_URL_PATH); // Remove trailing slash for comparison, but handle root vs subfolder $path = untrailingslashit($path); // Get site path to support subfolder installs $site_path = wp_parse_url(home_url(), PHP_URL_PATH); if ($site_path && $site_path !== '/') { $path = str_replace(untrailingslashit($site_path), '', $path); } $path = ltrim($path, '/'); if ($path === $slug) { // Allow this request to be processed as login // Using a constant to signal we are in custom login if (!defined('CDVAO_CUSTOM_LOGIN')) { define('CDVAO_CUSTOM_LOGIN', true); } // Load wp-login.php // We need to globalize some variables that wp-login.php expects global $error, $interim_login, $action, $user_login; require_once ABSPATH . 'wp-login.php'; die(); } } public function handle_prevent_default_access() { // If we serve the custom page, we are fine. if (defined('CDVAO_CUSTOM_LOGIN')) return; $request_uri = ''; if (isset($_SERVER['REQUEST_URI'])) { $request_uri = filter_var(wp_unslash($_SERVER['REQUEST_URI']), FILTER_SANITIZE_URL); } $path = wp_parse_url($request_uri, PHP_URL_PATH); $is_login_php = (strpos($path, 'wp-login.php') !== false); $is_admin_path = (strpos($path, 'wp-admin') !== false); // Allow admin-ajax and other exceptions if ($is_admin_path) { if (strpos($path, 'admin-ajax.php') !== false || strpos($path, 'async-upload.php') !== false) { return; } } // Condition: Trying to access wp-login.php directly (while not in admin context properly) // OR Trying to access wp-admin while NOT logged in (which triggers auth_redirect) $should_block = false; if ($is_login_php && !is_admin()) { $should_block = true; } if ($is_admin_path && !is_user_logged_in()) { $should_block = true; } if ($should_block) { // WooCommerce Compatibility check if ($this->get_setting('woo_compatibility')) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended if (isset($_GET['wc-ajax'])) return; } $action = $this->get_setting('redirect_action', 'custom_url'); // If action is custom_url, we don't strictly NEED to block here for wp-admin, // because WP core + our site_url filter will redirect to custom URL anyway. // BUT for wp-login.php we MUST block. // And to be safe/consistent, let's handle it explicitly. if ($action === 'custom_url') { $slug = $this->get_setting('custom_slug', 'login'); wp_safe_redirect(home_url($slug)); exit; } elseif ($action === 'custom_redirect') { $url = $this->get_setting('custom_redirect_url'); if (!empty($url)) { wp_safe_redirect($url); exit; } else { wp_safe_redirect(home_url()); exit; } } elseif ($action === '404') { global $wp_query; $wp_query->set_404(); status_header(404); if (get_query_template('404')) { include(get_query_template('404')); } else { echo "404 Not Found"; } exit; } elseif ($action === '403') { status_header(403); die('Forbidden'); } else { // Home wp_safe_redirect(home_url()); exit; } } } public function rewrite_login_url($url, $path = '', $scheme = null, $blog_id = null) { $slug = $this->get_setting('custom_slug', 'login'); if (empty($slug)) return $url; if ($scheme === 'login_post') { // Form action URLs // We should use the custom slug as well if possible, or wp-login.php? // wp-login.php handles POST fine if we whitelist it in block_default_login? // BUT, if handle_custom_login_slug loads wp-login.php, then POSTing to /slug works! // So we rewrite. // However, $url might be wp-login.php logic. } if (strpos($url, 'wp-login.php') !== false) { // Replace wp-login.php with slug // Handle query args $query = wp_parse_url($url, PHP_URL_QUERY); $new_url = home_url($slug); if ($query) { $new_url = add_query_arg($query, '', $new_url); // add_query_arg will merge? No, better use strings. $new_url .= '?' . $query; } return $new_url; } return $url; } public function filter_wp_redirect($location, $status) { if (strpos($location, 'wp-login.php') !== false) { $slug = $this->get_setting('custom_slug', 'login'); $location = str_replace('wp-login.php', $slug, $location); } return $location; } public function render_settings() { $settings = [ 'enable_custom_login' => ['type' => 'checkbox', 'label' => __('Enable Custom Login URL', 'admin-menu-optimizer')], 'custom_slug' => ['type' => 'text', 'label' => __('Custom Login Slug', 'admin-menu-optimizer'), 'desc' => __('Enter a custom slug for the login page. Use only letters, numbers, hyphens, and underscores.', 'admin-menu-optimizer')], 'redirect_action' => [ 'type' => 'select', 'label' => __('Default Login URL Redirection', 'admin-menu-optimizer'), 'options' => [ 'custom_url' => __('Redirect to New Login Page', 'admin-menu-optimizer'), 'custom_redirect' => __('Redirect to Custom URL', 'admin-menu-optimizer'), '403' => __('403 Forbidden', 'admin-menu-optimizer'), '404' => __('404 Not Found', 'admin-menu-optimizer'), 'home' => __('Redirect to Home', 'admin-menu-optimizer') ], 'desc' => __('Choose what happens when someone tries to access the default WordPress login URLs (wp-admin, wp-login.php).', 'admin-menu-optimizer') ], 'custom_redirect_url' => ['type' => 'text', 'label' => __('Default Login URL Custom Redirect', 'admin-menu-optimizer'), 'desc' => __('Enter a custom URL where users will be redirected when accessing default login URLs.', 'admin-menu-optimizer')], 'woo_compatibility' => ['type' => 'checkbox', 'label' => __('WooCommerce Compatibility', 'admin-menu-optimizer'), 'desc' => __('Preserve WooCommerce login pages and functionality when using custom login URL.', 'admin-menu-optimizer')], ]; echo ''; foreach ($settings as $key => $field) { $value = $this->get_setting($key); echo ''; echo ''; echo ''; echo ''; } echo ''; } }