define_redirects(); $this->init_hooks(); } /** * Define redirect mappings * * @return void */ private function define_redirects() { // Legacy URL to new URL mappings $this->legacy_redirects = array( 'community-login' => 'training-login', 'hvac-dashboard' => 'trainer/dashboard', 'manage-event' => 'trainer/event/manage', 'trainer-profile' => 'trainer/my-profile', 'event-summary' => 'trainer/event/summary', 'email-attendees' => 'trainer/email-attendees', 'certificate-reports' => 'trainer/certificate-reports', 'generate-certificates' => 'trainer/generate-certificates', 'certificate-fix' => 'master-trainer/certificate-fix', 'hvac-documentation' => 'trainer/documentation', 'attendee-profile' => 'trainer/attendee-profile', 'google-sheets' => 'master-trainer/google-sheets', 'communication-templates' => 'trainer/communication-templates', 'communication-schedules' => 'trainer/communication-schedules', 'trainer-registration' => 'trainer/registration', ); // Parent pages that redirect to dashboards $this->parent_redirects = array( 'trainer' => 'trainer/dashboard', 'master-trainer' => 'master-trainer/master-dashboard', 'master-trainer/dashboard' => 'master-trainer/master-dashboard', // Redirect old URL to new ); // Allow filtering $this->legacy_redirects = apply_filters('hvac_legacy_redirects', $this->legacy_redirects); $this->parent_redirects = apply_filters('hvac_parent_redirects', $this->parent_redirects); } /** * Initialize hooks * * @return void */ private function init_hooks() { // Register rewrite rules add_action('init', array($this, 'register_rewrite_rules'), 5); // Handle redirects - run very early add_action('template_redirect', array($this, 'handle_redirects'), 1); // Intercept page queries for legacy URLs add_action('pre_get_posts', array($this, 'intercept_legacy_page_queries'), 1); // Register query vars add_filter('query_vars', array($this, 'register_query_vars')); // Handle legacy redirect requests add_action('parse_request', array($this, 'handle_legacy_redirect_request')); // Flush rewrite rules on activation add_action('hvac_plugin_activated', array($this, 'flush_rewrite_rules')); } /** * Register rewrite rules * * @return void */ public function register_rewrite_rules() { // Add rewrite rules for legacy URLs foreach ($this->legacy_redirects as $legacy => $new) { add_rewrite_rule( '^' . $legacy . '/?$', 'index.php?hvac_legacy_redirect=' . $legacy, 'top' ); } // Add rewrite rules for hierarchical URLs // IMPORTANT: Only add rules for pages that don't exist as actual WordPress pages // Exclude 'manage' from the event subpage rule since it's a real page $hierarchical_rules = array( // Only add rules for event subpages that aren't real pages (exclude 'manage') 'trainer/event/(?!manage)([^/]+)/?$' => 'index.php?hvac_route=trainer&hvac_page=event&hvac_subpage=$matches[1]', ); foreach ($hierarchical_rules as $regex => $redirect) { add_rewrite_rule($regex, $redirect, 'top'); } // Log registration HVAC_Logger::info('Registered ' . count($this->legacy_redirects) . ' legacy redirects and ' . count($hierarchical_rules) . ' hierarchical rules', 'Routes'); } /** * Register query vars * * @param array $vars Query vars * @return array */ public function register_query_vars($vars) { $vars[] = 'hvac_legacy_redirect'; $vars[] = 'hvac_route'; $vars[] = 'hvac_page'; $vars[] = 'hvac_subpage'; return $vars; } /** * Handle legacy redirect requests * * @param WP $wp WordPress environment instance * @return void */ public function handle_legacy_redirect_request($wp) { if (!isset($wp->query_vars['hvac_legacy_redirect'])) { return; } $legacy_slug = $wp->query_vars['hvac_legacy_redirect']; if (isset($this->legacy_redirects[$legacy_slug])) { $new_url = home_url('/' . $this->legacy_redirects[$legacy_slug] . '/'); // Preserve query parameters if (!empty($_SERVER['QUERY_STRING'])) { $new_url .= '?' . $_SERVER['QUERY_STRING']; } // Log redirect HVAC_Logger::info("Redirecting legacy URL: {$legacy_slug} to {$new_url}", 'Routes'); wp_redirect($new_url, 301); exit; } } /** * Handle redirects * * @return void */ public function handle_redirects() { // Get current URL path $current_path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/'); // Handle legacy redirects if (isset($this->legacy_redirects[$current_path])) { $this->perform_redirect($this->legacy_redirects[$current_path]); } // Handle parent page redirects if (isset($this->parent_redirects[$current_path])) { $this->perform_redirect($this->parent_redirects[$current_path]); } // Also check if this is a 404 that should redirect if (is_404()) { // Check without trailing slash $path_no_slash = rtrim($current_path, '/'); if (isset($this->legacy_redirects[$path_no_slash])) { $this->perform_redirect($this->legacy_redirects[$path_no_slash]); } // Check with just the last segment (for pages that might exist but shouldn't) $segments = explode('/', $current_path); $last_segment = end($segments); if ($last_segment && isset($this->legacy_redirects[$last_segment])) { $this->perform_redirect($this->legacy_redirects[$last_segment]); } } // Also check if this is a page that exists with a legacy slug global $post; if (is_page() && $post) { $current_slug = $post->post_name; if (isset($this->legacy_redirects[$current_slug])) { $this->perform_redirect($this->legacy_redirects[$current_slug]); } } } /** * Perform redirect * * @param string $target Target path * @return void */ private function perform_redirect($target) { // Get current URL $current_url = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]"; $new_url = home_url('/' . $target . '/'); // Preserve query parameters if (!empty($_SERVER['QUERY_STRING'])) { $new_url .= '?' . $_SERVER['QUERY_STRING']; } // Don't redirect if we're already at the target URL if (rtrim($current_url, '/') === rtrim($new_url, '/')) { return; } // Log redirect HVAC_Logger::info("Performing redirect to: {$new_url}", 'Routes'); wp_redirect($new_url, 301); exit; } /** * Get legacy redirects * * @return array */ public function get_legacy_redirects() { return $this->legacy_redirects; } /** * Get parent redirects * * @return array */ public function get_parent_redirects() { return $this->parent_redirects; } /** * Add custom redirect * * @param string $from From path * @param string $to To path * @param string $type Type of redirect (legacy or parent) * @return void */ public function add_redirect($from, $to, $type = 'legacy') { if ($type === 'legacy') { $this->legacy_redirects[$from] = $to; } elseif ($type === 'parent') { $this->parent_redirects[$from] = $to; } // Re-register rules if already initialized if (did_action('init')) { $this->register_rewrite_rules(); flush_rewrite_rules(); } } /** * Remove redirect * * @param string $from From path * @param string $type Type of redirect (legacy or parent) * @return void */ public function remove_redirect($from, $type = 'legacy') { if ($type === 'legacy' && isset($this->legacy_redirects[$from])) { unset($this->legacy_redirects[$from]); } elseif ($type === 'parent' && isset($this->parent_redirects[$from])) { unset($this->parent_redirects[$from]); } // Re-register rules if already initialized if (did_action('init')) { $this->register_rewrite_rules(); flush_rewrite_rules(); } } /** * Flush rewrite rules * * @return void */ public function flush_rewrite_rules() { flush_rewrite_rules(); HVAC_Logger::info('Flushed rewrite rules', 'Routes'); } /** * Check if URL needs redirect * * @param string $url URL to check * @return string|false Redirect target or false */ public function needs_redirect($url) { $path = trim(parse_url($url, PHP_URL_PATH), '/'); if (isset($this->legacy_redirects[$path])) { return $this->legacy_redirects[$path]; } if (isset($this->parent_redirects[$path])) { return $this->parent_redirects[$path]; } return false; } /** * Intercept page queries for legacy URLs * * This prevents WordPress from finding pages with legacy slugs * and allows our redirects to work properly * * @param WP_Query $query The WordPress query object * @return void */ public function intercept_legacy_page_queries($query) { // Only run on the main query on the frontend if (!$query->is_main_query() || is_admin()) { return; } // Check if this is a page query if (!$query->is_page()) { return; } // Get the page name being queried $pagename = $query->get('pagename'); if (empty($pagename)) { return; } // Check if this is a legacy URL that should redirect if (isset($this->legacy_redirects[$pagename])) { // Prevent WordPress from finding this page $query->set('page_id', -1); $query->set('pagename', ''); // Force a 404 which will trigger our template_redirect $query->set_404(); // Log for debugging HVAC_Logger::info("Intercepted legacy page query: {$pagename}", 'Routes'); } } }