HOUR_IN_SECONDS, 'display' => __('Every Hour (WP-to-HTML)', 'wp-to-html'), ); $schedules['wp_to_html_twicedaily'] = array( 'interval' => 12 * HOUR_IN_SECONDS, 'display' => __('Twice Daily (WP-to-HTML)', 'wp-to-html'), ); return $schedules; } /** * Schedule the cron event */ public static function schedule_cron() { $settings = WP_To_HTML::get_settings(); $interval = isset($settings['cron_interval']) ? $settings['cron_interval'] : 'wp_to_html_hourly'; // Don't schedule if disabled if ($interval === 'disabled') { self::unschedule_cron(); return; } // Only schedule if not already scheduled if (!wp_next_scheduled(self::CRON_HOOK)) { wp_schedule_event(time(), $interval, self::CRON_HOOK); } } /** * Unschedule the cron event */ public static function unschedule_cron() { $timestamp = wp_next_scheduled(self::CRON_HOOK); if ($timestamp) { wp_unschedule_event($timestamp, self::CRON_HOOK); } // Clear all events with this hook wp_clear_scheduled_hook(self::CRON_HOOK); } /** * Reschedule cron with new interval * * @param string $interval New interval */ public static function reschedule_cron($interval) { self::unschedule_cron(); if ($interval !== 'disabled') { wp_schedule_event(time(), $interval, self::CRON_HOOK); } } /** * Run the scheduled regeneration */ public function run_scheduled_regeneration() { $settings = WP_To_HTML::get_settings(); // Check if plugin is enabled if (!$settings['enabled']) { return; } $generator = WP_To_HTML_Generator::get_instance(); $stale_posts = $this->get_stale_posts(); $total = count($stale_posts); // Set initial status self::set_regeneration_status(array( 'status' => 'running', 'source' => 'cron', 'started' => time(), 'total' => $total, 'processed' => 0, 'converted' => 0, 'skipped' => 0, 'errors' => 0, )); $converted = 0; $errors = 0; foreach ($stale_posts as $index => $post_id) { $result = $generator->generate($post_id); if (is_wp_error($result)) { $errors++; } else { $converted++; } // Update status periodically (every 5 pages or at the end) if (($index + 1) % 5 === 0 || ($index + 1) === $total) { self::set_regeneration_status(array( 'status' => 'running', 'source' => 'cron', 'started' => time(), 'total' => $total, 'processed' => $index + 1, 'converted' => $converted, 'skipped' => 0, 'errors' => $errors, )); } } // Mark complete self::set_regeneration_status(array( 'status' => 'complete', 'source' => 'cron', 'completed' => time(), 'total' => $total, 'processed' => $total, 'converted' => $converted, 'skipped' => 0, 'errors' => $errors, )); // Log the regeneration update_option('wp_to_html_last_cron_run', array( 'time' => current_time('mysql'), 'timestamp' => time(), 'regenerated' => $converted, )); } /** * Set regeneration status transient * * @param array $status Status data */ public static function set_regeneration_status($status) { set_transient('wp_to_html_regeneration_status', $status, 5 * MINUTE_IN_SECONDS); } /** * Get regeneration status * * @return array|false Status data or false if not set */ public static function get_regeneration_status() { return get_transient('wp_to_html_regeneration_status'); } /** * Clear regeneration status */ public static function clear_regeneration_status() { delete_transient('wp_to_html_regeneration_status'); } /** * Get posts that need regeneration * * @return array Array of post IDs */ private function get_stale_posts() { $stale_posts = array(); $metadata_dir = WP_TO_HTML_CACHE_DIR . '.metadata/'; if (!file_exists($metadata_dir)) { return $stale_posts; } // Scan metadata directory for cached posts $metadata_files = glob($metadata_dir . '*.json'); foreach ($metadata_files as $metadata_file) { $metadata = json_decode(file_get_contents($metadata_file), true); if (!$metadata || !isset($metadata['post_id'])) { continue; } $post_id = $metadata['post_id']; $post = get_post($post_id); // Skip if post no longer exists if (!$post) { continue; } // Check if post was modified after cache was generated $post_modified = strtotime($post->post_modified); $cache_generated = isset($metadata['generated_timestamp']) ? $metadata['generated_timestamp'] : 0; if ($post_modified > $cache_generated) { $stale_posts[] = $post_id; } } return $stale_posts; } /** * Get the next scheduled run time * * @return int|false Timestamp or false if not scheduled */ public static function get_next_run() { return wp_next_scheduled(self::CRON_HOOK); } /** * Get the last cron run info * * @return array|false */ public static function get_last_run() { return get_option('wp_to_html_last_cron_run', false); } }