'\Accessibility_Audio_TTS\Frontend\Controllers\Player_Controller', 'audio_controller' => '\Accessibility_Audio_TTS\Frontend\Controllers\Audio_Controller', 'api_controller' => '\Accessibility_Audio_TTS\Frontend\Controllers\API_Controller', ); foreach ( $controllers as $key => $class ) { if ( class_exists( $class ) ) { self::register_component( $key, $class ); } } self::mark_initialized( 'frontend_controllers' ); accessibility_audio_tts_debug_log( __( 'Frontend controllers initialized successfully', 'accessibility-audio-tts-text-to-speech-for-articles' ) ); } /** * Initialize public API endpoints * * Sets up public-facing API endpoints for frontend functionality. * * @return void */ private static function initialize_public_api(): void { if ( self::is_initialized( 'public_api' ) ) { return; } accessibility_audio_tts_debug_log( __( 'Initializing public API...', 'accessibility-audio-tts-text-to-speech-for-articles' ) ); // Initialize listening tracker for public use. if ( class_exists( '\Accessibility_Audio_TTS\Handlers\Listening_Tracker_Ajax' ) ) { self::register_component( 'listening_tracker', '\Accessibility_Audio_TTS\Handlers\Listening_Tracker_Ajax' ); } self::mark_initialized( 'public_api' ); accessibility_audio_tts_debug_log( __( 'Public API initialized successfully', 'accessibility-audio-tts-text-to-speech-for-articles' ) ); } /** * Enqueue frontend assets * * Called by WordPress wp_enqueue_scripts action. * * @return void */ public static function enqueue_frontend_assets(): void { // Only load assets if we have audio content on the page. if ( ! self::should_load_assets() ) { return; } try { $asset_loader = self::get_component( 'asset_loader' ); if ( method_exists( $asset_loader, 'enqueue_frontend_assets' ) ) { $asset_loader->enqueue_frontend_assets(); } } catch ( \Exception $e ) { accessibility_audio_tts_debug_log( 'Error loading frontend assets: ' . $e->getMessage() ); } } /** * Check if frontend assets should be loaded * * @return bool */ private static function should_load_assets(): bool { global $post; // Load on single posts/pages. if ( is_singular() ) { return true; } // Load on archive pages that might contain audio. if ( is_home() || is_archive() || is_search() ) { return true; } // Check for shortcode in content. if ( $post && has_shortcode( $post->post_content, 'accessibility_audio_tts_player' ) ) { return true; } return false; } /** * Register component for lazy loading * * @param string $key Component key. * @param string $class_name Class name. * @param array $args Constructor arguments. * @return void */ private static function register_component( string $key, string $class_name, array $args = array() ): void { self::$frontend_components[ $key ] = array( 'class' => $class_name, 'args' => $args, 'instance' => null, ); accessibility_audio_tts_debug_log( "Registered frontend component: {$key} -> {$class_name}" ); } /** * Register existing instance * * @param string $key Component key. * @param object $instance Instance. * @return void */ private static function register_instance( string $key, object $instance ): void { self::$frontend_components[ $key ] = array( 'class' => get_class( $instance ), 'args' => array(), 'instance' => $instance, ); accessibility_audio_tts_debug_log( "Registered frontend instance: {$key} -> " . get_class( $instance ) ); } /** * Get component instance (lazy loaded) * * @param string $key Component key. * @param string|null $class_name Class name (if not registered). * @param array $args Constructor arguments. * @throws \Exception If component not registered or class not found. * @return object Component instance. */ public static function get_component( string $key, ?string $class_name = null, array $args = array() ): object { // If not registered and class name provided, register it. if ( ! isset( self::$frontend_components[ $key ] ) && $class_name ) { self::register_component( $key, $class_name, $args ); } if ( ! isset( self::$frontend_components[ $key ] ) ) { throw new \Exception( sprintf( "Frontend component '%s' not registered", esc_html( $key ) ) ); } $component = &self::$frontend_components[ $key ]; // Lazy load instance. if ( null === $component['instance'] ) { if ( ! class_exists( $component['class'] ) ) { throw new \Exception( sprintf( "Frontend component class '%s' not found", esc_html( $component['class'] ) ) ); } // Handle singleton classes that have get_instance() method. if ( method_exists( $component['class'], 'get_instance' ) ) { $component['instance'] = $component['class']::get_instance(); } else { // Regular class instantiation. $component['instance'] = empty( $component['args'] ) ? new $component['class']() : new $component['class']( ...$component['args'] ); } accessibility_audio_tts_debug_log( "Lazy loaded frontend component: {$key}" ); } return $component['instance']; } /** * Check if component is initialized * * @param string $component Component name. * @return bool */ private static function is_initialized( string $component ): bool { return isset( self::$initialized[ $component ] ); } /** * Mark component as initialized * * @param string $component Component name. * @return void */ private static function mark_initialized( string $component ): void { self::$initialized[ $component ] = true; } /** * Handle initialization errors * * @param \Exception $e Exception. * @param string $area Area. * @return void */ private static function handle_initialization_error( \Exception $e, string $area ): void { /* translators: 1: initialization area (core/admin/frontend), 2: error message */ $msg = sprintf( __( 'CRITICAL ERROR in %1$s initialization: %2$s', 'accessibility-audio-tts-text-to-speech-for-articles' ), $area, $e->getMessage() ); accessibility_audio_tts_error_log( $msg ); add_action( 'admin_notices', function () use ( $e, $area ) { /* translators: 1: plugin area, 2: error message */ $text = sprintf( __( 'Accessibility Audio TTS %1$s Error: %2$s', 'accessibility-audio-tts-text-to-speech-for-articles' ), $area, $e->getMessage() ); ?>

count( self::$frontend_components ), 'loaded_components' => $loaded_components, 'initialized_systems' => count( self::$initialized ), 'systems' => array_keys( self::$initialized ), ); } /** * Clear frontend components (for testing) * * @return void */ public static function clear_components(): void { self::$frontend_components = array(); self::$initialized = array(); accessibility_audio_tts_debug_log( 'Frontend initializer components cleared' ); } }