Merge pull request #29182 from woocommerce/fix/26973-get-customer-location
Avoid/minimize wc-ajax requests when `geolocation_ajax` is enabled | #26973
This commit is contained in:
commit
bcdfe3cb68
|
@ -1,33 +1,90 @@
|
|||
/*global wc_geolocation_params */
|
||||
jQuery( function( $ ) {
|
||||
/**
|
||||
* Contains the current geo hash (or false if the hash
|
||||
* is not set/cannot be determined).
|
||||
*
|
||||
* @type {boolean|string}
|
||||
*/
|
||||
var geo_hash = false;
|
||||
|
||||
var this_page = window.location.toString();
|
||||
/**
|
||||
* Obtains the current geo hash from the `woocommerce_geo_hash` cookie, if set.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function get_geo_hash() {
|
||||
var geo_hash_cookie = Cookies.get( 'woocommerce_geo_hash' );
|
||||
|
||||
if ( 'string' === typeof geo_hash_cookie && geo_hash_cookie.length ) {
|
||||
geo_hash = geo_hash_cookie;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* If we have an active geo hash value but it does not match the `?v=` query var in
|
||||
* current page URL, that indicates that we need to refresh the page.
|
||||
*
|
||||
* @returns {boolean}
|
||||
*/
|
||||
function needs_refresh() {
|
||||
return geo_hash && ( new URLSearchParams( window.location.search ) ).get( 'v' ) !== geo_hash;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends (or replaces) the geo hash used for links on the current page.
|
||||
*/
|
||||
var $append_hashes = function() {
|
||||
if ( wc_geolocation_params.hash ) {
|
||||
$( 'a[href^="' + wc_geolocation_params.home_url + '"]:not(a[href*="v="]), a[href^="/"]:not(a[href*="v="])' ).each( function() {
|
||||
var $this = $( this ),
|
||||
href = $this.attr( 'href' ),
|
||||
href_parts = href.split( '#' );
|
||||
if ( ! geo_hash ) {
|
||||
return;
|
||||
}
|
||||
|
||||
href = href_parts[0];
|
||||
$( 'a[href^="' + wc_geolocation_params.home_url + '"]:not(a[href*="v="]), a[href^="/"]:not(a[href*="v="])' ).each( function() {
|
||||
var $this = $( this ),
|
||||
href = $this.attr( 'href' ),
|
||||
href_parts = href.split( '#' );
|
||||
|
||||
if ( href.indexOf( '?' ) > 0 ) {
|
||||
href = href + '&v=' + wc_geolocation_params.hash;
|
||||
} else {
|
||||
href = href + '?v=' + wc_geolocation_params.hash;
|
||||
}
|
||||
href = href_parts[0];
|
||||
|
||||
if ( typeof href_parts[1] !== 'undefined' && href_parts[1] !== null ) {
|
||||
href = href + '#' + href_parts[1];
|
||||
}
|
||||
if ( href.indexOf( '?' ) > 0 ) {
|
||||
href = href + '&v=' + geo_hash;
|
||||
} else {
|
||||
href = href + '?v=' + geo_hash;
|
||||
}
|
||||
|
||||
$this.attr( 'href', href );
|
||||
});
|
||||
if ( typeof href_parts[1] !== 'undefined' && href_parts[1] !== null ) {
|
||||
href = href + '#' + href_parts[1];
|
||||
}
|
||||
|
||||
$this.attr( 'href', href );
|
||||
});
|
||||
};
|
||||
|
||||
var $geolocate_customer = {
|
||||
url: wc_geolocation_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_customer_location' ),
|
||||
type: 'GET',
|
||||
success: function( response ) {
|
||||
if ( response.success && response.data.hash && response.data.hash !== geo_hash ) {
|
||||
$geolocation_redirect( response.data.hash );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Once we have a new hash, we redirect so a new version of the current page
|
||||
* (with correct pricing for the current region, etc) is displayed.
|
||||
*
|
||||
* @param {string} hash
|
||||
*/
|
||||
var $geolocation_redirect = function( hash ) {
|
||||
// Updates our (cookie-based) cache of the hash value. Expires in 1 hour.
|
||||
Cookies.set( 'woocommerce_geo_hash', hash, { expires: 1 / 24 } );
|
||||
|
||||
var this_page = window.location.toString();
|
||||
|
||||
if ( this_page.indexOf( '?v=' ) > 0 || this_page.indexOf( '&v=' ) > 0 ) {
|
||||
this_page = this_page.replace( /v=[^&]+/, 'v=' + hash );
|
||||
} else if ( this_page.indexOf( '?' ) > 0 ) {
|
||||
|
@ -39,50 +96,50 @@ jQuery( function( $ ) {
|
|||
window.location = this_page;
|
||||
};
|
||||
|
||||
var $geolocate_customer = {
|
||||
url: wc_geolocation_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'get_customer_location' ),
|
||||
type: 'GET',
|
||||
success: function( response ) {
|
||||
if ( response.success && response.data.hash && response.data.hash !== wc_geolocation_params.hash ) {
|
||||
$geolocation_redirect( response.data.hash );
|
||||
}
|
||||
/**
|
||||
* Updates any forms on the page so they use the current geo hash.
|
||||
*/
|
||||
function update_forms() {
|
||||
if ( ! geo_hash ) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if ( '1' === wc_geolocation_params.is_available ) {
|
||||
$.ajax( $geolocate_customer );
|
||||
|
||||
// Support form elements
|
||||
$( 'form' ).each( function() {
|
||||
var $this = $( this );
|
||||
$( 'form' ).each( function () {
|
||||
var $this = $( this );
|
||||
var method = $this.attr( 'method' );
|
||||
var hasField = $this.find('input[name="v"]').length > 0;
|
||||
var hasField = $this.find( 'input[name="v"]' ).length > 0;
|
||||
|
||||
if ( method && 'get' === method.toLowerCase() && !hasField ) {
|
||||
$this.append( '<input type="hidden" name="v" value="' + wc_geolocation_params.hash + '" />' );
|
||||
if ( method && 'get' === method.toLowerCase() && ! hasField ) {
|
||||
$this.append( '<input type="hidden" name="v" value="' + geo_hash + '" />' );
|
||||
} else {
|
||||
var href = $this.attr( 'action' );
|
||||
if ( href ) {
|
||||
if ( href.indexOf( '?' ) > 0 ) {
|
||||
$this.attr( 'action', href + '&v=' + wc_geolocation_params.hash );
|
||||
$this.attr( 'action', href + '&v=' + geo_hash );
|
||||
} else {
|
||||
$this.attr( 'action', href + '?v=' + wc_geolocation_params.hash );
|
||||
$this.attr( 'action', href + '?v=' + geo_hash );
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Append hashes on load
|
||||
$append_hashes();
|
||||
}
|
||||
|
||||
// Get the current geo hash. If it doesn't exist, or if it doesn't match the current
|
||||
// page URL, perform a geolocation request.
|
||||
if ( ! get_geo_hash() || needs_refresh() ) {
|
||||
$.ajax( $geolocate_customer );
|
||||
}
|
||||
|
||||
// Page updates.
|
||||
update_forms();
|
||||
$append_hashes();
|
||||
|
||||
$( document.body ).on( 'added_to_cart', function() {
|
||||
$append_hashes();
|
||||
});
|
||||
|
||||
|
||||
// Enable user to trigger manual append hashes on AJAX operations
|
||||
$( document.body ).on( 'woocommerce_append_geo_hashes', function() {
|
||||
$append_hashes();
|
||||
});
|
||||
|
||||
});
|
||||
|
|
|
@ -26,6 +26,7 @@ class WC_Cache_Helper {
|
|||
add_filter( 'nocache_headers', array( __CLASS__, 'additional_nocache_headers' ), 10 );
|
||||
add_action( 'shutdown', array( __CLASS__, 'delete_transients_on_shutdown' ), 10 );
|
||||
add_action( 'template_redirect', array( __CLASS__, 'geolocation_ajax_redirect' ) );
|
||||
add_action( 'wc_ajax_update_order_review', array( __CLASS__, 'update_geolocation_hash' ), 5 );
|
||||
add_action( 'admin_notices', array( __CLASS__, 'notices' ) );
|
||||
add_action( 'delete_version_transients', array( __CLASS__, 'delete_version_transients' ), 10 );
|
||||
add_action( 'wp', array( __CLASS__, 'prevent_caching' ) );
|
||||
|
@ -190,6 +191,24 @@ class WC_Cache_Helper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the `woocommerce_geo_hash` cookie, which is used to help ensure we display
|
||||
* the correct pricing etc to customers, according to their billing country.
|
||||
*
|
||||
* Note that:
|
||||
*
|
||||
* A) This only sets the cookie if the default customer address is set to "Geolocate (with
|
||||
* Page Caching Support)".
|
||||
*
|
||||
* B) It is hooked into the `wc_ajax_update_order_review` action, which has the benefit of
|
||||
* ensuring we update the cookie any time the billing country is changed.
|
||||
*/
|
||||
public static function update_geolocation_hash() {
|
||||
if ( 'geolocation_ajax' === get_option( 'woocommerce_default_customer_address' ) ) {
|
||||
wc_setcookie( 'woocommerce_geo_hash', static::geolocation_ajax_get_location_hash(), time() + HOUR_IN_SECONDS );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get transient version.
|
||||
*
|
||||
|
|
|
@ -398,7 +398,12 @@ class WC_Frontend_Scripts {
|
|||
self::enqueue_script( 'wc-single-product' );
|
||||
}
|
||||
|
||||
if ( 'geolocation_ajax' === get_option( 'woocommerce_default_customer_address' ) ) {
|
||||
// Only enqueue the geolocation script if the Default Current Address is set to "Geolocate
|
||||
// (with Page Caching Support) and outside of the cart, checkout, account and customizer preview.
|
||||
if (
|
||||
'geolocation_ajax' === get_option( 'woocommerce_default_customer_address' )
|
||||
&& ! ( is_cart() || is_account_page() || is_checkout() || is_customize_preview() )
|
||||
) {
|
||||
$ua = strtolower( wc_get_user_agent() ); // Exclude common bots from geolocation by user agent.
|
||||
|
||||
if ( ! strstr( $ua, 'bot' ) && ! strstr( $ua, 'spider' ) && ! strstr( $ua, 'crawl' ) ) {
|
||||
|
@ -473,8 +478,6 @@ class WC_Frontend_Scripts {
|
|||
$params = array(
|
||||
'wc_ajax_url' => WC_AJAX::get_endpoint( '%%endpoint%%' ),
|
||||
'home_url' => remove_query_arg( 'lang', home_url() ), // FIX for WPML compatibility.
|
||||
'is_available' => ! ( is_cart() || is_account_page() || is_checkout() || is_customize_preview() ) ? '1' : '0',
|
||||
'hash' => isset( $_GET['v'] ) ? wc_clean( wp_unslash( $_GET['v'] ) ) : '', // WPCS: input var ok, CSRF ok.
|
||||
);
|
||||
break;
|
||||
case 'wc-single-product':
|
||||
|
|
Loading…
Reference in New Issue