PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 8.5.4
WooCommerce v8.5.4
10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / includes / class-wc-countries.php
woocommerce / includes Last commit date
abstracts 2 years ago admin 2 years ago blocks 5 years ago cli 2 years ago customizer 3 years ago data-stores 2 years ago emails 2 years ago export 2 years ago gateways 2 years ago import 2 years ago integrations 2 years ago interfaces 3 years ago legacy 2 years ago libraries 3 years ago log-handlers 2 years ago payment-tokens 5 years ago queue 4 years ago react-admin 2 years ago rest-api 2 years ago shipping 2 years ago shortcodes 2 years ago theme-support 3 years ago tracks 2 years ago traits 5 years ago walkers 5 years ago wccom-site 2 years ago widgets 3 years ago class-wc-ajax.php 2 years ago class-wc-api.php 4 years ago class-wc-auth.php 4 years ago class-wc-autoloader.php 5 years ago class-wc-background-emailer.php 5 years ago class-wc-background-updater.php 5 years ago class-wc-breadcrumb.php 5 years ago class-wc-cache-helper.php 3 years ago class-wc-cart-fees.php 2 years ago class-wc-cart-session.php 2 years ago class-wc-cart-totals.php 2 years ago class-wc-cart.php 2 years ago class-wc-checkout.php 2 years ago class-wc-cli.php 3 years ago class-wc-comments.php 3 years ago class-wc-countries.php 2 years ago class-wc-coupon.php 2 years ago class-wc-customer-download-log.php 5 years ago class-wc-customer-download.php 4 years ago class-wc-customer.php 2 years ago class-wc-data-exception.php 8 years ago class-wc-data-store.php 3 years ago class-wc-datetime.php 4 years ago class-wc-deprecated-action-hooks.php 8 years ago class-wc-deprecated-filter-hooks.php 3 years ago class-wc-discounts.php 2 years ago class-wc-download-handler.php 3 years ago class-wc-emails.php 2 years ago class-wc-embed.php 5 years ago class-wc-form-handler.php 2 years ago class-wc-frontend-scripts.php 2 years ago class-wc-geo-ip.php 4 years ago class-wc-geolite-integration.php 6 years ago class-wc-geolocation.php 3 years ago class-wc-https.php 2 years ago class-wc-install.php 2 years ago class-wc-integrations.php 5 years ago class-wc-log-levels.php 2 years ago class-wc-logger.php 2 years ago class-wc-meta-data.php 4 years ago class-wc-order-factory.php 3 years ago class-wc-order-item-coupon.php 4 years ago class-wc-order-item-fee.php 4 years ago class-wc-order-item-meta.php 4 years ago class-wc-order-item-product.php 2 years ago class-wc-order-item-shipping.php 4 years ago class-wc-order-item-tax.php 4 years ago class-wc-order-item.php 4 years ago class-wc-order-query.php 4 years ago class-wc-order-refund.php 2 years ago class-wc-order.php 2 years ago class-wc-payment-gateways.php 2 years ago class-wc-payment-tokens.php 3 years ago class-wc-post-data.php 3 years ago class-wc-post-types.php 3 years ago class-wc-privacy-background-process.php 5 years ago class-wc-privacy-erasers.php 4 years ago class-wc-privacy-exporters.php 4 years ago class-wc-privacy.php 2 years ago class-wc-product-attribute.php 4 years ago class-wc-product-download.php 2 years ago class-wc-product-external.php 5 years ago class-wc-product-factory.php 5 years ago class-wc-product-grouped.php 8 years ago class-wc-product-query.php 5 years ago class-wc-product-simple.php 2 years ago class-wc-product-variable.php 3 years ago class-wc-product-variation.php 4 years ago class-wc-query.php 3 years ago class-wc-rate-limiter.php 4 years ago class-wc-regenerate-images-request.php 3 years ago class-wc-regenerate-images.php 3 years ago class-wc-register-wp-admin-settings.php 4 years ago class-wc-rest-authentication.php 3 years ago class-wc-rest-exception.php 5 years ago class-wc-session-handler.php 2 years ago class-wc-shipping-rate.php 3 years ago class-wc-shipping-zone.php 5 years ago class-wc-shipping-zones.php 5 years ago class-wc-shipping.php 4 years ago class-wc-shortcodes.php 5 years ago class-wc-structured-data.php 3 years ago class-wc-tax.php 2 years ago class-wc-template-loader.php 2 years ago class-wc-tracker.php 2 years ago class-wc-validation.php 3 years ago class-wc-webhook.php 2 years ago class-woocommerce.php 5 months ago wc-account-functions.php 2 years ago wc-attribute-functions.php 3 years ago wc-cart-functions.php 2 years ago wc-conditional-functions.php 2 years ago wc-core-functions.php 2 years ago wc-coupon-functions.php 3 years ago wc-deprecated-functions.php 3 years ago wc-formatting-functions.php 2 years ago wc-notice-functions.php 2 years ago wc-order-functions.php 2 years ago wc-order-item-functions.php 3 years ago wc-page-functions.php 2 years ago wc-product-functions.php 2 years ago wc-rest-functions.php 3 years ago wc-stock-functions.php 3 years ago wc-template-functions.php 2 years ago wc-template-hooks.php 5 years ago wc-term-functions.php 3 years ago wc-update-functions.php 2 years ago wc-user-functions.php 2 years ago wc-webhook-functions.php 4 years ago wc-widget-functions.php 5 years ago
class-wc-countries.php
1725 lines
1 <?php
2 /**
3 * WooCommerce countries
4 *
5 * @package WooCommerce\l10n
6 * @version 3.3.0
7 */
8
9 defined( 'ABSPATH' ) || exit;
10
11 /**
12 * The WooCommerce countries class stores country/state data.
13 */
14 class WC_Countries {
15
16 /**
17 * Locales list.
18 *
19 * @var array
20 */
21 public $locale = array();
22
23 /**
24 * List of address formats for locales.
25 *
26 * @var array
27 */
28 public $address_formats = array();
29
30 /**
31 * Cache of geographical regions.
32 *
33 * Only to be used by the get_* and load_* methods, as other methods may expect the regions to be
34 * loaded on demand.
35 *
36 * @var array
37 */
38 private $geo_cache = array();
39
40 /**
41 * Auto-load in-accessible properties on demand.
42 *
43 * @param mixed $key Key.
44 * @return mixed
45 */
46 public function __get( $key ) {
47 if ( 'countries' === $key ) {
48 return $this->get_countries();
49 } elseif ( 'states' === $key ) {
50 return $this->get_states();
51 } elseif ( 'continents' === $key ) {
52 return $this->get_continents();
53 }
54 }
55
56 /**
57 * Get all countries.
58 *
59 * @return array
60 */
61 public function get_countries() {
62 if ( empty( $this->geo_cache['countries'] ) ) {
63 /**
64 * Allows filtering of the list of countries in WC.
65 *
66 * @since 1.5.3
67 *
68 * @param array $countries
69 */
70 $this->geo_cache['countries'] = apply_filters( 'woocommerce_countries', include WC()->plugin_path() . '/i18n/countries.php' );
71 if ( apply_filters( 'woocommerce_sort_countries', true ) ) {
72 wc_asort_by_locale( $this->geo_cache['countries'] );
73 }
74 }
75
76 return $this->geo_cache['countries'];
77 }
78
79 /**
80 * Check if a given code represents a valid ISO 3166-1 alpha-2 code for a country known to us.
81 *
82 * @since 5.1.0
83 * @param string $country_code The country code to check as a ISO 3166-1 alpha-2 code.
84 * @return bool True if the country is known to us, false otherwise.
85 */
86 public function country_exists( $country_code ) {
87 return isset( $this->get_countries()[ $country_code ] );
88 }
89
90 /**
91 * Get all continents.
92 *
93 * @return array
94 */
95 public function get_continents() {
96 if ( empty( $this->geo_cache['continents'] ) ) {
97 /**
98 * Allows filtering of continents in WC.
99 *
100 * @since 2.6.0
101 *
102 * @param array[array] $continents
103 */
104 $this->geo_cache['continents'] = apply_filters( 'woocommerce_continents', include WC()->plugin_path() . '/i18n/continents.php' );
105 }
106
107 return $this->geo_cache['continents'];
108 }
109
110 /**
111 * Get continent code for a country code.
112 *
113 * @since 2.6.0
114 * @param string $cc Country code.
115 * @return string
116 */
117 public function get_continent_code_for_country( $cc ) {
118 $cc = trim( strtoupper( $cc ) );
119 $continents = $this->get_continents();
120 $continents_and_ccs = wp_list_pluck( $continents, 'countries' );
121 foreach ( $continents_and_ccs as $continent_code => $countries ) {
122 if ( false !== array_search( $cc, $countries, true ) ) {
123 return $continent_code;
124 }
125 }
126
127 return '';
128 }
129
130 /**
131 * Get calling code for a country code.
132 *
133 * @since 3.6.0
134 * @param string $cc Country code.
135 * @return string|array Some countries have multiple. The code will be stripped of - and spaces and always be prefixed with +.
136 */
137 public function get_country_calling_code( $cc ) {
138 $codes = wp_cache_get( 'calling-codes', 'countries' );
139
140 if ( ! $codes ) {
141 $codes = include WC()->plugin_path() . '/i18n/phone.php';
142 wp_cache_set( 'calling-codes', $codes, 'countries' );
143 }
144
145 $calling_code = isset( $codes[ $cc ] ) ? $codes[ $cc ] : '';
146
147 if ( is_array( $calling_code ) ) {
148 $calling_code = $calling_code[0];
149 }
150
151 return $calling_code;
152 }
153
154 /**
155 * Get continents that the store ships to.
156 *
157 * @since 3.6.0
158 * @return array
159 */
160 public function get_shipping_continents() {
161 $continents = $this->get_continents();
162 $shipping_countries = $this->get_shipping_countries();
163 $shipping_country_codes = array_keys( $shipping_countries );
164 $shipping_continents = array();
165
166 foreach ( $continents as $continent_code => $continent ) {
167 if ( count( array_intersect( $continent['countries'], $shipping_country_codes ) ) ) {
168 $shipping_continents[ $continent_code ] = $continent;
169 }
170 }
171
172 return $shipping_continents;
173 }
174
175 /**
176 * Load the states.
177 *
178 * @deprecated 3.6.0 This method was used to load state files, but is no longer needed. @see get_states().
179 */
180 public function load_country_states() {
181 global $states;
182
183 $states = include WC()->plugin_path() . '/i18n/states.php';
184
185 /**
186 * Allows filtering of country states in WC.
187 *
188 * @since 1.5.3
189 *
190 * @param array $states
191 */
192 $this->geo_cache['states'] = apply_filters( 'woocommerce_states', $states );
193 }
194
195 /**
196 * Get the states for a country.
197 *
198 * @param string $cc Country code.
199 * @return false|array of states
200 */
201 public function get_states( $cc = null ) {
202 if ( ! isset( $this->geo_cache['states'] ) ) {
203 /**
204 * Allows filtering of country states in WC.
205 *
206 * @since 1.5.3
207 *
208 * @param array $states
209 */
210 $this->geo_cache['states'] = apply_filters( 'woocommerce_states', include WC()->plugin_path() . '/i18n/states.php' );
211 }
212
213 if ( ! is_null( $cc ) ) {
214 return isset( $this->geo_cache['states'][ $cc ] ) ? $this->geo_cache['states'][ $cc ] : false;
215 } else {
216 return $this->geo_cache['states'];
217 }
218 }
219
220 /**
221 * Get the base address (first line) for the store.
222 *
223 * @since 3.1.1
224 * @return string
225 */
226 public function get_base_address() {
227 $base_address = get_option( 'woocommerce_store_address', '' );
228 return apply_filters( 'woocommerce_countries_base_address', $base_address );
229 }
230
231 /**
232 * Get the base address (second line) for the store.
233 *
234 * @since 3.1.1
235 * @return string
236 */
237 public function get_base_address_2() {
238 $base_address_2 = get_option( 'woocommerce_store_address_2', '' );
239 return apply_filters( 'woocommerce_countries_base_address_2', $base_address_2 );
240 }
241
242 /**
243 * Get the base country for the store.
244 *
245 * @return string
246 */
247 public function get_base_country() {
248 $default = wc_get_base_location();
249 return apply_filters( 'woocommerce_countries_base_country', $default['country'] );
250 }
251
252 /**
253 * Get the base state for the store.
254 *
255 * @return string
256 */
257 public function get_base_state() {
258 $default = wc_get_base_location();
259 return apply_filters( 'woocommerce_countries_base_state', $default['state'] );
260 }
261
262 /**
263 * Get the base city for the store.
264 *
265 * @version 3.1.1
266 * @return string
267 */
268 public function get_base_city() {
269 $base_city = get_option( 'woocommerce_store_city', '' );
270 return apply_filters( 'woocommerce_countries_base_city', $base_city );
271 }
272
273 /**
274 * Get the base postcode for the store.
275 *
276 * @since 3.1.1
277 * @return string
278 */
279 public function get_base_postcode() {
280 $base_postcode = get_option( 'woocommerce_store_postcode', '' );
281 return apply_filters( 'woocommerce_countries_base_postcode', $base_postcode );
282 }
283
284 /**
285 * Get countries that the store sells to.
286 *
287 * @return array
288 */
289 public function get_allowed_countries() {
290 if ( 'all' === get_option( 'woocommerce_allowed_countries' ) ) {
291 return apply_filters( 'woocommerce_countries_allowed_countries', $this->countries );
292 }
293
294 if ( 'all_except' === get_option( 'woocommerce_allowed_countries' ) ) {
295 $except_countries = get_option( 'woocommerce_all_except_countries', array() );
296
297 if ( ! $except_countries ) {
298 return $this->countries;
299 } else {
300 $all_except_countries = $this->countries;
301 foreach ( $except_countries as $country ) {
302 unset( $all_except_countries[ $country ] );
303 }
304 return apply_filters( 'woocommerce_countries_allowed_countries', $all_except_countries );
305 }
306 }
307
308 $countries = array();
309
310 $raw_countries = get_option( 'woocommerce_specific_allowed_countries', array() );
311
312 if ( $raw_countries ) {
313 foreach ( $raw_countries as $country ) {
314 $countries[ $country ] = $this->countries[ $country ];
315 }
316 }
317
318 return apply_filters( 'woocommerce_countries_allowed_countries', $countries );
319 }
320
321 /**
322 * Get countries that the store ships to.
323 *
324 * @return array
325 */
326 public function get_shipping_countries() {
327 if ( '' === get_option( 'woocommerce_ship_to_countries' ) ) {
328 return $this->get_allowed_countries();
329 }
330
331 if ( 'all' === get_option( 'woocommerce_ship_to_countries' ) ) {
332 return $this->countries;
333 }
334
335 $countries = array();
336
337 $raw_countries = get_option( 'woocommerce_specific_ship_to_countries' );
338
339 if ( $raw_countries ) {
340 foreach ( $raw_countries as $country ) {
341 $countries[ $country ] = $this->countries[ $country ];
342 }
343 }
344
345 return apply_filters( 'woocommerce_countries_shipping_countries', $countries );
346 }
347
348 /**
349 * Get allowed country states.
350 *
351 * @return array
352 */
353 public function get_allowed_country_states() {
354 if ( get_option( 'woocommerce_allowed_countries' ) !== 'specific' ) {
355 return $this->states;
356 }
357
358 $states = array();
359
360 $raw_countries = get_option( 'woocommerce_specific_allowed_countries' );
361
362 if ( $raw_countries ) {
363 foreach ( $raw_countries as $country ) {
364 if ( isset( $this->states[ $country ] ) ) {
365 $states[ $country ] = $this->states[ $country ];
366 }
367 }
368 }
369
370 return apply_filters( 'woocommerce_countries_allowed_country_states', $states );
371 }
372
373 /**
374 * Get shipping country states.
375 *
376 * @return array
377 */
378 public function get_shipping_country_states() {
379 if ( get_option( 'woocommerce_ship_to_countries' ) === '' ) {
380 return $this->get_allowed_country_states();
381 }
382
383 if ( get_option( 'woocommerce_ship_to_countries' ) !== 'specific' ) {
384 return $this->states;
385 }
386
387 $states = array();
388
389 $raw_countries = get_option( 'woocommerce_specific_ship_to_countries' );
390
391 if ( $raw_countries ) {
392 foreach ( $raw_countries as $country ) {
393 if ( ! empty( $this->states[ $country ] ) ) {
394 $states[ $country ] = $this->states[ $country ];
395 }
396 }
397 }
398
399 return apply_filters( 'woocommerce_countries_shipping_country_states', $states );
400 }
401
402 /**
403 * Gets an array of countries in the EU.
404 *
405 * @param string $type Type of countries to retrieve. Blank for EU member countries. eu_vat for EU VAT countries.
406 * @return string[]
407 */
408 public function get_european_union_countries( $type = '' ) {
409 $countries = array( 'AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GR', 'HR', 'HU', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK' );
410
411 if ( 'eu_vat' === $type ) {
412 $countries[] = 'MC';
413 }
414
415 return apply_filters( 'woocommerce_european_union_countries', $countries, $type );
416 }
417
418 /**
419 * Gets an array of Non-EU countries that use VAT as the Local name for their taxes based on this list - https://en.wikipedia.org/wiki/Value-added_tax#Non-European_Union_countries
420 *
421 * @deprecated 4.0.0
422 * @since 3.9.0
423 * @return string[]
424 */
425 public function countries_using_vat() {
426 wc_deprecated_function( 'countries_using_vat', '4.0', 'WC_Countries::get_vat_countries' );
427 $countries = array( 'AE', 'AL', 'AR', 'AZ', 'BB', 'BH', 'BO', 'BS', 'BY', 'CL', 'CO', 'EC', 'EG', 'ET', 'FJ', 'GH', 'GM', 'GT', 'IL', 'IN', 'IR', 'KN', 'KR', 'KZ', 'LK', 'MD', 'ME', 'MK', 'MN', 'MU', 'MX', 'NA', 'NG', 'NP', 'PS', 'PY', 'RS', 'RU', 'RW', 'SA', 'SV', 'TH', 'TR', 'UA', 'UY', 'UZ', 'VE', 'VN', 'ZA' );
428
429 return apply_filters( 'woocommerce_countries_using_vat', $countries );
430 }
431
432 /**
433 * Gets an array of countries using VAT.
434 *
435 * @since 4.0.0
436 * @return string[] of country codes.
437 */
438 public function get_vat_countries() {
439 $eu_countries = $this->get_european_union_countries();
440 $vat_countries = array( 'AE', 'AL', 'AR', 'AZ', 'BB', 'BH', 'BO', 'BS', 'BY', 'CL', 'CO', 'EC', 'EG', 'ET', 'FJ', 'GB', 'GH', 'GM', 'GT', 'IL', 'IM', 'IN', 'IR', 'KN', 'KR', 'KZ', 'LK', 'MC', 'MD', 'ME', 'MK', 'MN', 'MU', 'MX', 'NA', 'NG', 'NO', 'NP', 'PS', 'PY', 'RS', 'RU', 'RW', 'SA', 'SV', 'TH', 'TR', 'UA', 'UY', 'UZ', 'VE', 'VN', 'ZA' );
441
442 return apply_filters( 'woocommerce_vat_countries', array_merge( $eu_countries, $vat_countries ) );
443 }
444
445 /**
446 * Gets the correct string for shipping - either 'to the' or 'to'.
447 *
448 * @param string $country_code Country code.
449 * @return string
450 */
451 public function shipping_to_prefix( $country_code = '' ) {
452 $country_code = $country_code ? $country_code : WC()->customer->get_shipping_country();
453 $countries = array( 'AE', 'CZ', 'DO', 'GB', 'NL', 'PH', 'US', 'USAF' );
454 $return = in_array( $country_code, $countries, true ) ? _x( 'to the', 'shipping country prefix', 'woocommerce' ) : _x( 'to', 'shipping country prefix', 'woocommerce' );
455
456 return apply_filters( 'woocommerce_countries_shipping_to_prefix', $return, $country_code );
457 }
458
459 /**
460 * Prefix certain countries with 'the'.
461 *
462 * @param string $country_code Country code.
463 * @return string
464 */
465 public function estimated_for_prefix( $country_code = '' ) {
466 $country_code = $country_code ? $country_code : $this->get_base_country();
467 $countries = array( 'AE', 'CZ', 'DO', 'GB', 'NL', 'PH', 'US', 'USAF' );
468 $return = in_array( $country_code, $countries, true ) ? __( 'the', 'woocommerce' ) . ' ' : '';
469
470 return apply_filters( 'woocommerce_countries_estimated_for_prefix', $return, $country_code );
471 }
472
473 /**
474 * Correctly name tax in some countries VAT on the frontend.
475 *
476 * @return string
477 */
478 public function tax_or_vat() {
479 $return = in_array( $this->get_base_country(), $this->get_vat_countries(), true ) ? __( 'VAT', 'woocommerce' ) : __( 'Tax', 'woocommerce' );
480
481 return apply_filters( 'woocommerce_countries_tax_or_vat', $return );
482 }
483
484 /**
485 * Include the Inc Tax label.
486 *
487 * @return string
488 */
489 public function inc_tax_or_vat() {
490 $return = in_array( $this->get_base_country(), $this->get_vat_countries(), true ) ? __( '(incl. VAT)', 'woocommerce' ) : __( '(incl. tax)', 'woocommerce' );
491
492 return apply_filters( 'woocommerce_countries_inc_tax_or_vat', $return );
493 }
494
495 /**
496 * Include the Ex Tax label.
497 *
498 * @return string
499 */
500 public function ex_tax_or_vat() {
501 $return = in_array( $this->get_base_country(), $this->get_vat_countries(), true ) ? __( '(ex. VAT)', 'woocommerce' ) : __( '(ex. tax)', 'woocommerce' );
502
503 return apply_filters( 'woocommerce_countries_ex_tax_or_vat', $return );
504 }
505
506 /**
507 * Outputs the list of countries and states for use in dropdown boxes.
508 *
509 * @param string $selected_country Selected country.
510 * @param string $selected_state Selected state.
511 * @param bool $escape If we should escape HTML.
512 */
513 public function country_dropdown_options( $selected_country = '', $selected_state = '', $escape = false ) {
514 if ( $this->countries ) {
515 foreach ( $this->countries as $key => $value ) {
516 $states = $this->get_states( $key );
517 if ( $states ) {
518 // Maybe default the selected state as the first one.
519 if ( $selected_country === $key && '*' === $selected_state ) {
520 $selected_state = key( $states ) ?? '*';
521 }
522
523 echo '<optgroup label="' . esc_attr( $value ) . '">';
524 foreach ( $states as $state_key => $state_value ) {
525 echo '<option value="' . esc_attr( $key ) . ':' . esc_attr( $state_key ) . '"';
526
527 if ( $selected_country === $key && $selected_state === $state_key ) {
528 echo ' selected="selected"';
529 }
530
531 echo '>' . esc_html( $value ) . ' &mdash; ' . ( $escape ? esc_html( $state_value ) : $state_value ) . '</option>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
532
533 }
534 echo '</optgroup>';
535 } else {
536 echo '<option';
537 if ( $selected_country === $key && '*' === $selected_state ) {
538 echo ' selected="selected"';
539 }
540 echo ' value="' . esc_attr( $key ) . '">' . ( $escape ? esc_html( $value ) : $value ) . '</option>'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
541 }
542 }
543 }
544 }
545
546 /**
547 * Get country address formats.
548 *
549 * These define how addresses are formatted for display in various countries.
550 *
551 * @return array
552 */
553 public function get_address_formats() {
554 if ( empty( $this->address_formats ) ) {
555 $this->address_formats = apply_filters(
556 'woocommerce_localisation_address_formats',
557 array(
558 'default' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}\n{postcode}\n{country}",
559 'AT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
560 'AU' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
561 'BE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
562 'CA' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} {state_code} {postcode}\n{country}",
563 'CH' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
564 'CL' => "{company}\n{name}\n{address_1}\n{address_2}\n{state}\n{postcode} {city}\n{country}",
565 'CN' => "{country} {postcode}\n{state}, {city}, {address_2}, {address_1}\n{company}\n{name}",
566 'CZ' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
567 'DE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
568 'DK' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
569 'EE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
570 'ES' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city}\n{state}\n{country}",
571 'FI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
572 'FR' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city_upper}\n{country}",
573 'HK' => "{company}\n{first_name} {last_name_upper}\n{address_1}\n{address_2}\n{city_upper}\n{state_upper}\n{country}",
574 'HU' => "{last_name} {first_name}\n{company}\n{city}\n{address_1}\n{address_2}\n{postcode}\n{country}",
575 'IN' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} {postcode}\n{state}, {country}",
576 'IS' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
577 'IT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode}\n{city}\n{state_upper}\n{country}",
578 'JM' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}\n{postcode_upper}\n{country}",
579 'JP' => "{postcode}\n{state} {city} {address_1}\n{address_2}\n{company}\n{last_name} {first_name}\n{country}",
580 'LI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
581 'NL' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
582 'NO' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
583 'NZ' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {postcode}\n{country}",
584 'PL' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
585 'PR' => "{company}\n{name}\n{address_1} {address_2}\n{city} \n{country} {postcode}",
586 'PT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
587 'RS' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
588 'SE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
589 'SI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
590 'SK' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
591 'TR' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city} {state}\n{country}",
592 'TW' => "{company}\n{last_name} {first_name}\n{address_1}\n{address_2}\n{state}, {city} {postcode}\n{country}",
593 'UG' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}, {country}",
594 'US' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}, {state_code} {postcode}\n{country}",
595 'VN' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {postcode}\n{country}",
596 )
597 );
598 }
599 return $this->address_formats;
600 }
601
602 /**
603 * Get country address format.
604 *
605 * @param array $args Arguments.
606 * @param string $separator How to separate address lines. @since 3.5.0.
607 * @return string
608 */
609 public function get_formatted_address( $args = array(), $separator = '<br/>' ) {
610 $default_args = array(
611 'first_name' => '',
612 'last_name' => '',
613 'company' => '',
614 'address_1' => '',
615 'address_2' => '',
616 'city' => '',
617 'state' => '',
618 'postcode' => '',
619 'country' => '',
620 );
621
622 $args = array_map( 'trim', wp_parse_args( $args, $default_args ) );
623 $state = $args['state'];
624 $country = $args['country'];
625
626 // Get all formats.
627 $formats = $this->get_address_formats();
628
629 // Get format for the address' country.
630 $format = ( $country && isset( $formats[ $country ] ) ) ? $formats[ $country ] : $formats['default'];
631
632 // Handle full country name.
633 $full_country = ( isset( $this->countries[ $country ] ) ) ? $this->countries[ $country ] : $country;
634
635 // Country is not needed if the same as base.
636 if ( $country === $this->get_base_country() && ! apply_filters( 'woocommerce_formatted_address_force_country_display', false ) ) {
637 $format = str_replace( '{country}', '', $format );
638 }
639
640 // Handle full state name.
641 $full_state = ( $country && $state && isset( $this->states[ $country ][ $state ] ) ) ? $this->states[ $country ][ $state ] : $state;
642
643 // Substitute address parts into the string.
644 $replace = array_map(
645 'esc_html',
646 apply_filters(
647 'woocommerce_formatted_address_replacements',
648 array(
649 '{first_name}' => $args['first_name'],
650 '{last_name}' => $args['last_name'],
651 '{name}' => sprintf(
652 /* translators: 1: first name 2: last name */
653 _x( '%1$s %2$s', 'full name', 'woocommerce' ),
654 $args['first_name'],
655 $args['last_name']
656 ),
657 '{company}' => $args['company'],
658 '{address_1}' => $args['address_1'],
659 '{address_2}' => $args['address_2'],
660 '{city}' => $args['city'],
661 '{state}' => $full_state,
662 '{postcode}' => $args['postcode'],
663 '{country}' => $full_country,
664 '{first_name_upper}' => wc_strtoupper( $args['first_name'] ),
665 '{last_name_upper}' => wc_strtoupper( $args['last_name'] ),
666 '{name_upper}' => wc_strtoupper(
667 sprintf(
668 /* translators: 1: first name 2: last name */
669 _x( '%1$s %2$s', 'full name', 'woocommerce' ),
670 $args['first_name'],
671 $args['last_name']
672 )
673 ),
674 '{company_upper}' => wc_strtoupper( $args['company'] ),
675 '{address_1_upper}' => wc_strtoupper( $args['address_1'] ),
676 '{address_2_upper}' => wc_strtoupper( $args['address_2'] ),
677 '{city_upper}' => wc_strtoupper( $args['city'] ),
678 '{state_upper}' => wc_strtoupper( $full_state ),
679 '{state_code}' => wc_strtoupper( $state ),
680 '{postcode_upper}' => wc_strtoupper( $args['postcode'] ),
681 '{country_upper}' => wc_strtoupper( $full_country ),
682 ),
683 $args
684 )
685 );
686
687 $formatted_address = str_replace( array_keys( $replace ), $replace, $format );
688
689 // Clean up white space.
690 $formatted_address = preg_replace( '/ +/', ' ', trim( $formatted_address ) );
691 $formatted_address = preg_replace( '/\n\n+/', "\n", $formatted_address );
692
693 // Break newlines apart and remove empty lines/trim commas and white space.
694 $formatted_address = array_filter( array_map( array( $this, 'trim_formatted_address_line' ), explode( "\n", $formatted_address ) ) );
695
696 // Add html breaks.
697 $formatted_address = implode( $separator, $formatted_address );
698
699 // We're done!
700 return $formatted_address;
701 }
702
703 /**
704 * Trim white space and commas off a line.
705 *
706 * @param string $line Line.
707 * @return string
708 */
709 private function trim_formatted_address_line( $line ) {
710 return trim( $line, ', ' );
711 }
712
713 /**
714 * Returns the fields we show by default. This can be filtered later on.
715 *
716 * @return array
717 */
718 public function get_default_address_fields() {
719 $address_2_label = __( 'Apartment, suite, unit, etc.', 'woocommerce' );
720
721 // If necessary, append '(optional)' to the placeholder: we don't need to worry about the
722 // label, though, as woocommerce_form_field() takes care of that.
723 if ( 'optional' === get_option( 'woocommerce_checkout_address_2_field', 'optional' ) ) {
724 $address_2_placeholder = __( 'Apartment, suite, unit, etc. (optional)', 'woocommerce' );
725 } else {
726 $address_2_placeholder = $address_2_label;
727 }
728
729 $fields = array(
730 'first_name' => array(
731 'label' => __( 'First name', 'woocommerce' ),
732 'required' => true,
733 'class' => array( 'form-row-first' ),
734 'autocomplete' => 'given-name',
735 'priority' => 10,
736 ),
737 'last_name' => array(
738 'label' => __( 'Last name', 'woocommerce' ),
739 'required' => true,
740 'class' => array( 'form-row-last' ),
741 'autocomplete' => 'family-name',
742 'priority' => 20,
743 ),
744 'company' => array(
745 'label' => __( 'Company name', 'woocommerce' ),
746 'class' => array( 'form-row-wide' ),
747 'autocomplete' => 'organization',
748 'priority' => 30,
749 'required' => 'required' === get_option( 'woocommerce_checkout_company_field', 'optional' ),
750 ),
751 'country' => array(
752 'type' => 'country',
753 'label' => __( 'Country / Region', 'woocommerce' ),
754 'required' => true,
755 'class' => array( 'form-row-wide', 'address-field', 'update_totals_on_change' ),
756 'autocomplete' => 'country',
757 'priority' => 40,
758 ),
759 'address_1' => array(
760 'label' => __( 'Street address', 'woocommerce' ),
761 /* translators: use local order of street name and house number. */
762 'placeholder' => esc_attr__( 'House number and street name', 'woocommerce' ),
763 'required' => true,
764 'class' => array( 'form-row-wide', 'address-field' ),
765 'autocomplete' => 'address-line1',
766 'priority' => 50,
767 ),
768 'address_2' => array(
769 'label' => $address_2_label,
770 'label_class' => array( 'screen-reader-text' ),
771 'placeholder' => esc_attr( $address_2_placeholder ),
772 'class' => array( 'form-row-wide', 'address-field' ),
773 'autocomplete' => 'address-line2',
774 'priority' => 60,
775 'required' => 'required' === get_option( 'woocommerce_checkout_address_2_field', 'optional' ),
776 ),
777 'city' => array(
778 'label' => __( 'Town / City', 'woocommerce' ),
779 'required' => true,
780 'class' => array( 'form-row-wide', 'address-field' ),
781 'autocomplete' => 'address-level2',
782 'priority' => 70,
783 ),
784 'state' => array(
785 'type' => 'state',
786 'label' => __( 'State / County', 'woocommerce' ),
787 'required' => true,
788 'class' => array( 'form-row-wide', 'address-field' ),
789 'validate' => array( 'state' ),
790 'autocomplete' => 'address-level1',
791 'priority' => 80,
792 ),
793 'postcode' => array(
794 'label' => __( 'Postcode / ZIP', 'woocommerce' ),
795 'required' => true,
796 'class' => array( 'form-row-wide', 'address-field' ),
797 'validate' => array( 'postcode' ),
798 'autocomplete' => 'postal-code',
799 'priority' => 90,
800 ),
801 );
802
803 if ( 'hidden' === get_option( 'woocommerce_checkout_company_field', 'optional' ) ) {
804 unset( $fields['company'] );
805 }
806
807 if ( 'hidden' === get_option( 'woocommerce_checkout_address_2_field', 'optional' ) ) {
808 unset( $fields['address_2'] );
809 }
810
811 $default_address_fields = apply_filters( 'woocommerce_default_address_fields', $fields );
812 // Sort each of the fields based on priority.
813 uasort( $default_address_fields, 'wc_checkout_fields_uasort_comparison' );
814
815 return $default_address_fields;
816 }
817
818 /**
819 * Get JS selectors for fields which are shown/hidden depending on the locale.
820 *
821 * @return array
822 */
823 public function get_country_locale_field_selectors() {
824 $locale_fields = array(
825 'address_1' => '#billing_address_1_field, #shipping_address_1_field',
826 'address_2' => '#billing_address_2_field, #shipping_address_2_field',
827 'state' => '#billing_state_field, #shipping_state_field, #calc_shipping_state_field',
828 'postcode' => '#billing_postcode_field, #shipping_postcode_field, #calc_shipping_postcode_field',
829 'city' => '#billing_city_field, #shipping_city_field, #calc_shipping_city_field',
830 );
831 return apply_filters( 'woocommerce_country_locale_field_selectors', $locale_fields );
832 }
833
834 /**
835 * Get country locale settings.
836 *
837 * These locales override the default country selections after a country is chosen.
838 *
839 * @return array
840 */
841 public function get_country_locale() {
842 if ( empty( $this->locale ) ) {
843 $this->locale = apply_filters(
844 'woocommerce_get_country_locale',
845 array(
846 'AE' => array(
847 'postcode' => array(
848 'required' => false,
849 'hidden' => true,
850 ),
851 'state' => array(
852 'required' => false,
853 ),
854 ),
855 'AF' => array(
856 'state' => array(
857 'required' => false,
858 'hidden' => true,
859 ),
860 ),
861 'AL' => array(
862 'state' => array(
863 'label' => __( 'County', 'woocommerce' ),
864 ),
865 ),
866 'AO' => array(
867 'postcode' => array(
868 'required' => false,
869 'hidden' => true,
870 ),
871 'state' => array(
872 'label' => __( 'Province', 'woocommerce' ),
873 ),
874 ),
875 'AT' => array(
876 'postcode' => array(
877 'priority' => 65,
878 ),
879 'state' => array(
880 'required' => false,
881 'hidden' => true,
882 ),
883 ),
884 'AU' => array(
885 'city' => array(
886 'label' => __( 'Suburb', 'woocommerce' ),
887 ),
888 'postcode' => array(
889 'label' => __( 'Postcode', 'woocommerce' ),
890 ),
891 'state' => array(
892 'label' => __( 'State', 'woocommerce' ),
893 ),
894 ),
895 'AX' => array(
896 'postcode' => array(
897 'priority' => 65,
898 ),
899 'state' => array(
900 'required' => false,
901 'hidden' => true,
902 ),
903 ),
904 'BA' => array(
905 'postcode' => array(
906 'priority' => 65,
907 ),
908 'state' => array(
909 'label' => __( 'Canton', 'woocommerce' ),
910 'required' => false,
911 'hidden' => true,
912 ),
913 ),
914 'BD' => array(
915 'postcode' => array(
916 'required' => false,
917 ),
918 'state' => array(
919 'label' => __( 'District', 'woocommerce' ),
920 ),
921 ),
922 'BE' => array(
923 'postcode' => array(
924 'priority' => 65,
925 ),
926 'state' => array(
927 'required' => false,
928 'hidden' => true,
929 ),
930 ),
931 'BG' => array(
932 'state' => array(
933 'required' => false,
934 ),
935 ),
936 'BH' => array(
937 'postcode' => array(
938 'required' => false,
939 ),
940 'state' => array(
941 'required' => false,
942 'hidden' => true,
943 ),
944 ),
945 'BI' => array(
946 'state' => array(
947 'required' => false,
948 'hidden' => true,
949 ),
950 ),
951 'BO' => array(
952 'postcode' => array(
953 'required' => false,
954 'hidden' => true,
955 ),
956 'state' => array(
957 'label' => __( 'Department', 'woocommerce' ),
958 ),
959 ),
960 'BS' => array(
961 'postcode' => array(
962 'required' => false,
963 'hidden' => true,
964 ),
965 ),
966 'BZ' => array(
967 'postcode' => array(
968 'required' => false,
969 'hidden' => true,
970 ),
971 'state' => array(
972 'required' => false,
973 ),
974 ),
975 'CA' => array(
976 'postcode' => array(
977 'label' => __( 'Postal code', 'woocommerce' ),
978 ),
979 'state' => array(
980 'label' => __( 'Province', 'woocommerce' ),
981 ),
982 ),
983 'CH' => array(
984 'postcode' => array(
985 'priority' => 65,
986 ),
987 'state' => array(
988 'label' => __( 'Canton', 'woocommerce' ),
989 'required' => false,
990 ),
991 ),
992 'CL' => array(
993 'city' => array(
994 'required' => true,
995 ),
996 'postcode' => array(
997 'required' => false,
998 // Hidden for stores within Chile. @see https://github.com/woocommerce/woocommerce/issues/36546.
999 'hidden' => 'CL' === $this->get_base_country(),
1000 ),
1001 'state' => array(
1002 'label' => __( 'Region', 'woocommerce' ),
1003 ),
1004 ),
1005 'CN' => array(
1006 'state' => array(
1007 'label' => __( 'Province', 'woocommerce' ),
1008 ),
1009 ),
1010 'CO' => array(
1011 'postcode' => array(
1012 'required' => false,
1013 ),
1014 'state' => array(
1015 'label' => __( 'Department', 'woocommerce' ),
1016 ),
1017 ),
1018 'CR' => array(
1019 'state' => array(
1020 'label' => __( 'Province', 'woocommerce' ),
1021 ),
1022 ),
1023 'CW' => array(
1024 'postcode' => array(
1025 'required' => false,
1026 'hidden' => true,
1027 ),
1028 'state' => array(
1029 'required' => false,
1030 ),
1031 ),
1032 'CZ' => array(
1033 'state' => array(
1034 'required' => false,
1035 'hidden' => true,
1036 ),
1037 ),
1038 'DE' => array(
1039 'postcode' => array(
1040 'priority' => 65,
1041 ),
1042 'state' => array(
1043 'required' => false,
1044 'hidden' => true,
1045 ),
1046 ),
1047 'DK' => array(
1048 'postcode' => array(
1049 'priority' => 65,
1050 ),
1051 'state' => array(
1052 'required' => false,
1053 'hidden' => true,
1054 ),
1055 ),
1056 'DO' => array(
1057 'state' => array(
1058 'label' => __( 'Province', 'woocommerce' ),
1059 ),
1060 ),
1061 'EC' => array(
1062 'state' => array(
1063 'label' => __( 'Province', 'woocommerce' ),
1064 ),
1065 ),
1066 'EE' => array(
1067 'postcode' => array(
1068 'priority' => 65,
1069 ),
1070 'state' => array(
1071 'required' => false,
1072 'hidden' => true,
1073 ),
1074 ),
1075 'ET' => array(
1076 'state' => array(
1077 'required' => false,
1078 'hidden' => true,
1079 ),
1080 ),
1081 'FI' => array(
1082 'postcode' => array(
1083 'priority' => 65,
1084 ),
1085 'state' => array(
1086 'required' => false,
1087 'hidden' => true,
1088 ),
1089 ),
1090 'FR' => array(
1091 'postcode' => array(
1092 'priority' => 65,
1093 ),
1094 'state' => array(
1095 'required' => false,
1096 'hidden' => true,
1097 ),
1098 ),
1099 'GG' => array(
1100 'state' => array(
1101 'required' => false,
1102 'label' => __( 'Parish', 'woocommerce' ),
1103 ),
1104 ),
1105 'GH' => array(
1106 'postcode' => array(
1107 'required' => false,
1108 ),
1109 'state' => array(
1110 'label' => __( 'Region', 'woocommerce' ),
1111 ),
1112 ),
1113 'GP' => array(
1114 'state' => array(
1115 'required' => false,
1116 'hidden' => true,
1117 ),
1118 ),
1119 'GF' => array(
1120 'state' => array(
1121 'required' => false,
1122 'hidden' => true,
1123 ),
1124 ),
1125 'GR' => array(
1126 'state' => array(
1127 'required' => false,
1128 ),
1129 ),
1130 'GT' => array(
1131 'postcode' => array(
1132 'required' => false,
1133 ),
1134 'state' => array(
1135 'label' => __( 'Department', 'woocommerce' ),
1136 ),
1137 ),
1138 'HK' => array(
1139 'postcode' => array(
1140 'required' => false,
1141 ),
1142 'city' => array(
1143 'label' => __( 'Town / District', 'woocommerce' ),
1144 ),
1145 'state' => array(
1146 'label' => __( 'Region', 'woocommerce' ),
1147 ),
1148 ),
1149 'HN' => array(
1150 'state' => array(
1151 'label' => __( 'Department', 'woocommerce' ),
1152 ),
1153 ),
1154 'HU' => array(
1155 'last_name' => array(
1156 'class' => array( 'form-row-first' ),
1157 'priority' => 10,
1158 ),
1159 'first_name' => array(
1160 'class' => array( 'form-row-last' ),
1161 'priority' => 20,
1162 ),
1163 'postcode' => array(
1164 'class' => array( 'form-row-first', 'address-field' ),
1165 'priority' => 65,
1166 ),
1167 'city' => array(
1168 'class' => array( 'form-row-last', 'address-field' ),
1169 ),
1170 'address_1' => array(
1171 'priority' => 71,
1172 ),
1173 'address_2' => array(
1174 'priority' => 72,
1175 ),
1176 'state' => array(
1177 'label' => __( 'County', 'woocommerce' ),
1178 'required' => false,
1179 ),
1180 ),
1181 'ID' => array(
1182 'state' => array(
1183 'label' => __( 'Province', 'woocommerce' ),
1184 ),
1185 ),
1186 'IE' => array(
1187 'postcode' => array(
1188 'required' => false,
1189 'label' => __( 'Eircode', 'woocommerce' ),
1190 ),
1191 'state' => array(
1192 'label' => __( 'County', 'woocommerce' ),
1193 ),
1194 ),
1195 'IS' => array(
1196 'postcode' => array(
1197 'priority' => 65,
1198 ),
1199 'state' => array(
1200 'required' => false,
1201 'hidden' => true,
1202 ),
1203 ),
1204 'IL' => array(
1205 'postcode' => array(
1206 'priority' => 65,
1207 ),
1208 'state' => array(
1209 'required' => false,
1210 'hidden' => true,
1211 ),
1212 ),
1213 'IM' => array(
1214 'state' => array(
1215 'required' => false,
1216 'hidden' => true,
1217 ),
1218 ),
1219 'IN' => array(
1220 'postcode' => array(
1221 'label' => __( 'PIN Code', 'woocommerce' ),
1222 ),
1223 'state' => array(
1224 'label' => __( 'State', 'woocommerce' ),
1225 ),
1226 ),
1227 'IR' => array(
1228 'state' => array(
1229 'priority' => 50,
1230 ),
1231 'city' => array(
1232 'priority' => 60,
1233 ),
1234 'address_1' => array(
1235 'priority' => 70,
1236 ),
1237 'address_2' => array(
1238 'priority' => 80,
1239 ),
1240 ),
1241 'IT' => array(
1242 'postcode' => array(
1243 'priority' => 65,
1244 ),
1245 'state' => array(
1246 'required' => true,
1247 'label' => __( 'Province', 'woocommerce' ),
1248 ),
1249 ),
1250 'JM' => array(
1251 'city' => array(
1252 'label' => __( 'Town / City / Post Office', 'woocommerce' ),
1253 ),
1254 'postcode' => array(
1255 'required' => false,
1256 'label' => __( 'Postal Code', 'woocommerce' ),
1257 ),
1258 'state' => array(
1259 'required' => true,
1260 'label' => __( 'Parish', 'woocommerce' ),
1261 ),
1262 ),
1263 'JP' => array(
1264 'last_name' => array(
1265 'class' => array( 'form-row-first' ),
1266 'priority' => 10,
1267 ),
1268 'first_name' => array(
1269 'class' => array( 'form-row-last' ),
1270 'priority' => 20,
1271 ),
1272 'postcode' => array(
1273 'class' => array( 'form-row-first', 'address-field' ),
1274 'priority' => 65,
1275 ),
1276 'state' => array(
1277 'label' => __( 'Prefecture', 'woocommerce' ),
1278 'class' => array( 'form-row-last', 'address-field' ),
1279 'priority' => 66,
1280 ),
1281 'city' => array(
1282 'priority' => 67,
1283 ),
1284 'address_1' => array(
1285 'priority' => 68,
1286 ),
1287 'address_2' => array(
1288 'priority' => 69,
1289 ),
1290 ),
1291 'KN' => array(
1292 'postcode' => array(
1293 'required' => false,
1294 'label' => __( 'Postal code', 'woocommerce' ),
1295 ),
1296 'state' => array(
1297 'required' => true,
1298 'label' => __( 'Parish', 'woocommerce' ),
1299 ),
1300 ),
1301 'KR' => array(
1302 'state' => array(
1303 'required' => false,
1304 'hidden' => true,
1305 ),
1306 ),
1307 'KW' => array(
1308 'state' => array(
1309 'required' => false,
1310 'hidden' => true,
1311 ),
1312 ),
1313 'LV' => array(
1314 'state' => array(
1315 'label' => __( 'Municipality', 'woocommerce' ),
1316 'required' => false,
1317 ),
1318 ),
1319 'LB' => array(
1320 'state' => array(
1321 'required' => false,
1322 'hidden' => true,
1323 ),
1324 ),
1325 'MF' => array(
1326 'state' => array(
1327 'required' => false,
1328 'hidden' => true,
1329 ),
1330 ),
1331 'MQ' => array(
1332 'state' => array(
1333 'required' => false,
1334 'hidden' => true,
1335 ),
1336 ),
1337 'MT' => array(
1338 'state' => array(
1339 'required' => false,
1340 'hidden' => true,
1341 ),
1342 ),
1343 'MZ' => array(
1344 'postcode' => array(
1345 'required' => false,
1346 'hidden' => true,
1347 ),
1348 'state' => array(
1349 'label' => __( 'Province', 'woocommerce' ),
1350 ),
1351 ),
1352 'NI' => array(
1353 'state' => array(
1354 'label' => __( 'Department', 'woocommerce' ),
1355 ),
1356 ),
1357 'NL' => array(
1358 'postcode' => array(
1359 'priority' => 65,
1360 ),
1361 'state' => array(
1362 'required' => false,
1363 'hidden' => true,
1364 ),
1365 ),
1366 'NG' => array(
1367 'postcode' => array(
1368 'label' => __( 'Postcode', 'woocommerce' ),
1369 'required' => false,
1370 'hidden' => true,
1371 ),
1372 'state' => array(
1373 'label' => __( 'State', 'woocommerce' ),
1374 ),
1375 ),
1376 'NZ' => array(
1377 'postcode' => array(
1378 'label' => __( 'Postcode', 'woocommerce' ),
1379 ),
1380 'state' => array(
1381 'required' => false,
1382 'label' => __( 'Region', 'woocommerce' ),
1383 ),
1384 ),
1385 'NO' => array(
1386 'postcode' => array(
1387 'priority' => 65,
1388 ),
1389 'state' => array(
1390 'required' => false,
1391 'hidden' => true,
1392 ),
1393 ),
1394 'NP' => array(
1395 'state' => array(
1396 'label' => __( 'State / Zone', 'woocommerce' ),
1397 ),
1398 'postcode' => array(
1399 'required' => false,
1400 ),
1401 ),
1402 'PA' => array(
1403 'state' => array(
1404 'label' => __( 'Province', 'woocommerce' ),
1405 ),
1406 ),
1407 'PL' => array(
1408 'postcode' => array(
1409 'priority' => 65,
1410 ),
1411 'state' => array(
1412 'required' => false,
1413 'hidden' => true,
1414 ),
1415 ),
1416 'PR' => array(
1417 'city' => array(
1418 'label' => __( 'Municipality', 'woocommerce' ),
1419 ),
1420 'state' => array(
1421 'required' => false,
1422 'hidden' => true,
1423 ),
1424 ),
1425 'PT' => array(
1426 'state' => array(
1427 'required' => false,
1428 'hidden' => true,
1429 ),
1430 ),
1431 'PY' => array(
1432 'state' => array(
1433 'label' => __( 'Department', 'woocommerce' ),
1434 ),
1435 ),
1436 'RE' => array(
1437 'state' => array(
1438 'required' => false,
1439 'hidden' => true,
1440 ),
1441 ),
1442 'RO' => array(
1443 'state' => array(
1444 'label' => __( 'County', 'woocommerce' ),
1445 'required' => true,
1446 ),
1447 ),
1448 'RS' => array(
1449 'city' => array(
1450 'required' => true,
1451 ),
1452 'postcode' => array(
1453 'required' => true,
1454 ),
1455 'state' => array(
1456 'label' => __( 'District', 'woocommerce' ),
1457 'required' => false,
1458 ),
1459 ),
1460 'RW' => array(
1461 'state' => array(
1462 'required' => false,
1463 'hidden' => true,
1464 ),
1465 ),
1466 'SG' => array(
1467 'state' => array(
1468 'required' => false,
1469 'hidden' => true,
1470 ),
1471 'city' => array(
1472 'required' => false,
1473 ),
1474 ),
1475 'SK' => array(
1476 'postcode' => array(
1477 'priority' => 65,
1478 ),
1479 'state' => array(
1480 'required' => false,
1481 'hidden' => true,
1482 ),
1483 ),
1484 'SI' => array(
1485 'postcode' => array(
1486 'priority' => 65,
1487 ),
1488 'state' => array(
1489 'required' => false,
1490 'hidden' => true,
1491 ),
1492 ),
1493 'SR' => array(
1494 'postcode' => array(
1495 'required' => false,
1496 'hidden' => true,
1497 ),
1498 ),
1499 'SV' => array(
1500 'state' => array(
1501 'label' => __( 'Department', 'woocommerce' ),
1502 ),
1503 ),
1504 'ES' => array(
1505 'postcode' => array(
1506 'priority' => 65,
1507 ),
1508 'state' => array(
1509 'label' => __( 'Province', 'woocommerce' ),
1510 ),
1511 ),
1512 'LI' => array(
1513 'postcode' => array(
1514 'priority' => 65,
1515 ),
1516 'state' => array(
1517 'required' => false,
1518 'hidden' => true,
1519 ),
1520 ),
1521 'LK' => array(
1522 'state' => array(
1523 'required' => false,
1524 'hidden' => true,
1525 ),
1526 ),
1527 'LU' => array(
1528 'state' => array(
1529 'required' => false,
1530 'hidden' => true,
1531 ),
1532 ),
1533 'MD' => array(
1534 'state' => array(
1535 'label' => __( 'Municipality / District', 'woocommerce' ),
1536 ),
1537 ),
1538 'SE' => array(
1539 'postcode' => array(
1540 'priority' => 65,
1541 ),
1542 'state' => array(
1543 'required' => false,
1544 'hidden' => true,
1545 ),
1546 ),
1547 'TR' => array(
1548 'postcode' => array(
1549 'priority' => 65,
1550 ),
1551 'state' => array(
1552 'label' => __( 'Province', 'woocommerce' ),
1553 ),
1554 ),
1555 'UG' => array(
1556 'postcode' => array(
1557 'required' => false,
1558 'hidden' => true,
1559 ),
1560 'city' => array(
1561 'label' => __( 'Town / Village', 'woocommerce' ),
1562 'required' => true,
1563 ),
1564 'state' => array(
1565 'label' => __( 'District', 'woocommerce' ),
1566 'required' => true,
1567 ),
1568 ),
1569 'US' => array(
1570 'postcode' => array(
1571 'label' => __( 'ZIP Code', 'woocommerce' ),
1572 ),
1573 'state' => array(
1574 'label' => __( 'State', 'woocommerce' ),
1575 ),
1576 ),
1577 'UY' => array(
1578 'state' => array(
1579 'label' => __( 'Department', 'woocommerce' ),
1580 ),
1581 ),
1582 'GB' => array(
1583 'postcode' => array(
1584 'label' => __( 'Postcode', 'woocommerce' ),
1585 ),
1586 'state' => array(
1587 'label' => __( 'County', 'woocommerce' ),
1588 'required' => false,
1589 ),
1590 ),
1591 'ST' => array(
1592 'postcode' => array(
1593 'required' => false,
1594 'hidden' => true,
1595 ),
1596 'state' => array(
1597 'label' => __( 'District', 'woocommerce' ),
1598 ),
1599 ),
1600 'VN' => array(
1601 'state' => array(
1602 'required' => false,
1603 'hidden' => true,
1604 ),
1605 'postcode' => array(
1606 'priority' => 65,
1607 'required' => false,
1608 'hidden' => false,
1609 ),
1610 'address_2' => array(
1611 'required' => false,
1612 'hidden' => false,
1613 ),
1614 ),
1615 'WS' => array(
1616 'postcode' => array(
1617 'required' => false,
1618 'hidden' => true,
1619 ),
1620 ),
1621 'YT' => array(
1622 'state' => array(
1623 'required' => false,
1624 'hidden' => true,
1625 ),
1626 ),
1627 'ZA' => array(
1628 'state' => array(
1629 'label' => __( 'Province', 'woocommerce' ),
1630 ),
1631 ),
1632 'ZW' => array(
1633 'postcode' => array(
1634 'required' => false,
1635 'hidden' => true,
1636 ),
1637 ),
1638 )
1639 );
1640
1641 $this->locale = array_intersect_key( $this->locale, array_merge( $this->get_allowed_countries(), $this->get_shipping_countries() ) );
1642
1643 // Default Locale Can be filtered to override fields in get_address_fields(). Countries with no specific locale will use default.
1644 $this->locale['default'] = apply_filters( 'woocommerce_get_country_locale_default', $this->get_default_address_fields() );
1645
1646 // Filter default AND shop base locales to allow overrides via a single function. These will be used when changing countries on the checkout.
1647 if ( ! isset( $this->locale[ $this->get_base_country() ] ) ) {
1648 $this->locale[ $this->get_base_country() ] = $this->locale['default'];
1649 }
1650
1651 $this->locale['default'] = apply_filters( 'woocommerce_get_country_locale_base', $this->locale['default'] );
1652 $this->locale[ $this->get_base_country() ] = apply_filters( 'woocommerce_get_country_locale_base', $this->locale[ $this->get_base_country() ] );
1653 }
1654
1655 return $this->locale;
1656 }
1657
1658 /**
1659 * Apply locale and get address fields.
1660 *
1661 * @param mixed $country Country.
1662 * @param string $type Address type, defaults to 'billing_'.
1663 * @return array
1664 */
1665 public function get_address_fields( $country = '', $type = 'billing_' ) {
1666 if ( ! $country ) {
1667 $country = $this->get_base_country();
1668 }
1669
1670 $fields = $this->get_default_address_fields();
1671 $locale = $this->get_country_locale();
1672
1673 if ( isset( $locale[ $country ] ) ) {
1674 $fields = wc_array_overlay( $fields, $locale[ $country ] );
1675 }
1676
1677 // Prepend field keys.
1678 $address_fields = array();
1679
1680 foreach ( $fields as $key => $value ) {
1681 if ( 'state' === $key ) {
1682 $value['country_field'] = $type . 'country';
1683 $value['country'] = $country;
1684 }
1685 $address_fields[ $type . $key ] = $value;
1686 }
1687
1688 // Add email and phone fields.
1689 if ( 'billing_' === $type ) {
1690 if ( 'hidden' !== get_option( 'woocommerce_checkout_phone_field', 'required' ) ) {
1691 $address_fields['billing_phone'] = array(
1692 'label' => __( 'Phone', 'woocommerce' ),
1693 'required' => 'required' === get_option( 'woocommerce_checkout_phone_field', 'required' ),
1694 'type' => 'tel',
1695 'class' => array( 'form-row-wide' ),
1696 'validate' => array( 'phone' ),
1697 'autocomplete' => 'tel',
1698 'priority' => 100,
1699 );
1700 }
1701 $address_fields['billing_email'] = array(
1702 'label' => __( 'Email address', 'woocommerce' ),
1703 'required' => true,
1704 'type' => 'email',
1705 'class' => array( 'form-row-wide' ),
1706 'validate' => array( 'email' ),
1707 'autocomplete' => 'no' === get_option( 'woocommerce_registration_generate_username' ) ? 'email' : 'email username',
1708 'priority' => 110,
1709 );
1710 }
1711
1712 /**
1713 * Important note on this filter: Changes to address fields can and will be overridden by
1714 * the woocommerce_default_address_fields. The locales/default locales apply on top based
1715 * on country selection. If you want to change things like the required status of an
1716 * address field, filter woocommerce_default_address_fields instead.
1717 */
1718 $address_fields = apply_filters( 'woocommerce_' . $type . 'fields', $address_fields, $country );
1719 // Sort each of the fields based on priority.
1720 uasort( $address_fields, 'wc_checkout_fields_uasort_comparison' );
1721
1722 return $address_fields;
1723 }
1724 }
1725