Cache Enabler – WordPress Cache - Version 1.4.0

Version Description

  • Update default cache behavior for WooCommerce stock update
  • Update Cache Behavior setting for plugin actions
  • Update admin bar clear cache buttons
  • Update cache behavior for logged in users
  • Update default clear cache publishing action
  • Update advanced cache settings
  • Update trailing slash handling
  • Update settings page
  • Add Cache Behavior setting for WooCommerce stock update
  • Add fbclid as default URL query parameter to bypass cache
  • Add scheme-based caching
  • Fix advanced cache for multisite networks
  • Fix minor bugs
Download this release

Release Info

Developer keycdn
Plugin Icon 128x128 Cache Enabler – WordPress Cache
Version 1.4.0
Comparing to
See all releases

Code changes from version 1.3.5 to 1.4.0

advanced-cache.php CHANGED
@@ -1,7 +1,13 @@
1
  <?php
 
 
 
 
 
 
2
 
3
  // check if request method is GET
4
- if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || $_SERVER['REQUEST_METHOD'] != 'GET' ) {
5
  return false;
6
  }
7
 
@@ -9,113 +15,105 @@ if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || $_SERVER['REQUEST_METHOD'] != 'GET
9
  $path = _ce_file_path();
10
 
11
  // path to cached variants
12
- $path_html = $path . 'index.html';
13
- $path_gzip = $path . 'index.html.gz';
14
  $path_webp_html = $path . 'index-webp.html';
15
  $path_webp_gzip = $path . 'index-webp.html.gz';
16
 
17
-
18
- // if we don't have a cache copy, we do not need to proceed
19
- if ( !is_readable( $path_html ) ) {
20
  return false;
21
  }
22
 
23
- // check if there are settings passed out to us
24
- $settings_file = sprintf('%s-%s%s.json',
25
- WP_CONTENT_DIR. "/cache/cache-enabler-advcache",
 
26
  parse_url(
27
- 'http://' .strtolower($_SERVER['HTTP_HOST']),
28
  PHP_URL_HOST
29
  ),
30
- is_multisite() ? '-'. abs(intval($blog_id)) : ''
31
  );
32
- $settings = _read_settings($settings_file);
33
-
34
- // if post path excluded
35
- if ( !empty($settings['excl_regexp']) ) {
36
- $url_path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
37
 
38
- if ( preg_match($settings['excl_regexp'], $url_path) ) {
 
 
 
39
  return false;
40
  }
41
- }
42
-
43
- // check GET variables
44
- if ( !empty($_GET) ) {
45
- // set regex of analytics campaign tags that shall not prevent caching
46
- if ( !empty($settings['incl_attributes']) ) {
47
- $attributes_regex = $settings['incl_attributes'];
48
- } else {
49
- $attributes_regex = '/^utm_(source|medium|campaign|term|content)$/';
50
- }
51
- // prevent cache use if there is any GET variable not covered by the campaign tag regex
52
- if ( sizeof( preg_grep( $attributes_regex, array_keys( $_GET ), PREG_GREP_INVERT ) ) > 0 ) {
53
  return false;
54
  }
55
  }
56
 
57
- // check cookie values
58
- if ( !empty($_COOKIE) ) {
59
- // check cookie values
60
- if ( !empty($settings['excl_cookies']) ) {
61
- // if custom cookie regexps exist, we merge them
62
- $cookies_regex = $settings['excl_cookies'];
63
- } else {
64
- $cookies_regex = '/^(wp-postpass|wordpress_logged_in|comment_author)_/';
65
- }
66
-
67
- foreach ( $_COOKIE as $k => $v) {
68
- if ( preg_match($cookies_regex, $k) ) {
69
- return false;
70
- }
71
- }
72
- }
73
-
74
  // if an expiry time is set, check the file against it
75
- if ( isset($settings["expires"]) and $settings["expires"] > 0 ) {
76
  $now = time();
77
- $expires_seconds = 3600*$settings["expires"];
78
 
79
- // check if asset has expired
80
- if ( ( filemtime($path_html) + $expires_seconds ) <= $now ) {
81
  return false;
82
  }
83
  }
84
 
85
  // if a cache timeout is set, check if we have to bypass the cache
86
- if ( !empty($settings["cache_timeout"]) ) {
87
  $now = time();
88
 
89
  // check if timeout has been reached
90
- if ( $settings["cache_timeout"] <= $now ) {
91
- @unlink($path_html);
92
- @unlink($path_gzip);
93
- @unlink($path_webp_html);
94
- @unlink($path_webp_gzip);
95
  return false;
96
  }
97
  }
98
 
99
- // check if we need drop the ball to cause a redirect
100
- if ( isset($settings["permalink_trailing_slash"]) ) {
101
- if ( ! preg_match("/\/(|\?.*)$/", $_SERVER["REQUEST_URI"]) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
  return false;
103
  }
104
  }
105
 
106
- // set cache handler header
107
- header('x-cache-handler: wp');
108
 
109
- // get if-modified request headers
110
  if ( function_exists( 'apache_request_headers' ) ) {
111
- $headers = apache_request_headers();
112
  $http_if_modified_since = ( isset( $headers[ 'If-Modified-Since' ] ) ) ? $headers[ 'If-Modified-Since' ] : '';
113
- $http_accept = ( isset( $headers[ 'Accept' ] ) ) ? $headers[ 'Accept' ] : '';
114
- $http_accept_encoding = ( isset( $headers[ 'Accept-Encoding' ] ) ) ? $headers[ 'Accept-Encoding' ] : '';
115
  } else {
116
  $http_if_modified_since = ( isset( $_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ] ) ) ? $_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ] : '';
117
- $http_accept = ( isset( $_SERVER[ 'HTTP_ACCEPT' ] ) ) ? $_SERVER[ 'HTTP_ACCEPT' ] : '';
118
- $http_accept_encoding = ( isset( $_SERVER[ 'HTTP_ACCEPT_ENCODING' ] ) ) ? $_SERVER[ 'HTTP_ACCEPT_ENCODING' ] : '';
119
  }
120
 
121
  // check modified since with cached file and return 304 if no difference
