First Commit
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
<?php
|
||||
/**
|
||||
* Cron Class
|
||||
*
|
||||
* Handles scheduled cache regeneration for stale pages.
|
||||
*/
|
||||
|
||||
// Prevent direct access
|
||||
if (!defined('ABSPATH')) {
|
||||
exit;
|
||||
}
|
||||
|
||||
class WP_To_HTML_Cron {
|
||||
|
||||
/**
|
||||
* Single instance
|
||||
*/
|
||||
private static $instance = null;
|
||||
|
||||
/**
|
||||
* Cron hook name
|
||||
*/
|
||||
const CRON_HOOK = 'wp_to_html_scheduled_regeneration';
|
||||
|
||||
/**
|
||||
* Get singleton instance
|
||||
*/
|
||||
public static function get_instance() {
|
||||
if (null === self::$instance) {
|
||||
self::$instance = new self();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
private function __construct() {
|
||||
// Register the cron action
|
||||
add_action(self::CRON_HOOK, array($this, 'run_scheduled_regeneration'));
|
||||
|
||||
// Add custom cron schedules
|
||||
add_filter('cron_schedules', array($this, 'add_cron_schedules'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom cron schedules
|
||||
*
|
||||
* @param array $schedules Existing schedules
|
||||
* @return array Modified schedules
|
||||
*/
|
||||
public function add_cron_schedules($schedules) {
|
||||
$schedules['wp_to_html_hourly'] = array(
|
||||
'interval' => 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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user