feat: deterministic image composer — OG + square variants, branding, baked caption (v0.17.0)
Commit 2 (final scope) of the in-plugin editorial image pipeline (ARCHITECTURE.md #21). A deterministic local composer now runs between provider bytes and sideload: Image A yields a corner-marked featured (1200x632) + branded OG (1200x630, teal band, logo, baked caption in Poppins SemiBold) + square card (1080x1080, cream panel, Poppins Bold, teal footer with the reverse lockup); Image B gets the corner mark only. - Capability ladder: imagick (full compositing) -> wp_get_image_editor resize-only (unbranded, WARNING once) -> pass-through (WARNING once); probe cached in prautoblogger_image_compose_capability, fingerprinted by PHP version + imagick/gd presence so host flips auto-invalidate. compose() never throws; composition can never fail a publish. - Variants sideloaded with a role filename suffix; attachment meta _prautoblogger_image_role + _prautoblogger_base_attachment_id; post meta _prautoblogger_og_image_id (frozen for the rebuilt SEO stage) + _prautoblogger_square_image_id. No cost-tracker rows ($0 local stage; duration logged on the image_composer channel). - New Images settings: compose_enabled ('1'), compose_variants ('og,square'), featured_mark_enabled ('1') — read at point of use. Geometry ships as Layout defaults behind the prautoblogger_image_compose_layout filter. - Vendored brand rasters (assets/brand) + bundled OFL Poppins faces (assets/fonts) for per-environment byte-stable output (stripImage + PNG date/time chunks excluded). Validated on Hostinger PHP 8.3.30 / ImageMagick 7.1.1-43: php -l clean on all touched files, double render byte-identical (sha256), exact variant geometry. - Fix: featured/Image B alt text is the editorial caption (was the model name); model still persists in _prautoblogger_image_model. - Image_Attacher extracted from Image_Pipeline (300-line compliance); sideloader gains an optional filename suffix param (back-compat ''). - Version 0.16.0 -> 0.17.0 + CHANGELOG + ARCHITECTURE.md #21 + CONVENTIONS.md composer guide in this commit. Unit tests: layout clamp boundaries, capability ladder, cache invalidation, attacher meta-linking, pipeline integration, imagick determinism (gated). Agent-Session: engineer-prautoblogger-image-composer-20260611
This commit is contained in:
50
includes/core/interface-image-composer.php
Normal file
50
includes/core/interface-image-composer.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* phpcs:ignore WordPress.Files.FileName.InvalidClassFileName -- class naming convention differs from WordPress standard
|
||||
*
|
||||
* Contract for image composers that turn raw provider bytes into final variants.
|
||||
*
|
||||
* A composer sits between the image provider (raw generated bytes) and the
|
||||
* media sideloader. It receives one base image plus per-post context and
|
||||
* returns one or more finished variants — the first is always the `featured`
|
||||
* role (the bytes that become the post thumbnail), optionally followed by
|
||||
* social variants (`og`, `square`). Implementations must NEVER throw out of
|
||||
* compose(): on any internal failure they degrade to passing the base image
|
||||
* through unmodified so publishing is never blocked.
|
||||
*
|
||||
* Triggered by: PRAutoBlogger_Image_Pipeline between batch results and sideload.
|
||||
* Dependencies: none — this is the contract only.
|
||||
*
|
||||
* @see core/class-image-composer.php — Default implementation (capability ladder).
|
||||
* @see core/class-image-pipeline.php — Caller.
|
||||
* @see core/class-image-attacher.php — Persists the returned variants.
|
||||
*/
|
||||
interface PRAutoBlogger_Image_Composer_Interface {
|
||||
|
||||
/**
|
||||
* Compose final image variant(s) from raw provider bytes.
|
||||
*
|
||||
* Side effects: implementations may read plugin options and write to the
|
||||
* activity log; they must not make network calls or fail the publish.
|
||||
*
|
||||
* @param array{
|
||||
* bytes: string,
|
||||
* mime_type: string,
|
||||
* width: int,
|
||||
* height: int,
|
||||
* } $image_data Base image bytes + metadata from the provider result.
|
||||
* @param array{
|
||||
* post_id: int,
|
||||
* caption: string,
|
||||
* title: string,
|
||||
* slot: string,
|
||||
* } $context Post ID, editorial caption, post title, and slot
|
||||
* ('image_a' or 'image_b'); only image_a yields variants.
|
||||
*
|
||||
* @return array<int, array{bytes: string, mime_type: string, width: int, height: int, role: string}>
|
||||
* Non-empty list; index 0 always carries role 'featured'.
|
||||
*/
|
||||
public function compose( array $image_data, array $context ): array;
|
||||
}
|
||||
Reference in New Issue
Block a user