woocommerce/includes/class-wc-countries.php

1177 lines
33 KiB
PHP
Raw Normal View History

2011-08-09 15:16:18 +00:00
<?php
2015-11-06 09:22:19 +00:00
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
2011-08-09 15:16:18 +00:00
/**
2015-11-03 13:53:50 +00:00
* WooCommerce countries
2012-08-06 22:43:39 +00:00
*
2011-08-10 17:11:11 +00:00
* The WooCommerce countries class stores country/state data.
2011-08-09 15:16:18 +00:00
*
2015-01-18 18:59:17 +00:00
* @class WC_Countries
* @version 2.3.0
* @package WooCommerce/Classes
* @category Class
* @author WooThemes
2011-08-09 15:16:18 +00:00
*/
2012-01-27 16:38:39 +00:00
class WC_Countries {
2012-08-06 22:43:39 +00:00
2012-08-15 17:08:42 +00:00
/** @var array Array of locales */
public $locale;
2012-08-14 19:42:38 +00:00
2012-08-15 17:08:42 +00:00
/** @var array Array of address formats for locales */
public $address_formats;
2012-08-06 22:43:39 +00:00
/**
* Auto-load in-accessible properties on demand.
2015-01-18 18:59:17 +00:00
* @param mixed $key
* @return mixed
*/
public function __get( $key ) {
if ( 'countries' == $key ) {
return $this->get_countries();
} elseif ( 'states' == $key ) {
return $this->get_states();
}
}
/**
2015-01-18 18:59:17 +00:00
* Get all countries.
* @return array
*/
public function get_countries() {
if ( empty( $this->countries ) ) {
$this->countries = apply_filters( 'woocommerce_countries', include( WC()->plugin_path() . '/i18n/countries.php' ) );
2015-01-18 18:59:17 +00:00
if ( apply_filters( 'woocommerce_sort_countries', true ) ) {
asort( $this->countries );
}
}
return $this->countries;
}
2012-08-06 22:43:39 +00:00
2015-12-08 11:15:02 +00:00
/**
* Get all continents.
* @return array
*/
public function get_continents() {
if ( empty( $this->continents ) ) {
$this->continents = apply_filters( 'woocommerce_continents', include( WC()->plugin_path() . '/i18n/continents.php' ) );
}
return $this->continents;
}
2015-12-15 12:39:52 +00:00
/**
* Get continent code for a country code.
* @since 2.6.0
* @param string $cc string
2015-12-15 12:39:52 +00:00
* @return string
*/
public function get_continent_code_for_country( $cc ) {
2015-12-15 15:00:45 +00:00
$cc = trim( strtoupper( $cc ) );
2015-12-15 12:39:52 +00:00
$continents = $this->get_continents();
$continents_and_ccs = wp_list_pluck( $continents, 'countries' );
2015-12-15 15:00:45 +00:00
foreach ( $continents_and_ccs as $continent_code => $countries ) {
if ( false !== array_search( $cc, $countries ) ) {
return $continent_code;
}
}
return '';
2015-12-15 12:39:52 +00:00
}
/**
2015-01-18 18:59:17 +00:00
* Load the states.
*/
public function load_country_states() {
global $states;
2012-08-06 22:43:39 +00:00
// States set to array() are blank i.e. the country has no use for the state field.
$states = array(
2012-07-26 16:29:49 +00:00
'AF' => array(),
'AT' => array(),
2015-07-17 19:29:21 +00:00
'AX' => array(),
2012-02-28 10:12:13 +00:00
'BE' => array(),
2012-07-26 16:29:49 +00:00
'BI' => array(),
'CZ' => array(),
'DE' => array(),
'DK' => array(),
2013-09-10 12:41:40 +00:00
'EE' => array(),
'FI' => array(),
'FR' => array(),
'GP' => array(),
'GF' => array(),
'IS' => array(),
'IL' => array(),
2013-01-20 12:50:39 +00:00
'KR' => array(),
'KW' => array(),
'LB' => array(),
'MQ' => array(),
'NL' => array(),
'NO' => array(),
'PL' => array(),
'PT' => array(),
'RE' => array(),
'SG' => array(),
'SK' => array(),
'SI' => array(),
'LK' => array(),
'SE' => array(),
'VN' => array(),
'YT' => array(),
);
2015-01-18 18:59:17 +00:00
// Load only the state files the shop owner wants/needs.
$allowed = array_merge( $this->get_allowed_countries(), $this->get_shipping_countries() );
2016-06-06 18:39:23 +00:00
if ( ! empty( $allowed ) ) {
foreach ( $allowed as $code => $country ) {
if ( ! isset( $states[ $code ] ) && file_exists( WC()->plugin_path() . '/i18n/states/' . $code . '.php' ) ) {
include( WC()->plugin_path() . '/i18n/states/' . $code . '.php' );
}
}
}
$this->states = apply_filters( 'woocommerce_states', $states );
}
/**
* Get the states for a country.
2015-01-18 18:59:17 +00:00
* @param string $cc country code
* @return false|array of states
*/
2014-05-30 12:33:09 +00:00
public function get_states( $cc = null ) {
if ( empty( $this->states ) ) {
$this->load_country_states();
}
2015-01-18 18:59:17 +00:00
2014-05-30 12:33:09 +00:00
if ( ! is_null( $cc ) ) {
return isset( $this->states[ $cc ] ) ? $this->states[ $cc ] : false;
} else {
return $this->states;
}
}
/**
* Get the base address (first line) for the store.
* @since 3.1.1
* @return string
*/
public function get_base_address() {
$base_address = get_option( 'woocommerce_store_address', '' );
return apply_filters( 'woocommerce_countries_base_address', $base_address );
}
/**
* Get the base address (second line) for the store.
* @since 3.1.1
* @return string
*/
public function get_base_address_2() {
$base_address_2 = get_option( 'woocommerce_store_address_2', '' );
return apply_filters( 'woocommerce_countries_base_address_2', $base_address_2 );
}
2012-08-14 19:42:38 +00:00
/**
* Get the base country for the store.
* @return string
*/
public function get_base_country() {
2014-12-23 17:34:05 +00:00
$default = wc_get_base_location();
return apply_filters( 'woocommerce_countries_base_country', $default['country'] );
}
2012-08-14 19:42:38 +00:00
/**
* Get the base state for the store.
2012-08-14 19:42:38 +00:00
* @return string
*/
public function get_base_state() {
2014-12-23 17:34:05 +00:00
$default = wc_get_base_location();
return apply_filters( 'woocommerce_countries_base_state', $default['state'] );
}
/**
* Get the base city for the store.
* @version 3.1.1
* @return string
*/
public function get_base_city() {
$base_city = get_option( 'woocommerce_store_city', '' );
return apply_filters( 'woocommerce_countries_base_city', $base_city );
}
/**
* Get the base postcode for the store.
* @since 3.1.1
* @return string
*/
public function get_base_postcode() {
$base_postcode = get_option( 'woocommerce_store_postcode', '' );
return apply_filters( 'woocommerce_countries_base_postcode', $base_postcode );
2011-08-09 15:16:18 +00:00
}
2012-08-14 19:42:38 +00:00
/**
* Get the allowed countries for the store.
* @return array
*/
public function get_allowed_countries() {
2016-04-28 16:37:30 +00:00
if ( 'all' === get_option( 'woocommerce_allowed_countries' ) ) {
return $this->countries;
}
if ( 'all_except' === get_option( 'woocommerce_allowed_countries' ) ) {
$except_countries = get_option( 'woocommerce_all_except_countries', array() );
if ( ! $except_countries ) {
return $this->countries;
} else {
$all_except_countries = $this->countries;
foreach ( $except_countries as $country ) {
unset( $all_except_countries[ $country ] );
}
return apply_filters( 'woocommerce_countries_allowed_countries', $all_except_countries );
}
}
2011-08-09 15:16:18 +00:00
$countries = array();
2012-08-06 22:43:39 +00:00
$raw_countries = get_option( 'woocommerce_specific_allowed_countries', array() );
2012-08-06 22:43:39 +00:00
if ( $raw_countries ) {
foreach ( $raw_countries as $country ) {
$countries[ $country ] = $this->countries[ $country ];
}
2015-01-18 18:59:17 +00:00
}
2012-08-06 22:43:39 +00:00
return apply_filters( 'woocommerce_countries_allowed_countries', $countries );
2011-08-09 15:16:18 +00:00
}
2012-11-27 16:22:47 +00:00
/**
* Get the countries you ship to.
* @return array
*/
public function get_shipping_countries() {
if ( '' === get_option( 'woocommerce_ship_to_countries' ) ) {
2016-04-28 16:37:30 +00:00
return $this->get_allowed_countries();
2015-01-18 18:59:17 +00:00
}
2016-04-28 16:37:30 +00:00
if ( 'all' === get_option( 'woocommerce_ship_to_countries' ) ) {
return $this->countries;
2015-01-18 18:59:17 +00:00
}
$countries = array();
$raw_countries = get_option( 'woocommerce_specific_ship_to_countries' );
if ( $raw_countries ) {
foreach ( $raw_countries as $country ) {
$countries[ $country ] = $this->countries[ $country ];
}
2015-01-18 18:59:17 +00:00
}
return apply_filters( 'woocommerce_countries_shipping_countries', $countries );
}
2012-11-27 16:22:47 +00:00
/**
* Get allowed country states.
* @return array
*/
public function get_allowed_country_states() {
2015-01-18 18:59:17 +00:00
if ( get_option( 'woocommerce_allowed_countries' ) !== 'specific' ) {
return $this->states;
2015-01-18 18:59:17 +00:00
}
$states = array();
$raw_countries = get_option( 'woocommerce_specific_allowed_countries' );
if ( $raw_countries ) {
foreach ( $raw_countries as $country ) {
if ( isset( $this->states[ $country ] ) ) {
$states[ $country ] = $this->states[ $country ];
}
2015-01-18 18:59:17 +00:00
}
}
return apply_filters( 'woocommerce_countries_allowed_country_states', $states );
}
2012-08-06 22:43:39 +00:00
/**
* Get shipping country states.
* @return array
*/
public function get_shipping_country_states() {
2015-01-18 18:59:17 +00:00
if ( get_option( 'woocommerce_ship_to_countries' ) == '' ) {
return $this->get_allowed_country_states();
2015-01-18 18:59:17 +00:00
}
2015-01-18 18:59:17 +00:00
if ( get_option( 'woocommerce_ship_to_countries' ) !== 'specific' ) {
return $this->states;
2015-01-18 18:59:17 +00:00
}
$states = array();
$raw_countries = get_option( 'woocommerce_specific_ship_to_countries' );
if ( $raw_countries ) {
foreach ( $raw_countries as $country ) {
if ( ! empty( $this->states[ $country ] ) ) {
$states[ $country ] = $this->states[ $country ];
}
2015-01-18 18:59:17 +00:00
}
}
return apply_filters( 'woocommerce_countries_shipping_country_states', $states );
}
2012-08-14 19:42:38 +00:00
/**
* Gets an array of countries in the EU.
*
* MC (monaco) and IM (isle of man, part of UK) also use VAT.
*
* @param string $type Type of countries to retrieve. Blank for EU member countries. eu_vat for EU VAT countries.
2014-09-07 23:37:55 +00:00
* @return string[]
2012-08-14 19:42:38 +00:00
*/
public function get_european_union_countries( $type = '' ) {
$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' );
if ( 'eu_vat' === $type ) {
$countries[] = 'MC';
$countries[] = 'IM';
}
return $countries;
2011-10-31 10:54:49 +00:00
}
2012-08-06 22:43:39 +00:00
2012-08-14 19:42:38 +00:00
/**
* Gets the correct string for shipping - either 'to the' or 'to'
*
* @param string $country_code
*
2012-08-14 19:42:38 +00:00
* @return string
*/
public function shipping_to_prefix( $country_code = '' ) {
$country_code = $country_code ? $country_code : WC()->customer->get_shipping_country();
$countries = array( 'GB', 'US', 'AE', 'CZ', 'DO', 'NL', 'PH', 'USAF' );
$return = in_array( $country_code, $countries ) ? __( 'to the', 'woocommerce' ) : __( 'to', 'woocommerce' );
2014-11-20 00:43:09 +00:00
return apply_filters( 'woocommerce_countries_shipping_to_prefix', $return, $country_code );
2011-08-09 15:16:18 +00:00
}
2012-08-06 22:43:39 +00:00
2012-08-14 19:42:38 +00:00
/**
* Prefix certain countries with 'the'
*
* @param string $country_code
*
2012-08-14 19:42:38 +00:00
* @return string
*/
public function estimated_for_prefix( $country_code = '' ) {
$country_code = $country_code ? $country_code : $this->get_base_country();
$countries = array( 'GB', 'US', 'AE', 'CZ', 'DO', 'NL', 'PH', 'USAF' );
$return = in_array( $country_code, $countries ) ? __( 'the', 'woocommerce' ) . ' ' : '';
2012-08-06 22:43:39 +00:00
return apply_filters( 'woocommerce_countries_estimated_for_prefix', $return, $country_code );
2015-01-18 18:59:17 +00:00
}
2012-08-14 19:42:38 +00:00
/**
2015-01-18 18:59:17 +00:00
* Correctly name tax in some countries VAT on the frontend.
2012-08-14 19:42:38 +00:00
* @return string
*/
public function tax_or_vat() {
2017-05-10 16:48:03 +00:00
$return = in_array( $this->get_base_country(), array_merge( $this->get_european_union_countries( 'eu_vat' ), array( 'NO' ) ) ) ? __( 'VAT', 'woocommerce' ) : __( 'Tax', 'woocommerce' );
2012-08-06 22:43:39 +00:00
2012-08-14 19:42:38 +00:00
return apply_filters( 'woocommerce_countries_tax_or_vat', $return );
2011-10-31 10:54:49 +00:00
}
2012-08-06 22:43:39 +00:00
2012-08-14 19:42:38 +00:00
/**
* Include the Inc Tax label.
* @return string
*/
public function inc_tax_or_vat() {
2017-05-10 16:48:03 +00:00
$return = in_array( $this->get_base_country(), array_merge( $this->get_european_union_countries( 'eu_vat' ), array( 'NO' ) ) ) ? __( '(incl. VAT)', 'woocommerce' ) : __( '(incl. tax)', 'woocommerce' );
2012-08-06 22:43:39 +00:00
2012-08-14 19:42:38 +00:00
return apply_filters( 'woocommerce_countries_inc_tax_or_vat', $return );
2011-10-31 10:54:49 +00:00
}
2012-08-06 22:43:39 +00:00
2012-08-14 19:42:38 +00:00
/**
* Include the Ex Tax label.
* @return string
*/
public function ex_tax_or_vat() {
2017-05-10 16:48:03 +00:00
$return = in_array( $this->get_base_country(), array_merge( $this->get_european_union_countries( 'eu_vat' ), array( 'NO' ) ) ) ? __( '(ex. VAT)', 'woocommerce' ) : __( '(ex. tax)', 'woocommerce' );
2012-08-06 22:43:39 +00:00
2012-08-14 19:42:38 +00:00
return apply_filters( 'woocommerce_countries_ex_tax_or_vat', $return );
2011-08-09 15:16:18 +00:00
}
2012-08-06 22:43:39 +00:00
2012-08-14 19:42:38 +00:00
/**
* Outputs the list of countries and states for use in dropdown boxes.
2015-07-16 19:55:48 +00:00
* @param string $selected_country (default: '')
* @param string $selected_state (default: '')
* @param bool $escape (default: false)
2015-07-16 19:55:48 +00:00
* @param bool $escape (default: false)
2012-08-14 19:42:38 +00:00
*/
public function country_dropdown_options( $selected_country = '', $selected_state = '', $escape = false ) {
if ( $this->countries ) :
foreach ( $this->countries as $key => $value ) :
if ( $states = $this->get_states( $key ) ) :
echo '<optgroup label="' . esc_attr( $value ) . '">';
foreach ( $states as $state_key => $state_value ) :
echo '<option value="' . esc_attr( $key ) . ':' . $state_key . '"';
2017-08-08 16:32:21 +00:00
if ( $selected_country === $key && $selected_state === $state_key ) {
echo ' selected="selected"';
2017-08-08 16:32:21 +00:00
}
echo '>' . $value . ' &mdash; ' . ( $escape ? esc_js( $state_value ) : $state_value ) . '</option>';
endforeach;
echo '</optgroup>';
else :
echo '<option';
2017-08-08 16:32:21 +00:00
if ( $selected_country === $key && '*' === $selected_state ) {
echo ' selected="selected"';
}
echo ' value="' . esc_attr( $key ) . '">' . ( $escape ? esc_js( $value ) : $value ) . '</option>';
endif;
endforeach;
endif;
2011-08-09 15:16:18 +00:00
}
2012-08-06 22:43:39 +00:00
2012-08-14 19:42:38 +00:00
/**
2015-11-03 13:31:20 +00:00
* Get country address formats.
*
* These define how addresses are formatted for display in various countries.
*
2012-08-14 19:42:38 +00:00
* @return array
*/
public function get_address_formats() {
2016-06-06 18:39:23 +00:00
if ( empty( $this->address_formats ) ) {
2015-01-18 18:59:17 +00:00
$this->address_formats = apply_filters( 'woocommerce_localisation_address_formats', array(
'default' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}\n{postcode}\n{country}",
'AU' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
'AT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'BE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'CA' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
'CH' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'CL' => "{company}\n{name}\n{address_1}\n{address_2}\n{state}\n{postcode} {city}\n{country}",
'CN' => "{country} {postcode}\n{state}, {city}, {address_2}, {address_1}\n{company}\n{name}",
'CZ' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'DE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'EE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'FI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'DK' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'FR' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city_upper}\n{country}",
'HK' => "{company}\n{first_name} {last_name_upper}\n{address_1}\n{address_2}\n{city_upper}\n{state_upper}\n{country}",
'HU' => "{name}\n{company}\n{city}\n{address_1}\n{address_2}\n{postcode}\n{country}",
'IN' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} - {postcode}\n{state}, {country}",
'IS' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
2014-02-13 12:12:47 +00:00
'IT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode}\n{city}\n{state_upper}\n{country}",
'JP' => "{postcode}\n{state}{city}{address_1}\n{address_2}\n{company}\n{last_name} {first_name}\n{country}",
'TW' => "{company}\n{last_name} {first_name}\n{address_1}\n{address_2}\n{state}, {city} {postcode}\n{country}",
'LI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'NL' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'NZ' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {postcode}\n{country}",
'NO' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'PL' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'PT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'SK' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'SI' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'ES' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city}\n{state}\n{country}",
'SE' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}",
'TR' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city} {state}\n{country}",
'US' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}, {state_code} {postcode}\n{country}",
'VN' => "{name}\n{company}\n{address_1}\n{city}\n{country}",
) );
2016-06-06 18:39:23 +00:00
}
return $this->address_formats;
}
2012-08-06 22:43:39 +00:00
2012-08-14 19:42:38 +00:00
/**
2015-01-18 18:59:17 +00:00
* Get country address format.
* @param array $args (default: array())
2012-08-14 19:42:38 +00:00
* @return string address
*/
public function get_formatted_address( $args = array() ) {
$default_args = array(
'first_name' => '',
2015-03-05 09:20:24 +00:00
'last_name' => '',
'company' => '',
'address_1' => '',
'address_2' => '',
'city' => '',
'state' => '',
'postcode' => '',
'country' => '',
);
2015-03-05 09:20:24 +00:00
$args = array_map( 'trim', wp_parse_args( $args, $default_args ) );
extract( $args );
2012-08-06 22:43:39 +00:00
// Get all formats
$formats = $this->get_address_formats();
2012-08-06 22:43:39 +00:00
// Get format for the address' country
$format = ( $country && isset( $formats[ $country ] ) ) ? $formats[ $country ] : $formats['default'];
2012-08-06 22:43:39 +00:00
// Handle full country name
$full_country = ( isset( $this->countries[ $country ] ) ) ? $this->countries[ $country ] : $country;
2012-08-06 22:43:39 +00:00
// Country is not needed if the same as base
2015-03-05 09:20:24 +00:00
if ( $country == $this->get_base_country() && ! apply_filters( 'woocommerce_formatted_address_force_country_display', false ) ) {
2012-10-16 15:22:07 +00:00
$format = str_replace( '{country}', '', $format );
2015-03-05 09:20:24 +00:00
}
2012-08-06 22:43:39 +00:00
2011-12-18 13:41:42 +00:00
// Handle full state name
2015-03-05 09:20:24 +00:00
$full_state = ( $country && $state && isset( $this->states[ $country ][ $state ] ) ) ? $this->states[ $country ][ $state ] : $state;
2012-08-06 22:43:39 +00:00
// Substitute address parts into the string
$replace = array_map( 'esc_html', apply_filters( 'woocommerce_formatted_address_replacements', array(
'{first_name}' => $first_name,
'{last_name}' => $last_name,
'{name}' => $first_name . ' ' . $last_name,
'{company}' => $company,
'{address_1}' => $address_1,
'{address_2}' => $address_2,
'{city}' => $city,
'{state}' => $full_state,
'{postcode}' => $postcode,
'{country}' => $full_country,
2012-10-16 15:22:07 +00:00
'{first_name_upper}' => strtoupper( $first_name ),
'{last_name_upper}' => strtoupper( $last_name ),
'{name_upper}' => strtoupper( $first_name . ' ' . $last_name ),
'{company_upper}' => strtoupper( $company ),
'{address_1_upper}' => strtoupper( $address_1 ),
'{address_2_upper}' => strtoupper( $address_2 ),
'{city_upper}' => strtoupper( $city ),
'{state_upper}' => strtoupper( $full_state ),
'{state_code}' => strtoupper( $state ),
2012-10-16 15:22:07 +00:00
'{postcode_upper}' => strtoupper( $postcode ),
'{country_upper}' => strtoupper( $full_country ),
), $args ) );
2012-10-16 15:22:07 +00:00
$formatted_address = str_replace( array_keys( $replace ), $replace, $format );
2012-08-06 22:43:39 +00:00
2012-01-15 06:31:47 +00:00
// Clean up white space
2012-10-16 15:22:07 +00:00
$formatted_address = preg_replace( '/ +/', ' ', trim( $formatted_address ) );
$formatted_address = preg_replace( '/\n\n+/', "\n", $formatted_address );
2012-08-06 22:43:39 +00:00
// Break newlines apart and remove empty lines/trim commas and white space
$formatted_address = array_filter( array_map( array( $this, 'trim_formatted_address_line' ), explode( "\n", $formatted_address ) ) );
// Add html breaks
$formatted_address = implode( '<br/>', $formatted_address );
2012-08-06 22:43:39 +00:00
// We're done!
return $formatted_address;
}
2012-08-06 22:43:39 +00:00
/**
2015-01-18 18:59:17 +00:00
* Trim white space and commas off a line.
* @param string $line
* @return string
*/
private function trim_formatted_address_line( $line ) {
return trim( $line, ", " );
}
/**
* Returns the fields we show by default. This can be filtered later on.
* @return array
*/
public function get_default_address_fields() {
$fields = array(
2015-01-18 18:59:17 +00:00
'first_name' => array(
'label' => __( 'First name', 'woocommerce' ),
'required' => true,
'class' => array( 'form-row-first' ),
'autocomplete' => 'given-name',
2016-09-12 19:33:52 +00:00
'autofocus' => true,
2016-12-13 18:48:39 +00:00
'priority' => 10,
),
2015-01-18 18:59:17 +00:00
'last_name' => array(
'label' => __( 'Last name', 'woocommerce' ),
'required' => true,
'class' => array( 'form-row-last' ),
'autocomplete' => 'family-name',
2016-12-13 18:48:39 +00:00
'priority' => 20,
),
2015-01-18 18:59:17 +00:00
'company' => array(
'label' => __( 'Company name', 'woocommerce' ),
'class' => array( 'form-row-wide' ),
'autocomplete' => 'organization',
2016-12-13 18:48:39 +00:00
'priority' => 30,
),
'country' => array(
'type' => 'country',
'label' => __( 'Country', 'woocommerce' ),
'required' => true,
'class' => array( 'form-row-wide', 'address-field', 'update_totals_on_change' ),
'autocomplete' => 'country',
2016-12-13 18:48:39 +00:00
'priority' => 40,
),
2015-01-18 18:59:17 +00:00
'address_1' => array(
Change field label and placeholder to minimize user error, add translators notice Status Quo: Working with several high-volume WooCommerce shops (in the range of several thousand orders per day combined), we've seen that the current placeholder text (and its translations in particular) lead to quite a few users filling in their address data incorrectly. You'd be surprised by the number of people who fail to properly write down their own address (house number missing, house number in wrong place). Problem: This leads to incomplete shipping labels, unsuccessful deliveries, and costly returns (especially for international shipping: 10-40 Euros lost per parcel). Solution: While some of these may stem from misdirected or incomplete browser auto-fills, we've seen (by customizing the language files for German, French, Spanish and Italian) that a more descriptive placeholder text helps reduce user errors on address entry. The goal is basically to make this as fool-proof as possible. Why this matters: At 1000 orders shipped per day, getting the error rate from 5% down to 4% means 10 less parcels coming back every day, which can save hundreds of Euros per day. Choice of wording: - "Address" is not just one field, but rather the sum of all address fields that will end up on a shipping label. - "Street Address" is what the user needs to input here, hence the new label for the two address fields - "House number and street name" is the most descriptive placeholder text I can come up with for this field (assuming the U.S. as default), hence the new placeholder text. - Translator notice added since many countries will have the house number after the street name. References: - https://en.wikipedia.org/wiki/Address_(geography)
2017-04-20 01:46:14 +00:00
'label' => __( 'Street address', 'woocommerce' ),
/* translators: use local order of street name and house number. */
'placeholder' => esc_attr__( 'House number and street name', 'woocommerce' ),
'required' => true,
'class' => array( 'form-row-wide', 'address-field' ),
'autocomplete' => 'address-line1',
2016-12-13 18:48:39 +00:00
'priority' => 50,
),
2015-01-18 18:59:17 +00:00
'address_2' => array(
'placeholder' => esc_attr__( 'Apartment, suite, unit etc. (optional)', 'woocommerce' ),
'class' => array( 'form-row-wide', 'address-field' ),
'required' => false,
'autocomplete' => 'address-line2',
2016-12-13 18:48:39 +00:00
'priority' => 60,
),
2015-01-18 18:59:17 +00:00
'city' => array(
'label' => __( 'Town / City', 'woocommerce' ),
'required' => true,
'class' => array( 'form-row-wide', 'address-field' ),
'autocomplete' => 'address-level2',
2016-12-13 18:48:39 +00:00
'priority' => 70,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'type' => 'state',
'label' => __( 'State / County', 'woocommerce' ),
'required' => true,
'class' => array( 'form-row-wide', 'address-field' ),
'validate' => array( 'state' ),
'autocomplete' => 'address-level1',
2016-12-13 18:48:39 +00:00
'priority' => 80,
),
2015-01-18 18:59:17 +00:00
'postcode' => array(
'label' => __( 'Postcode / ZIP', 'woocommerce' ),
'required' => true,
'class' => array( 'form-row-wide', 'address-field' ),
'validate' => array( 'postcode' ),
'autocomplete' => 'postal-code',
2016-12-13 18:48:39 +00:00
'priority' => 90,
),
);
return apply_filters( 'woocommerce_default_address_fields', $fields );
}
/**
2013-12-03 12:14:12 +00:00
* Get JS selectors for fields which are shown/hidden depending on the locale.
* @return array
*/
2013-12-03 12:14:12 +00:00
public function get_country_locale_field_selectors() {
$locale_fields = array(
2015-01-18 18:59:17 +00:00
'address_1' => '#billing_address_1_field, #shipping_address_1_field',
'address_2' => '#billing_address_2_field, #shipping_address_2_field',
'state' => '#billing_state_field, #shipping_state_field, #calc_shipping_state_field',
'postcode' => '#billing_postcode_field, #shipping_postcode_field, #calc_shipping_postcode_field',
'city' => '#billing_city_field, #shipping_city_field, #calc_shipping_city_field',
);
2013-12-03 12:14:12 +00:00
return apply_filters( 'woocommerce_country_locale_field_selectors', $locale_fields );
}
2012-08-14 19:42:38 +00:00
/**
2015-01-18 18:59:17 +00:00
* Get country locale settings.
*
* These locales override the default country selections after a country is chosen.
*
2012-08-14 19:42:38 +00:00
* @return array
*/
public function get_country_locale() {
2016-06-06 18:39:23 +00:00
if ( empty( $this->locale ) ) {
2015-01-18 18:59:17 +00:00
$this->locale = apply_filters( 'woocommerce_get_country_locale', array(
2013-07-19 14:08:40 +00:00
'AE' => array(
'postcode' => array(
2015-01-18 18:59:17 +00:00
'required' => false,
'hidden' => true,
2013-07-19 14:08:40 +00:00
),
'state' => array(
'required' => false,
),
),
2012-07-26 16:29:49 +00:00
'AF' => array(
'state' => array(
'required' => false,
),
),
'AT' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'AU' => array(
2015-01-18 18:59:17 +00:00
'city' => array(
'label' => __( 'Suburb', 'woocommerce' ),
),
2015-01-18 18:59:17 +00:00
'postcode' => array(
'label' => __( 'Postcode', 'woocommerce' ),
),
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'State', 'woocommerce' ),
),
),
2015-07-17 19:29:21 +00:00
'AX' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-07-17 19:29:21 +00:00
'state' => array(
'required' => false,
),
),
'BD' => array(
'postcode' => array(
'required' => false,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'District', 'woocommerce' ),
),
),
2012-02-28 10:12:13 +00:00
'BE' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2012-02-28 10:12:13 +00:00
'state' => array(
'required' => false,
'label' => __( 'Province', 'woocommerce' ),
2012-02-28 10:12:13 +00:00
),
),
2012-07-26 16:29:49 +00:00
'BI' => array(
'state' => array(
'required' => false,
),
),
2013-11-26 21:41:54 +00:00
'BO' => array(
'postcode' => array(
2015-01-18 18:59:17 +00:00
'required' => false,
'hidden' => true,
2013-11-26 21:41:54 +00:00
),
),
'BS' => array(
'postcode' => array(
2015-01-18 18:59:17 +00:00
'required' => false,
'hidden' => true,
),
),
'CA' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'Province', 'woocommerce' ),
),
),
2012-07-10 12:36:13 +00:00
'CH' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'Canton', 'woocommerce' ),
'required' => false,
),
2015-01-18 18:59:17 +00:00
),
'CL' => array(
2015-01-18 18:59:17 +00:00
'city' => array(
'required' => true,
),
2015-01-18 18:59:17 +00:00
'postcode' => array(
'required' => false,
2015-01-18 18:59:17 +00:00
),
'state' => array(
'label' => __( 'Region', 'woocommerce' ),
),
),
'CN' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'Province', 'woocommerce' ),
),
),
2012-07-09 14:46:51 +00:00
'CO' => array(
'postcode' => array(
'required' => false,
),
2012-07-09 14:46:51 +00:00
),
2012-02-12 15:37:57 +00:00
'CZ' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
2012-02-12 15:37:57 +00:00
),
'DE' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'DK' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
2013-09-10 12:41:40 +00:00
'EE' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
2013-09-10 12:41:40 +00:00
),
'FI' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'FR' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
2017-04-11 18:10:01 +00:00
'GP' => array(
'state' => array(
'required' => false,
),
),
'GF' => array(
'state' => array(
'required' => false,
),
),
'HK' => array(
2015-01-18 18:59:17 +00:00
'postcode' => array(
'required' => false,
),
2015-01-18 18:59:17 +00:00
'city' => array(
'label' => __( 'Town / District', 'woocommerce' ),
),
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'Region', 'woocommerce' ),
),
),
'HU' => array(
2013-08-01 14:58:48 +00:00
'state' => array(
'label' => __( 'County', 'woocommerce' ),
),
),
'ID' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'Province', 'woocommerce' ),
),
2015-01-18 18:59:17 +00:00
),
'IE' => array(
'postcode' => array(
'required' => false,
'label' => __( 'Eircode', 'woocommerce' ),
),
'state' => array(
'label' => __( 'County', 'woocommerce' ),
),
),
'IS' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'IL' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'IT' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => true,
'label' => __( 'Province', 'woocommerce' ),
),
),
'JP' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'Prefecture', 'woocommerce' ),
2016-12-13 18:48:39 +00:00
'priority' => 66,
),
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
),
'KR' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
2017-04-11 18:02:23 +00:00
'KW' => array(
'state' => array(
'required' => false,
),
),
2017-04-11 18:10:01 +00:00
'LB' => array(
'state' => array(
'required' => false,
),
),
'MQ' => array(
'state' => array(
'required' => false,
),
),
'NL' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
'label' => __( 'Province', 'woocommerce' ),
),
),
'NZ' => array(
2016-04-13 03:39:04 +00:00
'postcode' => array(
'label' => __( 'Postcode', 'woocommerce' ),
2016-04-13 03:39:04 +00:00
),
2015-01-18 18:59:17 +00:00
'state' => array(
2016-04-13 03:39:04 +00:00
'required' => false,
'label' => __( 'Region', 'woocommerce' ),
),
),
'NO' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'NP' => array(
'state' => array(
2015-11-05 17:40:30 +00:00
'label' => __( 'State / Zone', 'woocommerce' ),
),
'postcode' => array(
'required' => false,
),
),
'PL' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
2013-03-19 21:33:01 +00:00
'PT' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
2013-03-19 21:33:01 +00:00
),
2017-04-11 18:10:01 +00:00
'RE' => array(
'state' => array(
'required' => false,
),
),
'RO' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'SG' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'SK' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'SI' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'ES' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'Province', 'woocommerce' ),
),
),
2012-07-10 12:36:13 +00:00
'LI' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'Municipality', 'woocommerce' ),
'required' => false,
),
2015-01-18 18:59:17 +00:00
),
'LK' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'SE' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
),
'TR' => array(
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
),
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'Province', 'woocommerce' ),
),
),
'US' => array(
2015-01-18 18:59:17 +00:00
'postcode' => array(
'label' => __( 'ZIP', 'woocommerce' ),
),
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'State', 'woocommerce' ),
),
),
'GB' => array(
2015-01-18 18:59:17 +00:00
'postcode' => array(
'label' => __( 'Postcode', 'woocommerce' ),
),
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'County', 'woocommerce' ),
'required' => false,
),
),
'VN' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'required' => false,
),
'postcode' => array(
2016-12-13 18:48:39 +00:00
'priority' => 65,
2015-01-18 18:59:17 +00:00
'required' => false,
'hidden' => false,
),
'address_2' => array(
2015-01-18 18:59:17 +00:00
'required' => false,
'hidden' => true,
),
2012-08-06 22:43:39 +00:00
),
2013-03-07 11:01:06 +00:00
'WS' => array(
'postcode' => array(
2015-01-18 18:59:17 +00:00
'required' => false,
'hidden' => true,
2013-03-07 11:01:06 +00:00
),
),
2017-04-11 18:10:01 +00:00
'YT' => array(
'state' => array(
'required' => false,
),
),
'ZA' => array(
2015-01-18 18:59:17 +00:00
'state' => array(
'label' => __( 'Province', 'woocommerce' ),
),
),
2013-02-01 14:53:44 +00:00
'ZW' => array(
'postcode' => array(
2015-01-18 18:59:17 +00:00
'required' => false,
'hidden' => true,
2013-02-01 14:53:44 +00:00
),
),
));
2012-08-06 22:43:39 +00:00
$this->locale = array_intersect_key( $this->locale, array_merge( $this->get_allowed_countries(), $this->get_shipping_countries() ) );
2012-08-06 22:43:39 +00:00
// Default Locale Can be filtered to override fields in get_address_fields(). Countries with no specific locale will use default.
$this->locale['default'] = apply_filters( 'woocommerce_get_country_locale_default', $this->get_default_address_fields() );
2012-08-06 22:43:39 +00:00
// Filter default AND shop base locales to allow overides via a single function. These will be used when changing countries on the checkout
2015-01-18 18:59:17 +00:00
if ( ! isset( $this->locale[ $this->get_base_country() ] ) ) {
$this->locale[ $this->get_base_country() ] = $this->locale['default'];
2015-01-18 18:59:17 +00:00
}
2012-08-06 22:43:39 +00:00
2015-01-18 18:59:17 +00:00
$this->locale['default'] = apply_filters( 'woocommerce_get_country_locale_base', $this->locale['default'] );
$this->locale[ $this->get_base_country() ] = apply_filters( 'woocommerce_get_country_locale_base', $this->locale[ $this->get_base_country() ] );
}
2012-08-06 22:43:39 +00:00
return $this->locale;
}
2012-08-06 22:43:39 +00:00
/**
2015-11-03 13:31:20 +00:00
* Apply locale and get address fields.
* @param mixed $country (default: '')
2015-01-18 18:59:17 +00:00
* @param string $type (default: 'billing_')
* @return array
*/
public function get_address_fields( $country = '', $type = 'billing_' ) {
if ( ! $country ) {
2015-01-18 18:59:17 +00:00
$country = $this->get_base_country();
}
2013-07-19 14:08:40 +00:00
2015-01-18 18:59:17 +00:00
$fields = $this->get_default_address_fields();
$locale = $this->get_country_locale();
2012-08-06 22:43:39 +00:00
if ( isset( $locale[ $country ] ) ) {
$fields = wc_array_overlay( $fields, $locale[ $country ] );
2012-07-10 12:36:13 +00:00
}
2012-08-06 22:43:39 +00:00
// Prepend field keys
$address_fields = array();
2012-08-06 22:43:39 +00:00
2012-07-10 12:36:13 +00:00
foreach ( $fields as $key => $value ) {
if ( 'state' === $key ) {
$value['country_field'] = $type . 'country';
}
2015-01-18 18:59:17 +00:00
$address_fields[ $type . $key ] = $value;
}
2012-08-06 22:43:39 +00:00
// Add email and phone fields.
if ( 'billing_' === $type ) {
$address_fields['billing_phone'] = array(
'label' => __( 'Phone', 'woocommerce' ),
'required' => true,
'type' => 'tel',
'class' => array( 'form-row-first' ),
'validate' => array( 'phone' ),
'autocomplete' => 'tel',
2016-12-13 18:48:39 +00:00
'priority' => 100,
);
$address_fields['billing_email'] = array(
2016-12-19 12:19:44 +00:00
'label' => __( 'Email address', 'woocommerce' ),
'required' => true,
'type' => 'email',
'class' => array( 'form-row-last' ),
'validate' => array( 'email' ),
'autocomplete' => 'no' === get_option( 'woocommerce_registration_generate_username' ) ? 'email' : 'email username',
'priority' => 110,
);
2012-07-10 12:36:13 +00:00
}
2012-08-06 22:43:39 +00:00
2016-11-25 12:24:23 +00:00
/**
* Important note on this filter: Changes to address fields can and will be overridden by
* the woocommerce_default_address_fields. The locales/default locales apply on top based
* on country selection. If you want to change things like the required status of an
* address field, filter woocommerce_default_address_fields instead.
*/
return apply_filters( 'woocommerce_' . $type . 'fields', $address_fields, $country );
}
}