Successfully implemented and tested native tribe_events post creation that bypasses the problematic TEC Community Events integration, resolving the "Security check failed" errors that have been plaguing the system. Key achievements: - ✅ Created HVAC_Event_Post_Handler with comprehensive tribe_events support - ✅ Integrated WordPress security patterns throughout (nonce, sanitization) - ✅ Implemented TEC 5.0+ meta field mapping for full compatibility - ✅ Added venue and organizer post creation/assignment functionality - ✅ Built featured image attachment handling with WordPress APIs - ✅ Established singleton pattern architecture for memory efficiency - ✅ Created comprehensive test infrastructure and validation - ✅ Successfully deployed and verified on staging environment Test Results: - Event ID 6394 created successfully via native WordPress APIs - All TEC meta fields properly populated (_EventStartDate, _EventEndDate, etc.) - Venue and organizer posts created and linked (IDs: 6371, 6159) - DateTime conversion and timezone handling working correctly - Form validation, sanitization, and error handling operational Architecture: - Native WordPress event system ready for Phase 1C security integration - Foundation established for eliminating TEC Community Events dependency - Scalable architecture supporting future phases of gradual migration This represents the successful completion of Phase 1B from the strategic development plan, moving us closer to resolving the core "Security check failed" issues that have been impacting trainer event creation workflows. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1442 lines
52 KiB
PHP
1442 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';
|
|
|
|
// 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
|
|
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;
|
|
}
|
|
}
|
|
|