Completed
Push — master ( f35d87...c6975f )
by Mike
08:15
created

WC_Countries::get_base_country()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 4
rs 10
cc 1
eloc 3
nc 1
nop 0
1
<?php
1 ignored issue
show
Coding Style Compatibility introduced by
For compatibility and reusability of your code, PSR1 recommends that a file should introduce either new symbols (like classes, functions, etc.) or have side-effects (like outputting something, or including other files), but not both at the same time. The first symbol is defined on line 18 and the first side effect is on line 4.

The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.

The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.

To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.

Loading history...
2
3
if ( ! defined( 'ABSPATH' ) ) {
4
	exit; // Exit if accessed directly
5
}
6
7
/**
8
 * WooCommerce countries
9
 *
10
 * The WooCommerce countries class stores country/state data.
11
 *
12
 * @class       WC_Countries
13
 * @version     2.3.0
14
 * @package     WooCommerce/Classes
15
 * @category    Class
16
 * @author      WooThemes
17
 */
18
class WC_Countries {
19
20
	/** @var array Array of locales */
21
	public $locale;
22
23
	/** @var array Array of address formats for locales */
24
	public $address_formats;
25
26
	/**
27
	 * Auto-load in-accessible properties on demand.
28
	 * @param  mixed $key
29
	 * @return mixed
30
	 */
31
	public function __get( $key ) {
32
		if ( 'countries' == $key ) {
33
			return $this->get_countries();
34
		} elseif ( 'states' == $key ) {
35
			return $this->get_states();
36
		}
37
	}
38
39
	/**
40
	 * Get all countries.
41
	 * @return array
42
	 */
43
	public function get_countries() {
44
		if ( empty( $this->countries ) ) {
45
			$this->countries = apply_filters( 'woocommerce_countries', include( WC()->plugin_path() . '/i18n/countries.php' ) );
46
			if ( apply_filters( 'woocommerce_sort_countries', true ) ) {
47
				asort( $this->countries );
48
			}
49
		}
50
		return $this->countries;
51
	}
52
53
	/**
54
	 * Get all continents.
55
	 * @return array
56
	 */
57
	public function get_continents() {
58
		if ( empty( $this->continents ) ) {
59
			$this->continents = apply_filters( 'woocommerce_continents', include( WC()->plugin_path() . '/i18n/continents.php' ) );
60
		}
61
		return $this->continents;
62
	}
63
64
	/**
65
	 * Get continent code for a country code.
66
	 * @since 2.6.0
67
	 * @param $cc string
68
	 * @return string
69
	 */
70
	public function get_continent_code_for_country( $cc ) {
71
		$cc                 = trim( strtoupper( $cc ) );
72
		$continents         = $this->get_continents();
73
		$continents_and_ccs = wp_list_pluck( $continents, 'countries' );
74
		foreach ( $continents_and_ccs as $continent_code => $countries ) {
75
			if ( false !== array_search( $cc, $countries ) ) {
76
				return $continent_code;
77
			}
78
		}
79
		return '';
80
	}
81
82
	/**
83
	 * Load the states.
84
	 */
85
	public function load_country_states() {
86
		global $states;
87
88
		// States set to array() are blank i.e. the country has no use for the state field.
89
		$states = array(
90
			'AF' => array(),
91
			'AT' => array(),
92
			'AX' => array(),
93
			'BE' => array(),
94
			'BI' => array(),
95
			'CZ' => array(),
96
			'DE' => array(),
97
			'DK' => array(),
98
			'EE' => array(),
99
			'FI' => array(),
100
			'FR' => array(),
101
			'IS' => array(),
102
			'IL' => array(),
103
			'KR' => array(),
104
			'NL' => array(),
105
			'NO' => array(),
106
			'PL' => array(),
107
			'PT' => array(),
108
			'SG' => array(),
109
			'SK' => array(),
110
			'SI' => array(),
111
			'LK' => array(),
112
			'SE' => array(),
113
			'VN' => array(),
114
		);
115
116
		// Load only the state files the shop owner wants/needs.
117
		$allowed = array_merge( $this->get_allowed_countries(), $this->get_shipping_countries() );
118
119
		if ( $allowed ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $allowed of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
120
			foreach ( $allowed as $code => $country ) {
121
				if ( ! isset( $states[ $code ] ) && file_exists( WC()->plugin_path() . '/i18n/states/' . $code . '.php' ) ) {
122
					include( WC()->plugin_path() . '/i18n/states/' . $code . '.php' );
123
				}
124
			}
125
		}
126
127
		$this->states = apply_filters( 'woocommerce_states', $states );
128
	}
129
130
	/**
131
	 * Get the states for a country.
132
	 * @param  string $cc country code
133
	 * @return array of states
134
	 */
135
	public function get_states( $cc = null ) {
136
		if ( empty( $this->states ) ) {
137
			$this->load_country_states();
138
		}
139
140
		if ( ! is_null( $cc ) ) {
141
			return isset( $this->states[ $cc ] ) ? $this->states[ $cc ] : false;
142
		} else {
143
			return $this->states;
144
		}
145
	}
146
147
	/**
148
	 * Get the base country for the store.
149
	 * @return string
150
	 */
151
	public function get_base_country() {
152
		$default = wc_get_base_location();
153
		return apply_filters( 'woocommerce_countries_base_country', $default['country'] );
154
	}
155
156
	/**
157
	 * Get the base state for the store.
158
	 * @return string
159
	 */
160
	public function get_base_state() {
161
		$default = wc_get_base_location();
162
		return apply_filters( 'woocommerce_countries_base_state', $default['state'] );
163
	}
164
165
	/**
166
	 * Get the base city for the store.
167
	 * @return string
168
	 */
169
	public function get_base_city() {
170
		return apply_filters( 'woocommerce_countries_base_city', '' );
171
	}
172
173
	/**
174
	 * Get the base postcode for the store.
175
	 * @return string
176
	 */
177
	public function get_base_postcode() {
178
		return apply_filters( 'woocommerce_countries_base_postcode', '' );
179
	}
180
181
	/**
182
	 * Get the allowed countries for the store.
183
	 * @return array
184
	 */
185
	public function get_allowed_countries() {
186
		if ( 'all' === get_option( 'woocommerce_allowed_countries' ) ) {
187
			return $this->countries;
188
		}
189
190
		if( 'all_except' === get_option( 'woocommerce_allowed_countries' ) ) {
191
			$except_countries = get_option( 'woocommerce_all_except_countries', array() );
192
193
			if ( ! $except_countries ) {
194
				return $this->countries;
195
			} else {
196
				$all_except_countries = $this->countries;
197
				foreach( $except_countries as $country ) {
198
					unset( $all_except_countries[ $country ] );
199
				}
200
				return apply_filters( 'woocommerce_countries_allowed_countries', $all_except_countries );
201
			}
202
		}
203
204
		$countries = array();
205
206
		$raw_countries = get_option( 'woocommerce_specific_allowed_countries', array() );
207
208
		if ( $raw_countries ) {
209
			foreach ( $raw_countries as $country ) {
210
				$countries[ $country ] = $this->countries[ $country ];
211
			}
212
		}
213
214
		return apply_filters( 'woocommerce_countries_allowed_countries', $countries );
215
	}
216
217
	/**
218
	 * Get the countries you ship to.
219
	 * @return array
220
	 */
221
	public function get_shipping_countries() {
222
		if ( '' === get_option( 'woocommerce_ship_to_countries' ) ) {
223
			return $this->get_allowed_countries();
224
		}
225
226
		if ( 'all' === get_option( 'woocommerce_ship_to_countries' ) ) {
227
			return $this->countries;
228
		}
229
230
		$countries = array();
231
232
		$raw_countries = get_option( 'woocommerce_specific_ship_to_countries' );
233
234
		foreach ( $raw_countries as $country ) {
235
			$countries[ $country ] = $this->countries[ $country ];
236
		}
237
238
		return apply_filters( 'woocommerce_countries_shipping_countries', $countries );
239
	}
240
241
	/**
242
	 * Get allowed country states.
243
	 * @return array
244
	 */
245
	public function get_allowed_country_states() {
246
		if ( get_option( 'woocommerce_allowed_countries' ) !== 'specific' ) {
247
			return $this->states;
248
		}
249
250
		$states = array();
251
252
		$raw_countries = get_option( 'woocommerce_specific_allowed_countries' );
253
254
		foreach ( $raw_countries as $country ) {
255
			if ( isset( $this->states[ $country ] ) ) {
256
				$states[ $country ] = $this->states[ $country ];
257
			}
258
		}
259
260
		return apply_filters( 'woocommerce_countries_allowed_country_states', $states );
261
	}
262
263
	/**
264
	 * Get shipping country states.
265
	 * @return array
266
	 */
267
	public function get_shipping_country_states() {
268
		if ( get_option( 'woocommerce_ship_to_countries' ) == '' ) {
269
			return $this->get_allowed_country_states();
270
		}
271
272
		if ( get_option( 'woocommerce_ship_to_countries' ) !== 'specific' ) {
273
			return $this->states;
274
		}
275
276
		$states = array();
277
278
		$raw_countries = get_option( 'woocommerce_specific_ship_to_countries' );
279
280
		foreach ( $raw_countries as $country ) {
281
			if ( ! empty( $this->states[ $country ] ) ) {
282
				$states[ $country ] = $this->states[ $country ];
283
			}
284
		}
285
286
		return apply_filters( 'woocommerce_countries_shipping_country_states', $states );
287
	}
288
289
	/**
290
	 * Gets an array of countries in the EU.
291
	 *
292
	 * MC (monaco) and IM (isle of man, part of UK) also use VAT.
293
	 *
294
	 * @param  $type Type of countries to retrieve. Blank for EU member countries. eu_vat for EU VAT countries.
295
	 * @return string[]
296
	 */
297
	public function get_european_union_countries( $type = '' ) {
298
		$countries = array( 'AT', 'BE', 'BG', 'CY', 'CZ', 'DE', 'DK', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HU', 'HR', 'IE', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'PL', 'PT', 'RO', 'SE', 'SI', 'SK' );
299
300
		if ( 'eu_vat' === $type ) {
301
			$countries[] = 'MC';
302
			$countries[] = 'IM';
303
		}
304
305
		return $countries;
306
	}
307
308
	/**
309
	 * Gets the correct string for shipping - either 'to the' or 'to'
310
	 * @return string
311
	 */
312
	public function shipping_to_prefix( $country_code = '' ) {
313
		$country_code = $country_code ? $country_code : WC()->customer->get_shipping_country();
314
		$countries    = array( 'GB', 'US', 'AE', 'CZ', 'DO', 'NL', 'PH', 'USAF' );
315
		$return       = in_array( $country_code, $countries ) ? __( 'to the', 'woocommerce' ) : __( 'to', 'woocommerce' );
316
317
		return apply_filters( 'woocommerce_countries_shipping_to_prefix', $return, $country_code );
318
	}
319
320
	/**
321
	 * Prefix certain countries with 'the'
322
	 * @return string
323
	 */
324
	public function estimated_for_prefix( $country_code = '' ) {
325
		$country_code = $country_code ? $country_code : $this->get_base_country();
326
		$countries    = array( 'GB', 'US', 'AE', 'CZ', 'DO', 'NL', 'PH', 'USAF' );
327
		$return       = in_array( $country_code, $countries ) ? __( 'the', 'woocommerce' ) . ' ' : '';
328
329
		return apply_filters( 'woocommerce_countries_estimated_for_prefix', $return, $country_code );
330
	}
331
332
	/**
333
	 * Correctly name tax in some countries VAT on the frontend.
334
	 * @return string
335
	 */
336
	public function tax_or_vat() {
337
		$return = in_array( $this->get_base_country(), $this->get_european_union_countries( 'eu_vat' ) ) ? __( 'VAT', 'woocommerce' ) : __( 'Tax', 'woocommerce' );
338
339
		return apply_filters( 'woocommerce_countries_tax_or_vat', $return );
340
	}
341
342
	/**
343
	 * Include the Inc Tax label.
344
	 * @return string
345
	 */
346
	public function inc_tax_or_vat() {
347
		$return = in_array( $this->get_base_country(), $this->get_european_union_countries( 'eu_vat' ) ) ? __( '(incl. VAT)', 'woocommerce' ) : __( '(incl. tax)', 'woocommerce' );
348
349
		return apply_filters( 'woocommerce_countries_inc_tax_or_vat', $return );
350
	}
351
352
	/**
353
	 * Include the Ex Tax label.
354
	 * @return string
355
	 */
356
	public function ex_tax_or_vat() {
357
		$return = in_array( $this->get_base_country(), $this->get_european_union_countries( 'eu_vat' ) ) ? __( '(ex. VAT)', 'woocommerce' ) : __( '(ex. tax)', 'woocommerce' );
358
359
		return apply_filters( 'woocommerce_countries_ex_tax_or_vat', $return );
360
	}
361
362
	/**
363
	 * Outputs the list of countries and states for use in dropdown boxes.
364
	 * @param string $selected_country (default: '')
365
	 * @param string $selected_state (default: '')
366
	 * @param bool $escape (default: false)
367
	 * @param bool   $escape (default: false)
368
	 */
369
	public function country_dropdown_options( $selected_country = '', $selected_state = '', $escape = false ) {
370
		if ( $this->countries ) foreach ( $this->countries as $key => $value ) :
371
			if ( $states = $this->get_states( $key ) ) :
372
				echo '<optgroup label="' . esc_attr( $value ) . '">';
373
					foreach ( $states as $state_key => $state_value ) :
374
						echo '<option value="' . esc_attr( $key ) . ':' . $state_key . '"';
375
376
						if ( $selected_country == $key && $selected_state == $state_key ) {
377
							echo ' selected="selected"';
378
						}
379
380
						echo '>' . $value . ' &mdash; ' . ( $escape ? esc_js( $state_value ) : $state_value ) . '</option>';
381
					endforeach;
382
				echo '</optgroup>';
383
			else :
384
				echo '<option';
385
				if ( $selected_country == $key && $selected_state == '*' ) {
386
					echo ' selected="selected"';
387
				}
388
				echo ' value="' . esc_attr( $key ) . '">' . ( $escape ? esc_js( $value ) : $value ) . '</option>';
389
			endif;
390
		endforeach;
391
	}
392
393
	/**
394
	 * Get country address formats.
395
	 * @return array
396
	 */
397
	public function get_address_formats() {
398
		if ( ! $this->address_formats ) :
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->address_formats of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
399
400
			// Common formats
401
			$postcode_before_city = "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}";
402
403
			// Define address formats
404
			$this->address_formats = apply_filters( 'woocommerce_localisation_address_formats', array(
405
				'default' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}\n{postcode}\n{country}",
406
				'AU' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
407
				'AT' => $postcode_before_city,
408
				'BE' => $postcode_before_city,
409
				'CA' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
410
				'CH' => $postcode_before_city,
411
				'CL' => "{company}\n{name}\n{address_1}\n{address_2}\n{state}\n{postcode} {city}\n{country}",
412
				'CN' => "{country} {postcode}\n{state}, {city}, {address_2}, {address_1}\n{company}\n{name}",
413
				'CZ' => $postcode_before_city,
414
				'DE' => $postcode_before_city,
415
				'EE' => $postcode_before_city,
416
				'FI' => $postcode_before_city,
417
				'DK' => $postcode_before_city,
418
				'FR' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city_upper}\n{country}",
419
				'HK' => "{company}\n{first_name} {last_name_upper}\n{address_1}\n{address_2}\n{city_upper}\n{state_upper}\n{country}",
420
				'HU' => "{name}\n{company}\n{city}\n{address_1}\n{address_2}\n{postcode}\n{country}",
421
				'IN' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} - {postcode}\n{state}, {country}",
422
				'IS' => $postcode_before_city,
423
				'IT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode}\n{city}\n{state_upper}\n{country}",
424
				'JP' => "{postcode}\n{state}{city}{address_1}\n{address_2}\n{company}\n{last_name} {first_name}\n{country}",
425
				'TW' => "{company}\n{last_name} {first_name}\n{address_1}\n{address_2}\n{state}, {city} {postcode}\n{country}",
426
				'LI' => $postcode_before_city,
427
				'NL' => $postcode_before_city,
428
				'NZ' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {postcode}\n{country}",
429
				'NO' => $postcode_before_city,
430
				'PL' => $postcode_before_city,
431
				'SK' => $postcode_before_city,
432
				'SI' => $postcode_before_city,
433
				'ES' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city}\n{state}\n{country}",
434
				'SE' => $postcode_before_city,
435
				'TR' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city} {state}\n{country}",
