2013-04-09 09:38:40 +00:00
< ? php
2014-05-28 13:52:50 +00:00
if ( ! defined ( 'ABSPATH' ) ) {
exit ; // Exit if accessed directly
}
2013-04-09 09:38:40 +00:00
/**
* WC_Cache_Helper class .
*
* @ class WC_Cache_Helper
2014-05-28 13:52:50 +00:00
* @ version 2.2 . 0
2013-04-09 09:38:40 +00:00
* @ package WooCommerce / Classes
* @ category Class
* @ author WooThemes
*/
class WC_Cache_Helper {
/**
2015-11-03 13:31:20 +00:00
* Hook in methods .
2013-04-09 09:38:40 +00:00
*/
2014-05-28 13:52:50 +00:00
public static function init () {
2015-06-22 13:55:15 +00:00
add_action ( 'template_redirect' , array ( __CLASS__ , 'geolocation_ajax_redirect' ) );
2014-05-28 13:52:50 +00:00
add_action ( 'before_woocommerce_init' , array ( __CLASS__ , 'prevent_caching' ) );
add_action ( 'admin_notices' , array ( __CLASS__ , 'notices' ) );
2015-07-15 14:12:52 +00:00
add_action ( 'delete_version_transients' , array ( __CLASS__ , 'delete_version_transients' ) );
2013-04-09 09:38:40 +00:00
}
2015-11-13 23:06:38 +00:00
/**
* Get prefix for use with wp_cache_set . Allows all cache in a group to be invalidated at once .
* @ param string $group
* @ return string
*/
public static function get_cache_prefix ( $group ) {
// Get cache key - uses cache key wc_orders_cache_prefix to invalidate when needed
$prefix = wp_cache_get ( 'wc_' . $group . '_cache_prefix' , $group );
if ( false === $prefix ) {
$prefix = 1 ;
wp_cache_set ( 'wc_' . $group . '_cache_prefix' , $prefix , $group );
}
return 'wc_cache_' . $prefix . '_' ;
}
/**
* Increment group cache prefix ( invalidates cache ) .
* @ param string $group
*/
public static function incr_cache_prefix ( $group ) {
wp_cache_incr ( 'wc_' . $group . '_cache_prefix' , 1 , $group );
}
2015-06-22 13:55:15 +00:00
/**
2015-11-03 13:31:20 +00:00
* Get a hash of the customer location .
2015-06-22 13:55:15 +00:00
* @ return string
*/
public static function geolocation_ajax_get_location_hash () {
$customer = new WC_Customer ();
2016-03-14 19:14:50 +00:00
$customer -> load_session ();
2015-06-22 13:55:15 +00:00
$location = array ();
2016-03-17 19:39:29 +00:00
$location [ 'country' ] = $customer -> get_billing_country ();
$location [ 'state' ] = $customer -> get_billing_state ();
$location [ 'postcode' ] = $customer -> get_billing_postcode ();
$location [ 'city' ] = $customer -> get_billing_city ();
2015-06-22 13:55:15 +00:00
return substr ( md5 ( implode ( '' , $location ) ), 0 , 12 );
}
/**
* When using geolocation via ajax , to bust cache , redirect if the location hash does not equal the querystring .
*
* This prevents caching of the wrong data for this request .
*/
public static function geolocation_ajax_redirect () {
2015-09-01 14:41:05 +00:00
if ( 'geolocation_ajax' === get_option ( 'woocommerce_default_customer_address' ) && ! is_checkout () && ! is_cart () && ! is_account_page () && ! is_ajax () && empty ( $_POST ) ) {
2015-06-22 13:55:15 +00:00
$location_hash = self :: geolocation_ajax_get_location_hash ();
$current_hash = isset ( $_GET [ 'v' ] ) ? wc_clean ( $_GET [ 'v' ] ) : '' ;
if ( empty ( $current_hash ) || $current_hash !== $location_hash ) {
global $wp ;
2015-06-22 14:30:42 +00:00
$redirect_url = trailingslashit ( home_url ( $wp -> request ) );
2015-09-07 15:58:05 +00:00
if ( ! empty ( $_SERVER [ 'QUERY_STRING' ] ) ) {
$redirect_url = add_query_arg ( $_SERVER [ 'QUERY_STRING' ], '' , $redirect_url );
}
2015-06-22 14:30:42 +00:00
if ( ! get_option ( 'permalink_structure' ) ) {
$redirect_url = add_query_arg ( $wp -> query_string , '' , $redirect_url );
}
$redirect_url = add_query_arg ( 'v' , $location_hash , remove_query_arg ( 'v' , $redirect_url ) );
wp_safe_redirect ( esc_url_raw ( $redirect_url ), 307 );
2015-06-22 13:55:15 +00:00
exit ;
}
}
}
2014-07-03 11:59:54 +00:00
/**
2015-11-03 13:31:20 +00:00
* Get transient version .
2014-07-03 11:59:54 +00:00
*
2015-11-03 13:31:20 +00:00
* When using transients with unpredictable names , e . g . those containing an md5 .
2014-09-20 18:44:22 +00:00
* hash in the name , we need a way to invalidate them all at once .
2014-07-03 11:59:54 +00:00
*
2015-11-03 13:31:20 +00:00
* When using default WP transients we ' re able to do this with a DB query to .
2014-07-03 11:59:54 +00:00
* delete transients manually .
*
2015-11-03 13:31:20 +00:00
* With external cache however , this isn ' t possible . Instead , this function is used .
* to append a unique string ( based on time ()) to each transient . When transients .
2014-07-03 11:59:54 +00:00
* are invalidated , the transient version will increment and data will be regenerated .
*
2016-09-28 10:17:40 +00:00
* Raised in issue https :// github . com / woocommerce / woocommerce / issues / 5777.
2015-11-03 13:31:20 +00:00
* Adapted from ideas in http :// tollmanz . com / invalidation - schemes /.
2014-09-20 18:44:22 +00:00
*
2014-07-03 11:59:54 +00:00
* @ param string $group Name for the group of transients we need to invalidate
* @ param boolean $refresh true to force a new version
* @ return string transient version based on time (), 10 digits
*/
public static function get_transient_version ( $group , $refresh = false ) {
$transient_name = $group . '-transient-version' ;
2014-07-03 12:02:19 +00:00
$transient_value = get_transient ( $transient_name );
2014-07-03 11:59:54 +00:00
if ( false === $transient_value || true === $refresh ) {
2015-05-25 00:48:17 +00:00
self :: delete_version_transients ( $transient_value );
set_transient ( $transient_name , $transient_value = time () );
2014-07-03 11:59:54 +00:00
}
return $transient_value ;
}
2015-05-25 00:48:17 +00:00
/**
* When the transient version increases , this is used to remove all past transients to avoid filling the DB .
*
* Note ; this only works on transients appended with the transient version , and when object caching is not being used .
*
* @ since 2.3 . 10
*/
2015-07-15 14:12:52 +00:00
public static function delete_version_transients ( $version = '' ) {
2015-05-27 14:56:42 +00:00
if ( ! wp_using_ext_object_cache () && ! empty ( $version ) ) {
2015-05-25 00:48:17 +00:00
global $wpdb ;
2015-07-15 14:12:52 +00:00
2015-08-18 09:47:19 +00:00
$limit = apply_filters ( 'woocommerce_delete_version_transients_limit' , 1000 );
2015-07-15 14:12:52 +00:00
$affected = $wpdb -> query ( $wpdb -> prepare ( " DELETE FROM { $wpdb -> options } WHERE option_name LIKE %s ORDER BY option_id LIMIT %d; " , " \ _transient \ _% " . $version , $limit ) );
// If affected rows is equal to limit, there are more rows to delete. Delete in 10 secs.
if ( $affected === $limit ) {
wp_schedule_single_event ( time () + 10 , 'delete_version_transients' , array ( $version ) );
}
2015-05-25 00:48:17 +00:00
}
}
2014-10-27 14:41:09 +00:00
/**
2015-11-03 13:31:20 +00:00
* Get the page name / id for a WC page .
2014-10-27 14:41:09 +00:00
* @ param string $wc_page
* @ return array
*/
private static function get_page_uris ( $wc_page ) {
$wc_page_uris = array ();
if ( ( $page_id = wc_get_page_id ( $wc_page ) ) && $page_id > 0 && ( $page = get_post ( $page_id ) ) ) {
$wc_page_uris [] = 'p=' . $page_id ;
2015-10-22 15:33:03 +00:00
$wc_page_uris [] = '/' . $page -> post_name . '/' ;
2014-10-27 14:41:09 +00:00
}
return $wc_page_uris ;
}
2013-04-09 09:38:40 +00:00
/**
* Prevent caching on dynamic pages .
* @ access public
*/
2014-05-28 13:52:50 +00:00
public static function prevent_caching () {
2013-04-09 09:38:40 +00:00
if ( false === ( $wc_page_uris = get_transient ( 'woocommerce_cache_excluded_uris' ) ) ) {
2014-10-27 14:41:09 +00:00
$wc_page_uris = array_filter ( array_merge ( self :: get_page_uris ( 'cart' ), self :: get_page_uris ( 'checkout' ), self :: get_page_uris ( 'myaccount' ) ) );
2013-04-09 09:38:40 +00:00
set_transient ( 'woocommerce_cache_excluded_uris' , $wc_page_uris );
}
2015-05-28 10:44:42 +00:00
if ( isset ( $_GET [ 'download_file' ] ) ) {
self :: nocache ();
} elseif ( is_array ( $wc_page_uris ) ) {
2016-08-27 04:23:02 +00:00
foreach ( $wc_page_uris as $uri ) {
2015-09-01 15:40:17 +00:00
if ( stristr ( $_SERVER [ 'REQUEST_URI' ], $uri ) ) {
2014-05-28 13:52:50 +00:00
self :: nocache ();
2013-04-09 09:38:40 +00:00
break ;
}
2014-10-02 13:52:09 +00:00
}
2014-05-28 13:52:50 +00:00
}
2013-04-09 09:38:40 +00:00
}
/**
* Set nocache constants and headers .
* @ access private
*/
2014-05-28 13:52:50 +00:00
private static function nocache () {
2016-02-29 12:52:45 +00:00
if ( ! defined ( 'DONOTCACHEPAGE' ) ) {
define ( " DONOTCACHEPAGE " , true );
}
if ( ! defined ( 'DONOTCACHEOBJECT' ) ) {
define ( " DONOTCACHEOBJECT " , true );
}
if ( ! defined ( 'DONOTCACHEDB' ) ) {
define ( " DONOTCACHEDB " , true );
}
2013-04-09 09:38:40 +00:00
nocache_headers ();
}
/**
* notices function .
*/
2014-05-28 13:52:50 +00:00
public static function notices () {
if ( ! function_exists ( 'w3tc_pgcache_flush' ) || ! function_exists ( 'w3_instance' ) ) {
2013-04-09 09:38:40 +00:00
return ;
2014-05-28 13:52:50 +00:00
}
2013-04-09 09:38:40 +00:00
2016-09-02 01:51:31 +00:00
$config = w3_instance ( 'W3_Config' );
2013-04-09 09:38:40 +00:00
$enabled = $config -> get_integer ( 'dbcache.enabled' );
2014-10-21 20:24:55 +00:00
$settings = array_map ( 'trim' , $config -> get_array ( 'dbcache.reject.sql' ) );
2013-04-09 09:38:40 +00:00
if ( $enabled && ! in_array ( '_wc_session_' , $settings ) ) {
?>
< div class = " error " >
< p >< ? php printf ( __ ( 'In order for <strong>database caching</strong> to work with WooCommerce you must add <code>_wc_session_</code> to the "Ignored Query Strings" option in W3 Total Cache settings <a href="%s">here</a>.' , 'woocommerce' ), admin_url ( 'admin.php?page=w3tc_dbcache' ) ); ?> </p>
</ div >
< ? php
}
}
}
2014-05-28 13:52:50 +00:00
WC_Cache_Helper :: init ();