Skip to content

Commit b5a10bf

Browse files
authored
Merge pull request #465 from newfold-labs/fix/cache-exclusion-invalid-option
Delete broken cache exclusion on a site when refreshed
2 parents a2ddd0c + 05f1120 commit b5a10bf

File tree

5 files changed

+51
-9
lines changed

5 files changed

+51
-9
lines changed

includes/Cache/CacheExclusion.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use NewfoldLabs\WP\ModuleLoader\Container;
55

6-
use function NewfoldLabs\WP\Module\Performance\get_default_cache_exclusions;
6+
use function NewfoldLabs\WP\Module\Performance\get_cache_exclusion;
77

88
/**
99
* Cache Exclusion Class
@@ -60,6 +60,6 @@ public function __construct( Container $container ) {
6060
* @return array
6161
*/
6262
public function add_to_runtime( $sdk ) {
63-
return array_merge( $sdk, array( 'cacheExclusion' => get_option( self::OPTION_CACHE_EXCLUSION, get_default_cache_exclusions() ) ) );
63+
return array_merge( $sdk, array( 'cacheExclusion' => get_cache_exclusion() ) );
6464
}
6565
}

includes/Cache/Types/Browser.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use NewfoldLabs\WP\Module\Htaccess\Api as HtaccessApi;
1010
use NewfoldLabs\WP\Module\Performance\Cache\Types\Fragments\BrowserCacheFragment;
1111

12+
use function NewfoldLabs\WP\Module\Performance\get_cache_exclusion;
1213
use function NewfoldLabs\WP\Module\Performance\get_cache_level;
1314

1415
/**
@@ -109,7 +110,7 @@ public static function addRules( $cache_level ) {
109110

110111
// Build exclusion pattern (same logic as before).
111112
$exclusion_pattern = '';
112-
$cache_exclusion = get_option( CacheExclusion::OPTION_CACHE_EXCLUSION, '' );
113+
$cache_exclusion = get_cache_exclusion();
113114

114115
if ( is_string( $cache_exclusion ) && '' !== $cache_exclusion ) {
115116
$parts = array_map( 'trim', explode( ',', sanitize_text_field( $cache_exclusion ) ) );

includes/Cache/Types/File.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use NewfoldLabs\WP\Module\Htaccess\Api as HtaccessApi;
1212
use wpscholar\Url;
1313

14+
use function NewfoldLabs\WP\Module\Performance\get_cache_exclusion;
1415
use function NewfoldLabs\WP\Module\Performance\get_cache_level;
1516
use function NewfoldLabs\WP\Module\Performance\remove_directory;
1617
use function NewfoldLabs\WP\Module\Performance\should_cache_pages;
@@ -109,7 +110,7 @@ public static function addRules() {
109110

110111
// Build optional exclusion pattern (pipe-separated).
111112
$exclusion_pattern = '';
112-
$cache_exclusion = get_option( CacheExclusion::OPTION_CACHE_EXCLUSION, '' );
113+
$cache_exclusion = get_cache_exclusion();
113114

114115
if ( is_string( $cache_exclusion ) && '' !== $cache_exclusion ) {
115116
$parts = array_map( 'trim', explode( ',', sanitize_text_field( $cache_exclusion ) ) );
@@ -286,7 +287,7 @@ public function shouldCache() {
286287
*/
287288
protected function exclusions() {
288289
$default = array( 'cart', 'checkout', 'wp-admin', '@', '%', ':', ';', '&', '=', '.', rest_get_url_prefix() );
289-
$cache_exclusion_option = array_map( 'trim', explode( ',', (string) get_option( CacheExclusion::OPTION_CACHE_EXCLUSION ) ) );
290+
$cache_exclusion_option = array_map( 'trim', explode( ',', (string) get_cache_exclusion() ) );
290291
return array_merge( $default, array_filter( $cache_exclusion_option ) );
291292
}
292293

includes/functions.php

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
use NewfoldLabs\WP\Module\Performance\Cache\CacheExclusion;
88

99
/**
10-
* Return defaul exclusions.
10+
* Return default cache exclusions (comma-separated string).
1111
*
12-
* @return array
12+
* Must stay compatible with CacheExclusion::CACHE_EXCLUSION_VALIDATE_REGEX (a-z0-9,- only)
13+
* so that get_cache_exclusion() validation and .htaccess fragment content remain valid.
14+
*
15+
* @return string
1316
*/
1417
function get_default_cache_exclusions() {
1518
return join( ',', array( 'cart', 'checkout', 'wp-admin', rest_get_url_prefix() ) );
@@ -27,10 +30,22 @@ function get_cache_level() {
2730
/**
2831
* Get the cache exclusion.
2932
*
30-
* @return int Cache exclusion.
33+
* If the stored value is invalid (non-empty but contains disallowed characters), the option is deleted
34+
* and the default exclusions are returned. Empty string is valid (exclude no paths).
35+
*
36+
* @return string Comma-separated exclusion slugs (e.g. cart,checkout,wp-admin,wp-json).
3137
*/
3238
function get_cache_exclusion() {
33-
return get_option( CacheExclusion::OPTION_CACHE_EXCLUSION, get_default_cache_exclusions() );
39+
$value = get_option( CacheExclusion::OPTION_CACHE_EXCLUSION, get_default_cache_exclusions() );
40+
$normalized = CacheExclusion::normalize( $value );
41+
42+
// Invalid: non-empty and does not match allowed characters (a-z0-9,-). Empty is valid (exclude nothing).
43+
if ( '' !== $normalized && ! preg_match( CacheExclusion::CACHE_EXCLUSION_VALIDATE_REGEX, $normalized ) ) {
44+
delete_option( CacheExclusion::OPTION_CACHE_EXCLUSION );
45+
return get_default_cache_exclusions();
46+
}
47+
48+
return $value;
3449
}
3550

3651
/**

tests/phpunit/includes/CacheExclusionTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,31 @@ public function test_update_cache_exclusion_option_invalid() {
118118
$this->assertSame( 400, $response->get_status() );
119119
$this->assertFalse( $response->get_data()['result'] );
120120
}
121+
122+
/**
123+
* Test that get_cache_exclusion() deletes invalid option and returns default.
124+
*/
125+
public function test_get_cache_exclusion_deletes_invalid_option_and_returns_default() {
126+
$invalid_value = 'cart,checkout,wp-admin,wp-json https://example.com/admin/';
127+
$option_name = \NewfoldLabs\WP\Module\Performance\Cache\CacheExclusion::OPTION_CACHE_EXCLUSION;
128+
$default = 'cart,checkout,wp-admin,wp-json';
129+
130+
WP_Mock::userFunction( 'get_option' )
131+
->with( $option_name, $default )
132+
->andReturn( $invalid_value );
133+
134+
WP_Mock::userFunction( 'delete_option' )
135+
->with( $option_name )
136+
->once()
137+
->andReturn( true );
138+
139+
WP_Mock::userFunction( 'rest_get_url_prefix' )
140+
->andReturn( 'wp-json' );
141+
142+
$result = \NewfoldLabs\WP\Module\Performance\get_cache_exclusion();
143+
144+
$this->assertSame( $default, $result );
145+
}
121146
}
122147
}
123148
// phpcs:enable

0 commit comments

Comments
 (0)