Skip to content

Commit 0990e40

Browse files
authored
v2.1.1: Check for module presence
fix: Improve cache-purge module detection to prevent false positives
2 parents 91a0c95 + 9e84412 commit 0990e40

File tree

5 files changed

+108
-42
lines changed

5 files changed

+108
-42
lines changed

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,16 @@
11
# Changelog
22
All notable changes to TNC Toolbox for WordPress will be documented in this file.
33

4+
## [2.1.1] - 2026-01-10
5+
6+
### 🐛 Bug Fix
7+
- **Cache Purge Detection**: Fix false positive module detection when `ea-nginx-cache-purge` is not installed
8+
- Detection now requires specific response signatures from the cache-purge module
9+
- Generic NGINX 301/404/405 responses no longer trigger false detection
10+
- **Detection Caching**: Fix stale detection cache preventing module discovery
11+
- Settings page now always performs fresh detection check
12+
- No HTTP requests on regular page loads (uses cached result)
13+
414
## [2.1.0] - 2026-01-08
515

616
### 🚀 Feature

tnc-toolbox/core/settings.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ class="regular-text" />
215215
class="regular-text" />
216216
</td>
217217
</tr>
218-
<?php $status = TNC_Cache_Purge::get_status(); ?>
218+
<?php $status = TNC_Cache_Purge::get_status( true ); // Force recheck on settings page ?>
219219
<tr>
220220
<th scope="row">
221221
<label for="tnc_selective_purge">Selective Purging?</label>

tnc-toolbox/readme.txt

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
=== TNC Toolbox: Web Performance ===
22
Author URI: https://tnc.works
33
Plugin URI: https://merlot.digital
4-
Donate link:
5-
Contributors:
4+
Donate link:
5+
Contributors:
66
Tags: NGINX, Cache Purge, Web Performance, Automatic Purge, Freeware
77
Tested up to: 6.9
8-
Stable tag: 2.1.0
8+
Stable tag: 2.1.1
99
License: GPLv3
1010
License URI: https://www.gnu.org/licenses/gpl-3.0.html
1111

@@ -14,11 +14,11 @@ Designed for ea-NGINX (Cache/Proxy) on cPanel+WHM. Made to help you fly online!
1414

1515
== Description ==
1616

17-
TNC Toolbox aims to enhance your WordPress experience with NGINX-on-cPanel (ea-nginx).
17+
TNC Toolbox aims to enhance your WordPress experience with NGINX-on-cPanel (ea-nginx).
1818

1919
**Built for our Managed Server clients, we've open-sourced it so others can enjoy it too!**
2020

21-
With a heavy focus on the Apache + NGINX as Reverse Caching Proxy web stack, the plugin aims to help with Website Management, Performance and Security.
21+
With a heavy focus on the Apache + NGINX as Reverse Caching Proxy web stack, the plugin aims to help with Website Management, Performance and Security.
2222

