Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.frankenpress.com/llms.txt

Use this file to discover all available pages before exploring further.

fp-mu-plugin is the WordPress-side glue for the FrankenPress stack. Two components only — anything else (URL fixers, object cache, metrics, WC log handlers) is considered optional and is the consumer site’s responsibility.
ComponentWhat it does
S3UploadsBootstrapConfigures humanmade/s3-uploads from FP_S3_* env vars. Refuses uploads when S3 isn’t fully configured (no silent local-disk fallback).
SouinInvalidatorDELs Souin’s Redis cache entries directly on save_post, clean_post_cache, switch_theme, etc. — bypasses cache-handler’s broken HTTP invalidation.
Composer name: eightoeight/fp-mu-plugin. Latest release: v0.1.1.

S3UploadsBootstrap

Maps FP_S3_* env vars to humanmade/s3-uploads’ S3_UPLOADS_* constants and auto-loads the s3-uploads plugin from composer’s vendor / plugins dir. Refuses media uploads via wp_handle_upload_prefilter when required env vars are missing.

Why refuse rather than fall back?

In a containerized deploy, local disk is ephemeral (gone on pod restart) and inconsistent across replicas (write to pod A, read from pod B → 404). Silently writing uploads to local disk would produce broken behaviour that surfaces minutes-to-hours later. A hard upload failure surfaces the misconfiguration immediately.

Env vars

VarDefaultRequired
FP_S3_BUCKET
FP_S3_KEY
FP_S3_SECRET
FP_S3_REGIONus-east-1
FP_S3_BUCKET_URLoptional CDN URL — auto-sets WP_CONTENT_URL if undefined
FP_S3_ENDPOINToptional, for non-AWS S3-compatible (MinIO, R2, GCS XML)
FP_S3_DISABLEDfalsetruthy → skip the bootstrap entirely (local dev only — never in production)

Endpoint filter (v0.1.1)

humanmade/s3-uploads documents S3_UPLOADS_ENDPOINT but doesn’t apply it to the AWS SDK by itself — you have to register a filter. v0.1.1 of this plugin registers s3_uploads_s3_client_params automatically when the endpoint constant is defined, with use_path_style_endpoint: true (MinIO and most S3-compatibles don’t support virtual-host bucket addressing).

SouinInvalidator

Connects directly to Redis and DELs Souin’s cache entries on WordPress lifecycle events.

Hooks

  • save_post, deleted_post, clean_post_cache — invalidate the post URL + tag + home page
  • comment_post, transition_comment_status — invalidate the parent post
  • switch_theme, permalink_structure_changed — invalidate everything
  • updated_option (for blogname, permalink_structure, etc.) — invalidate everything

Env vars

VarDefaultPurpose
FP_SOUIN_REDIS_HOSTredisRedis hostname
FP_SOUIN_REDIS_PORT6379Redis port
FP_SOUIN_REDIS_PASSWORD(empty)Redis AUTH password
FP_SOUIN_REDIS_DB0Logical database
FP_SOUIN_REDIS_TIMEOUT1.0Connect timeout (seconds)
FP_SOUIN_DISABLEDfalseTruthy → no-op the invalidator (cache then expires only by TTL)

Why direct Redis DEL?

Souin’s documented HTTP invalidation APIs (PURGE, POST-CRUD, the /api.souin/* admin endpoint) are broken in cache-handler v0.16.0:
  • PURGE returns 200 but caches the PURGE response itself instead of invalidating the GET.
  • POST likewise — caches the POST response.
  • The admin endpoint at /api.souin/... returns 404 even when the API basepath is configured.
Direct Redis manipulation is sub-millisecond, has no parser to break, and works against any Redis-compatible service (including DragonflyDB). Full investigation log: fp-runtime/PHASE-0.md.

Failure mode

If ext-redis isn’t loaded, or the connection fails, or FP_SOUIN_DISABLED is set, the invalidator is a silent no-op. Errors are logged via error_log but never raised — a broken cache layer must not break WordPress itself.

Install

composer require eightoeight/fp-mu-plugin
fp-site-template ships this dep preconfigured. The plugin lands at web/app/mu-plugins/fp-mu-plugin/ and is auto-loaded by roots/bedrock-autoloader via the 00-fp-stack.php loader.

Local testing

The package ships PHPUnit unit tests using Brain Monkey (WP function stubs) and Mockery (Redis client mocks). No real Redis or WP install needed:
composer install
composer test     # phpunit
composer lint     # phpcs (WordPress-Core ruleset)
composer stan     # phpstan level 6
composer ci       # all four checks (lint + stan + test + audit)