Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
f1035dedd0
|
@ -6,35 +6,237 @@ jQuery( function( $ ) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Shipping calculator
|
||||
$( document ).on( 'click', '.shipping-calculator-button', function() {
|
||||
$( '.shipping-calculator-form' ).slideToggle( 'slow' );
|
||||
return false;
|
||||
}).on( 'change', 'select.shipping_method, input[name^=shipping_method]', function() {
|
||||
var shipping_methods = [];
|
||||
// Gets a url for a given AJAX endpoint.
|
||||
var get_url = function( endpoint ) {
|
||||
return wc_cart_params.wc_ajax_url.toString().replace(
|
||||
'%%endpoint%%',
|
||||
endpoint
|
||||
);
|
||||
};
|
||||
|
||||
$( 'select.shipping_method, input[name^=shipping_method][type=radio]:checked, input[name^=shipping_method][type=hidden]' ).each( function() {
|
||||
shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val();
|
||||
});
|
||||
// Check if a node is blocked for processing.
|
||||
var is_blocked = function( $node ) {
|
||||
return $node.is( '.processing' );
|
||||
};
|
||||
|
||||
$( 'div.cart_totals' ).block({
|
||||
// Block a node for processing.
|
||||
var block = function( $node ) {
|
||||
$node.addClass( 'processing' ).block( {
|
||||
message: null,
|
||||
overlayCSS: {
|
||||
background: '#fff',
|
||||
opacity: 0.6
|
||||
}
|
||||
});
|
||||
} );
|
||||
};
|
||||
|
||||
// Unblock a node after processing is complete.
|
||||
var unblock = function( $node ) {
|
||||
$node.removeClass( 'processing' ).unblock();
|
||||
};
|
||||
|
||||
// Updates the .woocommerce div with a string of html.
|
||||
var update_wc_div = function( html_str ) {
|
||||
var $html = $.parseHTML( html_str );
|
||||
var $new_div = $( 'div.woocommerce', $html );
|
||||
$( 'div.woocommerce' ).replaceWith( $new_div );
|
||||
};
|
||||
|
||||
// Shipping calculator
|
||||
$( document ).on( 'click', '.shipping-calculator-button', function() {
|
||||
$( '.shipping-calculator-form' ).slideToggle( 'slow' );
|
||||
return false;
|
||||
} ).on( 'change', 'select.shipping_method, input[name^=shipping_method]', function() {
|
||||
var shipping_methods = [];
|
||||
|
||||
$( 'select.shipping_method, input[name^=shipping_method][type=radio]:checked, input[name^=shipping_method][type=hidden]' ).each( function() {
|
||||
shipping_methods[ $( this ).data( 'index' ) ] = $( this ).val();
|
||||
} );
|
||||
|
||||
block( $( 'div.cart_totals' ) );
|
||||
|
||||
var data = {
|
||||
security: wc_cart_params.update_shipping_method_nonce,
|
||||
shipping_method: shipping_methods
|
||||
};
|
||||
|
||||
$.post( wc_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'update_shipping_method' ), data, function( response ) {
|
||||
$.post( get_url( 'update_shipping_method' ), data, function( response ) {
|
||||
$( 'div.cart_totals' ).replaceWith( response );
|
||||
$( document.body ).trigger( 'updated_shipping_method' );
|
||||
});
|
||||
});
|
||||
} );
|
||||
} );
|
||||
|
||||
$( document ).on( 'submit', 'form.woocommerce-shipping-calculator', function( evt ) {
|
||||
evt.preventDefault();
|
||||
|
||||
var $form = $( evt.target );
|
||||
|
||||
block( $form );
|
||||
|
||||
// Provide the submit button value because wc-form-handler expects it.
|
||||
$( '<input />' ).attr( 'type', 'hidden' )
|
||||
.attr( 'name', 'calc_shipping' )
|
||||
.attr( 'value', 'x' )
|
||||
.appendTo( $form );
|
||||
|
||||
// Make call to actual form post URL.
|
||||
$.ajax( {
|
||||
type: $form.attr( 'method' ),
|
||||
url: $form.attr( 'action' ),
|
||||
data: $form.serialize(),
|
||||
dataType: 'html',
|
||||
success: function( response ) {
|
||||
update_wc_div(response );
|
||||
},
|
||||
complete: function() {
|
||||
unblock( $form );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
$( '.shipping-calculator-form' ).hide();
|
||||
});
|
||||
|
||||
// Update the cart after something has changed.
|
||||
var update_cart_totals = function() {
|
||||
block( $( 'div.cart_totals' ) );
|
||||
|
||||
$.ajax( {
|
||||
url: get_url( 'get_cart_totals' ),
|
||||
dataType: 'html',
|
||||
success: function( response ) {
|
||||
$( 'div.cart_totals' ).replaceWith( response );
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
// clears previous notices and shows new one above form.
|
||||
var show_notice = function( html_element ) {
|
||||
var $form = $( 'div.woocommerce > form' );
|
||||
|
||||
$( '.woocommerce-error, .woocommerce-message' ).remove();
|
||||
$form.before( html_element );
|
||||
};
|
||||
|
||||
// Handle form submit and route to correct logic.
|
||||
$( document ).on( 'submit', 'div.woocommerce > form', function( evt ) {
|
||||
evt.preventDefault();
|
||||
|
||||
var $form = $( evt.target );
|
||||
var $submit = $( document.activeElement );
|
||||
|
||||
window.console.log( $submit );
|
||||
|
||||
if ( is_blocked( $form ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( $submit.is( '[name="update_cart"]' ) || $submit.is( 'input.qty' ) ) {
|
||||
window.console.log( 'update cart' );
|
||||
quantity_update( $form );
|
||||
|
||||
} else if ( $submit.is( '[name="apply_coupon"]' ) || $submit.is( '#coupon_code' ) ) {
|
||||
window.console.log( 'apply coupon' );
|
||||
apply_coupon( $form );
|
||||
}
|
||||
} );
|
||||
|
||||
// Coupon code
|
||||
var apply_coupon = function( $form ) {
|
||||
block( $form );
|
||||
|
||||
var $text_field = $( '#coupon_code' );
|
||||
var coupon_code = $text_field.val();
|
||||
|
||||
var data = {
|
||||
security: wc_cart_params.apply_coupon_nonce,
|
||||
coupon_code: coupon_code
|
||||
};
|
||||
|
||||
$.ajax( {
|
||||
type: 'POST',
|
||||
url: get_url( 'apply_coupon' ),
|
||||
data: data,
|
||||
dataType: 'html',
|
||||
success: function( response ) {
|
||||
show_notice( response );
|
||||
},
|
||||
complete: function() {
|
||||
unblock( $form );
|
||||
$text_field.val( '' );
|
||||
update_cart_totals();
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
$( document ).on( 'click', 'a.woocommerce-remove-coupon', function( evt ) {
|
||||
evt.preventDefault();
|
||||
|
||||
var $tr = $( this ).parents( 'tr' );
|
||||
var coupon = $( this ).attr( 'data-coupon' );
|
||||
|
||||
block( $tr.parents( 'table' ) );
|
||||
|
||||
var data = {
|
||||
security: wc_cart_params.remove_coupon_nonce,
|
||||
coupon: coupon
|
||||
};
|
||||
|
||||
$.ajax( {
|
||||
type: 'POST',
|
||||
url: get_url( 'remove_coupon' ),
|
||||
data: data,
|
||||
dataType: 'html',
|
||||
success: function( response ) {
|
||||
show_notice( response );
|
||||
unblock( $tr.parents( 'table' ) );
|
||||
},
|
||||
complete: function() {
|
||||
update_cart_totals();
|
||||
}
|
||||
} );
|
||||
} );
|
||||
|
||||
// Quantity Update
|
||||
var quantity_update = function( $form ) {
|
||||
|
||||
// Provide the submit button value because wc-form-handler expects it.
|
||||
$( '<input />' ).attr( 'type', 'hidden' )
|
||||
.attr( 'name', 'update_cart' )
|
||||
.attr( 'value', 'Update Cart' )
|
||||
.appendTo( $form );
|
||||
|
||||
block( $form );
|
||||
|
||||
// Make call to actual form post URL.
|
||||
$.ajax( {
|
||||
type: $form.attr( 'method' ),
|
||||
url: $form.attr( 'action' ),
|
||||
data: $form.serialize(),
|
||||
dataType: 'html',
|
||||
success: update_wc_div,
|
||||
complete: function() {
|
||||
unblock( $form );
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
// Item Remove
|
||||
$( document ).on( 'click', 'td.product-remove > a', function( evt ) {
|
||||
evt.preventDefault();
|
||||
|
||||
var $a = $( evt.target );
|
||||
var $form = $a.parents( 'form' );
|
||||
|
||||
block( $form );
|
||||
|
||||
$.ajax( {
|
||||
type: 'GET',
|
||||
url: $a.attr( 'href' ),
|
||||
dataType: 'html',
|
||||
success: update_wc_div,
|
||||
complete: function() {
|
||||
unblock( $form );
|
||||
}
|
||||
} );
|
||||
} );
|
||||
} );
|
||||
|
|
|
@ -1 +1 @@
|
|||
jQuery(function(a){return"undefined"==typeof wc_cart_params?!1:(a(document).on("click",".shipping-calculator-button",function(){return a(".shipping-calculator-form").slideToggle("slow"),!1}).on("change","select.shipping_method, input[name^=shipping_method]",function(){var b=[];a("select.shipping_method, input[name^=shipping_method][type=radio]:checked, input[name^=shipping_method][type=hidden]").each(function(){b[a(this).data("index")]=a(this).val()}),a("div.cart_totals").block({message:null,overlayCSS:{background:"#fff",opacity:.6}});var c={security:wc_cart_params.update_shipping_method_nonce,shipping_method:b};a.post(wc_cart_params.wc_ajax_url.toString().replace("%%endpoint%%","update_shipping_method"),c,function(b){a("div.cart_totals").replaceWith(b),a(document.body).trigger("updated_shipping_method")})}),void a(".shipping-calculator-form").hide())});
|
||||
jQuery(function(a){if("undefined"==typeof wc_cart_params)return!1;var b=function(a){return wc_cart_params.wc_ajax_url.toString().replace("%%endpoint%%",a)},c=function(a){return a.is(".processing")},d=function(a){a.addClass("processing").block({message:null,overlayCSS:{background:"#fff",opacity:.6}})},e=function(a){a.removeClass("processing").unblock()},f=function(b){var c=a.parseHTML(b),d=a("div.woocommerce",c);a("div.woocommerce").replaceWith(d)};a(document).on("click",".shipping-calculator-button",function(){return a(".shipping-calculator-form").slideToggle("slow"),!1}).on("change","select.shipping_method, input[name^=shipping_method]",function(){var c=[];a("select.shipping_method, input[name^=shipping_method][type=radio]:checked, input[name^=shipping_method][type=hidden]").each(function(){c[a(this).data("index")]=a(this).val()}),d(a("div.cart_totals"));var e={security:wc_cart_params.update_shipping_method_nonce,shipping_method:c};a.post(b("update_shipping_method"),e,function(b){a("div.cart_totals").replaceWith(b),a(document.body).trigger("updated_shipping_method")})}),a(document).on("submit","form.woocommerce-shipping-calculator",function(b){b.preventDefault();var c=a(b.target);d(c),a("<input />").attr("type","hidden").attr("name","calc_shipping").attr("value","x").appendTo(c),a.ajax({type:c.attr("method"),url:c.attr("action"),data:c.serialize(),dataType:"html",success:function(a){f(a)},complete:function(){e(c)}})}),a(".shipping-calculator-form").hide();var g=function(){d(a("div.cart_totals")),a.ajax({url:b("get_cart_totals"),dataType:"html",success:function(b){a("div.cart_totals").replaceWith(b)}})},h=function(b){var c=a("div.woocommerce > form");a(".woocommerce-error, .woocommerce-message").remove(),c.before(b)};a(document).on("submit","div.woocommerce > form",function(b){b.preventDefault();var d=a(b.target),e=a(document.activeElement);return window.console.log(e),c(d)?!1:void(e.is('[name="update_cart"]')||e.is("input.qty")?(window.console.log("update cart"),j(d)):(e.is('[name="apply_coupon"]')||e.is("#coupon_code"))&&(window.console.log("apply coupon"),i(d)))});var i=function(c){d(c);var f=a("#coupon_code"),i=f.val(),j={security:wc_cart_params.apply_coupon_nonce,coupon_code:i};a.ajax({type:"POST",url:b("apply_coupon"),data:j,dataType:"html",success:function(a){h(a)},complete:function(){e(c),f.val(""),g()}})};a(document).on("click","a.woocommerce-remove-coupon",function(c){c.preventDefault();var f=a(this).parents("tr"),i=a(this).attr("data-coupon");d(f.parents("table"));var j={security:wc_cart_params.remove_coupon_nonce,coupon:i};a.ajax({type:"POST",url:b("remove_coupon"),data:j,dataType:"html",success:function(a){h(a),e(f.parents("table"))},complete:function(){g()}})});var j=function(b){a("<input />").attr("type","hidden").attr("name","update_cart").attr("value","Update Cart").appendTo(b),d(b),a.ajax({type:b.attr("method"),url:b.attr("action"),data:b.serialize(),dataType:"html",success:f,complete:function(){e(b)}})};a(document).on("click","td.product-remove > a",function(b){b.preventDefault();var c=a(b.target),g=c.parents("form");d(g),a.ajax({type:"GET",url:c.attr("href"),dataType:"html",success:f,complete:function(){e(g)}})})});
|
|
@ -94,6 +94,7 @@ class WC_AJAX {
|
|||
'apply_coupon' => true,
|
||||
'remove_coupon' => true,
|
||||
'update_shipping_method' => true,
|
||||
'get_cart_totals' => true,
|
||||
'update_order_review' => true,
|
||||
'add_to_cart' => true,
|
||||
'checkout' => true,
|
||||
|
@ -254,6 +255,22 @@ class WC_AJAX {
|
|||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX receive updated cart_totals div.
|
||||
*/
|
||||
public static function get_cart_totals() {
|
||||
|
||||
if ( ! defined( 'WOOCOMMERCE_CART' ) ) {
|
||||
define( 'WOOCOMMERCE_CART', true );
|
||||
}
|
||||
|
||||
WC()->cart->calculate_totals();
|
||||
|
||||
woocommerce_cart_totals();
|
||||
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* AJAX update order review on checkout.
|
||||
*/
|
||||
|
|
|
@ -765,18 +765,22 @@ class WC_Checkout {
|
|||
}
|
||||
|
||||
// Get the billing_ and shipping_ address fields
|
||||
$address_fields = array_merge( WC()->countries->get_address_fields(), WC()->countries->get_address_fields( '', 'shipping_' ) );
|
||||
if ( isset( $this->checkout_fields['shipping'] ) && isset( $this->checkout_fields['billing'] ) ) {
|
||||
|
||||
if ( is_user_logged_in() && array_key_exists( $input, $address_fields ) ) {
|
||||
$current_user = wp_get_current_user();
|
||||
$address_fields = array_merge( $this->checkout_fields['billing'], $this->checkout_fields['shipping'] );
|
||||
|
||||
if ( $meta = get_user_meta( $current_user->ID, $input, true ) ) {
|
||||
return $meta;
|
||||
if ( is_user_logged_in() && is_array( $address_fields ) && array_key_exists( $input, $address_fields ) ) {
|
||||
$current_user = wp_get_current_user();
|
||||
|
||||
if ( $meta = get_user_meta( $current_user->ID, $input, true ) ) {
|
||||
return $meta;
|
||||
}
|
||||
|
||||
if ( $input == 'billing_email' ) {
|
||||
return $current_user->user_email;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $input == 'billing_email' ) {
|
||||
return $current_user->user_email;
|
||||
}
|
||||
}
|
||||
|
||||
switch ( $input ) {
|
||||
|
|
|
@ -289,6 +289,8 @@ class WC_Frontend_Scripts {
|
|||
'ajax_url' => WC()->ajax_url(),
|
||||
'wc_ajax_url' => WC_AJAX::get_endpoint( "%%endpoint%%" ),
|
||||
'update_shipping_method_nonce' => wp_create_nonce( "update-shipping-method" ),
|
||||
'apply_coupon_nonce' => wp_create_nonce( "apply-coupon" ),
|
||||
'remove_coupon_nonce' => wp_create_nonce( "remove-coupon" ),
|
||||
);
|
||||
break;
|
||||
case 'wc-cart-fragments' :
|
||||
|
|
|
@ -376,68 +376,54 @@ class WC_Product_Variable extends WC_Product {
|
|||
* @return array of attributes and their available values
|
||||
*/
|
||||
public function get_variation_attributes() {
|
||||
global $wpdb;
|
||||
|
||||
$variation_attributes = array();
|
||||
$attributes = $this->get_attributes();
|
||||
$child_ids = $this->get_children( true );
|
||||
|
||||
if ( ! $this->has_child() ) {
|
||||
return $variation_attributes;
|
||||
}
|
||||
|
||||
$attributes = $this->get_attributes();
|
||||
|
||||
foreach ( $attributes as $attribute ) {
|
||||
if ( ! $attribute['is_variation'] ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$values = array();
|
||||
$attribute_field_name = 'attribute_' . sanitize_title( $attribute['name'] );
|
||||
|
||||
// Get used values from children variations
|
||||
foreach ( $this->get_children() as $child_id ) {
|
||||
$variation = $this->get_child( $child_id );
|
||||
|
||||
if ( ! empty( $variation->variation_id ) ) {
|
||||
if ( ! $variation->variation_is_visible() ) {
|
||||
continue; // Disabled or hidden
|
||||
}
|
||||
|
||||
$child_variation_attributes = $variation->get_variation_attributes();
|
||||
|
||||
if ( isset( $child_variation_attributes[ $attribute_field_name ] ) ) {
|
||||
$values[] = $child_variation_attributes[ $attribute_field_name ];
|
||||
}
|
||||
if ( ! empty( $child_ids ) ) {
|
||||
foreach ( $attributes as $attribute ) {
|
||||
if ( empty( $attribute['is_variation'] ) ) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// empty value indicates that all options for given attribute are available
|
||||
if ( in_array( '', $values ) ) {
|
||||
$values = $attribute['is_taxonomy'] ? wp_get_post_terms( $this->id, $attribute['name'], array( 'fields' => 'slugs' ) ) : wc_get_text_attributes( $attribute['value'] );
|
||||
// Get possible values for this attribute, for only visible variations.
|
||||
$values = array_unique( $wpdb->get_col( $wpdb->prepare(
|
||||
"SELECT meta_value FROM {$wpdb->postmeta} WHERE meta_key = %s AND post_id IN (" . implode( ',', array_map( 'esc_sql', $child_ids ) ) . ")",
|
||||
wc_variation_attribute_name( $attribute['name'] )
|
||||
) ) );
|
||||
|
||||
// Get custom attributes (non taxonomy) as defined
|
||||
} elseif ( ! $attribute['is_taxonomy'] ) {
|
||||
$text_attributes = wc_get_text_attributes( $attribute['value'] );
|
||||
$assigned_text_attributes = $values;
|
||||
$values = array();
|
||||
// empty value indicates that all options for given attribute are available
|
||||
if ( in_array( '', $values ) ) {
|
||||
$values = $attribute['is_taxonomy'] ? wp_get_post_terms( $this->id, $attribute['name'], array( 'fields' => 'slugs' ) ) : wc_get_text_attributes( $attribute['value'] );
|
||||
|
||||
// Pre 2.4 handling where 'slugs' were saved instead of the full text attribute
|
||||
if ( version_compare( get_post_meta( $this->id, '_product_version', true ), '2.4.0', '<' ) ) {
|
||||
$assigned_text_attributes = array_map( 'sanitize_title', $assigned_text_attributes );
|
||||
// Get custom attributes (non taxonomy) as defined
|
||||
} elseif ( ! $attribute['is_taxonomy'] ) {
|
||||
$text_attributes = wc_get_text_attributes( $attribute['value'] );
|
||||
$assigned_text_attributes = $values;
|
||||
$values = array();
|
||||
|
||||
foreach ( $text_attributes as $text_attribute ) {
|
||||
if ( in_array( sanitize_title( $text_attribute ), $assigned_text_attributes ) ) {
|
||||
$values[] = $text_attribute;
|
||||
// Pre 2.4 handling where 'slugs' were saved instead of the full text attribute
|
||||
if ( version_compare( get_post_meta( $this->id, '_product_version', true ), '2.4.0', '<' ) ) {
|
||||
$assigned_text_attributes = array_map( 'sanitize_title', $assigned_text_attributes );
|
||||
|
||||
foreach ( $text_attributes as $text_attribute ) {
|
||||
if ( in_array( sanitize_title( $text_attribute ), $assigned_text_attributes ) ) {
|
||||
$values[] = $text_attribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ( $text_attributes as $text_attribute ) {
|
||||
if ( in_array( $text_attribute, $assigned_text_attributes ) ) {
|
||||
$values[] = $text_attribute;
|
||||
} else {
|
||||
foreach ( $text_attributes as $text_attribute ) {
|
||||
if ( in_array( $text_attribute, $assigned_text_attributes ) ) {
|
||||
$values[] = $text_attribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$variation_attributes[ $attribute['name'] ] = array_unique( $values );
|
||||
$variation_attributes[ $attribute['name'] ] = array_unique( $values );
|
||||
}
|
||||
}
|
||||
|
||||
return $variation_attributes;
|
||||
|
|
|
@ -249,7 +249,7 @@ class WC_Shipping_Zone implements WC_Data {
|
|||
}
|
||||
}
|
||||
|
||||
return $methods;
|
||||
return apply_filters( 'woocommerce_shipping_zone_shipping_methods', $methods, $raw_methods, $allowed_classes, $this );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -198,8 +198,9 @@ class WC_Shortcode_Checkout {
|
|||
|
||||
if ( $order_id > 0 ) {
|
||||
$order = wc_get_order( $order_id );
|
||||
if ( $order->order_key != $order_key )
|
||||
unset( $order );
|
||||
if ( $order->order_key != $order_key ) {
|
||||
$order = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Empty awaiting payment session
|
||||
|
|
|
@ -49,6 +49,17 @@ function wc_attribute_taxonomy_name( $attribute_name ) {
|
|||
return 'pa_' . wc_sanitize_taxonomy_name( $attribute_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attribute name used when storing values in post meta.
|
||||
*
|
||||
* @param string $attribute_name Attribute name.
|
||||
* @since 2.6.0
|
||||
* @return string
|
||||
*/
|
||||
function wc_variation_attribute_name( $attribute_name ) {
|
||||
return 'attribute_' . sanitize_title( $attribute_name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a product attribute name by ID.
|
||||
*
|
||||
|
|
|
@ -153,5 +153,17 @@ class Core_Functions extends \WC_Unit_Test_Case {
|
|||
$this->assertEquals( '', $default['state'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test wc_format_country_state_string().
|
||||
*
|
||||
* @since 2.6.0
|
||||
*/
|
||||
public function test_wc_format_country_state_string() {
|
||||
// Test with correct values.
|
||||
$this->assertEquals( array( 'country' => 'US', 'state' => 'CA' ), wc_format_country_state_string( 'US:CA' ) );
|
||||
// Test what happens when we pass an incorrect value.
|
||||
$this->assertEquals( array( 'country' => 'US-CA', 'state' => '' ), wc_format_country_state_string( 'US-CA' ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue