PluginProbe
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score / 1.1.2
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score v1.1.2
trunk 1.0 1.0.1 1.1 1.1.1 1.1.2 1.2 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 2.0 2.0.1 2.0.2 2.0.3 2.0.4 2.1 2.1.1 2.1.2 2.2 2.2.1 All 69 releases
powered-cache / includes / dropins / page-cache.php

page-cache.php in Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score 1.1.2, at includes/dropins/page-cache.php

376 lines 11.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * File based caching drop-in based on Taylor Lovett's Simple Cache
4 * @link https://github.com/tlovett1/simple-cache/blob/master/inc/dropins/file-based-page-cache.php
5 */
6 defined( 'ABSPATH' ) || exit;
7
8 // Don't cache robots.txt or htacesss
9 if ( strpos( $_SERVER['REQUEST_URI'], 'robots.txt' ) !== false || strpos( $_SERVER['REQUEST_URI'], '.htaccess' ) !== false ) {
10 return;
11 }
12
13 // Don't cache non-GET requests
14 if ( ! isset( $_SERVER['REQUEST_METHOD'] ) || 'GET' !== $_SERVER['REQUEST_METHOD'] ) {
15 return;
16 }
17
18 // Don't cache wp-admin
19 if ( is_admin() ) {
20 return;
21 }
22
23
24
25 $file_extension = $_SERVER['REQUEST_URI'];
26 $file_extension = preg_replace( '#^(.*?)\?.*$#', '$1', $file_extension );
27 $file_extension = trim( preg_replace( '#^.*\.(.*)$#', '$1', $file_extension ) );
28
29 // Don't cache disallowed extensions. Prevents wp-cron.php, xmlrpc.php, etc.
30 if ( ! preg_match( '#index\.php$#i', $_SERVER['REQUEST_URI'] ) && in_array( $file_extension, array( 'php', 'xml', 'xsl' ) ) ) {
31 return;
32 }
33
34 if ( ! $GLOBALS['powered_cache_options']['enable_page_caching'] ) {
35 return;
36 }
37
38 // Don't cache page with these user agents
39 if ( ! empty( $GLOBALS['powered_cache_options']['rejected_user_agents'] ) ) {
40 $rejected_user_agents = preg_split( '#(\r\n|\r|\n)#', $GLOBALS['powered_cache_options']['rejected_user_agents'] );
41 $rejected_user_agents = implode( '|', $rejected_user_agents );
42 if ( ! empty( $rejected_user_agents ) && isset( $_SERVER['HTTP_USER_AGENT'] ) && preg_match( '#(' . $rejected_user_agents . ')#', $_SERVER['HTTP_USER_AGENT'] ) ) {
43 return;
44 }
45 }
46
47
48 // Don't cache SSL
49 if ( powered_cache_is_ssl() && ( ! isset( $GLOBALS['powered_cache_options']['ssl_cache'] ) || false === $GLOBALS['powered_cache_options']['ssl_cache'] ) ) {
50 return;
51 }
52
53
54 // dont cache mobile
55 if ( ! isset( $GLOBALS['powered_cache_options']['cache_mobile'] ) || true !== $GLOBALS['powered_cache_options']['cache_mobile'] ) {
56 global $powered_cache_mobile_browsers, $powered_cache_mobile_prefixes;
57
58 $mobile_browsers = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_browsers ) ), ' ' );
59 $mobile_prefixes = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_prefixes ) ), ' ' );
60 // Don't cache if mobile detection is activated
61 if ( (preg_match( '#^.*(' . $mobile_browsers . ').*#i', $_SERVER['HTTP_USER_AGENT'] ) || preg_match( '#^(' . $mobile_prefixes . ').*#i', substr( $_SERVER['HTTP_USER_AGENT'], 0, 4 ) ) ) ) {
62 return '';
63 }
64 }
65
66
67 if ( ! empty( $_COOKIE ) ) {
68 //Don't cache if logged in
69 if ( ! isset( $GLOBALS['powered_cache_options']['loggedin_user_cache'] ) || false === $GLOBALS['powered_cache_options']['loggedin_user_cache'] ) {
70 $wp_cookies = array( 'wordpressuser_', 'wordpresspass_', 'wordpress_sec_', 'wordpress_logged_in_' );
71
72 // check logged-in cookie
73 foreach ( $_COOKIE as $key => $value ) {
74 foreach ( $wp_cookies as $cookie ) {
75 if ( strpos( $key, $cookie ) !== false ) {
76 // Logged in!
77 return;
78 }
79 }
80 }
81 }
82
83
84 if ( ! empty( $_COOKIE['powered_cache_commented_posts'] ) ) {
85 foreach ( $_COOKIE['powered_cache_commented_posts'] as $path ) {
86 if ( rtrim( $path, '/' ) === rtrim( $_SERVER['REQUEST_URI'], '/' ) ) {
87 // User commented on this post
88 return;
89 }
90 }
91 }
92
93 // don't cache specific cookie
94 if ( ! empty( $GLOBALS['powered_cache_options']['rejected_cookies'] ) ) {
95 $rejected_cookies = preg_split( '#(\r\n|\r|\n)#', $GLOBALS['powered_cache_options']['rejected_cookies'] );
96 $rejected_cookies = implode( '|', $rejected_cookies );
97 if ( preg_match( '#(' . $rejected_cookies . ')#', var_export( $_COOKIE, true ) ) ) {
98 return;
99 }
100 }
101 } // End if().
102
103 // Deal with optional cache exceptions
104 if ( ! empty( $GLOBALS['powered_cache_options']['rejected_uri'] ) ) {
105 $exceptions = preg_split( '#(\r\n|\r|\n)#', $GLOBALS['powered_cache_options']['rejected_uri'] );
106
107 foreach ( $exceptions as $exception ) {
108 if ( preg_match( '#^[\s]*$#', $exception ) ) {
109 continue;
110 }
111
112 // full url exception
113 if ( preg_match( '#^https?://#', $exception ) ) {
114 $exception = parse_url( $exception, PHP_URL_PATH );
115 }
116
117 if ( preg_match( '#^(' . $exception . ')$#', $_SERVER['REQUEST_URI'] ) ) {
118 return;
119 }
120 }
121 }
122
123
124 $accepted_query_strings = array();
125 // cache url with allowed query string
126 if ( ! empty( $GLOBALS['powered_cache_options']['accepted_query_strings'] ) ) {
127 $accepted_query_strings = preg_split( '#(\r\n|\r|\n)#', $GLOBALS['powered_cache_options']['accepted_query_strings'] );
128 }
129
130 if ( ! empty( $_GET ) && isset( $accepted_query_strings ) && is_array( $accepted_query_strings ) && ! array_intersect( array_keys( $_GET ), $accepted_query_strings ) ) {
131 return;
132 }
133
134 powered_cache_serve_cache();
135
136 ob_start( 'powered_cache_page_buffer' );
137
138 /**
139 * Cache output before it goes to the browser
140 *
141 * @param string $buffer
142 * @param int $flags
143 * @since 1.0
144 * @return string
145 */
146 function powered_cache_page_buffer( $buffer, $flags ) {
147 if ( strlen( $buffer ) < 255 ) {
148 return $buffer;
149 }
150
151 // Don't cache search, 404, or password protected
152 if ( is_404() || is_search() || post_password_required() ) {
153 return $buffer;
154 }
155
156 // maybe we shouldn't cache template file has this constant
157 if ( defined( 'DONOTCACHEPAGE' ) && true === DONOTCACHEPAGE ) {
158 return $buffer;
159 }
160
161 // plugins might want to use filter
162 if ( true !== apply_filters( 'powered_cache_page_cache_enable', true ) ) {
163 return $buffer;
164 }
165
166 include_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php';
167 include_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php';
168
169 $filesystem = new WP_Filesystem_Direct( new StdClass() );
170
171 if ( ! function_exists( 'powered_cache_get_cache_dir' ) ) {
172 return $buffer;
173 }
174
175 // Make sure we can read/write files and that proper folders exist
176 if ( ! $filesystem->exists( untrailingslashit( powered_cache_get_cache_dir() ) ) ) {
177 if ( ! $filesystem->mkdir( untrailingslashit( powered_cache_get_cache_dir() ) ) ) {
178 // Can not cache!
179 return $buffer;
180 }
181 }
182
183 if ( ! $filesystem->exists( powered_cache_get_page_cache_dir() ) ) {
184 if ( ! $filesystem->mkdir( powered_cache_get_page_cache_dir() ) ) {
185 // Can not cache!
186 return $buffer;
187 }
188 }
189
190 $buffer = apply_filters( 'powered_cache_page_caching_buffer', $buffer );
191
192 $url_path = powered_cache_get_url_path();
193
194 $dirs = explode( '/', $url_path );
195
196 $path = untrailingslashit( powered_cache_get_page_cache_dir() );
197
198 foreach ( $dirs as $dir ) {
199 if ( ! empty( $dir ) ) {
200 $path .= '/' . $dir;
201
202 if ( ! $filesystem->exists( $path ) ) {
203 if ( ! $filesystem->mkdir( $path ) ) {
204 // Can not cache!
205 return $buffer;
206 }
207 }
208 }
209 }
210
211 $modified_time = time(); // Make sure modified time is consistent
212
213 if ( array_key_exists( 'show_cache_message', $GLOBALS['powered_cache_options'] ) && true === $GLOBALS['powered_cache_options']['show_cache_message'] ) {
214 if ( preg_match( '#</html>#i', $buffer ) ) {
215 $buffer .= "\n<!-- Cache served by Powered Cache - Last modified: " . gmdate( 'D, d M Y H:i:s', $modified_time ) . " GMT -->\n";
216 }
217 }
218
219 $index_name = powered_cache_index_file();
220
221 if ( $GLOBALS['powered_cache_options']['gzip_compression'] && function_exists( 'gzencode' ) ) {
222 $filesystem->put_contents( $path . '/' . $index_name, gzencode( $buffer, 3 ), FS_CHMOD_FILE );
223 $filesystem->touch( $path . '/' . $index_name, $modified_time );
224 } else {
225 $filesystem->put_contents( $path . '/' . $index_name, $buffer, FS_CHMOD_FILE );
226 $filesystem->touch( $path . '/' . $index_name, $modified_time );
227 }
228
229 header( 'Cache-Control: no-cache' ); // Check back every time to see if re-download is necessary
230
231 header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $modified_time ) . ' GMT' );
232
233 do_action( 'powered_cache_page_cached', $buffer );
234
235 if ( function_exists( 'ob_gzhandler' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
236 return ob_gzhandler( $buffer, $flags );
237 } else {
238 return $buffer;
239 }
240 }
241
242
243 /**
244 * Optionally serve cache and exit
245 *
246 * @since 1.0
247 */
248 function powered_cache_serve_cache() {
249
250 $file_name = powered_cache_index_file();
251
252 $path = rtrim( $GLOBALS['powered_cache_options']['cache_location'], '/' ) . '/powered-cache/' . rtrim( powered_cache_get_url_path(), '/' ) . '/' . $file_name;
253
254 $modified_time = (int) @filemtime( $path );
255
256 header( 'Cache-Control: no-cache' ); // Check back in an hour
257
258 if ( ! empty( $modified_time ) && ! empty( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) && strtotime( $_SERVER['HTTP_IF_MODIFIED_SINCE'] ) === $modified_time ) {
259 header( $_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified', true, 304 );
260 exit;
261 }
262
263 if ( @file_exists( $path ) && @is_readable( $path ) ) {
264
265 header( 'X-Powered-Cache: php' );
266
267 if ( function_exists( 'gzencode' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
268 header( 'Content-Encoding: gzip' );
269 }
270
271 @readfile( $path );
272
273 exit;
274 }
275 }
276
277 /**
278 * Get URL path for caching
279 *
280 * @since 1.0
281 * @return string
282 */
283 function powered_cache_get_url_path() {
284
285 $host = ( isset( $_SERVER['HTTP_HOST'] ) ) ? $_SERVER['HTTP_HOST'] : '';
286
287 return rtrim( $host, '/' ) . $_SERVER['REQUEST_URI'];
288 }
289
290 function powered_cache_get_user_cookie() {
291 if ( empty( $_COOKIE ) ) {
292 return false;
293 }
294
295 foreach ( $_COOKIE as $c_key => $val ) {
296 if ( false !== strpos( $c_key, 'wordpress_logged_in_' ) ) {
297 return $val;
298 }
299 }
300
301 return false;
302 }
303
304
305 /**
306 * Determines cache file names
307 * @since 1.0
308 * @return string
309 */
310 function powered_cache_index_file() {
311 $file_name = 'index';
312
313 if ( powered_cache_is_ssl() ) {
314 $file_name .= '-https';
315 }
316
317 // separate file for mobile cache
318 if ( isset( $GLOBALS['powered_cache_options']['cache_mobile'], $GLOBALS['powered_cache_options']['cache_mobile_separate_file'] )
319 && true === $GLOBALS['powered_cache_options']['cache_mobile']
320 && true === $GLOBALS['powered_cache_options']['cache_mobile_separate_file']
321 ) {
322
323 global $powered_cache_mobile_browsers, $powered_cache_mobile_prefixes;
324
325 $mobile_browsers = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_browsers ) ), ' ' );
326 $mobile_prefixes = addcslashes( implode( '|', preg_split( '/[\s*,\s*]*,+[\s*,\s*]*/', $powered_cache_mobile_prefixes ) ), ' ' );
327
328 // Don't cache if mobile detection is activated
329 if ( (preg_match( '#^.*(' . $mobile_browsers . ').*#i', $_SERVER['HTTP_USER_AGENT'] ) || preg_match( '#^(' . $mobile_prefixes . ').*#i', substr( $_SERVER['HTTP_USER_AGENT'], 0, 4 ) ) ) ) {
330 $file_name .= '-mobile';
331 }
332 }
333
334 if ( isset( $GLOBALS['powered_cache_options']['loggedin_user_cache'] )
335 && true === $GLOBALS['powered_cache_options']['loggedin_user_cache']
336 ) {
337 $usr_cookie = powered_cache_get_user_cookie();
338 if ( false !== $usr_cookie ) {
339 $cookie_info = explode( '|', $usr_cookie );
340
341 // user specific cache dir
342 $file_name .= '_' . $cookie_info[0] . '-' . $cookie_info[1];
343 }
344 }
345
346 $file_name .= '.html';
347
348 if ( function_exists( 'gzencode' ) && $GLOBALS['powered_cache_options']['gzip_compression'] ) {
349 $file_name .= '_gzip';
350 }
351
352 return $file_name;
353 }
354
355
356 /**
357 * is_ssl moved load.php in WP 4.6 but we support WP 4.1+
358 *
359 * @return bool
360 */
361 function powered_cache_is_ssl() {
362 if ( isset( $_SERVER['HTTPS'] ) ) {
363 if ( 'on' == strtolower( $_SERVER['HTTPS'] ) ) {
364 return true;
365 }
366
367 if ( '1' == $_SERVER['HTTPS'] ) {
368 return true;
369 }
370 } elseif ( isset( $_SERVER['SERVER_PORT'] ) && ( '443' == $_SERVER['SERVER_PORT'] ) ) {
371 return true;
372 }
373
374 return false;
375 }
376