Some checks failed
		
		
	
	HVAC Plugin CI/CD Pipeline / Code Quality & Standards (push) Has been cancelled
				
			HVAC Plugin CI/CD Pipeline / Unit Tests (push) Has been cancelled
				
			Security Monitoring & Compliance / Secrets & Credential Scan (push) Has been cancelled
				
			Security Monitoring & Compliance / WordPress Security Analysis (push) Has been cancelled
				
			HVAC Plugin CI/CD Pipeline / Security Analysis (push) Has been cancelled
				
			HVAC Plugin CI/CD Pipeline / Integration Tests (push) Has been cancelled
				
			Security Monitoring & Compliance / Dependency Vulnerability Scan (push) Has been cancelled
				
			Security Monitoring & Compliance / Static Code Security Analysis (push) Has been cancelled
				
			Security Monitoring & Compliance / Security Compliance Validation (push) Has been cancelled
				
			HVAC Plugin CI/CD Pipeline / Deploy to Staging (push) Has been cancelled
				
			HVAC Plugin CI/CD Pipeline / Deploy to Production (push) Has been cancelled
				
			HVAC Plugin CI/CD Pipeline / Notification (push) Has been cancelled
				
			Security Monitoring & Compliance / Security Summary Report (push) Has been cancelled
				
			Security Monitoring & Compliance / Security Team Notification (push) Has been cancelled
				
			- Deploy 6 simultaneous WordPress specialized agents using sequential thinking and Zen MCP - Resolve all critical issues: permissions, jQuery dependencies, CDN mapping, security vulnerabilities - Implement bulletproof jQuery loading system with WordPress hook timing fixes - Create professional MapGeo Safety system with CDN health monitoring and fallback UI - Fix privilege escalation vulnerability with capability-based authorization - Add complete announcement admin system with modal forms and AJAX handling - Enhance import/export functionality (54 trainers successfully exported) - Achieve 100% operational master trainer functionality verified via MCP Playwright E2E testing 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			739 lines
		
	
	
		
			No EOL
		
	
	
		
			27 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			739 lines
		
	
	
		
			No EOL
		
	
	
		
			27 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * HVAC Bundled Assets Manager
 | |
|  * 
 | |
|  * Modern asset management system using webpack-generated bundles
 | |
|  * Replaces individual script loading with optimized bundles
 | |
|  *
 | |
|  * @package HVAC_Community_Events
 | |
|  * @since 2.0.0
 | |
|  */
 | |
| 
 | |