436
				'US' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}, {state_code} {postcode}\n{country}",
437
				'VN' => "{name}\n{company}\n{address_1}\n{city}\n{country}",
438
			));
439
		endif;
440
441
		return $this->address_formats;
442
	}
443
444
	/**
445
	 * Get country address format.
446
	 * @param  array  $args (default: array())
447
	 * @return string address
448
	 */
449
	public function get_formatted_address( $args = array() ) {
450
		$default_args = array(
451
			'first_name' => '',
452
			'last_name'  => '',
453
			'company'    => '',
454
			'address_1'  => '',
455
			'address_2'  => '',
456
			'city'       => '',
457
			'state'      => '',
458
			'postcode'   => '',
459
			'country'    => ''
460
		);
461
462
		$args = array_map( 'trim', wp_parse_args( $args, $default_args ) );
463
464
		extract( $args );
465
466
		// Get all formats
467
		$formats = $this->get_address_formats();
468
469
		// Get format for the address' country
470
		$format = ( $country && isset( $formats[ $country ] ) ) ? $formats[ $country ] : $formats['default'];
471
472
		// Handle full country name
473
		$full_country = ( isset( $this->countries[ $country ] ) ) ? $this->countries[ $country ] : $country;
474
475
		// Country is not needed if the same as base
476
		if ( $country == $this->get_base_country() && ! apply_filters( 'woocommerce_formatted_address_force_country_display', false ) ) {
477
			$format = str_replace( '{country}', '', $format );
478
		}
479
480
		// Handle full state name
481
		$full_state = ( $country && $state && isset( $this->states[ $country ][ $state ] ) ) ? $this->states[ $country ][ $state ] : $state;
482
483
		// Substitute address parts into the string
484
		$replace = array_map( 'esc_html', apply_filters( 'woocommerce_formatted_address_replacements', array(
485
			'{first_name}'       => $first_name,
486
			'{last_name}'        => $last_name,
487
			'{name}'             => $first_name . ' ' . $last_name,
488
			'{company}'          => $company,
489
			'{address_1}'        => $address_1,
490
			'{address_2}'        => $address_2,
491
			'{city}'             => $city,
492
			'{state}'            => $full_state,
493
			'{postcode}'         => $postcode,
494
			'{country}'          => $full_country,
495
			'{first_name_upper}' => strtoupper( $first_name ),
496
			'{last_name_upper}'  => strtoupper( $last_name ),
497
			'{name_upper}'       => strtoupper( $first_name . ' ' . $last_name ),
498
			'{company_upper}'    => strtoupper( $company ),
499
			'{address_1_upper}'  => strtoupper( $address_1 ),
500
			'{address_2_upper}'  => strtoupper( $address_2 ),
501
			'{city_upper}'       => strtoupper( $city ),
502
			'{state_upper}'      => strtoupper( $full_state ),
503
			'{state_code}'       => strtoupper( $state ),
504
			'{postcode_upper}'   => strtoupper( $postcode ),
505
			'{country_upper}'    => strtoupper( $full_country ),
506
		), $args ) );
507
508
		$formatted_address = str_replace( array_keys( $replace ), $replace, $format );
509
510
		// Clean up white space
511
		$formatted_address = preg_replace( '/  +/', ' ', trim( $formatted_address ) );
512
		$formatted_address = preg_replace( '/\n\n+/', "\n", $formatted_address );
513
514
		// Break newlines apart and remove empty lines/trim commas and white space
515
		$formatted_address = array_filter( array_map( array( $this, 'trim_formatted_address_line' ), explode( "\n", $formatted_address ) ) );
516
517
		// Add html breaks
518
		$formatted_address = implode( '<br/>', $formatted_address );
519
520
		// We're done!
521
		return $formatted_address;
522
	}
