Files
wp-recache/includes/Common/Helpers.php
T
kevin.bataille d2be239c3f fix: address Phase 1 code review findings
- Serve cache via template_redirect so feeds/404/REST are excluded and
  query conditionals work
- Bypass cache on query strings; key files by md5(host+path) to avoid
  collisions and support multisite
- Write wp-content/wp-recache-cache.php drop-in server and set WP_CACHE
  in wp-config.php so advanced-cache.php actually runs
- Only remove advanced-cache.php on deactivation when it is ours
- Respect DONOTCACHEPAGE, non-200 responses; bots read but never warm
  cache
- Fix comment purge (comment_post_ID) and heartbeat purge ($data arg)
- Fix exclude URLs textarea parsing; purge all when exclusions change
- Enqueue admin purge script on every admin-bar page, not just settings
- Sync tests, add TESTING.md manual test guide
2026-09-13 13:44:30 +02:00

215 lines
4.8 KiB
PHP

<?php
/**
* Common helper functions.
*
* @package WP_Recache
*/
defined('ABSPATH') || exit;
/**
* Check if cache is enabled.
*/
function wp_recache_is_cache_enabled() {
return (bool) get_option('wp_recache_cache_enabled', true);
}
/**
* Check if a specific feature is enabled.
*
* @param string $feature Feature name.
*/
function wp_recache_is_feature_enabled($feature) {
return (bool) get_option("wp_recache_{$feature}_enabled", false);
}
/**
* Get plugin option with default.
*
* @param string $option Option name.
* @param mixed $default Default value.
*/
function wp_recache_get_option($option, $default = false) {
return get_option("wp_recache_{$option}", $default);
}
/**
* Set plugin option.
*
* @param string $option Option name.
* @param mixed $value Option value.
*/
function wp_recache_set_option($option, $value) {
return update_option("wp_recache_{$option}", $value);
}
/**
* Check if current user is logged in.
*/
function wp_recache_is_logged_in() {
return is_user_logged_in();
}
/**
* Check if current request should be excluded from cache.
*/
function wp_recache_should_exclude() {
if (wp_recache_is_logged_in()) {
return true;
}
// Dynamic query-string requests are never cached (story 11).
if (!empty($_SERVER['QUERY_STRING'])) {
return true;
}
if (is_preview() || is_feed() || is_404()) {
return true;
}
if (wp_recache_is_post_action()) {
return true;
}
$exclude_urls = wp_recache_get_option('exclude_urls', []);
$request_uri = wp_parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
foreach ($exclude_urls as $url) {
if (strpos($request_uri, trim($url)) !== false) {
return true;
}
}
return apply_filters('wp_recache_exclude', false);
}
/**
* Check if request is for a robot/crawler.
*/
function wp_recache_is_robots() {
return isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'], 'bot') !== false;
}
/**
* Check if request is a POST action.
*/
function wp_recache_is_post_action() {
return ($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST';
}
/**
* Get cache file path for URL.
*
* Keyed by md5(host + path) so nested paths, hosts and multisite
* sub-directories never collide. Query strings are bypassed upstream.
*
* @param string $url URL to cache.
*/
function wp_recache_get_cache_path($url) {
$host = (string) wp_parse_url($url, PHP_URL_HOST);
$path = (string) wp_parse_url($url, PHP_URL_PATH);
return WP_RECACHE_CACHE_PATH . md5($host . $path) . '.html';
}
/**
* Delete cache file for URL.
*
* @param string $url URL to delete cache for.
*/
function wp_recache_delete_cache($url) {
$path = wp_recache_get_cache_path($url);
if (file_exists($path)) {
return unlink($path);
}
return false;
}
/**
* Delete all cache files.
*/
function wp_recache_delete_all_cache() {
$cache_path = WP_RECACHE_CACHE_PATH;
if (!is_dir($cache_path)) {
return false;
}
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($cache_path, RecursiveDirectoryIterator::SKIP_DOTS),
RecursiveIteratorIterator::CHILD_FIRST
);
foreach ($files as $file) {
if ($file->isDir()) {
rmdir($file->getRealPath());
} else {
unlink($file->getRealPath());
}
}
return true;
}
/**
* Check if URL is mobile.
*/
function wp_recache_is_mobile() {
if (!isset($_SERVER['HTTP_USER_AGENT'])) {
return false;
}
$mobile_agents = [
'android',
'iphone',
'ipad',
'ipod',
'blackberry',
'opera mini',
'opera mobi',
];
$user_agent = strtolower($_SERVER['HTTP_USER_AGENT']);
foreach ($mobile_agents as $agent) {
if (strpos($user_agent, $agent) !== false) {
return true;
}
}
return false;
}
/**
* Get cache file path for URL with mobile detection.
*
* @param string $url URL to cache.
*/
function wp_recache_get_cache_path_with_device($url) {
$path = wp_recache_get_cache_path($url);
if (wp_recache_get_option('separate_mobile_cache', false)) {
$device = wp_recache_is_mobile() ? 'mobile' : 'desktop';
$path = str_replace('.html', "-{$device}.html", $path);
}
return $path;
}
/**
* Enqueue the admin-bar purge script (admin and front-end admin bar).
*/
function wp_recache_enqueue_admin_bar_script() {
if (!is_admin_bar_showing() || !current_user_can('manage_options')) {
return;
}
wp_enqueue_script('wp-recache-admin', WP_RECACHE_URL . 'assets/admin.js', ['jquery'], WP_RECACHE_VERSION, true);
wp_localize_script('wp-recache-admin', 'wpRecache', [
'ajaxUrl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('wp_recache_nonce'),
]);
}