PluginProbe
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance / 3.2.9
WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance v3.2.9
4.7.0 4.6.1 4.6.0 4.5.5 4.5.4 4.5.3 4.5.2 3.2.20 3.2.21 3.2.22 3.2.3 3.2.5 3.2.6 3.2.7 3.2.9 3.3.0 3.3.1 3.3.2 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.7.0 3.7.1 All 111 releases
wp-optimize / minify / class-wp-optimize-minify-cache-functions.php

class-wp-optimize-minify-cache-functions.php in WP-Optimize – Cache, Compress images, Minify & Clean database to boost page speed & performance 3.2.9, at minify/class-wp-optimize-minify-cache-functions.php

496 lines 15.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if (!defined('ABSPATH')) die('No direct access allowed');
3
4 if (!defined('WP_OPTIMIZE_MINIFY_DIR')) {
5 die('No direct access.');
6 }
7
8 if (!function_exists('wpo_delete_files')) {
9 include WPO_PLUGIN_MAIN_PATH.'cache/file-based-page-cache-functions.php';
10 }
11
12 class WP_Optimize_Minify_Cache_Functions {
13
14 /**
15 * Fix the permission bits on generated files
16 *
17 * @param String $file - full path to a file
18 */
19 public static function fix_permission_bits($file) {
20 if (function_exists('stat')) {
21 if ($stat = stat(dirname($file))) {
22 $perms = $stat['mode'] & 0007777;
23 chmod($file, $perms);
24 clearstatcache();
25 return true;
26 }
27 }
28
29 // Get permissions from parent directory
30 $perms = 0777;
31 if (function_exists('stat')) {
32 if ($stat = stat(dirname($file))) {
33 $perms = $stat['mode'] & 0007777;
34 }
35 }
36
37 if (file_exists($file)) {
38 if (($perms & ~umask() != $perms)) {
39 $folder_parts = explode('/', substr($file, strlen(dirname($file)) + 1));
40 for ($i = 1, $c = count($folder_parts); $i <= $c; $i++) {
41 chmod(dirname($file) . '/' . implode('/', array_slice($folder_parts, 0, $i)), $perms);
42 }
43 }
44 }
45 return true;
46 }
47
48 /**
49 * Get cache directories and urls
50 *
51 * @return Array
52 */
53 public static function cache_path() {
54 // get latest time stamp
55 $cache_time = wp_optimize_minify_config()->get('last-cache-update');
56
57 $cache_dir_url = WPO_CACHE_MIN_FILES_URL . "/$cache_time/assets";
58 $tmp_dir = WPO_CACHE_MIN_FILES_DIR . "/tmp";
59 $header_dir = WPO_CACHE_MIN_FILES_DIR . "/$cache_time/header";
60 $cache_dir = WPO_CACHE_MIN_FILES_DIR . "/$cache_time/assets";
61
62 // Create directories
63 $dirs = array($cache_dir, $tmp_dir, $header_dir);
64 foreach ($dirs as $target) {
65 $enabled = wp_optimize_minify_config()->get('enabled');
66 if (false === $enabled) break;
67
68 if (!is_dir($target) && !wp_mkdir_p($target)) {
69 error_log('WP_Optimize_Minify_Cache_Functions::cache_path(): The folder "'.$target.'" could not be created.');
70 }
71 }
72 return array(
73 'tmpdir' => $tmp_dir,
74 'cachedir' => $cache_dir,
75 'cachedirurl' => $cache_dir_url,
76 'headerdir' => $header_dir
77 );
78 }
79
80 /**
81 * Increment file names
82 */
83 public static function cache_increment() {
84 $stamp = time();
85 wp_optimize_minify_config()->update(array(
86 'last-cache-update' => $stamp
87 ));
88 return $stamp;
89 }
90
91 /**
92 * Reset the cache (Increment + purge temp files)
93 */
94 public static function reset() {
95 self::cache_increment();
96 self::purge_temp_files();
97 }
98
99 /**
100 * Will delete temporary intermediate stuff but leave final css/js alone for compatibility
101 *
102 * @return Array
103 */
104 public static function purge_temp_files() {
105 // get cache directories and urls
106 $cache_path = self::cache_path();
107 $tmp_dir = $cache_path['tmpdir'];
108 $header_dir = $cache_path['headerdir'];
109
110 // delete temporary directories only
111 if (is_dir($tmp_dir)) {
112 wpo_delete_files($tmp_dir, true);
113 }
114 if (is_dir($header_dir)) {
115 wpo_delete_files($header_dir, true);
116 }
117
118 /**
119 * Action triggered after purging temporary files
120 */
121 do_action('wpo_min_after_purge_temp_files');
122 return array(
123 'tmpdir' => $tmp_dir,
124 'headerdir' => $header_dir,
125 );
126 }
127
128 /**
129 * Purge supported hosting and plugins
130 *
131 * @return string
132 */
133 public static function purge_others() {
134 /**
135 * Action triggered before purging other plugins cache
136 */
137 do_action('wpo_min_before_purge_others');
138
139 // WordPress default cache
140 if (function_exists('wp_cache_flush')) {
141 wp_cache_flush();
142 }
143
144 // Purge WP-Optimize
145 WP_Optimize()->get_page_cache()->purge();
146
147 // When plugins have a simple method, add them to the array ('Plugin Name' => 'method_name')
148 $others = array(
149 'WP Super Cache' => 'wp_cache_clear_cache',
150 'W3 Total Cache' => 'w3tc_pgcache_flush',
151 'WP Fastest Cache' => 'wpfc_clear_all_cache',
152 'WP Rocket' => 'rocket_clean_domain',
153 'Cachify' => 'cachify_flush_cache',
154 'Comet Cache' => array('comet_cache', 'clear'),
155 'SG Optimizer' => 'sg_cachepress_purge_cache',
156 'Pantheon' => 'pantheon_wp_clear_edge_all',
157 'Zen Cache' => array('zencache', 'clear'),
158 'Breeze' => array('Breeze_PurgeCache', 'breeze_cache_flush'),
159 'Swift Performance' => array('Swift_Performance_Cache', 'clear_all_cache'),
160 );
161
162 foreach ($others as $plugin => $method) {
163 if (is_callable($method)) {
164 call_user_func($method);
165 return sprintf(__('All caches from %s have also been purged.', 'wp-optimize'), '<strong>'.$plugin.'</strong>');
166 }
167 }
168
169 // Purge LiteSpeed Cache
170 if (is_callable(array('LiteSpeed_Cache_Tags', 'add_purge_tag'))) {
171 LiteSpeed_Cache_Tags::add_purge_tag('*');
172 return sprintf(__('All caches from %s have also been purged.', 'wp-optimize'), '<strong>LiteSpeed Cache</strong>');
173 }
174
175 // Purge Hyper Cache
176 if (class_exists('HyperCache')) {
177 do_action('autoptimize_action_cachepurged');
178 return sprintf(__('All caches from %s have also been purged.', 'wp-optimize'), '<strong>Hyper Cache</strong>');
179 }
180
181 // Purge Godaddy Managed WordPress Hosting (Varnish + APC)
182 if (class_exists('WPaaS\Plugin')) {
183 self::godaddy_request('BAN');
184 return sprintf(__('A cache purge request has been sent to %s. Please note that it may not work every time, due to cache rate limiting by your host.', 'wp-optimize'), '<strong>Go Daddy Varnish</strong>');
185 }
186
187 // purge cache enabler
188 if (has_action('ce_clear_cache')) {
189 do_action('ce_clear_cache');
190 return sprintf(__('All caches from %s have also been purged.', 'wp-optimize'), '<strong>Cache Enabler</strong>');
191 }
192
193 // Purge WP Engine
194 if (class_exists("WpeCommon")) {
195 if (method_exists('WpeCommon', 'purge_memcached')) {
196 WpeCommon::purge_memcached();
197 }
198 if (method_exists('WpeCommon', 'clear_maxcdn_cache')) {
199 WpeCommon::clear_maxcdn_cache();
200 }
201 if (method_exists('WpeCommon', 'purge_varnish_cache')) {
202 WpeCommon::purge_varnish_cache();
203 }
204
205 if (method_exists('WpeCommon', 'purge_memcached') || method_exists('WpeCommon', 'clear_maxcdn_cache') || method_exists('WpeCommon', 'purge_varnish_cache')) {
206 return sprintf(__('A cache purge request has been sent to %s. Please note that it may not work every time, due to cache rate limiting by your host.', 'wp-optimize'), '<strong>WP Engine</strong>');
207 }
208 }
209
210 // Purge Kinsta
211 global $kinsta_cache;
212 if (isset($kinsta_cache) && class_exists('\\Kinsta\\CDN_Enabler')) {
213 if (!empty($kinsta_cache->kinsta_cache_purge) && is_callable(array($kinsta_cache->kinsta_cache_purge, 'purge_complete_caches'))) {
214 $kinsta_cache->kinsta_cache_purge->purge_complete_caches();
215 return sprintf(__('A cache purge request was also sent to %s', 'wp-optimize'), '<strong>Kinsta</strong>');
216 }
217 }
218
219 // Purge Pagely
220 if (class_exists('PagelyCachePurge')) {
221 $purge_pagely = new PagelyCachePurge();
222 if (is_callable(array($purge_pagely, 'purgeAll'))) {
223 $purge_pagely->purgeAll();
224 return sprintf(__('A cache purge request was also sent to %s', 'wp-optimize'), '<strong>Pagely</strong>');
225 }
226 }
227
228 // Purge Pressidum
229 if (defined('WP_NINUKIS_WP_NAME') && class_exists('Ninukis_Plugin') && is_callable(array('Ninukis_Plugin', 'get_instance'))) {
230 $purge_pressidum = Ninukis_Plugin::get_instance();
231 if (is_callable(array($purge_pressidum, 'purgeAllCaches'))) {
232 $purge_pressidum->purgeAllCaches();
233 return sprintf(__('A cache purge request was also sent to %s', 'wp-optimize'), '<strong>Pressidium</strong>');
234 }
235 }
236
237 // Purge Savvii
238 if (defined('\Savvii\CacheFlusherPlugin::NAME_DOMAINFLUSH_NOW')) {
239 $purge_savvii = new \Savvii\CacheFlusherPlugin(); // phpcs:ignore PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound
240 if (is_callable(array($purge_savvii, 'domainflush'))) {
241 $purge_savvii->domainflush();
242 return sprintf(__('A cache purge request was also sent to %s', 'wp-optimize'), '<strong>Savvii</strong>');
243 }
244 }
245
246 /**
247 * Action triggered when purging other plugins cache, and nothing was triggered
248 */
249 do_action('wpo_min_after_purge_others');
250
251 }
252
253 /**
254 * Purge all public files on uninstallation
255 * This will break cached pages that ref minified JS/CSS
256 *
257 * @return Boolean
258 */
259 public static function purge() {
260 $log = '';
261 if (is_dir(WPO_CACHE_MIN_FILES_DIR)) {
262 if (wpo_delete_files(WPO_CACHE_MIN_FILES_DIR, true)) {
263 $log = "[Minify] files and folders are deleted recursively";
264 } else {
265 $log = "[Minify] recursive files and folders deletion unsuccessful";
266 }
267 if (wp_optimize_minify_config()->get('debug')) {
268 error_log($log);
269 }
270 }
271 return true;
272 }
273
274 /**
275 * Purge cache files older than 30 days
276 *
277 * @return array
278 */
279 public static function purge_old() {
280 if (!class_exists('WP_Optimize_Minify_Config')) {
281 include_once WPO_PLUGIN_MAIN_PATH . '/minify/class-wp-optimize-minify-config.php';
282 }
283 $cache_time = wp_optimize_minify_config()->get('last-cache-update');
284 $cache_lifespan = wp_optimize_minify_config()->get('cache_lifespan');
285
286 /**
287 * Minify cache lifespan
288 *
289 * @param int The minify cache expiry timestamp
290 */
291 $expires = apply_filters('wp_optimize_minify_cache_expiry_time', time() - 86400 * $cache_lifespan);
292 $log = array();
293
294 // get all directories that are a direct child of current directory
295 if (is_dir(WPO_CACHE_MIN_FILES_DIR) && is_writable(dirname(WPO_CACHE_MIN_FILES_DIR))) {
296 if ($handle = opendir(WPO_CACHE_MIN_FILES_DIR)) {
297 while (false !== ($d = readdir($handle))) {
298 if (strcmp($d, '.')==0 || strcmp($d, '..')==0) {
299 continue;
300 }
301 $log[] = "cache expiration time - $expires";
302 $log[] = "checking if cache has expired - $d";
303 if ($d != $cache_time && (is_numeric($d) && $d <= $expires)) {
304 $dir = WPO_CACHE_MIN_FILES_DIR.'/'.$d;
305 if (is_dir($dir)) {
306 $log[] = "deleting cache in $dir";
307 if (wpo_delete_files($dir, true)) {
308 $log[] = "files and folders are deleted recursively - $dir";
309 } else {
310 $log[] = "recursive files and folders deletion unsuccessful - $dir";
311 }
312 if (file_exists($dir)) {
313 if (rmdir($dir)) {
314 $log[] = "folder deleted successfully - $dir";
315 } else {
316 $log[] = "folder deletion unsuccessful - $dir";
317 }
318 }
319 }
320 }
321 }
322 closedir($handle);
323 }
324 }
325 if (wp_optimize_minify_config()->get('debug')) {
326 foreach ($log as $message) {
327 error_log($message);
328 }
329 }
330
331 return $log;
332 }
333
334 /**
335 * Get transients from the disk
336 *
337 * @return String|Boolean
338 */
339 public static function get_transient($key) {
340 $cache_path = self::cache_path();
341 $tmp_dir = $cache_path['tmpdir'];
342 $f = $tmp_dir.'/'.$key.'.transient';
343 clearstatcache();
344 if (file_exists($f)) {
345 return file_get_contents($f);
346 } else {
347 return false;
348 }
349 }
350
351 /**
352 * Set cache on disk
353 *
354 * @param String $key
355 * @param Mixed $code
356 *
357 * @return Boolean
358 */
359 public static function set_transient($key, $code) {
360 if (is_null($code) || empty($code)) {
361 return false;
362 }
363 $cache_path = self::cache_path();
364 $tmp_dir = $cache_path['tmpdir'];
365 $f = $tmp_dir.'/'.$key.'.transient';
366 file_put_contents($f, $code);
367 self::fix_permission_bits($f);
368 return true;
369 }
370
371 /**
372 * Get the cache size and count
373 *
374 * @param string $folder
375 * @return String
376 */
377 public static function get_cachestats($folder) {
378 clearstatcache();
379 if (is_dir($folder)) {
380 $dir = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($folder, FilesystemIterator::SKIP_DOTS));
381 $size = 0;
382 $file_count = 0;
383 foreach ($dir as $file) {
384 $size += $file->getSize();
385 $file_count++;
386 }
387 return WP_Optimize()->format_size($size) . ' ('.$file_count.' files)';
388 } else {
389 return sprintf(__('Error: %s is not a directory!', 'wp-optimize'), $folder);
390 }
391 }
392
393 /**
394 * Purge GoDaddy Managed WordPress Hosting (Varnish)
395 *
396 * Source: https://github.com/wp-media/wp-rocket/blob/master/inc/3rd-party/hosting/godaddy.php
397 *
398 * @param String $method
399 * @param String|Null $url
400 */
401 public static function godaddy_request($method, $url = null) {
402 $url = empty($url) ? home_url() : $url;
403 $host = parse_url($url, PHP_URL_HOST);
404 $url = set_url_scheme(str_replace($host, WPaas\Plugin::vip(), $url), 'http'); // phpcs:ignore PHPCompatibility.LanguageConstructs.NewLanguageConstructs.t_ns_separatorFound
405 wp_cache_flush();
406 update_option('gd_system_last_cache_flush', time()); // purge apc
407 wp_remote_request(esc_url_raw($url), array('method' => $method, 'blocking' => false, 'headers' => array('Host' => $host)));
408 }
409
410 /**
411 * List all cache files
412 *
413 * @param integer $stamp A timestamp
414 * @param boolean $use_cache If true, do not use transient value
415 * @return array
416 */
417 public static function get_cached_files($stamp = 0, $use_cache = true) {
418 if ($use_cache && $files = get_transient('wpo_minify_get_cached_files')) {
419 return $files;
420 }
421 $cache_path = self::cache_path();
422 $cache_dir = $cache_path['cachedir'];
423 $size = self::get_cachestats($cache_dir);
424 $total_size = self::get_cachestats(WPO_CACHE_MIN_FILES_DIR);
425 $o = wp_optimize_minify_config()->get();
426 $cache_time = (0 == $o['last-cache-update']) ? __('Never.', 'wp-optimize') : self::format_date_time($o['last-cache-update']);
427 $return = array(
428 'js' => array(),
429 'css' => array(),
430 'stamp' => $stamp,
431 'cachesize' => esc_html($size),
432 'total_cache_size' => esc_html($total_size),
433 'cacheTime' => $cache_time,
434 'cachePath' => $cache_path['cachedir']
435 );
436
437 // Inspect directory with opendir, since glob might not be available in some systems
438 clearstatcache();
439 if (is_dir($cache_dir.'/') && $handle = opendir($cache_dir.'/')) {
440 while (false !== ($file = readdir($handle))) {
441 $file = $cache_dir.'/'.$file;
442 $ext = pathinfo($file, PATHINFO_EXTENSION);
443 if (in_array($ext, array('js', 'css'))) {
444 $log = false;
445 if (file_exists($file.'.json')) {
446 $log = json_decode(file_get_contents($file.'.json'));
447 }
448 $min_css = substr($file, 0, -4).'.min.css';
449 $minjs = substr($file, 0, -3).'.min.js';
450 $file_name = basename($file);
451 $file_url = trailingslashit($cache_path['cachedirurl']).$file_name;
452 if ('css' == $ext && file_exists($min_css)) {
453 $file_name = basename($min_css);
454 }
455 if ('js' == $ext && file_exists($minjs)) {
456 $file_name = basename($minjs);
457 }
458 $file_size = WP_Optimize()->format_size(filesize($file));
459 $uid = hash('adler32', $file_name);
460 array_push($return[$ext], array('uid' => $uid, 'filename' => $file_name, 'file_url' => $file_url, 'log' => $log, 'fsize' => $file_size));
461 }
462 }
463 closedir($handle);
464 }
465 set_transient('wpo_minify_get_cached_files', $return, DAY_IN_SECONDS);
466 return $return;
467 }
468
469 /**
470 * Format a timestamp using WP's date_format and time_format
471 *
472 * @param integer $timestamp - The timestamp
473 * @return string
474 */
475 public static function format_date_time($timestamp) {
476 return WP_Optimize()->format_date_time($timestamp);
477 }
478
479 /**
480 * Format the log created when merging assets. Called via array_map
481 *
482 * @param array $files The files array, containing the 'log' object or array.
483 * @return array
484 */
485 public static function format_file_logs($files) {
486 $files['log'] = WP_Optimize()->include_template(
487 'minify/cached-file-log.php',
488 true,
489 array(
490 'log' => $files['log']
491 )
492 );
493 return $files;
494 }
495 }
496