523
524
	/**
525
	 * Trim white space and commas off a line.
526
	 * @param  string $line
527
	 * @return string
528
	 */
529
	private function trim_formatted_address_line( $line ) {
530
		return trim( $line, ", " );
531
	}
532
533
	/**
534
	 * Returns the fields we show by default. This can be filtered later on.
535
	 * @return array
536
	 */
537
	public function get_default_address_fields() {
538
		$fields = array(
539
			'first_name' => array(
540
				'label'        => __( 'First Name', 'woocommerce' ),
541
				'required'     => true,
542
				'class'        => array( 'form-row-first' ),
543
				'autocomplete' => 'given-name',
544
			),
545
			'last_name' => array(
546
				'label'        => __( 'Last Name', 'woocommerce' ),
547
				'required'     => true,
548
				'class'        => array( 'form-row-last' ),
549
				'clear'        => true,
550
				'autocomplete' => 'family-name',
551
			),
552
			'company' => array(
553
				'label'        => __( 'Company Name', 'woocommerce' ),
554
				'class'        => array( 'form-row-wide' ),
555
				'autocomplete' => 'organization',
556
			),
557
			'country' => array(
558
				'type'         => 'country',
559
				'label'        => __( 'Country', 'woocommerce' ),
560
				'required'     => true,
561
				'class'        => array( 'form-row-wide', 'address-field', 'update_totals_on_change' ),
562
				'autocomplete' => 'country',
563
			),
564
			'address_1' => array(
565
				'label'        => __( 'Address', 'woocommerce' ),
566
				'placeholder'  => _x( 'Street address', 'placeholder', 'woocommerce' ),
567
				'required'     => true,
568
				'class'        => array( 'form-row-wide', 'address-field' ),
569
				'autocomplete' => 'address-line1',
570
			),
571
			'address_2' => array(
572
				'placeholder'  => _x( 'Apartment, suite, unit etc. (optional)', 'placeholder', 'woocommerce' ),
573
				'class'        => array( 'form-row-wide', 'address-field' ),
574
				'required'     => false,
575
				'autocomplete' => 'address-line2',
576
			),
577
			'city' => array(
578
				'label'        => __( 'Town / City', 'woocommerce' ),
579
				'required'     => true,
580
				'class'        => array( 'form-row-wide', 'address-field' ),
581
				'autocomplete' => 'address-level2',
582
			),
583
			'state' => array(
584
				'type'         => 'state',
585
				'label'        => __( 'State / County', 'woocommerce' ),
586
				'required'     => true,
587
				'class'        => array( 'form-row-first', 'address-field' ),
588
				'validate'     => array( 'state' ),
589
				'autocomplete' => 'address-level1',
590
			),
591
			'postcode' => array(
592
				'label'        => __( 'Postcode / ZIP', 'woocommerce' ),
593
				'required'     => true,
594
				'class'        => array( 'form-row-last', 'address-field' ),
595
				'clear'        => true,
596
				'validate'     => array( 'postcode' ),
597
				'autocomplete' => 'postal-code',
598
			),
599
		);
600
601
		return apply_filters( 'woocommerce_default_address_fields', $fields );
602
	}