2323
> ❤️ **FOSS by [The Network Crew Pty Ltd](https://tnc.works) (TNC) for [Merlot Digital](https://merlot.digital) & the world.** ❤️
2424

@@ -37,7 +37,7 @@ With a heavy focus on the Apache + NGINX as Reverse Caching Proxy web stack, the
3737

3838
**Eager for even more capabilities?**
3939

40-
We plan to add further features as clients & the community request it.
40+
We plan to add further features as clients & the community request it.
4141

4242
_Please let us know your ideas on [GitHub](https://github.com/The-Network-Crew/TNC-Toolbox-for-WordPress/) - we'd love to hear from you!_
4343

@@ -152,6 +152,9 @@ _(* Change to main plugin file name may result in deactivation)_
152152

153153
== Changelog ==
154154

155+
= 2.1.1: Jan 10, 2026 =
156+
* Bug Fix: Fix false positive cache-purge module detection
157+
155158
= 2.1.0: Jan 8, 2026 =
156159
* Feature: Selective Cache Purging with ea-nginx-cache-purge integration
157160
* Feature: "Purge This Page" button in admin bar when viewing posts

tnc-toolbox/tnc-toolbox.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
* @package TNCTOOLBOX
66
* @author The Network Crew Pty Ltd (Merlot Digital)
77
* @license gplv3
8-
* @version 2.1.0
8+
* @version 2.1.1
99
*
1010
* @wordpress-plugin
1111
* Plugin Name: TNC Toolbox: Web Performance
1212
* Plugin URI: https://merlot.digital
1313
* Description: Designed for ea-NGINX (Cache/Proxy) on cPanel+WHM. Now with selective cache purging support!
14-
* Version: 2.1.0
14+
* Version: 2.1.1
1515
* Author: The Network Crew Pty Ltd (Merlot Digital)
1616
* Author URI: https://tnc.works
1717
* Domain Path: /locale

tnc-toolbox/vendor/cache-purge.php

Lines changed: 86 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,12 @@ public static function is_available( $force = false ) {
8282
* PURGE requests must be sent to localhost (127.0.0.1) with the Host header
8383
* set to the actual domain. This is how ea-nginx-cache-purge is configured.
8484
*
85+
* The module returns specific signatures in the response body:
86+
* - HTTP 200 with body containing "Successful purge" = module working.
87+
* - HTTP 412 can occur when item not in cache, but we need body signature.
88+
*
89+
* Without the module, nginx may return 301/404/405 with generic HTML.
90+
*
8591
* @return bool True if PURGE is supported.
8692
*/
8793
private static function test_purge_capability() {
@@ -111,36 +117,40 @@ private static function test_purge_capability() {
111117
$code = wp_remote_retrieve_response_code( $response );
112118
$body = wp_remote_retrieve_body( $response );
113119

114-
// ea-nginx-cache-purge returns:
115-
// - 200 OK with "Successful purge" if entry existed.
116-
// - 404 Not Found if entry didn't exist (but PURGE is supported).
117-
// - 412 Precondition Failed if entry wasn't in cache.
118-
// - 405 Method Not Allowed if PURGE is not configured.
119-
if ( 200 === $code || 404 === $code || 412 === $code ) {
120-
// Check for cache-purge signature in body.
121-
if ( stripos( $body, 'purge' ) !== false || stripos( $body, 'cache' ) !== false ) {
122-
self::log( 'PURGE test successful: module detected' );
123-
return true;
124-
}
125-
// Even without body, 200/404/412 on PURGE is a good sign.
126-
self::log( 'PURGE test: got ' . $code . ', assuming module available' );
120+
// ea-nginx-cache-purge module returns specific signatures:
121+
// - 200 OK with body "Successful purge" and "Key :" when purged.
122+
// - 412 Precondition Failed when item wasn't in cache.
123+
//
124+
// Without module: 301 redirect, 404 generic HTML, or 405 Method Not Allowed.
125+
//
126+
// We MUST check body for "Successful purge" signature to confirm module.
127+
if ( 200 === $code && stripos( $body, 'Successful purge' ) !== false ) {
128+
self::log( 'PURGE test successful: module detected (200 + signature)' );
129+
return true;
130+
}
131+
132+
// 412 from module still indicates it's working (item just wasn't cached).
133+
// But generic nginx 412 doesn't have our signature, so check for module output.
134+
if ( 412 === $code && stripos( $body, 'Precondition Failed' ) !== false ) {
135+
// This is likely the module - generic nginx rarely returns 412 for PURGE.
136+
self::log( 'PURGE test successful: module detected (412 Precondition Failed)' );
127137
return true;
128138
}
129139

130-
self::log( 'PURGE test: got ' . $code . ', module not available' );
140+
self::log( 'PURGE test: got HTTP ' . $code . ', module not detected' );
131141
return false;
132142
}
133143

134144
/**
135145
* Check if selective purging is enabled.
136146
*
137-
* @return bool True if enabled and available.
147+
* Returns true if the user has enabled selective purging via checkbox.
148+
* Module availability is checked separately during actual purge operations.
149+
*
150+
* @return bool True if enabled by user.
138151
*/
139152
public static function is_enabled() {
140-
$enabled = get_option( self::OPTION_ENABLED, 'yes' );
141-
$available = get_option( self::OPTION_AVAILABLE, 'unknown' );
142-
143-
return 'yes' === $enabled && 'yes' === $available;
153+
return 'yes' === get_option( self::OPTION_ENABLED, 'no' );
144154
}
145155

146156
/**
@@ -207,21 +217,54 @@ public static function purge_url( $url ) {
207217
}
208218

209219
$code = wp_remote_retrieve_response_code( $response );
220+
$body = wp_remote_retrieve_body( $response );
210221

211-
// 200 = successfully purged, 404 = wasn't in cache (ok), 412 = wasn't in cache.
212-
if ( 200 === $code || 404 === $code || 412 === $code ) {
213-
self::log( 'Purged: ' . $url . ' (HTTP ' . $code . ')' );
222+
// ea-nginx-cache-purge module returns:
223+
// - 200 with "Successful purge" = item was in cache and purged.
224+
// - 412 Precondition Failed = item wasn't in cache (still success).
225+
//
226+
// Without module: 301/404/405 with generic nginx HTML (not a real purge).
227+
if ( 200 === $code && stripos( $body, 'Successful purge' ) !== false ) {
228+
self::log( 'Purged: ' . $url . ' (HTTP 200)' );
214229
return array(
215230
'success' => true,
216231
'message' => 'Purged successfully',
217232
'code' => $code,
218233
);
219234
}
220235

236+
// 412 means item wasn't cached - that's fine, nothing to purge.
237+
if ( 412 === $code ) {
238+
self::log( 'Not in cache: ' . $url . ' (HTTP 412)' );
239+
return array(
240+
'success' => true,
241+
'message' => 'Not in cache (already clean)',
242+
'code' => $code,
243+
);
244+
}
245+
246+
// Got a 200 but without cache-purge signature = module not working.
247+
if ( 200 === $code ) {
248+
self::log( 'Purge returned 200 but without module signature for ' . $url );
249+
return array(
250+
'success' => false,
251+
'message' => 'Cache purge module not responding correctly',
252+
'code' => $code,
253+
);
254+
}
255+
256+
// 301/404/405 = module not installed or not configured for this domain.
257+
$error_msg = 'Purge failed (HTTP ' . $code . ')';
258+
if ( 404 === $code || 301 === $code ) {
259+
$error_msg = 'Cache purge module not detected - install ea-nginx-cache-purge';
260+
} elseif ( 405 === $code ) {
261+
$error_msg = 'PURGE method not allowed - cache purge module not configured';
262+
}
263+
221264
self::log( 'Purge failed for ' . $url . ': HTTP ' . $code );
222265
return array(
223266
'success' => false,
224-
'message' => 'Unexpected response: HTTP ' . $code,
267+
'message' => $error_msg,
225268
'code' => $code,
226269
);
227270
}
@@ -466,28 +509,38 @@ private static function log( $message ) {
466509
/**
467510
* Get availability status for display.
468511
*
512+
* Detection only runs on settings page (force_recheck=true) to avoid
513+
* HTTP requests on every page load. Admin bar uses cached result.
514+
*
515+
* @param bool $force_recheck Force a fresh detection check (use on settings page).
469516
* @return array Status info with 'available', 'enabled', 'message' keys.
470517
*/
471-
public static function get_status() {
518+
public static function get_status( $force_recheck = false ) {
519+
$enabled = self::is_enabled();
472520
$available = get_option( self::OPTION_AVAILABLE, 'unknown' );
473-
$enabled = get_option( self::OPTION_ENABLED, 'yes' );
474521

475-
if ( 'unknown' === $available ) {
476-
$available = self::is_available() ? 'yes' : 'no';
522+
// Only recheck on settings page (force_recheck=true).
523+
// This avoids HTTP requests on every page load.
524+
if ( $force_recheck && $enabled ) {
525+
$available = self::is_available( true ) ? 'yes' : 'no';
477526
}
478527

479528
$message = '';
480-
if ( 'yes' === $available && 'yes' === $enabled ) {
481-
$message = 'Selective purging active — only changed pages are purged for maximum efficiency';
482-
} elseif ( 'yes' === $available && 'no' === $enabled ) {
483-
$message = 'Selective purging available but disabled';
529+
if ( $enabled ) {
530+
if ( 'yes' === $available ) {
531+
$message = 'Selective purging active — only changed pages are purged for maximum efficiency';
532+
} elseif ( 'no' === $available ) {
533+
$message = 'Selective purging enabled but module not detected — purges may fail';
534+
} else {
535+
$message = 'Selective purging enabled — checking module availability...';
536+
}
484537
} else {
485-
$message = 'nginx-module-cache-purge not detected — using full cache purge via cPanel API';
538+
$message = 'Selective purging disabled — using full cache purge via cPanel API';
486539
}
487540

488541
return array(
489542
'available' => 'yes' === $available,
490-
'enabled' => 'yes' === $enabled,
543+
'enabled' => $enabled,
491544
'message' => $message,
492545
);
493546
}

0 commit comments

Comments
 (0)