| if (!defined('ABSPATH')) {
 | |
|     exit;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * HVAC Bundled Assets Manager
 | |
|  */
 | |
| class HVAC_Bundled_Assets {
 | |
|     
 | |
|     /**
 | |
|      * Instance
 | |
|      * 
 | |
|      * @var HVAC_Bundled_Assets
 | |
|      */
 | |
|     private static $instance = null;
 | |
|     
 | |
|     /**
 | |
|      * Asset version for cache busting
 | |
|      * 
 | |
|      * @var string
 | |
|      */
 | |
|     private $version;
 | |
|     
 | |
|     /**
 | |
|      * Bundle manifest
 | |
|      * 
 | |
|      * @var array
 | |
|      */
 | |
|     private $manifest = array();
 | |
|     
 | |
|     /**
 | |
|      * Get instance
 | |
|      * 
 | |
|      * @return HVAC_Bundled_Assets
 | |
|      */
 | |
|     public static function instance() {
 | |
|         if (null === self::$instance) {
 | |
|             self::$instance = new self();
 | |
|         }
 | |
|         return self::$instance;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Constructor
 | |
|      */
 | |
|     private function __construct() {
 | |
|         $this->version = HVAC_PLUGIN_VERSION;
 | |
|         $this->load_manifest();
 | |
|         $this->init_hooks();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Load webpack manifest with integrity validation
 | |
|      */
 | |
|     private function load_manifest() {
 | |
|         $manifest_path = HVAC_PLUGIN_DIR . 'assets/js/dist/manifest.json';
 | |
|         if (!file_exists($manifest_path)) {
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         // Add integrity validation
 | |
|         $manifest_content = file_get_contents($manifest_path);
 | |
|         if ($manifest_content === false) {
 | |
|             error_log('HVAC: Failed to read manifest file');
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         $manifest_hash = hash('sha256', $manifest_content);
 | |
|         $expected_hash = get_option('hvac_manifest_hash');
 | |
|         
 | |
|         // Validate manifest integrity if hash exists
 | |
|         if ($expected_hash && $expected_hash !== $manifest_hash) {
 | |
|             error_log('HVAC: Manifest integrity check failed - possible tampering detected');
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         $decoded_manifest = json_decode($manifest_content, true);
 | |
|         if (json_last_error() !== JSON_ERROR_NONE) {
 | |
|             error_log('HVAC: Invalid manifest JSON - ' . json_last_error_msg());
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         // Validate manifest structure
 | |
|         if (!is_array($decoded_manifest)) {
 | |
|             error_log('HVAC: Manifest is not a valid array');
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         // Store hash for future validation
 | |
|         update_option('hvac_manifest_hash', $manifest_hash);
 | |
|         
 | |
|         $this->manifest = $decoded_manifest;
 | |
|         return true;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Initialize hooks
 | |
|      */
 | |
|     private function init_hooks() {
 | |
|         // CRITICAL FIX: Only initialize bundled assets if NOT using legacy Scripts_Styles system
 | |
|         // This prevents dual script loading that causes jQuery dependency conflicts
 | |
|         if (!$this->should_use_legacy_scripts_system()) {
 | |
|             add_action('wp_enqueue_scripts', array($this, 'enqueue_bundled_assets'), 5); // Load early
 | |
|             add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_bundled_assets'), 5);
 | |
|             add_action('wp_head', array($this, 'add_bundle_preload_hints'), 5);
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Check if we should use legacy Scripts_Styles system instead of bundles
 | |
|      * CRITICAL: Prevents dual script loading conflicts
 | |
|      * 
 | |
|      * @return bool
 | |
|      */
 | |
|     private function should_use_legacy_scripts_system() {
 | |
|         // Force legacy mode if HVAC_FORCE_LEGACY_SCRIPTS is defined
 | |
|         if (defined('HVAC_FORCE_LEGACY_SCRIPTS') && HVAC_FORCE_LEGACY_SCRIPTS) {
 | |
|             return true;
 | |
|         }
 | |
|         
 | |
|         // Use legacy system in development by default (safer for debugging)
 | |
|         if (defined('WP_DEBUG') && WP_DEBUG && (!defined('HVAC_USE_BUNDLES') || !HVAC_USE_BUNDLES)) {
 | |
|             return true;
 | |
|         }
 | |
|         
 | |
|         // Safari browsers should use legacy system to prevent cascade issues
 | |
|         if (class_exists('HVAC_Browser_Detection')) {
 | |
|             $browser_detection = HVAC_Browser_Detection::instance();
 | |
|             if ($browser_detection->is_safari_browser()) {
 | |
|                 error_log('HVAC Bundled Assets: Using legacy scripts for Safari compatibility');
 | |
|                 return true;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return false;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Check if we should use bundled assets
 | |
|      * 
 | |
|      * @return bool
 | |
|      */
 | |
|     private function should_use_bundled_assets() {
 | |
|         // Don't use bundles if we should use legacy system
 | |
|         if ($this->should_use_legacy_scripts_system()) {
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         // Don't use bundles if forced to legacy mode
 | |
|         if ($this->should_use_legacy_fallback()) {
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         // Don't use bundles if manifest is empty (loading failed)
 | |
|         if (empty($this->manifest)) {
 | |
|             error_log('HVAC: Manifest is empty, falling back to legacy assets');
 | |
|             return false;
 | |
|         }
 | |
|         
 | |
|         // Use bundled assets in production or if HVAC_USE_BUNDLES is true
 | |
|         return (!defined('WP_DEBUG') || !WP_DEBUG) || 
 | |
|                (defined('HVAC_USE_BUNDLES') && HVAC_USE_BUNDLES);
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Check if current page needs HVAC assets
 | |
|      * 
 | |
|      * @return bool
 | |
|      */
 | |
|     private function is_plugin_page() {
 | |
|         // Check if we're in a page template context
 | |
|         if (defined('HVAC_IN_PAGE_TEMPLATE') && HVAC_IN_PAGE_TEMPLATE) {
 | |
|             return true;
 | |
|         }
 | |
|         
 | |
|         // Check using template loader if available
 | |
|         if (class_exists('HVAC_Template_Loader')) {
 | |
|             return HVAC_Template_Loader::is_plugin_template();
 | |
|         }
 | |
|         
 | |
|         return false;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Enqueue bundled frontend assets
 | |
|      */
 | |
|     public function enqueue_bundled_assets() {
 | |
|         if (!$this->is_plugin_page() || !$this->should_use_bundled_assets()) {
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         $browser_detection = HVAC_Browser_Detection::instance();
 | |
|         
 | |
|         // Always load core bundle on plugin pages
 | |
|         $this->enqueue_bundle('hvac-core');
 | |
|         
 | |
|         // Safari compatibility bundle for Safari browsers
 | |
|         if ($browser_detection->is_safari_browser()) {
 | |
|             $this->enqueue_bundle('hvac-safari-compat');
 | |
|         }
 | |
|         
 | |
|         // Context-specific bundles based on page type
 | |
|         if ($this->is_dashboard_page()) {
 | |
|             $this->enqueue_bundle('hvac-dashboard');
 | |
|         }
 | |
|         
 | |
|         if ($this->is_certificate_page()) {
 | |
|             $this->enqueue_bundle('hvac-certificates');
 | |
|         }
 | |
|         
 | |
|         if ($this->is_master_trainer_page()) {
 | |
|             $this->enqueue_bundle('hvac-master');
 | |
|         }
 | |
|         
 | |
|         if ($this->is_trainer_page()) {
 | |
|             $this->enqueue_bundle('hvac-trainer');
 | |
|         }
 | |
|         
 | |
|         if ($this->is_event_page()) {
 | |
|             $this->enqueue_bundle('hvac-events');
 | |
|         }
 | |
|         
 | |
|         // Localization for core bundle
 | |
|         $this->localize_core_bundle();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Enqueue admin bundled assets
 | |
|      */
 | |
|     public function enqueue_admin_bundled_assets() {
 | |
|         if (!$this->should_use_bundled_assets()) {
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         // Admin bundle for WordPress admin areas
 | |
|         if ($this->is_hvac_admin_page()) {
 | |
|             $this->enqueue_bundle('hvac-admin');
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Enqueue a specific bundle with validation and graceful degradation
 | |
|      * 
 | |
|      * @param string $bundle_name
 | |
|      */
 | |
|     private function enqueue_bundle($bundle_name) {
 | |
|         $js_file = $this->get_bundle_file($bundle_name, 'js');
 | |
|         $css_file = $this->get_bundle_file($bundle_name, 'css');
 | |
|         
 | |
|         // Validate and enqueue JavaScript bundle with security and performance monitoring
 | |
|         if ($js_file) {
 | |
|             $js_path = HVAC_PLUGIN_DIR . 'assets/js/dist/' . $js_file;
 | |
|             if (file_exists($js_path)) {
 | |
|                 // Security: Validate file size is reasonable (prevent potential DoS)
 | |
|                 $file_size = filesize($js_path);
 | |
|                 if ($file_size > 1024 * 1024) { // 1MB limit
 | |
|                     error_log("[HVAC] Bundle {$js_file} exceeds size limit ({$file_size} bytes) - falling back");
 | |
|                     $this->enqueue_legacy_fallback($bundle_name);
 | |
|                     return;
 | |
|                 }
 | |
|                 
 | |
|                 // Security: Validate filename contains only safe characters
 | |
|                 if (!preg_match('/^[a-zA-Z0-9._-]+$/', $js_file)) {
 | |
|                     error_log("[HVAC] Invalid bundle filename: {$js_file} - falling back");
 | |
|                     $this->enqueue_legacy_fallback($bundle_name);
 | |
|                     return;
 | |
|                 }
 | |
|                 
 | |
|                 $version = filemtime($js_path); // Use file modification time for cache busting
 | |
|                 
 | |
|                 // CRITICAL FIX: Ensure jQuery is always loaded first
 | |
|                 wp_enqueue_script('jquery');
 | |
|                 
 | |
|                 wp_enqueue_script(
 | |
|                     $bundle_name,
 | |
|                     HVAC_PLUGIN_URL . 'assets/js/dist/' . $js_file,
 | |
|                     array('jquery'),
 | |
|                     $version,
 | |
|                     true
 | |
|                 );
 | |
|                 
 | |
|                 // Add performance monitoring attributes
 | |
|                 $this->add_bundle_performance_monitoring($bundle_name);
 | |
|                 
 | |
|                 if (defined('WP_DEBUG') && WP_DEBUG) {
 | |
|                     error_log('[HVAC Bundled Assets] Loaded JS bundle: ' . $bundle_name . ' (' . round($file_size / 1024, 1) . 'KB)');
 | |
|                 }
 | |
|             } else {
 | |
|                 error_log("[HVAC] Missing JS bundle: {$js_file} - falling back to legacy scripts");
 | |
|                 $this->enqueue_legacy_fallback($bundle_name);
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         // Validate and enqueue CSS bundle if exists
 | |
|         if ($css_file) {
 | |
|             $css_path = HVAC_PLUGIN_DIR . 'assets/js/dist/' . $css_file;
 | |
|             if (file_exists($css_path)) {
 | |
|                 wp_enqueue_style(
 | |
|                     $bundle_name . '-style',
 | |
|                     HVAC_PLUGIN_URL . 'assets/js/dist/' . $css_file,
 | |
|                     array(),
 | |
|                     filemtime($css_path)
 | |
|                 );
 | |
|                 
 | |
|                 if (defined('WP_DEBUG') && WP_DEBUG) {
 | |
|                     error_log('[HVAC Bundled Assets] Loaded CSS bundle: ' . $bundle_name);
 | |
|                 }
 | |
|             } else {
 | |
|                 if (defined('WP_DEBUG') && WP_DEBUG) {
 | |
|                     error_log("[HVAC] Missing CSS bundle: {$css_file}");
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get bundle file path from manifest with chunk support
 | |
|      * 
 | |
|      * @param string $bundle_name
 | |
|      * @param string $type js|css
 | |
|      * @return string|null
 | |
|      */
 | |
|     private function get_bundle_file($bundle_name, $type = 'js') {
 | |
|         $key = $bundle_name . '.' . $type;
 | |
|         
 | |
|         if (isset($this->manifest[$key])) {
 | |
|             return $this->manifest[$key];
 | |
|         }
 | |
|         
 | |
|         // Check for chunk files (lazy-loaded components)
 | |
|         $chunk_key = $bundle_name . '.chunk.' . $type;
 | |
|         if (isset($this->manifest[$chunk_key])) {
 | |
|             return $this->manifest[$chunk_key];
 | |
|         }
 | |
|         
 | |
|         // Fallback to expected filename pattern
 | |
|         $suffix = (defined('WP_DEBUG') && WP_DEBUG) ? '' : '.min';
 | |
|         return $bundle_name . '.bundle' . $suffix . '.' . $type;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Get all chunk files for a bundle (for preloading)
 | |
|      * 
 | |
|      * @param string $bundle_name
 | |
|      * @return array
 | |
|      */
 | |
|     private function get_bundle_chunks($bundle_name) {
 | |
|         $chunks = [];
 | |
|         
 | |
|         // Look for all chunk files related to this bundle
 | |
|         foreach ($this->manifest as $key => $filename) {
 | |
|             // Match chunk files like "trainer-profile.chunk.js", "event-editing.chunk.js"
 | |
|             if (preg_match("/({$bundle_name}-.+|.+-{$bundle_name})\.chunk\.(js|css)$/", $key)) {
 | |
|                 $chunks[$key] = $filename;
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         return $chunks;
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Fallback to legacy individual scripts when bundles fail
 | |
|      * 
 | |
|      * @param string $bundle_name
 | |
|      */
 | |
|     private function enqueue_legacy_fallback($bundle_name) {
 | |
|         // Check if we're already in too many error scenarios
 | |
|         if ($this->should_use_legacy_fallback()) {
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         // Increment error count
 | |
|         $error_count = get_transient('hvac_bundle_errors') ?: 0;
 | |
|         set_transient('hvac_bundle_errors', $error_count + 1, HOUR_IN_SECONDS);
 | |
|         
 | |
|         // Map bundle names to legacy script methods
 | |
|         $legacy_map = array(
 | |
|             'hvac-core' => 'enqueue_core_scripts',
 | |
|             'hvac-dashboard' => 'enqueue_dashboard_scripts',
 | |
|             'hvac-certificates' => 'enqueue_certificate_scripts',
 | |
|             'hvac-master' => 'enqueue_master_trainer_scripts',
 | |
|             'hvac-trainer' => 'enqueue_trainer_scripts',
 | |
|             'hvac-events' => 'enqueue_event_scripts',
 | |
|             'hvac-admin' => 'enqueue_admin_scripts'
 | |
|         );
 | |
|         
 | |
|         if (isset($legacy_map[$bundle_name]) && class_exists('HVAC_Scripts_Styles')) {
 | |
|             $scripts_instance = HVAC_Scripts_Styles::instance();
 | |
|             $method = $legacy_map[$bundle_name];
 | |
|             
 | |
|             if (method_exists($scripts_instance, $method)) {
 | |
|                 $scripts_instance->$method();
 | |
|                 error_log("[HVAC] Fallback activated for bundle: {$bundle_name}");
 | |
|             }
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Check if we should use legacy fallback due to too many errors
 | |
|      * 
 | |
|      * @return bool
 | |
|      */
 | |
|     private function should_use_legacy_fallback() {
 | |
|         $error_count = get_transient('hvac_bundle_errors');
 | |
|         if ($error_count > 5) {
 | |
|             // Too many errors, use legacy for 1 hour
 | |
|             set_transient('hvac_force_legacy', true, HOUR_IN_SECONDS);
 | |
|             return true;
 | |
|         }
 | |
|         
 | |
|         return get_transient('hvac_force_legacy');
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Localize core bundle with WordPress data and security monitoring
 | |
|      */
 | |
|     private function localize_core_bundle() {
 | |
|         wp_localize_script('hvac-core', 'hvacBundleData', array(
 | |
|             'ajax_url' => admin_url('admin-ajax.php'),
 | |
|             'nonce' => wp_create_nonce('hvac_bundle_nonce'),
 | |
|             'rest_url' => rest_url('hvac/v1/'),
 | |
|             'current_user_id' => get_current_user_id(),
 | |
|             'is_safari' => HVAC_Browser_Detection::instance()->is_safari_browser(),
 | |
|             'debug' => defined('WP_DEBUG') && WP_DEBUG,
 | |
|             'version' => $this->version,
 | |
|             // Security monitoring configuration
 | |
|             'security' => array(
 | |
|                 'report_errors' => true,
 | |
|                 'error_endpoint' => rest_url('hvac/v1/bundle-errors'),
 | |
|                 'performance_monitoring' => !defined('HVAC_DISABLE_PERF_MONITORING'),
 | |
|                 'max_load_time' => 5000, // 5 seconds
 | |
|                 'retry_attempts' => 2
 | |
|             )
 | |
|         ));
 | |
|         
 | |
|         // Add client-side error detection and performance monitoring
 | |
|         $this->add_client_side_monitoring();
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Add client-side error detection and performance monitoring
 | |
|      */
 | |
|     private function add_client_side_monitoring() {
 | |
|         $monitoring_script = "
 | |
|         (function() {
 | |
|             'use strict';
 | |
|             
 | |
|             var hvacSecurity = {
 | |
|                 errors: [],
 | |
|                 performance: {},
 | |
|                 
 | |
|                 // Report bundle loading errors
 | |
|                 reportError: function(error, bundle) {
 | |
|                     if (!window.hvacBundleData || !window.hvacBundleData.security.report_errors) return;
 | |
|                     
 | |
|                     this.errors.push({
 | |
|                         error: error,
 | |
|                         bundle: bundle,
 | |
|                         timestamp: Date.now(),
 | |
|                         userAgent: navigator.userAgent.substring(0, 100), // Limit length for security
 | |
|                         url: window.location.href
 | |
|                     });
 | |
|                     
 | |
|                     // Report to server if REST API available
 | |
|                     if (window.hvacBundleData.security.error_endpoint) {
 | |
|                         this.sendErrorReport();
 | |
|                     }
 | |
|                 },
 | |
|                 
 | |
|                 // Send error reports to server
 | |
|                 sendErrorReport: function() {
 | |
|                     if (this.errors.length === 0) return;
 | |
|                     
 | |
|                     fetch(window.hvacBundleData.security.error_endpoint, {
 | |
|                         method: 'POST',
 | |
|                         headers: {
 | |
|                             'Content-Type': 'application/json',
 | |
|                             'X-WP-Nonce': window.hvacBundleData.nonce
 | |
|                         },
 | |
|                         body: JSON.stringify({
 | |
|                             errors: this.errors.splice(0, 5), // Send max 5 errors at once
 | |
|                             page: window.location.pathname,
 | |
|                             version: window.hvacBundleData.version
 | |
|                         })
 | |
|                     }).catch(function(e) {
 | |
|                         console.warn('HVAC: Failed to report bundle errors', e);
 | |
|                     });
 | |
|                 },
 | |
|                 
 | |
|                 // Monitor bundle loading performance
 | |
|                 monitorPerformance: function(bundleName, startTime) {
 | |
|                     if (!window.hvacBundleData.security.performance_monitoring) return;
 | |
|                     
 | |
|                     var loadTime = Date.now() - startTime;
 | |
|                     this.performance[bundleName] = loadTime;
 | |
|                     
 | |
|                     var maxLoadTime = window.hvacBundleData.security.max_load_time || 5000;
 | |
|                     if (loadTime > maxLoadTime) {
 | |
|                         this.reportError('Bundle load time exceeded ' + maxLoadTime + 'ms (' + loadTime + 'ms)', bundleName);
 | |
|                     }
 | |
|                 }
 | |
|             };
 | |
|             
 | |
|             // Global error handler for script loading failures
 | |
|             window.addEventListener('error', function(e) {
 | |
|                 if (e.target && e.target.tagName === 'SCRIPT' && e.target.src && e.target.src.includes('hvac')) {
 | |
|                     var bundleName = e.target.src.match(/hvac-([^.]+)/) ? e.target.src.match(/hvac-([^.]+)/)[1] : 'unknown';
 | |
|                     hvacSecurity.reportError('Script load failed: ' + e.message, 'hvac-' + bundleName);
 | |
|                 }
 | |
|             });
 | |
|             
 | |
|             // Attach to global scope for bundle monitoring
 | |
|             window.hvacSecurity = hvacSecurity;
 | |
|             
 | |
|             // Auto-report errors every 30 seconds if any exist
 | |
|             setInterval(function() {
 | |
|                 if (hvacSecurity.errors.length > 0) {
 | |
|                     hvacSecurity.sendErrorReport();
 | |
|                 }
 | |
|             }, 30000);
 | |
|         })();
 | |
|         ";
 | |
|         
 | |
|         wp_add_inline_script('hvac-core', $monitoring_script, 'before');
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Add bundle preload hints for critical resources
 | |
|      */
 | |
|     public function add_bundle_preload_hints() {
 | |
|         if (!$this->is_plugin_page() || !$this->should_use_bundled_assets()) {
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         // Always preload core bundle on plugin pages
 | |
|         $this->add_preload_hint('hvac-core', 'script');
 | |
|         
 | |
|         // Context-specific preloading for critical bundles
 | |
|         if ($this->is_dashboard_page()) {
 | |
|             $this->add_preload_hint('hvac-dashboard', 'script');
 | |
|         }
 | |
|         
 | |
|         if ($this->is_master_trainer_page()) {
 | |
|             $this->add_preload_hint('hvac-master', 'script');
 | |
|         }
 | |
|         
 | |
|         // Safari compatibility bundle for Safari browsers
 | |
|         $browser_detection = HVAC_Browser_Detection::instance();
 | |
|         if ($browser_detection->is_safari_browser()) {
 | |
|             $this->add_preload_hint('hvac-safari-compat', 'script');
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Add individual preload hint with security validation
 | |
|      * 
 | |
|      * @param string $bundle_name
 | |
|      * @param string $type script|style
 | |
|      */
 | |
|     private function add_preload_hint($bundle_name, $type) {
 | |
|         $file_type = $type === 'script' ? 'js' : 'css';
 | |
|         $bundle_file = $this->get_bundle_file($bundle_name, $file_type);
 | |
|         
 | |
|         if (!$bundle_file) {
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         // Validate file exists and is safe
 | |
|         $file_path = HVAC_PLUGIN_DIR . 'assets/js/dist/' . $bundle_file;
 | |
|         if (!file_exists($file_path)) {
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         // Security: Validate filename contains only safe characters
 | |
|         if (!preg_match('/^[a-zA-Z0-9._-]+$/', $bundle_file)) {
 | |
|             error_log('HVAC: Invalid bundle filename for preload: ' . $bundle_file);
 | |
|             return;
 | |
|         }
 | |
|         
 | |
|         $bundle_url = esc_url(HVAC_PLUGIN_URL . 'assets/js/dist/' . $bundle_file);
 | |
|         $as_attribute = $type === 'script' ? 'script' : 'style';
 | |
|         
 | |
|         // Add integrity hash for additional security
 | |
|         $integrity_hash = base64_encode(hash('sha384', file_get_contents($file_path), true));
 | |
|         
 | |
|         echo '<link rel="preload" href="' . $bundle_url . '" as="' . $as_attribute . '" integrity="sha384-' . $integrity_hash . '" crossorigin="anonymous">' . "\n";
 | |
|         
 | |
|         if (defined('WP_DEBUG') && WP_DEBUG) {
 | |
|             error_log("[HVAC Bundled Assets] Preload hint added for: {$bundle_name}.{$file_type}");
 | |
|         }
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Add performance monitoring attributes to bundle scripts
 | |
|      * 
 | |
|      * @param string $bundle_name
 | |
|      */
 | |
|     private function add_bundle_performance_monitoring($bundle_name) {
 | |
|         // Add inline script to monitor bundle loading performance
 | |
|         $monitoring_script = "
 | |
|         (function() {
 | |
|             var startTime = performance.now();
 | |
|             var bundleName = '{$bundle_name}';
 | |
|             
 | |
|             // Monitor when this script finishes loading
 | |
|             if (window.hvacSecurity && window.hvacSecurity.monitorPerformance) {
 | |
|                 document.addEventListener('DOMContentLoaded', function() {
 | |
|                     window.hvacSecurity.monitorPerformance(bundleName, startTime);
 | |
|                 });
 | |
|             }
 | |
|             
 | |
|             // Fallback error detection if hvacSecurity not loaded
 | |
|             window.addEventListener('error', function(e) {
 | |
|                 if (e.target && e.target.src && e.target.src.includes(bundleName)) {
 | |
|                     console.error('HVAC Bundle Error: Failed to load ' + bundleName);
 | |
|                 }
 | |
|             });
 | |
|         })();
 | |
|         ";
 | |
|         
 | |
|         wp_add_inline_script($bundle_name, $monitoring_script, 'before');
 | |
|     }
 | |
|     
 | |
|     /**
 | |
|      * Page detection methods
 | |
|      */
 | |
|     private function is_dashboard_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists('HVAC_Scripts_Styles', 'instance') &&
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_dashboard_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_dashboard_page() : false;
 | |
|     }
 | |
|     
 | |
|     private function is_certificate_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists('HVAC_Scripts_Styles', 'instance') &&
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_certificate_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_certificate_page() : false;
 | |
|     }
 | |
|     
 | |
|     private function is_master_trainer_page() {
 | |
|         return $this->is_pending_approvals_page() || 
 | |
|                $this->is_master_events_page() ||
 | |
|                $this->is_import_export_page() ||
 | |
|                is_page('master-dashboard') ||
 | |
|                strpos($_SERVER['REQUEST_URI'], 'master-trainer/') !== false;
 | |
|     }
 | |
|     
 | |
|     private function is_trainer_page() {
 | |
|         return $this->is_trainer_profile_page() ||
 | |
|                $this->is_registration_page() ||
 | |
|                strpos($_SERVER['REQUEST_URI'], '/trainer/') !== false;
 | |
|     }
 | |
|     
 | |
|     private function is_event_page() {
 | |
|         return $this->is_event_manage_page() ||
 | |
|                $this->is_create_event_page() ||
 | |
|                $this->is_edit_event_page() ||
 | |
|                $this->is_organizers_page() ||
 | |
|                $this->is_venues_page();
 | |
|     }
 | |
|     
 | |
|     private function is_hvac_admin_page() {
 | |
|         $screen = get_current_screen();
 | |
|         return $screen && strpos($screen->id, 'hvac') !== false;
 | |
|     }
 | |
|     
 | |
|     // Helper methods (delegate to existing HVAC_Scripts_Styles if available)
 | |
|     private function is_pending_approvals_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_pending_approvals_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_pending_approvals_page() : false;
 | |
|     }
 | |
|     
 | |
|     private function is_master_events_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_master_events_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_master_events_page() : false;
 | |
|     }
 | |
|     
 | |
|     private function is_import_export_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_import_export_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_import_export_page() : false;
 | |
|     }
 | |
|     
 | |
|     private function is_trainer_profile_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_trainer_profile_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_trainer_profile_page() : false;
 | |
|     }
 | |
|     
 | |
|     private function is_registration_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_registration_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_registration_page() : false;
 | |
|     }
 | |
|     
 | |
|     private function is_event_manage_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_event_manage_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_event_manage_page() : false;
 | |
|     }
 | |
|     
 | |
|     private function is_create_event_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_create_event_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_create_event_page() : false;
 | |
|     }
 | |
|     
 | |
|     private function is_edit_event_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_edit_event_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_edit_event_page() : false;
 | |
|     }
 | |
|     
 | |
|     private function is_organizers_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_organizers_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_organizers_page() : false;
 | |
|     }
 | |
|     
 | |
|     private function is_venues_page() {
 | |
|         return class_exists('HVAC_Scripts_Styles') && 
 | |
|                method_exists(HVAC_Scripts_Styles::instance(), 'is_venues_page') ?
 | |
|                HVAC_Scripts_Styles::instance()->is_venues_page() : false;
 | |
|     }
 | |
| } |