=' )
&& version_compare( get_bloginfo( 'version' ), CACHINGOUT_MIN_WP, '>=' );
}
/**
* Bootstrap the plugin.
*
* Kept intentionally thin: this file declares constants and guards only. All
* wiring belongs in CachingOut_Plugin (includes/class-plugin.php).
*
* @return void
*/
function cachingout_bootstrap() {
if ( ! cachingout_environment_supported() ) {
add_action(
'admin_notices',
static function () {
printf(
'
Caching Out filesystem checkv' . esc_html( CACHINGOUT_VERSION ) . '
';
if ( ! empty( $report['steps'] ) && is_array( $report['steps'] ) ) {
foreach ( $report['steps'] as $step => $info ) {
if ( ! is_array( $info ) ) {
continue;
}
$status = ! empty( $info['ok'] ) ? 'OK' : 'FAILED';
$msg = isset( $info['message'] ) ? $info['message'] : '';
echo '' . esc_html( (string) $step ) . ': ' . esc_html( $status );
if ( $msg ) {
echo ' — ' . esc_html( (string) $msg );
}
echo ' ';
}
}
if ( ! empty( $report['paths'] ) && is_array( $report['paths'] ) ) {
echo '
Paths checked:
';
foreach ( $report['paths'] as $label => $path ) {
$exists = ( is_string( $path ) && $path !== '' && file_exists( $path ) ) ? 'exists' : 'MISSING';
echo '- ' . esc_html( (string) $label ) . ':
' . esc_html( (string) $path ) . ' (' . esc_html( $exists ) . ') ';
}
}
echo '
';
if ( ! $ok ) {
// BUG-019: the browser-cache .htaccess blocks are an optimisation
// layer; the page cache runs on the drop-in + wp-config + runtime
// config. Only say "page cache will not work" when one of THOSE
// failed - a refused .htaccess write must not read as a dead cache.
$core_failed = false;
if ( ! empty( $report['steps'] ) && is_array( $report['steps'] ) ) {
foreach ( $report['steps'] as $step => $info ) {
if ( is_array( $info ) && empty( $info['ok'] ) && 'write_browser_cache_rules' !== $step ) {
$core_failed = true;
}
}
}
if ( $core_failed ) {
echo '
The plugin is active in WordPress, but one or more filesystem writes failed (usually host permissions on wp-content/ or wp-config.php). Page cache will not work until those writes succeed.
';
} else {
echo '
The page cache is working. The Browser Caching rules (Expires / GZIP / Brotli) were NOT written to .htaccess; your original file is unchanged. Fix the cause shown above, then re-save the Browser Caching settings to retry.
';
}
}
// Operator UX (2026-09-01): a new user should go straight on from
// here, not back via Installed Plugins.
echo '
'
. 'Open Setup Wizard'
. 'Settings'
. 'Re-run filesystem check'
. '
';
echo '
';
}
);
/**
* The notices' own stylesheet (assets/css/admin-notice.css, spec 35). The
* notices in this file print on every admin screen, where the plugin's
* admin.css is not loaded; this 3 KB sheet carries the tokens their
* buttons and code chips need.
*/
add_action(
'admin_enqueue_scripts',
static function () {
wp_enqueue_style( 'cachingout-admin-notice', CACHINGOUT_URL . 'assets/css/admin-notice.css', array(), CACHINGOUT_VERSION );
}
);
/**
* Persistent admin notice when page caching is blocked by a foreign drop-in
* (Spec 23 Part A). Names the plugin found and explains that every other
* module remains active. Not dismissible — the state changes only when the
* conflict is resolved.
*/
add_action(
'admin_notices',
static function () {
if ( ! current_user_can( 'manage_options' ) ) {
return;
}
$guard = CACHINGOUT_PATH . 'includes/cache/class-dropin-owner.php';
if ( file_exists( $guard ) ) {
require_once $guard;
}
if ( ! class_exists( 'CachingOut_Dropin_Owner' ) ) {
return;
}
if ( 'blocked' !== \CachingOut_Dropin_Owner::get_page_cache_mode() ) {
return;
}
$owner = \CachingOut_Dropin_Owner::get_detected_owner_label();
?>