- 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
235 lines
6.4 KiB
PHP
235 lines
6.4 KiB
PHP
<?php
|
|
/**
|
|
* Admin functionality.
|
|
*
|
|
* @package WP_Recache
|
|
*/
|
|
|
|
defined('ABSPATH') || exit;
|
|
|
|
class WP_Recache_Admin {
|
|
|
|
/**
|
|
* Initialize admin hooks.
|
|
*/
|
|
public function init() {
|
|
add_action('admin_menu', [$this, 'add_admin_menu']);
|
|
add_action('admin_init', [$this, 'register_settings']);
|
|
add_action('admin_bar_menu', [$this, 'add_admin_bar_button'], 100);
|
|
add_action('wp_ajax_wp_recache_purge_all', [$this, 'ajax_purge_all']);
|
|
add_action('wp_ajax_wp_recache_purge_url', [$this, 'ajax_purge_url']);
|
|
add_action('admin_notices', [$this, 'admin_notices']);
|
|
add_action('admin_enqueue_scripts', 'wp_recache_enqueue_admin_bar_script');
|
|
// New exclusions must not leave stale files that the drop-in would still serve.
|
|
add_action('update_option_wp_recache_exclude_urls', 'wp_recache_delete_all_cache');
|
|
}
|
|
|
|
/**
|
|
* Add admin menu page.
|
|
*/
|
|
public function add_admin_menu() {
|
|
add_options_page(
|
|
'WP Recache',
|
|
'WP Recache',
|
|
'manage_options',
|
|
'wp-recache',
|
|
[$this, 'settings_page']
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Register settings.
|
|
*/
|
|
public function register_settings() {
|
|
register_setting('wp_recache_settings', 'wp_recache_cache_enabled', [
|
|
'type' => 'boolean',
|
|
'sanitize_callback' => 'rest_sanitize_boolean',
|
|
'default' => true,
|
|
]);
|
|
|
|
register_setting('wp_recache_settings', 'wp_recache_separate_mobile_cache', [
|
|
'type' => 'boolean',
|
|
'sanitize_callback' => 'rest_sanitize_boolean',
|
|
'default' => false,
|
|
]);
|
|
|
|
register_setting('wp_recache_settings', 'wp_recache_exclude_urls', [
|
|
'type' => 'array',
|
|
'sanitize_callback' => [$this, 'sanitize_exclude_urls'],
|
|
'default' => ['/cart', '/checkout', '/my-account'],
|
|
]);
|
|
|
|
register_setting('wp_recache_settings', 'wp_recache_minify_css', [
|
|
'type' => 'boolean',
|
|
'sanitize_callback' => 'rest_sanitize_boolean',
|
|
'default' => false,
|
|
]);
|
|
|
|
register_setting('wp_recache_settings', 'wp_recache_minify_js', [
|
|
'type' => 'boolean',
|
|
'sanitize_callback' => 'rest_sanitize_boolean',
|
|
'default' => false,
|
|
]);
|
|
|
|
register_setting('wp_recache_settings', 'wp_recache_lazyload_images', [
|
|
'type' => 'boolean',
|
|
'sanitize_callback' => 'rest_sanitize_boolean',
|
|
'default' => false,
|
|
]);
|
|
|
|
register_setting('wp_recache_settings', 'wp_recache_preload_enabled', [
|
|
'type' => 'boolean',
|
|
'sanitize_callback' => 'rest_sanitize_boolean',
|
|
'default' => false,
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Sanitize exclude URLs.
|
|
*
|
|
* @param mixed $input Input value.
|
|
* @return array Sanitized URLs.
|
|
*/
|
|
public function sanitize_exclude_urls($input) {
|
|
if (is_array($input)) {
|
|
$input = implode("\n", $input);
|
|
}
|
|
|
|
$lines = array_filter(array_map('trim', explode("\n", (string) $input)));
|
|
|
|
return array_map('sanitize_text_field', $lines);
|
|
}
|
|
|
|
/**
|
|
* Render settings page.
|
|
*/
|
|
public function settings_page() {
|
|
if (!current_user_can('manage_options')) {
|
|
return;
|
|
}
|
|
|
|
$active_tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'cache';
|
|
|
|
if (!in_array($active_tab, ['cache', 'optimize', 'advanced'], true)) {
|
|
$active_tab = 'cache';
|
|
}
|
|
|
|
include WP_RECACHE_INC_PATH . 'Admin/views/settings.php';
|
|
}
|
|
|
|
/**
|
|
* Add admin bar purge button.
|
|
*
|
|
* @param WP_Admin_Bar $admin_bar Admin bar instance.
|
|
*/
|
|
public function add_admin_bar_button($admin_bar) {
|
|
if (!is_user_logged_in()) {
|
|
return;
|
|
}
|
|
|
|
$admin_bar->add_menu([
|
|
'id' => 'wp-recache',
|
|
'title' => 'WP Recache',
|
|
'href' => admin_url('options-general.php?page=wp-recache'),
|
|
]);
|
|
|
|
$admin_bar->add_menu([
|
|
'id' => 'wp-recache-purge-all',
|
|
'parent' => 'wp-recache',
|
|
'title' => 'Purge All Cache',
|
|
'href' => '#',
|
|
'meta' => [
|
|
'onclick' => 'wpRecachePurgeAll();',
|
|
],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* AJAX handler for purging all cache.
|
|
*/
|
|
public function ajax_purge_all() {
|
|
check_ajax_referer('wp_recache_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error('Unauthorized');
|
|
}
|
|
|
|
wp_recache_delete_all_cache();
|
|
|
|
wp_send_json_success('Cache purged successfully');
|
|
}
|
|
|
|
/**
|
|
* AJAX handler for purging URL cache.
|
|
*/
|
|
public function ajax_purge_url() {
|
|
check_ajax_referer('wp_recache_nonce', 'nonce');
|
|
|
|
if (!current_user_can('manage_options')) {
|
|
wp_send_json_error('Unauthorized');
|
|
}
|
|
|
|
$url = isset($_POST['url']) ? esc_url_raw($_POST['url']) : '';
|
|
|
|
if (empty($url)) {
|
|
wp_send_json_error('No URL provided');
|
|
}
|
|
|
|
wp_recache_delete_cache($url);
|
|
|
|
wp_send_json_success('URL cache purged successfully');
|
|
}
|
|
|
|
/**
|
|
* Display admin notices.
|
|
*/
|
|
public function admin_notices() {
|
|
$screen = get_current_screen();
|
|
|
|
if (!$screen || $screen->id !== 'settings_page_wp-recache') {
|
|
return;
|
|
}
|
|
|
|
if (isset($_GET['settings-updated'])) {
|
|
echo '<div class="notice notice-success"><p>Settings saved.</p></div>';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get cache statistics.
|
|
*
|
|
* @return array Cache statistics.
|
|
*/
|
|
public static function get_cache_stats() {
|
|
$cache_path = WP_RECACHE_CACHE_PATH;
|
|
|
|
if (!is_dir($cache_path)) {
|
|
return [
|
|
'files' => 0,
|
|
'size' => 0,
|
|
'size_formatted' => '0 B',
|
|
];
|
|
}
|
|
|
|
$files = new RecursiveIteratorIterator(
|
|
new RecursiveDirectoryIterator($cache_path, RecursiveDirectoryIterator::SKIP_DOTS)
|
|
);
|
|
|
|
$count = 0;
|
|
$size = 0;
|
|
|
|
foreach ($files as $file) {
|
|
if ($file->isFile()) {
|
|
$count++;
|
|
$size += $file->getSize();
|
|
}
|
|
}
|
|
|
|
return [
|
|
'files' => $count,
|
|
'size' => $size,
|
|
'size_formatted' => size_format($size),
|
|
];
|
|
}
|
|
}
|