Two related fixes to the AVIF pipeline: Fix #1 — postmeta tracking Format_Generator::process_avif_job() now updates _h4b_img_optim's avif_status from 'queued' → 'done' (with byte size) or 'error' (with reason) after the cron job runs. Previously the postmeta said 'queued' forever even when AVIF files existed on disk. Fix #2 — root cause of missing AVIFs on rds.ink bulk run wp_schedule_single_event(time()+30, …) coalesces identical args at the same timestamp, so bulk-queueing hundreds of AVIF jobs in the same second silently dropped many. Added wp h4b-img generate-missing-siblings that walks attachment metadata, finds files missing .webp/.avif, and generates them SYNCHRONOUSLY (no queue, no coalescing). Only processes registered sizes by default; --include-orphans flag for disk-walk mode. Verified on prod rds.ink: 1,134 of 1,737 registered images >=20KB have AVIF, 603 are missing. Of 389 orphan files >=20KB missing AVIF, those aren't referenced from any post/postmeta — correctly excluded. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
87 lines
2.7 KiB
PHP
87 lines
2.7 KiB
PHP
<?php
|
|
/**
|
|
* Plugin loader. Wires hooks; defers heavy work until needed.
|
|
*
|
|
* @package H4B\ImageOptim
|
|
*/
|
|
|
|
namespace H4B\ImageOptim;
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-tools.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-settings.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-icc-profile.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-attachment-meta.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-optimizer.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-format-generator.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-uploader-hook.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-rescue-detector.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-cli.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-cli-bulk.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-cli-rescue.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-cli-migrate.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-cli-siblings.php';
|
|
require_once H4B_IMG_OPTIM_DIR . 'includes/class-picture-tag.php';
|
|
|
|
final class Plugin {
|
|
|
|
private static ?self $instance = null;
|
|
|
|
public static function instance(): self {
|
|
if ( null === self::$instance ) {
|
|
self::$instance = new self();
|
|
}
|
|
return self::$instance;
|
|
}
|
|
|
|
public function boot(): void {
|
|
// Settings load first — everything else reads them.
|
|
Settings::register();
|
|
|
|
// Activation / deactivation
|
|
register_activation_hook( H4B_IMG_OPTIM_FILE, [ $this, 'on_activate' ] );
|
|
register_deactivation_hook( H4B_IMG_OPTIM_FILE, [ $this, 'on_deactivate' ] );
|
|
|
|
// Upload pipeline
|
|
Uploader_Hook::register();
|
|
|
|
// Front-end <picture> rewriting
|
|
Picture_Tag::register();
|
|
|
|
// Background AVIF queue (WP-Cron)
|
|
Format_Generator::register_cron();
|
|
|
|
// Backup pruning cron
|
|
add_action( 'h4b_img_prune_originals', [ Optimizer::class, 'prune_originals' ] );
|
|
add_action( 'init', [ $this, 'maybe_schedule_cron' ] );
|
|
|
|
// WP-CLI
|
|
if ( defined( 'WP_CLI' ) && \WP_CLI ) {
|
|
CLI::register();
|
|
}
|
|
}
|
|
|
|
public function on_activate(): void {
|
|
Settings::install_defaults();
|
|
if ( ! wp_next_scheduled( 'h4b_img_prune_originals' ) ) {
|
|
wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'h4b_img_prune_originals' );
|
|
}
|
|
// Make sure the originals dir + .htaccess exist
|
|
Optimizer::ensure_dirs();
|
|
}
|
|
|
|
public function on_deactivate(): void {
|
|
wp_clear_scheduled_hook( 'h4b_img_prune_originals' );
|
|
wp_clear_scheduled_hook( 'h4b_img_generate_avif' );
|
|
}
|
|
|
|
public function maybe_schedule_cron(): void {
|
|
if ( ! wp_next_scheduled( 'h4b_img_prune_originals' ) ) {
|
|
wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'h4b_img_prune_originals' );
|
|
}
|
|
}
|
|
}
|