Files
h4b-image-optim/includes/class-plugin.php
Henk 4cd1390a94 feat: migrate-from-smush + Picture-tag rewriter (v0.2.0)
Unblocks production use on sites previously running Smush.

migrate-from-smush:
  - Reads wp-smpro-smush-data postmeta, writes _h4b_img_optim marker
  - --dry-run / --force-rescan / --remove-smush-meta / --limit flags
  - Verified: 100 attachments migrated cleanly on dev.rds.ink,
    bulk count drops from 734 → 634

Picture_Tag rewriter:
  - Hooks the_content + post_thumbnail_html + widget_text + Elementor
    frontend + wp_get_attachment_image at priority 99
  - Wraps <img> in <picture><source avif><source webp><img></picture>
    when sibling files exist
  - Double-wrap protection via byte-range tracking of existing <picture> blocks
  - Per-image opt-out via data-no-h4b attribute
  - Cached sibling lookups per request
  - 8 edge-case tests pass

LOC: 2480 (was 1997). Adds class-cli-migrate.php (193 LOC) and
class-picture-tag.php (284 LOC).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-19 13:50:41 +10:00

86 lines
2.6 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-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' );
}
}
}