Merge branch 'wc-geolocation'
This commit is contained in:
commit
f847b92a0f
|
@ -55,7 +55,8 @@ module.exports = function( grunt ) {
|
|||
'<%= dirs.js %>/admin/jquery.flot.resize.min.js': ['<%= dirs.js %>/admin/jquery.flot.resize.js'],
|
||||
'<%= dirs.js %>/admin/jquery.flot.stack.min.js': ['<%= dirs.js %>/admin/jquery.flot.stack.js'],
|
||||
'<%= dirs.js %>/admin/jquery.flot.time.min.js': ['<%= dirs.js %>/admin/jquery.flot.time.js'],
|
||||
'<%= dirs.js %>/jquery-payment/jquery.payment.min.js': ['<%= dirs.js %>/jquery-payment/jquery.payment.js']
|
||||
'<%= dirs.js %>/jquery-payment/jquery.payment.min.js': ['<%= dirs.js %>/jquery-payment/jquery.payment.js'],
|
||||
'<%= dirs.js %>/jquery-blockui/jquery.blockUI.min.js': ['<%= dirs.js %>/jquery-blockui/jquery.blockUI.js']
|
||||
}
|
||||
},
|
||||
frontend: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/*!
|
||||
* jQuery blockUI plugin
|
||||
* Version 2.66.0-2013.10.09
|
||||
* Version 2.70.0-2014.11.23
|
||||
* Requires jQuery v1.7 or later
|
||||
*
|
||||
* Examples at: http://malsup.com/jquery/block/
|
||||
|
@ -11,7 +11,6 @@
|
|||
*
|
||||
* Thanks to Amir-Hossein Sobhi for some excellent contributions!
|
||||
*/
|
||||
|
||||
;(function() {
|
||||
/*jshint eqeqeq:false curly:false latedef:false */
|
||||
"use strict";
|
||||
|
@ -107,7 +106,7 @@
|
|||
});
|
||||
};
|
||||
|
||||
$.blockUI.version = 2.66; // 2nd generation blocking at no extra cost!
|
||||
$.blockUI.version = 2.70; // 2nd generation blocking at no extra cost!
|
||||
|
||||
// override these in your code to change the default behavior and style
|
||||
$.blockUI.defaults = {
|
||||
|
@ -426,7 +425,7 @@
|
|||
if (msg)
|
||||
lyr3.show();
|
||||
if (opts.onBlock)
|
||||
opts.onBlock();
|
||||
opts.onBlock.bind(lyr3)();
|
||||
}
|
||||
|
||||
// bind key and mouse events
|
||||
|
@ -515,6 +514,7 @@
|
|||
if (data && data.el) {
|
||||
data.el.style.display = data.display;
|
||||
data.el.style.position = data.position;
|
||||
data.el.style.cursor = 'default'; // #59
|
||||
if (data.parent)
|
||||
data.parent.appendChild(data.el);
|
||||
$el.removeData('blockUI.history');
|
||||
|
@ -616,4 +616,4 @@
|
|||
setup(jQuery);
|
||||
}
|
||||
|
||||
})();
|
||||
})();
|
File diff suppressed because one or more lines are too long
|
@ -525,7 +525,7 @@ abstract class WC_Abstract_Order {
|
|||
|
||||
if ( 'base' === $tax_based_on ) {
|
||||
|
||||
$default = wc_get_default_location();
|
||||
$default = wc_get_base_location();
|
||||
$country = $default['country'];
|
||||
$state = $default['state'];
|
||||
$postcode = '';
|
||||
|
|
|
@ -44,12 +44,13 @@ return apply_filters( 'woocommerce_tax_settings', array(
|
|||
array(
|
||||
'title' => __( 'Default Customer Address:', 'woocommerce' ),
|
||||
'id' => 'woocommerce_default_customer_address',
|
||||
'desc_tip' => __( 'This option determines the customers default address (before they input their own).', 'woocommerce' ),
|
||||
'default' => 'base',
|
||||
'desc_tip' => __( 'This option determines the customers default address (before they input their details).', 'woocommerce' ),
|
||||
'default' => 'geolocation',
|
||||
'type' => 'select',
|
||||
'options' => array(
|
||||
'' => __( 'No address', 'woocommerce' ),
|
||||
'base' => __( 'Shop base address', 'woocommerce' ),
|
||||
'' => __( 'No address', 'woocommerce' ),
|
||||
'base' => __( 'Shop base address', 'woocommerce' ),
|
||||
'geolocation' => __( 'Geolocate address', 'woocommerce' ),
|
||||
),
|
||||
),
|
||||
|
||||
|
|
|
@ -118,10 +118,8 @@ class WC_Countries {
|
|||
* @return string
|
||||
*/
|
||||
public function get_base_country() {
|
||||
$default = esc_attr( get_option('woocommerce_default_country') );
|
||||
$country = ( ( $pos = strrpos( $default, ':' ) ) === false ) ? $default : substr( $default, 0, $pos );
|
||||
|
||||
return apply_filters( 'woocommerce_countries_base_country', $country );
|
||||
$default = wc_get_base_location();
|
||||
return apply_filters( 'woocommerce_countries_base_country', $default['country'] );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -131,10 +129,8 @@ class WC_Countries {
|
|||
* @return string
|
||||
*/
|
||||
public function get_base_state() {
|
||||
$default = wc_clean( get_option( 'woocommerce_default_country' ) );
|
||||
$state = ( ( $pos = strrpos( $default, ':' ) ) === false ) ? '' : substr( $default, $pos + 1 );
|
||||
|
||||
return apply_filters( 'woocommerce_countries_base_state', $state );
|
||||
$default = wc_get_base_location();
|
||||
return apply_filters( 'woocommerce_countries_base_state', $default['state'] );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,7 +32,7 @@ class WC_Customer {
|
|||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_data;
|
||||
protected $_data = array();
|
||||
|
||||
/**
|
||||
* Stores bool when data is changed
|
||||
|
@ -49,15 +49,12 @@ class WC_Customer {
|
|||
$this->_data = WC()->session->get( 'customer' );
|
||||
|
||||
if ( empty( $this->_data ) ) {
|
||||
// Defaults
|
||||
$this->_data = array(
|
||||
'country' => esc_html( $this->get_default_country() ),
|
||||
'state' => '',
|
||||
'postcode' => '',
|
||||
'city' => '',
|
||||
'address' => '',
|
||||
'address_2' => '',
|
||||
'shipping_country' => esc_html( $this->get_default_country() ),
|
||||
'shipping_state' => '',
|
||||
'shipping_postcode' => '',
|
||||
'shipping_city' => '',
|
||||
'shipping_address' => '',
|
||||
|
@ -65,6 +62,9 @@ class WC_Customer {
|
|||
'is_vat_exempt' => false,
|
||||
'calculated_shipping' => false
|
||||
);
|
||||
|
||||
$this->_data['country'] = $this->_data['shipping_country'] = $this->get_default_country();
|
||||
$this->_data['state'] = $this->_data['shipping_state'] = $this->get_default_state();
|
||||
}
|
||||
|
||||
// When leaving or ending page load, store data
|
||||
|
@ -116,8 +116,7 @@ class WC_Customer {
|
|||
* @return string
|
||||
*/
|
||||
public function get_default_country() {
|
||||
$default = wc_get_default_location();
|
||||
|
||||
$default = wc_get_customer_default_location();
|
||||
return $default['country'];
|
||||
}
|
||||
|
||||
|
@ -126,8 +125,7 @@ class WC_Customer {
|
|||
* @return string
|
||||
*/
|
||||
public function get_default_state() {
|
||||
$default = wc_get_default_location();
|
||||
|
||||
$default = wc_get_customer_default_location();
|
||||
return $default['state'];
|
||||
}
|
||||
|
||||
|
@ -170,7 +168,7 @@ class WC_Customer {
|
|||
|
||||
if ( $country ) {
|
||||
|
||||
$default = wc_get_default_location();
|
||||
$default = wc_get_base_location();
|
||||
|
||||
if ( $default['country'] !== $country ) {
|
||||
return true;
|
||||
|
@ -329,8 +327,7 @@ class WC_Customer {
|
|||
|
||||
if ( $tax_based_on == 'base' ) {
|
||||
|
||||
$default = wc_get_default_location();
|
||||
|
||||
$default = wc_get_base_location();
|
||||
$country = $default['country'];
|
||||
$state = $default['state'];
|
||||
$postcode = '';
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
<?php
|
||||
/**
|
||||
* Geolocation class.
|
||||
*
|
||||
* Handles geolocation and updating the geolocation database.
|
||||
*
|
||||
* This product uses GeoLite2 data created by MaxMind, available from http://www.maxmind.com
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category Admin
|
||||
* @package WooCommerce/Classes
|
||||
* @version 2.3.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Geolocation Class
|
||||
*/
|
||||
class WC_Geolocation {
|
||||
|
||||
/** URL to the geolocation database we're using */
|
||||
const GEOLITE_DB = 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz';
|
||||
|
||||
/** @var array API endpoints for looking up user IP address */
|
||||
private static $ip_lookup_apis = array(
|
||||
'icanhazip' => 'http://ipv4.icanhazip.com',
|
||||
'ipify' => 'http://api.ipify.org/',
|
||||
'ipecho' => 'http://ipecho.net/plain',
|
||||
'ident' => 'http://v4.ident.me',
|
||||
'whatismyipaddress' => 'http://bot.whatismyipaddress.com',
|
||||
'ip.appspot' => 'http://ip.appspot.com'
|
||||
);
|
||||
|
||||
/** @var array API endpoints for geolocating an IP address */
|
||||
private static $geoip_apis = array(
|
||||
'freegeoip' => 'https://freegeoip.net/json/%s',
|
||||
'telize' => 'http://www.telize.com/geoip/%s',
|
||||
'ip-api' => 'http://ip-api.com/json/%s',
|
||||
'geoip-api.meteor' => 'http://geoip-api.meteor.com/lookup/%s'
|
||||
);
|
||||
|
||||
/**
|
||||
* Hook in tabs.
|
||||
*/
|
||||
public static function init() {
|
||||
add_action( 'woocommerce_geoip_updater', array( __CLASS__, 'update_database' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current user IP Address
|
||||
* @return string
|
||||
*/
|
||||
public static function get_ip_address() {
|
||||
return isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user IP Address using a service
|
||||
* @return string
|
||||
*/
|
||||
public static function get_external_ip_address() {
|
||||
$transient_name = 'external_ip_address_' . self::get_ip_address();
|
||||
$external_ip_address = get_transient( $transient_name );
|
||||
|
||||
if ( false === $external_ip_address ) {
|
||||
$external_ip_address = '0.0.0.0';
|
||||
$ip_lookup_services = apply_filters( 'woocommerce_geolocation_ip_lookup_apis', self::$ip_lookup_apis );
|
||||
$ip_lookup_services_keys = array_keys( $ip_lookup_services );
|
||||
shuffle( $ip_lookup_services_keys );
|
||||
|
||||
foreach ( $ip_lookup_services_keys as $service_name ) {
|
||||
$service_endpoint = $ip_lookup_services[ $service_name ];
|
||||
$response = wp_remote_get( $service_endpoint, array( 'timeout' => 2 ) );
|
||||
|
||||
if ( ! is_wp_error( $response ) && $response['body'] ) {
|
||||
$external_ip_address = apply_filters( 'woocommerce_geolocation_ip_lookup_api_response', $response['body'], $service_name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
set_transient( $transient_name, $external_ip_address, WEEK_IN_SECONDS );
|
||||
}
|
||||
|
||||
return $external_ip_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* Geolocate an IP address
|
||||
* @param string $ip_address
|
||||
* @return array
|
||||
*/
|
||||
public static function geolocate_ip( $ip_address = '', $fallback = true ) {
|
||||
// If GEOIP is enabled in CloudFlare, we can use that (Settings -> CloudFlare Settings -> Settings Overview)
|
||||
if ( ! empty( $_SERVER[ "HTTP_CF_IPCOUNTRY" ] ) ) {
|
||||
$country_code = sanitize_text_field( strtoupper( $_SERVER["HTTP_CF_IPCOUNTRY"] ) );
|
||||
} else {
|
||||
$ip_address = $ip_address ? $ip_address : self::get_ip_address();
|
||||
|
||||
if ( file_exists( self::get_local_database_path() ) ) {
|
||||
$country_code = self::geolocate_via_db( $ip_address );
|
||||
} else {
|
||||
$country_code = self::geolocate_via_api( $ip_address );
|
||||
}
|
||||
|
||||
if ( ! $country_code && $fallback ) {
|
||||
// May be a local environment - find external IP
|
||||
return self::geolocate_ip( self::get_external_ip_address(), false );
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
'country' => $country_code,
|
||||
'state' => ''
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Path to our local db
|
||||
* @return string
|
||||
*/
|
||||
private static function get_local_database_path() {
|
||||
$upload_dir = wp_upload_dir();
|
||||
return $upload_dir['basedir'] . '/GeoIP.dat';
|
||||
}
|
||||
|
||||
/**
|
||||
* Update geoip database. Adapted from https://wordpress.org/plugins/geoip-detect/.
|
||||
*/
|
||||
public static function update_database() {
|
||||
require_once( ABSPATH . 'wp-admin/includes/file.php' );
|
||||
|
||||
$tmp_database = download_url( self::GEOLITE_DB );
|
||||
$logger = new WC_Logger();
|
||||
|
||||
if ( ! is_wp_error( $tmp_database ) ) {
|
||||
$gzhandle = @gzopen( $tmp_database, 'r' );
|
||||
$handle = @fopen( self::get_local_database_path(), 'w' );
|
||||
|
||||
if ( $gzhandle && $handle ) {
|
||||
while ( ( $string = gzread( $gzhandle, 4096 ) ) != false ) {
|
||||
fwrite( $handle, $string, strlen( $string ) );
|
||||
}
|
||||
gzclose( $gzhandle );
|
||||
fclose( $handle );
|
||||
} else {
|
||||
$logger->add( 'geolocation', 'Unable to open database file' );
|
||||
}
|
||||
@unlink( $tmp_database );
|
||||
} else {
|
||||
$logger->add( 'geolocation', 'Unable to download GeoIP Database: ' . $tmp_database->get_message() );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use MAXMIND GeoLite database to geolocation the user.
|
||||
* @param string $ip_address
|
||||
* @return string
|
||||
*/
|
||||
private static function geolocate_via_db( $ip_address ) {
|
||||
if ( ! class_exists( 'GeoIP' ) && ! class_exists( 'geoiprecord' ) ) {
|
||||
include_once( 'libraries/geoip.php' );
|
||||
}
|
||||
$database = self::get_local_database_path();
|
||||
$gi = geoip_open( $database, GEOIP_STANDARD );
|
||||
$country_code = geoip_country_code_by_addr( $gi, $ip_address );
|
||||
geoip_close( $gi );
|
||||
|
||||
return sanitize_text_field( strtoupper( $country_code ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Use APIs to Geolocate the user.
|
||||
* @param string $ip_address
|
||||
* @return string|bool
|
||||
*/
|
||||
private static function geolocate_via_api( $ip_address ) {
|
||||
$country_code = get_transient( 'geoip_' . $ip_address );
|
||||
|
||||
if ( false === $country_code ) {
|
||||
$geoip_services = apply_filters( 'woocommerce_geolocation_geoip_apis', self::$geoip_apis );
|
||||
$geoip_services_keys = array_keys( $geoip_services );
|
||||
shuffle( $geoip_services_keys );
|
||||
|
||||
foreach ( $geoip_services_keys as $service_name ) {
|
||||
$service_endpoint = $geoip_services[ $service_name ];
|
||||
$response = wp_remote_get( sprintf( $service_endpoint, $ip_address ), array( 'timeout' => 2 ) );
|
||||
|
||||
if ( ! is_wp_error( $response ) && $response['body'] ) {
|
||||
$country_code = '';
|
||||
|
||||
switch ( $service_name ) {
|
||||
case 'ip-api' :
|
||||
$data = json_decode( $response['body'] );
|
||||
$country_code = isset( $data->countryCode ) ? $data->countryCode : '';
|
||||
break;
|
||||
case 'geoip-api.meteor' :
|
||||
$data = json_decode( $response['body'] );
|
||||
$country_code = isset( $data->country ) ? $data->country : '';
|
||||
break;
|
||||
case 'freegeoip' :
|
||||
case 'telize' :
|
||||
$data = json_decode( $response['body'] );
|
||||
$country_code = isset( $data->country_code ) ? $data->country_code : '';
|
||||
break;
|
||||
default :
|
||||
$country_code = apply_filters( 'woocommerce_geolocation_geoip_response_' . $service_name, '', $response['body'] );
|
||||
break;
|
||||
}
|
||||
|
||||
$country_code = sanitize_text_field( strtoupper( $country_code ) );
|
||||
|
||||
if ( $country_code ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_transient( 'geoip_' . $ip_address, $country_code, WEEK_IN_SECONDS );
|
||||
}
|
||||
|
||||
return $country_code;
|
||||
}
|
||||
}
|
||||
|
||||
WC_Geolocation::init();
|
|
@ -125,6 +125,7 @@ class WC_Install {
|
|||
|
||||
// Flush rules after install
|
||||
flush_rewrite_rules();
|
||||
delete_transient( 'wc_attribute_taxonomies' );
|
||||
|
||||
// Redirect to welcome screen
|
||||
set_transient( '_wc_activation_redirect', 1, HOUR_IN_SECONDS );
|
||||
|
@ -160,6 +161,7 @@ class WC_Install {
|
|||
wp_clear_scheduled_hook( 'woocommerce_cancel_unpaid_orders' );
|
||||
wp_clear_scheduled_hook( 'woocommerce_cleanup_sessions' );
|
||||
wp_clear_scheduled_hook( 'woocommerce_language_pack_updater_check' );
|
||||
wp_clear_scheduled_hook( 'woocommerce_geoip_updater' );
|
||||
|
||||
$ve = get_option( 'gmt_offset' ) > 0 ? '+' : '-';
|
||||
|
||||
|
@ -173,6 +175,8 @@ class WC_Install {
|
|||
|
||||
wp_schedule_event( time(), 'twicedaily', 'woocommerce_cleanup_sessions' );
|
||||
wp_schedule_single_event( time(), 'woocommerce_language_pack_updater_check' );
|
||||
wp_schedule_single_event( time(), 'woocommerce_geoip_updater' );
|
||||
wp_schedule_event( strtotime( 'first tuesday of next month' ), 'monthly', 'woocommerce_geoip_updater' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -337,9 +337,9 @@ class WC_Tax {
|
|||
public static function get_tax_location( $tax_class = '' ) {
|
||||
$location = array();
|
||||
|
||||
if ( defined( 'WOOCOMMERCE_CHECKOUT' ) || ( ! empty( WC()->customer ) && WC()->customer->has_calculated_shipping() ) ) {
|
||||
if ( ! empty( WC()->customer ) ) {
|
||||
$location = WC()->customer->get_taxable_address();
|
||||
} elseif ( wc_prices_include_tax() || get_option( 'woocommerce_default_customer_address' ) == 'base' ) {
|
||||
} elseif ( wc_prices_include_tax() || 'base' === get_option( 'woocommerce_default_customer_address' ) ) {
|
||||
$location = array(
|
||||
WC()->countries->get_base_country(),
|
||||
WC()->countries->get_base_state(),
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -681,23 +681,59 @@ function wc_deliver_webhook_async( $webhook_id, $arg ) {
|
|||
add_action( 'woocommerce_deliver_webhook_async', 'wc_deliver_webhook_async', 10, 2 );
|
||||
|
||||
/**
|
||||
* Get the default location
|
||||
*
|
||||
* Formats a string in the format COUNTRY:STATE into an array.
|
||||
* @since 2.3.0
|
||||
* @param string $country_string
|
||||
* @return array
|
||||
*/
|
||||
function wc_get_default_location() {
|
||||
$default = apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) );
|
||||
|
||||
if ( strstr( $default, ':' ) ) {
|
||||
list( $country, $state ) = explode( ':', $default );
|
||||
function wc_format_country_state_string( $country_string ) {
|
||||
if ( strstr( $country_string, ':' ) ) {
|
||||
list( $country, $state ) = explode( ':', $country_string );
|
||||
} else {
|
||||
$country = $default;
|
||||
$country = $country_string;
|
||||
$state = '';
|
||||
}
|
||||
|
||||
return array(
|
||||
'country' => $country,
|
||||
'state' => $state
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the store's base location.
|
||||
* @todo should the woocommerce_default_country option be renamed to contain 'base'?
|
||||
* @since 2.3.0
|
||||
* @return array
|
||||
*/
|
||||
function wc_get_base_location() {
|
||||
$default = apply_filters( 'woocommerce_get_base_location', get_option( 'woocommerce_default_country' ) );
|
||||
|
||||
return wc_format_country_state_string( $default );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the customer's default location. Filtered, and set to base location or left blank.
|
||||
* @todo should the woocommerce_default_country option be renamed to contain 'base'?
|
||||
* @since 2.3.0
|
||||
* @return array
|
||||
*/
|
||||
function wc_get_customer_default_location() {
|
||||
switch ( get_option( 'woocommerce_default_customer_address' ) ) {
|
||||
case 'geolocation' :
|
||||
$location = WC_Geolocation::geolocate_ip();
|
||||
|
||||
// Base fallback
|
||||
if ( empty( $location['country'] ) ) {
|
||||
$location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
|
||||
}
|
||||
break;
|
||||
case 'base' :
|
||||
$location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
|
||||
break;
|
||||
default :
|
||||
$location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', '' ) );
|
||||
break;
|
||||
}
|
||||
|
||||
return $location;
|
||||
}
|
||||
|
|
|
@ -202,6 +202,7 @@ final class WooCommerce {
|
|||
include_once( 'includes/wc-widget-functions.php' );
|
||||
include_once( 'includes/wc-webhook-functions.php' );
|
||||
include_once( 'includes/class-wc-install.php' );
|
||||
include_once( 'includes/class-wc-geolocation.php' );
|
||||
include_once( 'includes/class-wc-download-handler.php' );
|
||||
include_once( 'includes/class-wc-comments.php' );
|
||||
include_once( 'includes/class-wc-post-data.php' );
|
||||
|
|
Loading…
Reference in New Issue