* Copyright 2001-2012 Strangecode, LLC * * This file is part of The Strangecode Codebase. * * The Strangecode Codebase is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at your option) * any later version. * * The Strangecode Codebase is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * The Strangecode Codebase. If not, see . */ /** * Currency.inc.php * * Class to convert currency values. * * @author Quinn Comendant * @version 1.5 * * Example of use: --------------------------------------------------------------------- $currency = new Currency(); $currency->setParam(array('cache_dir' => COMMON_BASE . '/tmp/xcache')); echo $currency->getRage('eur', 'usd'); echo $currency->getValue(125.50, 'eur', 'usd'); --------------------------------------------------------------------- */ class Currency { // Configuration parameters for this object. var $_params = array( 'cache_result' => true, 'cache_dir' => '', 'cache_age' => 86400, // 24 hours. 'api_type' => 'json', // 'json' or 'soap'. 'api_url' => 'http://xurrency.com/api/%s/%s/%s', 'api_key' => '', ); /** * Cart constructor. */ function Currency($params=array()) { $app =& App::getInstance(); // Set custom parameters. $this->setParam($params); // Setup cache directory. if ($this->getParam('cache_result')) { if ('' == $this->getParam('cache_dir')) { // Use a sane default cache directory. $this->setParam(array('cache_dir' => '/tmp/xcache_' . md5(COMMON_BASE))); } if (!is_dir($this->getParam('cache_dir'))) { $app->logMsg(sprintf('Creating cache_dir: %s', $this->getParam('cache_dir')), LOG_INFO, __FILE__, __LINE__); if (!mkdir($this->getParam('cache_dir'))) { $app->logMsg(sprintf('Could not create cache_dir: %s', $this->getParam('cache_dir')), LOG_WARNING, __FILE__, __LINE__); } } } } /** * Set the params of this object. * * @param array $params Array of param keys and values to set. */ function setParam($params=null) { if (isset($params) && is_array($params)) { // Merge new parameters with old overriding only those passed. $this->_params = array_merge($this->_params, $params); } } /** * Return the value of a parameter, if it exists. * * @access public * @param string $param Which parameter to return. * @return mixed Configured parameter value. */ function getParam($param) { $app =& App::getInstance(); if (isset($this->_params[$param])) { return $this->_params[$param]; } else { $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__); return null; } } /* * Return the exchange value between the two given currencies for given amount. * * @access public * @param float $amount Base amount to convert from. * @param string $base 3-letter currency code to convert from. * @param string $target 3-letter currency code to convert to. * @return mixed Float converted currency value, or false on error. * @author Quinn Comendant * @version 1.0 * @since 05 May 2008 23:50:59 */ function getValue($amount, $base, $target) { if (false !== $rate = $this->getRate($base, $target)) { return abs($rate * $amount); } else { return false; } } /* * Return the currency conversion rate as a ratio. * * @access public * @param string $base 3-letter currency code to convert from. * @param string $target 3-letter currency code to convert to. * @return mixed Float exchange rate value, or false on error. * @author Quinn Comendant * @version 1.0 * @since 25 May 2011 01:26:24 */ function getRate($base, $target) { $app =& App::getInstance(); $cache_file_path = sprintf('%s/%s-to-%s', $this->getParam('cache_dir'), $base, $target); $cache_file_mtime = @filemtime($cache_file_path); if (!$this->getParam('cache_result') || !$cache_file_mtime || $cache_file_mtime < time() - $this->getParam('cache_age')) { // Get fresh data and create cached file if missing or expired. $app->logMsg(sprintf('Getting fresh currency exchange rate: %s-to-%s', $base, $target), LOG_DEBUG, __FILE__, __LINE__); $value = $this->_performAPICall(array( 'amount' => '1', 'base' => $base, 'target' => $target )); if (false === $value || !is_numeric($value)) { // Failed retrieving value. Use cached copy for now. $app->logMsg(sprintf('Failed getting currency exchange rate: %s-to-%s, using cached copy', $base, $target), LOG_NOTICE, __FILE__, __LINE__); if (!$value = file_get_contents($cache_file_path)) { $app->logMsg(sprintf('Failed reading cached exchange rate file: %s', $cache_file_path), LOG_ERR, __FILE__, __LINE__); return false; } } else if ($this->getParam('cache_result') && !filePutContents($cache_file_path, $value)) { $app->logMsg(sprintf('Failed writing to target rate file: %s', $cache_file_path), LOG_ERR, __FILE__, __LINE__); return false; } } else { $app->logMsg(sprintf('Getting cached currency exchange rate: %s-to-%s', $base, $target), LOG_DEBUG, __FILE__, __LINE__); if (!$value = file_get_contents($cache_file_path)) { $app->logMsg(sprintf('Failed reading target rate file: %s', $cache_file_path), LOG_ERR, __FILE__, __LINE__); return false; } } $app->logMsg(sprintf('Found currency exchange rate: %s-to-%s = %s', $base, $target, $value), LOG_DEBUG, __FILE__, __LINE__); return trim($value); } /** * @param string * @param array * @return mixed * @access private */ function _performAPICall($parameters=null) { $app =& App::getInstance(); switch ($this->getParam('api_type')) { case 'json' : $api_url = $this->getParam('api_url'); if ('' != $this->getParam('api_key')) { $api_url .= '?key=' . $this->getParam('api_key'); } $json_response = file_get_contents(sprintf($api_url, $parameters['base'], $parameters['target'], $parameters['amount'])); $json = json_decode($json_response); if (null === $json) { $app->logMsg(sprintf('Could not decode JSON response: %s', getDump($json_response)), LOG_WARNING, __FILE__, __LINE__); return false; } else if ($json->status === 'fail') { if ($json->code == 3) { $app->logMsg(sprintf('Xurrency error LimitReachedException: %s', $json->message), LOG_WARNING, __FILE__, __LINE__); } elseif ($json->code == 2) { $app->logMsg(sprintf('Xurrency error InvalidCurrencies: %s', $json->message), LOG_WARNING, __FILE__, __LINE__); } elseif ($json->code == 4 || $json->code == 5) { $app->logMsg(sprintf('Xurrency error InvalidKey: %s', $json->message), LOG_WARNING, __FILE__, __LINE__); } else { $app->logMsg(sprintf('Xurrency unknown error: %s', $json->message), LOG_WARNING, __FILE__, __LINE__); } return false; } else { return $json->result->value; } break; case 'soap' : // Xurrency doesn't appear to support SOAP anymore, but we'll leave this here in case it comes back. // Setup SOAP object. require_once 'SOAP/Client.php'; $soap_client = new SOAP_Client($this->getParam('api_url')); // Call API $result = $soap_client->call('getValue', $parameters); // Check for errors. if (PEAR::isError($result)) { $app->logMsg(sprintf('SOAP Pear error: %s', $result->getMessage()), LOG_WARNING, __FILE__, __LINE__); return false; } return $result; break; default : trigger_error('Unknown api_type: ' . $this->getParam('api_type'), E_USER_ERROR); die; break; } } } ?>