PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.7.0.2
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.7.0.2
1.8.13.1 1.8.13 1.8.12.3 1.8.12.2 1.8.12.1 1.8.12 1.8.11.3 1.8.11.2 1.8.11.1 1.8.11 1.6.6 1.6.60 1.6.7 1.6.8 1.6.9 1.7.0 1.7.0.1 1.7.0.11 1.7.0.12 1.7.0.14 1.7.0.2 1.7.0.3 1.7.0.5 1.7.0.6 1.7.0.7 All 212 releases
charitable / includes / locale / class-charitable-locations.php

class-charitable-locations.php in Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) 1.7.0.2, at includes/locale/class-charitable-locations.php

460 lines 12.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Contains the class that provides a utility functions relating to locales.
4 *
5 * @package Charitable/Classes/Charitable_Locations
6 * @author David Bisset
7 * @copyright Copyright (c) 2022, WP Charitable LLC
8 * @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
9 * @since 1.0.0
10 * @version 1.6.35
11 */
12
13 // Exit if accessed directly.
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 if ( ! class_exists( 'Charitable_Locations' ) ) :
19
20 /**
21 * Charitable_Locations
22 *
23 * @since 1.0.0
24 */
25 class Charitable_Locations {
26
27 /**
28 * The single instance of this class.
29 *
30 * @since 1.0.0
31 *
32 * @var Charitable_Locations|null
33 */
34 private static $instance = null;
35
36 /**
37 * List of countries in country_code=>name format.
38 *
39 * @since 1.0.0
40 *
41 * @var string[]
42 */
43 private $countries = array();
44
45 /**
46 * List of states as a multidimensional array, grouped by country.
47 *
48 * @since 1.0.0
49 *
50 * @var array[]
51 */
52 private $states = array();
53
54 /**
55 * List of different countries' address formats.
56 *
57 * @since 1.0.0
58 *
59 * @var string[]
60 */
61 private $address_formats;
62
63 /**
64 * Returns and/or create the single instance of this class.
65 *
66 * @since 1.2.0
67 *
68 * @return Charitable_Locations
69 */
70 public static function get_instance() {
71 if ( is_null( self::$instance ) ) {
72 self::$instance = new self();
73 }
74
75 return self::$instance;
76 }
77
78 /**
79 * Set up the class.
80 *
81 * @since 1.2.0
82 */
83 private function __construct() {}
84
85 /**
86 * Return an array with all the countries supported by Charitable.
87 *
88 * @since 1.0.0
89 *
90 * @return string[]
91 */
92 public function get_countries() {
93 if ( empty( $this->countries ) ) {
94 /**
95 * Filter the list of countries supported by Charitable.
96 *
97 * @since 1.0.0
98 *
99 * @param array $countries The list of countries.
100 */
101 $this->countries = apply_filters( 'charitable_countries', include( charitable()->get_path( 'directory' ) . 'i18n/countries.php' ) );
102 }
103
104 return $this->countries;
105 }
106
107 /**
108 * Return the country codes of countries with states.
109 *
110 * @since 1.0.0
111 *
112 * @return string[]
113 */
114 public function get_countries_with_states() {
115 return array(
116 'AU',
117 'BD',
118 'BG',
119 'BR',
120 'CA',
121 'CN',
122 'ES',
123 'GR',
124 'HK',
125 'HU',
126 'ID',
127 'IN',
128 'IR',
129 'IT',
130 'JP',
131 'MX',
132 'MY',
133 'NP',
134 'NZ',
135 'PE',
136 'TH',
137 'TR',
138 'US',
139 'ZA',
140 );
141 }
142
143 /**
144 * Return an array with all the states supported by Charitable.
145 *
146 * @since 1.0.0
147 *
148 * @return string[]
149 */
150 public function get_all_states() {
151 foreach ( $this->get_countries_with_states() as $country_code ) {
152 $this->get_states_for_country( $country_code );
153 }
154
155 return $this->states;
156 }
157
158 /**
159 * Return the states in this country.
160 *
161 * @since 1.0.0
162 *
163 * @param string $country_code The three-character country code.
164 * @return string[]
165 */
166 public function get_states_for_country( $country_code ) {
167 if ( ! in_array( $country_code, $this->get_countries_with_states() ) ) {
168 return array();
169 }
170
171 if ( ! isset( $this->states[ $country_code ] ) ) {
172 /**
173 * Filter the list of states by country.
174 *
175 * @since 1.0.0
176 *
177 * @param array $states The list of states.
178 * @param string $country_code The country code.
179 */
180 $this->states[ $country_code ] = apply_filters(
181 'charitable_country_states',
182 include( charitable()->get_path( 'directory' ) . '/i18n/states/' . $country_code . '.php' ),
183 $country_code
184 );
185 }
186
187 return $this->states[ $country_code ];
188 }
189
190 /**
191 * Get the base country for the website.
192 *
193 * @since 1.0.0
194 *
195 * @return string
196 */
197 public function get_base_country() {
198 $country = esc_attr( get_option( 'charitable_default_country' ) );
199
200 /**
201 * Filter the default country.
202 *
203 * @since 1.0.0
204 *
205 * @param string $country The base country.
206 */
207 return apply_filters( 'charitable_countries_base_country', $country );
208 }
209
210 /**
211 * Get country address formats.
212 *
213 * @since 1.0.0
214 *
215 * @return string[]
216 */
217 public function get_address_formats() {
218 if ( ! isset( $this->address_formats ) ) {
219
220 /* Common formats. */
221 $postcode_before_city = "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}";
222
223 /**
224 * Filter address formats by country.
225 *
226 * @since 1.0.0
227 *
228 * @param array $formats
229 */
230 $this->address_formats = apply_filters(
231 'charitable_localisation_address_formats',
232 array(
233 'default' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}\n{postcode}\n{country}",
234 'AU' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
235 'AT' => $postcode_before_city,
236 'BE' => $postcode_before_city,
237 'CA' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
238 'CH' => $postcode_before_city,
239 'CN' => "{country} {postcode}\n{state}, {city}, {address_2}, {address_1}\n{company}\n{name}",
240 'CZ' => $postcode_before_city,
241 'DE' => $postcode_before_city,
242 'EE' => $postcode_before_city,
243 'FI' => $postcode_before_city,
244 'DK' => $postcode_before_city,
245 'FR' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city_upper}\n{country}",
246 'HK' => "{company}\n{first_name} {last_name_upper}\n{address_1}\n{address_2}\n{city_upper}\n{state_upper}\n{country}",
247 'HU' => "{name}\n{company}\n{city}\n{address_1}\n{address_2}\n{postcode}\n{country}",
248 'IS' => $postcode_before_city,
249 'IT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode}\n{city}\n{state_upper}\n{country}",
250 'JP' => "{postcode}\n{state}{city}{address_1}\n{address_2}\n{company}\n{last_name} {first_name}\n {country}",
251 'TW' => "{postcode}\n{city}{address_2}\n{address_1}\n{company}\n{last_name} {first_name}\n {country}",
252 'LI' => $postcode_before_city,
253 'NL' => $postcode_before_city,
254 'NZ' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {postcode}\n{country}",
255 'NO' => $postcode_before_city,
256 'PL' => $postcode_before_city,
257 'SK' => $postcode_before_city,
258 'SI' => $postcode_before_city,
259 'ES' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city}\n{state}\n{country}",
260 'SE' => $postcode_before_city,
261 'TR' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city} {state}\n{country}",
262 'US' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}, {state_code} {postcode}\n{country}",
263 'VN' => "{name}\n{company}\n{address_1}\n{city}\n{country}",
264 )
265 );
266
267 }//end if
268
269 return $this->address_formats;
270 }
271
272 /**
273 * Return the address format to use for the given address.
274 *
275 * @since 1.0.0
276 *
277 * @param array $address_fields Address fields.
278 * @return string
279 */
280 private function get_address_format( $address_fields ) {
281 $formats = $this->get_address_formats();
282 $country = $address_fields['country'];
283
284 /**
285 * If the country is set and it has its own specific format, use that. Otherwise, use default format.
286 */
287 $format = isset( $formats[ $country ] ) ? $formats[ $country ] : $formats['default'];
288
289 /**
290 * By default, the country field is left out for local addresses.
291 *
292 * Use the `charitable_formatted_address_force_country_display` filter
293 * to force the country to always be printed.
294 *
295 * @since 1.0.0
296 *
297 * @param boolean $force_country Whether the country is always shown. False by default.
298 */
299 if ( $country == $this->get_base_country() && false === apply_filters( 'charitable_formatted_address_force_country_display', false ) ) {
300 $format = str_replace( '{country}', '', $format );
301 }
302
303 return $format;
304
305 }
306
307 /**
308 * Process an array of address fields, trimming whitespace and adding full country and full state names.
309 *
310 * @since 1.0.0
311 *
312 * @param array $address_fields Address fields.
313 * @return string[]
314 */
315 private function sanitize_address_fields( $address_fields ) {
316 if ( ! is_array( $address_fields ) ) {
317 return $address_fields;
318 }
319
320 $address_fields = array_map( 'trim', array_filter( $address_fields, 'is_string' ) );
321
322 /**
323 * Set up empty default fields and merge with address fields.
324 */
325 $defaults = array(
326 'first_name' => '',
327 'last_name' => '',
328 'company' => '',
329 'address' => '',
330 'address_2' => '',
331 'city' => '',
332 'state' => '',
333 'full_state' => '',
334 'postcode' => '',
335 'country' => '',
336 'full_country' => '',
337 );
338
339 $address_fields = array_merge( $defaults, $address_fields );
340 $country = $address_fields['country'];
341 $state = $address_fields['state'];
342
343 /**
344 * If country is empty, return address fields as they are.
345 */
346 if ( empty( $country ) ) {
347 return $address_fields;
348 }
349
350 $countries = $this->get_countries();
351
352 if ( array_key_exists( $country, $countries ) ) {
353 $address_fields['full_country'] = $countries[ $country ];
354 }
355
356 /**
357 * Return address fields as they are if state is not set.
358 */
359 if ( empty( $state ) ) {
360 return $address_fields;
361 }
362
363 $states = $this->get_states_for_country( $country );
364
365 if ( array_key_exists( $address_fields['state'], $states ) ) {
366 $address_fields['full_state'] = $states[ $address_fields['state'] ];
367 }
368
369 return $address_fields;
370
371 }
372
373 /**
374 * Get formatted address based on country of address.
375 *
376 * @since 1.0.0
377 *
378 * @param array $address_fields Address fields.
379 * @return string
380 */
381 public function get_formatted_address( $address_fields = array() ) {
382 $address_fields = $this->sanitize_address_fields( $address_fields );
383 $formatted_address = '';
384
385 /* If main address field is empty, then do not format. */
386 if ( empty( $address_fields['address'] ) ) {
387 return $formatted_address;
388 }
389
390 /**
391 * Filter formatted address replacements.
392 *
393 * @since 1.0.0
394 *
395 * @param array $replacements The replacements as a key => value array.
396 * @param array $address_fields All the address fields.
397 */
398 $replacements = apply_filters(
399 'charitable_formatted_address_replacements',
400 array(
401 '{first_name}' => $address_fields['first_name'],
402 '{last_name}' => $address_fields['last_name'],
403 '{name}' => $address_fields['first_name'] . ' ' . $address_fields['last_name'],
404 '{company}' => $address_fields['company'],
405 '{address_1}' => $address_fields['address'],
406 '{address_2}' => $address_fields['address_2'],
407 '{city}' => $address_fields['city'],
408 '{state}' => $address_fields['full_state'],
409 '{postcode}' => $address_fields['postcode'],
410 '{country}' => $address_fields['full_country'],
411 '{first_name_upper}' => strtoupper( $address_fields['first_name'] ),
412 '{last_name_upper}' => strtoupper( $address_fields['last_name'] ),
413 '{name_upper}' => strtoupper( $address_fields['first_name'] . ' ' . $address_fields['last_name'] ),
414 '{company_upper}' => strtoupper( $address_fields['company'] ),
415 '{address_1_upper}' => strtoupper( $address_fields['address'] ),
416 '{address_2_upper}' => strtoupper( $address_fields['address_2'] ),
417 '{city_upper}' => strtoupper( $address_fields['city'] ),
418 '{state_upper}' => strtoupper( $address_fields['full_state'] ),
419 '{state_code}' => strtoupper( $address_fields['state'] ),
420 '{postcode_upper}' => strtoupper( $address_fields['postcode'] ),
421 '{country_upper}' => strtoupper( $address_fields['full_country'] ),
422 ),
423 $address_fields
424 );
425
426 /* Substitute address parts into the string */
427 $replace = array_map( 'esc_html', $replacements );
428 $format = $this->get_address_format( $address_fields );
429 $formatted_address = str_replace( array_keys( $replace ), $replace, $format );
430
431 /* Clean up white space */
432 $formatted_address = preg_replace( '/ +/', ' ', trim( $formatted_address ) );
433 $formatted_address = preg_replace( '/\n\n+/', "\n", $formatted_address );
434
435 /* Break newlines apart and remove empty lines/trim commas and white space */
436 $formatted_address = explode( "\n", $formatted_address );
437 $formatted_address = array_map( array( $this, 'trim_formatted_address_line' ), $formatted_address );
438 $formatted_address = array_filter( $formatted_address );
439
440 /* Add html breaks */
441 $formatted_address = implode( '<br/>', $formatted_address );
442
443 return $formatted_address;
444 }
445
446 /**
447 * Trim white space and commas off a line.
448 *
449 * @since 1.0.0
450 *
451 * @param string $line The line to be trimmed.
452 * @return string
453 */
454 private function trim_formatted_address_line( $line ) {
455 return trim( $line, ', ' );
456 }
457 }
458
459 endif;
460