| 1 |
<?php |
| 2 |
/** |
| 3 |
* @package VikBooking |
| 4 |
* @subpackage com_vikbooking |
| 5 |
* @author Alessio Gaggii - e4j - Extensionsforjoomla.com |
| 6 |
* @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved. |
| 7 |
* @license GNU General Public License version 2 or later; see LICENSE |
| 8 |
* @link https://vikwp.com |
| 9 |
*/ |
| 10 |
|
| 11 |
defined('ABSPATH') or die('No script kiddies please!'); |
| 12 |
|
| 13 |
class VboCurrencyConverter |
| 14 |
{ |
| 15 |
/** |
| 16 |
* The currency code on which the rates are based |
| 17 |
* |
| 18 |
* @var string |
| 19 |
*/ |
| 20 |
protected $from_currency; |
| 21 |
|
| 22 |
/** |
| 23 |
* The desired currency code for conversion |
| 24 |
* |
| 25 |
* @var string |
| 26 |
*/ |
| 27 |
protected $to_currency; |
| 28 |
|
| 29 |
/** |
| 30 |
* A list of numbers (rates) to convert |
| 31 |
* |
| 32 |
* @var array |
| 33 |
*/ |
| 34 |
protected $prices; |
| 35 |
|
| 36 |
/** |
| 37 |
* The formatting values for numbers |
| 38 |
* |
| 39 |
* @var array |
| 40 |
*/ |
| 41 |
protected $format; |
| 42 |
|
| 43 |
/** |
| 44 |
* A map of symbols and decimals for the various currency codes |
| 45 |
* |
| 46 |
* @var array |
| 47 |
*/ |
| 48 |
protected $currencymap; |
| 49 |
|
| 50 |
/** |
| 51 |
* The error message(s) occurred during the processes |
| 52 |
* |
| 53 |
* @var string |
| 54 |
*/ |
| 55 |
protected $error; |
| 56 |
|
| 57 |
/** |
| 58 |
* The list of supported currencies. |
| 59 |
* |
| 60 |
* @var array |
| 61 |
* @since 1.15.4 (J) - 1.5.10 (WP) |
| 62 |
*/ |
| 63 |
protected $currency_names = array( |
| 64 |
'AED' => 'AED - United Arab Emirates Dirham', |
| 65 |
'AFN' => 'AFN - Afghan Afghani', |
| 66 |
'ALL' => 'ALL - Albanian Lek', |
| 67 |
'AMD' => 'AMD - Armenian Dram', |
| 68 |
'ANG' => 'ANG - Netherlands Antillean Gulden', |
| 69 |
'AOA' => 'AOA - Angolan Kwanza', |
| 70 |
'ARS' => 'ARS - Argentine Peso', |
| 71 |
'AUD' => 'AUD - Australian Dollar', |
| 72 |
'AWG' => 'AWG - Aruban Florin', |
| 73 |
'AZN' => 'AZN - Azerbaijani Manat', |
| 74 |
'BAM' => 'BAM - Bosnia and Herzegovina Mark', |
| 75 |
'BBD' => 'BBD - Barbadian Dollar', |
| 76 |
'BDT' => 'BDT - Bangladeshi Taka', |
| 77 |
'BGN' => 'BGN - Bulgarian Lev', |
| 78 |
'BHD' => 'BHD - Bahraini Dinar', |
| 79 |
'BIF' => 'BIF - Burundian Franc', |
| 80 |
'BMD' => 'BMD - Bermudian Dollar', |
| 81 |
'BND' => 'BND - Brunei Dollar', |
| 82 |
'BOB' => 'BOB - Bolivian Boliviano', |
| 83 |
'BRL' => 'BRL - Brazilian Real', |
| 84 |
'BSD' => 'BSD - Bahamian Dollar', |
| 85 |
'BWP' => 'BWP - Botswana Pula', |
| 86 |
'BZD' => 'BZD - Belize Dollar', |
| 87 |
'CAD' => 'CAD - Canadian Dollar', |
| 88 |
'CDF' => 'CDF - Congolese Franc', |
| 89 |
'CHF' => 'CHF - Swiss Franc', |
| 90 |
'CLP' => 'CLP - Chilean Peso', |
| 91 |
'CNY' => 'CNY - Chinese Renminbi Yuan', |
| 92 |
'COP' => 'COP - Colombian Peso', |
| 93 |
'CRC' => 'CRC - Costa Rican Colón', |
| 94 |
'CVE' => 'CVE - Cape Verdean Escudo', |
| 95 |
'CZK' => 'CZK - Czech Koruna', |
| 96 |
'DJF' => 'DJF - Djiboutian Franc', |
| 97 |
'DKK' => 'DKK - Danish Krone', |
| 98 |
'DOP' => 'DOP - Dominican Peso', |
| 99 |
'DZD' => 'DZD - Algerian Dinar', |
| 100 |
'EEK' => 'EEK - Estonian Kroon', |
| 101 |
'EGP' => 'EGP - Egyptian Pound', |
| 102 |
'ETB' => 'ETB - Ethiopian Birr', |
| 103 |
'EUR' => 'EUR - Euro', |
| 104 |
'FJD' => 'FJD - Fijian Dollar', |
| 105 |
'FKP' => 'FKP - Falkland Islands Pound', |
| 106 |
'GBP' => 'GBP - British Pound', |
| 107 |
'GEL' => 'GEL - Georgian Lari', |
| 108 |
'GIP' => 'GIP - Gibraltar Pound', |
| 109 |
'GMD' => 'GMD - Gambian Dalasi', |
| 110 |
'GNF' => 'GNF - Guinean Franc', |
| 111 |
'GTQ' => 'GTQ - Guatemalan Quetzal', |
| 112 |
'GYD' => 'GYD - Guyanese Dollar', |
| 113 |
'HKD' => 'HKD - Hong Kong Dollar', |
| 114 |
'HNL' => 'HNL - Honduran Lempira', |
| 115 |
'HRK' => 'HRK - Croatian Kuna', |
| 116 |
'HTG' => 'HTG - Haitian Gourde', |
| 117 |
'HUF' => 'HUF - Hungarian Forint', |
| 118 |
'IDR' => 'IDR - Indonesian Rupiah', |
| 119 |
'ILS' => 'ILS - Israeli New Sheqel', |
| 120 |
'INR' => 'INR - Indian Rupee', |
| 121 |
'ISK' => 'ISK - Icelandic Króna', |
| 122 |
'JMD' => 'JMD - Jamaican Dollar', |
| 123 |
'JPY' => 'JPY - Japanese Yen', |
| 124 |
'JOD' => 'JOD - Jordanian Dinar', |
| 125 |
'KES' => 'KES - Kenyan Shilling', |
| 126 |
'KGS' => 'KGS - Kyrgyzstani Som', |
| 127 |
'KHR' => 'KHR - Cambodian Riel', |
| 128 |
'KMF' => 'KMF - Comorian Franc', |
| 129 |
'KRW' => 'KRW - South Korean Won', |
| 130 |
'KYD' => 'KYD - Cayman Islands Dollar', |
| 131 |
'KZT' => 'KZT - Kazakhstani Tenge', |
| 132 |
'KWD' => 'KWD - Kuwaiti Dinar', |
| 133 |
'LAK' => 'LAK - Lao Kip', |
| 134 |
'LBP' => 'LBP - Lebanese Pound', |
| 135 |
'LKR' => 'LKR - Sri Lankan Rupee', |
| 136 |
'LRD' => 'LRD - Liberian Dollar', |
| 137 |
'LSL' => 'LSL - Lesotho Loti', |
| 138 |
'LTL' => 'LTL - Lithuanian Litas', |
| 139 |
'LVL' => 'LVL - Latvian Lats', |
| 140 |
'MAD' => 'MAD - Moroccan Dirham', |
| 141 |
'MDL' => 'MDL - Moldovan Leu', |
| 142 |
'MGA' => 'MGA - Malagasy Ariary', |
| 143 |
'MKD' => 'MKD - Macedonian Denar', |
| 144 |
'MNT' => 'MNT - Mongolian Tögrög', |
| 145 |
'MOP' => 'MOP - Macanese Pataca', |
| 146 |
'MRU' => 'MRU - Mauritanian Ouguiya', |
| 147 |
'MUR' => 'MUR - Mauritian Rupee', |
| 148 |
'MVR' => 'MVR - Maldivian Rufiyaa', |
| 149 |
'MWK' => 'MWK - Malawian Kwacha', |
| 150 |
'MXN' => 'MXN - Mexican Peso', |
| 151 |
'MYR' => 'MYR - Malaysian Ringgit', |
| 152 |
'MZN' => 'MZN - Mozambican Metical', |
| 153 |
'NAD' => 'NAD - Namibian Dollar', |
| 154 |
'NGN' => 'NGN - Nigerian Naira', |
| 155 |
'NIO' => 'NIO - Nicaraguan Córdoba', |
| 156 |
'NOK' => 'NOK - Norwegian Krone', |
| 157 |
'NPR' => 'NPR - Nepalese Rupee', |
| 158 |
'NZD' => 'NZD - New Zealand Dollar', |
| 159 |
'OMR' => 'OMR - Omani Rial', |
| 160 |
'PAB' => 'PAB - Panamanian Balboa', |
| 161 |
'PEN' => 'PEN - Peruvian Nuevo Sol', |
| 162 |
'PGK' => 'PGK - Papua New Guinean Kina', |
| 163 |
'PHP' => 'PHP - Philippine Peso', |
| 164 |
'PKR' => 'PKR - Pakistani Rupee', |
| 165 |
'PLN' => 'PLN - Polish Złoty', |
| 166 |
'PYG' => 'PYG - Paraguayan Guaraní', |
| 167 |
'QAR' => 'QAR - Qatari Riyal', |
| 168 |
'RON' => 'RON - Romanian Leu', |
| 169 |
'RSD' => 'RSD - Serbian Dinar', |
| 170 |
'RUB' => 'RUB - Russian Ruble', |
| 171 |
'RWF' => 'RWF - Rwandan Franc', |
| 172 |
'SAR' => 'SAR - Saudi Riyal', |
| 173 |
'SBD' => 'SBD - Solomon Islands Dollar', |
| 174 |
'SCR' => 'SCR - Seychellois Rupee', |
| 175 |
'SEK' => 'SEK - Swedish Krona', |
| 176 |
'SGD' => 'SGD - Singapore Dollar', |
| 177 |
'SHP' => 'SHP - Saint Helenian Pound', |
| 178 |
'SLL' => 'SLL - Sierra Leonean Leone', |
| 179 |
'SOS' => 'SOS - Somali Shilling', |
| 180 |
'SRD' => 'SRD - Surinamese Dollar', |
| 181 |
'STD' => 'STD - São Tomé and Príncipe Dobra', |
| 182 |
'SVC' => 'SVC - Salvadoran Colón', |
| 183 |
'SZL' => 'SZL - Swazi Lilangeni', |
| 184 |
'THB' => 'THB - Thai Baht', |
| 185 |
'TJS' => 'TJS - Tajikistani Somoni', |
| 186 |
'TOP' => 'TOP - Tongan Paʻanga', |
| 187 |
'TRY' => 'TRY - Turkish Lira', |
| 188 |
'TTD' => 'TTD - Trinidad and Tobago Dollar', |
| 189 |
'TWD' => 'TWD - New Taiwan Dollar', |
| 190 |
'TZS' => 'TZS - Tanzanian Shilling', |
| 191 |
'UAH' => 'UAH - Ukrainian Hryvnia', |
| 192 |
'UGX' => 'UGX - Ugandan Shilling', |
| 193 |
'USD' => 'USD - United States Dollar', |
| 194 |
'UYU' => 'UYU - Uruguayan Peso', |
| 195 |
'UZS' => 'UZS - Uzbekistani Som', |
| 196 |
'VEF' => 'VEF - Venezuelan Bolívar', |
| 197 |
'VND' => 'VND - Vietnamese Đồng', |
| 198 |
'VUV' => 'VUV - Vanuatu Vatu', |
| 199 |
'WST' => 'WST - Samoan Tala', |
| 200 |
'XAF' => 'XAF - Central African Cfa Franc', |
| 201 |
'XCD' => 'XCD - East Caribbean Dollar', |
| 202 |
'XOF' => 'XOF - West African Cfa Franc', |
| 203 |
'XPF' => 'XPF - Cfp Franc', |
| 204 |
'YER' => 'YER - Yemeni Rial', |
| 205 |
'ZAR' => 'ZAR - South African Rand', |
| 206 |
'ZMW' => 'ZMW - Zambian Kwacha', |
| 207 |
'TND' => 'TND - Tunisian dinar', |
| 208 |
); |
| 209 |
|
| 210 |
/** |
| 211 |
* The suffix of the method for exchaning the rates |
| 212 |
* |
| 213 |
* @var string |
| 214 |
*/ |
| 215 |
public $api_provider; |
| 216 |
|
| 217 |
/** |
| 218 |
* Class constructor |
| 219 |
* |
| 220 |
* @param string $from current currency |
| 221 |
* @param string $to desired currency |
| 222 |
* @param array $numbers list of numbers |
| 223 |
* @param array $format formatting options |
| 224 |
*/ |
| 225 |
public function __construct($from, $to, $numbers, $format) |
| 226 |
{ |
| 227 |
$this->from_currency = $from; |
| 228 |
$this->to_currency = $to; |
| 229 |
$this->prices = $numbers; |
| 230 |
$this->format = $format; |
| 231 |
$this->error = ''; |
| 232 |
$this->currencymap = array( |
| 233 |
'AED' => array('symbol' => '1583;.إ'), |
| 234 |
'ALL' => array('symbol' => '76'), |
| 235 |
'AFN' => array('symbol' => '1547'), |
| 236 |
'ARS' => array('symbol' => '36'), |
| 237 |
'AWG' => array('symbol' => '402'), |
| 238 |
'AUD' => array('symbol' => '36'), |
| 239 |
'AZN' => array('symbol' => '1084'), |
| 240 |
'BSD' => array('symbol' => '36'), |
| 241 |
'BBD' => array('symbol' => '36'), |
| 242 |
'BYR' => array('symbol' => '112', 'decimals' => 0), |
| 243 |
'BZD' => array('symbol' => '66'), |
| 244 |
'BMD' => array('symbol' => '36'), |
| 245 |
'BOB' => array('symbol' => '36'), |
| 246 |
'BAM' => array('symbol' => '75'), |
| 247 |
'BWP' => array('symbol' => '80'), |
| 248 |
'BGN' => array('symbol' => '1083'), |
| 249 |
'BHD' => array('decimals' => 3), |
| 250 |
'BRL' => array('symbol' => '82'), |
| 251 |
'BND' => array('symbol' => '36'), |
| 252 |
'KHR' => array('symbol' => '6107'), |
| 253 |
'CAD' => array('symbol' => '36'), |
| 254 |
'KYD' => array('symbol' => '36'), |
| 255 |
'CLP' => array('symbol' => '36', 'decimals' => 0), |
| 256 |
'CNY' => array('symbol' => '165'), |
| 257 |
'COP' => array('symbol' => '36', 'decimals' => 3), |
| 258 |
'CRC' => array('symbol' => '8353'), |
| 259 |
'CVE' => array('symbol' => '36', 'decimals' => 2), |
| 260 |
'HRK' => array('symbol' => '107'), |
| 261 |
'CUP' => array('symbol' => '8369'), |
| 262 |
'CZK' => array('symbol' => '75'), |
| 263 |
'DKK' => array('symbol' => '107'), |
| 264 |
'DOP' => array('symbol' => '82'), |
| 265 |
'XCD' => array('symbol' => '36'), |
| 266 |
'EGP' => array('symbol' => '163'), |
| 267 |
'SVC' => array('symbol' => '36'), |
| 268 |
'EEK' => array('symbol' => '107'), |
| 269 |
'EUR' => array('symbol' => '8364'), |
| 270 |
'FKP' => array('symbol' => '163'), |
| 271 |
'FJD' => array('symbol' => '36'), |
| 272 |
'GHC' => array('symbol' => '162'), |
| 273 |
'GIP' => array('symbol' => '163'), |
| 274 |
'GTQ' => array('symbol' => '81'), |
| 275 |
'GGP' => array('symbol' => '163'), |
| 276 |
'GYD' => array('symbol' => '36'), |
| 277 |
'HNL' => array('symbol' => '76'), |
| 278 |
'HKD' => array('symbol' => '36'), |
| 279 |
'HUF' => array('symbol' => '70', 'decimals' => 0), |
| 280 |
'ISK' => array('symbol' => '107', 'decimals' => 0), |
| 281 |
'IDR' => array('symbol' => '82'), |
| 282 |
'INR' => array('symbol' => '8377'), |
| 283 |
'IRR' => array('symbol' => '65020'), |
| 284 |
'IMP' => array('symbol' => '163'), |
| 285 |
'ILS' => array('symbol' => '8362'), |
| 286 |
'JMD' => array('symbol' => '74'), |
| 287 |
'JPY' => array('symbol' => '165', 'decimals' => 0), |
| 288 |
'JEP' => array('symbol' => '163'), |
| 289 |
'KZT' => array('symbol' => '1083'), |
| 290 |
'KPW' => array('symbol' => '8361'), |
| 291 |
'KRW' => array('symbol' => '8361', 'decimals' => 0), |
| 292 |
'KGS' => array('symbol' => '1083'), |
| 293 |
'KWD' => array('decimals' => 3), |
| 294 |
'LAK' => array('symbol' => '8365'), |
| 295 |
'LVL' => array('symbol' => '76'), |
| 296 |
'LBP' => array('symbol' => '163'), |
| 297 |
'LRD' => array('symbol' => '36'), |
| 298 |
'LTL' => array('symbol' => '76'), |
| 299 |
'MKD' => array('symbol' => '1076'), |
| 300 |
'MYR' => array('symbol' => '82'), |
| 301 |
'MUR' => array('symbol' => '8360'), |
| 302 |
'MXN' => array('symbol' => '36'), |
| 303 |
'MNT' => array('symbol' => '8366'), |
| 304 |
'MZN' => array('symbol' => '77', 'decimals' => 0), |
| 305 |
'NAD' => array('symbol' => '36'), |
| 306 |
'NPR' => array('symbol' => '8360'), |
| 307 |
'ANG' => array('symbol' => '402'), |
| 308 |
'NZD' => array('symbol' => '36'), |
| 309 |
'NIO' => array('symbol' => '67'), |
| 310 |
'NGN' => array('symbol' => '8358'), |
| 311 |
'NOK' => array('symbol' => '107'), |
| 312 |
'OMR' => array('symbol' => '65020', 'decimals' => 3), |
| 313 |
'PKR' => array('symbol' => '8360'), |
| 314 |
'PAB' => array('symbol' => '66'), |
| 315 |
'PYG' => array('symbol' => '71', 'decimals' => 0), |
| 316 |
'PEN' => array('symbol' => '83'), |
| 317 |
'PHP' => array('symbol' => '8369'), |
| 318 |
'PLN' => array('symbol' => '122'), |
| 319 |
'QAR' => array('symbol' => '65020'), |
| 320 |
'RON' => array('symbol' => '108;ei'), |
| 321 |
'RUB' => array('symbol' => '1088'), |
| 322 |
'SHP' => array('symbol' => '163'), |
| 323 |
'SAR' => array('symbol' => '65020'), |
| 324 |
'RSD' => array('symbol' => '1044'), |
| 325 |
'SCR' => array('symbol' => '8360'), |
| 326 |
'SGD' => array('symbol' => '36'), |
| 327 |
'SBD' => array('symbol' => '36'), |
| 328 |
'SOS' => array('symbol' => '83'), |
| 329 |
'ZAR' => array('symbol' => '82'), |
| 330 |
'LKR' => array('symbol' => '8360'), |
| 331 |
'SEK' => array('symbol' => '107'), |
| 332 |
'CHF' => array('symbol' => '8355'), |
| 333 |
'SRD' => array('symbol' => '36'), |
| 334 |
'SYP' => array('symbol' => '163'), |
| 335 |
'TWD' => array('symbol' => '78'), |
| 336 |
'THB' => array('symbol' => '3647'), |
| 337 |
'TTD' => array('symbol' => '84'), |
| 338 |
'TRY' => array('symbol' => '8378', 'decimals' => 0), |
| 339 |
'UAH' => array('symbol' => '8372'), |
| 340 |
'GBP' => array('symbol' => '163'), |
| 341 |
'USD' => array('symbol' => '36'), |
| 342 |
'UYU' => array('symbol' => '36'), |
| 343 |
'UZS' => array('symbol' => '1083'), |
| 344 |
'VEF' => array('symbol' => '66'), |
| 345 |
'VND' => array('symbol' => '8363'), |
| 346 |
'YER' => array('symbol' => '65020'), |
| 347 |
'ZWD' => array('symbol' => '90'), |
| 348 |
'TND' => array('decimals' => 3), |
| 349 |
); |
| 350 |
|
| 351 |
/** |
| 352 |
* This is the API's Provider that the Class will use to retrieve the conversion rate. |
| 353 |
* The method callProvider{$suffix}() will be called by the getConversionRate() method. |
| 354 |
* |
| 355 |
* Supported Providers: ECB, FloatRates (used as callback by ECB) |
| 356 |
* Deprecated Providers: fixer, yahoo |
| 357 |
* |
| 358 |
* @see getConversionRate() |
| 359 |
*/ |
| 360 |
$this->api_provider = 'ECB'; |
| 361 |
} |
| 362 |
|
| 363 |
/** |
| 364 |
* Deprecated call to the Yahoo Finance APIs (shut down in November 2017). |
| 365 |
* Retrieve the conversion rate between base currency and symbol currency. |
| 366 |
* |
| 367 |
* @return mixed false in case of errors, float in case of success |
| 368 |
* |
| 369 |
* @deprecated since November 2017 |
| 370 |
*/ |
| 371 |
protected function callProviderYahoo() |
| 372 |
{ |
| 373 |
//http://finance.yahoo.com/currency-converter |
| 374 |
$apis_url = 'http://finance.yahoo.com/d/quotes.csv?e=.csv&f=sl1d1t1&s='. $this->from_currency . $this->to_currency .'=X'; |
| 375 |
$fp = @fopen($apis_url, 'r'); |
| 376 |
if ($fp) { |
| 377 |
$data = ''; |
| 378 |
while (!feof($fp)) { |
| 379 |
$data .= fread($fp, 4096); |
| 380 |
} |
| 381 |
if (!empty($data)) { |
| 382 |
$data = str_replace("\"", "", $data); |
| 383 |
$rate_info = explode(',', $data); |
| 384 |
if (strlen($rate_info[1]) > 0 && floatval($rate_info[1]) > 0.00) { |
| 385 |
return (float)$rate_info[1]; |
| 386 |
} |
| 387 |
} |
| 388 |
} |
| 389 |
return false; |
| 390 |
} |
| 391 |
|
| 392 |
/** |
| 393 |
* Call to the Fixer Foreign exchange rates and currency conversion API. |
| 394 |
* Retrieve the conversion rate between base currency and symbol currency. |
| 395 |
* |
| 396 |
* @return mixed false in case of errors, float in case of success |
| 397 |
* |
| 398 |
* @deprecated since June 2018 |
| 399 |
*/ |
| 400 |
protected function callProviderFixer() |
| 401 |
{ |
| 402 |
//http://fixer.io/ |
| 403 |
$apis_url = 'https://api.fixer.io/latest?'.($this->from_currency != 'EUR' ? 'base='.$this->from_currency.'&' : '').'symbols='.$this->to_currency; |
| 404 |
$fp = @fopen($apis_url, 'r'); |
| 405 |
if ($fp) { |
| 406 |
$data = ''; |
| 407 |
while (!feof($fp)) { |
| 408 |
$data .= fread($fp, 4096); |
| 409 |
} |
| 410 |
$resp = json_decode($data); |
| 411 |
if (is_object($resp) && property_exists($resp, 'rates') && is_object($resp->rates)) { |
| 412 |
$prop = $this->to_currency; |
| 413 |
if (property_exists($resp->rates, $prop) && floatval($resp->rates->$prop) > 0.00) { |
| 414 |
return (float)$resp->rates->$prop; |
| 415 |
} |
| 416 |
} |
| 417 |
} |
| 418 |
return false; |
| 419 |
} |
| 420 |
|
| 421 |
/** |
| 422 |
* Call to the European Central Bank exchange rates XML data. |
| 423 |
* Retrieve the conversion rate between base currency and symbol currency. |
| 424 |
* The exchange rates data is cached by downloading the file every day. |
| 425 |
* |
| 426 |
* @return mixed float exchange rate, or false in case of errors |
| 427 |
* |
| 428 |
* @since June 2018 |
| 429 |
*/ |
| 430 |
protected function callProviderECB() |
| 431 |
{ |
| 432 |
// load exchange rates |
| 433 |
$exchange_rates = $this->loadECBRates(); |
| 434 |
if (!$exchange_rates) { |
| 435 |
// something went wrong |
| 436 |
return false; |
| 437 |
} |
| 438 |
|
| 439 |
if (!isset($exchange_rates[$this->to_currency]) && $this->to_currency != 'EUR') { |
| 440 |
|
| 441 |
/** |
| 442 |
* The ECB only supports a few currencies, so as a fallback we also |
| 443 |
* use the provider floatrates to see if they support the to_currency |
| 444 |
* |
| 445 |
* @since October 2018 |
| 446 |
*/ |
| 447 |
$exchange_rates = $this->loadFloatRatesDotComRates(); |
| 448 |
if (!$exchange_rates) { |
| 449 |
// something went wrong |
| 450 |
return false; |
| 451 |
} |
| 452 |
// |
| 453 |
|
| 454 |
if (!isset($exchange_rates[$this->to_currency])) { |
| 455 |
// we do not have the exchange rate to this currency. |
| 456 |
$this->setError('exchange rates to this currency not supported ('.__LINE__.')'); |
| 457 |
return false; |
| 458 |
} |
| 459 |
} |
| 460 |
|
| 461 |
if ($this->from_currency == 'EUR') { |
| 462 |
// converting from EUR to a known currency |
| 463 |
return $this->to_currency == 'EUR' ? 1 : $exchange_rates[$this->to_currency]; |
| 464 |
} |
| 465 |
|
| 466 |
$from_changed = false; |
| 467 |
if (!isset($exchange_rates[$this->from_currency])) { |
| 468 |
/** |
| 469 |
* The ECB only supports a few currencies, so as a fallback we also |
| 470 |
* use the provider floatrates to see if they support the from_currency |
| 471 |
* |
| 472 |
* @since November 2018 |
| 473 |
*/ |
| 474 |
$exchange_rates = $this->loadFloatRatesDotComRates(strtolower($this->from_currency)); |
| 475 |
if (!$exchange_rates) { |
| 476 |
// something went wrong |
| 477 |
return false; |
| 478 |
} |
| 479 |
|
| 480 |
if (isset($exchange_rates[$this->to_currency])) { |
| 481 |
// we set the exchange rate for the from_currency to 1 |
| 482 |
$exchange_rates[$this->from_currency] = 1; |
| 483 |
} |
| 484 |
|
| 485 |
// the from_currency has changed |
| 486 |
$from_changed = true; |
| 487 |
} |
| 488 |
|
| 489 |
if (!isset($exchange_rates[$this->from_currency])) { |
| 490 |
// converting from this currency is not allowed as we do not know it |
| 491 |
$this->setError('converting from this currency not allowed because of missing exchange rates ('.__LINE__.')'); |
| 492 |
return false; |
| 493 |
} |
| 494 |
|
| 495 |
if ($this->from_currency == $this->to_currency) { |
| 496 |
// equal currencies should be stopped before this method |
| 497 |
return 1; |
| 498 |
} |
| 499 |
|
| 500 |
if ($from_changed && isset($exchange_rates[$this->to_currency])) { |
| 501 |
// we have loaded the exchange rates from the requested from_currency (loadFloatRatesDotComRates()) |
| 502 |
return $exchange_rates[$this->to_currency]; |
| 503 |
} |
| 504 |
|
| 505 |
if ($this->to_currency == 'EUR' && !$from_changed) { |
| 506 |
// converting to EUR from a known currency |
| 507 |
return (1 / $exchange_rates[$this->from_currency]); |
| 508 |
} |
| 509 |
|
| 510 |
// conversion is not involving EUR, but both currencies are known (from : to = 1 : x) |
| 511 |
return ($exchange_rates[$this->to_currency] / $exchange_rates[$this->from_currency]); |
| 512 |
} |
| 513 |
|
| 514 |
/** |
| 515 |
* Call to the European Central Bank exchange rates XML data. |
| 516 |
* Retrieves the conversion rates of all currencies by caching the results, |
| 517 |
* and by returning an array map with key-value pairs of currencycode-rate from EUR. |
| 518 |
* |
| 519 |
* @return mixed false in case of errors, array in case of success |
| 520 |
* |
| 521 |
* @since June 2018 |
| 522 |
*/ |
| 523 |
protected function loadECBRates() |
| 524 |
{ |
| 525 |
$rates_doc = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml'; |
| 526 |
$cache_rates = dirname(__FILE__) . DIRECTORY_SEPARATOR . date('Y-m-d') . '_ecb.xml'; |
| 527 |
$xml_data = ''; |
| 528 |
|
| 529 |
if (!is_file($cache_rates)) { |
| 530 |
// cached rates are not available, attempt to download the information |
| 531 |
$expcache = glob(dirname(__FILE__) . DIRECTORY_SEPARATOR . '*_ecb.xml'); |
| 532 |
// remove old expired cache files |
| 533 |
foreach ($expcache as $expf) { |
| 534 |
if (is_file($expf)) { |
| 535 |
@unlink($expf); |
| 536 |
} |
| 537 |
} |
| 538 |
|
| 539 |
/** |
| 540 |
* Remote files should be fetched using CURL rather than through fopen($foo, 'r'); |
| 541 |
* |
| 542 |
* @since 1.15.2 (J) - 1.5.5 (WP) |
| 543 |
*/ |
| 544 |
$http = new JHttp; |
| 545 |
|
| 546 |
try { |
| 547 |
$http_resp = $http->get($rates_doc); |
| 548 |
} catch (Exception $e) { |
| 549 |
// request failed |
| 550 |
$this->setError($e->getMessage()); |
| 551 |
return false; |
| 552 |
} |
| 553 |
|
| 554 |
if ($http_resp->code != 200) { |
| 555 |
// cannot read exchange rates from external XML file |
| 556 |
$this->setError('cannot read exchange rates from external XML file ('.__LINE__.')'); |
| 557 |
return false; |
| 558 |
} |
| 559 |
|
| 560 |
$xml_data = $http_resp->body; |
| 561 |
|
| 562 |
// store cache file |
| 563 |
$fp = @fopen($cache_rates, 'w+'); |
| 564 |
if (!$fp) { |
| 565 |
// cannot open cache file for writing. Exit. |
| 566 |
$this->setError('cannot open cache file for writing ('.__LINE__.')'); |
| 567 |
return false; |
| 568 |
} |
| 569 |
fwrite($fp, $xml_data); |
| 570 |
fclose($fp); |
| 571 |
} |
| 572 |
|
| 573 |
if (!is_file($cache_rates)) { |
| 574 |
// could not load rates |
| 575 |
$this->setError('could not load rates ('.__LINE__.')'); |
| 576 |
return false; |
| 577 |
} |
| 578 |
|
| 579 |
if (empty($xml_data)) { |
| 580 |
// read cached rates from XML file |
| 581 |
$fp = @fopen($cache_rates, 'r'); |
| 582 |
if (!$fp) { |
| 583 |
// cannot read exchange rates from cached XML file |
| 584 |
$this->setError('cannot read exchange rates from cached XML file ('.__LINE__.')'); |
| 585 |
return false; |
| 586 |
} |
| 587 |
$xml_data = ''; |
| 588 |
while (!feof($fp)) { |
| 589 |
$xml_data .= fread($fp, 4096); |
| 590 |
} |
| 591 |
fclose($fp); |
| 592 |
} |
| 593 |
|
| 594 |
$exchange_obj = simplexml_load_string($xml_data); |
| 595 |
if (!$exchange_obj instanceof SimpleXMLElement) { |
| 596 |
// this file does not contain correct XML |
| 597 |
$this->setError('the file does not contain valid XML ('.__LINE__.')'); |
| 598 |
return false; |
| 599 |
} |
| 600 |
|
| 601 |
$exchange_rates = array(); |
| 602 |
foreach ($exchange_obj->Cube->Cube->Cube as $exrate) { |
| 603 |
$attr = $exrate->attributes(); |
| 604 |
$currency = (string)$attr->currency; |
| 605 |
$rate = (float)$attr->rate; |
| 606 |
if ($rate > 0.00) { |
| 607 |
$exchange_rates[$currency] = $rate; |
| 608 |
} |
| 609 |
} |
| 610 |
|
| 611 |
return $exchange_rates; |
| 612 |
} |
| 613 |
|
| 614 |
/** |
| 615 |
* Call to Floatrates.com exchange rates XML data. |
| 616 |
* Retrieve the conversion rate between base currency and symbol currency. |
| 617 |
* The exchange rates data is cached by downloading the file every day. |
| 618 |
* |
| 619 |
* If this was used as default and only provider, then the from currency would |
| 620 |
* be passed to the rates loading method to fetch the exact XML feed for the |
| 621 |
* from currency. If the feed was not available, false would be returned. |
| 622 |
* |
| 623 |
* @return mixed float exchange rate, or false in case of errors |
| 624 |
* |
| 625 |
* @since October 2018 |
| 626 |
*/ |
| 627 |
protected function callProviderFloatRates() |
| 628 |
{ |
| 629 |
// load exchange rates |
| 630 |
$exchange_rates = $this->loadFloatRatesDotComRates($this->from_currency); |
| 631 |
if (!$exchange_rates) { |
| 632 |
// something went wrong |
| 633 |
return false; |
| 634 |
} |
| 635 |
|
| 636 |
if (!isset($exchange_rates[$this->to_currency])) { |
| 637 |
// we do not have the exchange rate to this currency. |
| 638 |
$this->setError('exchange rates to this currency not supported ('.__LINE__.')'); |
| 639 |
return false; |
| 640 |
} |
| 641 |
|
| 642 |
if ($this->from_currency == $this->to_currency) { |
| 643 |
// equal currencies should be stopped before this method |
| 644 |
return 1; |
| 645 |
} |
| 646 |
|
| 647 |
// conversion is not involving EUR, but both currencies are known (from : to = 1 : x) |
| 648 |
return $exchange_rates[$this->to_currency]; |
| 649 |
} |
| 650 |
|
| 651 |
/** |
| 652 |
* Call to the Floatrates.com XML feed. |
| 653 |
* Retrieves the conversion rates of all currencies by caching the results, and |
| 654 |
* by returning an array map with key-value pairs of currencycode-rate from EUR. |
| 655 |
* |
| 656 |
* @param [string] $currency the base currency 3 chars code, if specified |
| 657 |
* attempt to load the exact $currency.xml feed |
| 658 |
* |
| 659 |
* @return mixed false in case of errors, array in case of success |
| 660 |
* key (currency code) = value (exchange rate) |
| 661 |
* |
| 662 |
* @since October 2018 |
| 663 |
*/ |
| 664 |
protected function loadFloatRatesDotComRates($currency = '') |
| 665 |
{ |
| 666 |
$feed_name = empty($currency) ? 'eur' : substr(strtolower($currency), 0, 3); |
| 667 |
$rates_doc = "http://www.floatrates.com/daily/{$feed_name}.xml"; |
| 668 |
$cache_rates = dirname(__FILE__) . DIRECTORY_SEPARATOR . date('Y-m-d') . "{$feed_name}" . '_floatrates.xml'; |
| 669 |
$xml_data = ''; |
| 670 |
|
| 671 |
if (!is_file($cache_rates)) { |
| 672 |
// cached rates are not available, attempt to download the information |
| 673 |
$expcache = glob(dirname(__FILE__) . DIRECTORY_SEPARATOR . '*_floatrates.xml'); |
| 674 |
// remove old expired cache files |
| 675 |
foreach ($expcache as $expf) { |
| 676 |
if (is_file($expf)) { |
| 677 |
@unlink($expf); |
| 678 |
} |
| 679 |
} |
| 680 |
|
| 681 |
/** |
| 682 |
* Remote files should be fetched using CURL rather than through fopen($foo, 'r'); |
| 683 |
* |
| 684 |
* @since 1.15.2 (J) - 1.5.5 (WP) |
| 685 |
*/ |
| 686 |
$http = new JHttp; |
| 687 |
|
| 688 |
try { |
| 689 |
$http_resp = $http->get($rates_doc); |
| 690 |
} catch (Exception $e) { |
| 691 |
// request failed |
| 692 |
$this->setError($e->getMessage()); |
| 693 |
return false; |
| 694 |
} |
| 695 |
|
| 696 |
if ($http_resp->code != 200) { |
| 697 |
// cannot read exchange rates from external XML file |
| 698 |
$this->setError('cannot read exchange rates from external XML file ('.__LINE__.')'); |
| 699 |
return false; |
| 700 |
} |
| 701 |
|
| 702 |
$xml_data = $http_resp->body; |
| 703 |
|
| 704 |
// store cache file |
| 705 |
$fp = @fopen($cache_rates, 'w+'); |
| 706 |
if (!$fp) { |
| 707 |
// cannot open cache file for writing. Exit. |
| 708 |
$this->setError('cannot open cache file for writing ('.__LINE__.')'); |
| 709 |
return false; |
| 710 |
} |
| 711 |
fwrite($fp, $xml_data); |
| 712 |
fclose($fp); |
| 713 |
} |
| 714 |
|
| 715 |
if (!is_file($cache_rates)) { |
| 716 |
// could not load rates |
| 717 |
$this->setError('could not load rates ('.__LINE__.')'); |
| 718 |
return false; |
| 719 |
} |
| 720 |
|
| 721 |
if (empty($xml_data)) { |
| 722 |
// read cached rates from XML file |
| 723 |
$fp = @fopen($cache_rates, 'r'); |
| 724 |
if (!$fp) { |
| 725 |
// cannot read exchange rates from cached XML file |
| 726 |
$this->setError('cannot read exchange rates from cached XML file ('.__LINE__.')'); |
| 727 |
return false; |
| 728 |
} |
| 729 |
$xml_data = ''; |
| 730 |
while (!feof($fp)) { |
| 731 |
$xml_data .= fread($fp, 4096); |
| 732 |
} |
| 733 |
fclose($fp); |
| 734 |
} |
| 735 |
|
| 736 |
$exchange_obj = simplexml_load_string($xml_data); |
| 737 |
if (!$exchange_obj instanceof SimpleXMLElement) { |
| 738 |
// this file does not contain correct XML |
| 739 |
$this->setError('this file does not contain correct XML ('.__LINE__.')'); |
| 740 |
return false; |
| 741 |
} |
| 742 |
|
| 743 |
$exchange_rates = array(); |
| 744 |
foreach ($exchange_obj->item as $exrate) { |
| 745 |
if (!property_exists($exrate, 'targetCurrency') || !property_exists($exrate, 'exchangeRate')) { |
| 746 |
continue; |
| 747 |
} |
| 748 |
$currency = (string)$exrate->targetCurrency; |
| 749 |
/** |
| 750 |
* All conversion rates exceeding 1 thousand are formatted as strings, with a thousand separator |
| 751 |
* character (comma ","), and so we must get rid of the formatting to obtain a true float value. |
| 752 |
* |
| 753 |
* @since 1.14.3 (J) - 1.4.3 (WP) |
| 754 |
*/ |
| 755 |
$rate = floatval(str_replace(',', '', (string)$exrate->exchangeRate)); |
| 756 |
// |
| 757 |
if ($rate > 0.00) { |
| 758 |
$exchange_rates[$currency] = $rate; |
| 759 |
} |
| 760 |
} |
| 761 |
|
| 762 |
if (!count($exchange_rates)) { |
| 763 |
// invalid XML structure |
| 764 |
$this->setError('invalid exchange rates structure ('.__LINE__.')'); |
| 765 |
return false; |
| 766 |
} |
| 767 |
|
| 768 |
return $exchange_rates; |
| 769 |
} |
| 770 |
|
| 771 |
/** |
| 772 |
* Makes a float number from a given string number. |
| 773 |
* |
| 774 |
* @param string $num the formatted number to exchange. |
| 775 |
* |
| 776 |
* @return float the number to exchange. |
| 777 |
*/ |
| 778 |
protected function makeFloat($num) |
| 779 |
{ |
| 780 |
$floated = $num; |
| 781 |
if (is_array($this->format) && count($this->format) == 3) { |
| 782 |
$decimals = ''; |
| 783 |
if (strstr($num, $this->format[1]) !== false) { |
| 784 |
$decimals = substr($num, ((int)$this->format[0] - ((int)$this->format[0] * 2))); |
| 785 |
} |
| 786 |
$nosep = str_replace($this->format[1], '', $num); |
| 787 |
$nosep = str_replace($this->format[2], '', $nosep); |
| 788 |
$newdecimals = ''; |
| 789 |
if ((int)$this->format[0] > 0 && !empty($decimals)) { |
| 790 |
$nosep = substr_replace($nosep, '', (strlen($decimals) - (strlen($decimals) * 2))); |
| 791 |
$decimalsabs = abs($decimals); |
| 792 |
if ($decimalsabs > 0) { |
| 793 |
$newdecimals = $decimals; |
| 794 |
} |
| 795 |
} |
| 796 |
$floated = floatval($nosep.(!empty($newdecimals) ? '.'.$newdecimals : '')); |
| 797 |
} |
| 798 |
|
| 799 |
return $floated; |
| 800 |
} |
| 801 |
|
| 802 |
/** |
| 803 |
* Finds and returns an appropriate symbol for the currency converted. |
| 804 |
* |
| 805 |
* @param string $custom_currency Optional currency ISO name to read. |
| 806 |
* |
| 807 |
* @return string The symbol to return to the controller for the exchanged rates. |
| 808 |
* |
| 809 |
* @since 1.17.2 (J) - 1.7.2 (WP) added argument $custom_currency. |
| 810 |
*/ |
| 811 |
protected function currencySymbol($custom_currency = null) |
| 812 |
{ |
| 813 |
// the currency to evaluate |
| 814 |
$use_currency = $custom_currency ?: $this->to_currency; |
| 815 |
|
| 816 |
/** |
| 817 |
* Trigger event to allow third party plugins to return specific information for a currency. |
| 818 |
* |
| 819 |
* @since 1.16.0 (J) - 1.6.0 (WP) |
| 820 |
*/ |
| 821 |
$custom_conv = VBOFactory::getPlatform()->getDispatcher()->filter('onGetCurrencyDataVikBooking', [$use_currency]); |
| 822 |
if (is_array($custom_conv) && !empty($custom_conv[0]['symbol'])) { |
| 823 |
return $custom_conv[0]['symbol']; |
| 824 |
} |
| 825 |
|
| 826 |
if (isset($this->currencymap[$use_currency]['symbol'])) { |
| 827 |
$symbol = '&#'.$this->currencymap[$use_currency]['symbol'].';'; |
| 828 |
} else { |
| 829 |
$symbol = $use_currency; |
| 830 |
} |
| 831 |
|
| 832 |
return $symbol; |
| 833 |
} |
| 834 |
|
| 835 |
/** |
| 836 |
* Formats a number according to the values passed to the constructor |
| 837 |
* |
| 838 |
* @param mixed $num the number to format |
| 839 |
* |
| 840 |
* @return string the formatted number for display |
| 841 |
*/ |
| 842 |
protected function currencyFormat($num) |
| 843 |
{ |
| 844 |
// obtain the "to currency" formatting data options |
| 845 |
list($num_decimals, $decimals_sep, $thousands_sep) = $this->getCurrencyFormatData(); |
| 846 |
|
| 847 |
// return the formatted amount according to currency settings |
| 848 |
return number_format($num, $num_decimals, $decimals_sep, $thousands_sep); |
| 849 |
} |
| 850 |
|
| 851 |
/** |
| 852 |
* Returns a list of currency formatting data (number of decimals, separators). |
| 853 |
* |
| 854 |
* @param string $custom_currency Optional currency ISO name to check. |
| 855 |
* |
| 856 |
* @return array Linear list of formatting data. |
| 857 |
* |
| 858 |
* @since 1.17.2 (J) - 1.7.2 (WP) |
| 859 |
*/ |
| 860 |
protected function getCurrencyFormatData($custom_currency = null) |
| 861 |
{ |
| 862 |
// the currency to evaluate |
| 863 |
$use_currency = $custom_currency ?: $this->to_currency; |
| 864 |
|
| 865 |
$num_decimals = (int) $this->format[0]; |
| 866 |
|
| 867 |
if (isset($this->currencymap[$use_currency])) { |
| 868 |
if (isset($this->currencymap[$use_currency]['decimals'])) { |
| 869 |
// use the currency related number of decimals |
| 870 |
$num_decimals = $this->currencymap[$use_currency]['decimals']; |
| 871 |
} else { |
| 872 |
// default to 2 decimal points when the currency exists by default |
| 873 |
$num_decimals = 2; |
| 874 |
} |
| 875 |
} |
| 876 |
|
| 877 |
// decimals and thousands separators for this currency |
| 878 |
$decimals_sep = $this->format[1]; |
| 879 |
$thousands_sep = $this->format[2]; |
| 880 |
|
| 881 |
/** |
| 882 |
* Trigger event to allow third party plugins to return specific information for a currency. |
| 883 |
* |
| 884 |
* @since 1.16.0 (J) - 1.6.0 (WP) |
| 885 |
*/ |
| 886 |
$custom_conv = VBOFactory::getPlatform()->getDispatcher()->filter('onGetCurrencyDataVikBooking', [$use_currency]); |
| 887 |
if (is_array($custom_conv) && !empty($custom_conv[0]) && is_array($custom_conv[0])) { |
| 888 |
// override currency information for formatting the amounts |
| 889 |
$num_decimals = isset($custom_conv[0]['decimals']) && is_int($custom_conv[0]['decimals']) ? $custom_conv[0]['decimals'] : $num_decimals; |
| 890 |
$decimals_sep = isset($custom_conv[0]['decimals_separator']) && is_string($custom_conv[0]['decimals_separator']) ? $custom_conv[0]['decimals_separator'] : $decimals_sep; |
| 891 |
$thousands_sep = isset($custom_conv[0]['thousands_separator']) && is_string($custom_conv[0]['thousands_separator']) ? $custom_conv[0]['thousands_separator'] : $thousands_sep; |
| 892 |
} |
| 893 |
|
| 894 |
return [ |
| 895 |
$num_decimals, |
| 896 |
$decimals_sep, |
| 897 |
$thousands_sep, |
| 898 |
]; |
| 899 |
} |
| 900 |
|
| 901 |
/** |
| 902 |
* Obtains a list of currency data options for the requested currency. |
| 903 |
* |
| 904 |
* @param string $currency The currency ISO name (3-char) to get. |
| 905 |
* |
| 906 |
* @return array Associative currency options, or empty list. |
| 907 |
* |
| 908 |
* @since 1.17.2 (J) - 1.7.2 (WP) |
| 909 |
*/ |
| 910 |
public function getCurrencyData($currency) |
| 911 |
{ |
| 912 |
if (!$this->currencyExists($currency)) { |
| 913 |
return []; |
| 914 |
} |
| 915 |
|
| 916 |
// get the currency symbol |
| 917 |
$symbol = $this->currencySymbol($currency); |
| 918 |
|
| 919 |
// obtain the currency formatting data options |
| 920 |
list($num_decimals, $decimals_sep, $thousands_sep) = $this->getCurrencyFormatData($currency); |
| 921 |
|
| 922 |
return [ |
| 923 |
'name' => $this->currency_names[$currency] ?? $currency, |
| 924 |
'symbol' => $symbol, |
| 925 |
'decimals' => $num_decimals, |
| 926 |
'decimals_sep' => $decimals_sep, |
| 927 |
'thousands_sep' => $thousands_sep, |
| 928 |
]; |
| 929 |
} |
| 930 |
|
| 931 |
/** |
| 932 |
* Main method called by the controller after invoking the class. The same method is also |
| 933 |
* called by other classes of VBO, and keeps associative arrays of rates to exchange. |
| 934 |
* |
| 935 |
* @param bool $get_floats true to only return the plain exchanged rates. |
| 936 |
* |
| 937 |
* @return array the array of rates converted or an empty array in case of error |
| 938 |
* |
| 939 |
* @since 1.15.0 (J) - 1.5.0 (WP) added argument to return plain exchanged floats. |
| 940 |
*/ |
| 941 |
public function convert($get_floats = false) |
| 942 |
{ |
| 943 |
$conversion = []; |
| 944 |
|
| 945 |
if (!is_array($this->prices) || !$this->prices) { |
| 946 |
return $conversion; |
| 947 |
} |
| 948 |
|
| 949 |
// get the conversion rate between the currencies |
| 950 |
$conv_rate = $this->getConversionRate(); |
| 951 |
|
| 952 |
if ($conv_rate === false) { |
| 953 |
// return the original array |
| 954 |
return $conversion; |
| 955 |
} |
| 956 |
|
| 957 |
// get the currency symbol of the exchanged currency |
| 958 |
$conv_symbol = $this->currencySymbol(); |
| 959 |
|
| 960 |
// exchange values |
| 961 |
foreach ($this->prices as $k => $price) { |
| 962 |
// get the base price to exchange |
| 963 |
if ($get_floats) { |
| 964 |
// given price is expected to be already a raw float |
| 965 |
$base_price = (float)$price; |
| 966 |
} else { |
| 967 |
// given price has been formatted already |
| 968 |
$base_price = $this->makeFloat($price); |
| 969 |
} |
| 970 |
|
| 971 |
// apply conversion |
| 972 |
$exchanged = $base_price * $conv_rate; |
| 973 |
|
| 974 |
if ($get_floats) { |
| 975 |
// inject just the exchanged rate |
| 976 |
$conversion[$k] = $exchanged; |
| 977 |
} else { |
| 978 |
// build the exchanged information |
| 979 |
$conversion[$k]['symbol'] = $conv_symbol; |
| 980 |
$conversion[$k]['price'] = $this->currencyFormat($exchanged); |
| 981 |
} |
| 982 |
} |
| 983 |
|
| 984 |
return $conversion; |
| 985 |
} |
| 986 |
|
| 987 |
/** |
| 988 |
* Generic method called by convert() to invoke a provider and get |
| 989 |
* the necessary exchange rates for applying the conversions. |
| 990 |
* |
| 991 |
* @see convert() |
| 992 |
* |
| 993 |
* @return mixed float, the exchange rate for the given from and to currencies |
| 994 |
* in case of success. Boolean false otherwise. |
| 995 |
* |
| 996 |
* @since 1.15.0 (J) - 1.5.0 (WP) the visibility is public, but used to be private before. |
| 997 |
*/ |
| 998 |
public function getConversionRate() |
| 999 |
{ |
| 1000 |
$session = JFactory::getSession(); |
| 1001 |
$ses_conversions = $session->get('vboCurrencyConversions', ''); |
| 1002 |
$conversions_made = array(); |
| 1003 |
$data = ''; |
| 1004 |
$conv_rate = false; |
| 1005 |
|
| 1006 |
/** |
| 1007 |
* Trigger event to allow third party plugins to return a specific conversion rate for these currencies. |
| 1008 |
* |
| 1009 |
* @since 1.16.0 (J) - 1.6.0 (WP) |
| 1010 |
*/ |
| 1011 |
$custom_conv = VBOFactory::getPlatform()->getDispatcher()->filter('onGetConversionRateVikBooking', [$this->from_currency, $this->to_currency]); |
| 1012 |
if (is_array($custom_conv) && !empty($custom_conv[0]) && (is_int($custom_conv[0]) || is_float($custom_conv[0]))) { |
| 1013 |
return $custom_conv[0]; |
| 1014 |
} |
| 1015 |
|
| 1016 |
if (is_array($ses_conversions) && count($ses_conversions)) { |
| 1017 |
$conversions_made = $ses_conversions; |
| 1018 |
if (isset($ses_conversions[$this->from_currency.'_'.$this->to_currency])) { |
| 1019 |
if (strlen($ses_conversions[$this->from_currency.'_'.$this->to_currency]) && floatval($ses_conversions[$this->from_currency.'_'.$this->to_currency]) > 0.00) { |
| 1020 |
$conv_rate = $ses_conversions[$this->from_currency.'_'.$this->to_currency]; |
| 1021 |
} |
| 1022 |
} |
| 1023 |
} |
| 1024 |
|
| 1025 |
if ($conv_rate === false) { |
| 1026 |
// use an external provider for getting the conversion rate |
| 1027 |
$api_method = 'callProvider'.str_replace(' ', '', ucwords($this->api_provider)); |
| 1028 |
if (!method_exists($this, $api_method)) { |
| 1029 |
return false; |
| 1030 |
} |
| 1031 |
$conv_rate = $this->{$api_method}(); |
| 1032 |
if ($conv_rate !== false) { |
| 1033 |
// cache conversion rate into the session |
| 1034 |
$conversions_made[$this->from_currency.'_'.$this->to_currency] = $conv_rate; |
| 1035 |
$session->set('vboCurrencyConversions', $conversions_made); |
| 1036 |
} |
| 1037 |
|
| 1038 |
} |
| 1039 |
|
| 1040 |
return $conv_rate; |
| 1041 |
} |
| 1042 |
|
| 1043 |
/** |
| 1044 |
* Tells whether a currency name exists in the map-list. |
| 1045 |
* |
| 1046 |
* @param string $currency_name the currency name to check. |
| 1047 |
* |
| 1048 |
* @return bool true if available, or false. |
| 1049 |
* |
| 1050 |
* @since 1.15.0 (J) - 1.5.0 (WP) |
| 1051 |
*/ |
| 1052 |
public function currencyExists($currency_name) |
| 1053 |
{ |
| 1054 |
if (isset($this->currencymap[$currency_name])) { |
| 1055 |
return true; |
| 1056 |
} |
| 1057 |
|
| 1058 |
/** |
| 1059 |
* Trigger event to allow third party plugins to register a custom currency code. |
| 1060 |
* |
| 1061 |
* @since 1.16.0 (J) - 1.6.0 (WP) |
| 1062 |
*/ |
| 1063 |
$existing = VBOFactory::getPlatform()->getDispatcher()->filter('onCheckCurrencyExistsVikBooking', [$currency_name]); |
| 1064 |
if (is_array($existing) && in_array(true, $existing, true)) { |
| 1065 |
return true; |
| 1066 |
} |
| 1067 |
|
| 1068 |
return false; |
| 1069 |
} |
| 1070 |
|
| 1071 |
/** |
| 1072 |
* Overrides the prices to convert. |
| 1073 |
* |
| 1074 |
* @param array $prices the list of prices to convert. |
| 1075 |
* |
| 1076 |
* @return array the current list of prices to convert. |
| 1077 |
* |
| 1078 |
* @since 1.15.0 (J) - 1.5.0 (WP) |
| 1079 |
*/ |
| 1080 |
public function setPrices(array $prices = []) |
| 1081 |
{ |
| 1082 |
$this->prices = $prices; |
| 1083 |
|
| 1084 |
return $this->prices; |
| 1085 |
} |
| 1086 |
|
| 1087 |
/** |
| 1088 |
* Returns an associative list of currencies with code and name. |
| 1089 |
* |
| 1090 |
* @return array |
| 1091 |
* |
| 1092 |
* @since 1.15.4 (J) - 1.5.10 (WP) |
| 1093 |
*/ |
| 1094 |
public function getCurrencyNames() |
| 1095 |
{ |
| 1096 |
return $this->currency_names; |
| 1097 |
} |
| 1098 |
|
| 1099 |
/** |
| 1100 |
* Concatenates errors occurred during the execution |
| 1101 |
* |
| 1102 |
* @param string $err the error message |
| 1103 |
* |
| 1104 |
* @return void |
| 1105 |
*/ |
| 1106 |
protected function setError($err) |
| 1107 |
{ |
| 1108 |
$this->error .= $err . "\n"; |
| 1109 |
} |
| 1110 |
|
| 1111 |
/** |
| 1112 |
* Returns the errors occurred during the execution |
| 1113 |
* |
| 1114 |
* @return string the error message(s) |
| 1115 |
*/ |
| 1116 |
public function getError() |
| 1117 |
{ |
| 1118 |
return rtrim($this->error, "\n"); |
| 1119 |
} |
| 1120 |
} |
| 1121 |
|