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