AeliaWCEU_VAT_AssistantExchange_Rates_IrishRevenueHTML_Model

Retrieves the exchange rates from the European Central Bank.

Defined (1)

The class is defined in the following location(s).

/src/lib/classes/exchange_rates/aelia-wc-exchangerates-irish-revenue-html.php  
  1. class Exchange_Rates_IrishRevenueHTML_Model extends \Aelia\WC\ExchangeRatesModel { 
  2. // @var string The URL template to use to get rates from Irish Revenue's website (parsing the HTML page) 
  3. private $irish_revenue_html_rates_url = 'http://www.revenue.ie/en/customs/businesses/importing/exchange-rates/'; 
  4.  
  5. // @var array Maps the currency names used by Irish Revenue with the corresponding codes. 
  6. protected $currency_names_map = array( 
  7. 'US Dollar' => 'USD',  
  8. 'Sterling' => 'GBP',  
  9. 'Japanese Yen' => 'JPY',  
  10. 'Swiss Franc' => 'CHF',  
  11. 'Danish Krone' => 'DKK',  
  12. 'Swedish Krona' => 'SEK',  
  13. 'Norwegian Krone' => 'NOK',  
  14. 'Czech Koruna' => 'CZK',  
  15. 'Hungarian Forint' => 'HUF',  
  16. 'Polish Zloty' => 'PLN',  
  17. 'Canadian Dollar' => 'CAD',  
  18. 'Australian Dollar' => 'AUD',  
  19. 'New Zealand Dollar' => 'NZD',  
  20. 'Chinese Renminbi' => 'RMB',  
  21. 'Hong Kong Dollar' => 'HKD',  
  22. 'Indonesian Rupiah' => 'IDR',  
  23. 'South Korean Won' => 'KRW',  
  24. 'Lithuanian Litas' => 'LTL',  
  25. 'Malaysian Ringgit' => 'MYR',  
  26. 'Philippines Peso' => 'PHP',  
  27. 'Romanian Leu' => 'RON',  
  28. 'Russian Rouble' => 'RUB',  
  29. 'Singapore Dollar' => 'SGD',  
  30. 'South African Rand' => 'ZAR',  
  31. 'Thailand Baht' => 'THB',  
  32. 'Turkish Lira' => 'TRY',  
  33. 'Bulgarian Lev' => 'BGN',  
  34. 'Croatian Kuna' => 'HRK',  
  35. 'Algerian Dinar' => 'DZD',  
  36. 'Bahrain Dinar' => 'BHD',  
  37. 'Botswana Pula' => 'BWP',  
  38. 'CFA Franc' => 'XAF',  
  39. 'Costa Rican Colon' => 'CRC',  
  40. 'Egyptian Pound' => 'EGP',  
  41. 'Ghana Cedi' => 'GHS',  
  42. 'Gibraltar Pound' => 'GIP',  
  43. 'Indian Rupee' => 'INR',  
  44. 'Iraqi Dinar' => 'IQD',  
  45. 'Israeli Shekel' => 'ILS',  
  46. 'Kenyan Shilling' => 'KES',  
  47. 'Kuwaiti Dinar' => 'KWD',  
  48. 'Lebanese Pound' => 'LBP',  
  49. 'Malawi Kwacha' => 'MWK',  
  50. 'Mexican Peso' => 'MXN',  
  51. 'Moroccan Dirham' => 'MAD',  
  52. 'Nigerian Naira' => 'NGN',  
  53. 'Pakistan Rupee' => 'PKR',  
  54. 'Qatar Riyal' => 'QAR',  
  55. 'Saudi Arabia Riyal' => 'SAR',  
  56. 'Sri Lankan Rupee' => 'LKR',  
  57. 'Syrian Pound' => 'SYP',  
  58. 'Taiwan Dollar' => 'TWD',  
  59. 'Tanzanian Shilling' => 'TZS',  
  60. 'Trinidad/Tobago Dollar' => 'TTD',  
  61. 'Tunisian Dinar' => 'TND',  
  62. 'UAE Dirham' => 'AED',  
  63. 'Yemen Rial' => 'YER',  
  64. 'Omani Rial' => 'OMR',  
  65. 'Venezuelan Bolivar Fuerte' => 'VEF',  
  66. 'Argentina Peso' => 'ARS',  
  67. 'Colombian Peso' => 'COP',  
  68. 'Bermuda Dollar' => 'BMD',  
  69. 'Brazil Real' => 'BRL',  
  70. 'Brunei Dollar' => 'BND',  
  71. 'Fiji Dollar' => 'FJD',  
  72. 'Namibia Dollar' => 'NAD',  
  73. 'Libyan Dinar' => 'LYD',  
  74. 'Chilean Peso' => 'CLP',  
  75. 'Vietnam Dong' => 'VND',  
  76. 'Peruvian New Sol' => 'PEN',  
  77. 'Iran Rial' => 'IRR',  
  78. 'Tonga is Paanga' => 'TOP',  
  79. 'Nepalese Rupee' => 'NPR',  
  80. 'Serbia Dinar' => 'RSD',  
  81. 'Icelandic Krona' => 'ISK',  
  82. 'Maur Rupee' => 'MUR',  
  83. 'Ukraine Hryvnia' => 'UAH',  
  84. ); 
  85.  
  86. /** 
  87. * Tranforms the exchange rates retrieved from Irish Revenue site into an array of 
  88. * currency code => exchange rate pairs. 
  89. * @param string $irish_revenue_rates_html The HTML received from Irish Revenue webpage. 
  90. * @retur array 
  91. */ 
  92. protected function decode_rates($irish_revenue_rates_html) { 
  93. $html = new \DOMDocument; 
  94.  
  95. // Transform the HTML from the Revenue page into a DOM object 
  96. $html->loadHTML($irish_revenue_rates_html); 
  97. //var_dump($html);die(); 
  98.  
  99. $exchange_rates_tmp = array(); 
  100. $xpath = new \DOMXPath($html); 
  101.  
  102. // The HTML is not only heave, but it also lacks clear identifiers for the 
  103. // exchange rate elements. We have to find the first currency denomination 
  104. // and move to its parent <tr> 
  105. $nodes = $xpath->query('//ancestor::tr[td[@headers="denomination"]]'); 
  106. foreach($nodes as $node) { 
  107. $values = array(); 
  108. foreach($node->childNodes as $child) { 
  109. $values[] = trim($child->nodeValue); 
  110. $values = array_filter($values); 
  111.  
  112. $currency_name = array_shift($values); 
  113. foreach($values as $rate) { 
  114. if(is_numeric($rate)) { 
  115. $exchange_rates_tmp[$currency_name] = $rate; 
  116.  
  117. $exchange_rates = array(); 
  118. foreach($exchange_rates_tmp as $currency_name => $rate) { 
  119. if(isset($this->currency_names_map[$currency_name])) { 
  120. $exchange_rates[$this->currency_names_map[$currency_name]] = $rate; 
  121. // Irish Revenue feed is based against EUR, but it doesn't contain such currency. We 
  122. // can safely add it manually, with an exchange rate of 1 
  123. $exchange_rates['EUR'] = 1; 
  124. return $exchange_rates; 
  125.  
  126. /** 
  127. * Fetches all exchange rates from IrishRevenueHTML API. 
  128. * @return object|bool An object containing the response from Open Exchange, or 
  129. * False in case of failure. 
  130. */ 
  131. private function fetch_all_rates() { 
  132. try { 
  133. $response = \Httpful\Request::get($this->irish_revenue_html_rates_url) 
  134. ->expectsHtml() 
  135. ->send(); 
  136.  
  137. // Debug 
  138. //var_dump("IrishRevenueHTML RATES RESPONSE:", $response); die(); 
  139. if($response->hasErrors()) { 
  140. // OpenExchangeRates sends error details in response body 
  141. if($response->hasBody()) { 
  142. $response_data = $response->body; 
  143.  
  144. $this->add_error(self::ERR_ERROR_RETURNED,  
  145. sprintf(__('Error returned fetching Irish Revenue HTML page. ' . 
  146. 'Error code: %s. Error message: %s - %s.',  
  147. Definitions::TEXT_DOMAIN),  
  148. $response_data->status,  
  149. $response_data->message,  
  150. $response_data->description)); 
  151. return false; 
  152. return $response->body; 
  153. catch(Exception $e) { 
  154. $this->add_error(self::ERR_EXCEPTION_OCCURRED,  
  155. sprintf(__('Exception occurred while retrieving the exchange rates from Irish Revenue HTML page. ' . 
  156. 'Error message: %s.',  
  157. Definitions::TEXT_DOMAIN),  
  158. $e->getMessage())); 
  159. return null; 
  160.  
  161. /** 
  162. * Returns current exchange rates for the specified currency. 
  163. * @param string base_currency The base currency. 
  164. * @return array An array of Currency => Exchange Rate pairs. 
  165. */ 
  166. private function current_rates($base_currency) { 
  167. if(empty($this->_current_rates) || 
  168. $this->_base_currency != $base_currency) { 
  169.  
  170. $cache_key = md5(get_class($this)) . $base_currency; 
  171. // Try to get the cached rates for the specified base currency, if any 
  172. $this->_current_rates = $this->get_cached_exchange_rates($cache_key); 
  173. if(!empty($this->_current_rates)) { 
  174. return $this->_current_rates; 
  175.  
  176. // Fetch exchange rates 
  177. $irishrevenue_exchange_rates = $this->fetch_all_rates(); 
  178. if($irishrevenue_exchange_rates === false) { 
  179. return null; 
  180.  
  181. // Debug 
  182. //var_dump($irishrevenue_exchange_rates);die(); 
  183.  
  184. // IrishRevenueHTML rates are returned as JSON representation of an array of objects. 
  185. // We need to transform it into an array of currency => rate pairs 
  186. $exchange_rates = $this->decode_rates($irishrevenue_exchange_rates); 
  187. if(!is_array($exchange_rates)) { 
  188. $this->add_error(self::ERR_UNEXPECTED_ERROR_FETCHING_EXCHANGE_RATES,  
  189. __('An unexpected error occurred while fetching exchange rates ' . 
  190. 'from IrishRevenueHTML. The most common cause of this issue is the ' . 
  191. 'absence of PHP CURL extension. Please make sure that ' . 
  192. 'PHP CURL is installed and configured in your system.',  
  193. Definitions::TEXT_DOMAIN)); 
  194. return array(); 
  195.  
  196. // Since we didn't get the exchange rates related to the base currency,  
  197. // but in the default base currency used by OpenExchange, we need to 
  198. // recalculate them against the base currency we would like to use 
  199. $this->_current_rates = $this->rebase_rates($exchange_rates, $base_currency); 
  200. $this->_base_currency = $base_currency; 
  201.  
  202. // Cache the exchange rates 
  203. $this->cache_exchange_rates($cache_key, $this->_current_rates); 
  204. return $this->_current_rates; 
  205.  
  206. /** 
  207. * Recaculates the exchange rates using another base currency. This method 
  208. * is invoked because the rates fetched from IrishRevenueHTML are relative to BitCoin,  
  209. * but another currency is most likely is used by WooCommerce. 
  210. * @param array exchange_rates The exchange rates retrieved from IrishRevenueHTML. 
  211. * @param string base_currency The base currency against which the rates should 
  212. * be recalculated. 
  213. * @return array An array of currency => exchange rate pairs. 
  214. */ 
  215. private function rebase_rates(array $exchange_rates, $base_currency) { 
  216. $recalc_rate = get_value($base_currency, $exchange_rates); 
  217. //var_dump($base_currency, $exchange_rates); 
  218.  
  219. if(empty($recalc_rate)) { 
  220. $this->add_error(self::ERR_BASE_CURRENCY_NOT_FOUND,  
  221. sprintf(__('Could not rebase rates against base currency "%s". ' . 
  222. 'Currency not found in data returned by IrishRevenueHTML.',  
  223. Definitions::TEXT_DOMAIN),  
  224. $base_currency)); 
  225. return null; 
  226.  
  227. $result = array(); 
  228. foreach($exchange_rates as $currency => $rate) { 
  229. $result[$currency] = $rate / $recalc_rate; 
  230.  
  231. // Debug 
  232. //var_dump($result); die(); 
  233. return $result; 
  234.  
  235. /** 
  236. * Returns the exchange rate of a currency in respect to a base currency. 
  237. * @param string base_currency The code of the base currency. 
  238. * @param string currency The code of the currency for which to find the 
  239. * Exchange Rate. 
  240. * @return float 
  241. */ 
  242. protected function get_rate($base_currency, $currency) { 
  243. $current_rates = $this->current_rates($base_currency); 
  244. return get_value($currency, $current_rates); 
  245.  
  246. /** 
  247. * Class constructor. 
  248. * @param array An array of Settings that can be used to override the ones 
  249. * currently saved in the configuration. 
  250. * @return Exchange_Rates_IrishRevenueHTML_Model. 
  251. */ 
  252. public function __construct($settings = null) { 
  253. parent::__construct($settings);