PluginProbe
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) / 1.8.11.3
Charitable – Donation & Fundraising Platform (Donation Forms, Recurring Donations & Fundraising Campaigns) v1.8.11.3
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.8.11.3, at includes/locale/class-charitable-locations.php

458 lines 12.9 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) 2023, 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 * Process an array of address fields, trimming whitespace and adding full country and full state names.
308 *
309 * @since 1.0.0
310 *
311 * @param array $address_fields Address fields.
312 * @return string[]
313 */
314 private function sanitize_address_fields( $address_fields ) {
315 if ( ! is_array( $address_fields ) ) {
316 return $address_fields;
317 }
318
319 $address_fields = array_map( 'trim', array_filter( $address_fields, 'is_string' ) );
320
321 /**
322 * Set up empty default fields and merge with address fields.
323 */
324 $defaults = array(
325 'first_name' => '',
326 'last_name' => '',
327 'company' => '',
328 'address' => '',
329 'address_2' => '',
330 'city' => '',
331 'state' => '',
332 'full_state' => '',
333 'postcode' => '',
334 'country' => '',
335 'full_country' => '',
336 );
337
338 $address_fields = array_merge( $defaults, $address_fields );
339 $country = $address_fields['country'];
340 $state = $address_fields['state'];
341
342 /**
343 * If country is empty, return address fields as they are.
344 */
345 if ( empty( $country ) ) {
346 return $address_fields;
347 }
348
349 $countries = $this->get_countries();
350
351 if ( array_key_exists( $country, $countries ) ) {
352 $address_fields['full_country'] = $countries[ $country ];
353 }
354
355 /**
356 * Return address fields as they are if state is not set.
357 */
358 if ( empty( $state ) ) {
359 return $address_fields;
360 }
361
362 $states = $this->get_states_for_country( $country );
363
364 if ( array_key_exists( $address_fields['state'], $states ) ) {
365 $address_fields['full_state'] = $states[ $address_fields['state'] ];
366 }
367
368 return $address_fields;
369 }
370
371 /**
372 * Get formatted address based on country of address.
373 *
374 * @since 1.0.0
375 *
376 * @param array $address_fields Address fields.
377 * @return string
378 */
379 public function get_formatted_address( $address_fields = array() ) {
380 $address_fields = $this->sanitize_address_fields( $address_fields );
381 $formatted_address = '';
382
383 /* If main address field is empty, then do not format. */
384 if ( empty( $address_fields['address'] ) ) {
385 return $formatted_address;
386 }
387
388 /**
389 * Filter formatted address replacements.
390 *
391 * @since 1.0.0
392 *
393 * @param array $replacements The replacements as a key => value array.
394 * @param array $address_fields All the address fields.
395 */
396 $replacements = apply_filters(
397 'charitable_formatted_address_replacements',
398 array(
399 '{first_name}' => $address_fields['first_name'],
400 '{last_name}' => $address_fields['last_name'],
401 '{name}' => $address_fields['first_name'] . ' ' . $address_fields['last_name'],
402 '{company}' => $address_fields['company'],
403 '{address_1}' => $address_fields['address'],
404 '{address_2}' => $address_fields['address_2'],
405 '{city}' => $address_fields['city'],
406 '{state}' => $address_fields['full_state'],
407 '{postcode}' => $address_fields['postcode'],
408 '{country}' => $address_fields['full_country'],
409 '{first_name_upper}' => strtoupper( $address_fields['first_name'] ),
410 '{last_name_upper}' => strtoupper( $address_fields['last_name'] ),
411 '{name_upper}' => strtoupper( $address_fields['first_name'] . ' ' . $address_fields['last_name'] ),
412 '{company_upper}' => strtoupper( $address_fields['company'] ),
413 '{address_1_upper}' => strtoupper( $address_fields['address'] ),
414 '{address_2_upper}' => strtoupper( $address_fields['address_2'] ),
415 '{city_upper}' => strtoupper( $address_fields['city'] ),
416 '{state_upper}' => strtoupper( $address_fields['full_state'] ),
417 '{state_code}' => strtoupper( $address_fields['state'] ),
418 '{postcode_upper}' => strtoupper( $address_fields['postcode'] ),
419 '{country_upper}' => strtoupper( $address_fields['full_country'] ),
420 ),
421 $address_fields
422 );
423
424 /* Substitute address parts into the string */
425 $replace = array_map( 'esc_html', $replacements );
426 $format = $this->get_address_format( $address_fields );
427 $formatted_address = str_replace( array_keys( $replace ), $replace, $format );
428
429 /* Clean up white space */
430 $formatted_address = preg_replace( '/ +/', ' ', trim( $formatted_address ) );
431 $formatted_address = preg_replace( '/\n\n+/', "\n", $formatted_address );
432
433 /* Break newlines apart and remove empty lines/trim commas and white space */
434 $formatted_address = explode( "\n", $formatted_address );
435 $formatted_address = array_map( array( $this, 'trim_formatted_address_line' ), $formatted_address );
436 $formatted_address = array_filter( $formatted_address );
437
438 /* Add html breaks */
439 $formatted_address = implode( '<br/>', $formatted_address );
440
441 return $formatted_address;
442 }
443
444 /**
445 * Trim white space and commas off a line.
446 *
447 * @since 1.0.0
448 *
449 * @param string $line The line to be trimmed.
450 * @return string
451 */
452 private function trim_formatted_address_line( $line ) {
453 return trim( $line, ', ' );
454 }
455 }
456
457 endif;
458