@@ -124,12 +122,13 @@ if ( $http_if_modified_since && ( strtotime( $http_if_modified_since ) >= filemt
124
  exit;
125
  }
126
 
127
- header( 'Last-Modified: ' . gmdate("D, d M Y H:i:s",filemtime( $path_html )).' GMT' );
 
128
 
129
- // check webp and deliver gzip webp file if support
130
- if ( $http_accept && ( strpos($http_accept, 'webp') !== false ) ) {
131
  if ( is_readable( $path_webp_gzip ) ) {
132
- header('Content-Encoding: gzip');
133
  readfile( $path_webp_gzip );
134
  exit;
135
  } elseif ( is_readable( $path_webp_html ) ) {
@@ -138,9 +137,9 @@ if ( $http_accept && ( strpos($http_accept, 'webp') !== false ) ) {
138
  }
139
  }
140
 
141
- // check encoding and deliver gzip file if support
142
  if ( $http_accept_encoding && ( strpos($http_accept_encoding, 'gzip') !== false ) && is_readable( $path_gzip ) ) {
143
- header('Content-Encoding: gzip');
144
  readfile( $path_gzip );
145
  exit;
146
  }
@@ -151,13 +150,14 @@ exit;
151
 
152
 
153
  // generate cache path
154
- function _ce_file_path($path = NULL) {
 
155
  $path = sprintf(
156
  '%s%s%s%s',
157
  WP_CONTENT_DIR . '/cache/cache-enabler',
158
  DIRECTORY_SEPARATOR,
159
  parse_url(
160
- 'http://' .strtolower($_SERVER['HTTP_HOST']),
161
  PHP_URL_HOST
162
  ),
163
  parse_url(
@@ -166,7 +166,7 @@ function _ce_file_path($path = NULL) {
166
  )
167
  );
168
 
169
- if ( is_file($path) > 0 ) {
170
  header( $_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found', true, 404 );
171
  exit;
172
  }
@@ -177,15 +177,31 @@ function _ce_file_path($path = NULL) {
177
  return $path;
178
  }
179
 
 
 
 
 
 
 
 
 
 
180
  // read settings file
181
- function _read_settings($settings_file) {
182
- if (! file_exists($settings_file) ) {
183
- return [];
 
 
 
 
 
 
 
184
  }
185
 
186
- if ( ! $settings = json_decode(file_get_contents($settings_file), true) ) {
187
- // if there is an error reading our settings
188
- return [];
189
  }
190
 
191
  return $settings;
1
  <?php
2
+ /**
3
+ * Cache Enabler advanced cache
4
+ *
5
+ * @since 1.2.0
6
+ * @change 1.4.0
7
+ */
8
 
9
  // check if request method is GET
10
+ if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || $_SERVER['REQUEST_METHOD'] !== 'GET' ) {
11
  return false;
12
  }
13
 
15
  $path = _ce_file_path();
16
 
17
  // path to cached variants
18
+ $path_html = $path . 'index.html';
19
+ $path_gzip = $path . 'index.html.gz';
20
  $path_webp_html = $path . 'index-webp.html';
21
  $path_webp_gzip = $path . 'index-webp.html.gz';
22
 
23
+ // check if cached file exists
24
+ if ( ! is_readable( $path_html ) ) {
 
25
  return false;
26
  }
27
 
28
+ // check if there are settings
29
+ $settings_file = sprintf(
30
+ '%s-%s%s.json',
31
+ CE_SETTINGS_PATH,
32
  parse_url(
33
+ 'http://' . strtolower( $_SERVER['HTTP_HOST'] ),
34
  PHP_URL_HOST
35
  ),
36
+ ( is_multisite() && ! SUBDOMAIN_INSTALL ) ? _get_blog_path() : ''
37
  );
38
+ $settings = _read_settings( $settings_file );
 
 
 
 
39
 
40
+ // check trailing slash
41
+ if ( isset( $settings['permalink_trailing_slash'] ) && $settings['permalink_trailing_slash'] ) {
42
+ // if trailing slash is missing, check if we have to bypass the cache to allow a redirect
43
+ if ( ! preg_match( '/\/(|\?.*)$/', $_SERVER['REQUEST_URI'] ) ) {
44
  return false;
45
  }
46
+ } elseif ( isset( $settings['permalink_trailing_slash'] ) && ! $settings['permalink_trailing_slash'] ) {
47
+ // if trailing slash is appended, check if we have to bypass the cache to allow a redirect
48
+ if ( preg_match( '/(?!^)\/(|\?.*)$/', $_SERVER['REQUEST_URI'] ) ) {
 
 
 
 
 
 
 
 
 
49
  return false;
50
  }
51
  }
52
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  // if an expiry time is set, check the file against it
54
+ if ( isset( $settings['expires'] ) && $settings['expires'] > 0 ) {
55
  $now = time();
56
+ $expires_seconds = 3600 * $settings['expires'];
57
 
58
+ // check if cached file has expired
59
+ if ( ( filemtime( $path_html ) + $expires_seconds ) <= $now ) {
60
  return false;
61
  }
62
  }
63
 
64
  // if a cache timeout is set, check if we have to bypass the cache
65
+ if ( ! empty( $settings['cache_timeout'] ) ) {
66
  $now = time();
67
 
68
  // check if timeout has been reached
69
+ if ( $settings['cache_timeout'] <= $now ) {
 
 
 
 
70
  return false;
71
  }
72
  }
73
 
74
+ // check cookies
75
+ if ( ! empty( $_COOKIE ) ) {
76
+ // set regex matching cookies that should cause the cache to be bypassed
77
+ if ( ! empty( $settings['excl_cookies'] ) ) {
78
+ $cookies_regex = $settings['excl_cookies'];
79
+ } else {
80
+ $cookies_regex = '/^(wp-postpass|wordpress_logged_in|comment_author)_/';
81
+ }
82
+ // bypass the cache if an excluded cookie is found
83
+ foreach ( $_COOKIE as $key => $value) {
84
+ if ( preg_match( $cookies_regex, $key ) ) {
85
+ return false;
86
+ }
87
+ }
88
+ }
89
+
90
+ // check URL query parameters
91
+ if ( ! empty( $_GET ) ) {
92
+ // set regex matching URL query parameters that should not cause the cache to be bypassed
93
+ if ( ! empty( $settings['incl_parameters'] ) ) {
94
+ $parameters_regex = $settings['incl_parameters'];
95
+ } else {
96
+ $parameters_regex = '/^fbclid|utm_(source|medium|campaign|term|content)$/';
97
+ }
98
+ // bypass the cache if no included URL query parameters are found
99
+ if ( sizeof( preg_grep( $parameters_regex, array_keys( $_GET ), PREG_GREP_INVERT ) ) > 0 ) {
100
  return false;
101
  }
102
  }
103
 
104
+ // set X-Cache-Handler response header
105
+ header( 'X-Cache-Handler: wp' );
106
 
107
+ // get request headers
108
  if ( function_exists( 'apache_request_headers' ) ) {
109
+ $headers = apache_request_headers();
110
  $http_if_modified_since = ( isset( $headers[ 'If-Modified-Since' ] ) ) ? $headers[ 'If-Modified-Since' ] : '';
111
+ $http_accept = ( isset( $headers[ 'Accept' ] ) ) ? $headers[ 'Accept' ] : '';
112
+ $http_accept_encoding = ( isset( $headers[ 'Accept-Encoding' ] ) ) ? $headers[ 'Accept-Encoding' ] : '';
113
  } else {
114
  $http_if_modified_since = ( isset( $_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ] ) ) ? $_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ] : '';
115
+ $http_accept = ( isset( $_SERVER[ 'HTTP_ACCEPT' ] ) ) ? $_SERVER[ 'HTTP_ACCEPT' ] : '';
116
+ $http_accept_encoding = ( isset( $_SERVER[ 'HTTP_ACCEPT_ENCODING' ] ) ) ? $_SERVER[ 'HTTP_ACCEPT_ENCODING' ] : '';
117
  }
118
 
119
  // check modified since with cached file and return 304 if no difference
122
  exit;
123
  }
124
 
125
+ // set Last-Modified response header
126
+ header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', filemtime( $path_html ) ) . ' GMT' );
127
 
128
+ // check webp and deliver gzip webp file if supported
129
+ if ( $http_accept && ( strpos( $http_accept, 'webp' ) !== false ) ) {
130
  if ( is_readable( $path_webp_gzip ) ) {
131
+ header( 'Content-Encoding: gzip' );
132
  readfile( $path_webp_gzip );
133
  exit;
134
  } elseif ( is_readable( $path_webp_html ) ) {
137
  }
138
  }
139
 
140
+ // check encoding and deliver gzip file if supported
141
  if ( $http_accept_encoding && ( strpos($http_accept_encoding, 'gzip') !== false ) && is_readable( $path_gzip ) ) {
142
+ header( 'Content-Encoding: gzip' );
143
  readfile( $path_gzip );
144
  exit;
145
  }
150
 
151
 
152
  // generate cache path
153
+ function _ce_file_path( $path = null ) {
154
+
155
  $path = sprintf(
156
  '%s%s%s%s',
157
  WP_CONTENT_DIR . '/cache/cache-enabler',
158
  DIRECTORY_SEPARATOR,
159
  parse_url(
160
+ 'http://' .strtolower( $_SERVER['HTTP_HOST'] ),
161
  PHP_URL_HOST
162
  ),
163
  parse_url(
166
  )
167
  );
168
 
169
+ if ( is_file( $path ) > 0 ) {
170
  header( $_SERVER['SERVER_PROTOCOL'] . ' 404 Not Found', true, 404 );
171
  exit;
172
  }
177
  return $path;
178
  }
179
 
180
+ // get blog path
181
+ function _get_blog_path() {
182
+ $path = $_SERVER['REQUEST_URI'];
183
+
184
+ $path = explode( '/', $path, 3 );
185
+
186
+ return '-' . $path[1];
187
+ }
188
+
189
  // read settings file
190
+ function _read_settings( $settings_file ) {
191
+
192
+ // check if settings file exists
193
+ if ( ! file_exists( $settings_file ) ) {
194
+ // check if settings file exists for main site in network with subdirectory configuration
195
+ if ( is_multisite() && ! SUBDOMAIN_INSTALL && file_exists( str_replace( _get_blog_path(), '', $settings_file ) ) ) {
196
+ $settings_file = str_replace( _get_blog_path(), '', $settings_file );
197
+ } else {
198
+ return array();
199
+ }
200
  }
201
 
202
+ // check if any errors occur when reading the settings file
203
+ if ( ! $settings = json_decode( file_get_contents( $settings_file ), true ) ) {
204
+ return array();
205
  }
206
 
207
  return $settings;
cache-enabler.php CHANGED
Binary file
inc/cache_enabler.class.php CHANGED
@@ -2,13 +2,13 @@
2
 
3
 
4
  // exit
5
- defined('ABSPATH') OR exit;
6
 
7
 
8
  /**
9
  * Cache_Enabler
10
  *
11
- * @since 1.0.0
12
  */
13
 
14
  final class Cache_Enabler {
@@ -41,9 +41,9 @@ final class Cache_Enabler {
41
  * @var integer
42
  */
43
 
44
- const MINIFY_DISABLED = 0;
45
  const MINIFY_HTML_ONLY = 1;
46
- const MINIFY_HTML_JS = 2;
47
 
48
 
49
  /**
@@ -53,8 +53,8 @@ final class Cache_Enabler {
53
  * @change 1.0.0
54
  */
55
 
56
- public static function instance()
57
- {
58
  new self();
59
  }
60
 
@@ -63,291 +63,94 @@ final class Cache_Enabler {
63
  * constructor
64
  *
65
  * @since 1.0.0
66
- * @change 1.2.3
67
- *
68
- * @param void
69
- * @return void
70
  */
71
 
72
- public function __construct()
73
- {
74
  // set default vars
75
  self::_set_default_vars();
76
 
77
- // register publish hook
78
- add_action(
79
- 'init',
80
- array(
81
- __CLASS__,
82
- 'register_publish_hooks'
83
- ),
84
- 99
85
- );
86
 
87
  // clear cache hooks
88
- add_action(
89
- 'ce_clear_post_cache',
90
- array(
91
- __CLASS__,
92
- 'clear_page_cache_by_post_id'
93
- )
94
- );
95
- add_action(
96
- 'ce_clear_cache',
97
- array(
98
- __CLASS__,
99
- 'clear_total_cache'
100
- )
101
- );
102
- add_action(
103
- '_core_updated_successfully',
104
- array(
105
- __CLASS__,
106
- 'clear_total_cache'
107
- )
108
- );
109
- add_action(
110
- 'switch_theme',
111
- array(
112
- __CLASS__,
113
- 'clear_total_cache'
114
- )
115
- );
116
- add_action(
117
- 'wp_trash_post',
118
- function( $post_id ) {
119
- if ( get_post_status ( $post_id ) == 'publish' ) {
120
- self::clear_total_cache();
121
- }
122
- self::check_future_posts();
123
- }
124
- );
125
- add_action(
126
- 'save_post',
127
- array(
128
- __CLASS__,
129
- 'check_future_posts'
130
- )
131
- );
132
- add_action(
133
- 'autoptimize_action_cachepurged',
134
- array(
135
- __CLASS__,
136
- 'clear_total_cache'
137
- )
138
- );
139
- add_action(
140
- 'upgrader_process_complete',
141
- array(
142
- __CLASS__,
143
- 'on_upgrade_hook'
144
- ), 10, 2);
145
-
146
- // act on woocommerce actions
147
- add_action(
148
- 'woocommerce_product_set_stock',
149
- array(
150
- __CLASS__,
151
- 'woocommerce_product_set_stock',
152
- ),
153
- 10,
154
- 1
155
- );
156
- add_action(
157
- 'woocommerce_product_set_stock_status',
158
- array(
159
- __CLASS__,
160
- 'woocommerce_product_set_stock_status',
161
- ),
162
- 10,
163
- 1
164
- );
165
- add_action(
166
- 'woocommerce_variation_set_stock',
167
- array(
168
- __CLASS__,
169
- 'woocommerce_product_set_stock',
170
- ),
171
- 10,
172
- 1
173
- );
174
- add_action(
175
- 'woocommerce_variation_set_stock_status',
176
- array(
177
- __CLASS__,
178
- 'woocommerce_product_set_stock_status',
179
- ),
180
- 10,
181
- 1
182
- );
183
-
184
- // add admin clear link
185
- add_action(
186
- 'admin_bar_menu',
187
- array(
188
- __CLASS__,
189
- 'add_admin_links'
190
- ),
191
- 90
192
- );
193
- add_action(
194
- 'init',
195
- array(
196
- __CLASS__,
197
- 'process_clear_request'
198
- )
199
- );
200
- if ( !is_admin() ) {
201
- add_action(
202
- 'admin_bar_menu',
203
- array(
204
- __CLASS__,
205
- 'register_textdomain'
206
- )
207
- );
208
- }
209
-
210
- // admin
211
  if ( is_admin() ) {
212
- add_action(
213
- 'wpmu_new_blog',
214
- array(
215
- __CLASS__,
216
- 'install_later'
217
- )
218
- );
219
- add_action(
220
- 'delete_blog',
221
- array(
222
- __CLASS__,
223
- 'uninstall_later'
224
- )
225
- );
226
-
227
- add_action(
228
- 'admin_init',
229
- array(
230
- __CLASS__,
231
- 'register_textdomain'
232
- )
233
- );
234
- add_action(
235
- 'admin_init',
236
- array(
237
- __CLASS__,
238
- 'register_settings'
239
- )
240
- );
241
 
242
- add_action(
243
- 'admin_menu',
244
- array(
245
- __CLASS__,
246
- 'add_settings_page'
247
- )
248
- );
249
- add_action(
250
- 'admin_enqueue_scripts',
251
- array(
252
- __CLASS__,
253
- 'add_admin_resources'
254
- )
255
- );
256
 
257
- add_action(
258
- 'transition_comment_status',
259
- array(
260
- __CLASS__,
261
- 'change_comment'
262
- ),
263
- 10,
264
- 3
265
- );
266
- add_action(
267
- 'comment_post',
268
- array(
269
- __CLASS__,
270
- 'comment_post'
271
- ),
272
- 99,
273
- 2
274
- );
275
- add_action(
276
- 'edit_comment',
277
- array(
278
- __CLASS__,
279
- 'edit_comment'
280
- )
281
- );
282
 
283
- add_filter(
284
- 'dashboard_glance_items',
285
- array(
286
- __CLASS__,
287
- 'add_dashboard_count'
288
- )
289
- );
290
- add_action(
291
- 'post_submitbox_misc_actions',
292
- array(
293
- __CLASS__,
294
- 'add_clear_dropdown'
295
- )
296
- );
297
- add_filter(
298
- 'plugin_row_meta',
299
- array(
300
- __CLASS__,
301
- 'row_meta'
302
- ),
303
- 10,
304
- 2
305
- );
306
- add_filter(
307
- 'plugin_action_links_' .CE_BASE,
308
- array(
309
- __CLASS__,
310
- 'action_links'
311
- )
312
- );
313
 
314
- // warnings and notices
315
- add_action(
316
- 'admin_notices',
317
- array(
318
- __CLASS__,
319
- 'warning_is_permalink'
320
- )
321
- );
322
- add_action(
323
- 'admin_notices',
324
- array(
325
- __CLASS__,
326
- 'requirements_check'
327
- )
328
- );
329
 
330
- // caching
331
- } else {
332
- add_action(
333
- 'pre_comment_approved',
334
- array(
335
- __CLASS__,
336
- 'new_comment'
337
- ),
338
- 99,
339
- 2
340
- );
341
-
342
- add_action(
343
- 'template_redirect',
344
- array(
345
- __CLASS__,
346
- 'handle_cache'
347
- ),
348
- 0
349
- );
350
  }
 
 
 
351
  }
352
 
353
 
@@ -355,77 +158,126 @@ final class Cache_Enabler {
355
  * deactivation hook
356
  *
357
  * @since 1.0.0
358
- * @change 1.1.1
 
 
359
  */
360
 
361
- public static function on_deactivation() {
362
- self::clear_total_cache(true);
 
 
363
 
 
364
  if ( defined( 'WP_CACHE' ) && WP_CACHE ) {
365
- // unset WP_CACHE
366
- self::_set_wp_cache(false);
367
  }
368
 
369
  // delete advanced cache file
370
- unlink(WP_CONTENT_DIR . '/advanced-cache.php');
371
  }
372
 
373
 
374
  /**
375
- * activation hook
376
  *
377
- * @since 1.0.0
378
- * @change 1.1.1
 
 
 
379
  */
380
 
381
- public static function on_activation() {
382
 
383
- // multisite and network
384
- if ( is_multisite() && ! empty($_GET['networkwide']) ) {
385
- // blog ids
386
- $ids = self::_get_blog_ids();
387
 
388
- // switch to blog
389
- foreach ($ids as $id) {
390
- switch_to_blog($id);
391
- self::_install_backend();
 
 
 
 
 
 
 
 
 
392
  }
393
 
394
  // restore blog
395
  restore_current_blog();
396
-
397
  } else {
398
- self::_install_backend();
 
 
 
 
 
 
 
 
399
  }
400
 
401
- if ( !defined( 'WP_CACHE' ) || !WP_CACHE ) {
402
- // set WP_CACHE
403
- self::_set_wp_cache(true);
404
  }
 
405
 
406
- // copy advanced cache file
407
- copy(CE_DIR . '/advanced-cache.php', WP_CONTENT_DIR . '/advanced-cache.php');
 
 
 
 
 
 
 
 
 
 
 
 
408
  }
409
 
410
 
411
  /**
412
- * upgrade hook actions
 
 
 
413
  *
414
- * @since 1.2.3
 
415
  */
416
 
417
- public static function on_upgrade_hook( $obj, $options ) {
418
- // clear cache on other plugins being upgraded
 
419
  if ( self::$options['clear_on_upgrade'] ) {
420
  self::clear_total_cache();
421
  }
422
 
423
- // check if we got upgraded ourselves
424
- if ( $options['action'] == 'update' && $options['type'] == 'plugin' && array_key_exists('plugins', $options) ) {
425
- foreach ( (array)$options['plugins'] as $each_plugin ) {
426
- if ( preg_match("/^cache-enabler\//", $each_plugin) ) {
427
- // we got updated!
428
- self::on_upgrade();
 
 
 
 
 
 
 
429
  }
430
  }
431
  }
@@ -433,77 +285,187 @@ final class Cache_Enabler {
433
 
434
 
435
  /**
436
- * upgrade actions
 
 
 
437
  *
438
- * @since 1.2.3
439
  */
440
 
441
- public static function on_upgrade() {
442
- // copy advanced cache file which might have changed
443
- copy(CE_DIR . '/advanced-cache.php', WP_CONTENT_DIR . '/advanced-cache.php');
 
 
 
 
 
 
 
 
 
444
  }
445
 
446
 
447
  /**
448
- * install on multisite setup
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
449
  *
450
  * @since 1.0.0
451
- * @change 1.0.0
 
 
452
  */
453
 
454
- public static function install_later($id) {
455
 
456
- // check if multisite setup
457
- if ( ! is_plugin_active_for_network(CE_BASE) ) {
458
  return;
459
  }
460
 
461
  // switch to blog
462
- switch_to_blog($id);
463
 
464
- // installation
465
  self::_install_backend();
466
 
467
- // restore
468
  restore_current_blog();
469
  }
470
 
471
 
472
  /**
473
- * installation options
474
  *
475
  * @since 1.0.0
476
- * @change 1.0.0
477
  */
478
 
479
  private static function _install_backend() {
480
 
481
- add_option(
482
- 'cache-enabler',
483
- array()
484
- );
485
 
486
- // clear
487
- self::clear_total_cache(true);
488
  }
489
 
490
 
491
  /**
492
- * installation WP_CACHE (advanced cache)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
493
  *
494
  * @since 1.1.1
495
  * @change 1.1.1
 
 
496
  */
497
 
498
- private static function _set_wp_cache($wp_cache_value = true) {
 
499
  $wp_config_file = ABSPATH . 'wp-config.php';
500
 
501
  if ( file_exists( $wp_config_file ) && is_writable( $wp_config_file ) ) {
502
- // get wp config as array
503
  $wp_config = file( $wp_config_file );
504
 
505
- if ($wp_cache_value) {
506
- $wp_cache_ce_line = "define('WP_CACHE', true); // Added by Cache Enabler". "\r\n";
507
  } else {
508
  $wp_cache_ce_line = '';
509
  }
@@ -518,7 +480,7 @@ final class Cache_Enabler {
518
  }
519
  }
520
 
521
- // add wp cache ce line if not found yet
522
  if ( ! $found_wp_cache ) {
523
  array_shift( $wp_config );
524
  array_unshift( $wp_config, "<?php\r\n", $wp_cache_ce_line );
@@ -536,89 +498,35 @@ final class Cache_Enabler {
536
 
537
 
538
  /**
539
- * uninstall per multisite blog
540
- *
541
- * @since 1.0.0
542
- * @change 1.0.0
543
- */
544
-
545
- public static function on_uninstall() {
546
- global $wpdb;
547
-
548
- // multisite and network
549
- if ( is_multisite() && ! empty($_GET['networkwide']) ) {
550
- // legacy blog
551
- $old = $wpdb->blogid;
552
-
553
- // blog id
554
- $ids = self::_get_blog_ids();
555
-
556
- // uninstall per blog
557
- foreach ($ids as $id) {
558
- switch_to_blog($id);
559
- self::_uninstall_backend();
560
- }
561
-
562
- // restore
563
- switch_to_blog($old);
564
- } else {
565
- self::_uninstall_backend();
566
- }
567
- }
568
-
569
-
570
- /**
571
- * uninstall for multisite and network
572
- *
573
- * @since 1.0.0
574
- * @change 1.0.0
575
- */
576
-
577
- public static function uninstall_later($id) {
578
-
579
- // check if network plugin
580
- if ( ! is_plugin_active_for_network(CE_BASE) ) {
581
- return;
582
- }
583
-
584
- // switch
585
- switch_to_blog($id);
586
-
587
- // uninstall
588
- self::_uninstall_backend();
589
-
590
- // restore
591
- restore_current_blog();
592
- }
593
-
594
-
595
- /**
596
- * uninstall
597
  *
598
  * @since 1.0.0
599
  * @change 1.0.0
600
  */
601
 
602
- private static function _uninstall_backend() {
603
 
604
- // delete options
605
- delete_option('cache-enabler');
606
 
607
- // clear cache
608
- self::clear_total_cache(true);
 
 
609
  }
610
 
611
 
612
  /**
613
- * get blog ids
614
  *
615
  * @since 1.0.0
616
  * @change 1.0.0
617
  *
618
- * @return array blog ids array
619
  */
620
 
621
  private static function _get_blog_ids() {
 
622
  global $wpdb;
623
 
624
  return $wpdb->get_col("SELECT blog_id FROM `$wpdb->blogs`");
@@ -626,82 +534,103 @@ final class Cache_Enabler {
626
 
627
 
628
  /**
629
- * set default vars
630
  *
631
- * @since 1.0.0
632
- * @change 1.0.0
 
 
633
  */
634
 
635
- private static function _set_default_vars() {
636
 
637
- // get options
638
- self::$options = self::_get_options();
639
 
640
- // disk cache
641
- if ( Cache_Enabler_Disk::is_permalink() ) {
642
- self::$disk = new Cache_Enabler_Disk;
643
- }
644
  }
645
 
646
 
647
  /**
648
- * get options
649
  *
650
  * @since 1.0.0
651
- * @change 1.2.3
652
  *
653
- * @return array options array
654
  */
655
 
656
  private static function _get_options() {
657
 
658
- // decom
659
- $ce_leg = get_option('cache');
660
- if (!empty($ce_leg)) {
661
- delete_option('cache');
662
  add_option(
663
  'cache-enabler',
664
  $ce_leg
665
  );
666
  }
667
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
668
  return wp_parse_args(
669
- get_option('cache-enabler'),
670
  array(
671
- 'expires' => 0,
672
- 'new_post' => 0,
673
- 'new_comment' => 0,
674
- 'compress' => 0,
675
- 'webp' => 0,
676
- 'clear_on_upgrade' => 0,
677
- 'excl_ids' => '',
678
- 'excl_regexp' => '',
679
- 'excl_cookies' => '',
680
- 'incl_attributes' => '',
681
- 'minify_html' => self::MINIFY_DISABLED,
 
682
  )
683
  );
684
  }
685
 
686
 
687
  /**
688
- * warning if no custom permlinks
689
  *
690
  * @since 1.0.0
691
- * @change 1.0.0
692
- *
693
- * @return array options array
694
  */
695
 
696
  public static function warning_is_permalink() {
697
 
698
- if ( !Cache_Enabler_Disk::is_permalink() && current_user_can('manage_options') ) { ?>
699
-
700
- <div class="error">
701
- <p><?php printf( __('The <b>%s</b> plugin requires a custom permalink structure to start caching properly. Please go to <a href="%s">Permalink</a> to enable it.', 'cache-enabler'), 'Cache Enabler', admin_url( 'options-permalink.php' ) ); ?></p>
702
- </div>
703
 
704
- <?php
 
 
 
 
 
 
 
 
 
 
 
 
 
705
  }
706
  }
707
 
@@ -716,10 +645,10 @@ final class Cache_Enabler {
716
  * @return array $data appended links
717
  */
718
 
719
- public static function action_links($data) {
720
 
721
  // check user role
722
- if ( ! current_user_can('manage_options') ) {
723
  return $data;
724
  }
725
 
@@ -730,11 +659,11 @@ final class Cache_Enabler {
730
  '<a href="%s">%s</a>',
731
  add_query_arg(
732
  array(
733
- 'page' => 'cache-enabler'
734
  ),
735
- admin_url('options-general.php')
736
  ),
737
- esc_html__('Settings')
738
  )
739
  )
740
  );
@@ -742,27 +671,27 @@ final class Cache_Enabler {
742
 
743
 
744
  /**
745
- * cache enabler meta links
746
  *
747
  * @since 1.0.0
748
- * @change 1.0.0
749
  *
750
  * @param array $input existing links
751
  * @param string $page page
752
  * @return array $data appended links
753
  */
754
 
755
- public static function row_meta($input, $page) {
756
 
757
  // check permissions
758
- if ( $page != CE_BASE ) {
759
  return $input;
760
  }
761
 
762
  return array_merge(
763
  $input,
764
  array(
765
- '<a href="https://www.keycdn.com/support/wordpress-cache-enabler-plugin/" target="_blank">Support Page</a>',
766
  )
767
  );
768
  }
@@ -781,7 +710,7 @@ final class Cache_Enabler {
781
  public static function add_dashboard_count( $items = array() ) {
782
 
783
  // check user role
784
- if ( ! current_user_can('manage_options') ) {
785
  return $items;
786
  }
787
 
@@ -789,17 +718,19 @@ final class Cache_Enabler {
789
  $size = self::get_cache_size();
790
 
791
  // display items
792
- $items[] = sprintf(
793
- '<a href="%s" title="%s">%s %s</a>',
794
- add_query_arg(
795
- array(
796
- 'page' => 'cache-enabler'
 
 
 
797
  ),
798
- admin_url('options-general.php')
799
- ),
800
- esc_html__('Disk Cache', 'cache-enabler'),
801
- ( empty($size) ? esc_html__('Empty', 'cache-enabler') : size_format($size) ),
802
- esc_html__('Cache Size', 'cache-enabler')
803
  );
804
 
805
  return $items;
@@ -812,14 +743,14 @@ final class Cache_Enabler {
812
  * @since 1.0.0
813
  * @change 1.0.0
814
  *
815
- * @param integer $size cache size (bytes)
816
  */
817
 
818
  public static function get_cache_size() {
819
 
820
- if ( ! $size = get_transient('cache_size') ) {
821
 
822
- $size = is_object( self::$disk ) ? (int) self::$disk->cache_size(CE_CACHE_DIR) : 0;
823
 
824
  // set transient
825
  set_transient(
@@ -833,44 +764,82 @@ final class Cache_Enabler {
833
  }
834
 
835
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
836
  /**
837
  * add admin links
838
  *
839
  * @since 1.0.0
840
- * @change 1.1.0
841
- *
842
- * @hook mixed
843
  *
844
  * @param object menu properties
 
 
845
  */
846
 
847
- public static function add_admin_links($wp_admin_bar) {
848
 
849
  // check user role
850
- if ( ! is_admin_bar_showing() OR ! apply_filters('user_can_clear_cache', current_user_can('manage_options')) ) {
851
  return;
852
  }
853
 
854
- // add admin clear link
 
 
 
855
  $wp_admin_bar->add_menu(
856
  array(
857
- 'id' => 'clear-cache',
858
- 'href' => wp_nonce_url( add_query_arg('_cache', 'clear'), '_cache__clear_nonce'),
 
 
 
 
859
  'parent' => 'top-secondary',
860
- 'title' => '<span class="ab-item">'.esc_html__('Clear Cache', 'cache-enabler').'</span>',
861
- 'meta' => array( 'title' => esc_html__('Clear Cache', 'cache-enabler') )
 
 
862
  )
863
  );
864
 
 
865
  if ( ! is_admin() ) {
866
- // add admin clear link
867
  $wp_admin_bar->add_menu(
868
  array(
869
- 'id' => 'clear-url-cache',
870
- 'href' => wp_nonce_url( add_query_arg('_cache', 'clearurl'), '_cache__clear_nonce'),
 
 
 
 
871
  'parent' => 'top-secondary',
872
- 'title' => '<span class="ab-item">'.esc_html__('Clear URL Cache', 'cache-enabler').'</span>',
873
- 'meta' => array( 'title' => esc_html__('Clear URL Cache', 'cache-enabler') )
 
 
874
  )
875
  );
876
  }
@@ -881,55 +850,50 @@ final class Cache_Enabler {
881
  * process clear request
882
  *
883
  * @since 1.0.0
884
- * @change 1.1.0
885
  *
886
  * @param array $data array of metadata
887
  */
888
 
889
- public static function process_clear_request($data) {
890
 
891
  // check if clear request
892
- if ( empty($_GET['_cache']) OR ( $_GET['_cache'] !== 'clear' && $_GET['_cache'] !== 'clearurl' ) ) {
 
 
 
 
 
893
  return;
894
  }
895
 
896
  // validate nonce
897
- if ( empty($_GET['_wpnonce']) OR ! wp_verify_nonce($_GET['_wpnonce'], '_cache__clear_nonce') ) {
898
  return;
899
  }
900
 
901
  // check user role
902
- if ( ! is_admin_bar_showing() OR ! apply_filters('user_can_clear_cache', current_user_can('manage_options')) ) {
903
  return;
904
  }
905
 
906
- // load if network
907
- if ( ! function_exists('is_plugin_active_for_network') ) {
908
- require_once( ABSPATH. 'wp-admin/includes/plugin.php' );
909
  }
910
 
911
- // set clear url w/o query string
912
- $clear_url = preg_replace('/\?.*/', '', home_url( add_query_arg( NULL, NULL ) ));
913
-
914
- // multisite and network setup
915
- if ( is_multisite() && is_plugin_active_for_network(CE_BASE) ) {
916
-
917
- if ( is_network_admin() ) {
918
-
919
- // legacy blog
920
- $legacy = $GLOBALS['wpdb']->blogid;
921
 
922
- // blog ids
923
- $ids = self::_get_blog_ids();
924
 
925
- // switch blogs
926
- foreach ($ids as $id) {
927
- switch_to_blog($id);
928
- self::clear_page_cache_by_url(home_url());
929
- }
930
-
931
- // restore
932
- switch_to_blog($legacy);
933
 
934
  // clear notice
935
  if ( is_admin() ) {
@@ -937,17 +901,18 @@ final class Cache_Enabler {
937
  'network_admin_notices',
938
  array(
939
  __CLASS__,
940
- 'clear_notice'
941
  )
942
  );
943
  }
 
944
  } else {
945
- if ($_GET['_cache'] == 'clearurl') {
946
- // clear specific multisite url cache
947
- self::clear_page_cache_by_url($clear_url);
948
- } else {
949
- // clear specific multisite cache
950
- self::clear_page_cache_by_url(home_url());
951
 
952
  // clear notice
953
  if ( is_admin() ) {
@@ -955,18 +920,19 @@ final class Cache_Enabler {
955
  'admin_notices',
956
  array(
957
  __CLASS__,
958
- 'clear_notice'
959
  )
960
  );
961
  }
962
  }
963
  }
 
964
  } else {
965
- if ($_GET['_cache'] == 'clearurl') {
966
- // clear url cache
967
- self::clear_page_cache_by_url($clear_url);
968
- } else {
969
- // clear cache
970
  self::clear_total_cache();
971
 
972
  // clear notice
@@ -975,7 +941,7 @@ final class Cache_Enabler {
975
  'admin_notices',
976
  array(
977
  __CLASS__,
978
- 'clear_notice'
979
  )
980
  );
981
  }
@@ -985,7 +951,7 @@ final class Cache_Enabler {
985
  if ( ! is_admin() ) {
986
  wp_safe_redirect(
987
  remove_query_arg(
988
- '_cache',
989
  wp_get_referer()
990
  )
991
  );
@@ -1007,13 +973,13 @@ final class Cache_Enabler {
1007
  public static function clear_notice() {
1008
 
1009
  // check if admin
1010
- if ( ! is_admin_bar_showing() OR ! apply_filters('user_can_clear_cache', current_user_can('manage_options')) ) {
1011
  return false;
1012
  }
1013
 
1014
  echo sprintf(
1015
  '<div class="notice notice-success is-dismissible"><p>%s</p></div>',
1016
- esc_html__('The cache has been cleared.', 'cache-enabler')
1017
  );
1018
  }
1019
 
@@ -1022,22 +988,21 @@ final class Cache_Enabler {
1022
  * clear cache if post comment
1023
  *
1024
  * @since 1.2.0
1025
- * @change 1.2.0
1026
  *
1027
- * @param integer $id id of the comment
1028
- * @param mixed $approved approval status
1029
  */
1030
 
1031
- public static function comment_post($id, $approved) {
1032
 
1033
  // check if comment is approved
1034
  if ( $approved === 1 ) {
 
1035
  if ( self::$options['new_comment'] ) {
1036
  self::clear_total_cache();
1037
  } else {
1038
- self::clear_page_cache_by_post_id(
1039
- get_comment($id)->comment_post_ID
1040
- );
1041
  }
1042
  }
1043
  }
@@ -1047,20 +1012,18 @@ final class Cache_Enabler {
1047
  * clear cache if edit comment
1048
  *
1049
  * @since 1.0.0
1050
- * @change 1.0.0
1051
  *
1052
- * @param integer $id id of the comment
1053
  */
1054
 
1055
- public static function edit_comment($id) {
1056
 
1057
- // clear complete cache if option enabled
1058
  if ( self::$options['new_comment'] ) {
1059
  self::clear_total_cache();
1060
  } else {
1061
- self::clear_page_cache_by_post_id(
1062
- get_comment($id)->comment_post_ID
1063
- );
1064
  }
1065
  }
1066
 
@@ -1076,10 +1039,11 @@ final class Cache_Enabler {
1076
  * @return mixed $approved approval status
1077
  */
1078
 
1079
- public static function new_comment($approved, $comment) {
1080
 
1081
  // check if comment is approved
1082
  if ( $approved === 1 ) {
 
1083
  if ( self::$options['new_comment'] ) {
1084
  self::clear_total_cache();
1085
  } else {
@@ -1092,7 +1056,7 @@ final class Cache_Enabler {
1092
 
1093
 
1094
  /**
1095
- * clear cache if comment changes
1096
  *
1097
  * @since 1.0.0
1098
  * @change 1.0.0
@@ -1102,10 +1066,11 @@ final class Cache_Enabler {
1102
  * @param object $comment
1103
  */
1104
 
1105
- public static function change_comment($after_status, $before_status, $comment) {
1106
 
1107
  // check if changes occured
1108
- if ( $after_status != $before_status ) {
 
1109
  if ( self::$options['new_comment'] ) {
1110
  self::clear_total_cache();
1111
  } else {
@@ -1119,39 +1084,38 @@ final class Cache_Enabler {
1119
  * register publish hooks for custom post types
1120
  *
1121
  * @since 1.0.0
1122
- * @since 1.2.3
1123
- *
1124
- * @param void
1125
- * @return void
1126
  */
1127
 
1128
  public static function register_publish_hooks() {
1129
 
1130
  // get post types
1131
  $post_types = get_post_types(
1132
- array('public' => true)
 
 
1133
  );
1134
 
1135
  // check if empty
1136
- if ( empty($post_types) ) {
1137
  return;
1138
  }
1139
 
1140
  // post type actions
1141
  foreach ( $post_types as $post_type ) {
1142
  add_action(
1143
- 'publish_' .$post_type,
1144
  array(
1145
  __CLASS__,
1146
- 'publish_post_types'
1147
  ),
1148
  10,
1149
  2
1150
  );
1151
  add_action(
1152
- 'publish_future_' .$post_type,
1153
  function( $post_id ) {
1154
- // clear complete cache if option enabled
1155
  if ( self::$options['new_post'] ) {
1156
  self::clear_total_cache();
1157
  } else {
@@ -1167,27 +1131,27 @@ final class Cache_Enabler {
1167
  * delete post type cache on post updates
1168
  *
1169
  * @since 1.0.0
1170
- * @change 1.0.7
1171
  *
1172
- * @param integer $post_ID Post ID
1173
  */
1174
 
1175
- public static function publish_post_types($post_ID, $post) {
1176
 
1177
- // check if post id or post is empty
1178
- if ( empty($post_ID) OR empty($post) ) {
1179
  return;
1180
  }
1181
 
1182
  // check post status
1183
- if ( ! in_array( $post->post_status, array('publish', 'future') ) ) {
1184
  return;
1185
  }
1186
 
1187
- // clear cache if clean post on update
1188
- if ( ! isset($_POST['_clear_post_cache_on_update']) ) {
1189
 
1190
- // clear complete cache if option enabled
1191
  if ( self::$options['new_post'] ) {
1192
  return self::clear_total_cache();
1193
  } else {
@@ -1197,17 +1161,17 @@ final class Cache_Enabler {
1197
  }
1198
 
1199
  // validate nonce
1200
- if ( ! isset($_POST['_cache__status_nonce_' .$post_ID]) OR ! wp_verify_nonce($_POST['_cache__status_nonce_' .$post_ID], CE_BASE) ) {
1201
  return;
1202
  }
1203
 
1204
  // validate user role
1205
- if ( ! current_user_can('publish_posts') ) {
1206
  return;
1207
  }
1208
 
1209
- // save as integer
1210
- $clear_post_cache = (int)$_POST['_clear_post_cache_on_update'];
1211
 
1212
  // save user metadata
1213
  update_user_meta(
@@ -1216,64 +1180,83 @@ final class Cache_Enabler {
1216
  $clear_post_cache
1217
  );
1218
 
1219
- // clear complete cache or specific post
1220
  if ( $clear_post_cache ) {
1221
- self::clear_page_cache_by_post_id( $post_ID );
1222
  } else {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1223
  self::clear_total_cache();
1224
  }
 
 
 
1225
  }
1226
 
1227
 
1228
  /**
1229
- * clear page cache by post id
1230
  *
1231
  * @since 1.0.0
1232
- * @change 1.0.0
1233
  *
1234
- * @param integer $post_ID Post ID
1235
  */
1236
 
1237
- public static function clear_page_cache_by_post_id($post_ID) {
1238
 
1239
- // is int
1240
- if ( ! $post_ID = (int)$post_ID ) {
1241
  return;
1242
  }
1243
 
1244
- // clear cache by URL
1245
- self::clear_page_cache_by_url(
1246
- get_permalink( $post_ID )
1247
- );
1248
  }
1249
 
1250
 
1251
  /**
1252
- * clear page cache by url
1253
  *
1254
  * @since 1.0.0
1255
  * @change 1.2.3
1256
  *
1257
- * @param string $url url of a page
1258
  */
1259
 
1260
- public static function clear_page_cache_by_url($url) {
1261
 
1262
  // validate string
1263
- if ( ! $url = (string)$url ) {
1264
  return;
1265
  }
1266
 
1267
  call_user_func(
1268
  array(
1269
  self::$disk,
1270
- 'delete_asset'
1271
  ),
1272
  $url
1273
  );
1274
 
1275
- // clear cache by url post hook
1276
- do_action('ce_action_cache_by_url_cleared');
1277
  }
1278
 
1279
 
@@ -1282,7 +1265,6 @@ final class Cache_Enabler {
1282
  *
1283
  * @since 1.0.7
1284
  * @change 1.2.3
1285
- *
1286
  */
1287
 
1288
  public static function clear_home_page_cache() {
@@ -1290,100 +1272,135 @@ final class Cache_Enabler {
1290
  call_user_func(
1291
  array(
1292
  self::$disk,
1293
- 'clear_home'
1294
  )
1295
  );
1296
 
1297
  // clear home page cache post hook
1298
- do_action('ce_action_home_page_cache_cleared');
1299
  }
1300
 
1301
 
1302
  /**
1303
- * check if index.php
1304
  *
1305
- * @since 1.0.0
1306
- * @change 1.0.0
1307
  *
1308
- * @return boolean true if index.php
1309
  */
1310
 
1311
- private static function _is_index() {
1312
- return strtolower(basename($_SERVER['SCRIPT_NAME'])) != 'index.php';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1313
  }
1314
 
1315
 
1316
  /**
1317
- * check if mobile
1318
  *
1319
  * @since 1.0.0
1320
  * @change 1.0.0
1321
  *
1322
- * @return boolean true if mobile
1323
  */
1324
 
1325
- private static function _is_mobile() {
1326
- return ( strpos(TEMPLATEPATH, 'wptouch') OR strpos(TEMPLATEPATH, 'carrington') OR strpos(TEMPLATEPATH, 'jetpack') OR strpos(TEMPLATEPATH, 'handheld') );
 
1327
  }
1328
 
1329
 
1330
  /**
1331
- * check if logged in
1332
  *
1333
  * @since 1.0.0
1334
  * @change 1.0.0
1335
  *
1336
- * @return boolean true if logged in or cookie set
1337
  */
1338
 
1339
- private static function _is_logged_in() {
1340
-
1341
- // check if logged in
1342
- if ( is_user_logged_in() ) {
1343
- return true;
1344
- }
1345
-
1346
- // check cookie
1347
- if ( empty($_COOKIE) ) {
1348
- return false;
1349
- }
1350
-
1351
- // check cookie values
1352
- $options = self::$options;
1353
- if ( !empty($options['excl_cookies']) ) {
1354
- $cookies_regex = $options['excl_cookies'];
1355
- } else {
1356
- $cookies_regex = '/^(wp-postpass|wordpress_logged_in|comment_author)_/';
1357
- }
1358
 
1359
- foreach ( $_COOKIE as $k => $v) {
1360
- if ( preg_match($cookies_regex, $k) ) {
1361
- return true;
1362
- }
1363
- }
1364
  }
1365
 
1366
 
1367
  /**
1368
- * check if there are post to be published in the future
1369
  *
1370
  * @since 1.2.3
1371
- *
1372
- * @return void
1373
- *
1374
  */
1375
 
1376
  public static function check_future_posts() {
1377
 
1378
- $future_posts = new WP_Query(array('post_status' => array('future')));
 
 
1379
 
1380
  if ( $future_posts->have_posts() ) {
1381
- $post_dates = array_column($future_posts->get_posts(), "post_date");
1382
- sort($post_dates);
1383
- Cache_Enabler_Disk::record_advcache_settings(array(
1384
- "cache_timeout" => strtotime($post_dates[0])));
 
 
1385
  } else {
1386
- Cache_Enabler_Disk::delete_advcache_settings(array("cache_timeout"));
1387
  }
1388
  }
1389
 
@@ -1392,65 +1409,85 @@ final class Cache_Enabler {
1392
  * check to bypass the cache
1393
  *
1394
  * @since 1.0.0
1395
- * @change 1.2.3
1396
  *
1397
- * @return boolean true if exception
1398
  *
1399
- * @hook boolean bypass cache
1400
  */
1401
 
1402
  private static function _bypass_cache() {
1403
 
1404
  // bypass cache hook
1405
- if ( apply_filters('bypass_cache', false) ) {
1406
  return true;
1407
  }
1408
 
1409
- // conditional tags
1410
- if ( self::_is_index() OR is_search() OR is_404() OR is_feed() OR is_trackback() OR is_robots() OR is_preview() OR post_password_required() ) {
1411
  return true;
1412
  }
1413
 
1414
- // DONOTCACHEPAGE check e.g. woocommerce
1415
- if ( defined('DONOTCACHEPAGE') && DONOTCACHEPAGE ) {
1416
  return true;
1417
  }
1418
 
1419
- // cache enabler options
1420
- $options = self::$options;
1421
-
1422
- // Request method GET
1423
- if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || $_SERVER['REQUEST_METHOD'] != 'GET' ) {
1424
  return true;
1425
  }
1426
 
1427
- // Request with query strings
1428
- if ( ! empty($_GET) && ! isset( $_GET['utm_source'], $_GET['utm_medium'], $_GET['utm_campaign'] ) && get_option('permalink_structure') ) {
1429
  return true;
1430
  }
1431
 
1432
- // if logged in
1433
- if ( self::_is_logged_in() ) {
1434
- return true;
1435
- }
1436
 
1437
- // if mobile request
1438
- if ( self::_is_mobile() ) {
1439
- return true;
 
 
1440
  }
1441
 
1442
- // if post id excluded
1443
- if ( $options['excl_ids'] && is_singular() ) {
1444
- if ( in_array( $GLOBALS['wp_query']->get_queried_object_id(), (array)explode(',', $options['excl_ids']) ) ) {
 
 
1445
  return true;
1446
  }
1447
  }
1448
 
1449
- // if post path excluded
1450
- if ( !empty($options['excl_regexp']) ) {
1451
- $url_path = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
 
 
 
 
 
 
 
 
 
 
 
 
1452
 
1453
- if ( preg_match($options['excl_regexp'], $url_path) ) {
 
 
 
 
 
 
 
 
 
1454
  return true;
1455
  }
1456
  }
@@ -1460,7 +1497,7 @@ final class Cache_Enabler {
1460
 
1461
 
1462
  /**
1463
- * minify html
1464
  *
1465
  * @since 1.0.0
1466
  * @change 1.0.0
@@ -1471,30 +1508,30 @@ final class Cache_Enabler {
1471
  * @hook array cache_minify_ignore_tags
1472
  */
1473
 
1474
- private static function _minify_cache($data) {
1475
 
1476
  // check if disabled
1477
  if ( ! self::$options['minify_html'] ) {
1478
  return $data;
1479
  }
1480
 
1481
- // strlen limit
1482
- if ( strlen($data) > 700000) {
1483
  return $data;
1484
  }
1485
 
1486
- // ignore this tags
1487
- $ignore_tags = (array)apply_filters(
1488
  'cache_minify_ignore_tags',
1489
  array(
1490
  'textarea',
1491
- 'pre'
1492
  )
1493
  );
1494
 
1495
  // ignore JS if selected
1496
  if ( self::$options['minify_html'] !== self::MINIFY_HTML_JS ) {
1497
- $ignore_tags[] = 'script';
1498
  }
1499
 
1500
  // return of no ignore tags
@@ -1503,23 +1540,23 @@ final class Cache_Enabler {
1503
  }
1504
 
1505
  // stringify
1506
- $ignore_regex = implode('|', $ignore_tags);
1507
 
1508
  // regex minification
1509
  $cleaned = preg_replace(
1510
  array(
1511
  '/<!--[^\[><](.*?)-->/s',
1512
- '#(?ix)(?>[^\S ]\s*|\s{2,})(?=(?:(?:[^<]++|<(?!/?(?:' .$ignore_regex. ')\b))*+)(?:<(?>' .$ignore_regex. ')\b|\z))#'
1513
  ),
1514
  array(
1515
  '',
1516
- ' '
1517
  ),
1518
  $data
1519
  );
1520
 
1521
  // something went wrong
1522
- if ( strlen($cleaned) <= 1 ) {
1523
  return $data;
1524
  }
1525
 
@@ -1531,36 +1568,46 @@ final class Cache_Enabler {
1531
  * clear complete cache
1532
  *
1533
  * @since 1.0.0
1534
- * @change 1.2.3
1535
  */
1536
 
1537
  public static function clear_total_cache() {
1538
- // we need this here to update advanced-cache.php for the 1.2.3 upgrade
1539
- self::on_upgrade();
1540
 
1541
  // clear disk cache
1542
  Cache_Enabler_Disk::clear_cache();
1543
 
1544
  // delete transient
1545
- delete_transient('cache_size');
1546
 
1547
  // clear cache post hook
1548
- do_action('ce_action_cache_cleared');
1549
  }
1550
 
1551
 
1552
  /**
1553
- * Act on WooCommerce stock changes
1554
  *
1555
- * @since 1.3.0
 
 
 
1556
  */
1557
 
1558
- public static function woocommerce_product_set_stock($product) {
1559
- self::woocommerce_product_set_stock_status($product->get_id());
1560
- }
1561
 
1562
- public static function woocommerce_product_set_stock_status($product_id) {
1563
- self::clear_total_cache();
 
 
 
 
 
 
 
 
 
 
 
1564
  }
1565
 
1566
 
@@ -1568,28 +1615,30 @@ final class Cache_Enabler {
1568
  * set cache
1569
  *
1570
  * @since 1.0.0
1571
- * @change 1.0.0
1572
  *
1573
  * @param string $data content of a page
1574
  * @return string $data content of a page
 
 
1575
  */
1576
 
1577
- public static function set_cache($data) {
1578
 
1579
  // check if empty
1580
- if ( empty($data) ) {
1581
  return '';
1582
  }
1583
 
1584
- $data = apply_filters('cache_enabler_before_store', $data);
1585
 
1586
  // store as asset
1587
  call_user_func(
1588
  array(
1589
  self::$disk,
1590
- 'store_asset'
1591
  ),
1592
- self::_minify_cache($data)
1593
  );
1594
 
1595
  return $data;
@@ -1600,7 +1649,7 @@ final class Cache_Enabler {
1600
  * handle cache
1601
  *
1602
  * @since 1.0.0
1603
- * @change 1.0.1
1604
  */
1605
 
1606
  public static function handle_cache() {
@@ -1614,32 +1663,32 @@ final class Cache_Enabler {
1614
  $cached = call_user_func(
1615
  array(
1616
  self::$disk,
1617
- 'check_asset'
1618
  )
1619
  );
1620
 
1621
- // check if cache empty
1622
- if ( empty($cached) ) {
1623
- ob_start('Cache_Enabler::set_cache');
 
 
 
 
 
1624
  return;
1625
  }
1626
 
1627
- // get expiry status
1628
  $expired = call_user_func(
1629
  array(
1630
  self::$disk,
1631
- 'check_expiry'
1632
  )
1633
  );
1634
 
1635
- // check if expired
1636
  if ( $expired ) {
1637
- ob_start('Cache_Enabler::set_cache');
1638
- return;
1639
- }
1640
-
1641
- // check if we are missing a trailing slash
1642
- if ( self::missing_trailing_slash() ) {
1643
  return;
1644
  }
1645
 
@@ -1647,7 +1696,7 @@ final class Cache_Enabler {
1647
  call_user_func(
1648
  array(
1649
  self::$disk,
1650
- 'get_asset'
1651
  )
1652
  );
1653
  }
@@ -1657,26 +1706,26 @@ final class Cache_Enabler {
1657
  * add clear option dropdown on post publish widget
1658
  *
1659
  * @since 1.0.0
1660
- * @change 1.0.0
1661
  */
1662
 
1663
  public static function add_clear_dropdown() {
1664
 
1665
- // on published post page only
1666
- if ( empty($GLOBALS['pagenow']) OR $GLOBALS['pagenow'] !== 'post.php' OR empty($GLOBALS['post']) OR ! is_object($GLOBALS['post']) OR $GLOBALS['post']->post_status !== 'publish' ) {
1667
  return;
1668
  }
1669
 
1670
  // check user role
1671
- if ( ! current_user_can('publish_posts') ) {
1672
  return;
1673
  }
1674
 
1675
  // validate nonce
1676
- wp_nonce_field(CE_BASE, '_cache__status_nonce_' .$GLOBALS['post']->ID);
1677
 
1678
- // get current action
1679
- $current_action = (int)get_user_meta(
1680
  get_current_user_id(),
1681
  '_clear_post_cache_on_update',
1682
  true
@@ -1685,25 +1734,25 @@ final class Cache_Enabler {
1685
  // init variables
1686
  $dropdown_options = '';
1687
  $available_options = array(
1688
- esc_html__('Completely', 'cache-enabler'),
1689
- esc_html__('Page specific', 'cache-enabler')
1690
  );
1691
 
1692
  // set dropdown options
1693
- foreach( $available_options as $key => $value ) {
1694
  $dropdown_options .= sprintf(
1695
  '<option value="%1$d" %3$s>%2$s</option>',
1696
  $key,
1697
  $value,
1698
- selected($key, $current_action, false)
1699
  );
1700
  }
1701
 
1702
- // output drowdown
1703
  echo sprintf(
1704
  '<div class="misc-pub-section" style="border-top:1px solid #eee">
1705
  <label for="cache_action">
1706
- %1$s: <span id="output-cache-action">%2$s</span>
1707
  </label>
1708
  <a href="#" class="edit-cache-action hide-if-no-js">%3$s</a>
1709
 
@@ -1713,15 +1762,15 @@ final class Cache_Enabler {
1713
  </select>
1714
 
1715
  <a href="#" class="save-cache-action hide-if-no-js button">%5$s</a>
1716
- <a href="#" class="cancel-cache-action hide-if-no-js button-cancel">%6$s</a>
1717
  </div>
1718
  </div>',
1719
- esc_html__('Clear cache', 'cache-enabler'),
1720
- $available_options[$current_action],
1721
- esc_html__('Edit'),
1722
  $dropdown_options,
1723
- esc_html__('OK'),
1724
- esc_html__('Cancel')
1725
  );
1726
  }
1727
 
@@ -1733,7 +1782,7 @@ final class Cache_Enabler {
1733
  * @change 1.0.0
1734
  */
1735
 
1736
- public static function add_admin_resources($hook) {
1737
 
1738
  // hook check
1739
  if ( $hook !== 'index.php' && $hook !== 'post.php' ) {
@@ -1741,16 +1790,16 @@ final class Cache_Enabler {
1741
  }
1742
 
1743
  // plugin data
1744
- $plugin_data = get_plugin_data(CE_FILE);
1745
 
1746
  // enqueue scripts
1747
- switch($hook) {
1748
 
1749
  case 'post.php':
1750
  wp_enqueue_script(
1751
  'cache-post',
1752
- plugins_url('js/post.js', CE_FILE),
1753
- array('jquery'),
1754
  $plugin_data['Version'],
1755
  true
1756
  );
@@ -1778,7 +1827,7 @@ final class Cache_Enabler {
1778
  'cache-enabler',
1779
  array(
1780
  __CLASS__,
1781
- 'settings_page'
1782
  )
1783
  );
1784
  }
@@ -1790,39 +1839,36 @@ final class Cache_Enabler {
1790
  * @since 1.0.0
1791
  * @change 1.0.0
1792
  *
1793
- * @return array Key => value array
1794
  */
1795
 
1796
  private static function _minify_select() {
1797
 
1798
  return array(
1799
- self::MINIFY_DISABLED => esc_html__('Disabled', 'cache-enabler'),
1800
- self::MINIFY_HTML_ONLY => esc_html__('HTML', 'cache-enabler'),
1801
- self::MINIFY_HTML_JS => esc_html__('HTML & Inline JS', 'cache-enabler')
1802
  );
1803
  }
1804
 
1805
 
1806
  /**
1807
- * Check plugin requirements
1808
  *
1809
  * @since 1.1.0
1810
- * @change 1.1.0
1811
  */
1812
 
1813
  public static function requirements_check() {
1814
 
1815
- // cache enabler options
1816
- $options = self::$options;
1817
-
1818
  // WordPress version check
1819
- if ( version_compare($GLOBALS['wp_version'], CE_MIN_WP.'alpha', '<') ) {
1820
  show_message(
1821
  sprintf(
1822
  '<div class="error"><p>%s</p></div>',
1823
  sprintf(
1824
- __('The <b>%s</b> is optimized for WordPress %s. Please disable the plugin or upgrade your WordPress installation (recommended).', 'cache-enabler'),
1825
- 'Cache Enabler',
1826
  CE_MIN_WP
1827
  )
1828
  )
@@ -1830,31 +1876,39 @@ final class Cache_Enabler {
1830
  }
1831
 
1832
  // permission check
1833
- if ( file_exists( CE_CACHE_DIR ) && !is_writable( CE_CACHE_DIR ) ) {
1834
  show_message(
1835
  sprintf(
1836
  '<div class="error"><p>%s</p></div>',
1837
  sprintf(
1838
- __('The <b>%s</b> requires write permissions %s on %s. Please <a href="%s" target="_blank">change the permissions</a>.', 'cache-enabler'),
1839
- 'Cache Enabler',
1840
  '<code>755</code>',
1841
  '<code>wp-content/cache</code>',
1842
- 'http://codex.wordpress.org/Changing_File_Permissions',
1843
- CE_MIN_WP
 
 
 
1844
  )
1845
  )
1846
  );
1847
  }
1848
 
1849
  // autoptimize minification check
1850
- if ( defined('AUTOPTIMIZE_PLUGIN_DIR') && $options['minify_html'] && get_option('autoptimize_html', '') != '' ) {
1851
  show_message(
1852
  sprintf(
1853
  '<div class="error"><p>%s</p></div>',
1854
  sprintf(
1855
- __('The <b>%s</b> plugin is already active. Please disable minification in the <b>%s</b> settings.', 'cache-enabler'),
1856
- 'Autoptimize',
1857
- 'Cache Enabler'
 
 
 
 
 
1858
  )
1859
  )
1860
  );
@@ -1871,6 +1925,7 @@ final class Cache_Enabler {
1871
 
1872
  public static function register_textdomain() {
1873
 
 
1874
  load_plugin_textdomain(
1875
  'cache-enabler',
1876
  false,
@@ -1878,35 +1933,6 @@ final class Cache_Enabler {
1878
  );
1879
  }
1880
 
1881
- /**
1882
- * missing training slash
1883
- *
1884
- * we only have to really check that in advanced-cache.php
1885
- *
1886
- * @since 1.2.3
1887
- *
1888
- * @return boolean true if we need to redirct, otherwise false
1889
- */
1890
-
1891
- public static function missing_trailing_slash() {
1892
- if ( ($permalink_structure = get_option('permalink_structure')) &&
1893
- preg_match("/\/$/", $permalink_structure) ) {
1894
-
1895
- // record permalink structure for advanced-cache
1896
- Cache_Enabler_Disk::record_advcache_settings(array(
1897
- "permalink_trailing_slash" => true
1898
- ));
1899
-
1900
- if ( ! preg_match("/\/(|\?.*)$/", $_SERVER["REQUEST_URI"]) ) {
1901
- return true;
1902
- }
1903
- } else {
1904
- Cache_Enabler_Disk::delete_advcache_settings(array(
1905
- "permalink_trailing_slash"));
1906
- }
1907
-
1908
- return false;
1909
- }
1910
 
1911
  /**
1912
  * register settings
@@ -1922,33 +1948,71 @@ final class Cache_Enabler {
1922
  'cache-enabler',
1923
  array(
1924
  __CLASS__,
1925
- 'validate_settings'
1926
  )
1927
  );
1928
  }
1929
 
1930
 
1931
  /**
1932
- * validate regexps
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1933
  *
1934
  * @since 1.2.3
 
1935
  *
1936
- * @param string $re string containing regexps
1937
- * @return string string containing regexps or emty string if input invalid
1938
  */
1939
 
1940
- public static function validate_regexps($re) {
1941
- if ( $re != '' ) {
1942
 
1943
- if ( ! preg_match('/^\/.*\/$/', $re) ) {
1944
- $re = '/'.$re.'/';
 
1945
  }
1946
 
1947
- if ( @preg_match($re, null) === false ) {
1948
  return '';
1949
  }
1950
 
1951
- return sanitize_text_field($re);
1952
  }
1953
 
1954
  return '';
@@ -1958,69 +2022,67 @@ final class Cache_Enabler {
1958
  * validate settings
1959
  *
1960
  * @since 1.0.0
1961
- * @change 1.2.3
1962
  *
1963
- * @param array $data array form data
1964
- * @return array array form data valid
1965
  */
1966
 
1967
- public static function validate_settings($data) {
1968
 
1969
  // check if empty
1970
- if ( empty($data) ) {
1971
  return;
1972
  }
1973
 
1974
- // clear complete cache
1975
- self::clear_total_cache(true);
 
 
1976
 
1977
- // ignore result, but call for settings recording
1978
- self::missing_trailing_slash();
1979
 
1980
- // record expiry time value for advanced-cache.php
1981
  if ( $data['expires'] > 0 ){
1982
- Cache_Enabler_Disk::record_advcache_settings(array(
1983
- "expires" => $data['expires']));
1984
- } else {
1985
- Cache_Enabler_Disk::delete_advcache_settings(array("expires"));
1986
- }
1987
-
1988
- // path bypass regexp
1989
- if ( strlen($data["excl_regexp"]) > 0 ) {
1990
- Cache_Enabler_Disk::record_advcache_settings(array(
1991
- "excl_regexp" => $data["excl_regexp"]));
1992
  } else {
1993
- Cache_Enabler_Disk::delete_advcache_settings(array("excl_regexp"));
1994
  }
1995
 
1996
- // custom cookie exceptions
1997
- if ( strlen($data["excl_cookies"]) > 0 ) {
1998
- Cache_Enabler_Disk::record_advcache_settings(array(
1999
- "excl_cookies" => $data["excl_cookies"]));
 
2000
  } else {
2001
- Cache_Enabler_Disk::delete_advcache_settings(array("excl_cookies"));
2002
  }
2003
 
2004
- // custom GET attribute exceptions
2005
- if ( strlen($data["incl_attributes"]) > 0 ) {
2006
- Cache_Enabler_Disk::record_advcache_settings(array(
2007
- "incl_attributes" => $data["incl_attributes"]));
 
2008
  } else {
2009
- Cache_Enabler_Disk::delete_advcache_settings(array("incl_attributes"));
2010
  }
2011
 
2012
  return array(
2013
- 'expires' => (int)$data['expires'],
2014
- 'new_post' => (int)(!empty($data['new_post'])),
2015
- 'new_comment' => (int)(!empty($data['new_comment'])),
2016
- 'webp' => (int)(!empty($data['webp'])),
2017
- 'clear_on_upgrade' => (int)(!empty($data['clear_on_upgrade'])),
2018
- 'compress' => (int)(!empty($data['compress'])),
2019
- 'excl_ids' => (string)sanitize_text_field(@$data['excl_ids']),
2020
- 'excl_regexp' => (string)self::validate_regexps(@$data['excl_regexp']),
2021
- 'excl_cookies' => (string)self::validate_regexps(@$data['excl_cookies']),
2022
- 'incl_attributes' => (string)self::validate_regexps(@$data['incl_attributes']),
2023
- 'minify_html' => (int)$data['minify_html']
 
2024
  );
2025
  }
2026
 
@@ -2029,92 +2091,104 @@ final class Cache_Enabler {
2029
  * settings page
2030
  *
2031
  * @since 1.0.0
2032
- * @change 1.2.3
2033
  */
2034
 
2035
  public static function settings_page() {
2036
 
2037
- // wp cache check
2038
- if ( !defined('WP_CACHE') || !WP_CACHE ) {
2039
- echo sprintf(
2040
- '<div class="notice notice-warning"><p>%s</p></div>',
2041
  sprintf(
2042
- __("%s is not set in %s.", 'cache-enabler'),
2043
- "<code>define('WP_CACHE', true);</code>",
2044
- "wp-config.php"
 
 
 
2045
  )
2046
  );
2047
  }
2048
 
2049
  ?>
2050
 
2051
- <div class="wrap" id="cache-settings">
2052
  <h2>
2053
- <?php _e("Cache Enabler Settings", "cache-enabler") ?>
2054
  </h2>
2055
 
2056
  <div class="notice notice-info" style="margin-bottom: 35px;">
2057
- <p><?php printf( __('Combine <b><a href="%s">%s</a></b> with Cache Enabler for even better WordPress performance and achieve the next level of caching with a CDN.', 'cache-enabler'), 'https://www.keycdn.com?utm_source=wp-admin&utm_medium=plugins&utm_campaign=cache-enabler', 'KeyCDN'); ?></p>
 
 
 
 
 
 
 
2058
  </div>
2059
 
2060
- <p><?php $size=self::get_cache_size(); printf( __("Current cache size: <b>%s</b>", "cache-enabler"), ( empty($size) ? esc_html__("Empty", "cache-enabler") : size_format($size) ) ); ?></p>
2061
-
2062
  <form method="post" action="options.php">
2063
- <?php settings_fields('cache-enabler') ?>
2064
-
2065
- <?php $options = self::_get_options() ?>
2066
-
2067
  <table class="form-table">
2068
  <tr valign="top">
2069
  <th scope="row">
2070
- <?php _e("Cache Expiry", "cache-enabler") ?>
2071
  </th>
2072
  <td>
2073
- <fieldset>
2074
- <label for="cache_expires">
2075
- <input type="text" name="cache-enabler[expires]" id="cache_expires" value="<?php echo esc_attr($options['expires']) ?>" />
2076
- <p class="description"><?php _e("Cache expiry in hours. An expiry time of 0 means that the cache never expires.", "cache-enabler"); ?></p>
2077
- </label>
2078
- </fieldset>
2079
  </td>
2080
  </tr>
2081
  <tr valign="top">
2082
  <th scope="row">
2083
- <?php _e("Cache Behavior", "cache-enabler") ?>
2084
  </th>
2085
  <td>
2086
  <fieldset>
 
 
 
 
 
 
 
 
2087
  <label for="cache_new_post">
2088
- <input type="checkbox" name="cache-enabler[new_post]" id="cache_new_post" value="1" <?php checked('1', $options['new_post']); ?> />
2089
- <?php _e("Clear the complete cache if a new post has been published (instead of only the home page cache).", "cache-enabler") ?>
2090
  </label>
2091
 
2092
  <br />
2093
 
2094
  <label for="cache_new_comment">
2095
- <input type="checkbox" name="cache-enabler[new_comment]" id="cache_new_comment" value="1" <?php checked('1', $options['new_comment']); ?> />
2096
- <?php _e("Clear the complete cache if a new comment has been posted (instead of only the page specific cache).", "cache-enabler") ?>
2097
  </label>
2098
 
2099
  <br />
2100
 
2101
- <label for="cache_compress">
2102
- <input type="checkbox" name="cache-enabler[compress]" id="cache_compress" value="1" <?php checked('1', $options['compress']); ?> />
2103
- <?php _e("Pre-compression of cached pages. Needs to be disabled if the decoding fails in the web browser.", "cache-enabler") ?>
 
 
2104
  </label>
2105
 
2106
  <br />
 
2107
 
2108
- <label for="cache_webp">
2109
- <input type="checkbox" name="cache-enabler[webp]" id="cache_webp" value="1" <?php checked('1', $options['webp']); ?> />
2110
- <?php _e("Create an additional cached version for WebP image support. Convert your images to WebP with <a href=\"https://optimus.io/en/\" target=\"_blank\">Optimus</a>.", "cache-enabler") ?>
2111
  </label>
2112
 
2113
  <br />
2114
 
2115
- <label for="cache_clear_on_upgrade">
2116
- <input type="checkbox" name="cache-enabler[clear_on_upgrade]" id="cache_clear_on_upgrade" value="1" <?php checked('1', $options['clear_on_upgrade']); ?> />
2117
- <?php _e("Clear the complete cache if any plugin has been upgraded.", "cache-enabler") ?>
2118
  </label>
2119
  </fieldset>
2120
  </td>
@@ -2122,36 +2196,32 @@ final class Cache_Enabler {
2122
 
2123
  <tr valign="top">
2124
  <th scope="row">
2125
- <?php _e("Cache Exclusions", "cache-enabler") ?>
2126
  </th>
2127
  <td>
2128
  <fieldset>
2129
  <label for="cache_excl_ids">
2130
- <input type="text" name="cache-enabler[excl_ids]" id="cache_excl_ids" value="<?php echo esc_attr($options['excl_ids']) ?>" />
2131
- <p class="description">
2132
- <?php echo sprintf(__("Post or Pages IDs separated by a %s that should not be cached.", "cache-enabler"), "<code>,</code>"); ?>
2133
  </p>
2134
  </label>
2135
 
2136
  <br />
2137
 
2138
- <label for="cache_excl_regexp">
2139
- <input type="text" name="cache-enabler[excl_regexp]" id="cache_excl_regexp" value="<?php echo esc_attr($options['excl_regexp']) ?>" />
2140
- <p class="description">
2141
- <?php _e("Regexp matching page paths that should not be cached.", "cache-enabler"); ?><br>
2142
- <?php _e("Example:", "cache-enabler"); ?> <code>/(^\/$|\/robot\/$|^\/2018\/.*\/test\/)/</code>
2143
- </p>
2144
  </label>
2145
 
2146
  <br />
2147
 
2148
  <label for="cache_excl_cookies">
2149
- <input type="text" name="cache-enabler[excl_cookies]" id="cache_excl_cookies" value="<?php echo esc_attr($options['excl_cookies']) ?>" />
2150
- <p class="description">
2151
- <?php _e("Regexp matching cookies that should cause the cache to be bypassed.", "cache-enabler"); ?><br>
2152
- <?php _e("Example:", "cache-enabler"); ?> <code>/^(wp-postpass|wordpress_logged_in|comment_author|(woocommerce_items_in_cart|wp_woocommerce_session)_?)/</code><br>
2153
- <?php _e("Default if unset:", "cache-enabler"); ?> <code>/^(wp-postpass|wordpress_logged_in|comment_author)_/</code>
2154
- </p>
2155
  </label>
2156
  </fieldset>
2157
  </td>
@@ -2159,17 +2229,15 @@ final class Cache_Enabler {
2159
 
2160
  <tr valign="top">
2161
  <th scope="row">
2162
- <?php _e("Cache Inclusions", "cache-enabler") ?>
2163
  </th>
2164
  <td>
2165
  <fieldset>
2166
- <label for="cache_incl_attributes">
2167
- <input type="text" name="cache-enabler[incl_attributes]" id="cache_incl_attributes" value="<?php echo esc_attr($options['incl_attributes']) ?>" />
2168
- <p class="description">
2169
- <?php _e("Regexp matching campaign tracking GET attributes that should not cause the cache to be bypassed.", "cache-enabler"); ?><br>
2170
- <?php _e("Example:", "cache-enabler"); ?> <code>/^pk_(source|medium|campaign|kwd|content)$/</code><br>
2171
- <?php _e("Default if unset:", "cache-enabler"); ?> <code>/^utm_(source|medium|campaign|term|content)$/</code>
2172
- </p>
2173
  </label>
2174
  </fieldset>
2175
  </td>
@@ -2177,32 +2245,30 @@ final class Cache_Enabler {
2177
 
2178
  <tr valign="top">
2179
  <th scope="row">
2180
- <?php _e("Cache Minification", "cache-enabler") ?>
2181
  </th>
2182
  <td>
2183
  <label for="cache_minify_html">
2184
  <select name="cache-enabler[minify_html]" id="cache_minify_html">
2185
- <?php foreach( self::_minify_select() as $k => $v ) { ?>
2186
- <option value="<?php echo esc_attr($k) ?>" <?php selected($options['minify_html'], $k); ?>>
2187
- <?php echo esc_html($v) ?>
2188
  </option>
2189
- <?php } ?>
2190
  </select>
2191
  </label>
2192
  </td>
2193
  </tr>
2194
-
2195
- <tr valign="top">
2196
- <th scope="row">
2197
- <?php submit_button() ?>
2198
- </th>
2199
- <td>
2200
- <p class="description"><?php _e("Saving these settings will clear the complete cache.", "cache-enabler") ?></p>
2201
- </td>
2202
- </tr>
2203
  </table>
 
 
 
 
 
2204
  </form>
2205
- <p class="description"><?php _e("It is recommended to enable HTTP/2 on your origin server and use a CDN that supports HTTP/2. Avoid domain sharding and concatenation of your assets to benefit from parallelism of HTTP/2.", "cache-enabler") ?></p>
2206
- </div><?php
 
 
2207
  }
2208
  }
2
 
3
 
4
  // exit
5
+ defined( 'ABSPATH' ) || exit;
6
 
7
 
8
  /**
9
  * Cache_Enabler
10
  *
11
+ * @since 1.0.0
12
  */
13
 
14
  final class Cache_Enabler {
41
  * @var integer
42
  */
43
 
44
+ const MINIFY_DISABLED = 0;
45
  const MINIFY_HTML_ONLY = 1;
46
+ const MINIFY_HTML_JS = 2;
47
 
48
 
49
  /**
53
  * @change 1.0.0
54
  */
55
 
56
+ public static function instance() {
57
+
58
  new self();
59
  }
60
 
63
  * constructor
64
  *
65
  * @since 1.0.0
66
+ * @change 1.4.0
 
 
 
67
  */
68
 
69
+ public function __construct() {
70
+
71
  // set default vars
72
  self::_set_default_vars();
73
 
74
+ // init hooks
75
+ add_action( 'init', array( __CLASS__, 'process_clear_request' ) );
76
+ add_action( 'init', array( __CLASS__, 'register_textdomain' ) );
77
+ add_action( 'init', array( __CLASS__, 'register_publish_hooks' ), 99 );
 
 
 
 
 
78
 
79
  // clear cache hooks
80
+ add_action( 'ce_clear_post_cache', array( __CLASS__, 'clear_page_cache_by_post_id' ) );
81
+ add_action( 'ce_clear_cache', array( __CLASS__, 'clear_total_cache' ) );
82
+ add_action( '_core_updated_successfully', array( __CLASS__, 'clear_total_cache' ) );
83
+ add_action( 'upgrader_process_complete', array( __CLASS__, 'on_upgrade' ), 10, 2 );
84
+ add_action( 'switch_theme', array( __CLASS__, 'clear_total_cache' ) );
85
+ add_action( 'activated_plugin', array( __CLASS__, 'on_plugin_activation_deactivation' ), 10, 2 );
86
+ add_action( 'deactivated_plugin', array( __CLASS__, 'on_plugin_activation_deactivation' ), 10, 2 );
87
+ add_action( 'wp_trash_post', array( __CLASS__, 'on_trash_post' ) );
88
+ // third party
89
+ add_action( 'autoptimize_action_cachepurged', array( __CLASS__, 'clear_total_cache' ) );
90
+ add_action( 'woocommerce_product_set_stock', array( __CLASS__, 'on_woocommerce_stock_update' ) );
91
+ add_action( 'woocommerce_product_set_stock_status', array( __CLASS__, 'on_woocommerce_stock_update' ) );
92
+ add_action( 'woocommerce_variation_set_stock', array( __CLASS__, 'on_woocommerce_stock_update' ) );
93
+ add_action( 'woocommerce_variation_set_stock_status', array( __CLASS__, 'on_woocommerce_stock_update' ) );
94
+
95
+ // advanced cache hooks
96
+ add_action( 'permalink_structure_changed', array( __CLASS__, 'create_advcache_settings' ) );
97
+ add_action( 'save_post', array( __CLASS__, 'check_future_posts' ) );
98
+
99
+ // admin bar hooks
100
+ add_action( 'admin_bar_menu', array( __CLASS__, 'add_admin_links' ), 90 );
101
+
102
+ // admin interface hooks
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  if ( is_admin() ) {
104
+ // multisite
105
+ add_action( 'wp_initialize_site', array( __CLASS__, 'install_later' ) );
106
+ add_action( 'wp_uninitialize_site', array( __CLASS__, 'uninstall_later' ) );
107
+ // settings
108
+ add_action( 'admin_init', array( __CLASS__, 'register_settings' ) );
109
+ add_action( 'admin_menu', array( __CLASS__, 'add_settings_page' ) );
110
+ add_action( 'admin_enqueue_scripts', array( __CLASS__, 'add_admin_resources' ) );
111
+ add_filter( 'plugin_row_meta', array( __CLASS__, 'row_meta' ), 10, 2 );
112
+ // comments
113
+ add_action( 'transition_comment_status', array( __CLASS__, 'change_comment' ), 10, 3 );
114
+ add_action( 'comment_post', array( __CLASS__, 'comment_post' ), 99, 2 );
115
+ add_action( 'edit_comment', array( __CLASS__, 'edit_comment' ) );
116
+ // dashboard
117
+ add_filter( 'dashboard_glance_items', array( __CLASS__, 'add_dashboard_count' ) );
118
+ add_action( 'post_submitbox_misc_actions', array( __CLASS__, 'add_clear_dropdown' ) );
119
+ add_filter( 'plugin_action_links_' . CE_BASE, array( __CLASS__, 'action_links' ) );
120
+ // warnings and notices
121
+ add_action( 'admin_notices', array( __CLASS__, 'warning_is_permalink' ) );
122
+ add_action( 'admin_notices', array( __CLASS__, 'requirements_check' ) );
123
+ // caching hooks
124
+ } else {
125
+ // comments
126
+ add_action( 'pre_comment_approved', array( __CLASS__, 'new_comment' ), 99, 2 );
127
+ // output buffer
128
+ add_action( 'template_redirect', array( __CLASS__, 'handle_cache' ), 0 );
129
+ }
130
+ }
 
 
131
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
132
 
133
+ /**
134
+ * activation hook
135
+ *
136
+ * @since 1.0.0
137
+ * @change 1.4.0
138
+ *
139
+ * @param boolean $network_wide network activated
140
+ */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
+ public static function on_activation( $network_wide ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
+ // activation requirements
145
+ self::on_ce_activation_deactivation( 'activated', $network_wide );
 
 
 
 
 
 
 
 
 
 
 
 
 
146
 
147
+ // set WP_CACHE
148
+ if ( ! defined( 'WP_CACHE' ) || ! WP_CACHE ) {
149
+ self::_set_wp_cache();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  }
151
+
152
+ // copy advanced cache file
153
+ copy( CE_DIR . '/advanced-cache.php', WP_CONTENT_DIR . '/advanced-cache.php' );
154
  }
155
 
156
 
158
  * deactivation hook
159
  *
160
  * @since 1.0.0
161
+ * @change 1.4.0
162
+ *
163
+ * @param boolean $network_wide network deactivated
164
  */
165
 
166
+ public static function on_deactivation( $network_wide ) {
167
+
168
+ // deactivation requirements
169
+ self::on_ce_activation_deactivation( 'deactivated', $network_wide );
170
 
171
+ // unset WP_CACHE
172
  if ( defined( 'WP_CACHE' ) && WP_CACHE ) {
173
+ self::_set_wp_cache( false );
 
174
  }
175
 
176
  // delete advanced cache file
177
+ unlink( WP_CONTENT_DIR . '/advanced-cache.php' );
178
  }
179
 
180
 
181
  /**
182
+ * Cache Enabler activation and deactivation actions
183
  *
184
+ * @since 1.4.0
185
+ * @change 1.4.0
186
+ *
187
+ * @param string $action activated or deactivated
188
+ * @param boolean $network_wide network activated or deactivated
189
  */
190
 
191
+ public static function on_ce_activation_deactivation( $action, $network_wide ) {
192
 
193
+ // network activated
194
+ if ( is_multisite() && $network_wide ) {
195
+ // blog IDs
196
+ $blog_ids = self::_get_blog_ids();
197
 
198
+ // switch to each blog in network
199
+ foreach ( $blog_ids as $blog_id ) {
200
+ switch_to_blog( $blog_id );
201
+
202
+ if ( $action === 'activated' ) {
203
+ // install requirements
204
+ self::_install_backend();
205
+ }
206
+
207
+ if ( $action === 'deactivated' ) {
208
+ // delete advanced cache settings file
209
+ Cache_Enabler_Disk::delete_advcache_settings();
210
+ }
211
  }
212
 
213
  // restore blog
214
  restore_current_blog();
215
+ // site activated
216
  } else {
217
+ if ( $action === 'activated') {
218
+ // install requirements
219
+ self::_install_backend();
220
+ }
221
+
222
+ if ( $action === 'deactivated') {
223
+ // delete advanced cache settings file
224
+ Cache_Enabler_Disk::delete_advcache_settings();
225
+ }
226
  }
227
 
228
+ if ( $action === 'deactivated') {
229
+ // clear complete cache
230
+ self::clear_total_cache();
231
  }
232
+ }
233
 
234
+
235
+ /**
236
+ * plugin activation and deactivation hooks
237
+ *
238
+ * @since 1.4.0
239
+ * @change 1.4.0
240
+ */
241
+
242
+ public static function on_plugin_activation_deactivation() {
243
+
244
+ // if option enabled clear complete cache on any plugin activation or deactivation
245
+ if ( self::$options['clear_on_upgrade'] ) {
246
+ self::clear_total_cache();
247
+ }
248
  }
249
 
250
 
251
  /**
252
+ * upgrade hook
253
+ *
254
+ * @since 1.2.3
255
+ * @change 1.4.0
256
  *
257
+ * @param WP_Upgrader $obj upgrade instance
258
+ * @param array $data update data
259
  */
260
 
261
+ public static function on_upgrade( $obj, $data ) {
262
+
263
+ // if option enabled clear complete cache on any plugin update
264
  if ( self::$options['clear_on_upgrade'] ) {
265
  self::clear_total_cache();
266
  }
267
 
268
+ // check updated plugins
269
+ if ( $data['action'] === 'update' && $data['type'] === 'plugin' && array_key_exists( 'plugins', $data ) ) {
270
+ foreach ( (array) $data['plugins'] as $each_plugin ) {
271
+ // if Cache Enabler has been updated
272
+ if ( $each_plugin === CE_BASE ) {
273
+ // update requirements
274
+ if ( is_multisite() && is_plugin_active_for_network( CE_BASE ) ) {
275
+ $network_wide = true;
276
+ self::on_ce_update( $network_wide );
277
+ } else {
278
+ $network_wide = false;
279
+ self::on_ce_update( $network_wide );
280
+ }
281
  }
282
  }
283
  }
285
 
286
 
287
  /**
288
+ * Cache Enabler update actions
289
+ *
290
+ * @since 1.4.0
291
+ * @change 1.4.0
292
  *
293
+ * @param boolean $network_wide network activated
294
  */
295
 
296
+ public static function on_ce_update( $network_wide ) {
297
+
298
+ // delete advanced cache settings file(s) and clear complete cache
299
+ self::on_ce_activation_deactivation( 'deactivated', $network_wide );
300
+ // decom: delete old advanced cache settings file(s) (1.4.0)
301
+ array_map( 'unlink', glob( WP_CONTENT_DIR . '/cache/cache-enabler-advcache-*.json' ) );
302
+
303
+ // create advanced cache settings file(s)
304
+ self::on_ce_activation_deactivation( 'activated', $network_wide );
305
+
306
+ // update advanced cache file that might have changed
307
+ copy( CE_DIR . '/advanced-cache.php', WP_CONTENT_DIR . '/advanced-cache.php' );
308
  }
309
 
310
 
311
  /**
312
+ * create or update advanced cache settings
313
+ *
314
+ * @since 1.4.0
315
+ * @change 1.4.0
316
+ */
317
+
318
+ public static function create_advcache_settings() {
319
+
320
+ // get Cache Enabler options
321
+ $options = self::_get_options();
322
+
323
+ // create advanced cache settings file
324
+ if ( empty( $options ) ) {
325
+ // ignore results and only call permalink structure recording
326
+ self::handle_trailing_slash();
327
+ } else {
328
+ // ignore results and call all advance cache settings recordings
329
+ self::validate_settings( $options );
330
+ }
331
+ }
332
+
333
+
334
+ /**
335
+ * install Cache Enabler on new site in multisite network
336
  *
337
  * @since 1.0.0
338
+ * @change 1.4.0
339
+ *
340
+ * @param WP_Site $new_site new site instance
341
  */
342
 
343
+ public static function install_later( $new_site ) {
344
 
345
+ // check if network activated
346
+ if ( ! is_plugin_active_for_network( CE_BASE ) ) {
347
  return;
348
  }
349
 
350
  // switch to blog
351
+ switch_to_blog( (int) $new_site->blog_id );
352
 
353
+ // install requirements
354
  self::_install_backend();
355
 
356
+ // restore blog
357
  restore_current_blog();
358
  }
359
 
360
 
361
  /**
362
+ * installation requirements
363
  *
364
  * @since 1.0.0
365
+ * @change 1.4.0
366
  */
367
 
368
  private static function _install_backend() {
369
 
370
+ // add default Cache Enabler option if not already added
371
+ add_option( 'cache-enabler', array() );
 
 
372
 
373
+ // create advanced cache settings file
374
+ self::create_advcache_settings();
375
  }
376
 
377
 
378
  /**
379
+ * uninstall Cache Enabler
380
+ *
381
+ * @since 1.0.0
382
+ * @change 1.4.0
383
+ */
384
+
385
+ public static function on_uninstall() {
386
+
387
+ // network
388
+ if ( is_multisite() ) {
389
+ // blog IDs
390
+ $blog_ids = self::_get_blog_ids();
391
+
392
+ // switch to each blog in network
393
+ foreach ( $blog_ids as $blog_id ) {
394
+ switch_to_blog( $blog_id );
395
+ // uninstall requirements
396
+ self::_uninstall_backend();
397
+ }
398
+
399
+ // restore blog
400
+ restore_current_blog();
401
+ // site
402
+ } else {
403
+ // uninstall requirements
404
+ self::_uninstall_backend();
405
+ }
406
+
407
+ // clear complete cache
408
+ self::clear_total_cache();
409
+ }
410
+
411
+
412
+ /**
413
+ * uninstall Cache Enabler on deleted site in multisite network
414
+ *
415
+ * @since 1.0.0
416
+ * @change 1.4.0
417
+ *
418
+ * @param WP_Site $old_site old site instance
419
+ */
420
+
421
+ public static function uninstall_later( $old_site ) {
422
+
423
+ // check if network activated
424
+ if ( ! is_plugin_active_for_network( CE_BASE ) ) {
425
+ return;
426
+ }
427
+
428
+ // delete advanced cache settings file
429
+ Cache_Enabler_Disk::delete_advcache_settings();
430
+
431
+ // clear complete cache of deleted site
432
+ self::clear_blog_id_cache( (int) $old_site->blog_id );
433
+ }
434
+
435
+
436
+ /**
437
+ * uninstall installation requirements
438
+ *
439
+ * @since 1.0.0
440
+ * @change 1.4.0
441
+ */
442
+
443
+ private static function _uninstall_backend() {
444
+
445
+ // delete Cache Enabler option
446
+ delete_option( 'cache-enabler' );
447
+ }
448
+
449
+
450
+ /**
451
+ * set or unset WP_CACHE
452
  *
453
  * @since 1.1.1
454
  * @change 1.1.1
455
+ *
456
+ * @param boolean $wp_cache_value true to set WP_CACHE constant in wp-config.php, false to unset
457
  */
458
 
459
+ private static function _set_wp_cache( $wp_cache_value = true ) {
460
+
461
  $wp_config_file = ABSPATH . 'wp-config.php';
462
 
463
  if ( file_exists( $wp_config_file ) && is_writable( $wp_config_file ) ) {
464
+ // get wp-config.php as array
465
  $wp_config = file( $wp_config_file );
466
 
467
+ if ( $wp_cache_value ) {
468
+ $wp_cache_ce_line = "define('WP_CACHE', true); // Added by Cache Enabler" . "\r\n";
469
  } else {
470
  $wp_cache_ce_line = '';
471
  }
480
  }
481
  }
482
 
483
+ // add WP_CACHE if not found
484
  if ( ! $found_wp_cache ) {
485
  array_shift( $wp_config );
486
  array_unshift( $wp_config, "<?php\r\n", $wp_cache_ce_line );
498
 
499
 
500
  /**
501
+ * set default vars
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
502
  *
503
  * @since 1.0.0
504
  * @change 1.0.0
505
  */
506
 
507
+ private static function _set_default_vars() {
508
 
509
+ // get Cache Enabler options
510
+ self::$options = self::_get_options();
511
 
512
+ // disk cache
513
+ if ( Cache_Enabler_Disk::is_permalink() ) {
514
+ self::$disk = new Cache_Enabler_Disk;
515
+ }
516
  }
517
 
518
 
519
  /**
520
+ * get blog IDs
521
  *
522
  * @since 1.0.0
523
  * @change 1.0.0
524
  *
525
+ * @return array blog IDs array
526
  */
527
 
528
  private static function _get_blog_ids() {
529
+
530
  global $wpdb;
531
 
532
  return $wpdb->get_col("SELECT blog_id FROM `$wpdb->blogs`");
534
 
535
 
536
  /**
537
+ * get blog paths
538
  *
539
+ * @since 1.4.0
540
+ * @change 1.4.0
541
+ *
542
+ * @return array blog paths array
543
  */
544
 
545
+ private static function _get_blog_paths() {
546
 
547
+ global $wpdb;
 
548
 
549
+ return $wpdb->get_col("SELECT path FROM `$wpdb->blogs`");
 
 
 
550
  }
551
 
552
 
553
  /**
554
+ * get Cache Enabler options
555
  *
556
  * @since 1.0.0
557
+ * @change 1.4.0
558
  *
559
+ * @return array Cache Enabler options
560
  */
561
 
562
  private static function _get_options() {
563
 
564
+ // decom: rename option
565
+ $ce_leg = get_option( 'cache' );
566
+ if ( ! empty( $ce_leg ) ) {
567
+ delete_option( 'cache' );
568
  add_option(
569
  'cache-enabler',
570
  $ce_leg
571
  );
572
  }
573
 
574
+ // decom: rename options
575
+ $options = get_option( 'cache-enabler', array() );
576
+ // excl_regexp to excl_paths (1.4.0)
577
+ if ( ! empty( $options ) && array_key_exists( 'excl_regexp', $options ) ) {
578
+ $options['excl_paths'] = $options['excl_regexp'];
579
+ unset( $options['excl_regexp'] );
580
+ update_option( 'cache-enabler', $options );
581
+ }
582
+ // incl_attributes to incl_parameters (1.4.0)
583
+ if ( ! empty( $options ) && array_key_exists( 'incl_attributes', $options ) ) {
584
+ $options['incl_parameters'] = $options['incl_attributes'];
585
+ unset( $options['incl_attributes'] );
586
+ update_option( 'cache-enabler', $options );
587
+ }
588
+
589
  return wp_parse_args(
590
+ get_option( 'cache-enabler' ),
591
  array(
592
+ 'expires' => 0,
593
+ 'clear_on_upgrade' => 0,
594
+ 'new_post' => 0,
595
+ 'new_comment' => 0,
596
+ 'update_product_stock' => 0,
597
+ 'compress' => 0,
598
+ 'webp' => 0,
599
+ 'excl_ids' => '',
600
+ 'excl_paths' => '',
601
+ 'excl_cookies' => '',
602
+ 'incl_parameters' => '',
603
+ 'minify_html' => self::MINIFY_DISABLED,
604
  )
605
  );
606
  }
607
 
608
 
609
  /**
610
+ * warning if no custom permlink structure
611
  *
612
  * @since 1.0.0
613
+ * @change 1.4.0
 
 
614
  */
615
 
616
  public static function warning_is_permalink() {
617
 
618
+ if ( ! Cache_Enabler_Disk::is_permalink() && current_user_can( 'manage_options' ) ) {
 
 
 
 
619
 
620
+ show_message(
621
+ sprintf(
622
+ '<div class="error"><p>%s</p></div>',
623
+ sprintf(
624
+ esc_html__( 'The %s plugin requires a custom permalink structure to start caching properly. Please enable a custom structure in the %s.', 'cache-enabler' ),
625
+ '<strong>Cache Enabler</strong>',
626
+ sprintf(
627
+ '<a href="%s">%s</a>',
628
+ admin_url( 'options-permalink.php' ),
629
+ esc_html__( 'Permalink Settings', 'cache-enabler' )
630
+ )
631
+ )
632
+ )
633
+ );
634
  }
635
  }
636
 
645
  * @return array $data appended links
646
  */
647
 
648
+ public static function action_links( $data ) {
649
 
650
  // check user role
651
+ if ( ! current_user_can( 'manage_options' ) ) {
652
  return $data;
653
  }
654
 
659
  '<a href="%s">%s</a>',
660
  add_query_arg(
661
  array(
662
+ 'page' => 'cache-enabler',
663
  ),
664
+ admin_url( 'options-general.php' )
665
  ),
666
+ esc_html__( 'Settings' )
667
  )
668
  )
669
  );
671
 
672
 
673
  /**
674
+ * Cache Enabler meta links
675
  *
676
  * @since 1.0.0
677
+ * @change 1.4.0
678
  *
679
  * @param array $input existing links
680
  * @param string $page page
681
  * @return array $data appended links
682
  */
683
 
684
+ public static function row_meta( $input, $page ) {
685
 
686
  // check permissions
687
+ if ( $page !== CE_BASE ) {
688
  return $input;
689
  }
690
 
691
  return array_merge(
692
  $input,
693
  array(
694
+ '<a href="https://www.keycdn.com/support/wordpress-cache-enabler-plugin" target="_blank">Documentation</a>',
695
  )
696
  );
697
  }
710
  public static function add_dashboard_count( $items = array() ) {
711
 
712
  // check user role
713
+ if ( ! current_user_can( 'manage_options' ) ) {
714
  return $items;
715
  }
716
 
718
  $size = self::get_cache_size();
719
 
720
  // display items
721
+ $items = array(
722
+ sprintf(
723
+ '<a href="%s" title="%s">%s %s</a>',
724
+ add_query_arg(
725
+ array(
726
+ 'page' => 'cache-enabler'
727
+ ),
728
+ admin_url( 'options-general.php' )
729
  ),
730
+ esc_html__( 'Disk Cache', 'cache-enabler' ),
731
+ ( empty( $size ) ? esc_html__( 'Empty', 'cache-enabler' ) : size_format( $size ) ),
732
+ esc_html__( 'Cache Size', 'cache-enabler' )
733
+ )
 
734
  );
735
 
736
  return $items;
743
  * @since 1.0.0
744
  * @change 1.0.0
745
  *
746
+ * @return integer $size cache size (bytes)
747
  */
748
 
749
  public static function get_cache_size() {
750
 
751
+ if ( ! $size = get_transient( 'cache_size' ) ) {
752
 
753
+ $size = ( is_object( self::$disk ) ) ? (int) self::$disk->cache_size( CE_CACHE_DIR ) : 0;
754
 
755
  // set transient
756
  set_transient(
764
  }
765
 
766
 
767
+ /**
768
+ * get blog domain
769
+ *
770
+ * @since 1.4.0
771
+ * @change 1.4.0
772
+ *
773
+ * @return string $domain current blog domain
774
+ */
775
+
776
+ public static function get_blog_domain() {
777
+
778
+ // get current blog domain
779
+ $domain = parse_url( get_site_url(), PHP_URL_HOST );
780
+
781
+ // check if empty when creating new site in network
782
+ if ( is_multisite() && empty( $domain ) ) {
783
+ $domain = get_blog_details()->domain;
784
+ }
785
+
786
+ return $domain;
787
+ }
788
+
789
+
790
  /**
791
  * add admin links
792
  *
793
  * @since 1.0.0
794
+ * @change 1.4.0
 
 
795
  *
796
  * @param object menu properties
797
+ *
798
+ * @hook mixed user_can_clear_cache
799
  */
800
 
801
+ public static function add_admin_links( $wp_admin_bar ) {
802
 
803
  // check user role
804
+ if ( ! is_admin_bar_showing() || ! apply_filters( 'user_can_clear_cache', current_user_can( 'manage_options' ) ) ) {
805
  return;
806
  }
807
 
808
+ // get clear complete cache button title
809
+ $title = ( is_multisite() && is_network_admin() ) ? esc_html__( 'Clear Network Cache', 'cache-enabler' ) : esc_html__( 'Clear Cache', 'cache-enabler' );
810
+
811
+ // add Clear Cache or Clear Network Cache button in admin bar
812
  $wp_admin_bar->add_menu(
813
  array(
814
+ 'id' => 'clear-cache',
815
+ 'href' => wp_nonce_url( add_query_arg( array(
816
+ '_cache' => 'cache-enabler',
817
+ '_action' => 'clear',
818
+ '_cid' => time(),
819
+ ) ) ),
820
  'parent' => 'top-secondary',
821
+ 'title' => '<span class="ab-item">' . $title . '</span>',
822
+ 'meta' => array(
823
+ 'title' => $title,
824
+ ),
825
  )
826
  );
827
 
828
+ // add Clear URL Cache button in admin bar
829
  if ( ! is_admin() ) {
 
830
  $wp_admin_bar->add_menu(
831
  array(
832
+ 'id' => 'clear-url-cache',
833
+ 'href' => wp_nonce_url( add_query_arg( array(
834
+ '_cache' => 'cache-enabler',
835
+ '_action' => 'clearurl',
836
+ '_cid' => time(),
837
+ ) ) ),
838
  'parent' => 'top-secondary',
839
+ 'title' => '<span class="ab-item">' . esc_html__( 'Clear URL Cache', 'cache-enabler' ) . '</span>',
840
+ 'meta' => array(
841
+ 'title' => esc_html__( 'Clear URL Cache', 'cache-enabler' ),
842
+ ),
843
  )
844
  );
845
  }
850
  * process clear request
851
  *
852
  * @since 1.0.0
853
+ * @change 1.4.0
854
  *
855
  * @param array $data array of metadata
856
  */
857
 
858
+ public static function process_clear_request( $data ) {
859
 
860
  // check if clear request
861
+ if ( empty( $_GET['_cache'] ) || empty( $_GET['_action'] || $_GET['_cache'] !== 'cache-enabler' && $_GET['_action'] !== 'clear' || $_GET['_action'] !== 'clearurl' ) ) {
862
+ return;
863
+ }
864
+
865
+ // validate clear ID (prevent duplicate processing)
866
+ if ( empty( $_GET['_cid'] ) || ! empty( $_COOKIE['cache_enabler_clear_id'] ) && $_COOKIE['cache_enabler_clear_id'] === $_GET['_cid'] ) {
867
  return;
868
  }
869
 
870
  // validate nonce
871
+ if ( empty( $_GET['_wpnonce'] ) || ! wp_verify_nonce( $_GET['_wpnonce'] ) ) {
872
  return;
873
  }
874
 
875
  // check user role
876
+ if ( ! is_admin_bar_showing() || ! apply_filters( 'user_can_clear_cache', current_user_can( 'manage_options' ) ) ) {
877
  return;
878
  }
879
 
880
+ // load if network activated
881
+ if ( ! function_exists( 'is_plugin_active_for_network' ) ) {
882
+ require_once( ABSPATH . 'wp-admin/includes/plugin.php' );
883
  }
884
 
885
+ // set clear ID cookie
886
+ setcookie( 'cache_enabler_clear_id', $_GET['_cid'] );
 
 
 
 
 
 
 
 
887
 
888
+ // set clear URL without query string
889
+ $clear_url = preg_replace( '/\?.*/', '', home_url( add_query_arg( null, null ) ) );
890
 
891
+ // network activated
892
+ if ( is_multisite() && is_plugin_active_for_network( CE_BASE ) ) {
893
+ // network admin
894
+ if ( is_network_admin() && $_GET['_action'] === 'clear' ) {
895
+ // clear complete cache
896
+ self::clear_total_cache();
 
 
897
 
898
  // clear notice
899
  if ( is_admin() ) {
901
  'network_admin_notices',
902
  array(
903
  __CLASS__,
904
+ 'clear_notice',
905
  )
906
  );
907
  }
908
+ // site admin
909
  } else {
910
+ if ( $_GET['_action'] === 'clearurl' ) {
911
+ // clear specific site URL cache
912
+ self::clear_page_cache_by_url( $clear_url );
913
+ } elseif ( $_GET['_action'] === 'clear' ) {
914
+ // clear specific site complete cache
915
+ self::clear_blog_id_cache( get_current_blog_id() );
916
 
917
  // clear notice
918
  if ( is_admin() ) {
920
  'admin_notices',
921
  array(
922
  __CLASS__,
923
+ 'clear_notice',
924
  )
925
  );
926
  }
927
  }
928
  }
929
+ // site activated
930
  } else {
931
+ if ( $_GET['_action'] === 'clearurl' ) {
932
+ // clear URL cache
933
+ self::clear_page_cache_by_url( $clear_url );
934
+ } elseif ( $_GET['_action'] === 'clear' ) {
935
+ // clear complete cache
936
  self::clear_total_cache();
937
 
938
  // clear notice
941
  'admin_notices',
942
  array(
943
  __CLASS__,
944
+ 'clear_notice',
945
  )
946
  );
947
  }
951
  if ( ! is_admin() ) {
952
  wp_safe_redirect(
953
  remove_query_arg(
954
+ '_action',
955
  wp_get_referer()
956
  )
957
  );
973
  public static function clear_notice() {
974
 
975
  // check if admin
976
+ if ( ! is_admin_bar_showing() || ! apply_filters( 'user_can_clear_cache', current_user_can( 'manage_options' ) ) ) {
977
  return false;
978
  }
979
 
980
  echo sprintf(
981
  '<div class="notice notice-success is-dismissible"><p>%s</p></div>',
982
+ esc_html__( 'The cache has been cleared.', 'cache-enabler' )
983
  );
984
  }
985
 
988
  * clear cache if post comment
989
  *
990
  * @since 1.2.0
991
+ * @change 1.4.0
992
  *
993
+ * @param integer $comment_id comment ID
994
+ * @param mixed $approved approval status
995
  */
996
 
997
+ public static function comment_post( $comment_id, $approved ) {
998
 
999
  // check if comment is approved
1000
  if ( $approved === 1 ) {
1001
+ // if option enabled clear complete cache on new comment
1002
  if ( self::$options['new_comment'] ) {
1003
  self::clear_total_cache();
1004
  } else {
1005
+ self::clear_page_cache_by_post_id( get_comment( $comment_id )->comment_post_ID );
 
 
1006
  }
1007
  }
1008
  }
1012
  * clear cache if edit comment
1013
  *
1014
  * @since 1.0.0
1015
+ * @change 1.4.0
1016
  *
1017
+ * @param integer $comment_id comment ID
1018
  */
1019
 
1020
+ public static function edit_comment( $comment_id ) {
1021
 
1022
+ // if option enabled clear complete cache on new comment
1023
  if ( self::$options['new_comment'] ) {
1024
  self::clear_total_cache();
1025
  } else {
1026
+ self::clear_page_cache_by_post_id( get_comment( $comment_id )->comment_post_ID );
 
 
1027
  }
1028
  }
1029
 
1039
  * @return mixed $approved approval status
1040
  */
1041
 
1042
+ public static function new_comment( $approved, $comment ) {
1043
 
1044
  // check if comment is approved
1045
  if ( $approved === 1 ) {
1046
+ // if option enabled clear complete cache on new comment
1047
  if ( self::$options['new_comment'] ) {
1048
  self::clear_total_cache();
1049
  } else {
1056
 
1057
 
1058
  /**
1059
+ * clear cache if comment status changes
1060
  *
1061
  * @since 1.0.0
1062
  * @change 1.0.0
1066
  * @param object $comment
1067
  */
1068
 
1069
+ public static function change_comment( $after_status, $before_status, $comment ) {
1070
 
1071
  // check if changes occured
1072
+ if ( $after_status !== $before_status ) {
1073
+ // if option enabled clear complete cache on new comment
1074
  if ( self::$options['new_comment'] ) {
1075
  self::clear_total_cache();
1076
  } else {
1084
  * register publish hooks for custom post types
1085
  *
1086
  * @since 1.0.0
1087
+ * @change 1.2.3
 
 
 
1088
  */
1089
 
1090
  public static function register_publish_hooks() {
1091
 
1092
  // get post types
1093
  $post_types = get_post_types(
1094
+ array(
1095
+ 'public' => true,
1096
+ )
1097
  );
1098
 
1099
  // check if empty
1100
+ if ( empty( $post_types ) ) {
1101
  return;
1102
  }
1103
 
1104
  // post type actions
1105
  foreach ( $post_types as $post_type ) {
1106
  add_action(
1107
+ 'publish_' . $post_type,
1108
  array(
1109
  __CLASS__,
1110
+ 'publish_post_types',
1111
  ),
1112
  10,
1113
  2
1114
  );
1115
  add_action(
1116
+ 'publish_future_' . $post_type,
1117
  function( $post_id ) {
1118
+ // if option enabled clear complete cache on new post
1119
  if ( self::$options['new_post'] ) {
1120
  self::clear_total_cache();
1121
  } else {
1131
  * delete post type cache on post updates
1132
  *
1133
  * @since 1.0.0
1134
+ * @change 1.4.0
1135
  *
1136
+ * @param integer $post_id post ID
1137
  */
1138
 
1139
+ public static function publish_post_types( $post_id, $post ) {
1140
 
1141
+ // check if post ID or post is empty
1142
+ if ( empty( $post_id ) || empty( $post ) ) {
1143
  return;
1144
  }
1145
 
1146
  // check post status
1147
+ if ( ! in_array( $post->post_status, array( 'publish', 'future' ) ) ) {
1148
  return;
1149
  }
1150
 
1151
+ // clear cache on post publish
1152
+ if ( ! isset( $_POST['_clear_post_cache_on_update'] ) && $post->post_date_gmt === $post->post_modified_gmt ) {
1153
 
1154
+ // if option enabled clear complete cache on new post
1155
  if ( self::$options['new_post'] ) {
1156
  return self::clear_total_cache();
1157
  } else {
1161
  }
1162
 
1163
  // validate nonce
1164
+ if ( ! isset( $_POST['_cache__status_nonce_' . $post_id] ) || ! wp_verify_nonce( $_POST['_cache__status_nonce_' . $post_id], CE_BASE ) ) {
1165
  return;
1166
  }
1167
 
1168
  // validate user role
1169
+ if ( ! current_user_can( 'publish_posts' ) ) {
1170
  return;
1171
  }
1172
 
1173
+ // get clear cache publishing action
1174
+ $clear_post_cache = (int) $_POST['_clear_post_cache_on_update'];
1175
 
1176
  // save user metadata
1177
  update_user_meta(
1180
  $clear_post_cache
1181
  );
1182
 
1183
+ // clear cache on post publishing action
1184
  if ( $clear_post_cache ) {
1185
+ self::clear_total_cache();
1186
  } else {
1187
+ self::clear_page_cache_by_post_id( $post_id );
1188
+ }
1189
+ }
1190
+
1191
+
1192
+ /**
1193
+ * trash post hook
1194
+ *
1195
+ * @since 1.4.0
1196
+ * @change 1.4.0
1197
+ *
1198
+ * @param integer $post_id post ID
1199
+ */
1200
+
1201
+ public static function on_trash_post( $post_id ) {
1202
+
1203
+ // if any published post type is sent to the trash clear complete cache
1204
+ if ( get_post_status( $post_id ) === 'publish' ) {
1205
  self::clear_total_cache();
1206
  }
1207
+
1208
+ // check if cache timeout needs to be recorded
1209
+ self::check_future_posts();
1210
  }
1211
 
1212
 
1213
  /**
1214
+ * clear page cache by post ID
1215
  *
1216
  * @since 1.0.0
1217
+ * @change 1.4.0
1218
  *
1219
+ * @param integer $post_id post ID
1220
  */
1221
 
1222
+ public static function clear_page_cache_by_post_id( $post_id ) {
1223
 
1224
+ // validate integer
1225
+ if ( ! is_int( $post_id ) ) {
1226
  return;
1227
  }
1228
 
1229
+ // clear page cache
1230
+ self::clear_page_cache_by_url( get_permalink( $post_id ) );
 
 
1231
  }
1232
 
1233
 
1234
  /**
1235
+ * clear page cache by URL
1236
  *
1237
  * @since 1.0.0
1238
  * @change 1.2.3
1239
  *
1240
+ * @param string $url URL of a page
1241
  */
1242
 
1243
+ public static function clear_page_cache_by_url( $url ) {
1244
 
1245
  // validate string
1246
+ if ( ! is_string( $url ) ) {
1247
  return;
1248
  }
1249
 
1250
  call_user_func(
1251
  array(
1252
  self::$disk,
1253
+ 'delete_asset',
1254
  ),
1255
  $url
1256
  );
1257
 
1258
+ // clear cache by URL post hook
1259
+ do_action( 'ce_action_cache_by_url_cleared' );
1260
  }
1261
 
1262
 
1265
  *
1266
  * @since 1.0.7
1267
  * @change 1.2.3
 
1268
  */
1269
 
1270
  public static function clear_home_page_cache() {
1272
  call_user_func(
1273
  array(
1274
  self::$disk,
1275
+ 'clear_home',
1276
  )
1277
  );
1278
 
1279
  // clear home page cache post hook
1280
+ do_action( 'ce_action_home_page_cache_cleared' );
1281
  }
1282
 
1283
 
1284
  /**
1285
+ * clear blog ID cache
1286
  *
1287
+ * @since 1.4.0
1288
+ * @change 1.4.0
1289
  *
1290
+ * @param integer $blog_id blog ID
1291
  */
1292
 
1293
+ public static function clear_blog_id_cache( $blog_id ) {
1294
+
1295
+ // check if network
1296
+ if ( ! is_multisite() ) {
1297
+ return;
1298
+ }
1299
+
1300
+ // validate integer
1301
+ if ( ! is_int( $blog_id ) ) {
1302
+ return;
1303
+ }
1304
+
1305
+ // set clear URL
1306
+ $clear_url = get_site_url( $blog_id );
1307
+
1308
+ // network with subdomain configuration
1309
+ if ( is_subdomain_install() ) {
1310
+ // clear main site or subsite cache
1311
+ self::clear_page_cache_by_url( $clear_url );
1312
+ // network with subdirectory configuration
1313
+ } else {
1314
+ // get blog path
1315
+ $blog_path = get_blog_details( $blog_id )->path;
1316
+
1317
+ // main site
1318
+ if ( $blog_path === '/' ) {
1319
+ // get blog paths
1320
+ $blog_paths = self::_get_blog_paths();
1321
+
1322
+ // get blog domain
1323
+ $blog_domain = self::get_blog_domain();
1324
+
1325
+ // glob path
1326
+ $glob_path = CE_CACHE_DIR . '/' . $blog_domain;
1327
+
1328
+ // get cached page paths
1329
+ $page_paths = glob( $glob_path . '/*', GLOB_MARK | GLOB_ONLYDIR );
1330
+ foreach ( $page_paths as $page_path ) {
1331
+ $page_path = str_replace( $glob_path, '', $page_path );
1332
+ // if cached page belongs to main site
1333
+ if ( ! in_array( $page_path, $blog_paths ) ) {
1334
+ $clear_url .= $page_path;
1335
+ // clear page cache
1336
+ self::clear_page_cache_by_url( $clear_url );
1337
+ }
1338
+ }
1339
+
1340
+ // clear home page cache
1341
+ self::clear_home_page_cache();
1342
+ // subsite
1343
+ } else {
1344
+ $clear_url .= $blog_path;
1345
+ // clear subsite cache
1346
+ self::clear_page_cache_by_url( $clear_url );
1347
+ }
1348
+ }
1349
  }
1350
 
1351
 
1352
  /**
1353
+ * check if index.php
1354
  *
1355
  * @since 1.0.0
1356
  * @change 1.0.0
1357
  *
1358
+ * @return boolean true if index.php
1359
  */
1360
 
1361
+ private static function _is_index() {
1362
+
1363
+ return strtolower( basename( $_SERVER['SCRIPT_NAME'] ) ) !== 'index.php';
1364
  }
1365
 
1366
 
1367
  /**
1368
+ * check if mobile
1369
  *
1370
  * @since 1.0.0
1371
  * @change 1.0.0
1372
  *
1373
+ * @return boolean true if mobile
1374
  */
1375
 
1376
+ private static function _is_mobile() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1377
 
1378
+ return ( strpos( TEMPLATEPATH, 'wptouch' ) || strpos( TEMPLATEPATH, 'carrington' ) || strpos( TEMPLATEPATH, 'jetpack' ) || strpos( TEMPLATEPATH, 'handheld' ) );
 
 
 
 
1379
  }
1380
 
1381
 
1382
  /**
1383
+ * check if there are posts to be published in the future
1384
  *
1385
  * @since 1.2.3
1386
+ * @change 1.2.3
 
 
1387
  */
1388
 
1389
  public static function check_future_posts() {
1390
 
1391
+ $future_posts = new WP_Query( array(
1392
+ 'post_status' => array( 'future' ),
1393
+ ) );
1394
 
1395
  if ( $future_posts->have_posts() ) {
1396
+ $post_dates = array_column( $future_posts->get_posts(), 'post_date' );
1397
+ sort( $post_dates );
1398
+ // record cache timeout for advanced cache
1399
+ Cache_Enabler_Disk::record_advcache_settings( array(
1400
+ 'cache_timeout' => strtotime( $post_dates[0] )
1401
+ ) );
1402
  } else {
1403
+ Cache_Enabler_Disk::delete_advcache_settings( array( 'cache_timeout' ) );
1404
  }
1405
  }
1406
 
1409
  * check to bypass the cache
1410
  *
1411
  * @since 1.0.0
1412
+ * @change 1.4.0
1413
  *
1414
+ * @return boolean true if exception, false otherwise
1415
  *
1416
+ * @hook boolean bypass_cache
1417
  */
1418
 
1419
  private static function _bypass_cache() {
1420
 
1421
  // bypass cache hook
1422
+ if ( apply_filters( 'bypass_cache', false ) ) {
1423
  return true;
1424
  }
1425
 
1426
+ // check if request method is GET
1427
+ if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || $_SERVER['REQUEST_METHOD'] !== 'GET' ) {
1428
  return true;
1429
  }
1430
 
1431
+ // check if conditional tags
1432
+ if ( self::_is_index() || is_search() || is_404() || is_feed() || is_trackback() || is_robots() || is_preview() || post_password_required() ) {
1433
  return true;
1434
  }
1435
 
1436
+ // check DONOTCACHEPAGE
1437
+ if ( defined( 'DONOTCACHEPAGE' ) && DONOTCACHEPAGE ) {
 
 
 
1438
  return true;
1439
  }
1440
 
1441
+ // check mobile request
1442
+ if ( self::_is_mobile() ) {
1443
  return true;
1444
  }
1445
 
1446
+ // get Cache Enabler options
1447
+ $options = self::$options;
 
 
1448
 
1449
+ // if post ID excluded
1450
+ if ( $options['excl_ids'] && is_singular() ) {
1451
+ if ( in_array( $GLOBALS['wp_query']->get_queried_object_id(), (array) explode( ',', $options['excl_ids'] ) ) ) {
1452
+ return true;
1453
+ }
1454
  }
1455
 
1456
+ // if page path excluded
1457
+ if ( ! empty( $options['excl_paths'] ) ) {
1458
+ $url_path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
1459
+
1460
+ if ( preg_match( $options['excl_paths'], $url_path ) ) {
1461
  return true;
1462
  }
1463
  }
1464
 
1465
+ // check cookies
1466
+ if ( ! empty( $_COOKIE ) ) {
1467
+ // set regex matching cookies that should cause the cache to be bypassed
1468
+ if ( ! empty( $options['excl_cookies'] ) ) {
1469
+ $cookies_regex = $options['excl_cookies'];
1470
+ } else {
1471
+ $cookies_regex = '/^(wp-postpass|wordpress_logged_in|comment_author)_/';
1472
+ }
1473
+ // bypass the cache if an excluded cookie is found
1474
+ foreach ( $_COOKIE as $key => $value) {
1475
+ if ( preg_match( $cookies_regex, $key ) ) {
1476
+ return true;
1477
+ }
1478
+ }
1479
+ }
1480
 
1481
+ // check URL query parameters
1482
+ if ( ! empty( $_GET ) ) {
1483
+ // set regex matching URL query parameters that should not cause the cache to be bypassed
1484
+ if ( ! empty( $options['incl_parameters'] ) ) {
1485
+ $parameters_regex = $options['incl_parameters'];
1486
+ } else {
1487
+ $parameters_regex = '/^fbclid|utm_(source|medium|campaign|term|content)$/';
1488
+ }
1489
+ // bypass the cache if no included URL query parameters are found
1490
+ if ( sizeof( preg_grep( $parameters_regex, array_keys( $_GET ), PREG_GREP_INVERT ) ) > 0 ) {
1491
  return true;
1492
  }
1493
  }
1497
 
1498
 
1499
  /**
1500
+ * minify HTML
1501
  *
1502
  * @since 1.0.0
1503
  * @change 1.0.0
1508
  * @hook array cache_minify_ignore_tags
1509
  */
1510
 
1511
+ private static function _minify_cache( $data ) {
1512
 
1513
  // check if disabled
1514
  if ( ! self::$options['minify_html'] ) {
1515
  return $data;
1516
  }
1517
 
1518
+ // HTML character limit
1519
+ if ( strlen( $data ) > 700000) {
1520
  return $data;
1521
  }
1522
 
1523
+ // HTML tags to ignore
1524
+ $ignore_tags = (array) apply_filters(
1525
  'cache_minify_ignore_tags',
1526
  array(
1527
  'textarea',
1528
+ 'pre',
1529
  )
1530
  );
1531
 
1532
  // ignore JS if selected
1533
  if ( self::$options['minify_html'] !== self::MINIFY_HTML_JS ) {
1534
+ $ignore_tags = array( 'script' );
1535
  }
1536
 
1537
  // return of no ignore tags
1540
  }
1541
 
1542
  // stringify
1543
+ $ignore_regex = implode( '|', $ignore_tags );
1544
 
1545
  // regex minification
1546
  $cleaned = preg_replace(
1547
  array(
1548
  '/<!--[^\[><](.*?)-->/s',
1549
+ '#(?ix)(?>[^\S ]\s*|\s{2,})(?=(?:(?:[^<]++|<(?!/?(?:' . $ignore_regex . ')\b))*+)(?:<(?>' . $ignore_regex . ')\b|\z))#',
1550
  ),
1551
  array(
1552
  '',
1553
+ ' ',
1554
  ),
1555
  $data
1556
  );
1557
 
1558
  // something went wrong
1559
+ if ( strlen( $cleaned ) <= 1 ) {
1560
  return $data;
1561
  }
1562
 
1568
  * clear complete cache
1569
  *
1570
  * @since 1.0.0
1571
+ * @change 1.4.0
1572
  */
1573
 
1574
  public static function clear_total_cache() {
 
 
1575
 
1576
  // clear disk cache
1577
  Cache_Enabler_Disk::clear_cache();
1578
 
1579
  // delete transient
1580
+ delete_transient( 'cache_size' );
1581
 
1582
  // clear cache post hook
1583
+ do_action( 'ce_action_cache_cleared' );
1584
  }
1585
 
1586
 
1587
  /**
1588
+ * WooCommerce stock hooks
1589
  *
1590
+ * @since 1.3.0
1591
+ * @change 1.4.0
1592
+ *
1593
+ * @param integer|WC_Product $product product ID or product instance
1594
  */
1595
 
1596
+ public static function on_woocommerce_stock_update( $product ) {
 
 
1597
 
1598
+ // get product ID
1599
+ if ( is_int( $product ) ) {
1600
+ $product_id = $product;
1601
+ } else {
1602
+ $product_id = $product->get_id();
1603
+ }
1604
+
1605
+ // if option enabled clear complete cache on product stock update
1606
+ if ( self::$options['update_product_stock'] ) {
1607
+ self::clear_total_cache();
1608
+ } else {
1609
+ self::clear_page_cache_by_post_id( $product_id );
1610
+ }
1611
  }
1612
 
1613
 
1615
  * set cache
1616
  *
1617
  * @since 1.0.0
1618
+ * @change 1.3.1
1619
  *
1620
  * @param string $data content of a page
1621
  * @return string $data content of a page
1622
+ *
1623
+ * @hook string cache_enabler_before_store
1624
  */
1625
 
1626
+ public static function set_cache( $data ) {
1627
 
1628
  // check if empty
1629
+ if ( empty( $data ) ) {
1630
  return '';
1631
  }
1632
 
1633
+ $data = apply_filters( 'cache_enabler_before_store', $data );
1634
 
1635
  // store as asset
1636
  call_user_func(
1637
  array(
1638
  self::$disk,
1639
+ 'store_asset',
1640
  ),
1641
+ self::_minify_cache( $data )
1642
  );
1643
 
1644
  return $data;
1649
  * handle cache
1650
  *
1651
  * @since 1.0.0
1652
+ * @change 1.4.0
1653
  */
1654
 
1655
  public static function handle_cache() {
1663
  $cached = call_user_func(
1664
  array(
1665
  self::$disk,
1666
+ 'check_asset',
1667
  )
1668
  );
1669
 
1670
+ // check if cache is empty
1671
+ if ( empty( $cached ) ) {
1672
+ ob_start( 'Cache_Enabler::set_cache' );
1673
+ return;
1674
+ }
1675
+
1676
+ // check trailing slash
1677
+ if ( self::handle_trailing_slash() ) {
1678
  return;
1679
  }
1680
 
1681
+ // get cache expiry status
1682
  $expired = call_user_func(
1683
  array(
1684
  self::$disk,
1685
+ 'check_expiry',
1686
  )
1687
  );
1688
 
1689
+ // check if cache has expired
1690
  if ( $expired ) {
1691
+ ob_start( 'Cache_Enabler::set_cache' );
 
 
 
 
 
1692
  return;
1693
  }
1694
 
1696
  call_user_func(
1697
  array(
1698
  self::$disk,
1699
+ 'get_asset',
1700
  )
1701
  );
1702
  }
1706
  * add clear option dropdown on post publish widget
1707
  *
1708
  * @since 1.0.0
1709
+ * @change 1.4.0
1710
  */
1711
 
1712
  public static function add_clear_dropdown() {
1713
 
1714
+ // on published post/page only
1715
+ if ( empty( $GLOBALS['pagenow'] ) || $GLOBALS['pagenow'] !== 'post.php' || empty( $GLOBALS['post'] ) || ! is_object( $GLOBALS['post'] ) || $GLOBALS['post']->post_status !== 'publish' ) {
1716
  return;
1717
  }
1718
 
1719
  // check user role
1720
+ if ( ! current_user_can( 'publish_posts' ) ) {
1721
  return;
1722
  }
1723
 
1724
  // validate nonce
1725
+ wp_nonce_field( CE_BASE, '_cache__status_nonce_' . $GLOBALS['post']->ID );
1726
 
1727
+ // get current publishing action
1728
+ $current_action = (int) get_user_meta(
1729
  get_current_user_id(),
1730
  '_clear_post_cache_on_update',
1731
  true
1734
  // init variables
1735
  $dropdown_options = '';
1736
  $available_options = array(
1737
+ esc_html__( 'Page specific', 'cache-enabler' ),
1738
+ esc_html__( 'Completely', 'cache-enabler' ),
1739
  );
1740
 
1741
  // set dropdown options
1742
+ foreach ( $available_options as $key => $value ) {
1743
  $dropdown_options .= sprintf(
1744
  '<option value="%1$d" %3$s>%2$s</option>',
1745
  $key,
1746
  $value,
1747
+ selected( $key, $current_action, false )
1748
  );
1749
  }
1750
 
1751
+ // output dropdown
1752
  echo sprintf(
1753
  '<div class="misc-pub-section" style="border-top:1px solid #eee">
1754
  <label for="cache_action">
1755
+ %1$s: <strong id="output-cache-action">%2$s</strong>
1756
  </label>
1757
  <a href="#" class="edit-cache-action hide-if-no-js">%3$s</a>
1758
 
1762
  </select>
1763
 
1764
  <a href="#" class="save-cache-action hide-if-no-js button">%5$s</a>
1765
+ <a href="#" class="cancel-cache-action hide-if-no-js button-cancel">%6$s</a>
1766
  </div>
1767
  </div>',
1768
+ esc_html__( 'Clear cache', 'cache-enabler' ),
1769
+ $available_options[ $current_action ],
1770
+ esc_html__( 'Edit' ),
1771
  $dropdown_options,
1772
+ esc_html__( 'OK' ),
1773
+ esc_html__( 'Cancel' )
1774
  );
1775
  }
1776
 
1782
  * @change 1.0.0
1783
  */
1784
 
1785
+ public static function add_admin_resources( $hook ) {
1786
 
1787
  // hook check
1788
  if ( $hook !== 'index.php' && $hook !== 'post.php' ) {
1790
  }
1791
 
1792
  // plugin data
1793
+ $plugin_data = get_plugin_data( CE_FILE );
1794
 
1795
  // enqueue scripts
1796
+ switch( $hook ) {
1797
 
1798
  case 'post.php':
1799
  wp_enqueue_script(
1800
  'cache-post',
1801
+ plugins_url( 'js/post.js', CE_FILE ),
1802
+ array( 'jquery' ),
1803
  $plugin_data['Version'],
1804
  true
1805
  );
1827
  'cache-enabler',
1828
  array(
1829
  __CLASS__,
1830
+ 'settings_page',
1831
  )
1832
  );
1833
  }
1839
  * @since 1.0.0
1840
  * @change 1.0.0
1841
  *
1842
+ * @return array cache minification options
1843
  */
1844
 
1845
  private static function _minify_select() {
1846
 
1847
  return array(
1848
+ self::MINIFY_DISABLED => esc_html__( 'Disabled', 'cache-enabler' ),
1849
+ self::MINIFY_HTML_ONLY => esc_html__( 'HTML', 'cache-enabler' ),
1850
+ self::MINIFY_HTML_JS => esc_html__( 'HTML and Inline JS', 'cache-enabler' ),
1851
  );
1852
  }
1853
 
1854
 
1855
  /**
1856
+ * check plugin requirements
1857
  *
1858
  * @since 1.1.0
1859
+ * @change 1.4.0
1860
  */
1861
 
1862
  public static function requirements_check() {
1863
 
 
 
 
1864
  // WordPress version check
1865
+ if ( version_compare( $GLOBALS['wp_version'], CE_MIN_WP . 'alpha', '<' ) ) {
1866
  show_message(
1867
  sprintf(
1868
  '<div class="error"><p>%s</p></div>',
1869
  sprintf(
1870
+ esc_html__( 'The %s is optimized for WordPress %s. Please disable the plugin or upgrade your WordPress installation (recommended).', 'cache-enabler' ),
1871
+ '<strong>Cache Enabler</strong>',
1872
  CE_MIN_WP
1873
  )
1874
  )
1876
  }
1877
 
1878
  // permission check
1879
+ if ( file_exists( CE_CACHE_DIR ) && ! is_writable( CE_CACHE_DIR ) ) {
1880
  show_message(
1881
  sprintf(
1882
  '<div class="error"><p>%s</p></div>',
1883
  sprintf(
1884
+ esc_html__( 'The %s plugin requires write permissions %s in %s. Please change the %s.', 'cache-enabler' ),
1885
+ '<strong>Cache Enabler</strong>',
1886
  '<code>755</code>',
1887
  '<code>wp-content/cache</code>',
1888
+ sprintf(
1889
+ '<a href="%s" target="_blank"></a>',
1890
+ 'https://wordpress.org/support/article/changing-file-permissions/',
1891
+ esc_html__( 'file permissions', 'cache-enabler' )
1892
+ )
1893
  )
1894
  )
1895
  );
1896
  }
1897
 
1898
  // autoptimize minification check
1899
+ if ( defined( 'AUTOPTIMIZE_PLUGIN_DIR' ) && self::$options['minify_html'] && get_option( 'autoptimize_html', '' ) !== '' ) {
1900
  show_message(
1901
  sprintf(
1902
  '<div class="error"><p>%s</p></div>',
1903
  sprintf(
1904
+ esc_html__( 'The %s plugin is already active. Please disable %s in the %s.', 'cache-enabler' ),
1905
+ '<strong>Autoptimize</strong>',
1906
+ esc_html__( 'Cache Minification', 'cache-enabler' ),
1907
+ sprintf(
1908
+ '<a href="%s">%s</a>',
1909
+ admin_url( 'options-general.php' ) . '?page=cache-enabler',
1910
+ esc_html__( 'Cache Enabler Settings', 'cache-enabler' )
1911
+ )
1912
  )
1913
  )
1914
  );
1925
 
1926
  public static function register_textdomain() {
1927
 
1928
+ // load translated strings
1929
  load_plugin_textdomain(
1930
  'cache-enabler',
1931
  false,
1933
  );
1934
  }
1935
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1936
 
1937
  /**
1938
  * register settings
1948
  'cache-enabler',
1949
  array(
1950
  __CLASS__,
1951
+ 'validate_settings',
1952
  )
1953
  );
1954
  }
1955
 
1956
 
1957
  /**
1958
+ * handle trailing slash
1959
+ *
1960
+ * @since 1.2.3
1961
+ * @change 1.4.0
1962
+ *
1963
+ * @return boolean true if cache should be bypassed to allow a redirect, false otherwise
1964
+ */
1965
+
1966
+ public static function handle_trailing_slash() {
1967
+
1968
+ $permalink_structure = get_option( 'permalink_structure' );
1969
+
1970
+ if ( $permalink_structure && preg_match( '/\/$/', $permalink_structure ) ) {
1971
+ // record permalink structure has trailing slash for advanced cache
1972
+ Cache_Enabler_Disk::record_advcache_settings( array(
1973
+ 'permalink_trailing_slash' => true,
1974
+ ) );
1975
+ // if trailing slash is missing, check if we have to bypass the cache to allow a redirect
1976
+ if ( ! preg_match( '/\/(|\?.*)$/', $_SERVER['REQUEST_URI'] ) ) {
1977
+ return true;
1978
+ }
1979
+ } else {
1980
+ // record permalink structure does not have trailing slash for advanced cache
1981
+ Cache_Enabler_Disk::record_advcache_settings( array(
1982
+ 'permalink_trailing_slash' => false,
1983
+ ) );
1984
+ // if trailing slash is appended, check if we have to bypass the cache to allow a redirect
1985
+ if ( preg_match( '/(?!^)\/(|\?.*)$/', $_SERVER['REQUEST_URI'] ) ) {
1986
+ return true;
1987
+ }
1988
+ }
1989
+
1990
+ return false;
1991
+ }
1992
+
1993
+
1994
+ /**
1995
+ * validate regex
1996
  *
1997
  * @since 1.2.3
1998
+ * @change 1.2.3
1999
  *
2000
+ * @param string $re string containing regex
2001
+ * @return string string containing regex or empty string if input is invalid
2002
  */
2003
 
2004
+ public static function validate_regex( $re ) {
 
2005
 
2006
+ if ( $re !== '' ) {
2007
+ if ( ! preg_match( '/^\/.*\/$/', $re ) ) {
2008
+ $re = '/' . $re . '/';
2009
  }
2010
 
2011
+ if ( @preg_match( $re, null ) === false ) {
2012
  return '';
2013
  }
2014
 
2015
+ return sanitize_text_field( $re );
2016
  }
2017
 
2018
  return '';
2022
  * validate settings
2023
  *
2024
  * @since 1.0.0
2025
+ * @change 1.4.0
2026
  *
2027
+ * @param array $data form data array
2028
+ * @return array valid form data array
2029
  */
2030
 
2031
+ public static function validate_settings( $data ) {
2032
 
2033
  // check if empty
2034
+ if ( empty( $data ) ) {
2035
  return;
2036
  }
2037
 
2038
+ // check if cache should be cleared
2039
+ if ( isset( $data['clear_cache'] ) && $data['clear_cache'] ) {
2040
+ self::clear_total_cache();
2041
+ }
2042
 
2043
+ // ignore results and call permalink structure recording
2044
+ self::handle_trailing_slash();
2045
 
2046
+ // record cache expiry for advanced cache
2047
  if ( $data['expires'] > 0 ){
2048
+ Cache_Enabler_Disk::record_advcache_settings( array(
2049
+ 'expires' => $data['expires'],
2050
+ ) );
 
 
 
 
 
 
 
2051
  } else {
2052
+ Cache_Enabler_Disk::delete_advcache_settings( array( 'expires' ) );
2053
  }
2054
 
2055
+ // record cookies cache exclusion for advanced cache
2056
+ if ( strlen( $data['excl_cookies'] ) > 0 ) {
2057
+ Cache_Enabler_Disk::record_advcache_settings( array(
2058
+ 'excl_cookies' => $data['excl_cookies'],
2059
+ ) );
2060
  } else {
2061
+ Cache_Enabler_Disk::delete_advcache_settings( array( 'excl_cookies' ) );
2062
  }
2063
 
2064
+ // record URL query parameters inclusion for advanced cache
2065
+ if ( strlen( $data['incl_parameters'] ) > 0 ) {
2066
+ Cache_Enabler_Disk::record_advcache_settings( array(
2067
+ 'incl_parameters' => $data['incl_parameters'],
2068
+ ) );
2069
  } else {
2070
+ Cache_Enabler_Disk::delete_advcache_settings( array( 'incl_parameters' ) );
2071
  }
2072
 
2073
  return array(
2074
+ 'expires' => (int) $data['expires'],
2075
+ 'clear_on_upgrade' => (int) ( ! empty( $data['clear_on_upgrade'] ) ),
2076
+ 'new_post' => (int) ( ! empty( $data['new_post'] ) ),
2077
+ 'new_comment' => (int) ( ! empty( $data['new_comment'] ) ),
2078
+ 'update_product_stock' => (int) ( ! empty( $data['update_product_stock'] ) ),
2079
+ 'webp' => (int) ( ! empty( $data['webp'] ) ),
2080
+ 'compress' => (int) ( ! empty( $data['compress'] ) ),
2081
+ 'excl_ids' => (string) sanitize_text_field( @$data['excl_ids'] ),
2082
+ 'excl_paths' => (string) self::validate_regex( @$data['excl_paths'] ),
2083
+ 'excl_cookies' => (string) self::validate_regex( @$data['excl_cookies'] ),
2084
+ 'incl_parameters' => (string) self::validate_regex( @$data['incl_parameters'] ),
2085
+ 'minify_html' => (int) $data['minify_html'],
2086
  );
2087
  }
2088
 
2091
  * settings page
2092
  *
2093
  * @since 1.0.0
2094
+ * @change 1.4.0
2095
  */
2096
 
2097
  public static function settings_page() {
2098
 
2099
+ // WP_CACHE check
2100
+ if ( ! defined( 'WP_CACHE' ) || ! WP_CACHE ) {
2101
+ show_message(
 
2102
  sprintf(
2103
+ '<div class="notice notice-warning"><p>%s</p></div>',
2104
+ sprintf(
2105
+ esc_html__( '%s is not set in the %s file.', 'cache-enabler' ),
2106
+ "<code>define('WP_CACHE', true);</code>",
2107
+ '<code>wp-config.php</code>'
2108
+ )
2109
  )
2110
  );
2111
  }
2112
 
2113
  ?>
2114
 
2115
+ <div id="cache-enabler-settings" class="wrap">
2116
  <h2>
2117
+ <?php esc_html_e( 'Cache Enabler Settings', 'cache-enabler' ); ?>
2118
  </h2>
2119
 
2120
  <div class="notice notice-info" style="margin-bottom: 35px;">
2121
+ <p>
2122
+ <?php
2123
+ printf(
2124
+ esc_html__( 'Combine %s with Cache Enabler for even better WordPress performance and achieve the next level of caching with a CDN.', 'cache-enabler' ),
2125
+ '<strong><a href="https://www.keycdn.com?utm_source=wp-admin&utm_medium=plugins&utm_campaign=cache-enabler">KeyCDN</a></strong>'
2126
+ );
2127
+ ?>
2128
+ </p>
2129
  </div>
2130
 
 
 
2131
  <form method="post" action="options.php">
2132
+ <?php settings_fields( 'cache-enabler' ); ?>
2133
+ <?php $options = self::_get_options(); ?>
 
 
2134
  <table class="form-table">
2135
  <tr valign="top">
2136
  <th scope="row">
2137
+ <?php esc_html_e( 'Cache Expiry', 'cache-enabler' ); ?>
2138
  </th>
2139
  <td>
2140
+ <input name="cache-enabler[expires]" type="number" id="cache_expires" value="<?php echo esc_attr( $options['expires'] ); ?>" class="small-text" /> <?php esc_html_e( 'hours', 'cache-enabler' ); ?>
2141
+ <p class="description"><?php esc_html_e( 'An expiry time of 0 means that the cache never expires.', 'cache-enabler' ); ?></p>
 
 
 
 
2142
  </td>
2143
  </tr>
2144
  <tr valign="top">
2145
  <th scope="row">
2146
+ <?php esc_html_e( 'Cache Behavior', 'cache-enabler' ); ?>
2147
  </th>
2148
  <td>
2149
  <fieldset>
2150
+ <label for="cache_clear_on_upgrade">
2151
+ <input name="cache-enabler[clear_on_upgrade]" type="checkbox" id="cache_clear_on_upgrade" value="1" <?php checked( '1', $options['clear_on_upgrade'] ); ?> />
2152
+ <?php esc_html_e( 'Clear the complete cache if a plugin has been activated, updated, or deactivated.', 'cache-enabler' ); ?>
2153
+ <span style="display: inline-block; color: #155724; background-color: #d4edda; font-size: 75%; font-weight: 700; white-space: nowrap; border-radius: .25rem; padding: .25em .4em; margin-left: .5rem;"><?php esc_html_e( 'Updated', 'cache-enabler' ); ?></span>
2154
+ </label>
2155
+
2156
+ <br />
2157
+
2158
  <label for="cache_new_post">
2159
+ <input name="cache-enabler[new_post]" type="checkbox" id="cache_new_post" value="1" <?php checked( '1', $options['new_post'] ); ?> />
2160
+ <?php esc_html_e( 'Clear the complete cache if any new post type has been published (instead of only the home page cache).', 'cache-enabler' ); ?>
2161
  </label>
2162
 
2163
  <br />
2164
 
2165
  <label for="cache_new_comment">
2166
+ <input name="cache-enabler[new_comment]" type="checkbox" id="cache_new_comment" value="1" <?php checked( '1', $options['new_comment'] ); ?> />
2167
+ <?php esc_html_e( 'Clear the complete cache if a new comment has been posted (instead of only the page specific cache).', 'cache-enabler' ); ?>
2168
  </label>
2169
 
2170
  <br />
2171
 
2172
+ <?php if ( is_plugin_active( 'woocommerce/woocommerce.php') ): ?>
2173
+ <label for="cache_update_product_stock">
2174
+ <input name="cache-enabler[update_product_stock]" type="checkbox" id="cache_update_product_stock" value="1" <?php checked( '1', $options['update_product_stock'] ); ?> />
2175
+ <?php esc_html_e( 'Clear the complete cache if a product stock has been updated (instead of only the page specific cache).', 'cache-enabler' ); ?>
2176
+ <span style="display: inline-block; color: #155724; background-color: #d4edda; font-size: 75%; font-weight: 700; white-space: nowrap; border-radius: .25rem; padding: .25em .4em; margin-left: .5rem;"><?php esc_html_e( 'New', 'cache-enabler' ); ?></span>
2177
  </label>
2178
 
2179
  <br />
2180
+ <?php endif; ?>
2181
 
2182
+ <label for="cache_compress">
2183
+ <input name="cache-enabler[compress]" type="checkbox" id="cache_compress" value="1" <?php checked( '1', $options['compress'] ); ?> />
2184
+ <?php esc_html_e( 'Pre-compression of cached pages. Needs to be disabled if the decoding fails in the web browser.', 'cache-enabler' ); ?>
2185
  </label>
2186
 
2187
  <br />
2188
 
2189
+ <label for="cache_webp">
2190
+ <input name="cache-enabler[webp]" type="checkbox" id="cache_webp" value="1" <?php checked( '1', $options['webp'] ); ?> />
2191
+ <?php printf( esc_html__( 'Create an additional cached version for WebP image support. Convert your images to WebP with %s.', 'cache-enabler' ), '<a href="https://optimus.io" target="_blank">Optimus</a>' ); ?>
2192
  </label>
2193
  </fieldset>
2194
  </td>
2196
 
2197
  <tr valign="top">
2198
  <th scope="row">
2199
+ <?php esc_html_e( 'Cache Exclusions', 'cache-enabler' ); ?>
2200
  </th>
2201
  <td>
2202
  <fieldset>
2203
  <label for="cache_excl_ids">
2204
+ <input name="cache-enabler[excl_ids]" type="text" id="cache_excl_ids" value="<?php echo esc_attr( $options['excl_ids'] ) ?>" class="regular-text" />
2205
+ <p class="description"><?php printf( esc_html__( 'Post and page IDs separated by a %s that should not be cached.', 'cache-enabler' ), '<code>,</code>' ); ?>
2206
+ <p><?php esc_html_e( 'Example:', 'cache-enabler' ); ?> <code>2,43,65</code></p>
2207
  </p>
2208
  </label>
2209
 
2210
  <br />
2211
 
2212
+ <label for="cache_excl_paths">
2213
+ <input name="cache-enabler[excl_paths]" type="text" id="cache_excl_paths" value="<?php echo esc_attr( $options['excl_paths'] ) ?>" class="regular-text code" />
2214
+ <p class="description"><?php esc_html_e( 'A regex matching page paths that should not be cached.', 'cache-enabler' ); ?></p>
2215
+ <p><?php esc_html_e( 'Example:', 'cache-enabler' ); ?> <code>/(^\/$|\/robot\/$|^\/2018\/.*\/test\/)/</code></p>
 
 
2216
  </label>
2217
 
2218
  <br />
2219
 
2220
  <label for="cache_excl_cookies">
2221
+ <input name="cache-enabler[excl_cookies]" type="text" id="cache_excl_cookies" value="<?php echo esc_attr( $options['excl_cookies'] ) ?>" class="regular-text code" />
2222
+ <p class="description"><?php esc_html_e( 'A regex matching cookies that should cause the cache to be bypassed.', 'cache-enabler' ); ?></p>
2223
+ <p><?php esc_html_e( 'Example:', 'cache-enabler' ); ?> <code>/^(wp-postpass|wordpress_logged_in|comment_author|woocommerce_items_in_cart|wp_woocommerce_session)_?/</code></p>
2224
+ <p><?php esc_html_e( 'Default if unset:', 'cache-enabler' ); ?> <code>/^(wp-postpass|wordpress_logged_in|comment_author)_/</code></p>
 
 
2225
  </label>
2226
  </fieldset>
2227
  </td>
2229
 
2230
  <tr valign="top">
2231
  <th scope="row">
2232
+ <?php esc_html_e( 'Cache Inclusions', 'cache-enabler' ); ?>
2233
  </th>
2234
  <td>
2235
  <fieldset>
2236
+ <label for="cache_incl_parameters">
2237
+ <input name="cache-enabler[incl_parameters]" type="text" id="cache_incl_parameters" value="<?php echo esc_attr( $options['incl_parameters'] ) ?>" class="regular-text code" />
2238
+ <p class="description"><?php esc_html_e( 'A regex matching URL query parameters that should not cause the cache to be bypassed.', 'cache-enabler' ); ?></p>
2239
+ <p><?php esc_html_e( 'Example:', 'cache-enabler' ); ?> <code>/^fbclid|pk_(source|medium|campaign|kwd|content)$/</code></p>
2240
+ <p><?php esc_html_e( 'Default if unset:', 'cache-enabler' ); ?> <code>/^fbclid|utm_(source|medium|campaign|term|content)$/</code><span style="display: inline-block; color: #155724; background-color: #d4edda; font-size: 75%; font-weight: 700; white-space: nowrap; border-radius: .25rem; padding: .25em .4em; margin-left: .5rem;"><?php esc_html_e( 'Updated', 'cache-enabler' ); ?></span></p>
 
 
2241
  </label>
2242
  </fieldset>
2243
  </td>
2245
 
2246
  <tr valign="top">
2247
  <th scope="row">
2248
+ <?php esc_html_e( 'Cache Minification', 'cache-enabler' ); ?>
2249
  </th>
2250
  <td>
2251
  <label for="cache_minify_html">
2252
  <select name="cache-enabler[minify_html]" id="cache_minify_html">
2253
+ <?php foreach ( self::_minify_select() as $key => $value ): ?>
2254
+ <option value="<?php echo esc_attr( $key ) ?>" <?php selected( $options['minify_html'], $key ); ?>>
2255
+ <?php echo esc_html( $value ) ?>
2256
  </option>
2257
+ <?php endforeach; ?>
2258
  </select>
2259
  </label>
2260
  </td>
2261
  </tr>
 
 
 
 
 
 
 
 
 
2262
  </table>
2263
+
2264
+ <p class="submit">
2265
+ <input type="submit" class="button-secondary" value="<?php esc_html_e( 'Save Changes', 'cache-enabler' ); ?>" />
2266
+ <input name="cache-enabler[clear_cache]" type="submit" class="button-primary" value="<?php esc_html_e( 'Save Changes and Clear Cache', 'cache-enabler' ); ?>" />
2267
+ </p>
2268
  </form>
2269
+ </div>
2270
+
2271
+ <?php
2272
+
2273
  }
2274
  }
inc/cache_enabler_cli.class.php CHANGED
@@ -1,9 +1,19 @@
1
  <?php
 
 
 
 
 
 
2
  /**
3
- * Interact with Cache Enabler.
 
 
4
  */
 
5
  class Cache_Enabler_CLI {
6
 
 
7
  /**
8
  * Clear the page cache.
9
  *
@@ -28,7 +38,9 @@ class Cache_Enabler_CLI {
28
  *
29
  * @alias clear
30
  */
 
31
  public function clear( $args, $assoc_args ) {
 
32
  $assoc_args = wp_parse_args(
33
  $assoc_args,
34
  array(
@@ -37,14 +49,14 @@ class Cache_Enabler_CLI {
37
  )
38
  );
39
 
40
- // clear everything if we aren't given IDs and/or URLs.
41
  if ( empty( $assoc_args['ids'] ) && empty( $assoc_args['urls'] ) ) {
42
  Cache_Enabler::clear_total_cache();
43
 
44
  return WP_CLI::success( esc_html__( 'The page cache has been cleared.', 'cache-enabler' ) );
45
  }
46
 
47
- // clear specific IDs and/or URLs.
48
  array_map( 'Cache_Enabler::clear_page_cache_by_post_id', explode( ',', $assoc_args['ids'] ) );
49
  array_map( 'Cache_Enabler::clear_page_cache_by_url', explode( ',', $assoc_args['urls'] ) );
50
 
1
  <?php
2
+
3
+
4
+ // exit
5
+ defined( 'ABSPATH' ) || exit;
6
+
7
+
8
  /**
9
+ * Interact with Cache Enabler
10
+ *
11
+ * @since 1.3.5
12
  */
13
+
14
  class Cache_Enabler_CLI {
15
 
16
+
17
  /**
18
  * Clear the page cache.
19
  *
38
  *
39
  * @alias clear
40
  */
41
+
42
  public function clear( $args, $assoc_args ) {
43
+
44
  $assoc_args = wp_parse_args(
45
  $assoc_args,
46
  array(
49
  )
50
  );
51
 
52
+ // clear everything if we are not given IDs and/or URLs
53
  if ( empty( $assoc_args['ids'] ) && empty( $assoc_args['urls'] ) ) {
54
  Cache_Enabler::clear_total_cache();
55
 
56
  return WP_CLI::success( esc_html__( 'The page cache has been cleared.', 'cache-enabler' ) );
57
  }
58
 
59
+ // clear specific IDs and/or URLs
60
  array_map( 'Cache_Enabler::clear_page_cache_by_post_id', explode( ',', $assoc_args['ids'] ) );
61
  array_map( 'Cache_Enabler::clear_page_cache_by_url', explode( ',', $assoc_args['urls'] ) );
62
 
inc/cache_enabler_disk.class.php CHANGED
@@ -2,13 +2,13 @@
2
 
3
 
4
  // exit
5
- defined('ABSPATH') OR exit;
6
 
7
 
8
  /**
9
  * Cache_Enabler_Disk
10
  *
11
- * @since 1.0.0
12
  */
13
 
14
  final class Cache_Enabler_Disk {
@@ -17,14 +17,15 @@ final class Cache_Enabler_Disk {
17
  /**
18
  * cached filename settings
19
  *
20
- * @since 1.0.7
21
- * @change 1.0.7
22
  *
23
- * @var string
24
  */
25
 
26
- const FILE_HTML = 'index.html';
27
- const FILE_GZIP = 'index.html.gz';
 
28
  const FILE_WEBP_HTML = 'index-webp.html';
29
  const FILE_WEBP_GZIP = 'index-webp.html.gz';
30
 
@@ -39,7 +40,8 @@ final class Cache_Enabler_Disk {
39
  */
40
 
41
  public static function is_permalink() {
42
- return get_option('permalink_structure');
 
43
  }
44
 
45
 
@@ -49,21 +51,18 @@ final class Cache_Enabler_Disk {
49
  * @since 1.0.0
50
  * @change 1.0.0
51
  *
52
- * @param string $data content of the asset
53
  */
54
 
55
- public static function store_asset($data) {
56
 
57
  // check if empty
58
- if ( empty($data) ) {
59
- wp_die('Asset is empty.');
60
  }
61
 
62
  // save asset
63
- self::_create_files(
64
- $data
65
- );
66
-
67
  }
68
 
69
 
@@ -77,9 +76,8 @@ final class Cache_Enabler_Disk {
77
  */
78
 
79
  public static function check_asset() {
80
- return is_readable(
81
- self::_file_html()
82
- );
83
  }
84
 
85
 
@@ -94,24 +92,23 @@ final class Cache_Enabler_Disk {
94
 
95
  public static function check_expiry() {
96
 
97
- // cache enabler options
98
  $options = Cache_Enabler::$options;
99
 
100
- // check if expires is active
101
- if ($options['expires'] == 0) {
102
  return false;
103
  }
104
 
105
  $now = time();
106
- $expires_seconds = 3600*$options['expires'];
107
 
108
  // check if asset has expired
109
- if ( ( filemtime(self::_file_html()) + $expires_seconds ) <= $now ) {
110
  return true;
111
  }
112
 
113
  return false;
114
-
115
  }
116
 
117
 
@@ -121,20 +118,18 @@ final class Cache_Enabler_Disk {
121
  * @since 1.0.0
122
  * @change 1.0.0
123
  *
124
- * @param string $url url of cached asset
125
  */
126
 
127
- public static function delete_asset($url) {
128
 
129
- // check if url empty
130
- if ( empty($url) ) {
131
- wp_die('URL is empty.');
132
  }
133
 
134
  // delete
135
- self::_clear_dir(
136
- self::_file_path($url)
137
- );
138
  }
139
 
140
 
@@ -146,9 +141,9 @@ final class Cache_Enabler_Disk {
146
  */
147
 
148
  public static function clear_cache() {
149
- self::_clear_dir(
150
- CE_CACHE_DIR
151
- );
152
  }
153
 
154
 
@@ -156,22 +151,20 @@ final class Cache_Enabler_Disk {
156
  * clear home cache
157
  *
158
  * @since 1.0.7
159
- * @change 1.0.9
160
  */
161
 
162
  public static function clear_home() {
 
163
  $path = sprintf(
164
  '%s%s%s%s',
165
  CE_CACHE_DIR,
166
  DIRECTORY_SEPARATOR,
167
- preg_replace('#^https?://#', '', get_option('siteurl')),
168
  DIRECTORY_SEPARATOR
169
  );
170
 
171
- @unlink($path.self::FILE_HTML);
172
- @unlink($path.self::FILE_GZIP);
173
- @unlink($path.self::FILE_WEBP_HTML);
174
- @unlink($path.self::FILE_WEBP_GZIP);
175
  }
176
 
177
 
@@ -184,19 +177,19 @@ final class Cache_Enabler_Disk {
184
 
185
  public static function get_asset() {
186
 
187
- // set cache handler header
188
- header('x-cache-handler: php');
189
 
190
- // get if-modified request headers
191
  if ( function_exists( 'apache_request_headers' ) ) {
192
- $headers = apache_request_headers();
193
  $http_if_modified_since = ( isset( $headers[ 'If-Modified-Since' ] ) ) ? $headers[ 'If-Modified-Since' ] : '';
194
- $http_accept = ( isset( $headers[ 'Accept' ] ) ) ? $headers[ 'Accept' ] : '';
195
- $http_accept_encoding = ( isset( $headers[ 'Accept-Encoding' ] ) ) ? $headers[ 'Accept-Encoding' ] : '';
196
  } else {
197
  $http_if_modified_since = ( isset( $_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ] ) ) ? $_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ] : '';
198
- $http_accept = ( isset( $_SERVER[ 'HTTP_ACCEPT' ] ) ) ? $_SERVER[ 'HTTP_ACCEPT' ] : '';
199
- $http_accept_encoding = ( isset( $_SERVER[ 'HTTP_ACCEPT_ENCODING' ] ) ) ? $_SERVER[ 'HTTP_ACCEPT_ENCODING' ] : '';
200
  }
201
 
202
  // check modified since with cached file and return 304 if no difference
@@ -206,9 +199,9 @@ final class Cache_Enabler_Disk {
206
  }
207
 
208
  // check webp and deliver gzip webp file if support
209
- if ( $http_accept && ( strpos($http_accept, 'webp') !== false ) ) {
210
  if ( is_readable( self::_file_webp_gzip() ) ) {
211
- header('Content-Encoding: gzip');
212
  readfile( self::_file_webp_gzip() );
213
  exit;
214
  } elseif ( is_readable( self::_file_webp_html() ) ) {
@@ -218,8 +211,8 @@ final class Cache_Enabler_Disk {
218
  }
219
 
220
  // check encoding and deliver gzip file if support
221
- if ( $http_accept_encoding && ( strpos($http_accept_encoding, 'gzip') !== false ) && is_readable( self::_file_gzip() ) ) {
222
- header('Content-Encoding: gzip');
223
  readfile( self::_file_gzip() );
224
  exit;
225
  }
@@ -239,13 +232,14 @@ final class Cache_Enabler_Disk {
239
  * @return string signature
240
  */
241
 
242
- private static function _cache_signatur() {
 
243
  return sprintf(
244
  "\n\n<!-- %s @ %s",
245
  'Cache Enabler by KeyCDN',
246
  date_i18n(
247
  'd.m.Y H:i:s',
248
- current_time('timestamp')
249
  )
250
  );
251
  }
@@ -255,48 +249,47 @@ final class Cache_Enabler_Disk {
255
  * create files
256
  *
257
  * @since 1.0.0
258
- * @change 1.1.1
259
  *
260
- * @param string $data html content
261
  */
262
 
263
- private static function _create_files($data) {
264
 
265
- // create folder
266
- if ( ! wp_mkdir_p( self::_file_path() ) ) {
267
- wp_die('Unable to create directory.');
268
- }
269
 
270
  // get base signature
271
- $cache_signature = self::_cache_signatur();
272
 
273
- // cache enabler options
274
- $options = Cache_Enabler::$options;
 
 
275
 
276
  // create files
277
- self::_create_file( self::_file_html(), $data.$cache_signature." (html) -->" );
278
 
279
  // create pre-compressed file
280
- if ($options['compress']) {
281
- self::_create_file( self::_file_gzip(), gzencode($data.$cache_signature." (html gzip) -->", 9) );
282
  }
283
 
284
  // create webp supported files
285
- if ($options['webp']) {
286
  // magic regex rule
287
  $regex_rule = '#(?<=(?:(ref|src|set)=[\"\']))(?:[^\"\']+)(\.png|\.jp[e]?g)(?:[^\"\']+)?(?=[\"\')])#';
288
 
289
  // call the webp converter callback
290
- $converted_data = apply_filters('cache_enabler_disk_webp_converted_data', preg_replace_callback($regex_rule,'self::_convert_webp',$data));
291
 
292
- self::_create_file( self::_file_webp_html(), $converted_data.$cache_signature." (webp) -->" );
293
 
294
  // create pre-compressed file
295
- if ($options['compress']) {
296
- self::_create_file( self::_file_webp_gzip(), gzencode($converted_data.$cache_signature." (webp gzip) -->", 9) );
297
  }
298
  }
299
-
300
  }
301
 
302
 
@@ -307,26 +300,26 @@ final class Cache_Enabler_Disk {
307
  * @change 1.0.0
308
  *
309
  * @param string $file file path
310
- * @param string $data content of the html
311
  */
312
 
313
- private static function _create_file($file, $data) {
314
 
315
  // open file handler
316
- if ( ! $handle = @fopen($file, 'wb') ) {
317
- wp_die('Can not write to file.');
318
  }
319
 
320
  // write
321
- @fwrite($handle, $data);
322
- fclose($handle);
323
  clearstatcache();
324
 
325
  // set permissions
326
- $stat = @stat( dirname($file) );
327
  $perms = $stat['mode'] & 0007777;
328
  $perms = $perms & 0000666;
329
- @chmod($file, $perms);
330
  clearstatcache();
331
  }
332
 
@@ -340,43 +333,44 @@ final class Cache_Enabler_Disk {
340
  * @param string $dir directory
341
  */
342
 
343
- private static function _clear_dir($dir) {
344
 
345
  // remove slashes
346
- $dir = untrailingslashit($dir);
347
 
348
- // check if dir
349
- if ( ! is_dir($dir) ) {
350
  return;
351
  }
352
 
353
- // get dir data
354
- $data_dir = @scandir($dir);
355
- if(gettype($data_dir) === 'array') {
356
  $objects = array_diff(
357
  $data_dir,
358
- array('..', '.')
359
  );
360
  }
361
 
362
- if ( empty($objects) ) {
 
363
  return;
364
  }
365
 
366
  foreach ( $objects as $object ) {
367
  // full path
368
- $object = $dir. DIRECTORY_SEPARATOR .$object;
369
 
370
  // check if directory
371
- if ( is_dir($object) ) {
372
- self::_clear_dir($object);
373
  } else {
374
- @unlink($object);
375
  }
376
  }
377
 
378
  // delete
379
- @rmdir($dir);
380
 
381
  // clears file status cache
382
  clearstatcache();
@@ -393,20 +387,20 @@ final class Cache_Enabler_Disk {
393
  * @return mixed $size size in bytes
394
  */
395
 
396
- public static function cache_size($dir = '.') {
397
 
398
- // check if not dir
399
- if ( ! is_dir($dir) ) {
400
  return;
401
  }
402
 
403
- // get dir data
404
  $objects = array_diff(
405
- scandir($dir),
406
- array('..', '.')
407
  );
408
 
409
- if ( empty($objects) ) {
410
  return;
411
  }
412
 
@@ -414,13 +408,13 @@ final class Cache_Enabler_Disk {
414
 
415
  foreach ( $objects as $object ) {
416
  // full path
417
- $object = $dir. DIRECTORY_SEPARATOR .$object;
418
 
419
- // check if dir
420
- if ( is_dir($object) ) {
421
- $size += self::cache_size($object);
422
  } else {
423
- $size += filesize($object);
424
  }
425
  }
426
 
@@ -432,20 +426,20 @@ final class Cache_Enabler_Disk {
432
  * cache path
433
  *
434
  * @since 1.0.0
435
- * @change 1.1.0
436
  *
437
- * @param string $path uri or permlink
438
- * @return string $diff path to cached asset
439
  */
440
 
441
- private static function _file_path($path = NULL) {
442
 
443
  $path = sprintf(
444
  '%s%s%s%s',
445
  CE_CACHE_DIR,
446
  DIRECTORY_SEPARATOR,
447
  parse_url(
448
- 'http://' .strtolower($_SERVER['HTTP_HOST']),
449
  PHP_URL_HOST
450
  ),
451
  parse_url(
@@ -454,11 +448,37 @@ final class Cache_Enabler_Disk {
454
  )
455
  );
456
 
457
- if ( is_file($path) > 0 ) {
458
- wp_die('Path is not valid.');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
459
  }
460
 
461
- return trailingslashit($path);
 
 
 
 
 
 
462
  }
463
 
464
 
@@ -466,13 +486,14 @@ final class Cache_Enabler_Disk {
466
  * get file path
467
  *
468
  * @since 1.0.0
469
- * @change 1.0.7
470
  *
471
- * @return string path to the html file
472
  */
473
 
474
  private static function _file_html() {
475
- return self::_file_path(). self::FILE_HTML;
 
476
  }
477
 
478
 
@@ -480,13 +501,14 @@ final class Cache_Enabler_Disk {
480
  * get gzip file path
481
  *
482
  * @since 1.0.1
483
- * @change 1.0.7
484
  *
485
- * @return string path to the gzipped html file
486
  */
487
 
488
  private static function _file_gzip() {
489
- return self::_file_path(). self::FILE_GZIP;
 
490
  }
491
 
492
 
@@ -494,13 +516,14 @@ final class Cache_Enabler_Disk {
494
  * get webp file path
495
  *
496
  * @since 1.0.7
497
- * @change 1.0.7
498
  *
499
- * @return string path to the webp html file
500
  */
501
 
502
  private static function _file_webp_html() {
503
- return self::_file_path(). self::FILE_WEBP_HTML;
 
504
  }
505
 
506
 
@@ -508,32 +531,73 @@ final class Cache_Enabler_Disk {
508
  * get gzip webp file path
509
  *
510
  * @since 1.0.1
511
- * @change 1.0.7
512
  *
513
- * @return string path to the webp gzipped html file
514
  */
515
 
516
  private static function _file_webp_gzip() {
517
- return self::_file_path(). self::FILE_WEBP_GZIP;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
518
  }
519
 
520
 
521
  /**
522
  * read settings file
523
  *
524
- * @since 1.2.3
 
525
  *
526
- * @return array settings or emtpy
 
527
  */
528
 
529
- private static function _read_settings($settings_file) {
530
- if (! file_exists($settings_file) ) {
531
- return [];
 
 
532
  }
533
 
534
- if ( ! $settings = json_decode(file_get_contents($settings_file), true) ) {
535
- // if there is an error reading our settings
536
- return [];
537
  }
538
 
539
  return $settings;
@@ -543,13 +607,16 @@ final class Cache_Enabler_Disk {
543
  /**
544
  * write settings file
545
  *
546
- * @since 1.2.3
 
547
  *
548
- * @return void
 
549
  */
550
 
551
- private static function _write_settings($settings_file, $settings) {
552
- file_put_contents( $settings_file, wp_json_encode($settings) );
 
553
  }
554
 
555
 
@@ -557,31 +624,27 @@ final class Cache_Enabler_Disk {
557
  * record settings for advanced-cache.php
558
  *
559
  * @since 1.2.3
 
560
  *
561
  * @param array settings as array pairs
562
  * @return boolean true if successful
563
  */
564
 
565
- public static function record_advcache_settings($settings) {
566
- $settings_file = sprintf('%s-%s%s.json',
567
- WP_CONTENT_DIR. "/cache/cache-enabler-advcache",
568
- parse_url(
569
- 'http://' .strtolower($_SERVER['HTTP_HOST']),
570
- PHP_URL_HOST
571
- ),
572
- is_multisite() ? '-'. get_current_blog_id() : ''
573
- );
574
 
575
  // create folder if neccessary
576
- if ( ! wp_mkdir_p(dirname($settings_file)) ) {
577
- wp_die('Unable to create directory.');
578
  }
579
 
580
  // merge with old settings
581
- $settings = array_merge(self::_read_settings($settings_file), $settings);
582
 
583
  // update settings file
584
- self::_write_settings($settings_file, $settings);
585
 
586
  return true;
587
  }
@@ -591,39 +654,36 @@ final class Cache_Enabler_Disk {
591
  * delete settings for advanced-cache.php
592
  *
593
  * @since 1.2.3
 
594
  *
595
- * @param array settings as array or empty for delete all
596
  * @return boolean true if successful
597
  */
598
 
599
- public static function delete_advcache_settings($remsettings = array()) {
600
- $settings_file = sprintf('%s-%s%s.json',
601
- WP_CONTENT_DIR. "/cache/cache-enabler-advcache",
602
- parse_url(
603
- 'http://' .strtolower($_SERVER['HTTP_HOST']),
604
- PHP_URL_HOST
605
- ),
606
- is_multisite() ? '-'. get_current_blog_id() : ''
607
- );
608
 
609
- if ( ! file_exists($settings_file) or empty($remsettings)) {
 
610
  return true;
611
  }
612
 
613
- $settings = self::_read_settings($settings_file);
614
- foreach ($remsettings as $key) {
615
- if ( array_key_exists($key, $settings) ) {
616
- unset($settings[$key]);
617
  }
618
  }
619
 
620
- if (empty($settings)) {
621
- unlink($settings_file);
622
  return true;
623
  }
624
 
625
  // update settings file
626
- self::_write_settings($settings_file, $settings);
627
 
628
  return true;
629
  }
@@ -638,18 +698,17 @@ final class Cache_Enabler_Disk {
638
  * @return string converted HTML file
639
  */
640
 
641
- private static function _convert_webp($asset) {
642
 
643
- if ($asset[1] == 'src') {
644
- return self::_convert_webp_src($asset[0]);
645
- } elseif ($asset[1] == 'ref') {
646
- return self::_convert_webp_src($asset[0]);
647
- } elseif ($asset[1] == 'set') {
648
- return self::_convert_webp_srcset($asset[0]);
649
  }
650
 
651
  return $asset[0];
652
-
653
  }
654
 
655
 
@@ -662,31 +721,32 @@ final class Cache_Enabler_Disk {
662
  * @return string converted src webp source
663
  */
664
 
665
- private static function _convert_webp_src($src) {
 
666
  $upload_dir = wp_upload_dir();
667
- $src_url = parse_url($upload_dir['baseurl']);
668
  $upload_path = $src_url['path'];
669
 
670
- if ( strpos($src, $upload_path) !== false ) {
671
 
672
- $src_webp = str_replace('.jpg', '.webp', $src);
673
- $src_webp = str_replace('.jpeg', '.webp', $src_webp);
674
- $src_webp = str_replace('.png', '.webp', $src_webp);
675
 
676
- $parts = explode($upload_path, $src_webp);
677
  $relative_path = $parts[1];
678
 
679
  // check if relative path is not empty and file exists
680
- if ( !empty($relative_path) && file_exists($upload_dir['basedir'].$relative_path) ) {
681
  return $src_webp;
682
  } else {
683
  // try appended webp extension
684
- $src_webp_appended = $src.'.webp';
685
- $parts_appended = explode($upload_path, $src_webp_appended);
686
  $relative_path_appended = $parts_appended[1];
687
 
688
  // check if relative path is not empty and file exists
689
- if ( !empty($relative_path_appended) && file_exists($upload_dir['basedir'].$relative_path_appended) ) {
690
  return $src_webp_appended;
691
  }
692
  }
@@ -705,49 +765,44 @@ final class Cache_Enabler_Disk {
705
  * @return string converted srcset webp source
706
  */
707
 
708
- private static function _convert_webp_srcset($srcset) {
709
 
710
- $sizes = explode(', ', $srcset);
711
  $upload_dir = wp_upload_dir();
712
- $src_url = parse_url($upload_dir['baseurl']);
713
  $upload_path = $src_url['path'];
714
 
715
- for ($i=0; $i<count($sizes); $i++) {
716
-
717
- if ( strpos($sizes[$i], $upload_path) !== false ) {
 
 
718
 
719
- $src_webp = str_replace('.jpg', '.webp', $sizes[$i]);
720
- $src_webp = str_replace('.jpeg', '.webp', $src_webp);
721
- $src_webp = str_replace('.png', '.webp', $src_webp);
722
-
723
- $size_parts = explode(' ', $src_webp);
724
- $parts = explode($upload_path, $size_parts[0]);
725
  $relative_path = $parts[1];
726
 
727
  // check if relative path is not empty and file exists
728
- if ( !empty($relative_path) && file_exists($upload_dir['basedir'].$relative_path) ) {
729
- $sizes[$i] = $src_webp;
730
  } else {
731
  // try appended webp extension
732
- $size_parts_appended = explode(' ', $sizes[$i]);
733
- $src_webp_appended = $size_parts_appended[0].'.webp';
734
- $parts_appended = explode($upload_path, $src_webp_appended);
735
  $relative_path_appended = $parts_appended[1];
736
- $src_webp_appended = $src_webp_appended.' '.$size_parts_appended[1];
737
 
738
  // check if relative path is not empty and file exists
739
- if ( !empty($relative_path_appended) && file_exists($upload_dir['basedir'].$relative_path_appended) ) {
740
- $sizes[$i] = $src_webp_appended;
741
  }
742
  }
743
-
744
  }
745
-
746
  }
747
 
748
- $srcset = implode(', ', $sizes);
749
 
750
  return $srcset;
751
  }
752
-
753
  }
2
 
3
 
4
  // exit
5
+ defined( 'ABSPATH' ) || exit;
6
 
7
 
8
  /**
9
  * Cache_Enabler_Disk
10
  *
11
+ * @since 1.0.0
12
  */
13
 
14
  final class Cache_Enabler_Disk {
17
  /**
18
  * cached filename settings
19
  *
20
+ * @since 1.0.7
21
+ * @change 1.4.0
22
  *
23
+ * @var string
24
  */
25
 
26
+ const FILE_GLOB = '*index*';
27
+ const FILE_HTML = 'index.html';
28
+ const FILE_GZIP = 'index.html.gz';
29
  const FILE_WEBP_HTML = 'index-webp.html';
30
  const FILE_WEBP_GZIP = 'index-webp.html.gz';
31
 
40
  */
41
 
42
  public static function is_permalink() {
43
+
44
+ return get_option( 'permalink_structure' );
45
  }
46
 
47
 
51
  * @since 1.0.0
52
  * @change 1.0.0
53
  *
54
+ * @param string $data content of the asset
55
  */
56
 
57
+ public static function store_asset( $data ) {
58
 
59
  // check if empty
60
+ if ( empty( $data ) ) {
61
+ wp_die( 'Asset is empty.' );
62
  }
63
 
64
  // save asset
65
+ self::_create_files( $data );
 
 
 
66
  }
67
 
68
 
76
  */
77
 
78
  public static function check_asset() {
79
+
80
+ return is_readable( self::_file_html() );
 
81
  }
82
 
83
 
92
 
93
  public static function check_expiry() {
94
 
95
+ // get Cache Enabler options
96
  $options = Cache_Enabler::$options;
97
 
98
+ // check if an expiry time is set
99
+ if ( $options['expires'] === 0) {
100
  return false;
101
  }
102
 
103
  $now = time();
104
+ $expires_seconds = 3600 * $options['expires'];
105
 
106
  // check if asset has expired
107
+ if ( ( filemtime( self::_file_html() ) + $expires_seconds ) <= $now ) {
108
  return true;
109
  }
110
 
111
  return false;
 
112
  }
113
 
114
 
118
  * @since 1.0.0
119
  * @change 1.0.0
120
  *
121
+ * @param string $url URL of cached asset
122
  */
123
 
124
+ public static function delete_asset( $url ) {
125
 
126
+ // check if URL is empty
127
+ if ( empty( $url ) ) {
128
+ wp_die( 'URL is empty.' );
129
  }
130
 
131
  // delete
132
+ self::_clear_dir( self::_file_path( $url ) );
 
 
133
  }
134
 
135
 
141
  */
142
 
143
  public static function clear_cache() {
144
+
145
+ // clear complete cache
146
+ self::_clear_dir( CE_CACHE_DIR );
147
  }
148
 
149
 
151
  * clear home cache
152
  *
153
  * @since 1.0.7
154
+ * @change 1.4.0
155
  */
156
 
157
  public static function clear_home() {
158
+
159
  $path = sprintf(
160
  '%s%s%s%s',
161
  CE_CACHE_DIR,
162
  DIRECTORY_SEPARATOR,
163
+ preg_replace( '#^https?://#', '', get_option( 'siteurl' ) ),
164
  DIRECTORY_SEPARATOR
165
  );
166
 
167
+ array_map( 'unlink', glob( $path . self::FILE_GLOB ) );
 
 
 
168
  }
169
 
170
 
177
 
178
  public static function get_asset() {
179
 
180
+ // set X-Cache-Handler response header
181
+ header( 'X-Cache-Handler: php' );
182
 
183
+ // get request headers
184
  if ( function_exists( 'apache_request_headers' ) ) {
185
+ $headers = apache_request_headers();
186
  $http_if_modified_since = ( isset( $headers[ 'If-Modified-Since' ] ) ) ? $headers[ 'If-Modified-Since' ] : '';
187
+ $http_accept = ( isset( $headers[ 'Accept' ] ) ) ? $headers[ 'Accept' ] : '';
188
+ $http_accept_encoding = ( isset( $headers[ 'Accept-Encoding' ] ) ) ? $headers[ 'Accept-Encoding' ] : '';
189
  } else {
190
  $http_if_modified_since = ( isset( $_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ] ) ) ? $_SERVER[ 'HTTP_IF_MODIFIED_SINCE' ] : '';
191
+ $http_accept = ( isset( $_SERVER[ 'HTTP_ACCEPT' ] ) ) ? $_SERVER[ 'HTTP_ACCEPT' ] : '';
192
+ $http_accept_encoding = ( isset( $_SERVER[ 'HTTP_ACCEPT_ENCODING' ] ) ) ? $_SERVER[ 'HTTP_ACCEPT_ENCODING' ] : '';
193
  }
194
 
195
  // check modified since with cached file and return 304 if no difference
199
  }
200
 
201
  // check webp and deliver gzip webp file if support
202
+ if ( $http_accept && ( strpos( $http_accept, 'webp' ) !== false ) ) {
203
  if ( is_readable( self::_file_webp_gzip() ) ) {
204
+ header( 'Content-Encoding: gzip' );
205
  readfile( self::_file_webp_gzip() );
206
  exit;
207
  } elseif ( is_readable( self::_file_webp_html() ) ) {
211
  }
212
 
213
  // check encoding and deliver gzip file if support
214
+ if ( $http_accept_encoding && ( strpos( $http_accept_encoding, 'gzip' ) !== false ) && is_readable( self::_file_gzip() ) ) {
215
+ header( 'Content-Encoding: gzip' );
216
  readfile( self::_file_gzip() );
217
  exit;
218
  }
232
  * @return string signature
233
  */
234
 
235
+ private static function _cache_signature() {
236
+
237
  return sprintf(
238
  "\n\n<!-- %s @ %s",
239
  'Cache Enabler by KeyCDN',
240
  date_i18n(
241
  'd.m.Y H:i:s',
242
+ current_time( 'timestamp' )
243
  )
244
  );
245
  }
249
  * create files
250
  *
251
  * @since 1.0.0
252
+ * @change 1.4.0
253
  *
254
+ * @param string $data HTML content
255
  */
256
 
257
+ private static function _create_files( $data ) {
258
 
259
+ // get Cache Enabler options
260
+ $options = Cache_Enabler::$options;
 
 
261
 
262
  // get base signature
263
+ $cache_signature = self::_cache_signature();
264
 
265
+ // create folder
266
+ if ( ! wp_mkdir_p( self::_file_path() ) ) {
267
+ wp_die( 'Unable to create directory.' );
268
+ }
269
 
270
  // create files
271
+ self::_create_file( self::_file_html(), $data . $cache_signature . ' (' . self::_file_scheme() . ' html) -->' );
272
 
273
  // create pre-compressed file
274
+ if ( $options['compress'] ) {
275
+ self::_create_file( self::_file_gzip(), gzencode( $data . $cache_signature . ' (' . self::_file_scheme() . ' gzip) -->', 9) );
276
  }
277
 
278
  // create webp supported files
279
+ if ( $options['webp'] ) {
280
  // magic regex rule
281
  $regex_rule = '#(?<=(?:(ref|src|set)=[\"\']))(?:[^\"\']+)(\.png|\.jp[e]?g)(?:[^\"\']+)?(?=[\"\')])#';
282
 
283
  // call the webp converter callback
284
+ $converted_data = apply_filters( 'cache_enabler_disk_webp_converted_data', preg_replace_callback( $regex_rule, 'self::_convert_webp', $data ) );
285
 
286
+ self::_create_file( self::_file_webp_html(), $converted_data . $cache_signature . ' (' . self::_file_scheme() . ' webp html) -->' );
287
 
288
  // create pre-compressed file
289
+ if ( $options['compress'] ) {
290
+ self::_create_file( self::_file_webp_gzip(), gzencode( $converted_data . $cache_signature . ' (' . self::_file_scheme() . ' webp gzip) -->', 9) );
291
  }
292
  }
 
293
  }
294
 
295
 
300
  * @change 1.0.0
301
  *
302
  * @param string $file file path
303
+ * @param string $data content of the HTML
304
  */
305
 
306
+ private static function _create_file( $file, $data ) {
307
 
308
  // open file handler
309
+ if ( ! $handle = @fopen( $file, 'wb' ) ) {
310
+ wp_die( 'Cannot write to file.' );
311
  }
312
 
313
  // write
314
+ @fwrite( $handle, $data );
315
+ fclose( $handle );
316
  clearstatcache();
317
 
318
  // set permissions
319
+ $stat = @stat( dirname( $file ) );
320
  $perms = $stat['mode'] & 0007777;
321
  $perms = $perms & 0000666;
322
+ @chmod( $file, $perms );
323
  clearstatcache();
324
  }
325
 
333
  * @param string $dir directory
334
  */
335
 
336
+ private static function _clear_dir( $dir ) {
337
 
338
  // remove slashes
339
+ $dir = untrailingslashit( $dir );
340
 
341
+ // check if directory
342
+ if ( ! is_dir( $dir ) ) {
343
  return;
344
  }
345
 
346
+ // get directory data
347
+ $data_dir = @scandir( $dir );
348
+ if( gettype( $data_dir ) === 'array' ) {
349
  $objects = array_diff(
350
  $data_dir,
351
+ array( '..', '.' )
352
  );
353
  }
354
 
355
+ // check if empty
356
+ if ( empty( $objects ) ) {
357
  return;
358
  }
359
 
360
  foreach ( $objects as $object ) {
361
  // full path
362
+ $object = $dir . DIRECTORY_SEPARATOR . $object;
363
 
364
  // check if directory
365
+ if ( is_dir( $object ) ) {
366
+ self::_clear_dir( $object );
367
  } else {
368
+ @unlink( $object );
369
  }
370
  }
371
 
372
  // delete
373
+ @rmdir( $dir );
374
 
375
  // clears file status cache
376
  clearstatcache();
387
  * @return mixed $size size in bytes
388
  */
389
 
390
+ public static function cache_size( $dir = '.' ) {
391
 
392
+ // check if not directory
393
+ if ( ! is_dir( $dir ) ) {
394
  return;
395
  }
396
 
397
+ // get directory data
398
  $objects = array_diff(
399
+ scandir( $dir ),
400
+ array( '..', '.' )
401
  );
402
 
403
+ if ( empty( $objects ) ) {
404
  return;
405
  }
406
 
408
 
409
  foreach ( $objects as $object ) {
410
  // full path
411
+ $object = $dir . DIRECTORY_SEPARATOR . $object;
412
 
413
+ // check if directory
414
+ if ( is_dir( $object ) ) {
415
+ $size += self::cache_size( $object );
416
  } else {
417
+ $size += filesize( $object );
418
  }
419
  }
420
 
426
  * cache path
427
  *
428
  * @since 1.0.0
429
+ * @change 1.4.0
430
  *
431
+ * @param string $path URI or permalink
432
+ * @return string $diff path to cached file
433
  */
434
 
435
+ private static function _file_path( $path = null ) {
436
 
437
  $path = sprintf(
438
  '%s%s%s%s',
439
  CE_CACHE_DIR,
440
  DIRECTORY_SEPARATOR,
441
  parse_url(
442
+ get_site_url(),
443
  PHP_URL_HOST
444
  ),
445
  parse_url(
448
  )
449
  );
450
 
451
+ if ( is_file( $path ) > 0 ) {
452
+ wp_die( 'Path is not valid.' );
453
+ }
454
+
455
+ return trailingslashit( $path );
456
+ }
457
+
458
+
459
+ /**
460
+ * get file scheme
461
+ *
462
+ * @since 1.4.0
463
+ * @change 1.4.0
464
+ *
465
+ * @return string https, http, or port
466
+ */
467
+
468
+ private static function _file_scheme() {
469
+
470
+ // https
471
+ if ( $_SERVER['SERVER_PORT'] === '443' ) {
472
+ return 'https';
473
  }
474
 
475
+ // http
476
+ if ( $_SERVER['SERVER_PORT'] === '80' ) {
477
+ return 'http';
478
+ }
479
+
480
+ // port
481
+ return $_SERVER['SERVER_PORT'];
482
  }
483
 
484
 
486
  * get file path
487
  *
488
  * @since 1.0.0
489
+ * @change 1.4.0
490
  *
491
+ * @return string path to the HTML file
492
  */
493
 
494
  private static function _file_html() {
495
+
496
+ return self::_file_path() . self::_file_scheme() . '-' . self::FILE_HTML;
497
  }
498
 
499
 
501
  * get gzip file path
502
  *
503
  * @since 1.0.1
504
+ * @change 1.4.0
505
  *
506
+ * @return string path to the gzipped HTML file
507
  */
508
 
509
  private static function _file_gzip() {
510
+
511
+ return self::_file_path() . self::_file_scheme() . '-' . self::FILE_GZIP;
512
  }
513
 
514
 
516
  * get webp file path
517
  *
518
  * @since 1.0.7
519
+ * @change 1.4.0
520
  *
521
+ * @return string path to the webp HTML file
522
  */
523
 
524
  private static function _file_webp_html() {
525
+
526
+ return self::_file_path() . self::_file_scheme() . '-' . self::FILE_WEBP_HTML;
527
  }
528
 
529
 
531
  * get gzip webp file path
532
  *
533
  * @since 1.0.1
534
+ * @change 1.4.0
535
  *
536
+ * @return string path to the webp gzipped HTML file
537
  */
538
 
539
  private static function _file_webp_gzip() {
540
+
541
+ return self::_file_path() . self::_file_scheme() . '-' . self::FILE_WEBP_GZIP;
542
+ }
543
+
544
+
545
+ /**
546
+ * get settings file
547
+ *
548
+ * @since 1.4.0
549
+ * @change 1.4.0
550
+ *
551
+ * @return string settings file path
552
+ */
553
+
554
+ private static function _get_settings() {
555
+
556
+ // network with subdirectory configuration
557
+ if ( is_multisite() && ! is_subdomain_install() ) {
558
+ // get blog path
559
+ $path = trim( get_blog_details()->path, '/' );
560
+ // check if subsite
561
+ if ( ! empty( $path ) ) {
562
+ $path = '-' . $path;
563
+ }
564
+ // single site, network subdirectory main site, or any network subdomain site
565
+ } else {
566
+ $path = '';
567
+ }
568
+
569
+ // get settings file
570
+ $settings_file = sprintf(
571
+ '%s-%s%s.json',
572
+ CE_SETTINGS_PATH,
573
+ Cache_Enabler::get_blog_domain(),
574
+ $path
575
+ );
576
+
577
+ return $settings_file;
578
  }
579
 
580
 
581
  /**
582
  * read settings file
583
  *
584
+ * @since 1.2.3
585
+ * @change 1.2.3
586
  *
587
+ * @param string $settings_file settings file path
588
+ * @return array settings or empty
589
  */
590
 
591
+ private static function _read_settings( $settings_file ) {
592
+
593
+ // check if settings file exists
594
+ if ( ! file_exists( $settings_file ) ) {
595
+ return array();
596
  }
597
 
598
+ // check if any errors occur when reading the settings file
599
+ if ( ! $settings = json_decode( file_get_contents( $settings_file ), true ) ) {
600
+ return array();
601
  }
602
 
603
  return $settings;
607
  /**
608
  * write settings file
609
  *
610
+ * @since 1.2.3
611
+ * @change 1.2.3
612
  *
613
+ * @param string $settings_file settings file path
614
+ * @param array $settings settings
615
  */
616
 
617
+ private static function _write_settings( $settings_file, $settings ) {
618
+
619
+ file_put_contents( $settings_file, wp_json_encode( $settings ) );
620
  }
621
 
622
 
624
  * record settings for advanced-cache.php
625
  *
626
  * @since 1.2.3
627
+ * @change 1.4.0
628
  *
629
  * @param array settings as array pairs
630
  * @return boolean true if successful
631
  */
632
 
633
+ public static function record_advcache_settings( $settings ) {
634
+
635
+ // get settings file
636
+ $settings_file = self::_get_settings();
 
 
 
 
 
637
 
638
  // create folder if neccessary
639
+ if ( ! wp_mkdir_p( dirname( $settings_file ) ) ) {
640
+ wp_die( 'Unable to create directory.' );
641
  }
642
 
643
  // merge with old settings
644
+ $settings = array_merge( self::_read_settings( $settings_file ), $settings );
645
 
646
  // update settings file
647
+ self::_write_settings( $settings_file, $settings );
648
 
649
  return true;
650
  }
654
  * delete settings for advanced-cache.php
655
  *
656
  * @since 1.2.3
657
+ * @change 1.4.0
658
  *
659
+ * @param array settings keys as array or empty for delete all
660
  * @return boolean true if successful
661
  */
662
 
663
+ public static function delete_advcache_settings( $settings_keys = array() ) {
664
+
665
+ // get settings file
666
+ $settings_file = self::_get_settings();
 
 
 
 
 
667
 
668
+ // check if settings file exists
669
+ if ( ! file_exists( $settings_file ) ) {
670
  return true;
671
  }
672
 
673
+ $settings = self::_read_settings( $settings_file );
674
+ foreach ( $settings_keys as $key ) {
675
+ if ( array_key_exists( $key, $settings ) ) {
676
+ unset( $settings[ $key ] );
677
  }
678
  }
679
 
680
+ if ( empty( $settings ) || empty( $settings_keys ) ) {
681
+ unlink( $settings_file );
682
  return true;
683
  }
684
 
685
  // update settings file
686
+ self::_write_settings( $settings_file, $settings );
687
 
688
  return true;
689
  }
698
  * @return string converted HTML file
699
  */
700
 
701
+ private static function _convert_webp( $asset ) {
702
 
703
+ if ( $asset[1] === 'src' ) {
704
+ return self::_convert_webp_src( $asset[0] );
705
+ } elseif ( $asset[1] === 'ref' ) {
706
+ return self::_convert_webp_src( $asset[0] );
707
+ } elseif ( $asset[1] === 'set' ) {
708
+ return self::_convert_webp_srcset( $asset[0] );
709
  }
710
 
711
  return $asset[0];
 
712
  }
713
 
714
 
721
  * @return string converted src webp source
722
  */
723
 
724
+ private static function _convert_webp_src( $src ) {
725
+
726
  $upload_dir = wp_upload_dir();
727
+ $src_url = parse_url( $upload_dir['baseurl'] );
728
  $upload_path = $src_url['path'];
729
 
730
+ if ( strpos( $src, $upload_path ) !== false ) {
731
 
732
+ $src_webp = str_replace( '.jpg', '.webp', $src );
733
+ $src_webp = str_replace( '.jpeg', '.webp', $src_webp );
734
+ $src_webp = str_replace( '.png', '.webp', $src_webp );
735
 
736
+ $parts = explode( $upload_path, $src_webp );
737
  $relative_path = $parts[1];
738
 
739
  // check if relative path is not empty and file exists
740
+ if ( ! empty( $relative_path ) && file_exists( $upload_dir['basedir'] . $relative_path ) ) {
741
  return $src_webp;
742
  } else {
743
  // try appended webp extension
744
+ $src_webp_appended = $src . '.webp';
745
+ $parts_appended = explode( $upload_path, $src_webp_appended );
746
  $relative_path_appended = $parts_appended[1];
747
 
748
  // check if relative path is not empty and file exists
749
+ if ( ! empty( $relative_path_appended ) && file_exists( $upload_dir['basedir'] . $relative_path_appended ) ) {
750
  return $src_webp_appended;
751
  }
752
  }
765
  * @return string converted srcset webp source
766
  */
767
 
768
+ private static function _convert_webp_srcset( $srcset ) {
769
 
770
+ $sizes = explode( ', ', $srcset );
771
  $upload_dir = wp_upload_dir();
772
+ $src_url = parse_url( $upload_dir['baseurl'] );
773
  $upload_path = $src_url['path'];
774
 
775
+ for ( $i = 0; $i < count( $sizes ); $i++ ) {
776
+ if ( strpos( $sizes[ $i ], $upload_path ) !== false ) {
777
+ $src_webp = str_replace( '.jpg', '.webp', $sizes[ $i ] );
778
+ $src_webp = str_replace( '.jpeg', '.webp', $src_webp );
779
+ $src_webp = str_replace( '.png', '.webp', $src_webp );
780
 
781
+ $size_parts = explode( ' ', $src_webp );
782
+ $parts = explode( $upload_path, $size_parts[0] );
 
 
 
 
783
  $relative_path = $parts[1];
784
 
785
  // check if relative path is not empty and file exists
786
+ if ( ! empty( $relative_path ) && file_exists( $upload_dir['basedir'] . $relative_path ) ) {
787
+ $sizes[ $i ] = $src_webp;
788
  } else {
789
  // try appended webp extension
790
+ $size_parts_appended = explode( ' ', $sizes[ $i ] );
791
+ $src_webp_appended = $size_parts_appended[0] . '.webp';
792
+ $parts_appended = explode( $upload_path, $src_webp_appended );
793
  $relative_path_appended = $parts_appended[1];
794
+ $src_webp_appended = $src_webp_appended . ' '. $size_parts_appended[1];
795
 
796
  // check if relative path is not empty and file exists
797
+ if ( ! empty( $relative_path_appended ) && file_exists( $upload_dir['basedir'] . $relative_path_appended ) ) {
798
+ $sizes[ $i ] = $src_webp_appended;
799
  }
800
  }
 
801
  }
 
802
  }
803
 
804
+ $srcset = implode( ', ', $sizes );
805
 
806
  return $srcset;
807
  }
 
808
  }
js/post.js CHANGED
@@ -1,11 +1,12 @@
1
- jQuery(document).ready(
2
- function($) {
3
-
4
- $('.edit-cache-action', '#misc-publishing-actions').click(
5
- function(e) {
6
- $(this)
7
- .next(':hidden')
8
- .slideDown('fast')
 
9
  .end()
10
  .hide();
11
 
@@ -13,28 +14,30 @@ jQuery(document).ready(
13
  }
14
  );
15
 
16
- $('.save-cache-action', '#misc-publishing-actions').click(
17
- function(e) {
18
- $(this)
 
19
  .parent()
20
- .slideUp('fast')
21
- .prev(':hidden')
22
  .show();
23
 
24
- $('#output-cache-action').text(
25
- $('#cache_action').children('option:selected').text()
26
  );
27
 
28
  e.preventDefault();
29
  }
30
  );
31
 
32
- $('.cancel-cache-action', '#misc-publishing-actions').click(
33
- function(e) {
34
- $(this)
 
35
  .parent()
36
- .slideUp('fast')
37
- .prev(':hidden')
38
  .show();
39
 
40
  e.preventDefault();
1
+ jQuery( document ).ready(
2
+ function( $ ) {
3
+
4
+ $( '.edit-cache-action', '#misc-publishing-actions' ).click(
5
+ function( e ) {
6
+
7
+ $( this )
8
+ .next( ':hidden' )
9
+ .slideDown( 'fast' )
10
  .end()
11
  .hide();
12
 
14
  }
15
  );
16
 
17
+ $( '.save-cache-action', '#misc-publishing-actions' ).click(
18
+ function( e ) {
19
+
20
+ $( this )
21
  .parent()
22
+ .slideUp( 'fast' )
23
+ .prev( ':hidden' )
24
  .show();
25
 
26
+ $( '#output-cache-action' ).text(
27
+ $( '#cache_action' ).children( 'option:selected' ).text()
28
  );
29
 
30
  e.preventDefault();
31
  }
32
  );
33
 
34
+ $( '.cancel-cache-action', '#misc-publishing-actions' ).click(
35
+ function( e ) {
36
+
37
+ $( this )
38
  .parent()
39
+ .slideUp( 'fast' )
40
+ .prev( ':hidden' )
41
  .show();
42
 
43
  e.preventDefault();
readme.txt CHANGED
@@ -1,8 +1,8 @@
1
  === Cache Enabler - WordPress Cache ===
2
  Contributors: keycdn
3
  Tags: cache, caching, wordpress cache, wp cache, performance, gzip, webp, http2
4
- Requires at least: 4.6
5
- Tested up to: 5.3
6
  Stable tag: trunk
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
@@ -30,7 +30,7 @@ The Cache Enabler plugin creates static HTML files and stores them on the server
30
  * Custom Post Type support
31
  * Expiry Directive
32
  * Support of *304 Not Modified* if the page has not modified since last cached
33
- * WebP Support (when combined with [Optimus](https://optimus.io/en/ "Optimus"))
34
  * Supports responsive images via srcset since WP 4.4
35
  * Works perfectly with [Autoptimize](https://wordpress.org/plugins/autoptimize/)
36
 
@@ -38,14 +38,14 @@ The Cache Enabler plugin creates static HTML files and stores them on the server
38
 
39
 
40
  = How does the caching work? =
41
- This plugin requires minimal setup time and allows you to easily take advantage of the benefits that come from using Wordpress caching.
42
 
43
- The Wordpress Cache Enabler has the ability to create 2 cached files. One is plain HTML and the other version is gzipped (gzip level 9). These static files are then used to deliver content faster to your users without any database lookups or gzipping as the files are already pre-compressed.
44
 
45
- When combined with Optimus, the Wordpress Cache Enabler allows you to easily deliver WebP images. The plugin will check your upload directory for any JPG or PNG images that have an equivalent WebP file. If there is, the URI of these image will be cached in a WebP static file by Cache Enabler. It is not required for all images to be converted to WebP when the "Create an additional cached version for WebP image support" option is enabled. This will not break any images that are not in WebP format. The plugin will deliver images that do have a WebP equivalent and will fall back to the JPG or PNG format for images that don't.
46
 
47
 
48
- = WP CLI =
49
 
50
  * Clear all page caches
51
  `wp cache-enabler clear`
@@ -58,12 +58,12 @@ When combined with Optimus, the Wordpress Cache Enabler allows you to easily del
58
 
59
 
60
  = Website =
61
- * [WordPress Cache Enabler - Documentation](https://www.keycdn.com/support/wordpress-cache-enabler-plugin/ "WordPress Cache Enabler - Documentation")
62
 
63
 
64
  = System Requirements =
65
  * PHP >=5.6
66
- * WordPress >=4.6
67
 
68
 
69
  = Contribute =
@@ -81,8 +81,23 @@ When combined with Optimus, the Wordpress Cache Enabler allows you to easily del
81
 
82
  == Changelog ==
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  = 1.3.5 =
85
- * WP CLI cache clearing (Thanks to Steve Grunwell)
86
  * Added cache_enabler_disk_webp_converted_data filter
87
  * Improved WebP URL conversion
88
  * Fixed advanced cache issue
@@ -103,7 +118,7 @@ When combined with Optimus, the Wordpress Cache Enabler allows you to easily del
103
  * Add filter option before minification
104
 
105
  = 1.3.0 =
106
- * Clear cache on woocommerce stock updates
107
 
108
  = 1.2.3 =
109
  * Fix expiry time
@@ -112,7 +127,7 @@ When combined with Optimus, the Wordpress Cache Enabler allows you to easily del
112
  * Pages can now be excluded from cache by a path matching regex
113
  * Plugin upgrades can now trigger cache clear
114
  * Scheduled posts and drafts are now properly handled
115
- * A missing trailing slash will now redirect like wordpress does by default
116
 
117
  = 1.2.2 =
118
  * Fixed settings form issue
1
  === Cache Enabler - WordPress Cache ===
2
  Contributors: keycdn
3
  Tags: cache, caching, wordpress cache, wp cache, performance, gzip, webp, http2
4
+ Requires at least: 5.1
5
+ Tested up to: 5.5
6
  Stable tag: trunk
7
  License: GPLv2 or later
8
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
30
  * Custom Post Type support
31
  * Expiry Directive
32
  * Support of *304 Not Modified* if the page has not modified since last cached
33
+ * WebP Support (when combined with [Optimus](https://optimus.io "Optimus"))
34
  * Supports responsive images via srcset since WP 4.4
35
  * Works perfectly with [Autoptimize](https://wordpress.org/plugins/autoptimize/)
36
 
38
 
39
 
40
  = How does the caching work? =
41
+ This plugin requires minimal setup time and allows you to easily take advantage of the benefits that come from using WordPress caching.
42
 
43
+ The WordPress Cache Enabler has the ability to create 2 cached files. One is plain HTML and the other version is gzipped (gzip level 9). These static files are then used to deliver content faster to your users without any database lookups or gzipping as the files are already pre-compressed.
44
 
45
+ When combined with Optimus, the WordPress Cache Enabler allows you to easily deliver WebP images. The plugin will check your upload directory for any JPG or PNG images that have an equivalent WebP file. If there is, the URI of these image will be cached in a WebP static file by Cache Enabler. It is not required for all images to be converted to WebP when the "Create an additional cached version for WebP image support" option is enabled. This will not break any images that are not in WebP format. The plugin will deliver images that do have a WebP equivalent and will fall back to the JPG or PNG format for images that don't.
46
 
47
 
48
+ = WP-CLI =
49
 
50
  * Clear all page caches
51
  `wp cache-enabler clear`
58
 
59
 
60
  = Website =
61
+ * [WordPress Cache Enabler - Documentation](https://www.keycdn.com/support/wordpress-cache-enabler-plugin "WordPress Cache Enabler - Documentation")
62
 
63
 
64
  = System Requirements =
65
  * PHP >=5.6
66
+ * WordPress >=5.1
67
 
68
 
69
  = Contribute =
81
 
82
  == Changelog ==
83
 
84
+ = 1.4.0 =
85
+ * Update default cache behavior for WooCommerce stock update
86
+ * Update Cache Behavior setting for plugin actions
87
+ * Update admin bar clear cache buttons
88
+ * Update cache behavior for logged in users
89
+ * Update default clear cache publishing action
90
+ * Update advanced cache settings
91
+ * Update trailing slash handling
92
+ * Update settings page
93
+ * Add Cache Behavior setting for WooCommerce stock update
94
+ * Add fbclid as default URL query parameter to bypass cache
95
+ * Add scheme-based caching
96
+ * Fix advanced cache for multisite networks
97
+ * Fix minor bugs
98
+
99
  = 1.3.5 =
100
+ * WP-CLI cache clearing (Thanks to Steve Grunwell)
101
  * Added cache_enabler_disk_webp_converted_data filter
102
  * Improved WebP URL conversion
103
  * Fixed advanced cache issue
118
  * Add filter option before minification
119
 
120
  = 1.3.0 =
121
+ * Clear cache on WooCommerce stock updates
122
 
123
  = 1.2.3 =
124
  * Fix expiry time
127
  * Pages can now be excluded from cache by a path matching regex
128
  * Plugin upgrades can now trigger cache clear
129
  * Scheduled posts and drafts are now properly handled
130
+ * A missing trailing slash will now redirect like WordPress does by default
131
 
132
  = 1.2.2 =
133
  * Fixed settings form issue