PluginProbe
Property Hive / 2.3.0
Property Hive v2.3.0
2.3.1 2.3.0 2.2.6 2.2.5 2.2.4 2.2.3 2.2.2 1.4.46 1.4.47 1.4.48 1.4.49 1.4.5 1.4.50 1.4.51 1.4.52 1.4.53 1.4.54 1.4.55 1.4.56 1.4.57 1.4.58 1.4.59 1.4.6 1.4.60 1.4.61 All 261 releases
← All changes | includes/class-ph-countries.php +380 -117 1.4.562.3.0 View file →
@@ -1,6 +1,9 @@
1 1 <?php
2 +// phpcs:set WordPress.Security.ValidatedSanitizedInput customSanitizingFunctions[] ph_clean
3 +// ph_clean() recursively sanitizes text; presence, shape and unslashing checks remain separate.
2 4
5 +
3 6 if ( ! defined( 'ABSPATH' ) ) {
4 7 exit; // Exit if accessed directly
5 8 }
6 9
@@ -22,8 +25,9 @@
22 25 add_action( 'template_redirect', array( $this, 'ph_check_currency_change' ) );
23 26
24 27 add_action( 'propertyhive_update_currency_exchange_rates', array( $this, 'ph_update_currency_exchange_rates' ) );
25 28
29 + add_filter( 'propertyhive_search_form_fields_after', array( $this, 'ensure_currency_value_set' ) );
26 30 }
27 31
28 32 /**
29 33 * Auto-load in-accessible properties on demand.
@@ -35,13 +39,59 @@
35 39 return $this->get_countries();
36 40 }
37 41 }
38 42
43 + /**
44 + * Resolve a cookie choice using trusted currency definitions and current rates.
45 + */
46 + public function get_currency_from_cookie() {
47 + if ( ! isset( $_COOKIE['propertyhive_currency'] ) || ! is_string( $_COOKIE['propertyhive_currency'] ) ) {
48 + return false;
49 + }
50 + // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Decode the JSON envelope, then validate its only accepted field against the server's currency definitions below.
51 + $stored = json_decode( html_entity_decode( wp_unslash( $_COOKIE['propertyhive_currency'] ) ), true );
52 + if ( ! is_array( $stored ) || ! isset( $stored['currency_code'] ) || ! is_string( $stored['currency_code'] ) ) {
53 + return false;
54 + }
55 + $code = sanitize_text_field( $stored['currency_code'] );
56 + $currency = $this->get_currency( $code );
57 + if ( false === $currency ) {
58 + return false;
59 + }
60 + $rates = get_option( 'propertyhive_currency_exchange_rates', array() );
61 + $currency['exchange_rate'] = isset( $rates[ $code ] ) && is_numeric( $rates[ $code ] ) ? (float) $rates[ $code ] : 1;
62 + return $currency;
63 + }
64 +
65 + public function ensure_currency_value_set( $form_controls )
66 + {
67 + if ( isset($form_controls['currency']) )
68 + {
69 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Currency is a read-only display preference.
70 + if ( isset($_GET['currency']) && is_string( $_GET['currency'] ) && $_GET['currency'] != '' )
71 + {
72 +
73 + }
74 + elseif ( false !== ( $currency = $this->get_currency_from_cookie() ) )
75 + {
76 + if ( !empty($currency) && isset($currency['currency_code']) && array_key_exists(ph_clean($currency['currency_code']), $form_controls['currency']['options']) )
77 + {
78 + $form_controls['currency']['value'] = $currency['currency_code'];
79 + }
80 + }
81 + }
82 +
83 + return $form_controls;
84 + }
85 +
39 86 public function ph_check_currency_change()
40 87 {
41 - if ( is_post_type_archive('property') && isset($_GET['currency']) )
88 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public currency choice changes only the visitor's display-preference cookie.
89 + if ( is_post_type_archive('property') && isset($_GET['currency']) && is_string( $_GET['currency'] ) )
42 90 {
43 - if ( $_GET['currency'] == '' )
91 + // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Public currency choice changes only the visitor's display-preference cookie.
92 + $currency_code = sanitize_text_field( wp_unslash( $_GET['currency'] ) );
93 + if ( $currency_code == '' )
44 94 {
45 95 // Set to blank to reset back to properties entered currency
46 96 unset( $_COOKIE['propertyhive_currency'] );
47 97 setcookie( 'propertyhive_currency', '', time() - ( 15 * 60 ) );
@@ -47,12 +97,9 @@
47 97 setcookie( 'propertyhive_currency', '', time() - ( 15 * 60 ) );
48 98 return true;
49 99 }
50 100
51 - // TO DO: Make sure currency passed in is in list of countries they operate in
52 - // so we can get the exchange rate
53 -
54 - $currency = $this->get_currency( sanitize_text_field($_GET['currency']) );
101 + $currency = $this->get_currency( $currency_code );
55 102 if ( $currency === FALSE )
56 103 {
57 104 $default_country = get_option( 'propertyhive_default_country', 'GB' );
58 105 $default_country = $this->get_country( $default_country );
@@ -61,19 +108,17 @@
61 108 }
62 109
63 110 $currency['exchange_rate'] = 1;
64 111 $exchange_rates = get_option( 'propertyhive_currency_exchange_rates', array() );
65 - if ( isset($exchange_rates[$_GET['currency']]) )
112 + if ( isset($exchange_rates[$currency_code]) )
66 113 {
67 - $currency['exchange_rate'] = $exchange_rates[sanitize_text_field($_GET['currency'])];
114 + $currency['exchange_rate'] = $exchange_rates[$currency_code];
68 115 }
69 116
70 - ph_setcookie( 'propertyhive_currency', htmlentities(serialize($currency)), time() + (30 * DAY_IN_SECONDS), is_ssl() );
117 + ph_setcookie( 'propertyhive_currency', htmlentities(json_encode($currency)), time() + (30 * DAY_IN_SECONDS), is_ssl() );
71 118 }
72 119 }
73 120
74 -
75 -
76 121 public function get_country( $country_code ) {
77 122
78 123 $countries = $this->get_countries();
79 124
@@ -92,11 +137,15 @@
92 137 foreach ( $countries as $country )
93 138 {
94 139 if ( $country['currency_code'] == $currency_code )
95 140 {
141 + $currency_symbol = apply_filters( 'propertyhive_currency_symbol', $country['currency_symbol'], $currency_code);
142 + $currency_prefix = apply_filters( 'propertyhive_currency_prefix', $country['currency_prefix'], $currency_code);
143 +
96 144 return array(
97 - 'currency_symbol' => $country['currency_symbol'],
98 - 'currency_prefix' => $country['currency_prefix']
145 + 'currency_code' => $currency_code,
146 + 'currency_symbol' => $currency_symbol,
147 + 'currency_prefix' => $currency_prefix
99 148 );
100 149 }
101 150 }
102 151
@@ -108,8 +157,14 @@
108 157 * @return array
109 158 */
110 159 private function get_countries() {
111 160 $countries = array(
161 + 'AR' => array(
162 + 'name' => 'Argentina',
163 + 'currency_code' => 'ARS',
164 + 'currency_symbol' => '$',
165 + 'currency_prefix' => true
166 + ),
112 167 'AU' => array(
113 168 'name' => 'Australia',
114 169 'currency_code' => 'AUD',
115 170 'currency_symbol' => '$',
@@ -118,8 +173,14 @@
118 173 'AT' => array(
119 174 'name' => 'Austria',
120 175 'currency_code' => 'EUR',
121 176 'currency_symbol' => '&euro;',
177 + 'currency_prefix' => false
178 + ),
179 + 'BB' => array(
180 + 'name' => 'Barbados',
181 + 'currency_code' => 'BBD',
182 + 'currency_symbol' => '$',
122 183 'currency_prefix' => true
123 184 ),
124 185 'BE' => array(
125 186 'name' => 'Belgium',
@@ -124,15 +185,21 @@
124 185 'BE' => array(
125 186 'name' => 'Belgium',
126 187 'currency_code' => 'EUR',
127 188 'currency_symbol' => '&euro;',
128 - 'currency_prefix' => true
189 + 'currency_prefix' => false
129 190 ),
191 + 'BR' => array(
192 + 'name' => 'Brazil',
193 + 'currency_code' => 'BRL',
194 + 'currency_symbol' => 'R$',
195 + 'currency_prefix' => true
196 + ),
130 197 'BG' => array(
131 198 'name' => 'Bulgaria',
132 199 'currency_code' => 'BGN',
133 200 'currency_symbol' => 'лв',
134 - 'currency_prefix' => true
201 + 'currency_prefix' => false
135 202 ),
136 203 'CA' => array(
137 204 'name' => 'Canada',
138 205 'currency_code' => 'CAD',
@@ -138,12 +205,24 @@
138 205 'currency_code' => 'CAD',
139 206 'currency_symbol' => '$',
140 207 'currency_prefix' => true
141 208 ),
209 + 'CN' => array(
210 + 'name' => 'China',
211 + 'currency_code' => 'CNY',
212 + 'currency_symbol' => 'Â¥',
213 + 'currency_prefix' => true
214 + ),
215 + 'CO' => array(
216 + 'name' => 'Colombia',
217 + 'currency_code' => 'COP',
218 + 'currency_symbol' => '$',
219 + 'currency_prefix' => true
220 + ),
142 221 'HR' => array(
143 222 'name' => 'Croatia',
144 - 'currency_code' => 'HRK',
145 - 'currency_symbol' => 'kn',
223 + 'currency_code' => 'EUR',
224 + 'currency_symbol' => '&euro;',
146 225 'currency_prefix' => false
147 226 ),
148 227 'CY' => array(
149 228 'name' => 'Cyprus',
@@ -148,9 +227,9 @@
148 227 'CY' => array(
149 228 'name' => 'Cyprus',
150 229 'currency_code' => 'EUR',
151 230 'currency_symbol' => '&euro;',
152 - 'currency_prefix' => true
231 + 'currency_prefix' => false
153 232 ),
154 233 'CZ' => array(
155 234 'name' => 'Czech Republic',
156 235 'currency_code' => 'CZK',
@@ -162,36 +241,78 @@
162 241 'currency_code' => 'DKK',
163 242 'currency_symbol' => 'kr',
164 243 'currency_prefix' => false
165 244 ),
245 + 'EG' => array(
246 + 'name' => 'Egypt',
247 + 'currency_code' => 'EGP',
248 + 'currency_symbol' => 'E&pound;',
249 + 'currency_prefix' => true
250 + ),
166 251 'FI' => array(
167 252 'name' => 'Finland',
168 253 'currency_code' => 'EUR',
169 254 'currency_symbol' => '&euro;',
170 - 'currency_prefix' => true
255 + 'currency_prefix' => false
171 256 ),
172 257 'FR' => array(
173 258 'name' => 'France',
174 259 'currency_code' => 'EUR',
175 260 'currency_symbol' => '&euro;',
176 - 'currency_prefix' => true
261 + 'currency_prefix' => false
177 262 ),
178 263 'DE' => array(
179 264 'name' => 'Germany',
180 265 'currency_code' => 'EUR',
181 266 'currency_symbol' => '&euro;',
267 + 'currency_prefix' => false
268 + ),
269 + 'GI' => array(
270 + 'name' => 'Gibraltar',
271 + 'currency_code' => 'GBP',
272 + 'currency_symbol' => '&pound;',
182 273 'currency_prefix' => true
183 274 ),
275 + 'GR' => array(
276 + 'name' => 'Greece',
277 + 'currency_code' => 'EUR',
278 + 'currency_symbol' => '&euro;',
279 + 'currency_prefix' => false
280 + ),
281 + 'HK' => array(
282 + 'name' => 'Hong Kong',
283 + 'currency_code' => 'HKD',
284 + 'currency_symbol' => '$',
285 + 'currency_prefix' => true
286 + ),
287 + 'IN' => array(
288 + 'name' => 'India',
289 + 'currency_code' => 'INR',
290 + 'currency_symbol' => '₹',
291 + 'currency_prefix' => true
292 + ),
293 + 'ID' => array(
294 + 'name' => 'Indonesia',
295 + 'currency_code' => 'IDR',
296 + 'currency_symbol' => 'Rp',
297 + 'currency_prefix' => true
298 + ),
184 299 'IE' => array(
185 300 'name' => 'Ireland',
186 301 'currency_code' => 'EUR',
187 302 'currency_symbol' => '&euro;',
188 - 'currency_prefix' => true
303 + 'currency_prefix' => false
189 304 ),
190 305 'IT' => array(
191 306 'name' => 'Italy',
192 307 'currency_code' => 'EUR',
193 308 'currency_symbol' => '&euro;',
309 + 'currency_prefix' => false
310 + ),
311 + 'JM' => array(
312 + 'name' => 'Jamaica',
313 + 'currency_code' => 'JMD',
314 + 'currency_symbol' => '$',
194 315 'currency_prefix' => true
195 316 ),
196 317 'JP' => array(
197 318 'name' => 'Japan',
@@ -198,13 +319,31 @@
198 319 'currency_code' => 'JPY',
199 320 'currency_symbol' => '&yen;',
200 321 'currency_prefix' => true
201 322 ),
323 + 'KE' => array(
324 + 'name' => 'Kenya',
325 + 'currency_code' => 'KES',
326 + 'currency_symbol' => 'KSh ',
327 + 'currency_prefix' => true
328 + ),
329 + 'LU' => array(
330 + 'name' => 'Luxembourg',
331 + 'currency_code' => 'EUR',
332 + 'currency_symbol' => '&euro;',
333 + 'currency_prefix' => false
334 + ),
335 + 'MY' => array(
336 + 'name' => 'Malaysia',
337 + 'currency_code' => 'MYR',
338 + 'currency_symbol' => 'RM',
339 + 'currency_prefix' => true
340 + ),
202 341 'MT' => array(
203 342 'name' => 'Malta',
204 343 'currency_code' => 'EUR',
205 344 'currency_symbol' => '&euro;',
206 - 'currency_prefix' => true
345 + 'currency_prefix' => false
207 346 ),
208 347 'MU' => array(
209 348 'name' => 'Mauritius',
210 349 'currency_code' => 'MUR',
@@ -210,8 +349,32 @@
210 349 'currency_code' => 'MUR',
211 350 'currency_symbol' => 'Rs',
212 351 'currency_prefix' => false
213 352 ),
353 + 'MX' => array(
354 + 'name' => 'Mexico',
355 + 'currency_code' => 'MXN',
356 + 'currency_symbol' => '$',
357 + 'currency_prefix' => true
358 + ),
359 + 'MA' => array(
360 + 'name' => 'Morocco',
361 + 'currency_code' => 'MAD',
362 + 'currency_symbol' => 'د.م.',
363 + 'currency_prefix' => false
364 + ),
365 + 'NL' => array(
366 + 'name' => 'Netherlands',
367 + 'currency_code' => 'EUR',
368 + 'currency_symbol' => '&euro;',
369 + 'currency_prefix' => false
370 + ),
371 + 'NZ' => array(
372 + 'name' => 'New Zealand',
373 + 'currency_code' => 'NZD',
374 + 'currency_symbol' => '$',
375 + 'currency_prefix' => true
376 + ),
214 377 'NO' => array(
215 378 'name' => 'Norway',
216 379 'currency_code' => 'NOK',
217 380 'currency_symbol' => 'kr',
@@ -216,14 +379,32 @@
216 379 'currency_code' => 'NOK',
217 380 'currency_symbol' => 'kr',
218 381 'currency_prefix' => false
219 382 ),
383 + 'PK' => array(
384 + 'name' => 'Pakistan',
385 + 'currency_code' => 'PKR',
386 + 'currency_symbol' => 'Rs',
387 + 'currency_prefix' => false
388 + ),
389 + 'PL' => array(
390 + 'name' => 'Poland',
391 + 'currency_code' => 'PLN',
392 + 'currency_symbol' => 'zł',
393 + 'currency_prefix' => false
394 + ),
220 395 'PT' => array(
221 396 'name' => 'Portugal',
222 397 'currency_code' => 'EUR',
223 398 'currency_symbol' => '&euro;',
224 - 'currency_prefix' => true
399 + 'currency_prefix' => false
225 400 ),
401 + 'QA' => array(
402 + 'name' => 'Qatar',
403 + 'currency_code' => 'QAR',
404 + 'currency_symbol' => 'QR',
405 + 'currency_prefix' => false
406 + ),
226 407 'RU' => array(
227 408 'name' => 'Russia',
228 409 'currency_code' => 'RUB',
229 410 'currency_symbol' => '₽',
@@ -228,8 +409,26 @@
228 409 'currency_code' => 'RUB',
229 410 'currency_symbol' => '₽',
230 411 'currency_prefix' => true
231 412 ),
413 + 'VC' => array(
414 + 'name' => 'Saint Vincent and the Grenadines',
415 + 'currency_code' => 'XCD',
416 + 'currency_symbol' => '$',
417 + 'currency_prefix' => true
418 + ),
419 + 'SA' => array(
420 + 'name' => 'Saudi Arabia',
421 + 'currency_code' => 'SAR',
422 + 'currency_symbol' => 'ï·¼',
423 + 'currency_prefix' => false
424 + ),
425 + 'SG' => array(
426 + 'name' => 'Singapore',
427 + 'currency_code' => 'SGD',
428 + 'currency_symbol' => '$',
429 + 'currency_prefix' => true
430 + ),
232 431 'ZA' => array(
233 432 'name' => 'South Africa',
234 433 'currency_code' => 'ZAR',
235 434 'currency_symbol' => 'R',
@@ -234,13 +433,19 @@
234 433 'currency_code' => 'ZAR',
235 434 'currency_symbol' => 'R',
236 435 'currency_prefix' => true
237 436 ),
437 + 'KR' => array(
438 + 'name' => 'South Korea',
439 + 'currency_code' => 'KRW',
440 + 'currency_symbol' => 'â‚©',
441 + 'currency_prefix' => true
442 + ),
238 443 'ES' => array(
239 444 'name' => 'Spain',
240 445 'currency_code' => 'EUR',
241 446 'currency_symbol' => '&euro;',
242 - 'currency_prefix' => true
447 + 'currency_prefix' => false
243 448 ),
244 449 'SE' => array(
245 450 'name' => 'Sweden',
246 451 'currency_code' => 'SEK',
@@ -246,8 +451,26 @@
246 451 'currency_code' => 'SEK',
247 452 'currency_symbol' => 'kr',
248 453 'currency_prefix' => false
249 454 ),
455 + 'CH' => array(
456 + 'name' => 'Switzerland',
457 + 'currency_code' => 'CHF',
458 + 'currency_symbol' => 'CHF',
459 + 'currency_prefix' => true
460 + ),
461 + 'TH' => array(
462 + 'name' => 'Thailand',
463 + 'currency_code' => 'THB',
464 + 'currency_symbol' => '฿',
465 + 'currency_prefix' => true
466 + ),
467 + 'TR' => array(
468 + 'name' => 'Turkey',
469 + 'currency_code' => 'TRY',
470 + 'currency_symbol' => '‎₺',
471 + 'currency_prefix' => true
472 + ),
250 473 'AE' => array(
251 474 'name' => 'United Arab Emirates',
252 475 'currency_code' => 'AED',
253 476 'currency_symbol' => '‎د.إ',
@@ -264,8 +487,14 @@
264 487 'currency_code' => 'USD',
265 488 'currency_symbol' => '$',
266 489 'currency_prefix' => true
267 490 ),
491 + 'VN' => array(
492 + 'name' => 'Vietnam',
493 + 'currency_code' => 'VND',
494 + 'currency_symbol' => 'â‚«',
495 + 'currency_prefix' => true
496 + ),
268 497 );
269 498
270 499 return apply_filters( 'propertyhive_countries', $countries );
271 500 }
@@ -283,9 +512,9 @@
283 512 echo '<option';
284 513 if ( $selected_country == $key || ( $selected_country == '' && $key == 'GB' ) ) {
285 514 echo ' selected="selected"';
286 515 }
287 - echo ' value="' . esc_attr( $key ) . '">' . ( $escape ? esc_js( $value['name'] ) : $value['name'] ) . '</option>';
516 + echo ' value="' . esc_attr( $key ) . '">' . ( $escape ? esc_js( $value['name'] ) : esc_html( $value['name'] ) ) . '</option>';
288 517 }
289 518 }
290 519 }
291 520
@@ -310,9 +539,18 @@
310 539 {
311 540 $countries = $this->countries;
312 541
313 542 $department = get_post_meta( $postID, '_department', true );
543 + if ( ph_get_custom_department_based_on( $department ) !== false )
544 + {
545 + $department = ph_get_custom_department_based_on( $department );
546 + }
547 +
314 548 $country = get_post_meta( $postID, '_address_country', true );
549 + if ( $country == '' )
550 + {
551 + $country = get_option( 'propertyhive_default_country', 'GB' );
552 + }
315 553
316 554 if (isset($countries[$country]))
317 555 {
318 556 if ( $department == 'residential-sales' )
@@ -317,12 +555,8 @@
317 555 {
318 556 if ( $department == 'residential-sales' )
319 557 {
320 558 $currency = get_post_meta( $postID, '_currency', true );
321 - if ( $country == '' )
322 - {
323 - $country = get_option( 'propertyhive_default_country', 'GB' );
324 - }
325 559 if ( $currency == '' )
326 560 {
327 561 $currency = $this->get_country($country);
328 562 $currency = $currency['currency_code'];
@@ -336,12 +570,8 @@
336 570 }
337 571 elseif ( $department == 'residential-lettings' )
338 572 {
339 573 $currency = get_post_meta( $postID, '_currency', true );
340 - if ( $country == '' )
341 - {
342 - $country = get_option( 'propertyhive_default_country', 'GB' );
343 - }
344 574 if ( $currency == '' )
345 575 {
346 576 $currency = $this->get_country($country);
347 577 $currency = $currency['currency_code'];
@@ -347,34 +577,39 @@
347 577 $currency = $currency['currency_code'];
348 578 }
349 579
350 580 $rent = get_post_meta( $postID, '_rent', true );
351 - $rent_frequency = get_post_meta( $postID, '_rent_frequency', true );
581 +
582 + $converted_price = 0;
583 + if ( !empty($rent) && is_numeric($rent) )
584 + {
585 + $price = $rent; // Stored in pcm
586 + $rent_frequency = get_post_meta( $postID, '_rent_frequency', true );
587 + switch ($rent_frequency)
588 + {
589 + case "pd": { $price = ($rent * 365) / 12; break; }
590 + case "pppw":
591 + {
592 + $bedrooms = get_post_meta( $postID, '_bedrooms', true );
593 + if ( ( $bedrooms !== FALSE && $bedrooms != 0 && $bedrooms != '' ) && apply_filters( 'propertyhive_pppw_to_consider_bedrooms', true ) == true )
594 + {
595 + $price = (($rent * 52) / 12) * $bedrooms;
596 + }
597 + else
598 + {
599 + $price = ($rent * 52) / 12;
600 + }
601 + break;
602 + }
603 + case "pw": { $price = ($rent * 52) / 12; break; }
604 + case "pcm": { $price = $rent; break; }
605 + case "pq": { $price = ($rent * 4) / 12; break; }
606 + case "pa": { $price = ($rent / 12); break; }
607 + }
352 608
353 - $price = $rent; // Stored in pcm
354 - switch ($rent_frequency)
355 - {
356 - case "pppw":
357 - {
358 - $bedrooms = get_post_meta( $postID, '_bedrooms', true );
359 - if ( ( $bedrooms !== FALSE && $bedrooms != 0 && $bedrooms != '' ) && apply_filters( 'propertyhive_pppw_to_consider_bedrooms', true ) == true )
360 - {
361 - $price = (($rent * 52) / 12) * $bedrooms;
362 - }
363 - else
364 - {
365 - $price = ($rent * 52) / 12;
366 - }
367 - break;
368 - }
369 - case "pw": { $price = ($rent * 52) / 12; break; }
370 - case "pcm": { $price = $rent; break; }
371 - case "pq": { $price = ($rent * 4) / 12; break; }
372 - case "pa": { $price = ($rent / 12); break; }
609 + $converted_price = $this->convert_price_to_gbp( $price, $currency );
373 610 }
374 611
375 - $converted_price = $this->convert_price_to_gbp( $price, $currency );
376 -
377 612 update_post_meta( $postID, '_price_actual', $converted_price );
378 613 }
379 614 if ( $department == 'commercial' )
380 615 {
@@ -380,12 +615,8 @@
380 615 {
381 616 if ( get_post_meta( $postID, '_for_sale', true ) == 'yes' )
382 617 {
383 618 $currency = get_post_meta( $postID, '_commercial_price_currency', true );
384 - if ( $country == '' )
385 - {
386 - $country = get_option( 'propertyhive_default_country', 'GB' );
387 - }
388 619 if ( $currency == '' )
389 620 {
390 621 $currency = $this->get_country($country);
391 622 $currency = $currency['currency_code'];
@@ -391,8 +622,12 @@
391 622 $currency = $currency['currency_code'];
392 623 }
393 624
394 625 $price = get_post_meta( $postID, '_price_from', true );
626 + if ( $price == '' )
627 + {
628 + $price = get_post_meta( $postID, '_price_to', true );
629 + }
395 630
396 631 $converted_price = $this->convert_price_to_gbp( $price, $currency );
397 632
398 633 update_post_meta( $postID, '_price_from_actual', $converted_price );
@@ -397,8 +632,12 @@
397 632
398 633 update_post_meta( $postID, '_price_from_actual', $converted_price );
399 634
400 635 $price = get_post_meta( $postID, '_price_to', true );
636 + if ( $price == '' )
637 + {
638 + $price = get_post_meta( $postID, '_price_from', true );
639 + }
401 640
402 641 $converted_price = $this->convert_price_to_gbp( $price, $currency );
403 642
404 643 update_post_meta( $postID, '_price_to_actual', $converted_price );
@@ -405,12 +644,8 @@
405 644 }
406 645 if ( get_post_meta( $postID, '_to_rent', true ) == 'yes' )
407 646 {
408 647 $currency = get_post_meta( $postID, '_commercial_rent_currency', true );
409 - if ( $country == '' )
410 - {
411 - $country = get_option( 'propertyhive_default_country', 'GB' );
412 - }
413 648 if ( $currency == '' )
414 649 {
415 650 $currency = $this->get_country($country);
416 651 $currency = $currency['currency_code'];
@@ -418,15 +653,23 @@
418 653
419 654 $rent_units = get_post_meta( $postID, '_rent_units', true );
420 655
421 656 $price = get_post_meta( $postID, '_rent_from', true );
422 - switch ($rent_units)
423 - {
424 - case "pw": { $price = ($price * 52) / 12; break; }
425 - case "pcm": { $price = $price; break; }
426 - case "pq": { $price = ($price * 4) / 52; break; }
427 - case "pa": { $price = ($price / 52); break; }
428 - }
657 + if ( $price == '' )
658 + {
659 + $price = get_post_meta( $postID, '_rent_to', true );
660 + }
661 + if ( is_numeric($price) )
662 + {
663 + switch ($rent_units)
664 + {
665 + case "pd": { $price = ($price * 365) / 12; break; }
666 + case "pw": { $price = ($price * 52) / 12; break; }
667 + case "pcm": { $price = $price; break; }
668 + case "pq": { $price = ($price * 4) / 12; break; }
669 + case "pa": { $price = ($price / 12); break; }
670 + }
671 + }
429 672
430 673 $converted_price = $this->convert_price_to_gbp( $price, $currency );
431 674
432 675 update_post_meta( $postID, '_rent_from_actual', $converted_price );
@@ -436,15 +679,23 @@
436 679 update_post_meta( $postID, '_price_from_actual', $converted_price );
437 680 }
438 681
439 682 $price = get_post_meta( $postID, '_rent_to', true );
440 - switch ($rent_units)
441 - {
442 - case "pw": { $price = ($price * 52) / 12; break; }
443 - case "pcm": { $price = $price; break; }
444 - case "pq": { $price = ($price * 4) / 52; break; }
445 - case "pa": { $price = ($price / 52); break; }
446 - }
683 + if ( $price == '' )
684 + {
685 + $price = get_post_meta( $postID, '_rent_from', true );
686 + }
687 + if ( is_numeric($price) )
688 + {
689 + switch ($rent_units)
690 + {
691 + case "pd": { $price = ($price * 365) / 12; break; }
692 + case "pw": { $price = ($price * 52) / 12; break; }
693 + case "pcm": { $price = $price; break; }
694 + case "pq": { $price = ($price * 4) / 12; break; }
695 + case "pa": { $price = ($price / 12); break; }
696 + }
697 + }
447 698
448 699 $converted_price = $this->convert_price_to_gbp( $price, $currency );
449 700
450 701 update_post_meta( $postID, '_rent_to_actual', $converted_price );
@@ -450,8 +701,10 @@
450 701 update_post_meta( $postID, '_rent_to_actual', $converted_price );
451 702 }
452 703 }
453 704 }
705 +
706 + do_action('propertyhive_property_price_actual_updated', $postID);
454 707 }
455 708
456 709 public function ph_update_currency_exchange_rates()
457 710 {
@@ -460,72 +713,82 @@
460 713 if ( $this->countries )
461 714 {
462 715 $countries = $this->countries;
463 716
464 - $exchange_rates = array();
717 + // Filter 'propertyhive_new_currency_exchange_rates' allows someone to use their own currency API
718 + // Return should be in format:
719 + // array(
720 + // 'EUR' => x,
721 + // 'USD' => x,
722 + // ... etc
723 + // )
724 + $exchange_rates = apply_filters( 'propertyhive_new_currency_exchange_rates', array() );
465 725 $previous_exchange_rates = get_option( 'propertyhive_currency_exchange_rates' );
466 726
467 - $default_country = get_option( 'propertyhive_default_country', 'GB' );
468 - $selected_countries = get_option( 'propertyhive_countries', array( $default_country ) );
727 + if ( empty($exchange_rates) )
728 + {
729 + // Get all currency exchange rates from GBP
730 + // We're using the API from https://github.com/fawazahmed0/exchange-api
731 + $url = 'https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/gbp.json'; // phpcs:ignore PluginCheck.CodeAnalysis.Offloading.OffloadedContent -- Retrieves current exchange-rate data from the configured currency service.
732 + $response = wp_remote_get( $url );
469 733
470 - foreach ( $countries as $key => $value )
471 - {
472 - if (!isset($exchange_rates[$value['currency_code']]) && in_array($key, $selected_countries) && $value['currency_code'] != 'GBP')
734 + if ( is_array( $response ) )
473 735 {
474 - // we haven't got this exchange rate
475 - $from = 'GBP';
476 - $to = $value['currency_code'];
736 + $body = wp_remote_retrieve_body( $response );
737 + $json = json_decode($body, true);
477 738
478 - $exchangeRate = '';
479 -
480 - $url = 'https://finance.google.com/finance/converter?a=1&from=' . $from . '&to=' . $to;
481 -
482 - $response = wp_remote_get( $url );
483 -
484 - if ( is_array( $response ) )
739 + // If response is valid JSON and contains the core gbp key
740 + if ( $json !== null && isset( $json['gbp'] ) )
485 741 {
486 - $body = wp_remote_retrieve_body( $response );
742 + $exchange_rates_array = $json['gbp'];
487 743
488 - preg_match("/<span class=bld>(.*)<\/span>/", $body, $converted);
489 -
490 - if ( isset($converted[1]) && $converted[1] != '' )
744 + foreach ( $countries as $country )
491 745 {
492 - $converted = preg_replace("/[^0-9.]/", "", $converted[1]);
746 + $currency_code = $country['currency_code'];
493 747
494 - if ( $converted != '' )
748 + // If we haven't already got this currency and it's not GBP
749 + if (!isset($exchange_rates[$currency_code]) && $currency_code != 'GBP')
495 750 {
496 - $exchangeRate = $converted;
497 - $exchange_rates[$to] = $exchangeRate;
751 + // If this currency is in the list we received from the API
752 + if ( isset( $exchange_rates_array[strtolower( $currency_code )] ) )
753 + {
754 + $exchange_rates[$currency_code] = (string)$exchange_rates_array[strtolower( $currency_code )];
755 + }
498 756 }
499 757 }
500 758 }
501 - else
502 - {
759 + }
760 + }
503 761
504 - }
762 + // Only update the settings if the API call was successful and we got exchange rates, or if there were none set previously
763 + if ( !empty( $exchange_rates ) || empty( $previous_exchange_rates ) )
764 + {
765 + $exchange_rates['GBP'] = "1.0000";
766 + update_option( 'propertyhive_currency_exchange_rates', $exchange_rates );
767 + update_option( 'propertyhive_currency_exchange_rates_updated', gmdate("Y-m-d") );
768 + }
505 769
506 - if ( $exchangeRate == '' && isset($previous_exchange_rates[$to]) )
507 - {
508 - // if for some reason we get here and don't have an exchange rate
509 - $exchange_rates[$to] = $previous_exchange_rates[$to];
510 - }
511 - }
512 - }
513 - $exchange_rates['GBP'] = "1.0000";
514 - update_option( 'propertyhive_currency_exchange_rates', $exchange_rates );
515 - update_option( 'propertyhive_currency_exchange_rates_updated', date("Y-m-d") );
770 + do_action('propertyhive_exchange_rates_updated', $exchange_rates);
516 771
517 - // Loop through all on market properties and update _actual_price meta value to be price in GBP
772 + // Loop through all on market properties and update _price_actual meta value to be price in GBP
518 773 $args = array(
519 774 'post_type' => 'property',
775 + 'fields' => 'ids',
520 776 'post_status' => 'publish',
777 + // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query -- Currency recalculation must select all published on-market properties outside GB using their stored market/country metadata.
521 778 'meta_query' => array(
522 779 array(
523 780 'key' => '_on_market',
524 781 'value' => 'yes',
782 + ),
783 + array(
784 + 'key' => '_address_country',
785 + 'value' => 'GB',
786 + 'compare' => '!=',
525 787 )
526 788 ),
527 789 'nopaging' => true,
790 + 'orderby' => 'rand', // order by rand incase there are lots of properties and it times out, at least they should eventually all get processed
528 791 );
529 792 $property_query = new WP_Query($args);
530 793
531 794 if ($property_query->have_posts())
@@ -542,5 +805,5 @@
542 805
543 806 }
544 807 }
545 808
546 -}
809 +}