wp-plugin-cloudflare-cache/libs/cache_controller.class.php

3374 lines
122 KiB
PHP
Raw Permalink Normal View History

2024-03-27 15:58:02 -04:00
<?php
defined( 'ABSPATH' ) || die( 'Cheatin&#8217; uh?' );
class SWCFPC_Cache_Controller
{
private $main_instance = null;
private $objects = false;
private $skip_cache = false;
private $purge_all_already_done = false;
private $cache_buster = 'swcfpc';
private $htaccess_path = '';
function __construct( $cache_buster, $main_instance )
{
$this->cache_buster = $cache_buster;
$this->main_instance = $main_instance;
if( !function_exists('get_home_path') )
require_once ABSPATH . 'wp-admin/includes/file.php';
$this->htaccess_path = get_home_path().'.htaccess';
$this->actions();
}
function actions() {
// Purge cache cronjob
add_action( 'swcfpc_cache_purge_cron', array($this, 'purge_cache_queue_job') );
add_filter( 'cron_schedules', array($this, 'purge_cache_queue_custom_interval') );
add_action( 'shutdown', array($this, 'purge_cache_queue_start_cronjob'), PHP_INT_MAX );
// SEO redirect for all URLs that for any reason have been indexed together with the cache buster
if( $this->main_instance->get_single_config('cf_seo_redirect', 1) > 0 ) {
add_action('init', array($this, 'redirect_301_real_url'), 0);
}
add_action( 'wp_footer', array($this, 'inject_cache_buster_js_code'), PHP_INT_MAX );
add_action( 'admin_footer', array($this, 'inject_cache_buster_js_code'), PHP_INT_MAX );
// Auto prefetch URLs
add_action( 'wp_footer', array($this, 'prefetch_urls'), PHP_INT_MAX );
// Ajax preloader start
add_action( 'wp_ajax_swcfpc_preloader_start', array($this, 'ajax_preloader_start') );
// Ajax unlock preloader
add_action( 'wp_ajax_swcfpc_preloader_unlock', array($this, 'ajax_preloader_unlock') );
// Ajax clear whole cache
add_action( 'wp_ajax_swcfpc_purge_whole_cache', array($this, 'ajax_purge_whole_cache') );
// Force purge everything
add_action( 'wp_ajax_swcfpc_purge_everything', array($this, 'ajax_purge_everything') );
// Ajax clear single post cache
add_action( 'wp_ajax_swcfpc_purge_single_post_cache', array($this, 'ajax_purge_single_post_cache') );
// Ajax reset all
add_action( 'wp_ajax_swcfpc_reset_all', array($this, 'ajax_reset_all') );
//add_action( 'init', array( $this, 'force_bypass_for_logged_in_users' ), PHP_INT_MAX );
// This sets response headers for backend
add_action( 'init', array($this, 'setup_response_headers_backend'), 0 );
// These set response headers for frontend
add_action( 'send_headers', array($this, 'bypass_cache_on_init'), PHP_INT_MAX );
add_action( 'template_redirect', array($this, 'apply_cache'), PHP_INT_MAX );
//add_filter( 'wp_headers', array($this, 'setup_response_headers_filter'), PHP_INT_MAX );
// Purge cache via cronjob
add_action( 'init', array($this, 'cronjob_purge_cache') );
// Start preloader via cronjob
add_action( 'init', array($this, 'cronjob_preloader') );
// W3TC actions
if( $this->main_instance->get_single_config('cf_w3tc_purge_on_flush_dbcache', 0) > 0 )
add_action( 'w3tc_flush_dbcache', array($this, 'w3tc_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_w3tc_purge_on_flush_all', 0) > 0 )
add_action( 'w3tc_flush_all', array($this, 'w3tc_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_w3tc_purge_on_flush_fragmentcache', 0) > 0 )
add_action( 'w3tc_flush_fragmentcache', array($this, 'w3tc_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_w3tc_purge_on_flush_objectcache', 0) > 0 )
add_action( 'w3tc_flush_objectcache', array($this, 'w3tc_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_w3tc_purge_on_flush_posts', 0) > 0 )
add_action( 'w3tc_flush_posts', array($this, 'w3tc_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_w3tc_purge_on_flush_posts', 0) > 0 )
add_action( 'w3tc_flush_post', array($this, 'w3tc_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_w3tc_purge_on_flush_minfy', 0) > 0 )
add_action( 'w3tc_flush_minify', array($this, 'w3tc_hooks'), PHP_INT_MAX );
// WP-Optimize actions
if( $this->main_instance->get_single_config('cf_wp_optimize_purge_on_cache_flush', 0) > 0 )
add_action( 'wpo_cache_flush', array($this, 'wpo_hooks'), PHP_INT_MAX );
// WP Performance actions
if( $this->main_instance->get_single_config('cf_wp_performance_purge_on_cache_flush', 0) > 0 )
add_action( 'wpp-after-cache-delete', array($this, 'wp_performance_hooks'), PHP_INT_MAX );
// WP Rocket actions
if( $this->main_instance->get_single_config('cf_wp_rocket_purge_on_post_flush', 0) > 0 )
add_action( 'after_rocket_clean_post', array($this, 'wp_rocket_after_rocket_clean_post_hook'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_wp_rocket_purge_on_domain_flush', 0) > 0 )
add_action( 'after_rocket_clean_domain', array($this, 'wp_rocket_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_wp_rocket_purge_on_cache_dir_flush', 0) > 0 )
add_action( 'rocket_after_automatic_cache_purge_dir', array($this, 'wp_rocket_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_wp_rocket_purge_on_clean_files', 0) > 0 )
add_action( 'after_rocket_clean_files', array($this, 'wp_rocket_selective_url_purge_hooks'), PHP_INT_MAX, 1 );
if( $this->main_instance->get_single_config('cf_wp_rocket_purge_on_clean_cache_busting', 0) > 0 )
add_action( 'after_rocket_clean_cache_busting', array($this, 'wp_rocket_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_wp_rocket_purge_on_clean_minify', 0) > 0 )
add_action( 'after_rocket_clean_minify', array($this, 'wp_rocket_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_wp_rocket_purge_on_ccss_generation_complete', 0) > 0 )
add_action( 'rocket_critical_css_generation_process_complete', array($this, 'wp_rocket_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_wp_rocket_purge_on_rucss_job_complete', 0) > 0 )
add_action( 'rocket_rucss_complete_job_status', array($this, 'wp_rocket_selective_url_purge_hooks'), PHP_INT_MAX, 1 );
if( $this->main_instance->get_single_config('cf_wp_rocket_disable_cache', 0) > 0 )
add_action( 'admin_init', array($this, 'wp_rocket_disable_page_cache'), PHP_INT_MAX );
// LiteSpeed actions
if( $this->main_instance->get_single_config('cf_litespeed_purge_on_cache_flush', 0) > 0 )
add_action( 'litespeed_purged_all', array($this, 'litespeed_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_litespeed_purge_on_ccss_flush', 0) > 0 )
add_action( 'litespeed_purged_all_ccss', array($this, 'litespeed_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_litespeed_purge_on_cssjs_flush', 0) > 0 )
add_action( 'litespeed_purged_all_cssjs', array($this, 'litespeed_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_litespeed_purge_on_object_cache_flush', 0) > 0 )
add_action( 'litespeed_purged_all_object', array($this, 'litespeed_hooks'), PHP_INT_MAX );
if( $this->main_instance->get_single_config('cf_litespeed_purge_on_single_post_flush', 0) > 0 )
add_action( 'litespeed_api_purge_post', array($this, 'litespeed_single_post_hooks'), PHP_INT_MAX, 1 );
// Hummingbird actions
if( $this->main_instance->get_single_config('cf_hummingbird_purge_on_cache_flush', 0) > 0 )
add_action( 'wphb_clear_cache_url', array($this, 'hummingbird_hooks'), PHP_INT_MAX );
// Woocommerce actions
if( $this->main_instance->get_single_config('cf_auto_purge_woo_product_page', 0) > 0 )
add_action( 'woocommerce_updated_product_stock', array($this, 'woocommerce_purge_product_page_on_stock_change'), PHP_INT_MAX, 1 );
// Woocommerce scheduled sales
if( $this->main_instance->get_single_config('cf_auto_purge_woo_scheduled_sales', 0) > 0 ) {
add_action('wc_after_products_starting_sales', array($this, 'woocommerce_purge_scheduled_sales'), PHP_INT_MAX);
add_action('wc_after_products_ending_sales', array($this, 'woocommerce_purge_scheduled_sales'), PHP_INT_MAX);
}
// Swift Performance (Lite/Pro) actions
if( $this->main_instance->get_single_config('cf_spl_purge_on_flush_all', 0) > 0 ) {
add_action('swift_performance_after_clear_all_cache', array($this, 'spl_purge_all'), PHP_INT_MAX);
add_action('swift_performance_after_clear_expired_cache', array($this, 'spl_purge_all'), PHP_INT_MAX);
add_action('swift_performance_after_clear_post_cache', array($this, 'spl_purge_single_post'), PHP_INT_MAX);
}
// Edd actions
if( $this->main_instance->get_single_config('cf_auto_purge_edd_payment_add', 0) > 0 )
add_action( 'edd_built_order', array($this, 'edd_purge_cache_on_payment_add'), PHP_INT_MAX );
// Nginx Helper actions
if( $this->main_instance->get_single_config('cf_nginx_helper_purge_on_cache_flush', 0) > 0 ) {
add_action('rt_nginx_helper_after_fastcgi_purge_all', array($this, 'nginx_helper_purge_all_hooks'), PHP_INT_MAX);
add_action('rt_nginx_helper_fastcgi_purge_url_base', array($this, 'nginx_helper_purge_single_url_hooks'), PHP_INT_MAX, 1);
}
// YASR actions
if( $this->main_instance->get_single_config('cf_yasr_purge_on_rating', 0) > 0 ) {
add_action('yasr_action_on_overall_rating', array($this, 'yasr_hooks'), PHP_INT_MAX, 1);
add_action('yasr_action_on_visitor_vote', array($this, 'yasr_hooks'), PHP_INT_MAX, 1);
add_action('yasr_action_on_visitor_multiset_vote', array($this, 'yasr_hooks'), PHP_INT_MAX, 1);
}
// WP Asset Clean Up actions
if( $this->main_instance->get_single_config('cf_wpacu_purge_on_cache_flush', 0) > 0 )
add_action( 'wpacu_clear_cache_after', array($this, 'wpacu_hooks'), PHP_INT_MAX );
// Flying Press actions
if( $this->main_instance->get_single_config('cf_flypress_purge_on_cache_flush', 0) > 0 ) {
add_action( 'flying_press_purge_pages:after', array($this, 'flying_press_hook'), PHP_INT_MAX );
add_action( 'flying_press_purge_everything:after', array($this, 'flying_press_hook'), PHP_INT_MAX );
}
// Autoptimize actions
if( $this->main_instance->get_single_config('cf_autoptimize_purge_on_cache_flush', 0) > 0 )
add_action( 'autoptimize_action_cachepurged', array($this, 'autoptimize_hooks'), PHP_INT_MAX );
// Purge when upgrader process is complete
if( $this->main_instance->get_single_config('cf_auto_purge_on_upgrader_process_complete', 0) > 0 )
add_action( 'upgrader_process_complete', array($this, 'purge_on_plugin_update'), PHP_INT_MAX );
// Bypass WP JSON REST
if( $this->main_instance->get_single_config('cf_bypass_wp_json_rest', 0) > 0 )
add_filter( 'rest_send_nocache_headers', '__return_true' );
// Purge cache on comments
add_action( 'transition_comment_status', array($this, 'purge_cache_when_comment_is_approved'), PHP_INT_MAX, 3 );
add_action( 'comment_post', array($this, 'purge_cache_when_new_comment_is_added'), PHP_INT_MAX, 3 );
add_action( 'delete_comment', array($this, 'purge_cache_when_comment_is_deleted'), PHP_INT_MAX );
// Programmatically purge the cache via action
add_action( 'swcfpc_purge_cache', array($this, 'purge_cache_programmatically'), PHP_INT_MAX, 1 );
// Elementor AJAX update
//add_action('elementor/ajax/register_actions', array($this, 'purge_cache_on_elementor_ajax_update'));
$purge_actions = array(
'wp_update_nav_menu', // When a custom menu is updated
'update_option_theme_mods_' . get_option( 'stylesheet' ), // When any theme modifications are updated
'avada_clear_dynamic_css_cache', // When Avada theme purge its own cache
'switch_theme', // When user changes the theme
'customize_save_after', // Edit theme
'permalink_structure_changed', // When permalink structure is update
);
foreach ($purge_actions as $action) {
add_action( $action, array($this, 'purge_cache_on_theme_edit'), PHP_INT_MAX );
}
$purge_actions = array(
'deleted_post', // Delete a post
'wp_trash_post', // Before a post is sent to the Trash
'clean_post_cache', // After a posts cache is cleaned
'edit_post', // Edit a post - includes leaving comments
'delete_attachment', // Delete an attachment - includes re-uploading
'elementor/editor/after_save', // Elementor edit
'elementor/core/files/clear_cache', // Elementor clear cache
);
foreach ($purge_actions as $action) {
add_action( $action, array($this, 'purge_cache_on_post_edit'), PHP_INT_MAX, 2 );
}
add_action( 'transition_post_status', array($this, 'purge_cache_when_post_is_published'), PHP_INT_MAX, 3 );
// Metabox
if( $this->main_instance->get_single_config('cf_disable_single_metabox', 0) == 0 ) {
add_action('add_meta_boxes', array($this, 'add_metaboxes'), PHP_INT_MAX);
add_action('save_post', array($this, 'swcfpc_cache_mbox_save_values'), PHP_INT_MAX);
}
// Ajax enable page cache
add_action( 'wp_ajax_swcfpc_enable_page_cache', array($this, 'ajax_enable_page_cache') );
// Ajax disable page cache
add_action( 'wp_ajax_swcfpc_disable_page_cache', array($this, 'ajax_disable_page_cache') );
// Add wp_redirect filter to adding cache buster for logged in users
add_filter( 'wp_redirect', array($this, 'wp_redirect_filter'), PHP_INT_MAX, 2 );
}
function wp_rocket_disable_page_cache() {
// Disable page caching in WP Rocket
if( $this->is_cache_enabled() ) {
// Prevent WP Rocket from writing to the advanced-cache.php file
add_filter( 'rocket_generate_advanced_cache_file', '__return_false', PHP_INT_MAX );
// Disable WP Rocket mandatory cookies
add_filter( 'rocket_cache_mandatory_cookies', '__return_empty_array', PHP_INT_MAX );
// Prevent WP Rocket from changing the WP_CACHE constant
add_filter( 'rocket_set_wp_cache_constant', '__return_false', PHP_INT_MAX );
// Prevent WP Rocket from writing to the htaccess file
add_filter( 'rocket_disable_htaccess', '__return_false', PHP_INT_MAX );
// Disable other WP Rocket stuffs that are not needed and handelled by this plugin
add_filter( 'rocket_display_input_varnish_auto_purge', '__return_false', PHP_INT_MAX );
add_filter( 'do_rocket_generate_caching_files', '__return_false', PHP_INT_MAX );
}
}
function get_cache_buster() {
return $this->cache_buster;
}
function add_metaboxes() {
$allowed_post_types = apply_filters( 'swcfpc_bypass_cache_metabox_post_types', [ 'post', 'page' ] );
add_meta_box(
'swcfpc_cache_mbox',
__('Cloudflare Page Cache Settings', 'wp-cloudflare-page-cache'),
array($this, 'swcfpc_cache_mbox_callback'),
$allowed_post_types,
'side'
);
}
function swcfpc_cache_mbox_callback($post) {
$bypass_cache = (int) get_post_meta( $post->ID, 'swcfpc_bypass_cache', true );
?>
<label for="swcfpc_bypass_cache"><?php _e('Bypass the cache for this page', 'wp-cloudflare-page-cache'); ?></label>
<select name="swcfpc_bypass_cache">
<option value="0" <?php if($bypass_cache == 0) echo 'selected'; ?>><?php _e('No', 'wp-cloudflare-page-cache'); ?></option>
<option value="1" <?php if($bypass_cache == 1) echo 'selected'; ?>><?php _e('Yes', 'wp-cloudflare-page-cache'); ?></option>
</select>
<?php
}
function swcfpc_cache_mbox_save_values($post_id) {
if( array_key_exists('swcfpc_bypass_cache', $_POST) ) {
update_post_meta( $post_id, 'swcfpc_bypass_cache', $_POST['swcfpc_bypass_cache'] );
}
}
/*
function force_bypass_for_logged_in_users() {
if( !function_exists('is_user_logged_in') ) {
include_once( ABSPATH . 'wp-includes/pluggable.php' );
}
if ( is_user_logged_in() && $this->is_cache_enabled() ) {
add_action( 'wp_footer', array( $this, 'inject_cache_buster_js_code' ), 100 );
add_action( 'admin_footer', array( $this, 'inject_cache_buster_js_code' ), 100 );
}
}
*/
function redirect_301_real_url() {
// For non logged-in users, only redirect when the request URL is not from a CRON job
if( !is_user_logged_in() && ( isset($_GET['swcfpc-preloader']) || isset($_GET['swcfpc-purge-all']) ) ) return;
// For non CRON job URLs, we will redirect
if( !is_user_logged_in() && !empty( $_SERVER['QUERY_STRING'] ) ) {
if( strlen( $_SERVER['QUERY_STRING'] ) > 0 && strpos( $_SERVER['QUERY_STRING'], $this->get_cache_buster() ) !== false ) {
// Build the full URL
$parts = parse_url( home_url() );
$current_uri = "{$parts['scheme']}://{$parts['host']}" . add_query_arg(NULL, NULL);
// Strip out the cache buster
$parsed = parse_url($current_uri);
$query_string = $parsed['query'];
parse_str($query_string, $params);
unset($params[ $this->get_cache_buster() ]);
$query_string = http_build_query($params);
// Rebuild the full URL without the cache buster
$current_uri = "{$parts['scheme']}://{$parts['host']}";
if( isset($parsed['path']) )
$current_uri .= $parsed['path'];
if( strlen($query_string) > 0 )
$current_uri .= "?{$query_string}";
// SEO redirect
wp_redirect( $current_uri, 301 );
die();
}
}
}
function setup_response_headers_filter( $headers ) {
if( !isset($headers['X-WP-CF-Super-Cache']) ) {
$this->objects = $this->main_instance->get_objects();
if( ! $this->is_cache_enabled() ) {
$this->objects['fallback_cache']->fallback_cache_disable();
$this->objects['html_cache']->do_not_cache_current_page();
$headers['X-WP-CF-Super-Cache'] = 'disabled';
}
else if( $this->is_url_to_bypass() || $this->can_i_bypass_cache() ) {
$this->objects['fallback_cache']->fallback_cache_disable();
$this->objects['html_cache']->do_not_cache_current_page();
$headers['Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
$headers['X-WP-CF-Super-Cache-Cache-Control'] = 'no-store, no-cache, must-revalidate, max-age=0';
$headers['X-WP-CF-Super-Cache'] = 'no-cache';
$headers['Pragma'] = 'no-cache';
$headers['Expires'] = gmdate('D, d M Y H:i:s \G\M\T', time());
}
else {
$this->objects['fallback_cache']->fallback_cache_enable();
$this->objects['html_cache']->cache_current_page();
$headers['Cache-Control'] = $this->get_cache_control_value(); // Used by Cloudflare
$headers['X-WP-CF-Super-Cache-Cache-Control'] = $this->get_cache_control_value(); // Used by all
$headers['X-WP-CF-Super-Cache-Cookies-Bypass'] = $this->get_cookies_to_bypass_in_worker_mode(); // Used by CF worker
$headers['X-WP-CF-Super-Cache-Active'] = '1'; // Used by CF worker
$headers['X-WP-CF-Super-Cache'] = 'cache';
}
}
return $headers;
}
function setup_response_headers_backend() {
$this->objects = $this->main_instance->get_objects();
if( is_admin() ) {
$this->objects['fallback_cache']->fallback_cache_disable();
$this->objects['html_cache']->do_not_cache_current_page();
if( ! $this->is_cache_enabled() ) {
add_filter('nocache_headers', function() {
return array(
'X-WP-CF-Super-Cache' => 'disabled'
);
}, PHP_INT_MAX);
}
else {
add_filter('nocache_headers', function () {
return array(
'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0',
'X-WP-CF-Super-Cache-Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0',
'X-WP-CF-Super-Cache' => 'no-cache',
'Pragma' => 'no-cache',
'Expires' => gmdate('D, d M Y H:i:s \G\M\T', time())
);
}, PHP_INT_MAX);
}
return;
}
if( ! $this->is_cache_enabled() ) {
$this->objects['fallback_cache']->fallback_cache_disable();
$this->objects['html_cache']->do_not_cache_current_page();
add_filter('nocache_headers', function() {
return array(
'X-WP-CF-Super-Cache' => 'disabled'
);
}, PHP_INT_MAX);
}
else if( $this->is_url_to_bypass() || $this->can_i_bypass_cache() ) {
$this->objects['fallback_cache']->fallback_cache_disable();
$this->objects['html_cache']->do_not_cache_current_page();
add_filter('nocache_headers', function() {
return array(
'Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0',
'X-WP-CF-Super-Cache-Cache-Control' => 'no-store, no-cache, must-revalidate, max-age=0',
'X-WP-CF-Super-Cache' => 'no-cache',
'Pragma' => 'no-cache',
'Expires' => gmdate('D, d M Y H:i:s \G\M\T', time())
);
}, PHP_INT_MAX);
}
else {
$this->objects['fallback_cache']->fallback_cache_enable();
$this->objects['html_cache']->cache_current_page();
add_filter('nocache_headers', function() {
return array(
'Cache-Control' => $this->get_cache_control_value(), // Used by Cloudflare
'X-WP-CF-Super-Cache-Cache-Control' => $this->get_cache_control_value(), // Used by all
'X-WP-CF-Super-Cache-Cookies-Bypass' => $this->get_cookies_to_bypass_in_worker_mode(), // Used by CF worker
'X-WP-CF-Super-Cache-Active' => '1', // Used by CF Worker
'X-WP-CF-Super-Cache' => 'cache'
);
}, PHP_INT_MAX);
}
}
function bypass_cache_on_init() {
if( is_admin() )
return;
$this->objects = $this->main_instance->get_objects();
if( ! $this->is_cache_enabled() ) {
header('X-WP-CF-Super-Cache: disabled');
$this->objects['fallback_cache']->fallback_cache_disable();
$this->objects['html_cache']->do_not_cache_current_page();
return;
}
if( $this->skip_cache )
return;
header_remove('Pragma');
header_remove('Expires');
header_remove('Cache-Control');
if( $this->is_url_to_bypass() ) {
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time()));
header('X-WP-CF-Super-Cache: no-cache');
header('X-WP-CF-Super-Cache-Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
$this->skip_cache = true;
$this->objects['fallback_cache']->fallback_cache_disable();
$this->objects['html_cache']->do_not_cache_current_page();
return;
}
if( $this->is_cache_enabled() ) {
$this->objects['fallback_cache']->fallback_cache_enable();
$this->objects['html_cache']->cache_current_page();
}
}
function apply_cache() {
if( is_admin() )
return;
$this->objects = $this->main_instance->get_objects();
if( ! $this->is_cache_enabled() ) {
header('X-WP-CF-Super-Cache: disabled');
header('X-WP-CF-Super-Cache-Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
$this->objects['fallback_cache']->fallback_cache_disable();
$this->objects['html_cache']->do_not_cache_current_page();
return;
}
if( $this->skip_cache ) {
return;
}
if ( $this->can_i_bypass_cache() ) {
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
header('Pragma: no-cache');
header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time()));
header('X-WP-CF-Super-Cache: no-cache');
header('X-WP-CF-Super-Cache-Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
$this->objects['fallback_cache']->fallback_cache_disable();
$this->objects['html_cache']->do_not_cache_current_page();
return;
}
if( $this->main_instance->get_single_config('cf_strip_cookies', 0) > 0 ) {
header_remove('Set-Cookie');
}
header_remove('Pragma');
header_remove('Expires');
header_remove('Cache-Control');
header('Cache-Control: '.$this->get_cache_control_value());
header('X-WP-CF-Super-Cache: cache');
header('X-WP-CF-Super-Cache-Active: 1');
header('X-WP-CF-Super-Cache-Cache-Control: '.$this->get_cache_control_value());
header('X-WP-CF-Super-Cache-Cookies-Bypass: '.$this->get_cookies_to_bypass_in_worker_mode());
if( $this->is_cache_enabled() ) {
$this->objects['fallback_cache']->fallback_cache_enable();
$this->objects['html_cache']->cache_current_page();
}
}
function purge_all($disable_preloader=false, $queue_mode=true, $force_purge_everything=false) {
$this->objects = $this->main_instance->get_objects();
$error = '';
if( $queue_mode && $this->main_instance->get_single_config('cf_disable_cache_purging_queue', 0) == 0 ) {
$this->purge_cache_queue_write(array(), true);
}
else {
// Avoid to send multiple purge requests for the same session
if( $this->purge_all_already_done )
return true;
if( $force_purge_everything == false && $this->main_instance->get_single_config('cf_purge_only_html', 0) > 0 ) {
$timestamp = time();
$cached_html_pages = $this->objects['html_cache']->get_cached_urls_by_timestamp($timestamp);
if( is_array($cached_html_pages) ) {
$cached_html_pages_count = count($cached_html_pages);
if ($cached_html_pages_count > 0) {
$this->objects['html_cache']->delete_cached_urls_by_timestamp($timestamp);
if (!$this->objects['cloudflare']->purge_cache_urls($cached_html_pages, $error)) {
$this->objects['logs']->add_log('cache_controller::purge_all', "Unable to purge some URLs from Cloudflare due to error: {$error}");
return false;
}
}
else {
$this->objects['logs']->add_log('cache_controller::purge_all', 'There are no HTML pages to purge');
}
}
}
else {
if (!$this->objects['cloudflare']->purge_cache($error)) {
$this->objects['logs']->add_log('cache_controller::purge_all', "Unable to purge the whole Cloudflare cache due to error: {$error}");
return false;
}
if( $this->main_instance->get_single_config('cf_purge_only_html', 0) > 0 )
$this->objects['html_cache']->delete_all_cached_urls();
}
if ($this->main_instance->get_single_config('cf_varnish_support', 0) > 0 && $this->main_instance->get_single_config('cf_varnish_auto_purge', 0) > 0)
$this->objects['varnish']->purge_whole_cache($error);
if ($this->main_instance->get_single_config('cf_fallback_cache', 0) > 0 && $this->main_instance->get_single_config('cf_fallback_cache_auto_purge', 0) > 0)
$this->objects['fallback_cache']->fallback_cache_purge_all();
if ($this->main_instance->get_single_config('cf_opcache_purge_on_flush', 0) > 0)
$this->purge_opcache();
if ($this->main_instance->get_single_config('cf_object_cache_purge_on_flush', 0) > 0)
$this->purge_object_cache();
if ($this->main_instance->get_single_config('cf_wpengine_purge_on_flush', 0) > 0)
$this->purge_wpengine_cache();
if ($this->main_instance->get_single_config('cf_spinupwp_purge_on_flush', 0) > 0)
$this->purge_spinupwp_cache();
if ($this->main_instance->get_single_config('cf_kinsta_purge_on_flush', 0) > 0)
$this->purge_kinsta_cache();
if ($this->main_instance->get_single_config('cf_siteground_purge_on_flush', 0) > 0)
$this->purge_siteground_cache();
if( $this->main_instance->get_single_config('cf_purge_only_html', 0) == 0 || $force_purge_everything == true )
$this->objects['logs']->add_log('cache_controller::purge_all', 'Purged whole Cloudflare cache');
else {
if( !is_array($cached_html_pages) || !$cached_html_pages_count )
$this->objects['logs']->add_log('cache_controller::purge_all', 'There are no HTML pages to purge');
else {
if( $this->objects['logs']->get_verbosity() == SWCFPC_LOGS_HIGH_VERBOSITY ) {
$this->objects['logs']->add_log('cache_controller::purge_all', "Purged only {$cached_html_pages_count} HTML pages from Cloudflare");
$this->objects['logs']->add_log('cache_controller::purge_all', 'Pages purged ' . print_r($cached_html_pages, true));
}
else {
$this->objects['logs']->add_log('cache_controller::purge_all', "Purged only {$cached_html_pages_count} HTML pages from Cloudflare");
}
}
}
if ($disable_preloader === false && $this->main_instance->get_single_config('cf_preloader', 1) > 0 && $this->main_instance->get_single_config('cf_preloader_start_on_purge', 0) > 0) {
$this->start_preloader_for_all_urls();
}
do_action('swcfpc_purge_all');
// Reset timestamp for Auto prefetch URLs in viewport option
if( $this->main_instance->get_single_config('cf_prefetch_urls_viewport', 0) > 0 )
$this->generate_new_prefetch_urls_timestamp();
$this->purge_all_already_done = true;
}
return true;
}
function purge_urls( $urls, $queue_mode=true ) {
if( !is_array($urls) )
return false;
$this->objects = $this->main_instance->get_objects();
$error = '';
// Strip out external links or invalid URLs
foreach( $urls as $array_index => $single_url ) {
if( $this->is_external_link($single_url) || substr( strtolower($single_url), 0, 4) != 'http' )
unset($urls[$array_index]);
}
if( $queue_mode && $this->main_instance->get_single_config('cf_disable_cache_purging_queue', 0) == 0 ) {
$this->purge_cache_queue_write( $urls );
}
else {
$count_urls = count( $urls );
if (!$this->objects['cloudflare']->purge_cache_urls($urls, $error)) {
$this->objects['logs']->add_log('cache_controller::purge_urls', "Unable to purge some URLs from Cloudflare due to error: {$error}");
return false;
}
if ($this->main_instance->get_single_config('cf_varnish_support', 0) > 0 && $this->main_instance->get_single_config('cf_varnish_auto_purge', 0) > 0)
$this->objects['varnish']->purge_urls($urls);
if ($this->main_instance->get_single_config('cf_fallback_cache', 0) > 0 && $this->main_instance->get_single_config('cf_fallback_cache_auto_purge', 0) > 0)
$this->objects['fallback_cache']->fallback_cache_purge_urls($urls);
if ($this->main_instance->get_single_config('cf_purge_only_html', 0) > 0 )
$this->objects['html_cache']->delete_cached_urls_by_urls_list($urls);
if ($this->main_instance->get_single_config('cf_opcache_purge_on_flush', 0) > 0)
$this->purge_opcache();
if ($this->main_instance->get_single_config('cf_object_cache_purge_on_flush', 0) > 0)
$this->purge_object_cache();
if ($this->main_instance->get_single_config('cf_wpengine_purge_on_flush', 0) > 0)
$this->purge_wpengine_cache();
if ($this->main_instance->get_single_config('cf_spinupwp_purge_on_flush', 0) > 0) {
if( $count_urls > 1 )
$this->purge_spinupwp_cache();
else
$this->purge_spinupwp_cache_single_url($urls[0]);
}
if ($this->main_instance->get_single_config('cf_kinsta_purge_on_flush', 0) > 0) {
if( $count_urls > 1 )
$this->purge_kinsta_cache();
else
$this->purge_kinsta_cache_single_url($urls[0]);
}
if ($this->main_instance->get_single_config('cf_siteground_purge_on_flush', 0) > 0)
$this->purge_siteground_cache();
if ($this->main_instance->get_single_config('cf_preloader', 1) > 0 && $this->main_instance->get_single_config('cf_preloader_start_on_purge', 0) > 0)
$this->start_cache_preloader_for_specific_urls($urls);
//$this->unlock_cache_purge();
$this->objects['logs']->add_log('cache_controller::purge_urls', 'Purged specific URLs from Cloudflare cache');
do_action('swcfpc_purge_urls', $urls);
// Reset timestamp for Auto prefetch URLs in viewport option
if( $this->main_instance->get_single_config('cf_prefetch_urls_viewport', 0) > 0 )
$this->generate_new_prefetch_urls_timestamp();
}
return true;
}
function cronjob_purge_cache() {
if( $this->is_cache_enabled() && isset($_GET[$this->cache_buster]) && isset($_GET['swcfpc-purge-all']) && $_GET['swcfpc-sec-key'] == $this->main_instance->get_single_config('cf_purge_url_secret_key', wp_generate_password(20, false, false)) ) {
$this->objects = $this->main_instance->get_objects();
$this->purge_all(false, false);
$this->objects['logs']->add_log('cache_controller::cronjob_purge_cache', 'Cache purging complete' );
if ( ! headers_sent() ) {
nocache_headers();
}
die('Cache purged');
}
}
function cronjob_preloader() {
if( isset($_GET[$this->cache_buster]) && isset($_GET['swcfpc-preloader']) && $_GET['swcfpc-sec-key'] == $this->main_instance->get_single_config('cf_preloader_url_secret_key', wp_generate_password(20, false, false)) && $this->main_instance->get_single_config('cf_preloader', 1) > 0 ) {
$this->start_preloader_for_all_urls();
$this->objects = $this->main_instance->get_objects();
$this->objects['logs']->add_log('cache_controller::cronjob_preloader', 'Preloader started' );
if ( ! headers_sent() ) {
nocache_headers();
}
die('Preloader started');
}
}
function purge_cache_when_comment_is_approved($new_status, $old_status, $comment) {
if( $this->main_instance->get_single_config('cf_auto_purge_on_comments', 0) > 0 && $this->is_cache_enabled() ) {
if ($old_status != $new_status && $new_status == 'approved') {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$urls = array();
$urls[] = get_permalink($comment->comment_post_ID);
$this->purge_urls( $urls );
$this->objects['logs']->add_log('cache_controller::purge_cache_when_comment_is_approved', "Purge Cloudflare cache for only post {$comment->comment_post_ID} - Fired action: {$current_action}" );
}
}
}
function purge_cache_when_new_comment_is_added( $comment_ID, $comment_approved, $commentdata ) {
if( $this->main_instance->get_single_config('cf_auto_purge_on_comments', 0) > 0 && $this->is_cache_enabled() ) {
if (isset($commentdata['comment_post_ID'])) {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$error = '';
$urls = array();
$urls[] = get_permalink($commentdata['comment_post_ID']);
$this->purge_urls( $urls );
$this->objects['logs']->add_log('cache_controller::purge_cache_when_new_comment_is_added', "Purge Cloudflare cache for only post {$commentdata['comment_post_ID']} - Fired action: {$current_action}" );
}
}
}
function purge_cache_when_comment_is_deleted( $comment_ID ) {
if( $this->main_instance->get_single_config('cf_auto_purge_on_comments', 0) > 0 && $this->is_cache_enabled() ) {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$urls = array();
$comment = get_comment( $comment_ID );
$urls[] = get_permalink($comment->comment_post_ID);
$this->purge_urls( $urls );
$this->objects['logs']->add_log('cache_controller::purge_cache_when_comment_is_deleted', "Purge Cloudflare cache for only post {$comment->comment_post_ID} - Fired action: {$current_action}" );
}
}
function purge_cache_when_post_is_published( $new_status, $old_status, $post ) {
if( ($this->main_instance->get_single_config('cf_auto_purge', 0) > 0 || $this->main_instance->get_single_config('cf_auto_purge_all', 0) > 0) && $this->is_cache_enabled() ) {
if ( in_array( $old_status, [ 'future', 'draft', 'pending' ] ) && in_array( $new_status, [ 'publish', 'private' ] ) ) {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
if ($this->main_instance->get_single_config('cf_auto_purge_all', 0) > 0) {
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::purge_cache_when_post_is_published', "Purge whole Cloudflare cache (fired action: {$current_action}");
} else {
$urls = $this->get_post_related_links($post->ID);
$this->purge_urls($urls);
$this->objects['logs']->add_log('cache_controller::purge_cache_when_post_is_published', "Purge Cloudflare cache for only post id {$post->ID} and related contents - Fired action: {$current_action}");
}
}
}
}
function purge_cache_on_post_edit( $postId ) {
static $done = [];
if( isset( $done[ $postId ] ) ) {
return;
}
// Do not run this on the WordPress Nav Menu Pages
global $pagenow;
if ( $pagenow === 'nav-menus.php' ) return;
if( ($this->main_instance->get_single_config('cf_auto_purge', 0) > 0 || $this->main_instance->get_single_config('cf_auto_purge_all', 0) > 0) && $this->is_cache_enabled() ) {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$error = '';
$validPostStatus = [ 'publish', 'trash', 'private' ];
$thisPostStatus = get_post_status($postId);
if (get_permalink($postId) != true || !in_array($thisPostStatus, $validPostStatus)) {
return;
}
if (is_int(wp_is_post_autosave($postId)) || is_int(wp_is_post_revision($postId))) {
return;
}
if ($this->main_instance->get_single_config('cf_auto_purge_all', 0) > 0) {
$this->purge_all();
return;
}
$savedPost = get_post($postId);
if (is_a($savedPost, 'WP_Post') == false) {
return;
}
$urls = $this->get_post_related_links($postId);
$this->purge_urls($urls);
$this->objects['logs']->add_log('cache_controller::purge_cache_on_post_edit', "Purge Cloudflare cache for only post id {$postId} and related contents - Fired action: {$current_action}");
$done[ $postId ] = true;
}
}
function purge_cache_on_theme_edit() {
if( ($this->main_instance->get_single_config('cf_auto_purge', 0) > 0 || $this->main_instance->get_single_config('cf_auto_purge_all', 0) > 0) && $this->is_cache_enabled() ) {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::purge_cache_on_theme_edit', "Purge whole Cloudflare cache - Fired action: {$current_action}" );
}
}
function get_post_related_links($postId) {
$this->objects = $this->main_instance->get_objects();
$listofurls = apply_filters( 'swcfpc_post_related_url_init', __return_empty_array(), $postId );
$postType = get_post_type($postId);
// Post URL
array_push($listofurls, get_permalink($postId));
//Purge taxonomies terms URLs
$postTypeTaxonomies = get_object_taxonomies($postType);
foreach ($postTypeTaxonomies as $taxonomy) {
if( is_object($taxonomy) && ($taxonomy->public == false || $taxonomy->rewrite == false) ) {
continue;
}
$terms = get_the_terms($postId, $taxonomy);
if (empty($terms) || is_wp_error($terms)) {
continue;
}
foreach ($terms as $term) {
$termLink = get_term_link($term);
if (!is_wp_error($termLink)) {
array_push($listofurls, $termLink);
if( $this->main_instance->get_single_config('cf_post_per_page', 0) > 0 ) {
// Thanks to Davide Prevosto for the suggest
$term_count = $term->count;
$pages_number = ceil($term_count / $this->main_instance->get_single_config('cf_post_per_page', 0) );
$max_pages = $pages_number > 10 ? 10 : $pages_number; // Purge max 10 pages
for ($i=2; $i<=$max_pages; $i++) {
$paginated_url = "{$termLink}page/" . user_trailingslashit($i);
array_push($listofurls, $paginated_url);
}
}
}
}
}
// Author URL
array_push(
$listofurls,
get_author_posts_url(get_post_field('post_author', $postId)),
get_author_feed_link(get_post_field('post_author', $postId))
);
// Archives and their feeds
if (get_post_type_archive_link($postType) == true) {
array_push(
$listofurls,
get_post_type_archive_link($postType),
get_post_type_archive_feed_link($postType)
);
}
// Also clean URL for trashed post.
if (get_post_status($postId) == 'trash') {
$trashPost = get_permalink($postId);
$trashPost = str_replace('__trashed', '', $trashPost);
array_push($listofurls, $trashPost, "{$trashPost}feed/");
}
// Feeds
/*
array_push(
$listofurls,
get_bloginfo_rss('rdf_url'),
get_bloginfo_rss('rss_url'),
get_bloginfo_rss('rss2_url'),
get_bloginfo_rss('atom_url'),
get_bloginfo_rss('comments_rss2_url'),
get_post_comments_feed_link($postId)
);
*/
// Purge the home page as well if SWCFPC_HOME_PAGE_SHOWS_POSTS set to true
if( defined( 'SWCFPC_HOME_PAGE_SHOWS_POSTS' ) && SWCFPC_HOME_PAGE_SHOWS_POSTS === true ) {
array_push($listofurls, home_url('/'));
}
$pageLink = get_permalink(get_option('page_for_posts'));
if (is_string($pageLink) && !empty($pageLink) && get_option('show_on_front') == 'page') {
array_push($listofurls, $pageLink);
}
// Purge https and http URLs
/*
if (function_exists('force_ssl_admin') && force_ssl_admin()) {
$listofurls = array_merge($listofurls, str_replace('https://', 'http://', $listofurls));
} elseif (!is_ssl() && function_exists('force_ssl_content') && force_ssl_content()) {
$listofurls = array_merge($listofurls, str_replace('http://', 'https://', $listofurls));
}
*/
return $listofurls;
}
function reset_all( $keep_settings = false ) {
$this->objects = $this->main_instance->get_objects();
$error = '';
// Purge all caches and prevent preloader to start
$this->purge_all( true, false, true );
// Reset old browser cache TTL
$this->objects['cloudflare']->change_browser_cache_ttl( $this->main_instance->get_single_config('cf_old_bc_ttl', 0), $error );
// Delete worker and route
if( $this->main_instance->get_single_config('cf_woker_enabled', 0) > 0 ) {
$this->objects['cloudflare']->worker_delete($error);
if( $this->main_instance->get_single_config('cf_woker_route_id', '') != '' ) {
$this->objects['cloudflare']->worker_route_delete($error);
}
}
// Delete the page rule
if( $this->main_instance->get_single_config('cf_page_rule_id', '') != '' ) {
$this->objects['cloudflare']->delete_page_rule($this->main_instance->get_single_config('cf_page_rule_id', ''), $error);
}
// Delete additional page rule if exists
if( $this->main_instance->get_single_config('cf_bypass_backend_page_rule_id', '') != '' ) {
$this->objects['cloudflare']->delete_page_rule( $this->main_instance->get_single_config('cf_bypass_backend_page_rule_id', ''), $error );
}
// Disable fallback cache
if( defined('SWCFPC_ADVANCED_CACHE') ) {
$this->objects['fallback_cache']->fallback_cache_advanced_cache_disable();
}
// Delete all cached HTML pages temp files
$this->objects['html_cache']->delete_all_cached_urls();
// Restore default plugin config
if( $keep_settings == false ) {
$this->main_instance->set_config($this->main_instance->get_default_config());
$this->main_instance->update_config();
}
else {
$this->main_instance->set_single_config('cf_cache_enabled', 0);
$this->main_instance->update_config();
}
// Delete all htaccess rules
$this->reset_htaccess();
// Unschedule purge cache cron
$timestamp = wp_next_scheduled( 'swcfpc_cache_purge_cron' );
if( $timestamp !== false ) {
wp_unschedule_event($timestamp, 'swcfpc_cache_purge_cron');
wp_clear_scheduled_hook('swcfpc_cache_purge_cron');
}
// Reset log
$this->objects['logs']->reset_log();
$this->objects['logs']->add_log('cache_controller::reset_all', 'Reset complete' );
}
function wp_redirect_filter($location, $status) {
if( apply_filters('swcfpc_bypass_redirect_cache_buster', false, $location) === true )
return $location;
if( !$this->is_cache_enabled() )
return $location;
if( !is_user_logged_in() )
return $location;
$this->objects = $this->main_instance->get_objects();
if( $this->main_instance->get_single_config('cf_woker_enabled', 0) > 0 )
return $location;
if (version_compare(phpversion(), '8', '>='))
$cache_buster_exists = str_contains($location, $this->cache_buster);
else
$cache_buster_exists = strpos($location, $this->cache_buster);
if ($cache_buster_exists == false)
$location = add_query_arg( array($this->cache_buster => '1'), $location );
return $location;
}
function inject_cache_buster_js_code() {
if( !$this->is_cache_enabled() )
return;
if( $this->remove_cache_buster() )
return;
if( !is_user_logged_in() )
return;
// Make sure we don't add the following script for AMP endpoints as they are gonna be striped out by the AMP system anyway
if( !is_admin() && ( function_exists('amp_is_request') && amp_is_request() ) || ( function_exists('ampforwp_is_amp_endpoint') && ampforwp_is_amp_endpoint() ) )
return;
$this->objects = $this->main_instance->get_objects();
// Cache buster is disabled in worker mode
if( $this->main_instance->get_single_config('cf_woker_enabled', 0) > 0 )
return;
$selectors = 'a';
if( is_admin() )
$selectors = '#wp-admin-bar-my-sites-list a, #wp-admin-bar-site-name a, #wp-admin-bar-view-site a, #wp-admin-bar-view a, .row-actions a, .preview, #sample-permalink a, #message a, #editor .is-link, #editor .editor-post-preview, #editor .editor-post-permalink__link, .edit-post-post-link__preview-link-container .edit-post-post-link__link';
?>
<script id="swcfpc">
var swcfpc_adjust_internal_links = function ( selectors_txt ) {
const comp = new RegExp(location.host);
const current_url = window.location.href.split("#")[0];
[].forEach.call(document.querySelectorAll( selectors_txt ), function(el) {
if( comp.test( el.href ) && !el.href.includes("<?php echo $this->cache_buster; ?>=1") && !el.href.startsWith("#") && !el.href.startsWith(current_url+"#") ) {
if( el.href.indexOf('#') != -1 ) {
const link_split = el.href.split("#");
el.href = link_split[0];
el.href += (el.href.indexOf('?') != -1 ? "&<?php echo $this->cache_buster; ?>=1" : "?<?php echo $this->cache_buster; ?>=1");
el.href += "#"+link_split[1];
}
else {
el.href += (el.href.indexOf('?') != -1 ? "&<?php echo $this->cache_buster; ?>=1" : "?<?php echo $this->cache_buster; ?>=1");
}
}
});
}
document.addEventListener("DOMContentLoaded", function() {
swcfpc_adjust_internal_links("<?php echo $selectors; ?>");
});
window.addEventListener("load", function() {
swcfpc_adjust_internal_links("<?php echo $selectors; ?>");
});
setInterval(function(){ swcfpc_adjust_internal_links("<?php echo $selectors; ?>"); }, 3000);
// Looking for dynamic link added after clicking on Pusblish/Update button
var swcfpc_wordpress_btn_publish = document.querySelector(".editor-post-publish-button__button");
if( swcfpc_wordpress_btn_publish !== undefined && swcfpc_wordpress_btn_publish !== null ) {
swcfpc_wordpress_btn_publish.addEventListener('click', function() {
var swcfpc_wordpress_edited_post_interval = setInterval(function() {
var swcfpc_wordpress_edited_post_link = document.querySelector(".components-snackbar__action");
if( swcfpc_wordpress_edited_post_link !== undefined ) {
swcfpc_adjust_internal_links(".components-snackbar__action");
clearInterval(swcfpc_wordpress_edited_post_link);
}
}, 100);
}, false);
}
</script>
<?php
}
function generate_new_prefetch_urls_timestamp() {
$current_timestamp = $this->main_instance->get_single_config('cf_prefetch_urls_viewport_timestamp', time());
if( $current_timestamp < time() ) {
$current_timestamp = time()+120; // Cache the timestamp for 2 minutes
$this->main_instance->set_single_config('cf_prefetch_urls_viewport_timestamp', $current_timestamp);
$this->main_instance->update_config();
$this->objects = $this->main_instance->get_objects();
if( $this->objects['logs']->get_verbosity() == SWCFPC_LOGS_HIGH_VERBOSITY ) {
$this->objects['logs']->add_log('cache_controller::generate_new_prefetch_urls_timestamp', "New timestamp generated: {$current_timestamp}");
}
}
return $current_timestamp;
}
function prefetch_urls() {
if( !$this->is_cache_enabled() || is_user_logged_in() )
return;
if( $this->main_instance->get_single_config('cf_prefetch_urls_viewport', 0) > 0 ): ?>
<script id="swcfpc">
const swcfpc_prefetch_urls_timestamp_server = '<?php echo $this->main_instance->get_single_config('cf_prefetch_urls_viewport_timestamp', time()); ?>';
let swcfpc_prefetched_urls = localStorage.getItem("swcfpc_prefetched_urls");
swcfpc_prefetched_urls = (swcfpc_prefetched_urls) ? JSON.parse(swcfpc_prefetched_urls) : [];
let swcfpc_prefetch_urls_timestamp_client = localStorage.getItem("swcfpc_prefetch_urls_timestamp_client");
if( swcfpc_prefetch_urls_timestamp_client == undefined || swcfpc_prefetch_urls_timestamp_client != swcfpc_prefetch_urls_timestamp_server ) {
swcfpc_prefetch_urls_timestamp_client = swcfpc_prefetch_urls_timestamp_server;
swcfpc_prefetched_urls = new Array();
localStorage.setItem("swcfpc_prefetched_urls", JSON.stringify(swcfpc_prefetched_urls));
localStorage.setItem("swcfpc_prefetch_urls_timestamp_client", swcfpc_prefetch_urls_timestamp_client);
}
function swcfpc_element_is_in_viewport( element ) {
let bounding = element.getBoundingClientRect();
if ( bounding.top >= 0 && bounding.left >= 0 && bounding.right <= (window.innerWidth || document.documentElement.clientWidth) && bounding.bottom <= (window.innerHeight || document.documentElement.clientHeight) )
return true;
return false;
}
function swcfpc_prefetch_urls() {
let comp = new RegExp(location.host);
document.querySelectorAll("a").forEach( (item) => {
if( item.href ) {
let href = item.href.split("#")[0];
if( swcfpc_can_url_be_prefetched(href) && swcfpc_prefetched_urls.includes(href) == false && comp.test( item.href ) && swcfpc_element_is_in_viewport(item) ) {
swcfpc_prefetched_urls.push( href );
//console.log( href );
let prefetch_element = document.createElement('link');
prefetch_element.rel = "prefetch";
prefetch_element.href = href;
document.getElementsByTagName('body')[0].appendChild( prefetch_element );
}
}
} )
localStorage.setItem("swcfpc_prefetched_urls", JSON.stringify(swcfpc_prefetched_urls));
}
window.addEventListener("load", function(event) {
swcfpc_prefetch_urls();
});
window.addEventListener("scroll", function(event) {
swcfpc_prefetch_urls();
});
</script>
<?php endif; ?>
<?php
}
function is_url_to_bypass() {
$this->objects = $this->main_instance->get_objects();
// Bypass API requests
if( $this->main_instance->is_api_request() )
return true;
// Bypass AMP
if( $this->main_instance->get_single_config('cf_bypass_amp', 0) > 0 && preg_match('/(\/)((\?amp)|(amp\/))/', $_SERVER['REQUEST_URI']) ) {
return true;
}
// Bypass sitemap
if( $this->main_instance->get_single_config('cf_bypass_sitemap', 0) > 0 && strcasecmp($_SERVER['REQUEST_URI'], '/sitemap_index.xml') == 0 || preg_match('/[a-zA-Z0-9]-sitemap.xml$/', $_SERVER['REQUEST_URI']) ) {
return true;
}
// Bypass robots.txt
if( $this->main_instance->get_single_config('cf_bypass_file_robots', 0) > 0 && preg_match('/^\/robots.txt/', $_SERVER['REQUEST_URI']) ) {
return true;
}
// Bypass the cache on excluded URLs
$excluded_urls = $this->main_instance->get_single_config('cf_excluded_urls', array());
if( is_array($excluded_urls) && count($excluded_urls) > 0 ) {
$current_url = $_SERVER['REQUEST_URI'];
if( isset($_SERVER['QUERY_STRING']) && strlen($_SERVER['QUERY_STRING']) > 0 )
$current_url .= "?{$_SERVER['QUERY_STRING']}";
foreach( $excluded_urls as $url_to_exclude ) {
if( $this->main_instance->wildcard_match($url_to_exclude, $current_url) )
return true;
/*
if( fnmatch($url_to_exclude, $current_url, FNM_CASEFOLD) ) {
return true;
}
*/
}
}
if( isset($_GET[$this->cache_buster]) || (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') || (defined('DOING_AJAX') && DOING_AJAX) || (defined( 'DOING_CRON' ) && DOING_CRON) ) {
return true;
}
if( in_array($GLOBALS['pagenow'], array('wp-login.php', 'wp-register.php')) )
return true;
return false;
}
function can_i_bypass_cache() {
global $post;
$this->objects = $this->main_instance->get_objects();
// Bypass the cache using filter
if( has_filter('swcfpc_cache_bypass') ) {
$cache_bypass = apply_filters('swcfpc_cache_bypass', false);
if( $cache_bypass === true )
return true;
}
// Bypass post protected by password
if( is_object($post) && post_password_required($post->ID) !== false ) {
return true;
}
// Bypass single post by metabox
if( $this->main_instance->get_single_config('cf_disable_single_metabox', 0) == 0 && is_object($post) && (int) get_post_meta( $post->ID, 'swcfpc_bypass_cache', true ) > 0 ) {
return true;
}
// Bypass requests with query var
if( $this->main_instance->get_single_config('cf_bypass_query_var', 0) > 0 && isset($_SERVER['QUERY_STRING']) && strlen($_SERVER['QUERY_STRING']) > 0 ) {
return true;
}
// Bypass POST requests
if( $this->main_instance->get_single_config('cf_bypass_post', 0) > 0 && isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] == 'POST' ) {
return true;
}
// Bypass AJAX requests
if( $this->main_instance->get_single_config('cf_bypass_ajax', 0) > 0 ) {
if( function_exists( 'wp_doing_ajax' ) && wp_doing_ajax() ) {
return true;
}
if( function_exists( 'is_ajax' ) && is_ajax() ) {
return true;
}
if( (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest') || (defined('DOING_AJAX') && DOING_AJAX) ) {
return true;
}
}
// Bypass EDD pages
if( is_object($post) && $this->main_instance->get_single_config('cf_bypass_edd_checkout_page', 0) > 0 && function_exists( 'edd_get_option' ) && edd_get_option('purchase_page', 0) == $post->ID ) {
return true;
}
if( is_object($post) && $this->main_instance->get_single_config('cf_bypass_edd_success_page', 0) > 0 && function_exists( 'edd_get_option' ) && edd_get_option('success_page', 0) == $post->ID ) {
return true;
}
if( is_object($post) && $this->main_instance->get_single_config('cf_bypass_edd_failure_page', 0) > 0 && function_exists( 'edd_get_option' ) && edd_get_option('failure_page', 0) == $post->ID ) {
return true;
}
if( is_object($post) && $this->main_instance->get_single_config('cf_bypass_edd_purchase_history_page', 0) > 0 && function_exists( 'edd_get_option' ) && edd_get_option('purchase_history_page', 0) == $post->ID ) {
return true;
}
if( is_object($post) && $this->main_instance->get_single_config('cf_bypass_edd_login_redirect_page', 0) > 0 && function_exists( 'edd_get_option' ) && edd_get_option('login_redirect_page', 0) == $post->ID ) {
return true;
}
// Bypass WooCommerce pages
if( $this->main_instance->get_single_config('cf_bypass_woo_cart_page', 0) > 0 && function_exists( 'is_cart' ) && is_cart() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_woo_account_page', 0) > 0 && function_exists( 'is_account' ) && is_account() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_woo_checkout_page', 0) > 0 && function_exists( 'is_checkout' ) && is_checkout() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_woo_checkout_pay_page', 0) > 0 && function_exists( 'is_checkout_pay_page' ) && is_checkout_pay_page() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_woo_shop_page', 0) > 0 && function_exists( 'is_shop' ) && is_shop() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_woo_product_page', 0) > 0 && function_exists( 'is_product' ) && is_product() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_woo_product_cat_page', 0) > 0 && function_exists( 'is_product_category' ) && is_product_category() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_woo_product_tag_page', 0) > 0 && function_exists( 'is_product_tag' ) && is_product_tag() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_woo_product_tax_page', 0) > 0 && function_exists( 'is_product_taxonomy' ) && is_product_taxonomy() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_woo_pages', 0) > 0 && function_exists( 'is_woocommerce' ) && is_woocommerce() ) {
return true;
}
// Bypass Wordpress pages
if( $this->main_instance->get_single_config('cf_bypass_front_page', 0) > 0 && is_front_page() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_pages', 0) > 0 && is_page() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_home', 0) > 0 && is_home() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_archives', 0) > 0 && is_archive() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_tags', 0) > 0 && is_tag() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_category', 0) > 0 && is_category() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_feeds', 0) > 0 && is_feed() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_search_pages', 0) > 0 && is_search() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_author_pages', 0) > 0 && is_author() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_single_post', 0) > 0 && is_single() ) {
return true;
}
if( $this->main_instance->get_single_config('cf_bypass_404', 0) > 0 && is_404() ) {
return true;
}
/*
if( $this->main_instance->get_single_config('cf_bypass_logged_in', 0) > 0 && is_user_logged_in() ) {
return true;
}
*/
if( is_user_logged_in() ) {
return true;
}
// Bypass cache if the parameter swcfpc is setted or we are on backend
if( isset($_GET[$this->cache_buster]) || is_admin() ) {
return true;
}
return false;
}
function get_cookies_to_bypass_in_worker_mode() {
$this->objects = $this->main_instance->get_objects();
$cookies_list = $this->main_instance->get_single_config('cf_worker_bypass_cookies', array());
if( !count($cookies_list) )
return 'swfpc-feature-not-enabled';
return trim( implode('|', $cookies_list) );
}
function get_cache_control_value() {
$this->objects = $this->main_instance->get_objects();
$value = 's-maxage='.$this->main_instance->get_single_config('cf_maxage', 604800).', max-age='.$this->main_instance->get_single_config('cf_browser_maxage', 60);
return $value;
}
function is_cache_enabled() {
$this->objects = $this->main_instance->get_objects();
if( $this->main_instance->get_single_config('cf_cache_enabled', 0) > 0 )
return true;
return false;
}
function remove_cache_buster() {
$this->objects = $this->main_instance->get_objects();
if( $this->main_instance->get_single_config('cf_remove_cache_buster', 0) > 0 ) {
return true;
} else {
return false;
}
}
function w3tc_hooks() {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
if( $current_action == 'w3tc_flush_minify' )
$this->purge_all(false, true, true);
else
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::w3tc_hooks', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
function wpo_hooks() {
if( did_action( 'wpo_cache_flush' ) === 1 ) {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::wpo_hooks', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
}
function wp_performance_hooks() {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::wp_performance_hooks', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
function wp_rocket_hooks() {
// Do not run this on the WordPress Nav Menu Pages
global $pagenow;
if ( $pagenow === 'nav-menus.php' ) return;
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
if( $current_action == 'after_rocket_clean_minify' )
$this->purge_all(false, true, true);
else
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::wp_rocket_hooks', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
function wp_rocket_after_rocket_clean_post_hook( $post ) {
static $done = [];
if( isset( $done[ $post->ID ] ) ) {
return;
}
$current_action = function_exists('current_action') ? current_action() : '';
$this->objects = $this->main_instance->get_objects();
if( is_object( $post ) ) {
$purged_post_url = get_permalink( $post->ID );
$this->purge_urls( array( $purged_post_url ) );
$this->objects['logs']->add_log('cache_controller::wp_rocket_after_rocket_clean_post_hook', "Purge Cloudflare cache for only URL {$purged_post_url} - Fired action: {$current_action}" );
} else {
$this->objects['logs']->add_log('cache_controller::wp_rocket_after_rocket_clean_post_hook', "Unable to Purge Cloudflare cache. Valid post object not received - Fired action: {$current_action}" );
}
$done[ $post->ID ] = true;
}
function wp_rocket_selective_url_purge_hooks( $url_to_purge ) {
$current_action = function_exists('current_action') ? current_action() : '';
$this->objects = $this->main_instance->get_objects();
// If we are receiving only 1 URL then wrap it inside an array else if we are receiving an array of URLs then pass that
$url_to_purge = is_array( $url_to_purge ) ? $url_to_purge : array( $url_to_purge );
$this->purge_urls( $url_to_purge );
$urls_purged = json_encode( $url_to_purge );
$this->objects['logs']->add_log('cache_controller::wp_rocket_selective_url_purge_hooks', "Purge Cloudflare cache for only URL {$urls_purged} - Fired action: {$current_action}" );
}
function litespeed_hooks() {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
if( $current_action == 'litespeed_purged_all_cssjs' || $current_action == 'litespeed_purged_all' )
$this->purge_all(false, true, true);
else
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::litespeed_hooks', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
function litespeed_single_post_hooks( $post_id ) {
static $done = [];
if( isset( $done[ $post_id ] ) ) {
return;
}
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$urls = array();
$urls[] = get_permalink( $post_id );
$this->purge_urls( $urls );
$this->objects['logs']->add_log('cache_controller::litespeed_single_post_hooks', "Purge Cloudflare cache for only post {$post_id} - Fired action: {$current_action}" );
$done[ $post_id ] = true;
}
function hummingbird_hooks() {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::hummingbird_hooks', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
function nginx_helper_purge_all_hooks() {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::nginx_helper_purge_all_hooks', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
function nginx_helper_purge_single_url_hooks( $url_to_purge ) {
if( $this->main_instance->get_single_config('cf_nginx_helper_purge_on_cache_flush', 0) > 0 ) {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$this->purge_urls( array( $url_to_purge ) );
$this->objects['logs']->add_log('cache_controller::nginx_helper_purge_single_url_hooks', "Purge Cloudflare cache for only URL {$url_to_purge} - Fired action: {$current_action}" );
}
}
function yasr_hooks( $post_id ) {
static $done = [];
if( isset( $done[ $post_id ] ) ) {
return;
}
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$urls = array();
$post_id = is_array( $post_id ) ? $post_id[ 'post_id' ] : $post_id;
$urls[] = get_permalink( $post_id );
$this->purge_urls( $urls );
$this->objects['logs']->add_log('cache_controller::yasr_hooks', "Purge Cloudflare cache for only post {$post_id} - Fired action: {$current_action}" );
$done[ $post_id ] = true;
}
function spl_purge_all() {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
if( $current_action == 'swift_performance_after_clear_all_cache' )
$this->purge_all(false, true, true);
else
$this->purge_all();
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::spl_purge_all', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
function spl_purge_single_post( $post_id ) {
static $done = [];
if( isset( $done[ $post_id ] ) ) {
return;
}
if( $this->main_instance->get_single_config('cf_spl_purge_on_flush_single_post', 0) > 0 ) {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$urls = array();
$urls[] = get_permalink( $post_id );
$this->purge_urls( $urls );
$this->objects['logs']->add_log('cache_controller::spl_purge_single_post', "Purge Cloudflare cache for only post {$post_id} - Fired action: {$current_action}" );
$done[ $post_id ] = true;
}
}
function wpacu_hooks() {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::wpacu_hooks', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
function flying_press_hook() {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$this->purge_all(false, true, true);
$this->objects['logs']->add_log('cache_controller::flying_press_hook', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
function autoptimize_hooks() {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::autoptimize_hooks', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
function purge_on_plugin_update() {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$this->purge_all(false, true, true);
$this->objects['logs']->add_log('cache_controller::purge_on_plugin_update', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
function edd_purge_cache_on_payment_add() {
$current_action = function_exists('current_action') ? current_action() : "";
$this->objects = $this->main_instance->get_objects();
$this->purge_all();
$this->objects['logs']->add_log('cache_controller::edd_purge_cache_on_payment_add', "Purge whole Cloudflare cache (fired action: {$current_action})" );
}
/*function woocommerce_purge_product_page_on_stock_change( $order ) {
if( $this->main_instance->get_single_config('cf_auto_purge_woo_product_page', 0) > 0 && function_exists('wc_get_order') ) {
$items = $order->get_items();
$product_cats_ids = array();
$this->objects = $this->main_instance->get_objects();
$urls = array();
$error = '';
if( function_exists('wc_get_page_id') ) {
$urls[] = get_permalink( wc_get_page_id('shop') );
}
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
//$product_variation_id = $item->get_variation_id();
$product_cats_ids[] = wc_get_product_cat_ids( $product_id );
$urls = array_merge( $urls, $this->get_post_related_links( $product_id) );
}
$urls = array_unique( $urls );
// Reduce the multidimensional array to a flat one and get rid of ducplicate product_cat IDS
$product_cats_ids = call_user_func_array('array_merge', $product_cats_ids);
$product_cats_ids = array_unique($product_cats_ids);
foreach ( $product_cats_ids as $category_id ) {
$urls[] = get_category_link( $category_id );
}
$this->objects['cloudflare']->purge_cache_urls( $urls, $error );
$this->objects['logs']->add_log('cache_controller::woocommerce_purge_product_page_on_stock_change', 'Purge product pages and categories for WooCommerce order' );
}
}*/
function woocommerce_purge_product_page_on_stock_change( $product_id ) {
if( function_exists('wc_get_order') ) {
$this->objects = $this->main_instance->get_objects();
$urls = array();
// Get shop page URL
if (function_exists('wc_get_page_id')) {
$urls[] = get_permalink(wc_get_page_id('shop'));
}
// Get product categories URLs
$product_cats_ids = wc_get_product_cat_ids($product_id);
foreach ($product_cats_ids as $category_id) {
$urls[] = get_category_link($category_id);
}
// GET other related URLs
$urls = array_merge($urls, $this->get_post_related_links($product_id));
$urls = array_unique($urls);
$this->purge_urls($urls);
$this->objects['logs']->add_log('cache_controller::woocommerce_purge_product_page_on_stock_change', 'Purge product pages and categories for WooCommerce order');
}
}
function woocommerce_purge_scheduled_sales( $product_id_list ) {
$this->objects = $this->main_instance->get_objects();
$urls = array();
if (is_array($product_id_list) && count($product_id_list) > 0) {
foreach ($product_id_list as $product_id) {
$single_url = get_permalink($product_id);
if ($single_url !== false)
$urls[] = $single_url;
}
if (count($urls) > 0)
$this->purge_urls($urls);
}
}
function reset_htaccess() {
if( function_exists('insert_with_markers') )
insert_with_markers( $this->htaccess_path, 'WP Cloudflare Super Page Cache', array() );
}
function write_htaccess(&$error_msg) {
$this->objects = $this->main_instance->get_objects();
$htaccess_lines = array();
if( $this->main_instance->get_single_config('cf_cache_control_htaccess', 0) > 0 && $this->is_cache_enabled() && $this->main_instance->get_single_config('cf_woker_enabled', 0) == 0 ) {
$htaccess_lines[] = '<IfModule mod_headers.c>';
//$htaccess_lines[] = 'Header unset Pragma "expr=resp(\'x-wp-cf-super-cache-active\') == \'1\'"';
//$htaccess_lines[] = 'Header always unset Pragma "expr=resp(\'x-wp-cf-super-cache-active\') == \'1\'"';
//$htaccess_lines[] = 'Header unset Expires "expr=resp(\'x-wp-cf-super-cache-active\') == \'1\'"';
//$htaccess_lines[] = 'Header always unset Expires "expr=resp(\'x-wp-cf-super-cache-active\') == \'1\'"';
//$htaccess_lines[] = 'Header unset Cache-Control "expr=resp(\'x-wp-cf-super-cache-active\') == \'1\'"';
//$htaccess_lines[] = 'Header always unset Cache-Control "expr=resp(\'x-wp-cf-super-cache-active\') == \'1\'"';
//$htaccess_lines[] = 'Header always set Cache-Control "' . $this->get_cache_control_value() . '" "expr=resp(\'x-wp-cf-super-cache-active\') == \'1\'"';
$htaccess_lines[] = 'Header unset Pragma "expr=resp(\'x-wp-cf-super-cache-cache-control\') != \'\'"';
$htaccess_lines[] = 'Header always unset Pragma "expr=resp(\'x-wp-cf-super-cache-cache-control\') != \'\'"';
$htaccess_lines[] = 'Header unset Expires "expr=resp(\'x-wp-cf-super-cache-cache-control\') != \'\'"';
$htaccess_lines[] = 'Header always unset Expires "expr=resp(\'x-wp-cf-super-cache-cache-control\') != \'\'"';
$htaccess_lines[] = 'Header unset Cache-Control "expr=resp(\'x-wp-cf-super-cache-cache-control\') != \'\'"';
$htaccess_lines[] = 'Header always unset Cache-Control "expr=resp(\'x-wp-cf-super-cache-cache-control\') != \'\'"';
// Add a cache-control header with the value of x-wp-cf-super-cache-cache-control response header
$htaccess_lines[] = 'Header always set Cache-Control "expr=%{resp:x-wp-cf-super-cache-cache-control}" "expr=resp(\'x-wp-cf-super-cache-cache-control\') != \'\'"';
$htaccess_lines[] = '</IfModule>';
}
if( $this->main_instance->get_single_config('cf_strip_cookies', 0) > 0 && $this->is_cache_enabled() ) {
$htaccess_lines[] = '<IfModule mod_headers.c>';
$htaccess_lines[] = 'Header unset Set-Cookie "expr=resp(\'x-wp-cf-super-cache-active\') == \'1\'"';
$htaccess_lines[] = 'Header always unset Set-Cookie "expr=resp(\'x-wp-cf-super-cache-active\') == \'1\'"';
$htaccess_lines[] = '</IfModule>';
}
if( $this->main_instance->get_single_config('cf_bypass_sitemap', 0) > 0 && $this->is_cache_enabled() ) {
$htaccess_lines[] = '<IfModule mod_expires.c>';
$htaccess_lines[] = 'ExpiresActive on';
$htaccess_lines[] = 'ExpiresByType application/xml "access plus 0 seconds"';
$htaccess_lines[] = 'ExpiresByType text/xsl "access plus 0 seconds"';
$htaccess_lines[] = '</IfModule>';
$htaccess_lines[] = '<FilesMatch "\.(xml|xsl)$">';
$htaccess_lines[] = '<IfModule mod_headers.c>';
$htaccess_lines[] = 'Header set Cache-Control "no-cache, no-store, must-revalidate, max-age=0"';
$htaccess_lines[] = '</IfModule>';
$htaccess_lines[] = '</FilesMatch>';
}
if( $this->main_instance->get_single_config('cf_bypass_file_robots', 0) > 0 && $this->is_cache_enabled() ) {
$htaccess_lines[] = '<FilesMatch "robots\.txt">';
$htaccess_lines[] = '<IfModule mod_headers.c>';
$htaccess_lines[] = 'Header set Cache-Control "no-cache, no-store, must-revalidate, max-age=0"';
$htaccess_lines[] = '</IfModule>';
$htaccess_lines[] = '</FilesMatch>';
}
if( $this->main_instance->get_single_config('cf_browser_caching_htaccess', 0) > 0 && $this->is_cache_enabled() ) {
// Cache CSS/JS/PDF for 1 month
$htaccess_lines[] = '<FilesMatch "\.(css|js|pdf)$">';
$htaccess_lines[] = '<IfModule mod_headers.c>';
$htaccess_lines[] = 'Header set Cache-Control "public, must-revalidate, proxy-revalidate, immutable, max-age=2592000, stale-while-revalidate=86400, stale-if-error=604800"';
$htaccess_lines[] = '</IfModule>';
$htaccess_lines[] = '</FilesMatch>';
// Cache other static files for 1 year
$htaccess_lines[] = '<FilesMatch "\.(jpg|jpeg|png|gif|ico|eot|swf|svg|webp|avif|ttf|otf|woff|woff2|ogg|mp4|mpeg|avi|mkv|webm|mp3)$">';
$htaccess_lines[] = '<IfModule mod_headers.c>';
$htaccess_lines[] = 'Header set Cache-Control "public, must-revalidate, proxy-revalidate, immutable, max-age=31536000, stale-while-revalidate=86400, stale-if-error=604800"';
$htaccess_lines[] = '</IfModule>';
$htaccess_lines[] = '</FilesMatch>';
}
// Disable direct access to log file
$log_file_uri = $this->main_instance->get_plugin_wp_content_directory_uri() . '/debug.log';
$htaccess_lines[] = '<IfModule mod_rewrite.c>';
$htaccess_lines[] = "RewriteCond %{REQUEST_URI} ^(.*)?{$log_file_uri}(.*)$";
$htaccess_lines[] = 'RewriteRule ^(.*)$ - [F]';
$htaccess_lines[] = '</IfModule>';
// Force cache bypass for wp-cron.php
$htaccess_lines[] = '<FilesMatch "wp-cron.php">';
$htaccess_lines[] = '<IfModule mod_headers.c>';
$htaccess_lines[] = 'Header set Cache-Control "no-cache, no-store, must-revalidate, max-age=0"';
$htaccess_lines[] = '</IfModule>';
$htaccess_lines[] = '</FilesMatch>';
$nginx_rules = $this->get_nginx_rules();
if( is_array($nginx_rules) ) {
file_put_contents($this->main_instance->get_plugin_wp_content_directory() . '/nginx.conf', implode("\n", $nginx_rules));
}
else {
file_put_contents($this->main_instance->get_plugin_wp_content_directory() . '/nginx.conf', '');
}
if( function_exists('insert_with_markers') && !insert_with_markers( $this->htaccess_path, 'WP Cloudflare Super Page Cache', $htaccess_lines ) ) {
$error_msg = sprintf( __( 'The .htaccess file (%s) could not be edited. Check if the file has write permissions.', 'wp-cloudflare-page-cache' ), $this->htaccess_path );
return false;
}
return true;
}
function get_nginx_rules() {
$this->objects = $this->main_instance->get_objects();
$log_file_uri = $this->main_instance->get_plugin_wp_content_directory_uri() . '/debug.log';
$nginx_lines = array();
if( $this->main_instance->get_single_config('cf_bypass_sitemap', 0) > 0 ) {
$nginx_lines[] = 'location ~* \.(xml|xsl)$ { add_header Cache-Control "no-cache, no-store, must-revalidate, max-age=0"; expires -1; }';
}
if( $this->main_instance->get_single_config('cf_bypass_file_robots', 0) > 0 ) {
$nginx_lines[] = 'location /robots.txt { add_header Cache-Control "no-cache, no-store, must-revalidate, max-age=0"; expires -1; }';
}
if( $this->main_instance->get_single_config('cf_browser_caching_htaccess', 0) > 0 ) {
// Cache CSS/JS/PDF for 1 month
$nginx_lines[] = 'location ~* \.(css|js|pdf)$ { add_header Cache-Control "public, must-revalidate, proxy-revalidate, immutable, max-age=2592000, stale-while-revalidate=86400, stale-if-error=604800"; expires 30d; }';
// Cache other static files for 1 year
$nginx_lines[] = 'location ~* \.(jpg|jpeg|png|gif|ico|eot|swf|svg|webp|avif|ttf|otf|woff|woff2|ogg|mp4|mpeg|avi|mkv|webm|mp3)$ { add_header Cache-Control "public, must-revalidate, proxy-revalidate, immutable, max-age=31536000, stale-while-revalidate=86400, stale-if-error=604800"; expires 365d; }';
if( $this->main_instance->get_single_config('cf_bypass_sitemap', 0) == 0 )
$nginx_lines[] = 'location ~* \.(xml|xsl)$ { add_header Cache-Control "no-cache, no-store, must-revalidate, max-age=0"; expires -1; }';
}
$nginx_lines[] = 'location /wp-cron.php { add_header Cache-Control "no-cache, no-store, must-revalidate, max-age=0"; expires -1; }';
// Disable direct access to log file
$nginx_lines[] = "location = {$log_file_uri} { access_log off; deny all; }";
return $nginx_lines;
}
function ajax_purge_everything() {
check_ajax_referer( 'ajax-nonce-string', 'security' );
$return_array = array('status' => 'ok');
$this->objects = $this->main_instance->get_objects();
if( ! $this->main_instance->can_current_user_purge_cache() ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Permission denied', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
$this->objects['logs']->add_log('cache_controller::ajax_purge_whole_cache', 'Purge whole Cloudflare cache' );
$this->purge_all(false, false, true);
$return_array['success_msg'] = __('Cache purged successfully! It may take up to 30 seconds for the cache to be permanently cleaned by Cloudflare.', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
function ajax_purge_whole_cache() {
check_ajax_referer( 'ajax-nonce-string', 'security' );
$return_array = array('status' => 'ok');
$this->objects = $this->main_instance->get_objects();
if( ! $this->main_instance->can_current_user_purge_cache() ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Permission denied', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
$this->objects['logs']->add_log('cache_controller::ajax_purge_whole_cache', 'Purge whole Cloudflare cache' );
$this->purge_all(false, false);
$return_array['success_msg'] = __('Cache purged successfully! It may take up to 30 seconds for the cache to be permanently cleaned by Cloudflare.', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
function ajax_purge_single_post_cache() {
check_ajax_referer( 'ajax-nonce-string', 'security' );
$return_array = array('status' => 'ok');
$data = stripslashes($_POST['data']);
$data = json_decode($data, true);
$this->objects = $this->main_instance->get_objects();
if( ! $this->main_instance->can_current_user_purge_cache() ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Permission denied', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
$post_id = (int) $data['post_id'];
$urls = $this->get_post_related_links( $post_id );
if( ! $this->purge_urls( $urls, false ) ) {
$return_array['status'] = 'error';
$return_array['error'] = __('An error occurred while cleaning the cache. Please check log file for further details.', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
$this->objects['logs']->add_log('cache_controller::ajax_purge_single_post_cache', "Purge Cloudflare cache for only post id {$post_id} and related contents" );
$return_array['success_msg'] = __('Cache purged successfully! It may take up to 30 seconds for the cache to be permanently cleaned by Cloudflare.', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
function ajax_reset_all() {
check_ajax_referer( 'ajax-nonce-string', 'security' );
$return_array = array('status' => 'ok');
if( !current_user_can('manage_options') ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Permission denied', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
$this->reset_all();
$return_array['success_msg'] = __('Cloudflare and all configurations have been reset to the initial settings.', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
function can_i_start_preloader() {
$preloader_lock = get_option('swcfpc_preloader_lock', 0);
if( $preloader_lock == 0 || ((time()-$preloader_lock)/60) > 15 )
return true;
return false;
}
function lock_preloader() {
update_option('swcfpc_preloader_lock', time());
}
function unlock_preloader() {
update_option('swcfpc_preloader_lock', 0);
}
function is_purge_cache_queue_writable() {
$purge_cache_lock = get_option('swcfpc_purge_cache_lock', 0);
if( $purge_cache_lock == 0 || (time()-$purge_cache_lock) > 60 )
return true;
return false;
}
function lock_cache_purge_queue() {
update_option('swcfpc_purge_cache_lock', time());
}
function unlock_cache_purge_queue() {
update_option('swcfpc_purge_cache_lock', 0);
}
function purge_cache_queue_init_directory() {
$cache_path = $this->main_instance->get_plugin_wp_content_directory().'/purge_cache_queue/';
if( ! file_exists($cache_path) && wp_mkdir_p( $cache_path ) ) {
file_put_contents($cache_path . 'index.php', '<?php // Silence is golden');
}
return $cache_path;
}
function purge_cache_queue_write($urls=array(), $purge_all=false) {
$this->objects = $this->main_instance->get_objects();
while( ! $this->is_purge_cache_queue_writable() ) {
$this->objects['logs']->add_log('cache_controller::purge_cache_queue_write', 'Queue file not writable. Sleep 1 second' );
sleep( 1 );
}
$this->lock_cache_purge_queue();
$cache_queue_path = $this->purge_cache_queue_init_directory().'cache_queue.json';
$swcfpc_cache_queue = [];
if( file_exists($cache_queue_path) ) {
$swcfpc_cache_queue = json_decode( file_get_contents( $cache_queue_path ), true );
if( !is_array($swcfpc_cache_queue) || (is_array($swcfpc_cache_queue) && (!isset($swcfpc_cache_queue['purge_all']) || !isset($swcfpc_cache_queue['urls'])) )) {
$this->unlock_cache_purge_queue();
return true;
}
if( $swcfpc_cache_queue['purge_all'] ) {
$this->unlock_cache_purge_queue();
return true;
}
if( $swcfpc_cache_queue['purge_all'] === false && $purge_all === true ) {
$swcfpc_cache_queue['purge_all'] = true;
}
else {
$swcfpc_cache_queue['urls'] = array_unique( array_merge( $swcfpc_cache_queue['urls'], $urls ) );
}
}
else {
$this->objects['logs']->add_log('cache_controller::purge_cache_queue_write', 'queue file not exist');
if( !is_array($urls) )
$urls = array();
$swcfpc_cache_queue = array('purge_all' => $purge_all, 'urls' => $urls);
}
if( $this->objects['logs']->get_verbosity() == SWCFPC_LOGS_HIGH_VERBOSITY ) {
$this->objects['logs']->add_log('cache_controller::purge_cache_queue_write', 'URLs in purge queue ' . print_r($swcfpc_cache_queue, true));
}
file_put_contents( $cache_queue_path, json_encode( $swcfpc_cache_queue ) );
$this->unlock_cache_purge_queue();
}
function purge_cache_queue_custom_interval( $schedules ) {
$schedules['swcfpc_purge_cache_cron_interval'] = array(
'interval' => ( defined('SWCFPC_PURGE_CACHE_CRON_INTERVAL') && SWCFPC_PURGE_CACHE_CRON_INTERVAL > 0 ) ? SWCFPC_PURGE_CACHE_CRON_INTERVAL : 10,
'display' => esc_html__( 'Super Page Cache for Cloudflare - Purge Cache Cron Interval' ,'wp-cloudflare-page-cache') );
return $schedules;
}
function purge_cache_queue_start_cronjob() {
if( $this->main_instance->get_single_config('cf_disable_cache_purging_queue', 0) > 0 )
return false;
$cache_queue_path = $this->purge_cache_queue_init_directory().'cache_queue.json';
$this->objects = $this->main_instance->get_objects();
// Purge queue file does not exist, so don't start purge events and unschedule running purge events
if( ! file_exists($cache_queue_path) ) {
$timestamp = wp_next_scheduled( 'swcfpc_cache_purge_cron' );
if( $timestamp !== false ) {
if( wp_unschedule_event($timestamp, 'swcfpc_cache_purge_cron') ) {
wp_clear_scheduled_hook('swcfpc_cache_purge_cron');
if( $this->objects['logs']->get_verbosity() == SWCFPC_LOGS_HIGH_VERBOSITY ) {
$this->objects['logs']->add_log('cache_controller::purge_cache_queue_start_cronjob', "Purge queue scheduled event stopped successfully - Timestamp {$timestamp}");
}
}
else {
if( $this->objects['logs']->get_verbosity() == SWCFPC_LOGS_HIGH_VERBOSITY ) {
$this->objects['logs']->add_log('cache_controller::purge_cache_queue_start_cronjob', "Unable to stop the purge queue scheduled event - Timestamp {$timestamp}");
}
}
}
return false;
}
// If the purge queue file exists and there are not aready running scheduled events, start a new one
if ( ! wp_next_scheduled( 'swcfpc_purge_cache_cron' ) && ! wp_get_schedule('swcfpc_cache_purge_cron') ) {
$timestamp = time();
if (wp_schedule_event($timestamp, 'swcfpc_purge_cache_cron_interval', 'swcfpc_cache_purge_cron')) {
if ($this->objects['logs']->get_verbosity() == SWCFPC_LOGS_HIGH_VERBOSITY) {
$this->objects['logs']->add_log('cache_controller::purge_cache_queue_start_cronjob', "Purge queue cronjob started successfully - Timestamp {$timestamp}");
}
return true;
}
if ($this->objects['logs']->get_verbosity() == SWCFPC_LOGS_HIGH_VERBOSITY) {
$this->objects['logs']->add_log('cache_controller::purge_cache_queue_start_cronjob', "Unable to start the purge queue scheduled event - Timestamp {$timestamp}");
}
}
return false;
}
function purge_cache_queue_job() {
$this->objects = $this->main_instance->get_objects();
$this->objects['logs']->add_log('cache_controller::purge_cache_queue_job', 'I\'m the purge cache cronjob' );
$cache_queue_path = $this->purge_cache_queue_init_directory() . 'cache_queue.json';
if( ! file_exists($cache_queue_path) ) {
$this->objects['logs']->add_log('cache_controller::purge_cache_queue_job', 'Queue file does not exists. Exit.' );
return false;
}
while( ! $this->is_purge_cache_queue_writable() ) {
$this->objects['logs']->add_log('cache_controller::purge_cache_queue_job', 'Queue file not writable. Sleep 1 second' );
sleep( 1 );
}
$this->lock_cache_purge_queue();
$swcfpc_cache_queue = json_decode( file_get_contents( $cache_queue_path ), true );
if( isset($swcfpc_cache_queue['purge_all']) && $swcfpc_cache_queue['purge_all'] ) {
$this->purge_all(false, false);
}
else if( isset($swcfpc_cache_queue['urls']) && is_array($swcfpc_cache_queue['urls']) && count($swcfpc_cache_queue['urls']) > 0 ) {
$this->purge_urls( $swcfpc_cache_queue['urls'], false );
}
@unlink( $cache_queue_path );
$this->unlock_cache_purge_queue();
$this->objects['logs']->add_log('cache_controller::purge_cache_queue_job', 'Cache purging complete' );
return true;
}
function start_cache_preloader_for_specific_urls( $urls ) {
if( class_exists('SWCFPC_Preloader_Process') ) {
// Remove empty and duplicated URLs
$urls = array_filter( $urls );
$urls = array_unique( $urls );
$this->objects = $this->main_instance->get_objects();
if( $this->can_i_start_preloader() ) {
$this->lock_preloader();
$num_url = count($urls);
if( $this->objects['logs']->get_verbosity() == SWCFPC_LOGS_HIGH_VERBOSITY ) {
$this->objects['logs']->add_log('cache_controller::start_cache_preloader_for_specific_urls', 'Adding these URLs to preloader queue: ' . print_r($urls, true));
}
else {
$this->objects['logs']->add_log('cache_controller::start_cache_preloader_for_specific_urls', "Adding {$num_url} URLs to preloader queue");
}
$preloader = new SWCFPC_Preloader_Process($this->main_instance);
$max_post_to_preload = $num_url >= SWCFPC_PRELOADER_MAX_POST_NUMBER ? SWCFPC_PRELOADER_MAX_POST_NUMBER : $num_url;
// Add URLs to preloader
for ($i = 0; $i < $num_url && $i < $max_post_to_preload; $i++) {
if ( $this->is_external_link($urls[$i]) === false )
$preloader->push_to_queue( array( 'url' => $urls[$i] ) );
}
// Start background preloader
$preloader->save()->dispatch();
}
else {
$this->objects['logs']->add_log('cache_controller::start_cache_preloader_for_specific_urls', 'Unable to start the preloader. Another preloading process is currently running.' );
}
}
}
function start_preloader_for_all_urls() {
$this->objects = $this->main_instance->get_objects();
$home_url = home_url('/');
$urls = array();
// Preload all registered navigation menu locations URLs
if( count( $this->main_instance->get_single_config('cf_preloader_nav_menus', array()) ) > 0 ) {
// Get urls from wordpress menus
//$wordpress_menus = get_nav_menu_locations();
$wordpress_menus = $this->main_instance->get_single_config('cf_preloader_nav_menus', array());
foreach ($wordpress_menus as $nav_menu_id) {
$single_menu_items = wp_get_nav_menu_items($nav_menu_id);
if ($single_menu_items) {
foreach ($single_menu_items as $menu_item) {
if( in_array( $menu_item->url, $urls ) )
continue;
if( $menu_item->url && $this->is_external_link($menu_item->url) )
continue;
if ( $menu_item->type == 'post_type' && $menu_item->url && strlen($menu_item->url) > 0 && (substr( strtolower($menu_item->url), 0, 6) == 'https:' || substr( strtolower($menu_item->url), 0, 5) == 'http:') ) {
$urls[] = $menu_item->url;
continue;
}
if( $menu_item->url && strcasecmp(substr($menu_item->url, 0, strlen($home_url)-1), $home_url) == 0 ) {
$urls[] = $menu_item->url;
continue;
}
}
}
}
}
// Preload URLs in sitemaps
if( count( $this->main_instance->get_single_config('cf_preload_sitemap_urls', array()) ) > 0 ) {
$sitemap_urls = $this->main_instance->get_single_config('cf_preload_sitemap_urls', array());
if( is_array($sitemap_urls) && count($sitemap_urls) > 0 ) {
foreach( $sitemap_urls as $single_sitemap_url ) {
$single_sitemap_url = home_url( $single_sitemap_url );
$this->objects['logs']->add_log('cloudflare::start_preloader_for_all_urls', "Preload sitemap {$single_sitemap_url}");
$response = wp_remote_post(
esc_url_raw( $single_sitemap_url ),
array(
'timeout' => defined('SWCFPC_CURL_TIMEOUT') ? SWCFPC_CURL_TIMEOUT : 10,
'sslverify' => false,
'blocking' => true,
'user-agent' => 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0'
)
);
if ( is_wp_error( $response ) ) {
$error = sprintf( __('Connection error while retriving the sitemap %1$s: %2$s', 'wp-cloudflare-page-cache'), $single_sitemap_url, $response->get_error_message());
$this->objects['logs']->add_log('cloudflare::start_preloader_for_all_urls', "Error wp_remote_post: {$error}");
continue;
}
if( wp_remote_retrieve_response_code( $response ) != 200 ) {
$this->objects['logs']->add_log('cloudflare::start_preloader_for_all_urls', "Response code for {$single_sitemap_url} is not 200. Response code: ".wp_remote_retrieve_response_code( $response ));
continue;
}
$response_body = wp_remote_retrieve_body($response);
if( strlen($response_body) == 0 ) {
$this->objects['logs']->add_log('cloudflare::start_preloader_for_all_urls', "Empty response body for sitemap {$single_sitemap_url}");
continue;
}
libxml_use_internal_errors(true);
$xml = simplexml_load_string($response_body);
if( $xml === false ) {
$xml_errors = libxml_get_errors();
foreach ($xml_errors as $single_xml_error) {
$this->objects['logs']->add_log('cloudflare::start_preloader_for_all_urls', "Invalid XML for sitemap {$single_sitemap_url}: {$single_xml_error->message}");
}
libxml_clear_errors();
}
/*
try {
$xml = new SimpleXMLElement($response_body);
} catch (Exception $e){
$this->objects['logs']->add_log('cloudflare::start_preloader_for_all_urls', 'Invalid XML for sitemap $single_sitemap_url: ' . $e->getMessage());
continue;
}
*/
if( isset($xml->url) && !empty($xml->url) ) {
foreach ($xml->url as $url_list) {
if ( !isset($url_list->loc) || empty($url_list->loc) || in_array($url_list->loc, $urls) || $this->is_external_link($url_list->loc))
continue;
$urls[] = $url_list->loc->__toString();
}
}
}
}
}
// Preload last published posts
if( $this->main_instance->get_single_config('cf_preload_last_urls', 0) > 0 ) {
// Get public post types.
$post_types = array('post', 'page');
$other_post_types = get_post_types(array('public' => true, '_builtin' => false, 'publicly_queryable' => true));
foreach($other_post_types as $key => $single_post_type)
$post_types[] = $single_post_type;
$post_types = array_diff( $post_types, $this->main_instance->get_single_config('cf_preload_excluded_post_types', array()) );
$this->objects['logs']->add_log('cloudflare::start_preloader_for_all_urls', 'Getting last published posts for post types: ' . print_r($post_types, true));
$args = array(
'fields' => 'ids',
'numberposts' => 20,
//'posts_per_page' => -1,
'post_type' => $post_types,
'orderby' => 'date',
'order' => 'DESC'
);
$all_posts = get_posts($args);
foreach ($all_posts as $post) {
$permalink = get_permalink($post);
if ( $permalink !== false && !in_array( $permalink, $urls ) && strlen($permalink) > 0 ) {
$urls[] = $permalink;
}
}
}
// Start preloader
if( count($urls) > 0 ) {
if( !in_array( $home_url, $urls ) ) {
$urls[] = $home_url;
}
$this->start_cache_preloader_for_specific_urls( $urls );
}
else {
$this->objects['logs']->add_log('cloudflare::start_preloader_for_all_urls', 'Nothing to preload');
}
}
function is_external_link($url) {
$source = parse_url( home_url() );
$target = parse_url($url);
if( !$source || empty($source['host']) || !$target || empty($target['host']) )
return false;
if( strcasecmp($target['host'], $source['host']) === 0 )
return false;
return true;
}
function purge_wpengine_cache() {
if ( class_exists( 'WpeCommon' ) ) {
$this->objects = $this->main_instance->get_objects();
if( method_exists('WpeCommon', 'purge_memcached') ) {
WpeCommon::purge_memcached();
$this->objects['logs']->add_log('cache_controller::purge_wpengine_cache', 'Purge WP Engine memcached cache' );
}
if( method_exists('WpeCommon', 'purge_varnish_cache') ) {
WpeCommon::purge_varnish_cache();
$this->objects['logs']->add_log('cache_controller::purge_wpengine_cache', 'Purge WP Engine varnish cache' );
}
}
}
function can_wpengine_cache_be_purged() {
if ( !class_exists( 'WpeCommon' ) )
return false;
if( !method_exists('WpeCommon', 'purge_memcached') && !method_exists('WpeCommon', 'purge_varnish_cache') )
return false;
return true;
}
function purge_spinupwp_cache() {
if ( ! function_exists( 'spinupwp_purge_site' ) ) {
return;
}
spinupwp_purge_site();
$this->objects = $this->main_instance->get_objects();
$this->objects['logs']->add_log('cache_controller::purge_spinupwp_cache', 'Purge whole SpinupWP' );
}
function purge_spinupwp_cache_single_url($url) {
if ( ! function_exists( 'spinupwp_purge_url' ) ) {
return;
}
spinupwp_purge_url($url);
$this->objects = $this->main_instance->get_objects();
$this->objects['logs']->add_log('cache_controller::purge_spinupwp_cache_single_url', "Purge SpinupWP cache for the URL {$url}" );
}
function can_spinupwp_cache_be_purged() {
if ( ! function_exists( 'spinupwp_purge_site' ) || ! function_exists( 'spinupwp_purge_url' ) ) {
return;
}
}
function can_kinsta_cache_be_purged() {
global $kinsta_cache;
if ( isset( $kinsta_cache ) && class_exists( '\\Kinsta\\CDN_Enabler' ) )
return true;
return false;
}
function purge_kinsta_cache() {
global $kinsta_cache;
if( $this->can_kinsta_cache_be_purged() && ! empty($kinsta_cache->kinsta_cache_purge) ) {
$kinsta_cache->kinsta_cache_purge->purge_complete_caches();
$this->objects = $this->main_instance->get_objects();
$this->objects['logs']->add_log('cache_controller::purge_kinsta_cache', 'Purge whole Kinsta cache' );
return true;
}
return false;
}
function purge_kinsta_cache_single_url($url) {
if( ! $this->can_kinsta_cache_be_purged() )
return false;
$url = trailingslashit( $url ) . 'kinsta-clear-cache/';
wp_remote_get(
$url,
[
'blocking' => false,
'timeout' => 0.01,
]
);
return true;
}
function get_siteground_supercacher_version() {
static $version;
if ( isset( $version ) )
return $version;
if( file_exists(WP_PLUGIN_DIR . '/sg-cachepress/sg-cachepress.php') ) {
$sg_optimizer = get_file_data(WP_PLUGIN_DIR . '/sg-cachepress/sg-cachepress.php', ['Version' => 'Version']);
$version = $sg_optimizer['Version'];
return $version;
}
return false;
}
function is_siteground_supercacher_enabled() {
$sg_version = $this->get_siteground_supercacher_version();
if( $sg_version === false )
return false;
if ( ! version_compare( $sg_version, '5.0' ) < 0 ) {
global $sg_cachepress_environment;
return isset( $sg_cachepress_environment ) && $sg_cachepress_environment instanceof SG_CachePress_Environment && $sg_cachepress_environment->cache_is_enabled();
}
return (bool) get_option( 'siteground_optimizer_enable_cache', 0 );
}
function purge_siteground_cache() {
if ( ! $this->is_siteground_supercacher_enabled() )
return;
if ( ! version_compare( $this->get_siteground_supercacher_version(), '5.0' ) < 0 )
SiteGround_Optimizer\Supercacher\Supercacher::purge_cache();
elseif ( isset( $sg_cachepress_supercacher ) && $sg_cachepress_supercacher instanceof SG_CachePress_Supercacher )
$sg_cachepress_supercacher->purge_cache();
$this->objects = $this->main_instance->get_objects();
$this->objects['logs']->add_log('cache_controller::purge_siteground_cache', 'Purge whole Siteground cache' );
}
function purge_object_cache() {
if( !function_exists('wp_cache_flush') )
return false;
wp_cache_flush();
$this->objects = $this->main_instance->get_objects();
$this->objects['logs']->add_log('cache_controller::purge_object_cache', 'Purge object cache' );
return true;
}
function purge_opcache() {
if ( !extension_loaded('Zend OPcache') )
return false;
$opcache_status = opcache_get_status();
if ( !$opcache_status || !isset($opcache_status['opcache_enabled']) || $opcache_status['opcache_enabled'] === false )
return false;
if ( !opcache_reset() )
return false;
/**
* opcache_reset() is performed, now try to clear the
* file cache.
* Please note: http://stackoverflow.com/a/23587079/1297898
* "Opcache does not evict invalid items from memory - they
* stay there until the pool is full at which point the
* memory is completely cleared"
*/
foreach( $opcache_status['scripts'] as $key => $data ) {
$dirs[dirname($key)][basename($key)] = $data;
opcache_invalidate($data['full_path'] , $force=true);
}
$this->objects = $this->main_instance->get_objects();
$this->objects['logs']->add_log('cache_controller::purge_opcache', 'Purge OPcache cache' );
return true;
}
function purge_cache_programmatically( $urls ) {
if( !is_array($urls) || count($urls) == 0 )
$this->purge_all(true, false);
else
$this->purge_urls($urls, false);
}
/*function purge_cache_on_elementor_ajax_update() {
if( isset($_REQUEST['editor_post_id']) ) {
$current_action = function_exists('current_action') ? current_action() : "";
$post_id = $_REQUEST['editor_post_id'];
$url = get_permalink( $post_id );
if( $url !== false ) {
$this->purge_urls(array($url));
$this->objects = $this->main_instance->get_objects();
$this->objects['logs']->add_log('cache_controller::purge_cache_on_elementor_ajax_update', "Purge Cloudflare cache for only post {$post_id} - Fired action: {$current_action}" );
}
}
}*/
function ajax_preloader_unlock() {
check_ajax_referer( 'ajax-nonce-string', 'security' );
$this->objects = $this->main_instance->get_objects();
$return_array = array('status' => 'ok');
if( !current_user_can('manage_options') ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Permission denied', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
if( $this->main_instance->get_single_config('cf_preloader', 1) == 0 ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Preloader is not enabled', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
if( $this->can_i_start_preloader() ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Preloader is already unlocked', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
$this->unlock_preloader();
$return_array['success_msg'] = __('Preloader unlocked successfully', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
function ajax_preloader_start() {
check_ajax_referer( 'ajax-nonce-string', 'security' );
$this->objects = $this->main_instance->get_objects();
$return_array = array('status' => 'ok');
if( !current_user_can('manage_options') ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Permission denied', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
if( $this->main_instance->get_single_config('cf_preloader', 1) == 0 ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Preloader is not enabled', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
if( !$this->can_i_start_preloader() ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Unable to start the preloader. Another preloading process is currently running.', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
if( !class_exists('WP_Background_Process') ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Unable to start background processes: WP_Background_Process does not exists.', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
if( !class_exists('SWCFPC_Preloader_Process') ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Unable to start background processes: SWCFPC_Preloader_Process does not exists.', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
if( ! $this->is_cache_enabled() ) {
$return_array['status'] = 'error';
$return_array['error'] = __('You cannot start the preloader while the page cache is disabled.', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
$this->start_preloader_for_all_urls();
$return_array['success_msg'] = __('Preloader started successfully', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
function ajax_enable_page_cache() {
check_ajax_referer( 'ajax-nonce-string', 'security' );
$this->objects = $this->main_instance->get_objects();
$return_array = array('status' => 'ok');
$error = '';
if( !current_user_can('manage_options') ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Permission denied', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
if( ! $this->objects['cloudflare']->enable_page_cache($error) ) {
$return_array['status'] = 'error';
$return_array['error'] = $error;
die(json_encode($return_array));
}
if( $this->main_instance->get_single_config('cf_fallback_cache', 0) > 0 && $this->main_instance->get_single_config('cf_fallback_cache_curl', 0) == 0 && !defined('SWCFPC_ADVANCED_CACHE') ) {
$this->objects['fallback_cache']->fallback_cache_advanced_cache_enable();
}
$return_array['success_msg'] = __('Page cache enabled successfully', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
function ajax_disable_page_cache() {
check_ajax_referer( 'ajax-nonce-string', 'security' );
$this->objects = $this->main_instance->get_objects();
$return_array = array('status' => 'ok');
$error = '';
if( !current_user_can('manage_options') ) {
$return_array['status'] = 'error';
$return_array['error'] = __('Permission denied', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
if( ! $this->objects['cloudflare']->disable_page_cache($error) ) {
$return_array['status'] = 'error';
$return_array['error'] = $error;
die(json_encode($return_array));
}
if( $this->main_instance->get_single_config('cf_fallback_cache', 0) > 0 && $this->main_instance->get_single_config('cf_fallback_cache_curl', 0) == 0 && defined('SWCFPC_ADVANCED_CACHE') ) {
$this->objects['fallback_cache']->fallback_cache_advanced_cache_disable();
}
$return_array['success_msg'] = __('Page cache disabled successfully', 'wp-cloudflare-page-cache');
die(json_encode($return_array));
}
}