<?php use WP_Rocket\Logger\Logger; use WP_Rocket\Engine\Cache\AdvancedCache; defined('ABSPATH') || exit; function rocket_generate_advanced_cache_file($advanced_cache = null) { if (!(bool) apply_filters('rocket_generate_advanced_cache_file', true)) { return false; } static $done = false; if (rocket_get_constant('WP_ROCKET_IS_TESTING', false)) { $done = false; } if ($done) { return false; } $done = true; if (is_null($advanced_cache)) { $container = apply_filters('rocket_container', null); $advanced_cache = $container->get('advanced_cache'); } return rocket_put_content(rocket_get_constant('WP_CONTENT_DIR') . '/advanced-cache.php', $advanced_cache->get_advanced_cache_content()); } function get_rocket_config_file() { $options = get_option(WP_ROCKET_SLUG); if (!$options) { return [[], '']; } $buffer = "<?php\n"; $buffer .= "defined( 'ABSPATH' ) || exit;\n\n"; $buffer .= '$rocket_cookie_hash = \'' . COOKIEHASH . "';\n"; $buffer .= '$rocket_logged_in_cookie = \'' . LOGGED_IN_COOKIE . "';\n"; if (apply_filters('rocket_common_cache_logged_users', false)) { $buffer .= '$rocket_common_cache_logged_users = 1;' . "\n"; } if (!empty($options['cache_webp'])) { $disable_webp_cache = apply_filters('rocket_disable_webp_cache', false); if ($disable_webp_cache) { $options['cache_webp'] = 0; } } $buffer .= '$rocket_cache_mobile_files_tablet = \'' . apply_filters('rocket_cache_mobile_files_tablet', 'desktop') . "';\n"; foreach ($options as $option => $value) { if ('cache_ssl' === $option) { if (1 !== (int) $value) { if (rocket_is_ssl_website()) { update_rocket_option('cache_ssl', 1); $value = 1; } } $buffer .= '$rocket_' . $option . ' = ' . (int) $value . ";\n"; } if ('cache_mobile' === $option || 'do_caching_mobile_files' === $option || 'cache_webp' === $option) { $buffer .= '$rocket_' . $option . ' = ' . (int) $value . ";\n"; } if ('secret_cache_key' === $option) { $buffer .= '$rocket_' . $option . ' = \'' . $value . "';\n"; } if ('cache_reject_uri' === $option) { $buffer .= '$rocket_' . $option . ' = \'' . get_rocket_cache_reject_uri() . "';\n"; } if ('cache_query_strings' === $option) { $buffer .= '$rocket_' . $option . ' = ' . call_user_func('var_export', get_rocket_cache_query_string(), true) . ";\n"; } if ('cache_reject_cookies' === $option) { $cookies = get_rocket_cache_reject_cookies(); if ($cookies && get_rocket_option('cache_logged_user')) { $logged_in_cookie = explode(COOKIEHASH, LOGGED_IN_COOKIE); $logged_in_cookie = array_map('preg_quote', $logged_in_cookie); $logged_in_cookie = implode('[^|]*', $logged_in_cookie); $cookies = preg_replace('/\\|' . $logged_in_cookie . '\\|/', '|', '|' . $cookies . '|'); $cookies = trim($cookies, '|'); } $buffer .= '$rocket_' . $option . ' = \'' . $cookies . "';\n"; } if ('cache_reject_ua' === $option) { $buffer .= '$rocket_' . $option . ' = \'' . get_rocket_cache_reject_ua() . "';\n"; } } $buffer .= '$rocket_cache_ignored_parameters = ' . call_user_func('var_export', rocket_get_ignored_parameters(), true) . ";\n"; $buffer .= '$rocket_cache_mandatory_cookies = ' . call_user_func('var_export', get_rocket_cache_mandatory_cookies(), true) . ";\n"; $buffer .= '$rocket_cache_dynamic_cookies = ' . call_user_func('var_export', get_rocket_cache_dynamic_cookies(), true) . ";\n"; if (apply_filters('rocket_url_no_dots', false)) { $buffer .= '$rocket_url_no_dots = 1;'; } $config_files_path = []; $urls = [rocket_get_home_url()]; $subdomains = get_rocket_i18n_subdomains(); if ($subdomains) { $urls = $subdomains; } foreach ($urls as $url) { $file = get_rocket_parse_url(untrailingslashit($url)); $file['path'] = !empty($file['path']) ? str_replace('/', '.', untrailingslashit($file['path'])) : ''; $config_files_path[] = WP_ROCKET_CONFIG_PATH . strtolower($file['host']) . $file['path'] . '.php'; } $config_files_path = apply_filters('rocket_config_files_path', $config_files_path); $buffer = apply_filters('rocket_config_file', $buffer, $config_files_path); $buffer = preg_replace('@array\\s+\\(@i', 'array(', $buffer); $buffer = preg_replace('@array\\(\\s+\\)@i', 'array()', $buffer); return [$config_files_path, $buffer]; } function rocket_generate_config_file() { list($config_files_path, $buffer) = get_rocket_config_file(); if (count($config_files_path)) { rocket_init_config_dir(); foreach ($config_files_path as $file) { rocket_put_content($file, $buffer); } } } function rocket_delete_config_file() { list($config_files_path) = get_rocket_config_file(); foreach ($config_files_path as $config_file) { rocket_direct_filesystem()->delete($config_file); } } function rocket_init_cache_dir() { global $is_apache; $filesystem = rocket_direct_filesystem(); if (!$filesystem->is_dir(WP_ROCKET_CACHE_PATH)) { rocket_mkdir_p(WP_ROCKET_CACHE_PATH); } if (!$filesystem->is_file(WP_ROCKET_CACHE_PATH . 'index.html')) { $filesystem->touch(WP_ROCKET_CACHE_PATH . 'index.html'); } if ($is_apache) { $htaccess_path = WP_ROCKET_CACHE_PATH . '.htaccess'; if (!$filesystem->is_file($htaccess_path)) { $filesystem->touch($htaccess_path); rocket_put_content($htaccess_path, "<IfModule mod_autoindex.c>\nOptions -Indexes\n</IfModule>"); } } if (!$filesystem->is_dir(WP_ROCKET_MINIFY_CACHE_PATH)) { rocket_mkdir_p(WP_ROCKET_MINIFY_CACHE_PATH); } if (!$filesystem->is_file(WP_ROCKET_MINIFY_CACHE_PATH . 'index.html')) { $filesystem->touch(WP_ROCKET_MINIFY_CACHE_PATH . 'index.html'); } if (!$filesystem->is_dir(WP_ROCKET_CACHE_BUSTING_PATH)) { rocket_mkdir_p(WP_ROCKET_CACHE_BUSTING_PATH); } if (!$filesystem->is_file(WP_ROCKET_CACHE_BUSTING_PATH . 'index.html')) { $filesystem->touch(WP_ROCKET_CACHE_BUSTING_PATH . 'index.html'); } if (!$filesystem->is_dir(WP_ROCKET_CRITICAL_CSS_PATH)) { rocket_mkdir_p(WP_ROCKET_CRITICAL_CSS_PATH); } if (!$filesystem->is_file(WP_ROCKET_CRITICAL_CSS_PATH . 'index.html')) { $filesystem->touch(WP_ROCKET_CRITICAL_CSS_PATH . 'index.html'); } } function rocket_init_config_dir() { $filesystem = rocket_direct_filesystem(); if (!$filesystem->is_dir(WP_ROCKET_CONFIG_PATH)) { rocket_mkdir_p(WP_ROCKET_CONFIG_PATH); } if (!$filesystem->is_file(WP_ROCKET_CONFIG_PATH . 'index.html')) { $filesystem->touch(WP_ROCKET_CONFIG_PATH . 'index.html'); } } function rocket_clean_minify($extensions = array('js', 'css')) { if (empty($extensions)) { return; } if (is_string($extensions)) { $extensions = (array) $extensions; } $min_cache_path = rocket_get_constant('WP_ROCKET_MINIFY_CACHE_PATH'); $min_path = $min_cache_path . get_current_blog_id() . '/'; $iterator = _rocket_get_cache_path_iterator($min_path); if (false === $iterator) { return; } $filesystem = rocket_direct_filesystem(); $min_path_regex = str_replace('/', '\\/', $min_path); foreach ($extensions as $ext) { do_action('before_rocket_clean_minify', $ext); try { $entries = new RegexIterator($iterator, "/{$min_path_regex}.*\\.{$ext}/"); } catch (Exception $e) { return; } foreach ($entries as $entry) { $filesystem->delete($entry->getPathname()); } do_action('after_rocket_clean_minify', $ext); } foreach ($iterator as $item) { if ($filesystem->is_dir($item)) { $filesystem->delete($item); } } try { $files = new FilesystemIterator("{$min_cache_path}3rd-party"); foreach ($files as $file) { if ($filesystem->is_file($file)) { $filesystem->delete($file); } } } catch (UnexpectedValueException $e) { return; } } function rocket_clean_cache_busting($extensions = array('js', 'css')) { $extensions = is_string($extensions) ? (array) $extensions : $extensions; $cache_busting_path = WP_ROCKET_CACHE_BUSTING_PATH . get_current_blog_id(); if (!rocket_direct_filesystem()->is_dir($cache_busting_path)) { rocket_mkdir_p($cache_busting_path); Logger::debug('No Cache Busting folder found.', ['mkdir cache busting folder', 'cache_busting_path' => $cache_busting_path]); return; } try { $dir = new RecursiveDirectoryIterator($cache_busting_path, FilesystemIterator::SKIP_DOTS); } catch (UnexpectedValueException $e) { return; } try { $iterator = new RecursiveIteratorIterator($dir, RecursiveIteratorIterator::CHILD_FIRST); } catch (Exception $e) { return; } foreach ($extensions as $ext) { do_action('before_rocket_clean_busting', $ext); try { $files = new RegexIterator($iterator, '#.*\\.' . $ext . '#', RegexIterator::GET_MATCH); foreach ($files as $file) { rocket_direct_filesystem()->delete($file[0]); } } catch (InvalidArgumentException $e) { return; } do_action('after_rocket_clean_cache_busting', $ext); } try { foreach ($iterator as $item) { if (rocket_direct_filesystem()->is_dir($item)) { rocket_direct_filesystem()->delete($item); } } } catch (UnexpectedValueException $e) { Logger::debug('Cache Busting folder structure contains a directory we cannot recurse into.', ['Full error', 'UnexpectedValueException' => $e->getMessage()]); } } function rocket_clean_files($urls, $filesystem = null) { $urls = (array) $urls; if (empty($urls)) { return; } $urls = array_filter($urls); if (empty($urls)) { return; } $url_no_dots = (bool) apply_filters('rocket_url_no_dots', false); $cache_path = _rocket_get_wp_rocket_cache_path(); if (empty($filesystem)) { $filesystem = rocket_direct_filesystem(); } do_action('before_rocket_clean_files', $urls); foreach ($urls as $url) { do_action('before_rocket_clean_file', $url); if ($url_no_dots) { $url = str_replace('.', '_', $url); } $parsed_url = get_rocket_parse_url($url); if (!empty($parsed_url['host'])) { foreach (_rocket_get_cache_dirs($parsed_url['host'], $cache_path) as $dir) { $entry = $dir . $parsed_url['path']; if (!$filesystem->exists($entry)) { continue; } if ($filesystem->is_dir($entry)) { rocket_rrmdir($entry, [], $filesystem); } else { $filesystem->delete($entry); } } } do_action('after_rocket_clean_file', $url); } do_action('after_rocket_clean_files', $urls); } function rocket_clean_home($lang = '') { $parse_url = get_rocket_parse_url(get_rocket_i18n_home_url($lang)); if (apply_filters('rocket_url_no_dots', false)) { $parse_url['host'] = str_replace('.', '_', $parse_url['host']); } $root = WP_ROCKET_CACHE_PATH . $parse_url['host'] . '*' . untrailingslashit($parse_url['path']); $root = apply_filters('rocket_clean_home_root', $root, $parse_url['host'], $parse_url['path']); do_action('before_rocket_clean_home', $root, $lang); $files = glob($root . '/{index,index-*}.{html,html_gzip}', GLOB_BRACE | GLOB_NOSORT); if ($files) { foreach ($files as $file) { rocket_direct_filesystem()->delete($file); } } $dirs = glob($root . '*/' . $GLOBALS['wp_rewrite']->pagination_base, GLOB_NOSORT); if ($dirs) { foreach ($dirs as $dir) { rocket_rrmdir($dir); } } $nginx_mobile_detect_files = glob($root . '/.mobile-active', GLOB_BRACE | GLOB_NOSORT); if ($nginx_mobile_detect_files) { foreach ($nginx_mobile_detect_files as $nginx_mobile_detect_file) { rocket_direct_filesystem()->delete($nginx_mobile_detect_file); } } $nowebp_detect_files = glob($root . '/.no-webp', GLOB_BRACE | GLOB_NOSORT); if ($nowebp_detect_files) { foreach ($nowebp_detect_files as $nowebp_detect_file) { rocket_direct_filesystem()->delete($nowebp_detect_file); } } do_action('after_rocket_clean_home', $root, $lang); } function rocket_clean_home_feeds() { $urls = []; $urls[] = get_feed_link(); $urls[] = get_feed_link('comments_'); $urls = apply_filters('rocket_clean_home_feeds', $urls); do_action('before_rocket_clean_home_feeds', $urls); rocket_clean_files($urls); do_action('after_rocket_clean_home_feeds', $urls); } function rocket_clean_domain($lang = '', $filesystem = null) { $urls = !$lang || is_object($lang) || is_array($lang) || is_int($lang) ? (array) get_rocket_i18n_uri() : (array) get_rocket_i18n_home_url($lang); $urls = (array) apply_filters('rocket_clean_domain_urls', $urls, $lang); $urls = array_filter($urls); if (empty($urls)) { return false; } $url_no_dots = (bool) apply_filters('rocket_url_no_dots', false); $cache_path = _rocket_get_wp_rocket_cache_path(); $dirs_to_preserve = get_rocket_i18n_to_preserve($lang, $cache_path); if (empty($filesystem)) { $filesystem = rocket_direct_filesystem(); } foreach ($urls as $url) { $parsed_url = get_rocket_parse_url($url); if ($url_no_dots) { $parsed_url['host'] = str_replace('.', '_', $parsed_url['host']); } $root = $cache_path . $parsed_url['host'] . $parsed_url['path']; do_action('before_rocket_clean_domain', $root, $lang, $url); foreach (_rocket_get_cache_dirs($parsed_url['host'], $cache_path) as $dir) { $entry = $dir . $parsed_url['path']; if (!$filesystem->exists($entry)) { continue; } if ($filesystem->is_dir($entry)) { rocket_rrmdir($entry, $dirs_to_preserve, $filesystem); } else { $filesystem->delete($entry); } } do_action('after_rocket_clean_domain', $root, $lang, $url); } return true; } function rocket_clean_term($term_id, $taxonomy_slug) { $purge_urls = []; $term = get_term_by('id', $term_id, $taxonomy_slug); $i18n_plugin = rocket_has_i18n(); if ('wpml' === $i18n_plugin && !rocket_is_plugin_active('woocommerce-multilingual/wpml-woocommerce.php')) { $lang = $GLOBALS['sitepress']->get_language_for_element($term_id, 'tax_' . $taxonomy_slug); } elseif ('polylang' === $i18n_plugin) { $lang = pll_get_term_language($term_id); } else { $lang = false; } $permalink = get_term_link($term, $taxonomy_slug); if ('/' !== rocket_extract_url_component($permalink, PHP_URL_PATH)) { array_push($purge_urls, $permalink); } do_action('before_rocket_clean_term', $term, $purge_urls, $lang); $purge_urls = apply_filters('rocket_term_purge_urls', $purge_urls, $term); rocket_clean_files($purge_urls); rocket_clean_home($lang); do_action('after_rocket_clean_term', $term, $purge_urls, $lang); } function rocket_clean_user($user_id, $lang = '') { $urls = !$lang || is_object($lang) ? get_rocket_i18n_uri() : get_rocket_i18n_home_url($lang); $urls = (array) $urls; $urls = apply_filters('rocket_clean_domain_urls', $urls, $lang); $urls = array_filter($urls); $user = get_user_by('id', $user_id); if (!$user) { return; } $user_key = $user->user_login . '-' . get_rocket_option('secret_cache_key'); foreach ($urls as $url) { $parse_url = get_rocket_parse_url($url); if (apply_filters('rocket_url_no_dots', false)) { $parse_url['host'] = str_replace('.', '_', $parse_url['host']); } $root = rocket_get_constant('WP_ROCKET_CACHE_PATH') . $parse_url['host'] . '-' . $user_key . '*' . $parse_url['path']; do_action('before_rocket_clean_user', $user_id, $lang); $dirs = glob($root . '*', GLOB_NOSORT); if ($dirs) { foreach ($dirs as $dir) { rocket_rrmdir($dir, get_rocket_i18n_to_preserve($lang)); } } do_action('after_rocket_clean_user', $user_id, $lang); } } function rocket_clean_cache_dir() { do_action('before_rocket_clean_cache_dir'); $dirs = glob(WP_ROCKET_CACHE_PATH . '*', GLOB_NOSORT); if ($dirs) { foreach ($dirs as $dir) { rocket_rrmdir($dir); } } do_action('after_rocket_clean_cache_dir'); } function rocket_rrmdir($dir, array $dirs_to_preserve = array(), $filesystem = null) { $dir = untrailingslashit($dir); if (empty($filesystem)) { $filesystem = rocket_direct_filesystem(); } do_action('before_rocket_rrmdir', $dir, $dirs_to_preserve); $nginx_mobile_detect_file = $dir . '/.mobile-active'; if ($filesystem->is_dir($dir) && $filesystem->exists($nginx_mobile_detect_file)) { $filesystem->delete($nginx_mobile_detect_file); } $nowebp_detect_file = $dir . '/.no-webp'; if ($filesystem->is_dir($dir) && $filesystem->exists($nowebp_detect_file)) { $filesystem->delete($nowebp_detect_file); } if (!$filesystem->is_dir($dir)) { $filesystem->delete($dir); return; } $entries = []; try { foreach (new FilesystemIterator($dir) as $entry) { $entries[] = $entry->getPathname(); } } catch (Exception $e) { } if (!empty($dirs_to_preserve) && !empty($entries)) { $keys = []; foreach ($dirs_to_preserve as $dir_to_preserve) { $matches = preg_grep("#^{$dir_to_preserve}\$#", $entries); $keys[] = reset($matches); } if (!empty($keys)) { $keys = array_filter($keys); if (!empty($keys)) { $entries = array_diff($entries, $keys); } } } foreach ($entries as $entry) { if (!$filesystem->is_dir($entry)) { $filesystem->delete($entry); } else { rocket_rrmdir($entry, $dirs_to_preserve, $filesystem); } } $filesystem->delete($dir); do_action('after_rocket_rrmdir', $dir, $dirs_to_preserve); } function rocket_direct_filesystem() { require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-base.php'; require_once ABSPATH . 'wp-admin/includes/class-wp-filesystem-direct.php'; return new WP_Filesystem_Direct(new StdClass()); } function rocket_mkdir($dir) { $chmod = rocket_get_filesystem_perms('dir'); return rocket_direct_filesystem()->mkdir($dir, $chmod); } function rocket_mkdir_p($target) { $wrapper = null; if (rocket_is_stream($target)) { list($wrapper, $target) = explode('://', $target, 2); } $target = str_replace('//', '/', $target); if (null !== $wrapper) { $target = $wrapper . '://' . $target; } $target = rtrim($target, '/\\'); if (empty($target)) { $target = '/'; } if (rocket_direct_filesystem()->exists($target)) { return rocket_direct_filesystem()->is_dir($target); } if (rocket_mkdir($target)) { return true; } elseif (rocket_direct_filesystem()->is_dir(dirname($target))) { return false; } if ('/' !== $target && rocket_mkdir_p(dirname($target))) { return rocket_mkdir_p($target); } return false; } function rocket_is_stream($path) { $scheme_separator = strpos($path, '://'); if (false === $scheme_separator) { return false; } $stream = substr($path, 0, $scheme_separator); return in_array($stream, stream_get_wrappers(), true); } function rocket_put_content($file, $content) { $chmod = rocket_get_filesystem_perms('file'); return rocket_direct_filesystem()->put_contents($file, $content, $chmod); } function rocket_get_filesystem_perms($type) { static $perms = array(); if (rocket_get_constant('WP_ROCKET_IS_TESTING', false)) { $perms = []; } switch ($type) { case 'dir': case 'dirs': case 'folder': case 'folders': $type = 'dir'; break; case 'file': case 'files': $type = 'file'; break; default: return 0755; } if (isset($perms[$type])) { return $perms[$type]; } if ('dir' === $type) { $fs_chmod_dir = (int) rocket_get_constant('FS_CHMOD_DIR', 0); $perms[$type] = $fs_chmod_dir > 0 ? $fs_chmod_dir : fileperms(rocket_get_constant('ABSPATH')) & 0777 | 0755; } else { $fs_chmod_file = (int) rocket_get_constant('FS_CHMOD_FILE', 0); $perms[$type] = $fs_chmod_file > 0 ? $fs_chmod_file : fileperms(rocket_get_constant('ABSPATH') . 'index.php') & 0777 | 0644; } return $perms[$type]; } function _rocket_get_dir_files_by_regex($dir, $regex) { try { $iterator = new IteratorIterator(new FilesystemIterator($dir)); return new RegexIterator($iterator, $regex); } catch (Exception $e) { return []; } } function _rocket_get_cache_path_iterator($cache_path) { try { return new RecursiveIteratorIterator(new RecursiveDirectoryIterator($cache_path), RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD); } catch (Exception $e) { return false; } } function _rocket_get_cache_dirs($url_host, $cache_path = '', $hard_reset = false) { static $domain_dirs = array(); if (true === $hard_reset) { $domain_dirs = []; return; } if (isset($domain_dirs[$url_host])) { return $domain_dirs[$url_host]; } if (empty($cache_path)) { $cache_path = _rocket_get_wp_rocket_cache_path(); } try { $iterator = new IteratorIterator(new FilesystemIterator($cache_path)); } catch (Exception $e) { return []; } $regex = sprintf('/%1$s%2$s(.*)/i', _rocket_normalize_path($cache_path, true), $url_host); try { $entries = new RegexIterator($iterator, $regex); } catch (Exception $e) { return []; } $domain_dirs[$url_host] = []; foreach ($entries as $entry) { $domain_dirs[$url_host][] = $entry->getPathname(); } return $domain_dirs[$url_host]; } function _rocket_normalize_path($path, $escape = false, $force = false) { if (_rocket_is_windows_fs($path)) { $path = str_replace('/', '\\', $path); return $escape ? str_replace('\\', '\\\\', $path) : $path; } if ($escape) { return str_replace('/', '\\/', $path); } if (!$force) { return $path; } return wp_normalize_path($path); } function _rocket_is_windows_fs($hard_reset = false) { static $is_windows = null; if ($hard_reset) { $is_windows = null; } if (is_null($is_windows)) { $is_windows = DIRECTORY_SEPARATOR === '\\' && !rocket_get_constant('WP_ROCKET_RUNNING_VFS', false); } return $is_windows; } function _rocket_get_wp_rocket_cache_path() { return _rocket_normalize_path(rocket_get_constant('WP_ROCKET_CACHE_PATH')); } function _rocket_get_php_files_in_dir($dir_path) { try { $config_dir = new FilesystemIterator((string) $dir_path); } catch (Exception $e) { return []; } $files = []; foreach ($config_dir as $file) { if ($file->isFile() && 'php' === $file->getExtension()) { $files[] = $file; } } return $files; } function _rocket_get_recursive_dir_files_by_regex($regex) { try { $cache_path = _rocket_get_wp_rocket_cache_path(); $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($cache_path, FilesystemIterator::SKIP_DOTS)); return new RegexIterator($iterator, $regex, RecursiveRegexIterator::MATCH); } catch (Exception $e) { return []; } }