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>
1448 lines
52 KiB
PHP
1448 lines
52 KiB
PHP
<?php
|
|
/**
|
|
* Main Plugin Class for HVAC Community Events
|
|
*
|
|
* Core plugin initialization and orchestration class following modern PHP 8+ patterns.
|
|
* Handles plugin lifecycle, dependency injection, component initialization, and
|
|
* WordPress integration using memory-efficient singleton pattern.
|
|
*
|
|
* Features:
|
|
* - Strict type declarations and comprehensive type hints
|
|
* - Modern singleton implementation with trait
|
|
* - Memory-efficient component loading with lazy initialization
|
|
* - Generator-based file inclusion for large plugin architectures
|
|
* - SPL data structures for performance optimization
|
|
* - Exception-based error handling with proper logging
|
|
* - WordPress security best practices throughout
|
|
*
|
|
* @package HVAC_Community_Events
|
|
* @since 1.0.0
|
|
* @version 2.0.0
|
|
*
|
|
* @author HVAC Community Events Team
|
|
* @copyright 2025 HVAC Community Events
|
|
* @license GPL-2.0-or-later
|
|
*/
|
|
|
|
declare(strict_types=1);
|
|
|
|
if (!defined('ABSPATH')) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Main plugin orchestration class
|
|
*
|
|
* Manages plugin initialization, component loading, and WordPress integration
|
|
* using modern PHP 8+ patterns and memory-efficient techniques.
|
|
*/
|
|
final class HVAC_Plugin {
|
|
|
|
/**
|
|
* @var static|null Singleton instance
|
|
*/
|
|
private static ?self $instance = null;
|
|
|
|
/**
|
|
* @var SplQueue<string> Component initialization queue
|
|
*/
|
|
private SplQueue $initQueue;
|
|
|
|
/**
|
|
* @var ArrayObject<string, bool> Component initialization status tracker
|
|
*/
|
|
private ArrayObject $componentStatus;
|
|
|
|
/**
|
|
* @var array<string, mixed> Plugin configuration cache
|
|
*/
|
|
private array $configCache = [];
|
|
|
|
/**
|
|
* @var bool Whether plugin is fully initialized
|
|
*/
|
|
private bool $isInitialized = false;
|
|
|
|
/**
|
|
* Constructor with property initialization
|
|
*
|
|
* Initializes SPL data structures and begins plugin bootstrap process.
|
|
* Uses lazy loading to prevent Safari cascade overload issues.
|
|
*/
|
|
private function __construct() {
|
|
$this->initQueue = new SplQueue();
|
|
$this->componentStatus = new ArrayObject([], ArrayObject::ARRAY_AS_PROPS);
|
|
|
|
$this->defineConstants();
|
|
$this->includeFiles();
|
|
$this->initializeHooks();
|
|
}
|
|
|
|
/**
|
|
* Get singleton instance
|
|
*
|
|
* @return static The singleton instance
|
|
*/
|
|
public static function instance(): self {
|
|
if (self::$instance === null) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
/**
|
|
* Prevent cloning of singleton
|
|
*/
|
|
private function __clone(): void {}
|
|
|
|
/**
|
|
* Prevent unserialization of singleton
|
|
*
|
|
* @throws Exception Always throws to prevent unserialization
|
|
*/
|
|
public function __wakeup(): never {
|
|
throw new Exception('Cannot unserialize singleton instance');
|
|
}
|
|
|
|
/**
|
|
* Define plugin constants with type safety
|
|
*
|
|
* Defines all plugin constants with proper validation and fallbacks.
|
|
* Uses PHP 8+ match expression for cleaner constant definition logic.
|
|
*/
|
|
private function defineConstants(): void {
|
|
if (!defined('HVAC_PLUGIN_VERSION')) {
|
|
define('HVAC_PLUGIN_VERSION', '2.0.0');
|
|
}
|
|
if (!defined('HVAC_VERSION')) {
|
|
define('HVAC_VERSION', '2.0.0');
|
|
}
|
|
if (!defined('HVAC_PLUGIN_FILE')) {
|
|
define('HVAC_PLUGIN_FILE', dirname(__DIR__) . '/hvac-community-events.php');
|
|
}
|
|
if (!defined('HVAC_PLUGIN_DIR')) {
|
|
define('HVAC_PLUGIN_DIR', plugin_dir_path(HVAC_PLUGIN_FILE));
|
|
}
|
|
if (!defined('HVAC_PLUGIN_URL')) {
|
|
define('HVAC_PLUGIN_URL', plugin_dir_url(HVAC_PLUGIN_FILE));
|
|
}
|
|
if (!defined('HVAC_PLUGIN_BASENAME')) {
|
|
define('HVAC_PLUGIN_BASENAME', plugin_basename(HVAC_PLUGIN_FILE));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Include required files using generator for memory efficiency
|
|
*
|
|
* Uses generator-based file inclusion to minimize memory footprint
|
|
* and prevent Safari browser cascade loading issues.
|
|
*
|
|
* @throws RuntimeException If critical files are missing
|
|
*/
|
|
private function includeFiles(): void {
|
|
// Safari request debugger - load first to catch all requests
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-safari-request-debugger.php';
|
|
|
|
// Safari script blocker - RE-ENABLED with improved lightweight approach
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-safari-script-blocker.php';
|
|
|
|
// Theme-agnostic layout manager
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-layout-manager.php';
|
|
|
|
// Load critical core files first
|
|
$coreFiles = [
|
|
'includes/class-hvac-logger.php',
|
|
'includes/class-hvac-activator.php',
|
|
'includes/class-hvac-deactivator.php',
|
|
'includes/class-hvac-page-manager.php',
|
|
'includes/class-hvac-template-loader.php',
|
|
'includes/class-hvac-secure-storage.php'
|
|
];
|
|
|
|
foreach ($this->loadCoreFiles($coreFiles) as $file => $loaded) {
|
|
if (!$loaded) {
|
|
throw new RuntimeException("Critical file missing: {$file}");
|
|
}
|
|
}
|
|
|
|
// Check which roles manager exists
|
|
if (file_exists(HVAC_PLUGIN_DIR . 'includes/class-hvac-roles-manager.php')) {
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-roles-manager.php';
|
|
} elseif (file_exists(HVAC_PLUGIN_DIR . 'includes/class-hvac-roles.php')) {
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-roles.php';
|
|
}
|
|
|
|
// Core architecture includes
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-browser-detection.php';
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-find-trainer-assets.php';
|
|
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-safari-debugger.php';
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-shortcodes.php';
|
|
// DISABLED - Using TEC Community Events 5.x instead
|
|
// require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-edit-event-shortcode.php';
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-scripts-styles.php';
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-bundled-assets.php';
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-route-manager.php';
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-menu-system.php';
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-master-menu-system.php';
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-master-content-injector.php';
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-role-consolidator.php';
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-welcome-popup.php';
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-query-monitor.php';
|
|
|
|
// TEC Integration - Load early for proper routing
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-tec-integration.php';
|
|
|
|
// Load singleton trait first (required by multiple classes)
|
|
require_once HVAC_PLUGIN_DIR . 'includes/trait-hvac-singleton.php';
|
|
|
|
// Core security framework
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-security.php';
|
|
|
|
// Form building framework
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-form-builder.php';
|
|
|
|
// Native event form builder (Phase 1A - Native WordPress Events)
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-event-form-builder.php';
|
|
|
|
// Native event post handler (Phase 1B - tribe_events creation)
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-event-post-handler.php';
|
|
|
|
// Event caching system (Phase 1D - Performance Optimization)
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-event-cache.php';
|
|
|
|
// AJAX optimization system (Phase 1D - Performance Optimization)
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-ajax-optimizer.php';
|
|
|
|
// Unified Event Management System (replaces 8+ fragmented implementations)
|
|
require_once HVAC_PLUGIN_DIR . 'includes/class-hvac-event-manager.php';
|
|
|
|
// Load feature files using generator for memory efficiency
|
|
$featureFiles = [
|
|
'class-hvac-ajax-security.php',
|
|
'class-hvac-ajax-handlers.php',
|
|
'class-hvac-trainer-status.php',
|
|
'class-hvac-access-control.php',
|
|
'class-hvac-registration.php',
|
|
'class-hvac-security-helpers.php',
|
|
'class-hvac-venues.php',
|
|
'class-hvac-trainer-profile-manager.php',
|
|
'class-hvac-profile-sync-handler.php',
|
|
'class-hvac-geocoding-service.php',
|
|
'class-hvac-trainer-profile-settings.php',
|
|
'class-hvac-geocoding-ajax.php',
|
|
'class-hvac-qr-generator.php',
|
|
'class-hvac-organizers.php',
|
|
'class-hvac-trainer-navigation.php',
|
|
'class-hvac-breadcrumbs.php',
|
|
'class-hvac-template-integration.php',
|
|
'class-hvac-training-leads.php',
|
|
'class-hvac-trainer-communication-templates.php',
|
|
'class-hvac-import-export-manager.php',
|
|
// DISABLED - Using TEC Community Events 5.x instead
|
|
// REMOVED: Consolidated into HVAC_Event_Manager
|
|
// 'class-hvac-manage-event.php',
|
|
// 'class-hvac-event-edit-fix.php',
|
|
// 'class-hvac-event-edit-comprehensive.php',
|
|
// 'class-hvac-custom-event-edit.php',
|
|
// 'class-hvac-edit-event-shortcode.php',
|
|
// 'class-event-form-handler.php',
|
|
// 'class-hvac-event-summary.php',
|
|
'class-hvac-trainer-profile.php',
|
|
'class-hvac-master-dashboard.php',
|
|
'class-hvac-master-dashboard-data.php',
|
|
'class-hvac-settings.php',
|
|
'class-hvac-dashboard.php',
|
|
'class-hvac-dashboard-data.php',
|
|
'class-hvac-approval-workflow.php',
|
|
'class-hvac-master-pending-approvals.php',
|
|
'class-hvac-master-events-overview.php',
|
|
'class-hvac-master-trainers-overview.php',
|
|
'class-hvac-announcements-manager.php',
|
|
'class-hvac-announcements-display.php',
|
|
'class-hvac-master-pages-fixer.php',
|
|
'class-hvac-master-layout-standardizer.php',
|
|
'class-hvac-master-content-injector.php',
|
|
'class-hvac-event-navigation.php',
|
|
'class-hvac-event-manage-header.php',
|
|
'class-hvac-help-system.php',
|
|
'class-hvac-documentation-content.php',
|
|
'class-event-form-handler.php',
|
|
'class-event-author-fixer.php',
|
|
'class-attendee-profile.php',
|
|
'class-hvac-page-content-fixer.php',
|
|
'class-hvac-page-content-manager.php',
|
|
];
|
|
|
|
// Find a Trainer feature files
|
|
$findTrainerFiles = [
|
|
'database/class-hvac-contact-submissions-table.php',
|
|
'find-trainer/class-hvac-find-trainer-page.php',
|
|
'find-trainer/class-hvac-mapgeo-integration.php',
|
|
'find-trainer/class-hvac-contact-form-handler.php',
|
|
'find-trainer/class-hvac-trainer-directory-query.php',
|
|
'class-hvac-mapgeo-safety.php', // MapGeo safety wrapper
|
|
];
|
|
|
|
// Load feature files with memory-efficient generator
|
|
foreach ($this->loadFeatureFiles($featureFiles) as $file => $status) {
|
|
if ($status === 'loaded') {
|
|
$this->componentStatus[$file] = true;
|
|
}
|
|
}
|
|
|
|
// Load Find a Trainer feature files
|
|
foreach ($this->loadFeatureFiles($findTrainerFiles) as $file => $status) {
|
|
if ($status === 'loaded') {
|
|
$this->componentStatus["find_trainer_{$file}"] = true;
|
|
}
|
|
}
|
|
|
|
// Load community system files
|
|
$communityFiles = [
|
|
'community/class-login-handler.php',
|
|
'community/class-event-handler.php'
|
|
];
|
|
|
|
foreach ($this->loadFeatureFiles($communityFiles) as $file => $status) {
|
|
if ($status === 'loaded' && $file === 'community/class-login-handler.php') {
|
|
// Initialize Login_Handler to register shortcode
|
|
if (class_exists('\HVAC_Community_Events\Community\Login_Handler')) {
|
|
new \HVAC_Community_Events\Community\Login_Handler();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Certificate system files
|
|
$certificateFiles = [
|
|
'certificates/class-certificate-security.php',
|
|
'certificates/class-certificate-installer.php',
|
|
'certificates/class-certificate-manager.php',
|
|
'certificates/class-certificate-generator.php',
|
|
'certificates/class-certificate-url-handler.php',
|
|
];
|
|
|
|
// Trainer certification system files
|
|
$trainerCertificationFiles = [
|
|
'certifications/class-hvac-trainer-certification-manager.php',
|
|
'certifications/class-hvac-certification-migrator.php',
|
|
'certifications/class-hvac-certification-admin.php',
|
|
];
|
|
|
|
// Load certificate and certification files
|
|
foreach ($this->loadFeatureFiles($certificateFiles) as $file => $status) {
|
|
if ($status === 'loaded') {
|
|
$this->componentStatus["certificate_{$file}"] = true;
|
|
}
|
|
}
|
|
|
|
foreach ($this->loadFeatureFiles($trainerCertificationFiles) as $file => $status) {
|
|
if ($status === 'loaded') {
|
|
$this->componentStatus["trainer_cert_{$file}"] = true;
|
|
}
|
|
}
|
|
|
|
// Initialize announcements system
|
|
$announcementsFile = 'class-hvac-announcements-manager.php';
|
|
foreach ($this->loadFeatureFiles([$announcementsFile]) as $file => $status) {
|
|
if ($status === 'loaded' && class_exists('HVAC_Announcements_Manager')) {
|
|
HVAC_Announcements_Manager::init();
|
|
}
|
|
}
|
|
|
|
// Admin system files
|
|
$adminFiles = [
|
|
'admin/class-zoho-admin.php',
|
|
'admin/class-admin-dashboard.php',
|
|
'admin/class-hvac-enhanced-settings.php',
|
|
];
|
|
|
|
// Load admin files conditionally
|
|
if (is_admin() || wp_doing_ajax()) {
|
|
foreach ($this->loadFeatureFiles($adminFiles) as $file => $status) {
|
|
if ($status === 'loaded') {
|
|
$this->componentStatus["admin_{$file}"] = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Google Sheets integration files
|
|
$googleFiles = [
|
|
'google-sheets/class-google-sheets-auth.php',
|
|
'google-sheets/class-google-sheets-admin.php',
|
|
];
|
|
|
|
// Load Google integration files
|
|
foreach ($this->loadFeatureFiles($googleFiles) as $file => $status) {
|
|
if ($status === 'loaded') {
|
|
$this->componentStatus["google_{$file}"] = true;
|
|
}
|
|
}
|
|
|
|
// Communication system files
|
|
$communicationFiles = [
|
|
'communication/class-communication-installer.php',
|
|
'communication/class-communication-scheduler.php',
|
|
'communication/class-communication-templates.php',
|
|
];
|
|
|
|
// Load communication files
|
|
foreach ($this->loadFeatureFiles($communicationFiles) as $file => $status) {
|
|
if ($status === 'loaded') {
|
|
$this->componentStatus["comm_{$file}"] = true;
|
|
}
|
|
}
|
|
|
|
// Load helper files
|
|
$helperFiles = ['helpers/attendee-profile-link.php'];
|
|
foreach ($this->loadFeatureFiles($helperFiles) as $file => $status) {
|
|
if ($status === 'loaded') {
|
|
$this->componentStatus["helper_{$file}"] = true;
|
|
}
|
|
}
|
|
|
|
// Load legacy files for backward compatibility
|
|
$this->includeLegacyFiles();
|
|
}
|
|
|
|
/**
|
|
* Initialize WordPress hooks with proper typing
|
|
*
|
|
* Registers all WordPress actions and filters with type-safe callbacks.
|
|
* Uses modern array syntax and proper hook priorities.
|
|
*/
|
|
private function initializeHooks(): void {
|
|
// Lifecycle hooks
|
|
register_activation_hook(HVAC_PLUGIN_FILE, [$this, 'activate']);
|
|
register_deactivation_hook(HVAC_PLUGIN_FILE, [$this, 'deactivate']);
|
|
|
|
// Core initialization hooks
|
|
add_action('init', [$this, 'initialize'], 0);
|
|
add_action('plugins_loaded', [$this, 'pluginsLoaded']);
|
|
|
|
// Admin hooks
|
|
add_action('admin_init', [$this, 'adminInit']);
|
|
add_action('admin_menu', [$this, 'addAdminMenus']);
|
|
|
|
// Feature initialization
|
|
add_action('init', [$this, 'initializeFindTrainer'], 20);
|
|
|
|
// TEC Integration WordPress filter hooks (Priority 1 - WordPress/TEC Best Practice Fix)
|
|
add_action('init', [$this, 'initializeTECIntegration'], 5);
|
|
|
|
// AJAX handlers with proper naming
|
|
add_action('wp_ajax_hvac_master_dashboard_events', [$this, 'ajax_master_dashboard_events']);
|
|
add_action('wp_ajax_hvac_safari_debug', [$this, 'ajaxSafariDebug']);
|
|
add_action('wp_ajax_nopriv_hvac_safari_debug', [$this, 'ajaxSafariDebug']);
|
|
|
|
// Theme integration
|
|
add_filter('body_class', [$this, 'add_hvac_body_classes']);
|
|
add_filter('post_class', [$this, 'addHvacPostClasses']);
|
|
|
|
// Astra theme layout overrides
|
|
add_filter('astra_page_layout', [$this, 'force_full_width_layout']);
|
|
add_filter('astra_get_content_layout', [$this, 'force_full_width_layout']);
|
|
|
|
// Page management hooks
|
|
add_action('admin_init', [$this, 'checkForPageUpdates']);
|
|
add_action('init', [$this, 'checkPageUpdateFlag'], 99);
|
|
}
|
|
|
|
/**
|
|
* Plugin activation handler
|
|
*
|
|
* Delegates to activator class with proper error handling.
|
|
*
|
|
* @throws RuntimeException If activation fails
|
|
*/
|
|
public function activate(): void {
|
|
try {
|
|
HVAC_Activator::activate();
|
|
} catch (Exception $e) {
|
|
error_log('HVAC Plugin activation failed: ' . $e->getMessage());
|
|
throw new RuntimeException('Plugin activation failed', 0, $e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Plugin deactivation handler
|
|
*
|
|
* Delegates to deactivator class with proper cleanup.
|
|
*/
|
|
public function deactivate(): void {
|
|
try {
|
|
HVAC_Deactivator::deactivate();
|
|
} catch (Exception $e) {
|
|
error_log('HVAC Plugin deactivation error: ' . $e->getMessage());
|
|
// Don't throw on deactivation - log and continue
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Main initialization method
|
|
*
|
|
* Initializes core components with lazy loading to prevent memory issues.
|
|
* Uses SPL queue to manage component initialization order.
|
|
*/
|
|
public function initialize(): void {
|
|
if ($this->isInitialized) {
|
|
return;
|
|
}
|
|
// Initialize core architecture components with type safety
|
|
$coreComponents = [
|
|
'HVAC_Shortcodes' => fn() => HVAC_Shortcodes::instance(),
|
|
'HVAC_Scripts_Styles' => fn() => HVAC_Scripts_Styles::instance(),
|
|
'HVAC_Bundled_Assets' => fn() => HVAC_Bundled_Assets::instance(),
|
|
'HVAC_Find_Trainer_Assets' => fn() => HVAC_Find_Trainer_Assets::instance(),
|
|
'HVAC_Safari_Debugger' => fn() => HVAC_Safari_Debugger::instance(),
|
|
'HVAC_Route_Manager' => fn() => HVAC_Route_Manager::instance()
|
|
];
|
|
|
|
// Initialize core components with error handling
|
|
foreach ($coreComponents as $name => $initializer) {
|
|
try {
|
|
if (class_exists($name)) {
|
|
$initializer();
|
|
$this->componentStatus[$name] = true;
|
|
}
|
|
} catch (Exception $e) {
|
|
error_log("Failed to initialize {$name}: " . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// Initialize template loader
|
|
HVAC_Template_Loader::init();
|
|
|
|
// Initialize access control with error handling
|
|
if (class_exists('HVAC_Access_Control')) {
|
|
new HVAC_Access_Control();
|
|
}
|
|
|
|
// Initialize optional components
|
|
$this->initializeOptionalComponents();
|
|
|
|
// Initialize secondary components
|
|
$this->initializeComponents();
|
|
|
|
// Registration access hook - TEMPORARILY DISABLED due to conflict with HVAC_Access_Control
|
|
// add_action('template_redirect', [$this, 'ensure_registration_access'], 5);
|
|
|
|
$this->isInitialized = true;
|
|
}
|
|
|
|
/**
|
|
* Initialize optional components with proper error handling
|
|
*
|
|
* Components are initialized only if their classes exist to prevent fatal errors.
|
|
*/
|
|
private function initializeOptionalComponents(): void {
|
|
// Trainer certification system
|
|
if (class_exists('HVAC_Trainer_Certification_Manager')) {
|
|
try {
|
|
HVAC_Trainer_Certification_Manager::instance();
|
|
$this->componentStatus['trainer_certification'] = true;
|
|
} catch (Exception $e) {
|
|
error_log('Trainer certification initialization failed: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
// Query monitoring
|
|
if (class_exists('HVAC_Query_Monitor')) {
|
|
HVAC_Query_Monitor::init();
|
|
$this->componentStatus['query_monitor'] = true;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize plugin components with lazy loading
|
|
*
|
|
* Prevents Safari cascade overload by using deferred initialization.
|
|
*/
|
|
private function initializeComponents(): void {
|
|
// Initialize only critical core components immediately
|
|
if (class_exists('HVAC_Community_Events')) {
|
|
// DISABLED - Using TEC Community Events 5.x instead
|
|
// HVAC_Community_Events::instance();
|
|
}
|
|
|
|
// Schedule non-critical components for lazy loading
|
|
add_action('wp_loaded', [$this, 'initializeSecondaryComponents'], 5);
|
|
add_action('admin_init', [$this, 'initializeAdminComponents'], 5);
|
|
}
|
|
|
|
/**
|
|
* Initialize secondary components with lazy loading
|
|
*
|
|
* Spreads initialization across multiple hooks to prevent browser overload.
|
|
* Uses memory-efficient component loading patterns.
|
|
*/
|
|
public function initializeSecondaryComponents(): void {
|
|
// Initialize registration if class exists
|
|
if (class_exists('HVAC_Registration')) {
|
|
new HVAC_Registration();
|
|
}
|
|
|
|
// Initialize venues management
|
|
if (class_exists('HVAC_Venues')) {
|
|
HVAC_Venues::instance();
|
|
}
|
|
|
|
// Initialize trainer profile manager
|
|
if (class_exists('HVAC_Trainer_Profile_Manager')) {
|
|
HVAC_Trainer_Profile_Manager::get_instance();
|
|
}
|
|
|
|
// Initialize profile sync handler
|
|
if (class_exists('HVAC_Profile_Sync_Handler')) {
|
|
HVAC_Profile_Sync_Handler::get_instance();
|
|
}
|
|
|
|
// Initialize geocoding service
|
|
if (class_exists('HVAC_Geocoding_Service')) {
|
|
HVAC_Geocoding_Service::get_instance();
|
|
}
|
|
|
|
// Initialize trainer profile settings
|
|
if (class_exists('HVAC_Trainer_Profile_Settings')) {
|
|
HVAC_Trainer_Profile_Settings::get_instance();
|
|
}
|
|
|
|
// Initialize organizers management
|
|
if (class_exists('HVAC_Organizers')) {
|
|
HVAC_Organizers::instance();
|
|
}
|
|
|
|
// Initialize training leads management
|
|
if (class_exists('HVAC_Training_Leads')) {
|
|
HVAC_Training_Leads::instance();
|
|
}
|
|
|
|
// Initialize menu systems
|
|
if (class_exists('HVAC_Menu_System')) {
|
|
HVAC_Menu_System::instance();
|
|
}
|
|
|
|
if (class_exists('HVAC_Master_Menu_System')) {
|
|
HVAC_Master_Menu_System::instance();
|
|
}
|
|
|
|
// Initialize breadcrumbs
|
|
if (class_exists('HVAC_Breadcrumbs')) {
|
|
HVAC_Breadcrumbs::instance();
|
|
}
|
|
|
|
// Initialize unified event management system (replaces 8+ fragmented implementations)
|
|
if (class_exists('HVAC_Event_Manager')) {
|
|
HVAC_Event_Manager::instance();
|
|
}
|
|
|
|
// Legacy event summary (if still needed)
|
|
if (class_exists('HVAC_Event_Summary')) {
|
|
new HVAC_Event_Summary();
|
|
}
|
|
|
|
// Initialize trainer profile
|
|
if (class_exists('HVAC_Trainer_Profile')) {
|
|
new HVAC_Trainer_Profile();
|
|
}
|
|
|
|
// Initialize dashboards
|
|
if (class_exists('HVAC_Dashboard')) {
|
|
new HVAC_Dashboard();
|
|
}
|
|
if (class_exists('HVAC_Master_Dashboard')) {
|
|
new HVAC_Master_Dashboard();
|
|
}
|
|
|
|
// Initialize settings
|
|
if (class_exists('HVAC_Settings')) {
|
|
new HVAC_Settings();
|
|
}
|
|
|
|
// Initialize approval workflow
|
|
if (class_exists('HVAC_Approval_Workflow')) {
|
|
new HVAC_Approval_Workflow();
|
|
}
|
|
|
|
// Initialize event navigation
|
|
if (class_exists('HVAC_Event_Navigation')) {
|
|
new HVAC_Event_Navigation();
|
|
}
|
|
|
|
// Initialize help system
|
|
if (class_exists('HVAC_Help_System')) {
|
|
HVAC_Help_System::instance();
|
|
}
|
|
|
|
// Initialize Master Layout Standardizer
|
|
if (class_exists('HVAC_Master_Layout_Standardizer')) {
|
|
HVAC_Master_Layout_Standardizer::instance();
|
|
}
|
|
|
|
// Initialize Master Content Injector
|
|
if (class_exists('HVAC_Master_Content_Injector')) {
|
|
HVAC_Master_Content_Injector::instance();
|
|
}
|
|
|
|
// Initialize Page Content Manager
|
|
if (class_exists('HVAC_Page_Content_Manager')) {
|
|
HVAC_Page_Content_Manager::instance();
|
|
}
|
|
|
|
// Initialize certificate security
|
|
if (class_exists('HVAC_Certificate_Security')) {
|
|
HVAC_Certificate_Security::instance();
|
|
}
|
|
|
|
// Initialize certificate URL handler
|
|
if (class_exists('HVAC_Certificate_URL_Handler')) {
|
|
HVAC_Certificate_URL_Handler::instance();
|
|
}
|
|
|
|
// Initialize attendee profile
|
|
if (class_exists('HVAC_Attendee_Profile')) {
|
|
HVAC_Attendee_Profile::instance();
|
|
}
|
|
|
|
// Initialize Google Sheets
|
|
if (class_exists('HVAC_Google_Sheets_Auth')) {
|
|
new HVAC_Google_Sheets_Auth();
|
|
}
|
|
if (class_exists('HVAC_Google_Sheets_Admin')) {
|
|
new HVAC_Google_Sheets_Admin();
|
|
}
|
|
|
|
// Initialize communication system
|
|
if (class_exists('HVAC_Communication_Installer')) {
|
|
HVAC_Communication_Installer::maybe_update();
|
|
}
|
|
if (class_exists('HVAC_Communication_Scheduler')) {
|
|
hvac_communication_scheduler();
|
|
}
|
|
|
|
// Initialize Master Trainer manager classes (fix for missing shortcode registrations)
|
|
if (class_exists('HVAC_Master_Events_Overview')) {
|
|
HVAC_Master_Events_Overview::instance();
|
|
}
|
|
if (class_exists('HVAC_Master_Pending_Approvals')) {
|
|
HVAC_Master_Pending_Approvals::instance();
|
|
}
|
|
if (class_exists('HVAC_Master_Trainers_Overview')) {
|
|
HVAC_Master_Trainers_Overview::instance();
|
|
}
|
|
if (class_exists('HVAC_Announcements_Display')) {
|
|
HVAC_Announcements_Display::get_instance();
|
|
}
|
|
if (class_exists('HVAC_Announcements_Admin')) {
|
|
HVAC_Announcements_Admin::get_instance();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize admin components with conditional loading
|
|
*
|
|
* Only loads admin components in admin context to improve frontend performance.
|
|
*/
|
|
public function initializeAdminComponents(): void {
|
|
// Initialize admin components only when needed
|
|
if (class_exists('HVAC_Zoho_Admin')) {
|
|
HVAC_Zoho_Admin::instance();
|
|
}
|
|
if (class_exists('HVAC_Admin_Dashboard')) {
|
|
new HVAC_Admin_Dashboard();
|
|
}
|
|
if (class_exists('HVAC_Enhanced_Settings')) {
|
|
HVAC_Enhanced_Settings::instance();
|
|
}
|
|
|
|
// Initialize trainer certification admin interface
|
|
if (class_exists('HVAC_Certification_Admin') && current_user_can('manage_hvac_certifications')) {
|
|
HVAC_Certification_Admin::instance();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Initialize TEC Community Events integration with WordPress filter hooks
|
|
*
|
|
* Implements WordPress/TEC best practices for form submission handling.
|
|
* Uses proper WordPress filter hooks instead of JavaScript overrides.
|
|
* Addresses Priority 1 issue from WordPress/TEC Implementation Plan.
|
|
*/
|
|
public function initializeTECIntegration(): void {
|
|
// Only initialize if TEC Community Events is active
|
|
if (!function_exists('tribe_community_events_init')) {
|
|
return;
|
|
}
|
|
|
|
// TEC form submission pre-processing hook (correct TEC 5.0+ hook name)
|
|
add_filter('tec_events_community_before_save_submission', [$this, 'processTECSubmissionData'], 10, 1);
|
|
|
|
// TEC form submission post-processing hook for additional handling
|
|
add_action('tribe_community_event_save_updated', [$this, 'processTECSubmissionSuccess'], 10, 1);
|
|
|
|
// Debug TEC submission data if WP_DEBUG is enabled
|
|
if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
add_action('tec_events_community_before_save_submission', [$this, 'debugTECSubmissionData'], 5, 1);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Process TEC submission data before save using WordPress filters
|
|
*
|
|
* Normalizes form data for TEC Community Events compatibility.
|
|
* Replaces JavaScript form override with WordPress-compliant approach.
|
|
*
|
|
* @param array $submission Raw submission data from TEC form
|
|
* @return array Normalized submission data
|
|
*/
|
|
public function processTECSubmissionData(array $submission): array {
|
|
// Debug payload structure for investigation
|
|
if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
error_log('[HVAC TEC Integration] Processing submission: ' . print_r($submission, true));
|
|
}
|
|
|
|
// Normalize excerpt field - TEC expects 'post_excerpt', not 'excerpt'
|
|
if (isset($submission['excerpt']) && !isset($submission['post_excerpt'])) {
|
|
$submission['post_excerpt'] = sanitize_textarea_field($submission['excerpt']);
|
|
error_log('[HVAC TEC Integration] Normalized excerpt field: ' . $submission['excerpt']);
|
|
}
|
|
|
|
// Ensure proper date formatting for TEC
|
|
if (isset($submission['EventStartDate']) && !empty($submission['EventStartDate'])) {
|
|
$submission['EventStartDate'] = tribe_format_date($submission['EventStartDate'], true, 'Y-m-d H:i:s');
|
|
}
|
|
|
|
if (isset($submission['EventEndDate']) && !empty($submission['EventEndDate'])) {
|
|
$submission['EventEndDate'] = tribe_format_date($submission['EventEndDate'], true, 'Y-m-d H:i:s');
|
|
}
|
|
|
|
// Ensure event status is properly set
|
|
if (!isset($submission['post_status'])) {
|
|
$submission['post_status'] = 'publish'; // Default to published for trainers
|
|
}
|
|
|
|
return $submission;
|
|
}
|
|
|
|
/**
|
|
* Process TEC submission after successful save
|
|
*
|
|
* Handles post-processing after successful event save.
|
|
* Uses TEC Community Events tribe_community_event_save_updated hook.
|
|
*
|
|
* @param int $event_id The created/updated event ID
|
|
*/
|
|
public function processTECSubmissionSuccess(int $event_id): void {
|
|
// Log successful submission for debugging
|
|
if (defined('WP_DEBUG') && WP_DEBUG) {
|
|
error_log("[HVAC TEC Integration] Successfully processed event {$event_id} via tribe_community_event_save_updated hook");
|
|
}
|
|
|
|
// Additional post-processing can be added here as needed
|
|
do_action('hvac_tec_event_saved', $event_id);
|
|
}
|
|
|
|
/**
|
|
* Debug TEC submission data for troubleshooting
|
|
*
|
|
* @param array $submission Submission data to debug
|
|
*/
|
|
public function debugTECSubmissionData(array $submission): void {
|
|
$debug_info = [
|
|
'timestamp' => current_time('Y-m-d H:i:s'),
|
|
'user_id' => get_current_user_id(),
|
|
'submission_keys' => array_keys($submission),
|
|
'has_excerpt' => isset($submission['excerpt']),
|
|
'has_post_excerpt' => isset($submission['post_excerpt']),
|
|
'excerpt_value' => $submission['excerpt'] ?? 'not_set',
|
|
'event_start' => $submission['EventStartDate'] ?? 'not_set',
|
|
'event_end' => $submission['EventEndDate'] ?? 'not_set'
|
|
];
|
|
|
|
error_log('[HVAC TEC Debug] Submission data: ' . print_r($debug_info, true));
|
|
}
|
|
|
|
/**
|
|
* Initialize Find a Trainer feature components
|
|
*
|
|
* Loads trainer directory functionality with proper error handling.
|
|
*/
|
|
public function initializeFindTrainer(): void {
|
|
// Initialize Find a Trainer page
|
|
if (class_exists('HVAC_Find_Trainer_Page')) {
|
|
HVAC_Find_Trainer_Page::get_instance();
|
|
}
|
|
|
|
// Initialize MapGeo integration
|
|
if (class_exists('HVAC_MapGeo_Integration')) {
|
|
HVAC_MapGeo_Integration::get_instance();
|
|
}
|
|
|
|
// Initialize contact form handler
|
|
if (class_exists('HVAC_Contact_Form_Handler')) {
|
|
HVAC_Contact_Form_Handler::get_instance();
|
|
}
|
|
|
|
// Initialize trainer directory query
|
|
if (class_exists('HVAC_Trainer_Directory_Query')) {
|
|
HVAC_Trainer_Directory_Query::get_instance();
|
|
}
|
|
|
|
// Initialize master trainer manager components
|
|
if (class_exists('HVAC_Master_Trainers_Overview')) {
|
|
HVAC_Master_Trainers_Overview::instance();
|
|
}
|
|
|
|
if (class_exists('HVAC_Announcements_Manager')) {
|
|
HVAC_Announcements_Manager::get_instance();
|
|
}
|
|
|
|
if (class_exists('HVAC_Master_Pending_Approvals')) {
|
|
HVAC_Master_Pending_Approvals::instance();
|
|
}
|
|
|
|
if (class_exists('HVAC_Master_Events_Overview')) {
|
|
HVAC_Master_Events_Overview::instance();
|
|
}
|
|
|
|
// Fix master trainer pages if needed
|
|
if (class_exists('HVAC_Master_Pages_Fixer')) {
|
|
// Run the fix immediately on plugin activation
|
|
if (defined('WP_INSTALLING_PLUGIN') || (isset($_GET['action']) && $_GET['action'] === 'activate')) {
|
|
HVAC_Master_Pages_Fixer::fix_pages();
|
|
}
|
|
// Also check periodically
|
|
add_action('init', array('HVAC_Master_Pages_Fixer', 'check_pages'), 999);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Plugins loaded hook - internationalization setup
|
|
*
|
|
* Loads plugin text domain for translations with proper path resolution.
|
|
*/
|
|
public function pluginsLoaded(): void {
|
|
$textDomainPath = dirname(HVAC_PLUGIN_BASENAME) . '/languages';
|
|
|
|
$loaded = load_plugin_textdomain(
|
|
'hvac-community-events',
|
|
false,
|
|
$textDomainPath
|
|
);
|
|
|
|
if (!$loaded && defined('WP_DEBUG') && WP_DEBUG) {
|
|
error_log("Failed to load text domain from: {$textDomainPath}");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Admin initialization hook
|
|
*
|
|
* Handles admin-specific initialization including version management.
|
|
*/
|
|
public function adminInit(): void {
|
|
$this->checkPluginUpdates();
|
|
}
|
|
|
|
/**
|
|
* Add admin menu items with proper capability checking
|
|
*
|
|
* Registers admin menu pages with appropriate capabilities and callbacks.
|
|
*/
|
|
public function addAdminMenus(): void {
|
|
// Add event seeder page
|
|
add_submenu_page(
|
|
'tools.php', // Parent menu
|
|
'HVAC Event Seeder', // Page title
|
|
'HVAC Event Seeder', // Menu title
|
|
'manage_options', // Capability
|
|
'hvac-seed-events', // Menu slug
|
|
[$this, 'renderSeedEventsPage'] // Callback
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Render the seed events admin page
|
|
*
|
|
* Includes the seeding interface with proper security checks.
|
|
*
|
|
* @throws RuntimeException If admin file is missing
|
|
*/
|
|
public function renderSeedEventsPage(): void {
|
|
$adminFile = HVAC_PLUGIN_DIR . 'admin/seed-events-direct.php';
|
|
|
|
if (!file_exists($adminFile)) {
|
|
throw new RuntimeException('Seed events admin file not found');
|
|
}
|
|
|
|
require_once $adminFile;
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Check for plugin updates with semantic versioning
|
|
*
|
|
* Compares current version with installed version and triggers upgrade.
|
|
*/
|
|
private function checkPluginUpdates(): void {
|
|
$currentVersion = get_option('hvac_plugin_version', '0.0.0');
|
|
|
|
if (version_compare($currentVersion, HVAC_PLUGIN_VERSION, '<')) {
|
|
try {
|
|
$this->runUpgradeRoutines($currentVersion);
|
|
update_option('hvac_plugin_version', HVAC_PLUGIN_VERSION);
|
|
} catch (Exception $e) {
|
|
error_log('Plugin upgrade failed: ' . $e->getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Run version-specific upgrade routines
|
|
*
|
|
* @param string $fromVersion Version upgrading from
|
|
* @throws Exception If upgrade fails
|
|
*/
|
|
private function runUpgradeRoutines(string $fromVersion): void {
|
|
if (class_exists('HVAC_Logger')) {
|
|
HVAC_Logger::info(
|
|
"Upgrading from version {$fromVersion} to " . HVAC_PLUGIN_VERSION,
|
|
'Upgrade'
|
|
);
|
|
}
|
|
|
|
// Version-specific upgrade logic can be added here using match expression
|
|
$upgradeActions = match (true) {
|
|
version_compare($fromVersion, '2.0.0', '<') => $this->upgradeTo200(),
|
|
default => null
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Upgrade to version 2.0.0
|
|
*
|
|
* Handles specific upgrade tasks for version 2.0.0.
|
|
*/
|
|
private function upgradeTo200(): void {
|
|
// Version 2.0.0 specific upgrade tasks
|
|
// This method can be expanded as needed
|
|
}
|
|
|
|
|
|
/**
|
|
* Ensure trainer registration page is publicly accessible
|
|
*
|
|
* @return void
|
|
*/
|
|
public function ensure_registration_access() {
|
|
// If we're on the trainer registration page, don't apply any authentication checks
|
|
$current_path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
|
|
if ($current_path === 'trainer/registration' || is_page('registration') || is_page('trainer-registration')) {
|
|
// Remove any potential authentication hooks that might be added by other code
|
|
remove_all_actions('template_redirect', 10);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handle AJAX request for master dashboard events table
|
|
*
|
|
* @return void
|
|
*/
|
|
public function ajax_master_dashboard_events() {
|
|
// Check authentication first
|
|
if (!is_user_logged_in()) {
|
|
wp_send_json_error('Authentication required', 401);
|
|
}
|
|
|
|
// Verify nonce
|
|
if (!isset($_POST['nonce']) || !wp_verify_nonce($_POST['nonce'], 'hvac_master_dashboard_nonce')) {
|
|
wp_die('Security check failed');
|
|
}
|
|
|
|
// Check permissions
|
|
if (!current_user_can('view_master_dashboard') && !current_user_can('view_all_trainer_data') && !current_user_can('manage_options')) {
|
|
wp_send_json_error('Insufficient permissions');
|
|
}
|
|
|
|
// Load master dashboard data class if needed
|
|
if (!class_exists('HVAC_Master_Dashboard_Data')) {
|
|
$data_file = HVAC_PLUGIN_DIR . 'includes/class-hvac-master-dashboard-data.php';
|
|
if (file_exists($data_file)) {
|
|
require_once $data_file;
|
|
}
|
|
}
|
|
|
|
if (!class_exists('HVAC_Master_Dashboard_Data')) {
|
|
wp_send_json_error('Master dashboard data class not found');
|
|
}
|
|
|
|
// Initialize data handler
|
|
$master_data = new HVAC_Master_Dashboard_Data();
|
|
|
|
// Get table data with filters
|
|
$args = array(
|
|
'status' => sanitize_text_field($_POST['status'] ?? 'all'),
|
|
'search' => sanitize_text_field($_POST['search'] ?? ''),
|
|
'orderby' => sanitize_text_field($_POST['orderby'] ?? 'date'),
|
|
'order' => sanitize_text_field($_POST['order'] ?? 'DESC'),
|
|
'page' => absint($_POST['page'] ?? 1),
|
|
'per_page' => absint($_POST['per_page'] ?? 10),
|
|
'date_from' => sanitize_text_field($_POST['date_from'] ?? ''),
|
|
'date_to' => sanitize_text_field($_POST['date_to'] ?? ''),
|
|
'trainer_id' => absint($_POST['trainer_id'] ?? 0),
|
|
);
|
|
|
|
$table_data = $master_data->get_events_table_data($args);
|
|
wp_send_json_success($table_data);
|
|
}
|
|
|
|
/**
|
|
* Handle AJAX request for Safari debugging logs
|
|
*
|
|
* Processes browser debug data with proper sanitization and logging.
|
|
*/
|
|
public function ajaxSafariDebug(): void {
|
|
// Validate log data
|
|
$logData = $_POST['log'] ?? '';
|
|
|
|
if (empty($logData)) {
|
|
wp_send_json_error('No log data provided');
|
|
return;
|
|
}
|
|
|
|
// Decode and validate JSON data
|
|
$logEntry = json_decode(stripslashes($logData), true);
|
|
|
|
if (!is_array($logEntry)) {
|
|
wp_send_json_error('Invalid log data format');
|
|
return;
|
|
}
|
|
|
|
// Create sanitized log entry
|
|
$safeLogEntry = [
|
|
'timestamp' => $logEntry['time']
|
|
? sanitize_text_field($logEntry['time'])
|
|
: current_time('Y-m-d H:i:s'),
|
|
'message' => sanitize_text_field($logEntry['message'] ?? ''),
|
|
'user_agent' => sanitize_text_field($logEntry['userAgent'] ?? ''),
|
|
'data' => isset($logEntry['data']) ? wp_json_encode($logEntry['data']) : null,
|
|
'error_info' => sanitize_text_field($logEntry['error'] ?? ''),
|
|
'stack_trace' => sanitize_textarea_field($logEntry['stack'] ?? '')
|
|
];
|
|
|
|
// Log to WordPress debug log with structured format
|
|
if (defined('WP_DEBUG_LOG') && WP_DEBUG_LOG) {
|
|
$logParts = [
|
|
'[SAFARI-DEBUG]',
|
|
$safeLogEntry['timestamp'],
|
|
$safeLogEntry['message'],
|
|
'UA: ' . $safeLogEntry['user_agent']
|
|
];
|
|
|
|
if (!empty($safeLogEntry['data'])) {
|
|
$logParts[] = 'Data: ' . $safeLogEntry['data'];
|
|
}
|
|
|
|
if (!empty($safeLogEntry['error_info'])) {
|
|
$logParts[] = 'Error: ' . $safeLogEntry['error_info'];
|
|
}
|
|
|
|
error_log(implode(' | ', $logParts));
|
|
}
|
|
|
|
// Store in database with size limits to prevent bloat
|
|
$logOptionKey = 'hvac_safari_debug_logs_' . date('Y_m_d');
|
|
$existingLogs = get_option($logOptionKey, []);
|
|
$existingLogs[] = $safeLogEntry;
|
|
|
|
// Keep only last 100 entries per day
|
|
if (count($existingLogs) > 100) {
|
|
$existingLogs = array_slice($existingLogs, -100);
|
|
}
|
|
|
|
update_option($logOptionKey, $existingLogs, false);
|
|
|
|
wp_send_json_success(['logged' => true]);
|
|
}
|
|
|
|
/**
|
|
* Add HVAC-specific body classes
|
|
*
|
|
* @param array $classes Body classes
|
|
* @return array Modified body classes
|
|
*/
|
|
public function add_hvac_body_classes($classes) {
|
|
// Check if we're on a plugin page
|
|
if (defined('HVAC_IN_PAGE_TEMPLATE') && HVAC_IN_PAGE_TEMPLATE) {
|
|
$classes[] = 'hvac-page';
|
|
$classes[] = 'hvac-plugin-active';
|
|
|
|
// Add solid header class to prevent transparency
|
|
$classes[] = 'ast-header-without-transparency';
|
|
$classes[] = 'header-main-layout-standard';
|
|
|
|
// Add Astra full-width layout classes
|
|
$classes[] = 'ast-no-sidebar';
|
|
$classes[] = 'single';
|
|
$classes[] = 'ast-single-post';
|
|
$classes[] = 'ast-full-width-layout';
|
|
}
|
|
|
|
// Check URL for plugin pages
|
|
$current_path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
|
|
if (strpos($current_path, 'trainer/') !== false || strpos($current_path, 'master-trainer/') !== false) {
|
|
$classes[] = 'hvac-trainer-page';
|
|
$classes[] = 'ast-header-without-transparency';
|
|
|
|
// Ensure full-width for all trainer pages
|
|
$classes[] = 'ast-no-sidebar';
|
|
$classes[] = 'ast-full-width-layout';
|
|
}
|
|
|
|
// Add specific page classes
|
|
if (is_page_template('page-trainer-dashboard.php')) {
|
|
$classes[] = 'hvac-trainer-dashboard';
|
|
}
|
|
if (is_page_template('page-certificate-reports.php')) {
|
|
$classes[] = 'hvac-certificate-reports';
|
|
}
|
|
if (is_page_template('page-trainer-profile.php')) {
|
|
$classes[] = 'hvac-trainer-profile';
|
|
}
|
|
|
|
// Remove sidebar classes using modern array syntax
|
|
$sidebarClasses = [
|
|
'ast-right-sidebar',
|
|
'ast-left-sidebar',
|
|
'ast-separate-container'
|
|
];
|
|
|
|
$classes = array_diff($classes, $sidebarClasses);
|
|
|
|
return $classes;
|
|
}
|
|
|
|
/**
|
|
* Add HVAC-specific post classes with type safety
|
|
*
|
|
* @param string[] $classes Post classes array
|
|
* @return string[] Modified post classes
|
|
*/
|
|
public function addHvacPostClasses(array $classes): array {
|
|
global $post;
|
|
|
|
if ($post instanceof WP_Post && str_contains($post->post_name, 'trainer')) {
|
|
$classes[] = 'hvac-post';
|
|
}
|
|
|
|
return $classes;
|
|
}
|
|
|
|
/**
|
|
* Force full-width layout for HVAC pages in Astra theme
|
|
*
|
|
* @param string $layout Current layout
|
|
* @return string Modified layout
|
|
*/
|
|
public function force_full_width_layout($layout) {
|
|
// Check if we're on a plugin page
|
|
if (defined('HVAC_IN_PAGE_TEMPLATE') && HVAC_IN_PAGE_TEMPLATE) {
|
|
return 'no-sidebar';
|
|
}
|
|
|
|
// Check URL for plugin pages
|
|
$current_path = trim(parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH), '/');
|
|
if (strpos($current_path, 'trainer/') !== false || strpos($current_path, 'master-trainer/') !== false) {
|
|
return 'no-sidebar';
|
|
}
|
|
|
|
// Check by page template with modern string functions
|
|
if (is_page_template()) {
|
|
$template = get_page_template_slug();
|
|
$hvacTemplates = [
|
|
'page-trainer',
|
|
'page-master',
|
|
'page-certificate',
|
|
'page-generate',
|
|
'page-manage-event'
|
|
];
|
|
|
|
foreach ($hvacTemplates as $hvacTemplate) {
|
|
if (str_contains($template, $hvacTemplate)) {
|
|
return 'no-sidebar';
|
|
}
|
|
}
|
|
}
|
|
|
|
return $layout;
|
|
}
|
|
|
|
/**
|
|
* Check for manual page update request with security validation
|
|
*
|
|
* Handles admin-triggered page updates with proper authorization.
|
|
*/
|
|
public function checkForPageUpdates(): void {
|
|
// Only allow admins to trigger updates
|
|
if (!current_user_can('manage_options')) {
|
|
return;
|
|
}
|
|
|
|
// Check for update trigger with type safety
|
|
$updateRequest = $_GET['hvac_update_pages'] ?? '';
|
|
|
|
if ($updateRequest === 'true') {
|
|
$pageManagerFile = HVAC_PLUGIN_DIR . 'includes/class-hvac-page-manager.php';
|
|
|
|
if (!file_exists($pageManagerFile)) {
|
|
error_log('HVAC Page Manager file not found');
|
|
return;
|
|
}
|
|
|
|
require_once $pageManagerFile;
|
|
|
|
try {
|
|
// Update all page layouts and templates
|
|
HVAC_Page_Manager::update_existing_page_layouts();
|
|
|
|
// Add admin notice using anonymous function
|
|
add_action('admin_notices', static function(): void {
|
|
echo '<div class="notice notice-success is-dismissible">';
|
|
echo '<p>HVAC pages have been updated with correct templates and layouts.</p>';
|
|
echo '</div>';
|
|
});
|
|
|
|
// Clean redirect
|
|
$redirectUrl = remove_query_arg('hvac_update_pages');
|
|
wp_safe_redirect($redirectUrl);
|
|
exit;
|
|
|
|
} catch (Exception $e) {
|
|
error_log('Page update failed: ' . $e->getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if pages need update after activation
|
|
*
|
|
* Handles post-activation page updates with proper error handling.
|
|
*/
|
|
public function checkPageUpdateFlag(): void {
|
|
if (!get_option('hvac_pages_need_update', false)) {
|
|
return;
|
|
}
|
|
|
|
$pageManagerFile = HVAC_PLUGIN_DIR . 'includes/class-hvac-page-manager.php';
|
|
|
|
if (!file_exists($pageManagerFile)) {
|
|
error_log('HVAC Page Manager file not found during activation update');
|
|
return;
|
|
}
|
|
|
|
require_once $pageManagerFile;
|
|
|
|
try {
|
|
// Update all page layouts and templates
|
|
HVAC_Page_Manager::update_existing_page_layouts();
|
|
|
|
// Remove the update flag
|
|
delete_option('hvac_pages_need_update');
|
|
|
|
// Log successful update
|
|
if (class_exists('HVAC_Logger')) {
|
|
HVAC_Logger::info('Pages updated after activation', 'HVAC Plugin');
|
|
}
|
|
|
|
} catch (Exception $e) {
|
|
error_log('Post-activation page update failed: ' . $e->getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load core files with error handling
|
|
*
|
|
* @param string[] $files Array of file paths relative to plugin directory
|
|
* @return Generator<string, bool> File path => loaded status
|
|
*/
|
|
private function loadCoreFiles(array $files): Generator {
|
|
foreach ($files as $file) {
|
|
$filePath = HVAC_PLUGIN_DIR . $file;
|
|
|
|
if (file_exists($filePath)) {
|
|
require_once $filePath;
|
|
yield $file => true;
|
|
} else {
|
|
yield $file => false;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Load feature files with memory-efficient generator
|
|
*
|
|
* @param string[] $files Array of file paths
|
|
* @return Generator<string, string> File path => load status
|
|
*/
|
|
private function loadFeatureFiles(array $files): Generator {
|
|
foreach ($files as $file) {
|
|
$filePath = HVAC_PLUGIN_DIR . 'includes/' . $file;
|
|
|
|
if (file_exists($filePath)) {
|
|
try {
|
|
require_once $filePath;
|
|
yield $file => 'loaded';
|
|
} catch (Exception $e) {
|
|
error_log("Failed to load feature file {$file}: " . $e->getMessage());
|
|
yield $file => 'error';
|
|
}
|
|
} else {
|
|
yield $file => 'missing';
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Include legacy files for backward compatibility
|
|
*
|
|
* Loads legacy function files with proper error handling.
|
|
*/
|
|
private function includeLegacyFiles(): void {
|
|
$legacyFiles = [
|
|
'includes/hvac-ce-functions.php',
|
|
'includes/hvac-ce-admin.php',
|
|
'includes/hvac-ce-certificates.php'
|
|
];
|
|
|
|
foreach ($legacyFiles as $file) {
|
|
$filePath = HVAC_PLUGIN_DIR . $file;
|
|
|
|
if (file_exists($filePath)) {
|
|
try {
|
|
require_once $filePath;
|
|
$this->componentStatus["legacy_{$file}"] = true;
|
|
} catch (Exception $e) {
|
|
error_log("Failed to load legacy file {$file}: " . $e->getMessage());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get component initialization status
|
|
*
|
|
* @return ArrayObject<string, bool> Component status map
|
|
*/
|
|
public function getComponentStatus(): ArrayObject {
|
|
return $this->componentStatus;
|
|
}
|
|
|
|
/**
|
|
* Check if plugin is fully initialized
|
|
*/
|
|
public function isInitialized(): bool {
|
|
return $this->isInitialized;
|
|
}
|
|
}
|
|
|