- Added phpcs:ignore for class file naming convention (79 violations)
WordPress.Files.FileName.InvalidClassFileName is a known architectural
issue — class files use short names without prautoblogger- prefix
- Added phpcs:ignore for ->prepare() table interpolation (56 violations)
WordPress.DB.PreparedSQL.InterpolatedNotPrepared: dynamic table names
(prab_generation_logs, prab_cost_logs) require interpolation; ->prepare()
does not support table name placeholders, only column values
- Fixed file-level docblock positioning (2 violations)
prautoblogger.php and uninstall.php: moved declare(strict_types=1) before
file docblock per PHP best practices
Run phpcbf --standard=WordPress-Core across includes/, prautoblogger.php,
and uninstall.php. Fixed 1,362 formatting violations in 75 files:
- Short array syntax: [] → array()
- Line breaking for long function calls
- Consistent indentation
- Function call parameter alignment
No logic changes; purely mechanical formatting.
Both Image A and Image B now fire concurrently through a single
generate_image_batch() call instead of sequentially. Total wall-clock
time equals the slowest image (~20s), not the sum (~40s), which
eliminates the Image B timeout problem on Hostinger where
max_execution_time killed the cron before the second request finished.
New files:
- class-open-router-image-batch.php — curl_multi orchestrator
- generate_image_batch() added to image provider interface
Pipeline refactored: prompts built upfront, single batch call, results
processed per-key. Cloudflare provider gets a sequential fallback.
Tests updated for batch API. All files under 300-line cap.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three fixes in one:
1. Duplicate image: prepend_caption_to_post() was embedding the full
image + caption as a <figure> block, but the theme already displays
the featured image. Now only the caption text is prepended — no
second copy of the image.
2. Hardcoded model names: removed all FLUX.1/FLUX.2 references from
model-agnostic code (pipeline, prompt builder, sideloader, OpenRouter
provider, interface, admin labels). The Cloudflare provider still
references FLUX since it specifically wraps that model family.
3. Test alignment: OpenRouterImagePricingTest was asserting against
removed models (flux-2-pro, seedream). Updated to match current
COST_PER_IMAGE entries (Gemini Flash, GPT-5 Image).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Gemini image models reject arbitrary aspect ratios like 150:79
(computed via GCD from 1200×632 pixels). Replace GCD-based calculation
with a snap-to-nearest approach using 7 standard ratios (1:1, 3:2,
2:3, 4:3, 3:4, 16:9, 9:16). Also set modalities to ["image", "text"]
as required by some providers.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Three issues found in activity logs:
1. Image model IDs stale — FLUX and Seedream removed from OpenRouter.
Updated to current models: Gemini 2.5/3.1 Flash Image, Gemini 3 Pro
Image, GPT-5 Image/Mini. Default changed to gemini-2.5-flash-image.
2. openrouter/free router wraps upstream 429 errors in HTTP 200 body
with error object. Both text and image response parsers now detect
this pattern and surface a proper RuntimeException.
3. Image request used modalities: ["image"] but Gemini needs
["image", "text"]. Updated to include both.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The autoloader splits CamelCase on lowercase→uppercase transitions, so
PRAutoBlogger_OpenRouter_Image_Provider maps to class-open-router-image-provider.php.
Files were named class-openrouter-* (missing hyphen), causing a PHP fatal
error when the pipeline tried to instantiate the provider — which killed
the process before any logging could fire.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>