603
604
	/**
605
	 * Get JS selectors for fields which are shown/hidden depending on the locale.
606
	 * @return array
607
	 */
608
	public function get_country_locale_field_selectors() {
609
		$locale_fields = array (
610
			'address_1' => '#billing_address_1_field, #shipping_address_1_field',
611
			'address_2' => '#billing_address_2_field, #shipping_address_2_field',
612
			'state'     => '#billing_state_field, #shipping_state_field, #calc_shipping_state_field',
613
			'postcode'  => '#billing_postcode_field, #shipping_postcode_field, #calc_shipping_postcode_field',
614
			'city'      => '#billing_city_field, #shipping_city_field, #calc_shipping_city_field',
615
		);
616
		return apply_filters( 'woocommerce_country_locale_field_selectors', $locale_fields );
617
	}
618
619
	/**
620
	 * Get country locale settings.
621
	 * @return array
622
	 * @todo  [2.4] Check select2 4.0.0 compatibility with `placeholder` attribute and uncomment relevant lines. https://github.com/woothemes/woocommerce/issues/7729
623
	 */
624
	public function get_country_locale() {
625
		if ( ! $this->locale ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $this->locale of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
626
627
			// Locale information used by the checkout
628
			$this->locale = apply_filters( 'woocommerce_get_country_locale', array(
629
				'AE' => array(
630
					'postcode' => array(
631
						'required' => false,
632
						'hidden'   => true
633
					),
634
				),
635
				'AF' => array(
636
					'state' => array(
637
						'required' => false,
638
					),
639
				),
640
				'AT' => array(
641
					'postcode_before_city' => true,
642
					'state' => array(
643
						'required' => false
644
					)
645
				),
646
				'AU' => array(
647
					'city'      => array(
648
						'label'       => __( 'Suburb', 'woocommerce' ),
649
					),
650
					'postcode'  => array(
651
						'label'       => __( 'Postcode', 'woocommerce' ),
652
					),
653
					'state'     => array(
654
						'label'       => __( 'State', 'woocommerce' ),
655
					)
656
				),
657
				'AX' => array(
658
					'postcode_before_city' => true,
659
					'state' => array(
660
						'required' => false,
661
					),
662
				),
663
				'BD' => array(
664
					'postcode' => array(
665
						'required' => false
666
					),
667
					'state' => array(
668
						'label'       => __( 'District', 'woocommerce' ),
669
					)
670
				),
671
				'BE' => array(
672
					'postcode_before_city' => true,
673
					'state' => array(
674
						'required'    => false,
675
						'label'       => __( 'Province', 'woocommerce' ),
676
					),
677
				),
678
				'BI' => array(
679
					'state' => array(
680
						'required' => false,
681
					),
682
				),
683
				'BO' => array(
684
					'postcode' => array(
685
						'required' => false,
686
						'hidden'   => true
687
					),
688
				),
689
				'BS' => array(
690
					'postcode' => array(
691
						'required' => false,
692
						'hidden'   => true
693
					),
694
				),
695
				'CA' => array(
696
					'state' => array(
697
						'label'       => __( 'Province', 'woocommerce' ),
698
					)
699
				),
700
				'CH' => array(
701
					'postcode_before_city' => true,
702
					'state' => array(
703
						'label'       => __( 'Canton', 'woocommerce' ),
704
						'required'    => false
705
					)
706
				),
707
				'CL' => array(
708
					'city'      => array(
709
						'required' 	=> true,
710
					),
711
					'postcode'  => array(
712
						'required' => false
713
					),
714
					'state'     => array(
715
						'label'       => __( 'Region', 'woocommerce' ),
716
					)
717
				),
718
				'CN' => array(
719
					'state' => array(
720
						'label'       => __( 'Province', 'woocommerce' ),
721
					)
722
				),
723
				'CO' => array(
724
					'postcode' => array(
725
						'required' => false
726
					)
727
				),
728
				'CZ' => array(
729
					'state' => array(
730
						'required' => false
731
					)
732
				),
733
				'DE' => array(
734
					'postcode_before_city' => true,
735
					'state' => array(
736
						'required' => false
737
					)
738
				),
739
				'DK' => array(
740
					'postcode_before_city' => true,
741
					'state' => array(
742
						'required' => false
743
					)
744
				),
745
				'EE' => array(
746
					'postcode_before_city' => true,
747
					'state' => array(
748
						'required' => false
749
					)
750
				),
751
				'FI' => array(
752
					'postcode_before_city' => true,
753
					'state' => array(
754
						'required' => false
755
					)
756
				),
757
				'FR' => array(
758
					'postcode_before_city' => true,
759
					'state' => array(
760
						'required' => false
761
					)
762
				),
763
				'HK' => array(
764
					'postcode' => array(
765
						'required' => false
766
					),
767
					'city'  => array(
768
						'label'       => __( 'Town / District', 'woocommerce' ),
769
					),
770
					'state' => array(
771
						'label'       => __( 'Region', 'woocommerce' ),
772
					)
773
				),
774
				'HU' => array(
775
					'state' => array(
776
						'label'       => __( 'County', 'woocommerce' ),
777
					)
778
				),
779
				'ID' => array(
780
					'state' => array(
781
						'label'       => __( 'Province', 'woocommerce' ),
782
					)
783
				),
784
				'IE' => array(
785
					'postcode' => array(
786
						'required' => false,
787
						'label'    => __( 'Postcode', 'woocommerce' ),
788
					),
789
				),
790
				'IS' => array(
791
					'postcode_before_city' => true,
792
					'state' => array(
793
						'required' => false
794
					)
795
				),
796
				'IL' => array(
797
					'postcode_before_city' => true,
798
					'state' => array(
799
						'required' => false
800
					)
801
				),
802
				'IT' => array(
803
					'postcode_before_city' => true,
804
					'state' => array(
805
						'required'    => true,
806
						'label'       => __( 'Province', 'woocommerce' ),
807
					)
808
				),
809
				'JP' => array(
810
					'state' => array(
811
						'label' => __( 'Prefecture', 'woocommerce' )
812
					)
813
				),
814
				'KR' => array(
815
					'state' => array(
816
						'required' => false
817
					)
818
				),
819
				'NL' => array(
820
					'postcode_before_city' => true,
821
					'state' => array(
822
						'required'    => false,
823
						'label'       => __( 'Province', 'woocommerce' ),
824
					)
825
				),
826
				'NZ' => array(
827
					'postcode' => array(
828
						'label' => __( 'Postcode', 'woocommerce' )
829
					),
830
					'state' => array(
831
						'required' => false,
832
						'label'    => __( 'Region', 'woocommerce' )
833
					)
834
				),
835
				'NO' => array(
836
					'postcode_before_city' => true,
837
					'state' => array(
838
						'required' => false
839
					)
840
				),
841
				'NP' => array(
842
					'state' => array(
843
						'label'       => __( 'State / Zone', 'woocommerce' ),
844
					),
845
					'postcode' => array(
846
						'required' => false
847
					)
848
				),
849
				'PL' => array(
850
					'postcode_before_city' => true,
851
					'state' => array(
852
						'required' => false
853
					)
854
				),
855
				'PT' => array(
856
					'state' => array(
857
						'required' => false
858
					)
859
				),
860
				'RO' => array(
861
					'state' => array(
862
						'required' => false
863
					)
864
				),
865
				'SG' => array(
866
					'state' => array(
867
						'required' => false
868
					)
869
				),
870
				'SK' => array(
871
					'postcode_before_city' => true,
872
					'state' => array(
873
						'required' => false
874
					)
875
				),
876
				'SI' => array(
877
					'postcode_before_city' => true,
878
					'state' => array(
879
						'required' => false
880
					)
881
				),
882
				'ES' => array(
883
					'postcode_before_city' => true,
884
					'state' => array(
885
						'label'       => __( 'Province', 'woocommerce' ),
886
					)
887
				),
888
				'LI' => array(
889
					'postcode_before_city' => true,
890
					'state' => array(
891
						'label'       => __( 'Municipality', 'woocommerce' ),
892
						'required'    => false
893
					)
894
				),
895
				'LK' => array(
896
					'state' => array(
897
						'required' => false
898
					)
899
				),
900
				'SE' => array(
901
					'postcode_before_city' => true,
902
					'state' => array(
903
						'required' => false
904
					)
905
				),
906
				'TR' => array(
907
					'postcode_before_city' => true,
908
					'state' => array(
909
						'label'       => __( 'Province', 'woocommerce' ),
910
					)
911
				),
912
				'US' => array(
913
					'postcode'  => array(
914
						'label'       => __( 'ZIP', 'woocommerce' ),
915
					),
916
					'state'     => array(
917
						'label'       => __( 'State', 'woocommerce' ),
918
					)
919
				),
920
				'GB' => array(
921
					'postcode'  => array(
922
						'label'       => __( 'Postcode', 'woocommerce' ),
923
					),
924
					'state'     => array(
925
						'label'       => __( 'County', 'woocommerce' ),
926
						'required'    => false
927
					)
928
				),
929
				'VN' => array(
930
					'postcode_before_city' => true,
931
					'state' => array(
932
						'required' => false
933
					),
934
					'postcode' => array(
935
						'required' => false,
936
						'hidden'   => false
937
					),
938
					'address_2' => array(
939
						'required' => false,
940
						'hidden'   => true
941
					)
942
				),
943
				'WS' => array(
944
					'postcode' => array(
945
						'required' => false,
946
						'hidden'   => true
947
					),
948
				),
949
				'ZA' => array(
950
					'state' => array(
951
						'label'       => __( 'Province', 'woocommerce' ),
952
					)
953
				),
954
				'ZW' => array(
955
					'postcode' => array(
956
						'required' => false,
957
						'hidden'   => true
958
					),
959
				),
960
			));
961
962
			$this->locale = array_intersect_key( $this->locale, array_merge( $this->get_allowed_countries(), $this->get_shipping_countries() ) );
963
964
			// Default Locale Can be filtered to override fields in get_address_fields().
965
			// Countries with no specific locale will use default.
966
			$this->locale['default'] = apply_filters('woocommerce_get_country_locale_default', $this->get_default_address_fields() );
967
968
			// Filter default AND shop base locales to allow overides via a single function. These will be used when changing countries on the checkout
969
			if ( ! isset( $this->locale[ $this->get_base_country() ] ) ) {
970
				$this->locale[ $this->get_base_country() ] = $this->locale['default'];
971
			}
972
973
			$this->locale['default']                   = apply_filters( 'woocommerce_get_country_locale_base', $this->locale['default'] );
974
			$this->locale[ $this->get_base_country() ] = apply_filters( 'woocommerce_get_country_locale_base', $this->locale[ $this->get_base_country() ] );
975
		}
976
977
		return $this->locale;
978
	}
