Fixed comparisons for ranges and wildcards
This commit is contained in:
parent
558211a869
commit
23271af0f6
|
@ -281,42 +281,56 @@ class WC_Tax {
|
|||
|
||||
// Query criteria - these will be ANDed
|
||||
$criteria = array();
|
||||
$criteria[] = $wpdb->prepare( "tax_rate_country IN ( %s, '' )", strtoupper( wc_clean( $country ) ) );
|
||||
$criteria[] = $wpdb->prepare( "tax_rate_state IN ( %s, '' )", strtoupper( wc_clean( $state ) ) );
|
||||
$criteria[] = $wpdb->prepare( "tax_rate_country IN ( %s, '' )", strtoupper( $country ) );
|
||||
$criteria[] = $wpdb->prepare( "tax_rate_state IN ( %s, '' )", strtoupper( $state ) );
|
||||
$criteria[] = $wpdb->prepare( "tax_rate_class = %s", sanitize_title( $tax_class ) );
|
||||
|
||||
// Location matching criteria - ORed
|
||||
$locations_criteria = array();
|
||||
$locations_criteria[] = "locations.location_type IS NULL"; // No locations matches all
|
||||
$locations_criteria[] = $wpdb->prepare( "locations.location_type = 'city' AND locations.location_code = %s", strtoupper( wc_clean( $city ) ) ); // City match
|
||||
$locations_criteria[] = "0 = (
|
||||
SELECT COUNT(*) FROM {$wpdb->prefix}woocommerce_tax_rate_locations as sublocations
|
||||
WHERE sublocations.location_type = 'city'
|
||||
AND sublocations.tax_rate_id = tax_rates.tax_rate_id
|
||||
)"; // No cities
|
||||
// Pre-query postcode ranges for PHP based matching.
|
||||
$postcode_search = wc_get_wildcard_postcodes( $postcode );
|
||||
$postcode_ranges = $wpdb->get_results( "SELECT tax_rate_id, location_code FROM {$wpdb->prefix}woocommerce_tax_rate_locations WHERE location_type = 'postcode' AND location_code LIKE '%-%';" );
|
||||
|
||||
$criteria[] = ' ( ' . implode( ' ) OR ( ', $locations_criteria ) . ' ) ';
|
||||
|
||||
// Pre-query for postcode range and wildcard matching
|
||||
$rates_with_postcodes = $wpdb->get_results( "SELECT tax_rate_id, location_code FROM {$wpdb->prefix}woocommerce_tax_rate_locations WHERE location_type = 'postcode';" );
|
||||
|
||||
if ( $rates_with_postcodes ) {
|
||||
$rates_with_postcodes_ids = array_unique( wp_list_pluck( $rates_with_postcodes, 'tax_rate_id' ) );
|
||||
$matches = wc_postcode_location_matcher( $postcode, $rates_with_postcodes, 'tax_rate_id', 'location_code' );
|
||||
$do_not_match = array_unique( array_diff( $rates_with_postcodes_ids, $matches ) );
|
||||
|
||||
// Do not match any rate with a postcode which didn't match the customer postcode
|
||||
if ( $do_not_match ) {
|
||||
$criteria[] = "tax_rates.tax_rate_id NOT IN (" . implode( ',', array_map( 'esc_sql', $do_not_match ) ) . ")";
|
||||
}
|
||||
if ( $postcode_ranges ) {
|
||||
$matches = wc_postcode_location_matcher( $postcode, $postcode_ranges, 'tax_rate_id', 'location_code' );
|
||||
$postcode_search = array_unique( array_merge( $postcode_search, array_values( $matches ) ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Location matching criteria - ORed
|
||||
* Needs to match:
|
||||
* - rates with no postcodes and cities
|
||||
* - rates with a matching postcode and city
|
||||
* - rates with matching postcode, no city
|
||||
* - rates with matching city, no postcode
|
||||
*/
|
||||
$locations_criteria = array();
|
||||
$locations_criteria[] = "locations.location_type IS NULL";
|
||||
$locations_criteria[] = "
|
||||
locations.location_type = 'postcode' AND locations.location_code IN ('" . implode( "','", array_map( 'esc_sql', $postcode_search ) ) . "')
|
||||
AND (
|
||||
( locations2.location_type = 'city' AND locations2.location_code = '" . esc_sql( strtoupper( $city ) ) . "' )
|
||||
OR NOT EXISTS (
|
||||
SELECT sub.tax_rate_id FROM {$wpdb->prefix}woocommerce_tax_rate_locations as sub
|
||||
WHERE sub.location_type = 'city'
|
||||
AND sub.tax_rate_id = tax_rates.tax_rate_id
|
||||
)
|
||||
)
|
||||
";
|
||||
$locations_criteria[] = "
|
||||
locations.location_type = 'city' AND locations.location_code = '" . esc_sql( strtoupper( $city ) ) . "'
|
||||
AND NOT EXISTS (
|
||||
SELECT sub.tax_rate_id FROM {$wpdb->prefix}woocommerce_tax_rate_locations as sub
|
||||
WHERE sub.location_type = 'postcode'
|
||||
AND sub.tax_rate_id = tax_rates.tax_rate_id
|
||||
)
|
||||
";
|
||||
$criteria[] = '( ( ' . implode( ' ) OR ( ', $locations_criteria ) . ' ) )';
|
||||
|
||||
$found_rates = $wpdb->get_results( "
|
||||
SELECT tax_rates.*
|
||||
FROM {$wpdb->prefix}woocommerce_tax_rates as tax_rates
|
||||
LEFT OUTER JOIN {$wpdb->prefix}woocommerce_tax_rate_locations as locations ON tax_rates.tax_rate_id = locations.tax_rate_id
|
||||
LEFT OUTER JOIN {$wpdb->prefix}woocommerce_tax_rate_locations as locations2 ON tax_rates.tax_rate_id = locations2.tax_rate_id
|
||||
WHERE 1=1 AND ( " . implode( ' ) AND ( ', $criteria ) . " )
|
||||
WHERE 1=1 AND " . implode( ' AND ', $criteria ) . "
|
||||
GROUP BY tax_rate_id
|
||||
ORDER BY tax_rate_priority, tax_rate_order
|
||||
" );
|
||||
|
|
|
@ -1248,19 +1248,18 @@ function wc_get_wildcard_postcodes( $postcode ) {
|
|||
* @param array $objects Array of postcode objects from Database
|
||||
* @param string $object_compare_key DB column name for the ID.
|
||||
* @param string $object_compare_key DB column name for the value.
|
||||
* @return array Array of matching IDs
|
||||
* @return array Array of matching object ID and values.
|
||||
*/
|
||||
function wc_postcode_location_matcher( $postcode, $objects, $object_id_key, $object_compare_key ) {
|
||||
$matches = array();
|
||||
$wildcard_postcodes = array_map( 'wc_clean', wc_get_wildcard_postcodes( $postcode ) );
|
||||
$postcodes = wp_list_pluck( $objects, $object_compare_key, $object_id_key );
|
||||
|
||||
foreach ( $objects as $object ) {
|
||||
$compare = $postcode;
|
||||
$compare_against = $object->$object_compare_key;
|
||||
$object_id = absint( $object->$object_id_key );
|
||||
foreach ( $postcodes as $object_id => $compare_against ) {
|
||||
$compare = $postcode;
|
||||
|
||||
// Handle postcodes containing ranges
|
||||
if ( strstr( '-', $compare_against ) ) {
|
||||
if ( strstr( $compare_against, '-' ) ) {
|
||||
$range = array_map( 'trim', explode( '-', $compare_against ) );
|
||||
|
||||
if ( 2 !== sizeof( $range ) ) {
|
||||
|
@ -1277,12 +1276,12 @@ function wc_postcode_location_matcher( $postcode, $objects, $object_id_key, $obj
|
|||
}
|
||||
|
||||
if ( $compare >= $min && $compare <= $max ) {
|
||||
$matches[] = $object_id;
|
||||
$matches[ $object_id ] = $compare_against;
|
||||
}
|
||||
|
||||
// Wildcard and standard comparison
|
||||
} elseif ( in_array( $compare_against, $wildcard_postcodes ) ) {
|
||||
$matches[] = $object_id;
|
||||
$matches[ $object_id ] = $compare_against;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue