Skip to content

Commit 9a5507d

Browse files
committed
Fix object-cache drop-in removal when Redis constants are commented out
- Use wp-cli/wp-config-transformer to detect Redis config in wp-config.php so commented-out defines are not treated as present (drop-in was defining WP_REDIS_PREFIX from env/WP_CACHE_KEY_SALT, so is_available() stayed true) - Add is_configured_in_wp_config() and use it in maybe_remove_dropin_if_unavailable instead of is_available() - Performance: check for drop-in file first so wp-config is only read when the drop-in exists; cache is_configured_in_wp_config() result per request - Add wp-cli/wp-config-transformer ^1.4 dependency
1 parent 80104a8 commit 9a5507d

File tree

4 files changed

+113
-61
lines changed

4 files changed

+113
-61
lines changed

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@
4040
"newfold-labs/wp-module-features": "^1.5",
4141
"newfold-labs/wp-module-installer": "^1.7",
4242
"newfold-labs/wp-module-htaccess": "^1.0",
43-
"predis/predis": "^3.4"
43+
"predis/predis": "^3.4",
44+
"wp-cli/wp-config-transformer": "^1.4"
4445
},
4546
"require-dev": {
4647
"newfold-labs/wp-php-standards": "^1.2",

composer.lock

Lines changed: 50 additions & 50 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

includes/Cache/Types/ObjectCache.php

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,49 @@ class ObjectCache {
5858
*/
5959
public static function is_available() {
6060
foreach ( self::REDIS_CONNECTION_CONSTANTS as $constant ) {
61-
if ( defined( $constant ) ) {
62-
return true;
61+
if ( ! defined( $constant ) ) {
62+
return false;
6363
}
6464
}
65-
return false;
65+
return true;
66+
}
67+
68+
/**
69+
* Whether Redis is configured in wp-config.php (at least one connection constant is defined there).
70+
* Used for removal: we remove the drop-in when wp-config no longer has Redis config, even if the
71+
* drop-in has already defined a constant (e.g. WP_REDIS_PREFIX from WP_CACHE_KEY_SALT or env).
72+
* Uses WP-CLI's wp-config-transformer so commented-out defines are not counted as present.
73+
* Result is cached per request to avoid repeated file reads and parsing.
74+
*
75+
* @return bool
76+
*/
77+
public static function is_configured_in_wp_config() {
78+
static $result = null;
79+
if ( null !== $result ) {
80+
return $result;
81+
}
82+
$path = defined( 'WP_CONFIG_FILE' ) ? constant( 'WP_CONFIG_FILE' ) : ( ABSPATH . 'wp-config.php' );
83+
if ( ! file_exists( $path ) ) {
84+
$path = dirname( ABSPATH ) . '/wp-config.php';
85+
}
86+
if ( ! file_exists( $path ) || ! is_readable( $path ) ) {
87+
$result = false;
88+
return $result;
89+
}
90+
try {
91+
$transformer = new \WPConfigTransformer( $path, true );
92+
foreach ( self::REDIS_CONNECTION_CONSTANTS as $constant ) {
93+
if ( ! $transformer->exists( 'constant', $constant ) ) {
94+
$result = false;
95+
return $result;
96+
}
97+
}
98+
} catch ( \Exception $e ) {
99+
$result = false;
100+
return $result;
101+
}
102+
$result = true;
103+
return $result;
66104
}
67105

68106
/**
@@ -305,18 +343,20 @@ public static function maybe_restore_on_activation() {
305343
/**
306344
* If Redis config is no longer present (e.g. constants commented out in wp-config) but our drop-in
307345
* is still in place, remove the drop-in so WordPress does not load a broken object cache.
308-
* Also clears the enabled preference so state stays consistent.
346+
* Uses wp-config content (not defined()) so we still remove when the drop-in has already defined
347+
* a constant (e.g. WP_REDIS_PREFIX from WP_CACHE_KEY_SALT or env). Also clears the enabled preference.
348+
* Checks for the drop-in file first so we skip wp-config read/parse on most requests (no drop-in).
309349
*
310350
* @return void
311351
*/
312352
public static function maybe_remove_dropin_if_unavailable() {
313-
if ( self::is_available() ) {
314-
return;
315-
}
316353
$path = self::get_drop_in_path();
317354
if ( ! file_exists( $path ) || ! self::is_our_drop_in( $path ) ) {
318355
return;
319356
}
357+
if ( self::is_configured_in_wp_config() ) {
358+
return;
359+
}
320360
if ( ! function_exists( 'WP_Filesystem' ) ) {
321361
require_once ABSPATH . 'wp-admin/includes/file.php';
322362
}

includes/PerformanceLifecycleHooks.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,9 @@ public function hooks() {
115115
* @return void
116116
*/
117117
public function on_activation() {
118-
// Purge object cache on shutdown so the next request reads active_plugins from DB (not Redis).
119-
add_action( 'shutdown', array( $this, 'purge_object_cache_on_shutdown' ), PHP_INT_MAX );
118+
// Clear plugin list from object cache on shutdown so the next request reads active_plugins from DB (not Redis).
119+
// Only clears options group — avoids full flush which would destroy session/auth data and log the user out.
120+
add_action( 'shutdown', array( $this, 'clear_plugin_cache_on_shutdown' ), PHP_INT_MAX );
120121
// Cache feature bits.
121122
File::on_activation();
122123
Browser::on_activation();
@@ -146,7 +147,17 @@ protected function delete_plugin_list_option_cache() {
146147
}
147148

148149
/**
149-
* Purge object cache (options + full flush + runtime) on shutdown after activate/deactivate.
150+
* Clear only the plugin list from object cache on shutdown after activation.
151+
* Ensures the next request reads active_plugins from DB without destroying session/auth data.
152+
*
153+
* @return void
154+
*/
155+
public function clear_plugin_cache_on_shutdown() {
156+
$this->delete_plugin_list_option_cache();
157+
}
158+
159+
/**
160+
* Purge object cache (options + full flush + runtime) on shutdown after deactivation.
150161
* Ensures the next request reads active_plugins from DB even if something re-cached after our hooks.
151162
*
152163
* @return void

0 commit comments

Comments
 (0)