Last active
June 23, 2021 21:26
-
-
Save igorbenic/97ffa507052b7d0583affc841271807d to your computer and use it in GitHub Desktop.
How to use the WooCommerce Postcode Validator | https://www.ibenic.com/woocommerce-postcode-validator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Shipping method id: rp_table_rate | |
* You can use any ID here and replace rp_table_rate to add this field to your shipping method settings page. | |
*/ | |
add_filter( 'woocommerce_settings_api_form_fields_rp_table_rate', 'ibenic_add_postcodes_field_a_shipping_method' ); | |
/** | |
* Add Postcodes field to the Table Rate | |
* | |
* @param array $fields | |
* | |
* @return mixed | |
*/ | |
function ibenic_add_postcodes_field_a_shipping_method( $fields ) { | |
// Unset it so that we can set it back and have it at the last place. | |
unset( $fields['domestic_shipping_table']); | |
// Adding postcodes field | |
$fields['postcodes'] = array( | |
'title' => __( 'ZIP Codes', 'ibenic-table-rates' ), | |
'type' => 'textarea', | |
'class' => 'widefat', | |
'css' => 'width: 450px;', | |
'default' => '', | |
'description' => sprintf( __( 'Postcodes containing wildcards (e.g. CB23*) or fully numeric ranges (e.g. <code>90210...99000</code>) are also supported. Please see the shipping zones <a href="%s" target="_blank">documentation</a>) for more information.', 'woocommerce' ), 'https://docs.woocommerce.com/document/setting-up-shipping-zones/#section-3' ), | |
); | |
$fields['domestic_shipping_table'] = array( | |
'type' => 'shipping_table' | |
); | |
return $fields; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Shipping method id: rp_table_rate | |
* You can use any ID here and replace rp_table_rate to add this field to your shipping method settings page. | |
*/ | |
add_filter( 'woocommerce_shipping_rp_table_rate_is_available', 'ibenic_is_shipping_method_available', 20, 3 ); | |
/** | |
* Check if the Table Rate is available or not. | |
* | |
* @param $available | |
* @param $package | |
* @param WC_Shipping_Method $method | |
*/ | |
function ibenic_is_shipping_method_available( $available, $package, $method ) { | |
if ( ! $available ) { | |
return $available; | |
} | |
$compare_codes = $method->get_option( 'postcodes', '' ); | |
if ( ! $compare_codes ) { | |
return $available; | |
} | |
$postcodes = array_filter( array_map( 'strtoupper', array_map( 'wc_clean', explode( "\n", $compare_codes ) ) ) ); | |
if ( ! $postcodes ) { | |
return $available; | |
} | |
$shipping_code = $package['destination']['postcode']; | |
$country = $package['destination']['country']; | |
$objects = array(); | |
// Building our own objects | |
foreach ( $postcodes as $index => $postcode ) { | |
$object = new stdClass(); | |
$object->id = $index; | |
$object->postcode = $postcode; | |
$objects[] = $object; | |
} | |
$matches = wc_postcode_location_matcher( $shipping_code, $objects, 'id', 'postcode', $country ); | |
// We did not find any matching postcodes? Return it as not available. | |
if ( ! $matches ) { | |
return false; | |
} | |
return true; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* Used by shipping zones and taxes to compare a given $postcode to stored | |
* postcodes to find matches for numerical ranges, and wildcards. | |
* | |
* @since 2.6.0 | |
* @param string $postcode Postcode you want to match against stored postcodes. | |
* @param array $objects Array of postcode objects from Database. | |
* @param string $object_id_key DB column name for the ID. | |
* @param string $object_compare_key DB column name for the value. | |
* @param string $country Country from which this postcode belongs. Allows for formatting. | |
* @return array Array of matching object ID and matching values. | |
*/ | |
function wc_postcode_location_matcher( $postcode, $objects, $object_id_key, $object_compare_key, $country = '' ) { | |
$postcode = wc_normalize_postcode( $postcode ); | |
$wildcard_postcodes = array_map( 'wc_clean', wc_get_wildcard_postcodes( $postcode, $country ) ); | |
$matches = array(); | |
foreach ( $objects as $object ) { | |
$object_id = $object->$object_id_key; | |
$compare_against = $object->$object_compare_key; | |
// Handle postcodes containing ranges. | |
if ( strstr( $compare_against, '...' ) ) { | |
$range = array_map( 'trim', explode( '...', $compare_against ) ); | |
if ( 2 !== count( $range ) ) { | |
continue; | |
} | |
list( $min, $max ) = $range; | |
// If the postcode is non-numeric, make it numeric. | |
if ( ! is_numeric( $min ) || ! is_numeric( $max ) ) { | |
$compare = wc_make_numeric_postcode( $postcode ); | |
$min = str_pad( wc_make_numeric_postcode( $min ), strlen( $compare ), '0' ); | |
$max = str_pad( wc_make_numeric_postcode( $max ), strlen( $compare ), '0' ); | |
} else { | |
$compare = $postcode; | |
} | |
if ( $compare >= $min && $compare <= $max ) { | |
$matches[ $object_id ] = isset( $matches[ $object_id ] ) ? $matches[ $object_id ] : array(); | |
$matches[ $object_id ][] = $compare_against; | |
} | |
} elseif ( in_array( $compare_against, $wildcard_postcodes, true ) ) { | |
// Wildcard and standard comparison. | |
$matches[ $object_id ] = isset( $matches[ $object_id ] ) ? $matches[ $object_id ] : array(); | |
$matches[ $object_id ][] = $compare_against; | |
} | |
} | |
return $matches; | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Postcode range and wildcard matching. | |
$postcode_locations = $wpdb->get_results( "SELECT zone_id, location_code FROM {$wpdb->prefix}woocommerce_shipping_zone_locations WHERE location_type = 'postcode';" ); | |
if ( $postcode_locations ) { | |
$zone_ids_with_postcode_rules = array_map( 'absint', wp_list_pluck( $postcode_locations, 'zone_id' ) ); | |
$matches = wc_postcode_location_matcher( $postcode, $postcode_locations, 'zone_id', 'location_code', $country ); | |
$do_not_match = array_unique( array_diff( $zone_ids_with_postcode_rules, array_keys( $matches ) ) ); | |
if ( ! empty( $do_not_match ) ) { | |
$criteria[] = 'AND zones.zone_id NOT IN (' . implode( ',', $do_not_match ) . ')'; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment