feat: initial v0.1.0 MVP
Replaces Smush Pro's optimisation pipeline without the grey-wash bug. CLI commands working: wp h4b-img status wp h4b-img optimise --id=<n> wp h4b-img bulk wp h4b-img rescue Verified on dev.rds.ink: - ICC profile preservation works (the Smush-bug fix) - Bulk: 20 attachments → 487 KB saved (10.4%), 0 errors - Rescue: end-to-end mechanism verified on WorkingAsOne_horse fixture - WebP synchronous, AVIF queued via WP-Cron - Originals backed up to wp-content/h4b-img-originals/ See CHANGELOG.md for details + ../DESIGN-h4b-image-optim.md for architecture. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
71
includes/class-attachment-meta.php
Normal file
71
includes/class-attachment-meta.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* Tracks per-attachment optimisation history.
|
||||
*
|
||||
* Stored as a single postmeta key `_h4b_img_optim` containing:
|
||||
* [
|
||||
* 'version' => '0.1.0',
|
||||
* 'processed_at' => 'ISO-8601',
|
||||
* 'tool_chain' => ['imagick','cjpeg','jpegoptim',...],
|
||||
* 'sizes' => [
|
||||
* 'full' => ['before'=>123, 'after'=>78, 'webp'=>45, 'avif'=>30, 'percent'=>37],
|
||||
* '800x524' => [...],
|
||||
* ],
|
||||
* 'backup_path' => 'wp-content/h4b-img-originals/2026/02/...',
|
||||
* 'errors' => [],
|
||||
* ]
|
||||
*
|
||||
* @package H4B\ImageOptim
|
||||
*/
|
||||
|
||||
namespace H4B\ImageOptim;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
final class Attachment_Meta {
|
||||
|
||||
public const META_KEY = '_h4b_img_optim';
|
||||
|
||||
public static function get( int $attachment_id ): array {
|
||||
$meta = get_post_meta( $attachment_id, self::META_KEY, true );
|
||||
return is_array( $meta ) ? $meta : [];
|
||||
}
|
||||
|
||||
public static function set( int $attachment_id, array $meta ): void {
|
||||
update_post_meta( $attachment_id, self::META_KEY, $meta );
|
||||
}
|
||||
|
||||
public static function is_processed( int $attachment_id ): bool {
|
||||
$meta = self::get( $attachment_id );
|
||||
return ! empty( $meta['processed_at'] );
|
||||
}
|
||||
|
||||
public static function record_size( int $attachment_id, string $size_key, array $stats ): void {
|
||||
$meta = self::get( $attachment_id );
|
||||
$meta['sizes'] = $meta['sizes'] ?? [];
|
||||
$meta['sizes'][ $size_key ] = $stats;
|
||||
$meta['version'] = H4B_IMG_OPTIM_VERSION;
|
||||
$meta['processed_at'] = current_time( 'c' );
|
||||
self::set( $attachment_id, $meta );
|
||||
}
|
||||
|
||||
public static function mark_avif_pending( int $attachment_id, string $size_key ): void {
|
||||
$meta = self::get( $attachment_id );
|
||||
$meta['avif_pending'] = $meta['avif_pending'] ?? [];
|
||||
$meta['avif_pending'][ $size_key ] = current_time( 'c' );
|
||||
self::set( $attachment_id, $meta );
|
||||
}
|
||||
|
||||
public static function clear_avif_pending( int $attachment_id, string $size_key ): void {
|
||||
$meta = self::get( $attachment_id );
|
||||
if ( isset( $meta['avif_pending'][ $size_key ] ) ) {
|
||||
unset( $meta['avif_pending'][ $size_key ] );
|
||||
if ( empty( $meta['avif_pending'] ) ) {
|
||||
unset( $meta['avif_pending'] );
|
||||
}
|
||||
self::set( $attachment_id, $meta );
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user