upskill-event-manager/includes/class-hvac-route-manager.php
ben 06a20ccee7 fix: resolve critical authentication failures in production
Fixes multiple authentication system conflicts causing redirect loops
that prevented all trainer and master trainer pages from loading.

Root cause: Three authentication systems competing on template_redirect:
- HVAC_Route_Manager (priority 1)
- HVAC_Plugin (priority 5)
- HVAC_Access_Control (priority 10)

Solution: Temporarily disable conflicting systems, keep HVAC_Access_Control
as primary authentication handler.

Verified working:
- /trainer/dashboard/, /trainer/venue/list/, /trainer/venue/manage/
- /master-trainer/dashboard/, /master-trainer/announcements/, /master-trainer/trainers/

Phase 1 Native Event System now fully operational in production.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-24 17:48:19 -03:00

404 lines
No EOL
12 KiB
PHP

<?php
/**
* HVAC Route Manager
*
* Centralized management of URL routing, redirects, and rewrite rules
*
* @package HVAC_Community_Events
* @since 2.0.0
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* HVAC_Route_Manager class
*/
class HVAC_Route_Manager {
/**
* Instance
*
* @var HVAC_Route_Manager
*/
private static $instance = null;
/**
* Legacy redirect mappings
*
* @var array
*/
private $legacy_redirects = array();
/**
* Parent page redirects
*
* @var array
*/
private $parent_redirects = array();
/**
* Get instance
*
* @return HVAC_Route_Manager
*/
public static function instance() {
if (null === self::$instance) {
self::$instance = new self();
}
return self::$instance;
}
/**
* Constructor
*/
private function __construct() {
$this->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',
'find-trainer' => 'find-a-trainer', // Fix E2E testing URL mismatch
);
// 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 - TEMPORARILY DISABLED due to conflict with HVAC_Access_Control
// 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');
}
}
}