>
*/
static function definitions() {
$definitions = array();
$active = false;
foreach (self::plugins() as $slug => $plugin) {
if (!Detector::is_active($slug)) {
continue;
}
$active = true;
$definitions[] = Helper::ability(
'get-' . $slug,
sprintf(
/* translators: %s: cache plugin name. */
__('Get %s cache', 'onemcp-pro'),
$plugin['label']
),
sprintf(
/* translators: %s: cache plugin name. */
__('Reads whether %s caching is on, plus mobile, preload, and minify flags. CDN tokens are not included.', 'onemcp-pro'),
$plugin['label']
),
'onemcp-cache',
true,
function ($input) use ($slug) {
unset($input);
return Cache::read($slug);
},
array(),
array(),
array('cap' => 'manage_options')
);
$definitions[] = Helper::ability(
'purge-' . $slug,
sprintf(
/* translators: %s: cache plugin name. */
__('Purge %s cache', 'onemcp-pro'),
$plugin['label']
),
sprintf(
/* translators: %s: cache plugin name. */
__('Purges the %s page cache. Send post_id or url to purge one page. Omit both to purge the whole cache.', 'onemcp-pro'),
$plugin['label']
),
'onemcp-cache',
false,
function ($input) use ($slug) {
return Cache::purge($slug, $input);
},
self::purge_properties(),
array(),
array('cap' => 'manage_options', 'destructive' => true)
);
}
if ($active) {
$definitions[] = Helper::ability(
'get-cache',
__('Get cache status', 'onemcp-pro'),
__('Reads the public cache settings of every active cache plugin. SpeedyCache is listed first when it is active.', 'onemcp-pro'),
'onemcp-cache',
true,
array(__CLASS__, 'read_all'),
array(),
array(),
array('cap' => 'manage_options')
);
$definitions[] = Helper::ability(
'purge-cache',
__('Purge cache', 'onemcp-pro'),
__('Purges every active cache plugin. Send post_id or url to purge one page. Omit both to purge the whole cache. SpeedyCache is purged first when it is active.', 'onemcp-pro'),
'onemcp-cache',
false,
array(__CLASS__, 'purge_all'),
self::purge_properties(),
array(),
array('cap' => 'manage_options', 'destructive' => true)
);
}
return $definitions;
}
/**
* Read one plugin.
*
* @param string $slug Plugin slug.
* @return array|WP_Error
*/
static function read($slug) {
if (!isset(self::plugins()[$slug]) || !Detector::is_active($slug)) {
return Helper::error('onemcp_unavailable', __('That cache plugin is not active.', 'onemcp-pro'));
}
return self::view($slug);
}
/**
* Read every active cache plugin. SpeedyCache comes first.
*
* @param array $input Input.
* @return array
*/
static function read_all($input) {
unset($input);
$plugins = array();
foreach (self::plugins() as $slug => $plugin) {
if (!Detector::is_active($slug)) {
continue;
}
$plugins[] = self::view($slug);
}
return array(
'plugins' => $plugins,
);
}
/**
* Purge one plugin.
*
* @param string $slug Plugin slug.
* @param array $input Input.
* @return array|WP_Error
*/
static function purge($slug, $input) {
if (!isset(self::plugins()[$slug]) || !Detector::is_active($slug)) {
return Helper::error('onemcp_unavailable', __('That cache plugin is not active.', 'onemcp-pro'));
}
$target = self::target(is_array($input) ? $input : array());
if (is_wp_error($target)) {
return $target;
}
return self::purge_one($slug, $target, is_array($input) ? $input : array());
}
/**
* Purge every active cache plugin. SpeedyCache runs first.
*
* @param array $input Input.
* @return array|WP_Error
*/
static function purge_all($input) {
$input = is_array($input) ? $input : array();
$target = self::target($input);
if (is_wp_error($target)) {
return $target;
}
$results = array();
foreach (self::plugins() as $slug => $plugin) {
if (!Detector::is_active($slug)) {
continue;
}
$result = self::purge_one($slug, $target, $input);
if (is_wp_error($result)) {
$results[] = array(
'plugin' => $slug,
'label' => $plugin['label'],
'purged' => false,
'message' => $result->get_error_message(),
);
continue;
}
$results[] = $result;
}
if ($results === array()) {
return Helper::error('onemcp_unavailable', __('No supported cache plugin is active.', 'onemcp-pro'));
}
return array(
'scope' => $target['scope'],
'post_id' => $target['post_id'],
'url' => $target['url'],
'plugins' => $results,
);
}
/**
* Supported plugins. SpeedyCache is first.
*
* @return array>
*/
private static function plugins() {
return array(
'speedycache' => array(
'label' => 'SpeedyCache',
),
'litespeed' => array(
'label' => 'LiteSpeed Cache',
),
'wp-rocket' => array(
'label' => 'WP Rocket',
),
'wp-super-cache' => array(
'label' => 'WP Super Cache',
),
'w3-total-cache' => array(
'label' => 'W3 Total Cache',
),
'wp-fastest-cache' => array(
'label' => 'WP Fastest Cache',
),
'wp-optimize' => array(
'label' => 'WP-Optimize',
),
'siteground' => array(
'label' => 'SiteGround Optimizer',
),
);
}
/**
* Fields a purge ability accepts.
*
* @return array>
*/
private static function purge_properties() {
return array(
'post_id' => Helper::int_prop(__('Post or page ID to purge. Use 0 for the homepage. Omit, along with url, to purge the whole cache.', 'onemcp-pro')),
'url' => Helper::string_prop(__('A URL on this site to purge. Omit, along with post_id, to purge the whole cache.', 'onemcp-pro'), 500),
'minified' => Helper::bool_prop(__('Also delete minified CSS and JS. Used by SpeedyCache and WP Fastest Cache on a full purge.', 'onemcp-pro')),
'fonts' => Helper::bool_prop(__('Also delete locally cached fonts. Used by SpeedyCache on a full purge.', 'onemcp-pro')),
'gravatars' => Helper::bool_prop(__('Also delete cached gravatars. Used by SpeedyCache on a full purge.', 'onemcp-pro')),
'preload' => Helper::bool_prop(__('Rebuild the SpeedyCache preload list after a full purge.', 'onemcp-pro')),
);
}
/**
* Public settings for one plugin.
*
* @param string $slug Plugin slug.
* @return array
*/
private static function view($slug) {
$plugins = self::plugins();
$base = array(
'plugin' => $slug,
'label' => $plugins[$slug]['label'],
);
if ($slug === 'speedycache') {
return array_merge($base, self::view_speedycache());
}
if ($slug === 'litespeed') {
return array_merge($base, self::view_litespeed());
}
if ($slug === 'wp-rocket') {
return array_merge($base, self::view_rocket());
}
if ($slug === 'wp-super-cache') {
return array_merge($base, self::view_super_cache());
}
if ($slug === 'w3-total-cache') {
return array_merge($base, self::view_w3tc());
}
if ($slug === 'wp-fastest-cache') {
return array_merge($base, self::view_fastest());
}
if ($slug === 'wp-optimize') {
return array_merge($base, self::view_wp_optimize());
}
if ($slug === 'siteground') {
return array_merge($base, self::view_siteground());
}
return $base;
}
/**
* SpeedyCache settings and cache size. Credentials are left out.
*
* @return array
*/
private static function view_speedycache() {
$options = get_option('speedycache_options', array());
if (!is_array($options)) {
$options = array();
}
$cdn = get_option('speedycache_cdn', array());
if (!is_array($cdn)) {
$cdn = array();
}
$excludes = get_option('speedycache_exclude', array());
$queued = get_transient('speedycache_preload_transient');
$size = (int) get_option('speedycache_html_size', 0);
return array(
'cache_enabled' => !empty($options['status']),
'gzip' => !empty($options['gzip']),
'logged_in_user' => !empty($options['logged_in_user']),
'mobile' => !empty($options['mobile']),
'mobile_theme' => !empty($options['mobile_theme']),
'browser_cache' => !empty($options['lbc']),
'purge_varnish' => !empty($options['purge_varnish']),
'varnish_ip' => isset($options['varniship']) ? Helper::text($options['varniship'], 80) : '',
'preload' => !empty($options['preload']),
'preload_queued' => is_array($queued) ? count($queued) : 0,
'cache_lifespan' => isset($options['purge_interval']) ? (int) $options['purge_interval'] : 0,
'cache_lifespan_unit' => isset($options['purge_interval_unit']) ? Helper::text($options['purge_interval_unit'], 20) : '',
'minify_html' => !empty($options['minify_html']),
'minify_css' => !empty($options['minify_css']),
'minify_js' => !empty($options['minify_js']),
'combine_css' => !empty($options['combine_css']),
'combine_js' => !empty($options['combine_js']),
'lazy_load' => !empty($options['lazy_load']),
'delay_js' => !empty($options['delay_js']),
'cdn_enabled' => !empty($cdn['enabled']),
'cdn_url' => isset($cdn['cdn_url']) ? esc_url_raw((string) $cdn['cdn_url']) : '',
'exclude_rules' => is_array($excludes) ? count($excludes) : 0,
'cached_pages' => (int) get_option('speedycache_html', 0),
'cache_size_kb' => round($size / 1000, 2),
);
}
/**
* LiteSpeed Cache flags stored as individual options.
*
* @return array
*/
private static function view_litespeed() {
return array(
'cache_enabled' => self::option_on('litespeed.conf.cache'),
'mobile' => self::option_on('litespeed.conf.cache-mobile'),
'logged_in_user' => self::option_on('litespeed.conf.cache-priv'),
'object_cache' => self::option_on('litespeed.conf.object'),
'browser_cache' => self::option_on('litespeed.conf.cache-browser'),
);
}
/**
* WP Rocket public flags. API keys stay in the option.
*
* @return array
*/
private static function view_rocket() {
$settings = get_option('wp_rocket_settings', array());
if (!is_array($settings)) {
$settings = array();
}
return array(
'cache_enabled' => true,
'mobile' => !empty($settings['cache_mobile']),
'logged_in_user' => !empty($settings['cache_logged_user']),
'preload' => !empty($settings['manual_preload']),
'minify_css' => !empty($settings['minify_css']),
'minify_js' => !empty($settings['minify_js']),
'lazy_load' => !empty($settings['lazyload']),
'delay_js' => !empty($settings['delay_js']),
'cdn_enabled' => !empty($settings['cdn']),
);
}
/**
* WP Super Cache switches from its runtime config.
*
* @return array
*/
private static function view_super_cache() {
global $cache_enabled, $super_cache_enabled, $wp_cache_mod_rewrite, $cache_max_time;
return array(
'cache_enabled' => !empty($cache_enabled),
'supercache' => !empty($super_cache_enabled),
'mod_rewrite' => !empty($wp_cache_mod_rewrite),
'cache_max_time'=> isset($cache_max_time) ? (int) $cache_max_time : 0,
);
}
/**
* W3 Total Cache page-cache flag.
*
* @return array
*/
private static function view_w3tc() {
$enabled = null;
$object = null;
if (function_exists('w3tc_config')) {
$config = w3tc_config();
if (is_object($config) && method_exists($config, 'get_boolean')) {
$enabled = (bool) $config->get_boolean('pgcache.enabled');
$object = (bool) $config->get_boolean('objectcache.enabled');
}
}
return array(
'cache_enabled' => $enabled,
'object_cache' => $object,
);
}
/**
* WP Fastest Cache status from its JSON option.
*
* @return array
*/
private static function view_fastest() {
$stored = get_option('WpFastestCache', '');
$data = is_string($stored) ? json_decode($stored, true) : $stored;
if (!is_array($data)) {
$data = array();
}
return array(
'cache_enabled' => !empty($data['wpFastestCacheStatus']),
'mobile' => !empty($data['wpFastestCacheMobile']),
'preload' => !empty($data['wpFastestCachePreload']),
'minify_css' => !empty($data['wpFastestCacheMinifyCss']),
'minify_js' => !empty($data['wpFastestCacheMinifyJs']),
);
}
/**
* WP-Optimize page cache config.
*
* @return array
*/
private static function view_wp_optimize() {
$config = get_option('wpo_cache_config', array());
if (!is_array($config)) {
$config = array();
}
return array(
'cache_enabled' => !empty($config['enable_page_caching']),
'mobile' => !empty($config['enable_mobile_caching']),
'preload' => !empty($config['enable_preload']),
);
}
/**
* SiteGround Optimizer dynamic cache switch.
*
* @return array
*/
private static function view_siteground() {
return array(
'cache_enabled' => self::option_on('siteground_optimizer_enable_cache'),
'mobile' => self::option_on('siteground_optimizer_file_caching'),
);
}
/**
* Whether a WordPress option is stored as on.
*
* @param string $name Option name.
* @return bool
*/
private static function option_on($name) {
$value = get_option($name, '');
if (is_bool($value)) {
return $value;
}
if (is_numeric($value)) {
return (int) $value === 1;
}
return in_array(strtolower(trim((string) $value)), array('1', 'true', 'yes', 'on'), true);
}
/**
* Resolve a full purge, a post, or a same-site URL.
*
* @param array $input Input.
* @return array|WP_Error
*/
private static function target($input) {
$has_post = array_key_exists('post_id', $input) && $input['post_id'] !== '' && $input['post_id'] !== null;
$url = '';
if (isset($input['url']) && (string) $input['url'] !== '') {
$url = self::site_url($input['url']);
if ($url === null) {
return Helper::error('onemcp_invalid', __('The cache URL must be a page on this site.', 'onemcp-pro'));
}
}
if ($has_post) {
$post_id = (int) $input['post_id'];
if ($post_id < 0) {
return Helper::error('onemcp_invalid', __('Post ID must be 0 for the homepage, or a positive ID.', 'onemcp-pro'));
}
if ($post_id > 0) {
$post = get_post($post_id);
if (!$post instanceof \WP_Post) {
return Helper::error('onemcp_not_found', __('That post was not found.', 'onemcp-pro'));
}
}
return array(
'scope' => 'post',
'post_id' => $post_id,
'url' => $post_id > 0 ? (string) get_permalink($post_id) : (string) home_url('/'),
);
}
if ($url !== '') {
$post_id = url_to_postid($url);
return array(
'scope' => 'url',
'post_id' => $post_id > 0 ? $post_id : 0,
'url' => $url,
);
}
return array(
'scope' => 'all',
'post_id' => 0,
'url' => '',
);
}
/**
* A URL on this site, or null when it points somewhere else.
*
* @param mixed $value Raw URL.
* @return string|null
*/
private static function site_url($value) {
$url = esc_url_raw(is_scalar($value) ? (string) $value : '');
$home = wp_parse_url(home_url());
$parts = wp_parse_url($url);
if ($url === '' || empty($parts['host']) || empty($home['host'])) {
return null;
}
if (strtolower((string) $parts['host']) !== strtolower((string) $home['host'])) {
return null;
}
return $url;
}
/**
* Purge one plugin and describe what happened.
*
* @param string $slug Plugin slug.
* @param array $target Resolved target.
* @param array $input Original input.
* @return array|WP_Error
*/
private static function purge_one($slug, $target, $input) {
$purged = false;
$note = '';
if ($slug === 'speedycache') {
$purged = self::purge_speedycache($target, $input, $note);
} elseif ($slug === 'litespeed') {
$purged = self::purge_litespeed($target, $note);
} elseif ($slug === 'wp-rocket') {
$purged = self::purge_rocket($target, $note);
} elseif ($slug === 'wp-super-cache') {
$purged = self::purge_super_cache($target, $note);
} elseif ($slug === 'w3-total-cache') {
$purged = self::purge_w3tc($target, $note);
} elseif ($slug === 'wp-fastest-cache') {
$purged = self::purge_fastest($target, $input, $note);
} elseif ($slug === 'wp-optimize') {
$purged = self::purge_wp_optimize($target, $note);
} elseif ($slug === 'siteground') {
$purged = self::purge_siteground($target, $note);
}
if (!$purged) {
return Helper::error(
'onemcp_failed',
sprintf(
/* translators: %s: cache plugin name. */
__('%s did not expose a purge method.', 'onemcp-pro'),
self::plugins()[$slug]['label']
)
);
}
$plugins = self::plugins();
$message = $target['scope'] === 'all'
? sprintf(
/* translators: %s: cache plugin name. */
__('Purged the %s cache.', 'onemcp-pro'),
$plugins[$slug]['label']
)
: sprintf(
/* translators: %s: cache plugin name. */
__('Purged the %s cache for that page.', 'onemcp-pro'),
$plugins[$slug]['label']
);
if ($note !== '') {
$message .= ' ' . $note;
}
return array(
'plugin' => $slug,
'label' => $plugins[$slug]['label'],
'purged' => true,
'scope' => $target['scope'],
'post_id' => $target['post_id'],
'url' => $target['url'],
'message' => $message,
);
}
/**
* SpeedyCache purge through Delete and, on request, Preload.
*
* @param array $target Target.
* @param array $input Input.
* @param string $note Extra note.
* @return bool
*/
private static function purge_speedycache($target, $input, &$note) {
if (!class_exists('\SpeedyCache\Delete')) {
if ($target['scope'] === 'all' && function_exists('speedycache_delete_cache')) {
speedycache_delete_cache(!empty($input['minified']));
return true;
}
return false;
}
if ($target['scope'] === 'post' && method_exists('\SpeedyCache\Delete', 'cache')) {
\SpeedyCache\Delete::cache((int) $target['post_id']);
return true;
}
if ($target['scope'] === 'url' && method_exists('\SpeedyCache\Delete', 'url')) {
\SpeedyCache\Delete::url(array($target['url']));
return true;
}
if ($target['scope'] !== 'all' || !method_exists('\SpeedyCache\Delete', 'run')) {
return false;
}
$actions = array();
if (!empty($input['minified'])) {
$actions['minified'] = true;
}
if (!empty($input['fonts'])) {
$actions['font'] = true;
}
if (!empty($input['gravatars'])) {
$actions['gravatars'] = true;
}
if (!empty($input['preload'])) {
$actions['preload'] = true;
}
\SpeedyCache\Delete::run($actions);
if (!empty($input['preload']) && class_exists('\SpeedyCache\Preload') && method_exists('\SpeedyCache\Preload', 'build_preload_list')) {
\SpeedyCache\Preload::build_preload_list();
$note = __('The preload list was rebuilt.', 'onemcp-pro');
}
return true;
}
/**
* LiteSpeed Cache purge hooks.
*
* @param array $target Target.
* @param string $note Extra note.
* @return bool
*/
private static function purge_litespeed($target, &$note) {
unset($note);
if ($target['scope'] === 'post') {
if (!has_action('litespeed_purge_post') && !(class_exists('\LiteSpeed\Purge') && method_exists('\LiteSpeed\Purge', 'purge_post'))) {
return false;
}
do_action('litespeed_purge_post', (int) $target['post_id']);
return true;
}
if ($target['scope'] === 'url') {
if (!has_action('litespeed_purge_url')) {
return false;
}
do_action('litespeed_purge_url', $target['url']);
return true;
}
if (class_exists('\LiteSpeed\Purge') && method_exists('\LiteSpeed\Purge', 'purge_all')) {
\LiteSpeed\Purge::purge_all();
return true;
}
if (!has_action('litespeed_purge_all')) {
return false;
}
do_action('litespeed_purge_all');
return true;
}
/**
* WP Rocket purge functions.
*
* @param array $target Target.
* @param string $note Extra note.
* @return bool
*/
private static function purge_rocket($target, &$note) {
unset($note);
if ($target['scope'] === 'post' && function_exists('rocket_clean_post')) {
rocket_clean_post((int) $target['post_id']);
return true;
}
if ($target['scope'] === 'url' && function_exists('rocket_clean_files')) {
rocket_clean_files(array($target['url']));
return true;
}
if ($target['scope'] === 'all' && function_exists('rocket_clean_domain')) {
rocket_clean_domain();
return true;
}
return false;
}
/**
* WP Super Cache purge. A single URL falls back to that post when one exists.
*
* @param array $target Target.
* @param string $note Extra note.
* @return bool
*/
private static function purge_super_cache($target, &$note) {
$post_id = (int) $target['post_id'];
if ($target['scope'] !== 'all' && $post_id > 0) {
if (function_exists('wpsc_delete_post_cache')) {
wpsc_delete_post_cache($post_id);
return true;
}
if (function_exists('wp_cache_post_change')) {
wp_cache_post_change($post_id);
return true;
}
}
if (!function_exists('wp_cache_clear_cache')) {
return false;
}
if (is_multisite()) {
wp_cache_clear_cache(get_current_blog_id());
} else {
wp_cache_clear_cache();
}
if ($target['scope'] !== 'all') {
$note = __('WP Super Cache cleared the whole cache for this site.', 'onemcp-pro');
}
return true;
}
/**
* W3 Total Cache flush helpers.
*
* @param array $target Target.
* @param string $note Extra note.
* @return bool
*/
private static function purge_w3tc($target, &$note) {
unset($note);
if ($target['scope'] === 'post' && function_exists('w3tc_flush_post')) {
w3tc_flush_post((int) $target['post_id']);
return true;
}
if ($target['scope'] === 'url' && function_exists('w3tc_flush_url')) {
w3tc_flush_url($target['url']);
return true;
}
if ($target['scope'] === 'all' && function_exists('w3tc_flush_all')) {
w3tc_flush_all();
return true;
}
return false;
}
/**
* WP Fastest Cache purge. Minified files are included only on a full purge.
*
* @param array $target Target.
* @param array $input Input.
* @param string $note Extra note.
* @return bool
*/
private static function purge_fastest($target, $input, &$note) {
unset($note);
$cache = isset($GLOBALS['wp_fastest_cache']) ? $GLOBALS['wp_fastest_cache'] : null;
if ($target['scope'] !== 'all' && (int) $target['post_id'] > 0 && is_object($cache) && method_exists($cache, 'singleDeleteCache')) {
$cache->singleDeleteCache(false, (int) $target['post_id']);
return true;
}
if ($target['scope'] !== 'all') {
return false;
}
$minified = !empty($input['minified']);
if (is_object($cache) && method_exists($cache, 'deleteCache')) {
$cache->deleteCache($minified);
return true;
}
if (function_exists('wpfc_clear_all_cache')) {
wpfc_clear_all_cache($minified);
return true;
}
return false;
}
/**
* WP-Optimize page cache purge.
*
* @param array $target Target.
* @param string $note Extra note.
* @return bool
*/
private static function purge_wp_optimize($target, &$note) {
unset($note);
if ($target['scope'] === 'post' && class_exists('WPO_Page_Cache') && method_exists('WPO_Page_Cache', 'delete_single_post_cache')) {
\WPO_Page_Cache::delete_single_post_cache((int) $target['post_id']);
return true;
}
if ($target['scope'] === 'url' && class_exists('WPO_Page_Cache') && method_exists('WPO_Page_Cache', 'delete_cache_by_url')) {
\WPO_Page_Cache::delete_cache_by_url($target['url']);
return true;
}
if ($target['scope'] !== 'all') {
return false;
}
if (function_exists('wpo_cache_flush')) {
wpo_cache_flush();
return true;
}
if (function_exists('WP_Optimize')) {
$optimize = WP_Optimize();
if (is_object($optimize) && method_exists($optimize, 'get_page_cache')) {
$page_cache = $optimize->get_page_cache();
if (is_object($page_cache) && method_exists($page_cache, 'purge')) {
$page_cache->purge();
return true;
}
}
}
return false;
}
/**
* SiteGround Optimizer purge helper.
*
* @param array $target Target.
* @param string $note Extra note.
* @return bool
*/
private static function purge_siteground($target, &$note) {
unset($note);
if (!function_exists('sg_cachepress_purge_cache')) {
return false;
}
if ($target['scope'] === 'all') {
sg_cachepress_purge_cache();
return true;
}
if ($target['url'] === '') {
return false;
}
sg_cachepress_purge_cache($target['url']);
return true;
}
}