cron_manager = $cron_manager ?? new Admin_Cron_Manager(); } /** * Process background posts - delegates to cron manager */ public function process_background_posts() { $this->cron_manager->process_background_posts( func_get_args() ); } /** * Execute auto trigger - delegates to cron manager */ public function execute_auto_trigger() { $this->cron_manager->execute_auto_trigger(); } /** * Auto schedule post conversion - delegates to cron manager */ public function auto_schedule_post_conversion() { $args = func_get_args(); $post_id = isset( $args[0] ) ? $args[0] : null; $post = isset( $args[1] ) ? $args[1] : null; $this->cron_manager->auto_schedule_post_conversion( $post_id, $post ); } /** * Process auto queue - delegates to cron manager */ public function process_auto_queue() { $this->cron_manager->process_auto_queue(); } /** * Check if background processing is enabled. * * @return bool True if background processing is enabled. */ public function is_background_processing_enabled() { $background_enabled = get_option( 'accessibility_audio_tts_background_enabled', '1' ); if ( '1' !== $background_enabled ) { return false; } $processing_mode = get_option( 'accessibility_audio_tts_processing_mode', 'wp_cron' ); return 'wp_cron' === $processing_mode; } /** * Get background processing status * * @return array Background processing status information */ public function get_background_status() { $status = array( 'enabled' => $this->is_background_processing_enabled(), 'next_background_run' => wp_next_scheduled( 'accessibility_audio_tts_process_background_posts' ), 'next_auto_trigger' => wp_next_scheduled( 'accessibility_audio_tts_execute_auto_trigger' ), 'next_queue_process' => wp_next_scheduled( 'accessibility_audio_tts_process_queue' ), 'auto_conversion_enabled' => get_option( 'accessibility_audio_tts_auto_conversion', false ), 'processing_mode' => get_option( 'accessibility_audio_tts_processing_mode', 'wp_cron' ), ); // Format timestamps for display. if ( $status['next_background_run'] ) { $status['next_background_run_formatted'] = gmdate( 'Y-m-d H:i:s', $status['next_background_run'] ); } if ( $status['next_auto_trigger'] ) { $status['next_auto_trigger_formatted'] = gmdate( 'Y-m-d H:i:s', $status['next_auto_trigger'] ); } if ( $status['next_queue_process'] ) { $status['next_queue_process_formatted'] = gmdate( 'Y-m-d H:i:s', $status['next_queue_process'] ); } return $status; } /** * Schedule immediate background processing. * * @param array $post_ids Optional specific post IDs to process. * @return bool Success status. */ public function schedule_immediate_processing( $post_ids = array() ) { if ( ! \Accessibility_Audio_TTS\Admin\Conversion_Processor::background_processing_enabled() ) { return false; } try { if ( empty( $post_ids ) ) { // Schedule general background processing. wp_schedule_single_event( time() + 5, 'accessibility_audio_tts_process_background_posts', array( array( 'post_ids' => array() ) ) ); accessibility_audio_tts_debug_log( 'Admin_Background_Controller: Scheduled immediate general background processing' ); } else { // Schedule specific posts. wp_schedule_single_event( time() + 5, 'accessibility_audio_tts_process_background_posts', array( array( 'post_ids' => $post_ids ) ) ); accessibility_audio_tts_debug_log( 'Admin_Background_Controller: Scheduled immediate processing for ' . count( $post_ids ) . ' posts' ); } return true; } catch ( \Exception $e ) { accessibility_audio_tts_debug_log( 'Admin_Background_Controller: Error scheduling immediate processing: ' . $e->getMessage() ); return false; } } /** * Cancel all scheduled background processing. * * @return bool Success status. */ public function cancel_all_background_processing() { try { // Cancel background posts processing. $timestamp = wp_next_scheduled( 'accessibility_audio_tts_process_background_posts' ); while ( false !== $timestamp ) { wp_unschedule_event( $timestamp, 'accessibility_audio_tts_process_background_posts' ); $timestamp = wp_next_scheduled( 'accessibility_audio_tts_process_background_posts' ); } // Cancel auto trigger. $timestamp = wp_next_scheduled( 'accessibility_audio_tts_execute_auto_trigger' ); while ( false !== $timestamp ) { wp_unschedule_event( $timestamp, 'accessibility_audio_tts_execute_auto_trigger' ); $timestamp = wp_next_scheduled( 'accessibility_audio_tts_execute_auto_trigger' ); } // Cancel queue processing. $timestamp = wp_next_scheduled( 'accessibility_audio_tts_process_queue' ); while ( false !== $timestamp ) { wp_unschedule_event( $timestamp, 'accessibility_audio_tts_process_queue' ); $timestamp = wp_next_scheduled( 'accessibility_audio_tts_process_queue' ); } accessibility_audio_tts_debug_log( 'Admin_Background_Controller: All background processing cancelled' ); return true; } catch ( \Exception $e ) { accessibility_audio_tts_debug_log( 'Admin_Background_Controller: Error cancelling background processing: ' . $e->getMessage() ); return false; } } /** * Get statistics about background processing. * * @return array Background processing statistics. */ public function get_background_statistics() { global $wpdb; try { // Get number of posts without audio. $cache_key_wo = 'accessibility_audio_tts_bg_posts_without_audio'; $posts_without_audio = wp_cache_get( $cache_key_wo, 'accessibility_audio_tts' ); if ( false === $posts_without_audio ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Aggregated admin stats (read-only; cached below) $posts_without_audio = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(p.ID) FROM {$wpdb->posts} p LEFT JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id AND pm.meta_key = %s WHERE p.post_status = %s AND p.post_type IN ('post', 'page') AND pm.meta_id IS NULL", 'accessibility_audio_tts_generated', 'publish' ) ); wp_cache_set( $cache_key_wo, $posts_without_audio, 'accessibility_audio_tts', 120 ); } // Get number of posts with audio. $cache_key_w = 'accessibility_audio_tts_bg_posts_with_audio'; $posts_with_audio = wp_cache_get( $cache_key_w, 'accessibility_audio_tts' ); if ( false === $posts_with_audio ) { // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching -- Aggregated admin stats (read-only; cached below) $posts_with_audio = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(DISTINCT p.ID) FROM {$wpdb->posts} p INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id WHERE pm.meta_key = %s AND pm.meta_value = %s AND p.post_status = %s", 'accessibility_audio_tts_generated', '1', 'publish' ) ); wp_cache_set( $cache_key_w, $posts_with_audio, 'accessibility_audio_tts', 120 ); } return array( 'posts_without_audio' => intval( $posts_without_audio ), 'posts_with_audio' => intval( $posts_with_audio ), 'total_posts' => intval( $posts_without_audio ) + intval( $posts_with_audio ), 'completion_percentage' => intval( $posts_with_audio ) > 0 ? round( ( intval( $posts_with_audio ) / ( intval( $posts_without_audio ) + intval( $posts_with_audio ) ) ) * 100, 2 ) : 0, ); } catch ( \Exception $e ) { accessibility_audio_tts_debug_log( 'Admin_Background_Controller: Error getting background statistics: ' . $e->getMessage() ); return array( 'posts_without_audio' => 0, 'posts_with_audio' => 0, 'total_posts' => 0, 'completion_percentage' => 0, ); } } }