PluginProbe
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score / trunk
Powered Cache – Caching and Optimization for WordPress – Easily Improve PageSpeed & Web Vitals Score vtrunk
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
← All changes | includes/file-optimizer.php +107 -6 2.0trunk View file →
@@ -60,14 +60,28 @@
60 60 'css' => 'text/css',
61 61 'js' => 'application/javascript',
62 62 );
63 63
64 -/*
65 - Constants */
64 +$wp_content_base = '/wp-content';
65 +if ( isset( $_SERVER['SCRIPT_NAME'] ) && false === strpos( $_SERVER['SCRIPT_NAME'], '/wp-content' ) ) {
66 + $script_name = explode( '/', ltrim( $_SERVER['SCRIPT_NAME'], '/' ) );
67 + if ( ! empty( $script_name[0] ) ) {
68 + $wp_content_base = '/' . $script_name[0];
69 + }
70 +}
71 +
72 +$current_dir = file_optimizer_normalize_path( realpath( dirname( __DIR__ ) ) );
73 +
74 +/* Constants */
66 75 // By default determine the document root from this scripts path in the plugins dir (you can hardcode this define)
67 -define( 'CONCAT_FILES_ROOT', substr( dirname( __DIR__ ), 0, strpos( dirname( __DIR__ ), '/wp-content' ) ) );
68 -define( 'POWERED_CACHE_FO_CACHE_DIR', CONCAT_FILES_ROOT . '/wp-content/cache/min/' );
76 +define( 'CONCAT_FILES_ROOT', substr( $current_dir, 0, strpos( $current_dir, $wp_content_base ) ) );
77 +define( 'POWERED_CACHE_FO_CACHE_DIR', CONCAT_FILES_ROOT . $wp_content_base.'/cache/min/' );
78 +define( 'POWERED_CACHE_FO_DEBUG', false );
69 79
80 +if ( ! defined( 'POWERED_CACHE_FO_DISABLE_CACHE_HEADERS' ) ) {
81 + define( 'POWERED_CACHE_FO_DISABLE_CACHE_HEADERS', false );
82 +}
83 +
70 84 if ( ! file_exists( POWERED_CACHE_FO_CACHE_DIR ) ) {
71 85 mkdir( POWERED_CACHE_FO_CACHE_DIR, 0775, true );
72 86 }
73 87
@@ -115,12 +129,14 @@
115 129 }
116 130
117 131 function concat_get_path( $uri ) {
118 132 if ( ! strlen( $uri ) ) {
133 + maybe_add_debug_log( sprintf( "File Optimizer 400 - could not retrieve file path for uri %s", $uri ) );
119 134 concat_http_status_exit( 400 );
120 135 }
121 136
122 137 if ( false !== strpos( $uri, '..' ) || false !== strpos( $uri, "\0" ) ) {
138 + maybe_add_debug_log( sprintf( "File Optimizer 400 - could not retrieve file path for uri %s", $uri ) );
123 139 concat_http_status_exit( 400 );
124 140 }
125 141
126 142 return CONCAT_FILES_ROOT . ( '/' != $uri[0] ? '/' : '' ) . $uri;
@@ -138,8 +154,9 @@
138 154 }
139 155
140 156 /* Main() */
141 157 if ( ! in_array( $_SERVER['REQUEST_METHOD'], array( 'GET', 'HEAD' ) ) ) {
158 + maybe_add_debug_log( sprintf( "File Optimizer 400 - unsupported request method: %s", $_SERVER['REQUEST_METHOD'] ) );
142 159 concat_http_status_exit( 400 );
143 160 }
144 161
145 162 // /_static/??/foo/bar.css,/foo1/bar/baz.css?m=293847g
@@ -146,12 +163,14 @@
146 163 // or
147 164 // /_static/??-eJzTT8vP109KLNJLLi7W0QdyDEE8IK4CiVjn2hpZGluYmKcDABRMDPM=
148 165 $args = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_QUERY );
149 166 if ( ! $args || false === strpos( $args, '?' ) ) {
167 + maybe_add_debug_log( sprintf( "File Optimizer 400 - empty query arg or not ? exists" ) );
150 168 concat_http_status_exit( 400 );
151 169 }
152 170
153 171 $args = substr( $args, strpos( $args, '?' ) + 1 );
172 +$args = str_replace( [ '&minify=1', '&minify=0' ], '', $args ); // remove minify parameter
154 173
155 174 // /foo/bar.css,/foo1/bar/baz.css?m=293847g
156 175 // or
157 176 // -eJzTT8vP109KLNJLLi7W0QdyDEE8IK4CiVjn2hpZGluYmKcDABRMDPM=
@@ -159,8 +178,9 @@
159 178 $args = @gzuncompress( base64_decode( substr( $args, 1 ) ) );
160 179
161 180 // Invalid data, abort!
162 181 if ( false === $args ) {
182 + maybe_add_debug_log( sprintf( "File Optimizer 400 - Invalid Data" ) );
163 183 concat_http_status_exit( 400 );
164 184 }
165 185 }
166 186
@@ -172,13 +192,23 @@
172 192
173 193 // /foo/bar.css,/foo1/bar/baz.css
174 194 $args = explode( ',', $args );
175 195 if ( ! $args ) {
196 + maybe_add_debug_log( sprintf( "File Optimizer 400 - Empty args" ) );
176 197 concat_http_status_exit( 400 );
177 198 }
178 199
200 +// array('/wp-content/foo/bar.css','//cdn.cname.com/wp-content/foo/bar.css')
201 +// get real path when it masked from cdn
202 +foreach ( $args as $index => $arg ) {
203 + if ( 0 === stripos( $arg, '//' ) ) {
204 + $args[ $index ] = parse_url( str_replace( '//', 'http://', $arg ), PHP_URL_PATH );
205 + }
206 +}
207 +
179 208 // array( '/foo/bar.css', '/foo1/bar/baz.css' )
180 209 if ( 0 == count( $args ) || count( $args ) > $concat_max_files ) {
210 + maybe_add_debug_log( sprintf( "File Optimizer 400 - Concatenating too many or zero file: %s files on queue", count( $args ) ) );
181 211 concat_http_status_exit( 400 );
182 212 }
183 213
184 214 // If we're in a subdirectory context, use that as the root.
@@ -194,10 +224,10 @@
194 224 $last_modified = 0;
195 225 $pre_output = '';
196 226 $output = '';
197 227
198 -$do_minify = (bool) stripos( $_SERVER['REQUEST_URI'], 'minify=1' );
199 -$hash = sha1( $_SERVER['REQUEST_URI'] );
228 +$do_minify = (bool) stripos( $_SERVER['REQUEST_URI'], 'minify=1' );
229 +$hash = sha1( $_SERVER['REQUEST_URI'] );
200 230 $latest_file = end( $args );
201 231
202 232 $cache_file_name = POWERED_CACHE_FO_CACHE_DIR . $hash;
203 233 if ( 'application/javascript' == concat_get_mtype( $latest_file ) ) {
@@ -210,8 +240,9 @@
210 240 $buf = @file_get_contents( $cache_file_name );
211 241 if ( $buf ) {
212 242 $stat = stat( $cache_file_name );
213 243
244 + set_cache_headers();
214 245 header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $stat['mtime'] ) . ' GMT' );
215 246 header( 'Content-Length: ' . ( strlen( $pre_output ) + strlen( $buf ) ) );
216 247 header( 'Content-Type: ' . concat_get_mtype( $latest_file ) );
217 248
@@ -224,13 +255,15 @@
224 255
225 256 $fullpath = concat_get_path( $uri );
226 257
227 258 if ( ! file_exists( $fullpath ) ) {
259 + maybe_add_debug_log( sprintf( "File Optimizer 404 - Missing file: %s", $fullpath ) );
228 260 concat_http_status_exit( 404 );
229 261 }
230 262
231 263 $mime_type = concat_get_mtype( $fullpath );
232 264 if ( ! in_array( $mime_type, $concat_types ) ) {
265 + maybe_add_debug_log( sprintf( "File Optimizer 400 - Unsupported mime type: %s", $mime_type ) );
233 266 concat_http_status_exit( 400 );
234 267 }
235 268
236 269 if ( $concat_unique ) {
@@ -238,8 +271,9 @@
238 271 $last_mime_type = $mime_type;
239 272 }
240 273
241 274 if ( $last_mime_type != $mime_type ) {
275 + maybe_add_debug_log( sprintf( "File Optimizer 400 - Different mime type: last mime %s vs current mime: %s", $last_mime_type, $mime_type ) );
242 276 concat_http_status_exit( 400 );
243 277 }
244 278 }
245 279
@@ -244,8 +278,9 @@
244 278 }
245 279
246 280 $stat = stat( $fullpath );
247 281 if ( false === $stat ) {
282 + maybe_add_debug_log( sprintf( "File Optimizer 500 - false stat" ) );
248 283 concat_http_status_exit( 500 );
249 284 }
250 285
251 286 if ( $stat['mtime'] > $last_modified ) {
@@ -253,8 +288,9 @@
253 288 }
254 289
255 290 $buf = file_get_contents( $fullpath );
256 291 if ( false === $buf ) {
292 + maybe_add_debug_log( sprintf( "File Optimizer 500 - false buffer" ) );
257 293 concat_http_status_exit( 500 );
258 294 }
259 295
260 296 if ( 'text/css' == $mime_type ) {
@@ -327,8 +363,9 @@
327 363 $output = $css_minify->minify();
328 364 }
329 365 }
330 366
367 +set_cache_headers();
331 368 header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s', $last_modified ) . ' GMT' );
332 369 header( 'Content-Length: ' . ( strlen( $pre_output ) + strlen( $output ) ) );
333 370 header( "Content-Type: $mime_type" );
334 371
@@ -341,4 +378,68 @@
341 378 $cache_file_name .= '.css';
342 379 }
343 380
344 381 file_put_contents( $cache_file_name, $pre_output . $output );
382 +
383 +
384 +/**
385 + * Normalize a filesystem path.
386 + *
387 + * On windows systems, replaces backslashes with forward slashes
388 + * and forces upper-case drive letters.
389 + * Allows for two leading slashes for Windows network shares, but
390 + * ensures that all other duplicate slashes are reduced to a single.
391 + *
392 + * @param string $path Path to normalize.
393 + *
394 + * @return string Normalized path.
395 + * @see wp_normalize_path
396 + *
397 + */
398 +function file_optimizer_normalize_path( $path ) {
399 + $wrapper = '';
400 +
401 + // Standardise all paths to use '/'.
402 + $path = str_replace( '\\', '/', $path );
403 +
404 + // Replace multiple slashes down to a singular, allowing for network shares having two slashes.
405 + $path = preg_replace( '|(?<=.)/+|', '/', $path );
406 +
407 + // Windows paths should uppercase the drive letter.
408 + if ( ':' === substr( $path, 1, 1 ) ) {
409 + $path = ucfirst( $path );
410 + }
411 +
412 + return $wrapper . $path;
413 +}
414 +
415 +/**
416 + * Maybe add debug message
417 + *
418 + * @param string $message Debug message
419 + *
420 + * @since 2.3
421 + */
422 +function maybe_add_debug_log( $message ) {
423 + if ( defined( 'POWERED_CACHE_FO_DEBUG' ) && POWERED_CACHE_FO_DEBUG ) {
424 + error_log( $message );
425 + }
426 +}
427 +
428 +
429 +/**
430 + * Add cache headers
431 + *
432 + * @return void
433 + * @since 2.5.3
434 + */
435 +function set_cache_headers() {
436 + if ( defined( 'POWERED_CACHE_FO_DISABLE_CACHE_HEADERS' ) && POWERED_CACHE_FO_DISABLE_CACHE_HEADERS ) {
437 + return;
438 + }
439 +
440 + $ttl_in_seconds = 31536000; // 365 days
441 + $ttl = gmdate( "D, d M Y H:i:s", time() + $ttl_in_seconds ) . " GMT";
442 +
443 + header( "Expires: $ttl" );
444 + header( "Cache-Control: max-age=$ttl_in_seconds" );
445 +}