PluginProbe
Autoptimize / 1.2
Autoptimize v1.2
2.2.2 2.3.0 2.3.1 2.3.2 2.3.3 2.3.4 2.4.0 2.4.1 2.4.2 2.4.3 2.4.4 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 2.7.8 All 107 releases
← All changes | classes/autoptimizeCache.php +155 -827 2.7.81.2 View file →
@@ -1,833 +1,161 @@
1 1 <?php
2 -/**
3 - * Handles disk-cache-related operations.
4 - */
5 2
6 -if ( ! defined( 'ABSPATH' ) ) {
7 - exit;
8 -}
9 -
10 3 class autoptimizeCache
11 4 {
12 - /**
13 - * Cache filename.
14 - *
15 - * @var string
16 - */
17 - private $filename;
5 + private $filename;
6 + private $mime;
7 + private $cachedir;
8 + private $delayed;
9 +
10 + public function __construct($md5,$ext='php')
11 + {
12 + $this->cachedir = AUTOPTIMIZE_CACHE_DIR;
13 + $this->delayed = AUTOPTIMIZE_CACHE_DELAY;
14 + $this->nogzip = AUTOPTIMIZE_CACHE_NOGZIP;
15 + if($this->nogzip == false)
16 + $this->filename = 'autoptimize_'.$md5.'.php';
17 + else
18 + $this->filename = 'autoptimize_'.$md5.'.'.$ext;
19 + }
20 +
21 + public function check()
22 + {
23 + if(!file_exists($this->cachedir.$this->filename))
24 + {
25 + //No cached file, sorry
26 + return false;
27 + }
28 + //Cache exists!
29 + return true;
30 + }
31 +
32 + public function retrieve()
33 + {
34 + if($this->check())
35 + {
36 + if($this->nogzip == false)
37 + return file_get_contents($this->cachedir.$this->filename.'.none');
38 + else
39 + return file_get_contents($this->cachedir.$this->filename);
40 + }
41 + return false;
42 + }
43 +
44 + public function cache($code,$mime)
45 + {
46 + if($this->nogzip == false)
47 + {
48 + $file = ($this->delayed ? 'delayed.php' : 'default.php');
49 + $phpcode = file_get_contents(WP_PLUGIN_DIR.'/autoptimize/config/'.$file);
50 + $phpcode = str_replace(array('%%CONTENT%%','exit;'),array($mime,''),$phpcode);
51 + file_put_contents($this->cachedir.$this->filename,$phpcode);
52 + file_put_contents($this->cachedir.$this->filename.'.none',$code);
53 + if(!$this->delayed)
54 + {
55 + //Compress now!
56 + file_put_contents($this->cachedir.$this->filename.'.deflate',gzencode($code,9,FORCE_DEFLATE));
57 + file_put_contents($this->cachedir.$this->filename.'.gzip',gzencode($code,9,FORCE_GZIP));
58 + }
59 + }else{
60 + //Write code to cache without doing anything else
61 + file_put_contents($this->cachedir.$this->filename,$code);
62 + }
63 + }
64 +
65 + public function getname()
66 + {
67 + return $this->filename;
68 + }
69 +
70 + static function clearall()
71 + {
72 + //Cache not available :(
73 + if(!autoptimizeCache::cacheavail())
74 + return false;
75 +
76 + //Clean the cachedir
77 + $scan = scandir(AUTOPTIMIZE_CACHE_DIR);
78 + foreach($scan as $file)
79 + {
80 + if(!in_array($file,array('.','..')) && strpos($file,'autoptimize') !== false && is_file(AUTOPTIMIZE_CACHE_DIR.$file))
81 + {
82 + @unlink(AUTOPTIMIZE_CACHE_DIR.$file);
83 + }
84 + }
85 +
86 + //Do we need to clean WP Super Cache's cache files?
87 + if(function_exists('wp_cache_clear_cache'))
88 + {
89 + //Newer WP-Super-Cache
90 + //See http://ocaoimh.ie/wp-super-cache-developers/
91 + wp_cache_clear_cache();
92 + }elseif(file_exists(WP_CONTENT_DIR.'/wp-cache-config.php') && function_exists('prune_super_cache')){
93 + //Old WP-Super-Cache
94 + global $cache_path;
95 + prune_super_cache($cache_path.'supercache/',true);
96 + prune_super_cache($cache_path,true);
97 + }
98 +
99 + return true;
100 + }
101 +
102 + static function stats()
103 + {
104 + //Cache not available :(
105 + if(!autoptimizeCache::cacheavail())
106 + return 0;
18 107
19 - /**
20 - * Cache directory path (with a trailing slash).
21 - *
22 - * @var string
23 - */
24 - private $cachedir;
25 -
26 - /**
27 - * Whether gzipping is done by the web server or us.
28 - * True => we don't gzip, the web server does it.
29 - * False => we do it ourselves.
30 - *
31 - * @var bool
32 - */
33 - private $nogzip;
34 -
35 - /**
36 - * Ctor.
37 - *
38 - * @param string $md5 Hash.
39 - * @param string $ext Extension.
40 - */
41 - public function __construct( $md5, $ext = 'php' )
42 - {
43 - $_min_ext = '';
44 - if ( apply_filters( 'autoptimize_filter_cache_url_add_min_ext', false ) ) {
45 - $_min_ext = '.min';
46 - }
47 -
48 - $this->cachedir = AUTOPTIMIZE_CACHE_DIR;
49 - $this->nogzip = AUTOPTIMIZE_CACHE_NOGZIP;
50 - if ( ! $this->nogzip ) {
51 - $this->filename = AUTOPTIMIZE_CACHEFILE_PREFIX . $md5 . $_min_ext . '.php';
52 - } else {
53 - if ( in_array( $ext, array( 'js', 'css' ) ) ) {
54 - $this->filename = $ext . '/' . AUTOPTIMIZE_CACHEFILE_PREFIX . $md5 . $_min_ext . '.' . $ext;
55 - } else {
56 - $this->filename = AUTOPTIMIZE_CACHEFILE_PREFIX . $md5 . $_min_ext . '.' . $ext;
57 - }
58 - }
59 - }
60 -
61 - /**
62 - * Returns true if the cached file exists on disk.
63 - *
64 - * @return bool
65 - */
66 - public function check()
67 - {
68 - return file_exists( $this->cachedir . $this->filename );
69 - }
70 -
71 - /**
72 - * Returns cache contents if they exist, false otherwise.
73 - *
74 - * @return string|false
75 - */
76 - public function retrieve()
77 - {
78 - if ( $this->check() ) {
79 - if ( false == $this->nogzip ) {
80 - return file_get_contents( $this->cachedir . $this->filename . '.none' );
81 - } else {
82 - return file_get_contents( $this->cachedir . $this->filename );
83 - }
84 - }
85 - return false;
86 - }
87 -
88 - /**
89 - * Stores given $data in cache.
90 - *
91 - * @param string $data Data to cache.
92 - * @param string $mime Mimetype.
93 - *
94 - * @return void
95 - */
96 - public function cache( $data, $mime )
97 - {
98 - // readonly FS explicitly OK'ed by developer, so just pretend all is OK.
99 - if ( defined( 'AUTOPTIMIZE_CACHE_READONLY' ) ) {
100 - return true;
101 - }
102 -
103 - // off by default; check if cachedirs exist every time before caching
104 - //
105 - // to be activated for users that experience these ugly errors;
106 - // PHP Warning: file_put_contents failed to open stream: No such file or directory.
107 - if ( apply_filters( 'autoptimize_filter_cache_checkdirs_on_write', false ) ) {
108 - $this->check_and_create_dirs();
109 - }
110 -
111 - if ( false === $this->nogzip ) {
112 - // We handle gzipping ourselves.
113 - $file = 'default.php';
114 - $phpcode = file_get_contents( AUTOPTIMIZE_PLUGIN_DIR . 'config/' . $file );
115 - $phpcode = str_replace( array( '%%CONTENT%%', 'exit;' ), array( $mime, '' ), $phpcode );
116 -
117 - file_put_contents( $this->cachedir . $this->filename, $phpcode );
118 - file_put_contents( $this->cachedir . $this->filename . '.none', $data );
119 - } else {
120 - // Write code to cache without doing anything else.
121 - file_put_contents( $this->cachedir . $this->filename, $data );
122 -
123 - // save fallback .js or .css file if filter true (to be false by default) but not if snippet or single.
124 - if ( self::do_fallback() && strpos( $this->filename, '_snippet_' ) === false && strpos( $this->filename, '_single_' ) === false ) {
125 - $_extension = pathinfo( $this->filename, PATHINFO_EXTENSION );
126 - $_fallback_file = AUTOPTIMIZE_CACHEFILE_PREFIX . 'fallback.' . $_extension;
127 - if ( ( 'css' === $_extension || 'js' === $_extension ) && ! file_exists( $this->cachedir . $_extension . '/' . $_fallback_file ) ) {
128 - file_put_contents( $this->cachedir . $_extension . '/' . $_fallback_file, $data );
129 - }
130 - }
131 -
132 - if ( apply_filters( 'autoptimize_filter_cache_create_static_gzip', false ) ) {
133 - // Create an additional cached gzip file.
134 - file_put_contents( $this->cachedir . $this->filename . '.gz', gzencode( $data, 9, FORCE_GZIP ) );
135 - // If PHP Brotli extension is installed, create an additional cached Brotli file.
136 - if ( function_exists( 'brotli_compress' ) ) {
137 - file_put_contents( $this->cachedir . $this->filename . '.br', brotli_compress( $data, 11, BROTLI_GENERIC ) );
138 - }
139 - }
140 - }
141 -
142 - // Provide 3rd party action hook for every cache file that is created.
143 - // This hook can for example be used to inject a copy of the created cache file to a other domain.
144 - do_action( 'autoptimize_action_cache_file_created', $this->cachedir . $this->filename );
145 - }
146 -
147 - /**
148 - * Get cache filename.
149 - *
150 - * @return string
151 - */
152 - public function getname()
153 - {
154 - // NOTE: This could've maybe been a do_action() instead, however,
155 - // that ship has sailed.
156 - // The original idea here was to provide 3rd party code a hook so that
157 - // it can "listen" to all the complete autoptimized-urls that the page
158 - // will emit... Or something to that effect I think?
159 - apply_filters( 'autoptimize_filter_cache_getname', AUTOPTIMIZE_CACHE_URL . $this->filename );
160 -
161 - return $this->filename;
162 - }
163 -
164 - /**
165 - * Returns true if given `$file` is considered a valid Autoptimize cache file,
166 - * false otherwise.
167 - *
168 - * @param string $dir Directory name (with a trailing slash).
169 - * @param string $file Filename.
170 - * @return bool
171 - */
172 - protected static function is_valid_cache_file( $dir, $file )
173 - {
174 - if ( '.' !== $file && '..' !== $file &&
175 - false !== strpos( $file, AUTOPTIMIZE_CACHEFILE_PREFIX ) &&
176 - is_file( $dir . $file ) ) {
177 -
178 - // It's a valid file!
179 - return true;
180 - }
181 -
182 - // Everything else is considered invalid!
183 - return false;
184 - }
185 -
186 - /**
187 - * Clears contents of AUTOPTIMIZE_CACHE_DIR.
188 - *
189 - * @return void
190 - */
191 - protected static function clear_cache_classic()
192 - {
193 - $contents = self::get_cache_contents();
194 - foreach ( $contents as $name => $files ) {
195 - $dir = rtrim( AUTOPTIMIZE_CACHE_DIR . $name, '/' ) . '/';
196 - foreach ( $files as $file ) {
197 - if ( self::is_valid_cache_file( $dir, $file ) ) {
198 - @unlink( $dir . $file ); // @codingStandardsIgnoreLine
199 - }
200 - }
201 - }
202 -
203 - @unlink( AUTOPTIMIZE_CACHE_DIR . '/.htaccess' ); // @codingStandardsIgnoreLine
204 - }
205 -
206 - /**
207 - * Recursively deletes the specified pathname (file/directory) if possible.
208 - * Returns true on success, false otherwise.
209 - *
210 - * @param string $pathname Pathname to remove.
211 - *
212 - * @return bool
213 - */
214 - protected static function rmdir( $pathname )
215 - {
216 - $files = self::get_dir_contents( $pathname );
217 - foreach ( $files as $file ) {
218 - $path = $pathname . '/' . $file;
219 - if ( is_dir( $path ) ) {
220 - self::rmdir( $path );
221 - } else {
222 - unlink( $path );
223 - }
224 - }
225 -
226 - return rmdir( $pathname );
227 - }
228 -
229 - /**
230 - * Clears contents of AUTOPTIMIZE_CACHE_DIR by renaming the current
231 - * cache directory into a new one with a unique name and then
232 - * re-creating the default (empty) cache directory.
233 - *
234 - * Important/ Fixme: this does not take multisite into account, so
235 - * if advanced_cache_clear_enabled is true (it is not by default)
236 - * then the content for all subsites is zapped!
237 - *
238 - * @return bool Returns true when everything is done successfully, false otherwise.
239 - */
240 - protected static function clear_cache_via_rename()
241 - {
242 - $ok = false;
243 - $dir = self::get_pathname_base();
244 - $new_name = self::get_unique_name();
245 -
246 - // Makes sure the new pathname is on the same level...
247 - $new_pathname = dirname( $dir ) . '/' . $new_name;
248 - $renamed = @rename( $dir, $new_pathname ); // @codingStandardsIgnoreLine
249 -
250 - // When renamed, re-create the default cache directory back so it's
251 - // available again...
252 - if ( $renamed ) {
253 - $ok = self::cacheavail();
254 - }
255 -
256 - return $ok;
257 - }
258 -
259 - /**
260 - * Returns true when advanced cache clearing is enabled.
261 - *
262 - * @return bool
263 - */
264 - public static function advanced_cache_clear_enabled()
265 - {
266 - return apply_filters( 'autoptimize_filter_cache_clear_advanced', false );
267 - }
268 -
269 - /**
270 - * Returns a (hopefully) unique new cache folder name for renaming purposes.
271 - *
272 - * @return string
273 - */
274 - protected static function get_unique_name()
275 - {
276 - $prefix = self::get_advanced_cache_clear_prefix();
277 - $new_name = uniqid( $prefix, true );
278 -
279 - return $new_name;
280 - }
281 -
282 - /**
283 - * Get cache prefix name used in advanced cache clearing mode.
284 - *
285 - * @return string
286 - */
287 - protected static function get_advanced_cache_clear_prefix()
288 - {
289 - $pathname = self::get_pathname_base();
290 - $basename = basename( $pathname );
291 - $prefix = $basename . '-artifact-';
292 -
293 - return $prefix;
294 - }
295 -
296 - /**
297 - * Returns an array of file and directory names found within
298 - * the given $pathname without '.' and '..' elements.
299 - *
300 - * @param string $pathname Pathname.
301 - *
302 - * @return array
303 - */
304 - protected static function get_dir_contents( $pathname )
305 - {
306 - return array_slice( scandir( $pathname ), 2 );
307 - }
308 -
309 - /**
310 - * Wipes directories which were created as part of the fast cache clearing
311 - * routine (which renames the current cache directory into a new one with
312 - * a custom-prefixed unique name).
313 - *
314 - * @return bool
315 - */
316 - public static function delete_advanced_cache_clear_artifacts()
317 - {
318 - // Don't go through these motions (called from the cachechecker) if advanced cache clear isn't even active.
319 - if ( ! self::advanced_cache_clear_enabled() ) {
320 - return false;
321 - }
322 -
323 - $dir = self::get_pathname_base();
324 - $prefix = self::get_advanced_cache_clear_prefix();
325 - $parent = dirname( $dir );
326 - $ok = false;
327 -
328 - // Returns the list of files without '.' and '..' elements.
329 - $files = self::get_dir_contents( $parent );
330 - if ( is_array( $files ) && ! empty( $files ) ) {
331 - foreach ( $files as $file ) {
332 - $path = $parent . '/' . $file;
333 - $prefixed = ( false !== strpos( $path, $prefix ) );
334 - // Removing only our own (prefixed) directories...
335 - if ( is_dir( $path ) && $prefixed ) {
336 - $ok = self::rmdir( $path );
337 - }
338 - }
339 - }
340 -
341 - return $ok;
342 - }
343 -
344 - /**
345 - * Returns the cache directory pathname used.
346 - * Done as a function so we canSlightly different
347 - * if multisite is used and `autoptimize_separate_blog_caches` filter
348 - * is used.
349 - *
350 - * @return string
351 - */
352 - public static function get_pathname()
353 - {
354 - $pathname = self::get_pathname_base();
355 -
356 - if ( is_multisite() && apply_filters( 'autoptimize_separate_blog_caches', true ) ) {
357 - $blog_id = get_current_blog_id();
358 - $pathname .= $blog_id . '/';
359 - }
360 -
361 - return $pathname;
362 - }
363 -
364 - /**
365 - * Returns the base path of our cache directory.
366 - *
367 - * @return string
368 - */
369 - protected static function get_pathname_base()
370 - {
371 - $pathname = WP_CONTENT_DIR . AUTOPTIMIZE_CACHE_CHILD_DIR;
372 -
373 - return $pathname;
374 - }
375 -
376 - /**
377 - * Deletes everything from the cache directories.
378 - *
379 - * @param bool $propagate Whether to trigger additional actions when cache is purged.
380 - *
381 - * @return bool
382 - */
383 - public static function clearall( $propagate = true )
384 - {
385 - if ( ! self::cacheavail() ) {
386 - return false;
387 - }
388 -
389 - // TODO/FIXME: If cache is big, switch to advanced/new cache clearing automatically?
390 - if ( self::advanced_cache_clear_enabled() ) {
391 - self::clear_cache_via_rename();
392 - } else {
393 - self::clear_cache_classic();
394 - }
395 -
396 - // Remove 404 handler if required.
397 - if ( self::do_fallback() ) {
398 - $_fallback_php = trailingslashit( WP_CONTENT_DIR ) . 'autoptimize_404_handler.php';
399 - @unlink( $_fallback_php ); // @codingStandardsIgnoreLine
400 - }
401 -
402 - // Remove the transient so it gets regenerated...
403 - delete_transient( 'autoptimize_stats' );
404 -
405 - // Cache was just purged, clear page cache and allow others to hook into our purging...
406 - if ( true === $propagate ) {
407 - if ( ! function_exists( 'autoptimize_do_cachepurged_action' ) ) {
408 - function autoptimize_do_cachepurged_action() {
409 - do_action( 'autoptimize_action_cachepurged' );
410 - }
411 - }
412 - add_action( 'shutdown', 'autoptimize_do_cachepurged_action', 11 );
413 - add_action( 'autoptimize_action_cachepurged', array( 'autoptimizeCache', 'flushPageCache' ), 10, 0 );
414 - }
415 -
416 - // Warm cache (part of speedupper)!
417 - if ( apply_filters( 'autoptimize_filter_speedupper', true ) && false == get_transient( 'autoptimize_cache_warmer_protector' ) ) {
418 - set_transient( 'autoptimize_cache_warmer_protector', 'I shall not warm cache for another 10 minutes.', 60 * 10 );
419 - $url = site_url() . '/?ao_speedup_cachebuster=' . rand( 1, 100000 );
420 - $url = apply_filters( 'autoptimize_filter_cache_warmer_url', $url );
421 - $cache = @wp_remote_get( $url ); // @codingStandardsIgnoreLine
422 - unset( $cache );
423 - }
424 -
425 - return true;
426 - }
427 -
428 - /**
429 - * Wrapper for clearall but with false param
430 - * to ensure the event is not propagated to others
431 - * through our own hooks (to avoid infinite loops).
432 - *
433 - * @return bool
434 - */
435 - public static function clearall_actionless()
436 - {
437 - return self::clearall( false );
438 - }
439 -
440 - /**
441 - * Returns the contents of our cache dirs.
442 - *
443 - * @return array
444 - */
445 - protected static function get_cache_contents()
446 - {
447 - $contents = array();
448 -
449 - foreach ( array( '', 'js', 'css' ) as $dir ) {
450 - $contents[ $dir ] = scandir( AUTOPTIMIZE_CACHE_DIR . $dir );
451 - }
452 -
453 - return $contents;
454 - }
455 -
456 - /**
457 - * Returns stats about cached contents.
458 - *
459 - * @return array
460 - */
461 - public static function stats()
462 - {
463 - $stats = get_transient( 'autoptimize_stats' );
464 -
465 - // If no transient, do the actual scan!
466 - if ( ! is_array( $stats ) ) {
467 - if ( ! self::cacheavail() ) {
468 - return 0;
469 - }
470 - $stats = self::stats_scan();
471 - $count = $stats[0];
472 - if ( $count > 100 ) {
473 - // Store results in transient.
474 - set_transient(
475 - 'autoptimize_stats',
476 - $stats,
477 - apply_filters( 'autoptimize_filter_cache_statsexpiry', HOUR_IN_SECONDS )
478 - );
479 - }
480 - }
481 -
482 - return $stats;
483 - }
484 -
485 - /**
486 - * Performs a scan of cache directory contents and returns an array
487 - * with 3 values: count, size, timestamp.
488 - * count = total number of found files
489 - * size = total filesize (in bytes) of found files
490 - * timestamp = unix timestamp when the scan was last performed/finished.
491 - *
492 - * @return array
493 - */
494 - protected static function stats_scan()
495 - {
496 - $count = 0;
497 - $size = 0;
498 -
499 - // Scan everything in our cache directories.
500 - foreach ( self::get_cache_contents() as $name => $files ) {
501 - $dir = rtrim( AUTOPTIMIZE_CACHE_DIR . $name, '/' ) . '/';
502 - foreach ( $files as $file ) {
503 - if ( self::is_valid_cache_file( $dir, $file ) ) {
504 - if ( AUTOPTIMIZE_CACHE_NOGZIP &&
505 - (
506 - false !== strpos( $file, '.js' ) ||
507 - false !== strpos( $file, '.css' ) ||
508 - false !== strpos( $file, '.img' ) ||
509 - false !== strpos( $file, '.txt' )
510 - )
511 - ) {
512 - // Web server is gzipping, we count .js|.css|.img|.txt files.
513 - $count++;
514 - } elseif ( ! AUTOPTIMIZE_CACHE_NOGZIP && false !== strpos( $file, '.none' ) ) {
515 - // We are gzipping ourselves via php, counting only .none files.
516 - $count++;
517 - }
518 - $size += filesize( $dir . $file );
519 - }
520 - }
521 - }
522 -
523 - $stats = array( $count, $size, time() );
524 -
525 - return $stats;
526 - }
527 -
528 - /**
529 - * Ensures the cache directory exists, is writeable and contains the
530 - * required .htaccess files.
531 - * Returns false in case it fails to ensure any of those things.
532 - *
533 - * @return bool
534 - */
535 - public static function cacheavail()
536 - {
537 - // readonly FS explicitly OK'ed by dev, let's assume the cache dirs are there!
538 - if ( defined( 'AUTOPTIMIZE_CACHE_READONLY' ) ) {
539 - return true;
540 - }
541 -
542 - if ( false === autoptimizeCache::check_and_create_dirs() ) {
543 - return false;
544 - }
545 -
546 - // Using .htaccess inside our cache folder to overrule wp-super-cache.
547 - $htaccess = AUTOPTIMIZE_CACHE_DIR . '/.htaccess';
548 - if ( ! is_file( $htaccess ) ) {
549 - /**
550 - * Create `wp-content/AO_htaccess_tmpl` file with
551 - * whatever htaccess rules you might need
552 - * if you want to override default AO htaccess
553 - */
554 - $htaccess_tmpl = WP_CONTENT_DIR . '/AO_htaccess_tmpl';
555 - if ( is_file( $htaccess_tmpl ) ) {
556 - $content = file_get_contents( $htaccess_tmpl );
557 - } elseif ( is_multisite() || ! AUTOPTIMIZE_CACHE_NOGZIP ) {
558 - $content = '<IfModule mod_expires.c>
559 - ExpiresActive On
560 - ExpiresByType text/css A30672000
561 - ExpiresByType text/javascript A30672000
562 - ExpiresByType application/javascript A30672000
563 -</IfModule>
564 -<IfModule mod_headers.c>
565 - Header append Cache-Control "public, immutable"
566 -</IfModule>
567 -<IfModule mod_deflate.c>
568 - <FilesMatch "\.(js|css)$">
569 - SetOutputFilter DEFLATE
570 - </FilesMatch>
571 -</IfModule>
572 -<IfModule mod_authz_core.c>
573 - <Files *.php>
574 - Require all granted
575 - </Files>
576 -</IfModule>
577 -<IfModule !mod_authz_core.c>
578 - <Files *.php>
579 - Order allow,deny
580 - Allow from all
581 - </Files>
582 -</IfModule>';
583 - } else {
584 - $content = '<IfModule mod_expires.c>
585 - ExpiresActive On
586 - ExpiresByType text/css A30672000
587 - ExpiresByType text/javascript A30672000
588 - ExpiresByType application/javascript A30672000
589 -</IfModule>
590 -<IfModule mod_headers.c>
591 - Header append Cache-Control "public, immutable"
592 -</IfModule>
593 -<IfModule mod_deflate.c>
594 - <FilesMatch "\.(js|css)$">
595 - SetOutputFilter DEFLATE
596 - </FilesMatch>
597 -</IfModule>
598 -<IfModule mod_authz_core.c>
599 - <Files *.php>
600 - Require all denied
601 - </Files>
602 -</IfModule>
603 -<IfModule !mod_authz_core.c>
604 - <Files *.php>
605 - Order deny,allow
606 - Deny from all
607 - </Files>
608 -</IfModule>';
609 - }
610 -
611 - if ( self::do_fallback() === true ) {
612 - $content .= "\nErrorDocument 404 " . trailingslashit( parse_url( content_url(), PHP_URL_PATH ) ) . 'autoptimize_404_handler.php';
613 - }
614 - @file_put_contents( $htaccess, $content ); // @codingStandardsIgnoreLine
615 - }
616 -
617 - if ( self::do_fallback() ) {
618 - self::check_fallback_php();
619 - }
620 -
621 - // All OK!
622 - return true;
623 - }
624 -
625 - /**
626 - * Checks if fallback-php file exists and create it if not.
627 - *
628 - * Return bool
629 - */
630 - public static function check_fallback_php() {
631 - $_fallback_filename = 'autoptimize_404_handler.php';
632 - $_fallback_php = trailingslashit( WP_CONTENT_DIR ) . $_fallback_filename;
633 - $_fallback_status = true;
634 -
635 - if ( ! file_exists( $_fallback_php ) ) {
636 - $_fallback_php_contents = file_get_contents( AUTOPTIMIZE_PLUGIN_DIR . 'config/' . $_fallback_filename );
637 - $_fallback_php_contents = str_replace( '<?php exit;', '<?php', $_fallback_php_contents );
638 - $_fallback_php_contents = str_replace( '<!--ao-cache-dir-->', AUTOPTIMIZE_CACHE_DIR, $_fallback_php_contents );
639 - if ( apply_filters( 'autoptimize_filter_cache_fallback_log_errors', false ) ) {
640 - $_fallback_php_contents = str_replace( '// error_log', 'error_log', $_fallback_php_contents );
641 - }
642 - $_fallback_status = file_put_contents( $_fallback_php, $_fallback_php_contents );
643 - }
644 -
645 - return $_fallback_status;
646 - }
647 -
648 - /**
649 - * Tells if AO should try to avoid 404's by creating fallback filesize
650 - * and create a php 404 handler and tell .htaccess to redirect to said handler
651 - * and hook into WordPress to redirect 404 to said handler as well. NGINX users
652 - * are smart enough to get this working, no? ;-)
653 - *
654 - * Return bool
655 - */
656 - public static function do_fallback() {
657 - static $_do_fallback = null;
658 -
659 - if ( null === $_do_fallback ) {
660 - $_do_fallback = (bool) apply_filters( 'autoptimize_filter_cache_do_fallback', autoptimizeOptionWrapper::get_option( 'autoptimize_cache_fallback', '1' ) );
661 - }
662 -
663 - return $_do_fallback;
664 - }
665 -
666 - /**
667 - * Hooks into template_redirect, will act on 404-ing requests for
668 - * Autoptimized files and redirects to the fallback CSS/ JS if available
669 - * and 410'ing ("Gone") if fallback not available.
670 - */
671 - public static function wordpress_notfound_fallback() {
672 - $original_request = strtok( $_SERVER['REQUEST_URI'], '?' );
673 - if ( strpos( $original_request, wp_basename( WP_CONTENT_DIR ) . AUTOPTIMIZE_CACHE_CHILD_DIR ) !== false && is_404() ) {
674 - // make sure this is not considered a 404.
675 - global $wp_query;
676 - $wp_query->is_404 = false;
677 -
678 - // set fallback path.
679 - $js_or_css = pathinfo( $original_request, PATHINFO_EXTENSION );
680 - $fallback_path = AUTOPTIMIZE_CACHE_DIR . $js_or_css . '/autoptimize_fallback.' . $js_or_css;
681 -
682 - // prepare for Shakeeb's Unused CSS files to be 404-handled as well.
683 - if ( strpos( $original_request, 'uucss/uucss-' ) !== false ) {
684 - $original_request = preg_replace( '/uucss\/uucss-[a-z0-9]{32}-/', 'css/', $original_request );
685 - }
686 -
687 - // set fallback URL.
688 - $fallback_target = preg_replace( '/(.*)_(?:[a-z0-9]{32})\.(js|css)$/', '${1}_fallback.${2}', $original_request );
689 -
690 - // redirect to fallback if possible.
691 - if ( $original_request !== $fallback_target && file_exists( $fallback_path ) ) {
692 - // redirect to fallback.
693 - wp_redirect( $fallback_target, 302 );
694 - } else {
695 - // return HTTP 410 (gone) reponse.
696 - status_header( 410 );
697 - }
698 - }
699 - }
700 -
701 - /**
702 - * Checks if cache dirs exist and create if not.
703 - * Returns false if not succesful.
704 - *
705 - * @return bool
706 - */
707 - public static function check_and_create_dirs() {
708 - if ( ! defined( 'AUTOPTIMIZE_CACHE_DIR' ) ) {
709 - // We didn't set a cache.
710 - return false;
711 - }
712 -
713 - foreach ( array( '', 'js', 'css' ) as $dir ) {
714 - if ( ! self::check_cache_dir( AUTOPTIMIZE_CACHE_DIR . $dir ) ) {
715 - return false;
716 - }
717 - }
718 - return true;
719 - }
720 -
721 - /**
722 - * Ensures the specified `$dir` exists and is writeable.
723 - * Returns false if that's not the case.
724 - *
725 - * @param string $dir Directory to check/create.
726 - *
727 - * @return bool
728 - */
729 - protected static function check_cache_dir( $dir )
730 - {
731 - // Try creating the dir if it doesn't exist.
732 - if ( ! file_exists( $dir ) ) {
733 - @mkdir( $dir, 0775, true ); // @codingStandardsIgnoreLine
734 - if ( ! file_exists( $dir ) ) {
735 - return false;
736 - }
737 - }
738 -
739 - // If we still cannot write, bail.
740 - if ( ! is_writable( $dir ) ) {
741 - return false;
742 - }
743 -
744 - // Create an index.html in there to avoid prying eyes!
745 - $idx_file = rtrim( $dir, '/\\' ) . '/index.html';
746 - if ( ! is_file( $idx_file ) ) {
747 - @file_put_contents( $idx_file, '<html><head><meta name="robots" content="noindex, nofollow"></head><body>Generated by <a href="http://wordpress.org/extend/plugins/autoptimize/" rel="nofollow">Autoptimize</a></body></html>' ); // @codingStandardsIgnoreLine
748 - }
749 -
750 - return true;
751 - }
752 -
753 - /**
754 - * Flushes as many page cache plugin's caches as possible.
755 - *
756 - * @return void
757 - */
758 - // @codingStandardsIgnoreStart
759 - public static function flushPageCache()
760 - {
761 - if ( function_exists( 'wp_cache_clear_cache' ) ) {
762 - if ( is_multisite() ) {
763 - $blog_id = get_current_blog_id();
764 - wp_cache_clear_cache( $blog_id );
765 - } else {
766 - wp_cache_clear_cache();
767 - }
768 - } elseif ( has_action( 'cachify_flush_cache' ) ) {
769 - do_action( 'cachify_flush_cache' );
770 - } elseif ( function_exists( 'w3tc_pgcache_flush' ) ) {
771 - w3tc_pgcache_flush();
772 - } elseif ( function_exists( 'wp_fast_cache_bulk_delete_all' ) ) {
773 - wp_fast_cache_bulk_delete_all();
774 - } elseif ( function_exists( 'rapidcache_clear_cache' ) ) {
775 - rapidcache_clear_cache();
776 - } elseif ( class_exists( 'Swift_Performance_Cache' ) ) {
777 - Swift_Performance_Cache::clear_all_cache();
778 - } elseif ( class_exists( 'WpFastestCache' ) ) {
779 - $wpfc = new WpFastestCache();
780 - $wpfc->deleteCache();
781 - } elseif ( class_exists( 'c_ws_plugin__qcache_purging_routines' ) ) {
782 - c_ws_plugin__qcache_purging_routines::purge_cache_dir(); // quick cache
783 - } elseif ( class_exists( 'zencache' ) ) {
784 - zencache::clear();
785 - } elseif ( class_exists( 'comet_cache' ) ) {
786 - comet_cache::clear();
787 - } elseif ( class_exists( 'WpeCommon' ) ) {
788 - // WPEngine cache purge/flush methods to call by default
789 - $wpe_methods = array(
790 - 'purge_varnish_cache',
791 - );
792 -
793 - // More agressive clear/flush/purge behind a filter
794 - if ( apply_filters( 'autoptimize_flush_wpengine_aggressive', false ) ) {
795 - $wpe_methods = array_merge( $wpe_methods, array( 'purge_memcached', 'clear_maxcdn_cache' ) );
796 - }
797 -
798 - // Filtering the entire list of WpeCommon methods to be called (for advanced usage + easier testing)
799 - $wpe_methods = apply_filters( 'autoptimize_flush_wpengine_methods', $wpe_methods );
800 -
801 - foreach ( $wpe_methods as $wpe_method ) {
802 - if ( method_exists( 'WpeCommon', $wpe_method ) ) {
803 - WpeCommon::$wpe_method();
804 - }
805 - }
806 - } elseif ( function_exists( 'sg_cachepress_purge_cache' ) ) {
807 - sg_cachepress_purge_cache();
808 - } elseif ( array_key_exists( 'KINSTA_CACHE_ZONE', $_SERVER ) ) {
809 - $_kinsta_clear_cache_url = 'https://localhost/kinsta-clear-cache-all';
810 - $_kinsta_response = wp_remote_get(
811 - $_kinsta_clear_cache_url,
812 - array(
813 - 'sslverify' => false,
814 - 'timeout' => 5,
815 - )
816 - );
817 - } elseif ( defined('NGINX_HELPER_BASENAME') ) {
818 - do_action( 'rt_nginx_helper_purge_all' );
819 - } elseif ( file_exists( WP_CONTENT_DIR . '/wp-cache-config.php' ) && function_exists( 'prune_super_cache' ) ) {
820 - // fallback for WP-Super-Cache
821 - global $cache_path;
822 - if ( is_multisite() ) {
823 - $blog_id = get_current_blog_id();
824 - prune_super_cache( get_supercache_dir( $blog_id ), true );
825 - prune_super_cache( $cache_path . 'blogs/', true );
826 - } else {
827 - prune_super_cache( $cache_path . 'supercache/', true );
828 - prune_super_cache( $cache_path, true );
829 - }
830 - }
831 - }
832 - // @codingStandardsIgnoreEnd
108 + //Count cached info
109 + $count = 0;
110 + $scan = scandir(AUTOPTIMIZE_CACHE_DIR);
111 + foreach($scan as $file)
112 + {
113 + if(!in_array($file,array('.','..')) && strpos($file,'autoptimize') !== false)
114 + {
115 + if(is_file(AUTOPTIMIZE_CACHE_DIR.$file))
116 + {
117 + if(AUTOPTIMIZE_CACHE_NOGZIP && (strpos($file,'.js') !== false || strpos($file,'.css') !== false))
118 + {
119 + $count++;
120 + }elseif(!AUTOPTIMIZE_CACHE_NOGZIP && strpos($file,'.none') !== false){
121 + $count++;
122 + }/*else{
123 + //Tricky one... it was a dir or a gzip/deflate file
124 + }*/
125 + }
126 + }
127 + }
128 +
129 + //Tell the number of instances
130 + return $count;
131 + }
132 +
133 + static function cacheavail()
134 + {
135 + if(!defined('AUTOPTIMIZE_CACHE_DIR'))
136 + {
137 + //We didn't set a cache
138 + return false;
139 + }
140 +
141 + //Check for existence
142 + if(!file_exists(AUTOPTIMIZE_CACHE_DIR))
143 + {
144 + @mkdir(AUTOPTIMIZE_CACHE_DIR,0775,true);
145 + if(!file_exists(AUTOPTIMIZE_CACHE_DIR))
146 + {
147 + //Where should we cache?
148 + return false;
149 + }
150 + }
151 +
152 + if(!is_writable(AUTOPTIMIZE_CACHE_DIR))
153 + {
154 + //How are we supposed to write?
155 + return false;
156 + }
157 +
158 + //All OK
159 + return true;
160 + }
833 161 }