1.0.1
Security
- The compiled cache configuration and the Redis runtime configuration are no longer executable PHP. Both are stored as JSON behind a fixed
<?php exit; ?>guard line and are read withfile_get_contents()andjson_decode(), never included. The guard keeps a direct web request from disclosing the Redis credentials on servers that do not honour.htaccess. - The early cache drop-in and
RequestContext::fromGlobals()now sanitize the request through one shared implementation. Control characters are stripped and every name and value is bounded before any of it reaches thegt_performance_htmlfilter.
Fixed
- Updating from 1.0.0 took the whole site down. The drop-in published by that release loads a fixed list of runtime files that predates
ConfigFile, so the moment the new plugin files landed it fatally errored insidewp-settings.php— before WordPress exists to catch it — taking the front end and wp-admin down together with no way back except filesystem access.DropinRuntime::serve()now loads its own dependency when an older drop-in did not. - Schema 3 renames this plugin’s tables from the
gtp_prefix togtperf_. Without a schema bump the upgrade left the old tables in place and every queue, dependency, and CSS artifact query failed against a table that did not exist. The upgrade now creates the renamed tables and drops the superseded ones. WpCacheConstant::enable()rewrote an already-correctWP_CACHEline to an identical value, read the unchanged file as a failed update, and returned an error — which madeDropinInstaller::install()delete the drop-in it had just published. Installing twice in a row disabled page caching.DropinInstaller::syncVersion()gated only on the version, so a migrated or restored site running the same release from a new path kept a compiled configuration naming the old directory. The drop-in found nothing to load and the site served uncached indefinitely without reporting anything. The gate now tracks the location alongside the version.- Keyboard focus styles were pruned out of generated CSS.
:focus-visibleand:focus-withinmatched the shorterfocusalternative in the dynamic-state pattern, leaving-visibleand-withinfused to the class name, so the rules matched nothing and were removed as unused. RequestContext::fromGlobals()did not unslash the superglobals, so any URL, query value, or cookie containing a quote hashed differently in WordPress than in the drop-in and could never produce a cache hit.DropinInstaller::installedVersion()captured the trailing period after the drop-in signature, which made every version comparison unequal and reinstalled the drop-in on each request.
Changed
- Page-cache entry metadata is now
<hash>.meta.jsoninstead of a generated<hash>.meta.php. Because metadata no longer passes through opcache, the opcode-invalidation workaround is gone along with the stale-metadata window it covered on hosts runningopcache.validate_timestamps=0. advanced-cache.phpis a bundled file copied verbatim fromdropins/, with only its version stamped in. It resolves the cache root fromWP_CONTENT_DIRand the plugin directory from the compiled configuration, so no path is baked into the published drop-in.- Every output buffer the plugin opens is closed explicitly through
Core\OutputBuffer, onshutdownat priority 0, ahead of core’s ownwp_ob_end_flush_all(). - Renamed the
GTP_andgtp_prefixes toGTPERF_andgtperf_across constants, transients, AJAX actions, the cron schedule, the Private Islands shortcode, and the Redis key prefix. There is no compatibility shim:wp-config.phpconstants and any stored shortcode must use the new names. - Updated
sabberworm/php-css-parserfrom 8.9.0 to 9.4.0. Version 9 requiresthecodingmachine/safeat runtime, which adds about 2.4 MB to the package and eagerly loads 79 function-definition files when the plugin bootstraps. That cost lands only on full WordPress requests, measured at roughly 5 ms; requests served from the page cache never load the plugin autoloader and are unaffected. - The compiled configuration files are now
config.json.phpandredis-config.json.php. The names deliberately differ from theconfig.phpandredis-config.phpused up to 1.0.0: a drop-in left over from that release reads those paths withrequire, so pointing the new guarded files at the old names could have blanked every front-end response if the drop-in swap did not complete. Compiling also deletes the old files. dropins/is now covered by the coding-standards run.