979
980
	/**
981
	 * Apply locale and get address fields.
982
	 * @param  mixed  $country (default: '')
983
	 * @param  string $type (default: 'billing_')
984
	 * @return array
985
	 */
986
	public function get_address_fields( $country = '', $type = 'billing_' ) {
987
		if ( ! $country ) {
988
			$country = $this->get_base_country();
989
		}
990
991
		$fields = $this->get_default_address_fields();
992
		$locale = $this->get_country_locale();
993
994
		if ( isset( $locale[ $country ] ) ) {
995
			$fields = wc_array_overlay( $fields, $locale[ $country ] );
996
		}
997
998
		// Prepend field keys
999
		$address_fields = array();
1000
1001
		foreach ( $fields as $key => $value ) {
1002
			$keys = array_keys( $fields );
1003
			$address_fields[ $type . $key ] = $value;
1004
1005
			// Add email and phone after company or last
1006
			if ( 'billing_' === $type && ( 'company' === $key || ( ! array_key_exists( 'company', $fields ) && $key === end( $keys ) ) ) ) {
1007
				$address_fields['billing_email'] = array(
1008
					'label'        => __( 'Email Address', 'woocommerce' ),
1009
					'required'     => true,
1010
					'type'         => 'email',
1011
					'class'        => array( 'form-row-first' ),
1012
					'validate'     => array( 'email' ),
1013
					'autocomplete' => 'email',
1014
				);
1015
				$address_fields['billing_phone'] = array(
1016
					'label'        => __( 'Phone', 'woocommerce' ),
1017
					'required'     => true,
1018
					'type'         => 'tel',
1019
					'class'        => array( 'form-row-last' ),
1020
					'clear'        => true,
1021
					'validate'     => array( 'phone' ),
1022
					'autocomplete' => 'tel',
1023
				);
1024
			}
1025
		}
1026
1027
		$address_fields = apply_filters( 'woocommerce_' . $type . 'fields', $address_fields, $country );
1028
1029
		return $address_fields;
1030
	}
1031
}
1032