diff --git a/.gitignore b/.gitignore index 106a68b..675fea7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ vendor/ coverage/ .phpunit.result.cache + +# Generated class-loader cache (a build artefact, not source) +class-loader-cache/ diff --git a/CHANGELOG.md b/CHANGELOG.md index ca9040d..127735c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file, per [the Keep a Changelog standard](http://keepachangelog.com/) and will adhere to [Semantic Versioning](http://semver.org/). ## [Unreleased] - TBD +### Added +- Build-time class-cache generation: a `tenup-framework-generate-class-cache` command (installed to `vendor/bin/`) and a `composer generate-class-cache` alias that build the cache in CI without bootstrapping WordPress. See [Build and Deployment](docs/Build-and-Deployment.md) ([#30](https://github.com/10up/wp-framework/issues/30)). +- Hidden admin page (`admin.php?page=tenup-framework-loaders`, `manage_options`) that aggregates every class-loader cache on the site — across all framework copies — and shows each cache's path, status, loaded classes, and an on-demand live-vs-cache staleness check. Admin-only (no front-end overhead) and read-only. Disable with the `tenup_framework_enable_loader_debug` filter or the `TENUP_FRAMEWORK_DISABLE_LOADER_DEBUG` constant. See [Debugging class loaders](docs/Debugging.md). + +### Changed +- The class-loader cache is now **read-only at runtime** and opt-in. The framework reads a pre-built cache if present and discovers live otherwise, but never writes one on the server — fixing stale caches that could only be cleared by hand ([#30](https://github.com/10up/wp-framework/issues/30)). +- Bumped the cache identifier so a cache written by an older version is ignored after upgrade rather than served stale. +- `TENUP_FRAMEWORK_DISABLE_CLASS_CACHE` now forces live discovery (ignores any shipped cache). + +### Removed +- Automatic runtime cache generation and its environment gating — `should_use_cache()`, the `production`/`staging` checks, and the `VIP_GO_APP_ENVIRONMENT` handling. Caching is now produced at build time instead. ## [1.2.0] - 2025-03-20 ### Changed diff --git a/bin/tenup-framework-generate-class-cache b/bin/tenup-framework-generate-class-cache new file mode 100755 index 0000000..23458fb --- /dev/null +++ b/bin/tenup-framework-generate-class-cache @@ -0,0 +1,76 @@ +#!/usr/bin/env php + [
' . esc_html__( 'Each card is a directory passed to ModuleInitialization::init_classes(), with the state of its class-loader cache. Caches are built at deploy time and read — never written — at runtime.', 'tenup-framework' ) . '
'; + + if ( empty( $loaders ) ) { + echo '' . esc_html( $value ) . '| ' . esc_html__( 'Class', 'tenup-framework' ) . ' | ' . esc_html__( 'File', 'tenup-framework' ) . ' |
|---|---|
' . esc_html( $class ) . ' | ' . esc_html( $file ) . ' |
' . esc_html__( 'Check this cache for staleness', 'tenup-framework' ) . '
'; + return; + } + + $live = ModuleInitialization::instance()->discover_live( $directory ); + $loaded = array_values( $classes ); + $removed = array_diff( $loaded, $live ); // In cache but no longer on disk. + $added = array_diff( $live, $loaded ); // On disk but missing from the cache. + + if ( empty( $removed ) && empty( $added ) ) { + echo '' . esc_html__( 'On disk but missing from the cache:', 'tenup-framework' ) . '
' . esc_html( $class ) . '' . esc_html__( 'In the cache but no longer on disk:', 'tenup-framework' ) . '
' . esc_html( $class ) . '' . esc_html__( 'Regenerate the cache in your build (composer generate-class-cache) or remove the file and redeploy.', 'tenup-framework' ) . '
'; + echo '