Files
tysweld.com/wp-content/plugins/wp-optimize-premium/cache/class-wpo-cache-premium.php
2025-02-24 22:33:42 +01:00

560 lines
19 KiB
PHP

<?php
if (!defined('ABSPATH')) die('No direct access allowed');
if (!class_exists('WPO_Cache_Premium')) :
class WPO_Cache_Premium {
/**
* Cache config object
*
* @var mixed
*/
protected $config;
/**
* Construct WPO_Cache_Premium - setup filters and actions, initiate class variables
*/
public function __construct() {
// option defaults filter for premium features.
add_filter('wpo_cache_defaults', array($this, 'get_defaults'));
// Add premium cache rules before initializing the default cache rules.
WPO_Cache_Rules_Premium::get_instance();
$this->config = WP_Optimize()->get_page_cache()->config->get();
add_action('woocommerce_init', array($this, 'maybe_set_tax_country_cookie'), 40);
add_action('wpo_page_cache_settings_after', array($this, 'add_woocommerce_template_to_cache_settings'), 20, 1);
add_filter('wpo_cache_update_config', array($this, 'add_default_values_to_cache_config'), 20);
add_filter('wpo_cache_cookies', array($this, 'add_cache_cookies'), 20, 2);
add_filter('wpo_cache_query_variables', array($this, 'add_cache_query_variables'), 20, 2);
add_filter('display_post_states', array($this, 'add_post_state'), 30, 2);
add_action('add_meta_boxes', array($this, 'add_cache_control_metabox'));
add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts_styles'));
add_action('wpo_premium_scripts_styles', array($this, 'wpo_page_only_scripts'), 20, 3);
add_action('wpo_after_cache_exception_urls', array($this, 'output_excluded_posts'));
add_action('wpo_after_cache_exception_urls_fieldgroup', array($this, 'output_always_purge_posts'));
add_action('save_post', array($this, 'always_purge_post_on_update'), 10, 1);
add_action('add_attachment', array($this, 'always_purge_post_on_update'), 10, 1);
add_action('edit_attachment', array($this, 'always_purge_post_on_update'), 10, 1);
add_action('delete_attachment', array($this, 'always_purge_post_on_update'), 10, 1);
// Cloudflare initialisation.
include_once(WPO_PLUGIN_MAIN_PATH.'cache/class-wp-optimize-cloudflare-api.php');
include_once(WPO_PLUGIN_MAIN_PATH.'cache/class-wp-optimize-cloudflare.php');
new WP_Optimize_Cloudflare($this->config);
// Add action for disable caching for selected posts.
add_action('wp', array($this, 'disable_posts_caching'));
// Add user per role cache option
add_action('wpo_after_cache_settings', array($this, 'output_user_per_role_cache_option'), 9);
// Add user specific cache option
add_action('wpo_after_cache_settings', array($this, 'output_user_specific_cache_option'), 10);
WPO_Cache_Preloader_Premium::get_instance();
WPO_Cache_Purge_Premium::get_instance();
}
/**
* Default options values.
*/
public function get_defaults($defaults) {
$defaults['enable_per_role_cache'] = false;
$defaults['enable_user_specific_cache'] = false;
return $defaults;
}
/**
* Disable caching for posts those have _wpo_disable_caching meta field.
*/
public function disable_posts_caching() {
global $post;
if (!defined('DONOTCACHEPAGE') && $post && get_post_meta($post->ID, '_wpo_disable_caching') && (is_page() || is_single())) {
define('DONOTCACHEPAGE', true);
}
}
/**
* Output excluded posts list.
*/
public function output_excluded_posts() {
$wpo_cache_excluded_posts = $this->get_excluded_posts();
WP_Optimize()->include_template('cache/page-cache-excluded-posts.php', false, array(
'wpo_cache_excluded_posts' => $wpo_cache_excluded_posts,
));
}
/**
* Output always purge posts section.
*/
public function output_always_purge_posts() {
$always_purge_post_type = isset($this->config['always_purge_post_type']) ? $this->config['always_purge_post_type'] : array();
$always_purge_post_id = isset($this->config['always_purge_post_id']) ? $this->config['always_purge_post_id'] : array();
$post_types = $this->get_post_types();
$always_purge_post_type_str = array();
foreach ($always_purge_post_type as $i => $post_type) {
$post_types_arr = explode(',', $post_type);
$post_types_str = '';
foreach ($post_types_arr as $single_pt) {
$single_pt = trim($single_pt);
$post_types_str .= ('' != $post_types_str) ? ', ' : '';
$post_types_str .= isset($post_types[$single_pt]) ? $post_types[$single_pt] : $single_pt;
}
$always_purge_post_type_str[$i] = $post_types_str;
}
WP_Optimize()->include_template('cache/page-cache-always-purge-posts.php', false, array(
'always_purge_post_type' => $always_purge_post_type,
'always_purge_post_type_str' => $always_purge_post_type_str,
'always_purge_post_id' => $always_purge_post_id,
'post_types' => $post_types,
));
}
/**
* Get list name => label with available public post types.
*/
private function get_post_types() {
$result = array();
$post_types = get_post_types(array('public' => true), 'objects');
foreach ($post_types as $post_type_obj) {
$result[$post_type_obj->name] = $post_type_obj->labels->singular_name;
}
return $result;
}
/**
* Get array with "always purge this page" settings.
*
* @return array
*/
public function get_always_purge_config() {
$always_purge_post_type = isset($this->config['always_purge_post_type']) ? $this->config['always_purge_post_type'] : array();
$always_purge_post_id = isset($this->config['always_purge_post_id']) ? $this->config['always_purge_post_id'] : array();
$result = array();
foreach ($always_purge_post_type as $i => $post_type) {
$result[] = array(
'post_id' => $always_purge_post_id[$i],
'post_type' => $post_type,
);
}
return $result;
}
/**
* Get always purge settings for selected post.
*
* @param int $post_id
*
* @return array
*/
public function get_always_purge_post_config($post_id) {
$always_purge_config = $this->get_always_purge_config();
$post_type = array();
foreach ($always_purge_config as $item) {
if ($post_id != $item['post_id']) continue;
$post_type = array_merge($post_type, explode(',', $item['post_type']));
}
return $post_type;
}
/**
* Handle post update and purge pages configured in "always purge this page" settings.
*/
public function always_purge_post_on_update($post_id) {
$post_type = get_post_type($post_id);
$post_type_object = get_post_type_object($post_type);
if ((defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) || 'revision' === $post_type || !$post_type_object->public) {
return;
}
$always_purge_config = $this->get_always_purge_config();
foreach ($always_purge_config as $item) {
$post_types = explode(',', $item['post_type']);
if (in_array($post_type, $post_types)) {
WPO_Page_Cache::delete_single_post_cache($item['post_id']);
}
}
}
/**
* Enqueue scripts and styles for premium cache features.
*/
public function enqueue_scripts_styles() {
$current_screen = get_current_screen();
if (null === $current_screen) return;
$enqueue_version = WP_Optimize()->get_enqueue_version();
$min_or_not = WP_Optimize()->get_min_or_not_string();
$min_or_not_internal = WP_Optimize()->get_min_or_not_internal_string();
// Only enqueue If the screen is the post edit page
if ('post' == $current_screen->base) {
if (!wp_script_is('select2')) {
wp_enqueue_script('select2', WPO_PLUGIN_URL . 'js/select2/select2' . $min_or_not . '.js', array('jquery'), $enqueue_version);
}
if (!wp_style_is('select2')) {
wp_enqueue_style('select2', WPO_PLUGIN_URL . 'css/select2/select2' . $min_or_not . '.css', array(), $enqueue_version);
}
wp_enqueue_script('wp-optimize-cache-premium-admin', WPO_PLUGIN_URL . 'js/wpo-cache-premium-edit-post' . $min_or_not_internal . '.js', array('wp-optimize-send-command', 'select2'), $enqueue_version);
}
if ('edit' === $current_screen->base) {
wp_enqueue_script('wp-optimize-cache-premium-admin-preload-purge', WPO_PLUGIN_URL . 'js/wpo-cache-premium-preload-purge' . $min_or_not_internal . '.js', array('jquery', 'block-ui-js', 'wp-optimize-send-command'), $enqueue_version);
wp_localize_script('wp-optimize-cache-premium-admin-preload-purge', 'wp_optimize_admin', array(
'purge' => __('Purge cache', 'wp-optimize'),
'preload' => __('Preload cache', 'wp-optimize'),
));
}
}
/**
* Adds scripts to WP-Optimize's dashboard only
*
* @param string $min_or_not_internal - The .min-version-number suffix to use on internal assets
* @param string $min_or_not - The .min suffix to use on third party assets
* @param string $enqueue_version - The enqueued version
* @return void
*/
public function wpo_page_only_scripts($min_or_not_internal, $min_or_not, $enqueue_version) {
wp_enqueue_script('wp-optimize-cache-premium', WPO_PLUGIN_URL . 'js/wpo-cache-premium' . $min_or_not_internal . '.js', array('wp-optimize-send-command'), $enqueue_version);
}
/**
* Add default values to use in cache extensions - filters the WPO config when updating it
*
* @param array $config - The original config array
* @return array
*/
public function add_default_values_to_cache_config($config) {
if (!isset($config['default_values'])) {
$config['default_values'] = array();
}
// Add WooCommerce's default currency
if (function_exists('get_woocommerce_currency')) {
/**
* Filters wether or not to add WooCommerce default currency to the cache config.
*/
if (apply_filters('wpo_add_woocommerce_default_currency_to_cache_config', true)) {
// Save the default WC currency in our config.
// Note: We use get_option('woocommerce_currency') as get_woocommerce_currency() is overridden by the currency selector plugin.
$config['default_values']['woocommerce_currency'] = get_option('woocommerce_currency');
}
}
// Set default woocommerce values
if (defined('WC_ABSPATH') && function_exists('WC')) {
$config['default_values']['WC_ABSPATH'] = wp_normalize_path(WC_ABSPATH);
// If cache per country is enabled
if (isset($config['enable_cache_per_country']) && $config['enable_cache_per_country']) {
$wc_get_base_location = wc_get_base_location();
$config['default_values']['wc_default_country'] = $wc_get_base_location['country'];
// Get Geolite database path
if (version_compare(WC()->version, '3.9.0', '>=')) {
$integrations = WC()->integrations;
if (is_callable(array($integrations, 'get_integration'))) {
$integration = $integrations->get_integration('maxmind_geolocation');
if (is_callable(array($integration, 'get_database_service'))) {
$database = $integration->get_database_service()->get_database_path();
}
}
} elseif (is_callable(array('WC_Geolocation', 'get_local_database_path'))) {
$database = WC_Geolocation::get_local_database_path();
}
// We need the database, WooCommerce 3.4+ and PHP 5.4+ to use Geolite2
$config['default_values']['wc_geolocate'] = isset($database) && file_exists($database) && version_compare(WC()->version, '3.4.0', '>=') && version_compare(PHP_VERSION, '5.4.0', '>=');
if (isset($database) && file_exists($database)) {
$config['default_values']['wc_geolocate_database'] = wp_normalize_path($database);
}
}
}
return $config;
}
/**
* Filter COOKIE variable names used for building cache file name.
*
* @param array $cookies - The array of cookies
* @param array $config - The cache configuration
*
* @return array
*/
public function add_cache_cookies($cookies, $config) {
// Aelia currency switcher
if (class_exists('WC_Aelia_CurrencySwitcher')) {
$aelia_cookies = array(
'aelia_cs_selected_currency',
'aelia_customer_country',
'aelia_customer_state',
'aelia_tax_exempt',
);
$cookies = array_merge($cookies, $aelia_cookies);
}
if (isset($config['enable_cache_per_country']) && $config['enable_cache_per_country']) {
$cookies[] = 'woocommerce_tax_country';
}
return array_merge($cookies, $this->get_curcy_cookies());
}
/**
* Filter GET query variable names used for building cache file name.
*
* @param array $variables - The array of query variables
* @param array $config - The cache configuration
*
* @return array
*/
public function add_cache_query_variables($variables, $config) {
// WPML multi currency plugin.
if (defined('WCML_VERSION')) {
$variables[] = 'wcmlc';
}
// check if active WPML plugin.
if (defined('ICL_SITEPRESS_VERSION')) {
$variables[] = 'lang';
}
// Aelia Currency switcher
if (class_exists('WC_Aelia_CurrencySwitcher')) {
$variables[] = 'aelia_cs_currency';
}
// WooCommerce geolocation - Selecting 'geolocation_ajax' in WC will add v=location-key to every request.
if ('geolocation_ajax' === get_option('woocommerce_default_customer_address') && isset($config['enable_cache_per_country']) && $config['enable_cache_per_country']) {
$variables[] = 'v';
}
if (class_exists('WOOMULTI_CURRENCY_F')) {
$variables[] = 'wmc-currency';
}
return $variables;
}
/**
* Include the extra template
*
* @param array $wpo_cache_options - The main page cache options
* @return void
*/
public function add_woocommerce_template_to_cache_settings($wpo_cache_options) {
// Load this if WooCommerce is loaded
if (!apply_filters('wpo_add_woocommerce_template_to_cache_settings', function_exists('WC'))) return;
WP_Optimize()->include_template('cache/page-cache-woocommerce.php', false, array('wpo_cache_options' => $wpo_cache_options));
}
/**
* Maybe sets a cookie with the user's tax country
*
* @return void
*/
public function maybe_set_tax_country_cookie() {
if ((defined('DOING_CRON') && DOING_CRON)
|| (is_admin() && (!defined('DOING_AJAX') || !DOING_AJAX))
|| (defined('XMLRPC_REQUEST') && XMLRPC_REQUEST)
) return;
if (!isset($this->config['enable_cache_per_country']) || !$this->config['enable_cache_per_country']) return;
// Override current value when a known $_REQUEST changes it in WC
if (isset($_POST['billing_country'])) {
// Value from WooCommerce form
setcookie('woocommerce_tax_country', $_POST['billing_country'], (time() + 30 * 86400), '/');
$_COOKIE['woocommerce_tax_country'] = $_POST['billing_country'];
return;
} elseif (isset($_REQUEST['wc_country_preselect'])) {
// Value from VAT compliance form
setcookie('woocommerce_tax_country', $_REQUEST['wc_country_preselect'], (time() + 30 * 86400), '/');
$_COOKIE['woocommerce_tax_country'] = $_REQUEST['wc_country_preselect'];
return;
}
$country = isset(WC()->customer) ? WC()->customer->get_billing_country() : '';
if (!$country) return;
// By default, set the country to WC()->customer->get_billing_country(), and override it if it was set to something else.
if (!isset($_COOKIE['woocommerce_tax_country'])) {
// $country if cookie was empty
setcookie('woocommerce_tax_country', $country, (time() + 30 * 86400), '/');
$_COOKIE['woocommerce_tax_country'] = $country;
} elseif ($_COOKIE['woocommerce_tax_country'] != $country) {
// Use $country if cookie was different than $country.
setcookie('woocommerce_tax_country', $country, (time() + 30 * 86400), '/');
$_COOKIE['woocommerce_tax_country'] = $country;
}
}
/**
* Show the cache status in a "post state" in the Posts list table.
*
* @param array $post_states
* @param object $post
* @return array
*/
public function add_post_state($post_states, $post) {
$do_not_cache = get_post_meta($post->ID, '_wpo_disable_caching', true);
if ($do_not_cache) $post_states['wpo-do-not-cache-state'] = __('Excluded from caching', 'wp-optimize');
return $post_states;
}
/**
* Add metaboxes for disable cache functionality on single post screen.
*/
public function add_cache_control_metabox() {
add_meta_box('wpo-cache-metabox', '<span title="'.__('by WP-Optimize', 'wp-optimize').'">'.__('Page caching', 'wp-optimize').'</span>', array($this, 'render_cache_control_metabox'), get_post_types(array('public' => true)), 'side');
}
/**
* Output metabox for disable cache functionality.
*
* @param WP_Post $post - post object that the current editing page is for
*/
public function render_cache_control_metabox($post) {
$post_id = $post->ID;
$meta_key = '_wpo_disable_caching';
$disable_caching = get_post_meta($post_id, $meta_key, true);
$post_type_obj = get_post_type_object(get_post_type($post_id));
$extract = array(
'disable_caching' => $disable_caching,
'post_id' => $post_id,
'post_type' => strtolower($post_type_obj->labels->singular_name),
'post_types' => $this->get_post_types(),
'always_purge_post_type' => $this->get_always_purge_post_config($post_id),
);
WP_Optimize()->include_template('cache/admin-metabox-cache-control.php', false, $extract);
}
/**
* Get list of excluded posts from cache.
*
* @return array
*/
public function get_excluded_posts() {
global $wpdb;
$excluded_posts = $wpdb->get_results("SELECT p.ID, p.post_title, p.post_type FROM {$wpdb->postmeta} pm JOIN {$wpdb->posts} p ON pm.post_id = p.ID WHERE pm.meta_key = '_wpo_disable_caching' AND p.post_status = 'publish' ORDER BY p.post_title;", ARRAY_A);
return $excluded_posts;
}
/**
* Output user specific cache option.
*/
public function output_user_specific_cache_option() {
global $is_nginx;
$extract = array(
'wpo_cache_options' => $this->config,
'is_nginx' => $is_nginx,
'path_to_cache' => defined('WPO_CACHE_DIR') ? str_replace(ABSPATH, '/', WPO_CACHE_DIR) : '/path/to/cache',
);
WP_Optimize()->include_template('cache/page-cache-user-specific-cache.php', false, $extract);
}
/**
* Output cache per role option.
*/
public function output_user_per_role_cache_option() {
if (!function_exists('get_editable_roles')) {
include_once ABSPATH . 'wp-admin/includes/user.php';
}
$user_roles = array();
$wp_roles = get_editable_roles();
foreach ($wp_roles as $role => $info) {
$user_roles[] = array(
'role' => $role,
'label' => translate_user_role($info['name']),
);
}
$extract = array(
'user_roles' => $user_roles,
'wpo_cache_options' => $this->config,
);
WP_Optimize()->include_template('cache/page-cache-per-role-cache.php', false, $extract);
}
/**
* Curcy cookies
*/
private function get_curcy_cookies() {
$cookies = array();
if (!class_exists('WOOMULTI_CURRENCY_F') || !class_exists('WOOMULTI_CURRENCY_F_Data')) return $cookies;
if (!is_callable(array('WOOMULTI_CURRENCY_F_Data', 'get_ins'))) {
error_log('WP-Optimize: Cache - WOOMULTI_CURRENCY_F_Data::get_ins() method not found');
return $cookies;
} else {
$curcy_settings = WOOMULTI_CURRENCY_F_Data::get_ins();
if (!is_callable(array($curcy_settings, 'get_params'))) {
error_log('WP-Optimize: Cache - WOOMULTI_CURRENCY_F_Data::get_params() method not found');
return $cookies;
} else {
if ($curcy_settings->get_params('use_session')) return $cookies;
$cookies[] = 'wmc_current_currency';
$cookies[] = 'wmc_current_currency_old';
if (!is_callable(array($curcy_settings, 'get_auto_detect'))) {
error_log('WP-Optimize: Cache - WOOMULTI_CURRENCY_F_Data::get_auto_detect() method not found');
return $cookies;
} else {
$auto_detect = $curcy_settings->get_auto_detect();
if (1 === $auto_detect || 2 === $auto_detect) {
$cookies[] = 'wmc_ip_info';
if (!is_callable(array($curcy_settings, 'get_geo_api'))) {
error_log('WP-Optimize: Cache - WOOMULTI_CURRENCY_F_Data::get_geo_api() method not found');
return $cookies;
} else {
if (2 !== $curcy_settings->get_geo_api()) {
$cookies[] = 'wmc_ip_add';
}
}
}
}
}
}
return $cookies;
}
}
endif;