source: branches/eli_branch/lib/Currency.inc.php @ 530

Last change on this file since 530 was 439, checked in by anonymous, 11 years ago

added public and private keywords to all properties and methods, changed old classname constructor function to construct, removed more ?> closing tags

File size: 10.4 KB
Line 
1<?php
2/**
3 * The Strangecode Codebase - a general application development framework for PHP
4 * For details visit the project site: <http://trac.strangecode.com/codebase/>
5 * Copyright 2001-2012 Strangecode, LLC
6 *
7 * This file is part of The Strangecode Codebase.
8 *
9 * The Strangecode Codebase is free software: you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as published by the
11 * Free Software Foundation, either version 3 of the License, or (at your option)
12 * any later version.
13 *
14 * The Strangecode Codebase is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 * details.
18 *
19 * You should have received a copy of the GNU General Public License along with
20 * The Strangecode Codebase. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23/**
24 * Currency.inc.php
25 *
26 * Class to convert currency values.
27 *
28 * @author  Quinn Comendant <quinn@strangecode.com>
29 * @version 1.5
30 *
31 * Example of use:
32---------------------------------------------------------------------
33$currency = new Currency();
34$currency->setParam(array('cache_dir' => COMMON_BASE . '/tmp/xcache'));
35echo $currency->getRage('eur', 'usd');
36echo $currency->getValue(125.50, 'eur', 'usd');
37---------------------------------------------------------------------
38 */
39 
40class Currency {
41
42    // Configuration parameters for this object.
43    private $_params = array(
44        'cache_result' => true,
45        'cache_dir' => '',
46        'cache_age' => 86400, // 24 hours.
47        'api' => 'ecb', // 'xurrency' or 'ecb'. Add other APIs under the _performAPICall() method.
48        'api_key' => '', // Used only by xurrency API.
49    );
50   
51    /**
52     * Cart constructor.
53     */
54    public function __construct($params=array())
55    {
56        $app =& App::getInstance();
57
58        // Set custom parameters.
59        $this->setParam($params);
60       
61        // Setup cache directory.
62        if ($this->getParam('cache_result')) {
63            if ('' == $this->getParam('cache_dir')) {
64                // Use a sane default cache directory.
65                $this->setParam(array('cache_dir' => '/tmp/xcache_' . md5(COMMON_BASE)));
66            }
67            if (!is_dir($this->getParam('cache_dir'))) {
68                $app->logMsg(sprintf('Creating cache_dir: %s', $this->getParam('cache_dir')), LOG_INFO, __FILE__, __LINE__);               
69                if (!mkdir($this->getParam('cache_dir'))) {
70                    $app->logMsg(sprintf('Could not create cache_dir: %s', $this->getParam('cache_dir')), LOG_WARNING, __FILE__, __LINE__);               
71                }
72            }
73        }
74    }
75
76    /**
77     * Set the params of this object.
78     *
79     * @param  array $params   Array of param keys and values to set.
80     */
81    public function setParam($params=null)
82    {
83        if (isset($params) && is_array($params)) {
84            // Merge new parameters with old overriding only those passed.
85            $this->_params = array_merge($this->_params, $params);
86        }
87    }
88
89    /**
90     * Return the value of a parameter, if it exists.
91     *
92     * @access public
93     * @param string $param        Which parameter to return.
94     * @return mixed               Configured parameter value.
95     */
96    public function getParam($param)
97    {
98        $app =& App::getInstance();
99   
100        if (isset($this->_params[$param])) {
101            return $this->_params[$param];
102        } else {
103            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__);
104            return null;
105        }
106    }
107   
108    /*
109    * Return the exchange value between the two given currencies for given amount.
110    *
111    * @access   public
112    * @param    float   $amount Base amount to convert from.
113    * @param    string  $base   3-letter currency code to convert from.
114    * @param    string  $target 3-letter currency code to convert to.
115    * @return   mixed   Float converted currency value, or false on error.
116    * @author   Quinn Comendant <quinn@strangecode.com>
117    * @version  1.0
118    * @since    05 May 2008 23:50:59
119    */
120    public function getValue($amount, $base, $target)
121    {
122        if (false !== $rate = $this->getRate($base, $target)) {
123            return abs($rate * $amount);           
124        } else {
125            return false;
126        }
127    }
128   
129    /*
130    * Return the currency conversion rate as a ratio.
131    *
132    * @access   public
133    * @param    string  $base   3-letter currency code to convert from.
134    * @param    string  $target 3-letter currency code to convert to.
135    * @return   mixed   Float exchange rate value, or false on error.
136    * @author   Quinn Comendant <quinn@strangecode.com>
137    * @version  1.0
138    * @since    25 May 2011 01:26:24
139    */
140    public function getRate($base, $target)
141    {
142        $app =& App::getInstance();
143
144        $cache_file_path = sprintf('%s/%s-to-%s', $this->getParam('cache_dir'), $base, $target);
145        $cache_file_mtime = @filemtime($cache_file_path);
146        if (!$this->getParam('cache_result') || !$cache_file_mtime || $cache_file_mtime < time() - $this->getParam('cache_age')) {
147            // Get fresh data and create cached file if missing or expired.
148            $app->logMsg(sprintf('Getting fresh currency exchange rate: %s-to-%s', $base, $target), LOG_DEBUG, __FILE__, __LINE__);
149            $value = $this->_performAPICall(array(
150                'amount' => '1',
151                'base' => $base,
152                'target' => $target
153            ));
154            if (false === $value || !is_numeric($value)) {
155                // Failed retrieving value. Use cached copy for now.
156                $app->logMsg(sprintf('Failed getting currency exchange rate: %s-to-%s, using cached copy', $base, $target), LOG_NOTICE, __FILE__, __LINE__);
157                if (!$value = @file_get_contents($cache_file_path)) {
158                    $app->logMsg(sprintf('Failed reading cached exchange rate file: %s', $cache_file_path), LOG_ERR, __FILE__, __LINE__);
159                    return false;
160                }
161            } else if ($this->getParam('cache_result') && !filePutContents($cache_file_path, $value)) {
162                $app->logMsg(sprintf('Failed writing to target rate file: %s', $cache_file_path), LOG_ERR, __FILE__, __LINE__);
163                return false;
164            }
165        } else {
166            $app->logMsg(sprintf('Getting cached currency exchange rate: %s-to-%s', $base, $target), LOG_DEBUG, __FILE__, __LINE__);
167            if (!$value = file_get_contents($cache_file_path)) {
168                $app->logMsg(sprintf('Failed reading target rate file: %s', $cache_file_path), LOG_ERR, __FILE__, __LINE__);
169                return false;
170            }
171        }
172        $app->logMsg(sprintf('Found currency exchange rate: %s-to-%s = %s', $base, $target, $value), LOG_DEBUG, __FILE__, __LINE__);
173        return trim($value);
174    }
175   
176    /**
177     * @param  string
178     * @param  array
179     * @return mixed
180     * @access private
181     */
182    private function _performAPICall($parameters=null)
183    {
184        $app =& App::getInstance();
185
186        switch ($this->getParam('api')) {
187        case 'xurrency' :
188            $api_url = 'http://xurrency.com/api/%s/%s/%s';
189            if ('' != $this->getParam('api_key')) {
190                $api_url .= '?key=' . $this->getParam('api_key');
191            }
192            $json_response = file_get_contents(sprintf($api_url, $parameters['base'], $parameters['target'], $parameters['amount']));
193            $json = json_decode($json_response);
194            if (null === $json) {
195                $app->logMsg(sprintf('Could not decode JSON response: %s', getDump($json_response)), LOG_WARNING, __FILE__, __LINE__);
196                return false;
197            } else if ($json->status === 'fail') {
198                if ($json->code == 3) {
199                    $app->logMsg(sprintf('Xurrency error LimitReachedException: %s', $json->message), LOG_WARNING, __FILE__, __LINE__);
200                } elseif ($json->code == 2) {
201                    $app->logMsg(sprintf('Xurrency error InvalidCurrencies: %s', $json->message), LOG_WARNING, __FILE__, __LINE__);
202                } elseif ($json->code == 4 || $json->code == 5) {
203                    $app->logMsg(sprintf('Xurrency error InvalidKey: %s', $json->message), LOG_WARNING, __FILE__, __LINE__);
204                } else {
205                    $app->logMsg(sprintf('Xurrency unknown error: %s', $json->message), LOG_WARNING, __FILE__, __LINE__);
206                }
207                return false;
208            } else {
209                return $json->result->value;
210            }
211            break;
212
213        case 'ecb' :
214            // Fetch XML from ECB <http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml>
215            $api_url = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';
216            if (false === $sXML = file_get_contents($api_url)) {
217                $app->logMsg(sprintf('Failed to load ECB XML data from ', $api_url), LOG_WARNING, __FILE__, __LINE__);
218                return false;
219            }
220            if (false === $oXML = simplexml_load_string($sXML)) {
221                $app->logMsg(sprintf('Failed to decode ECB XML data: ', truncate($sXML, 200, 'end')), LOG_WARNING, __FILE__, __LINE__);
222                return false;
223            }
224            // Populate Array
225            foreach ($oXML->Cube->Cube->Cube as $oRate) {
226                foreach ($oRate->attributes() as $sKey => $sAttribute) {
227                    if ($sKey == 'currency') {
228                        $sCurrency = strtolower((string) $sAttribute);
229                    } else if ($sKey == 'rate') {
230                        $nRate = (string) $sAttribute;
231                    }
232                }
233                $aCurrencies['eur'][$sCurrency] = $nRate;
234                $aCurrencies[$sCurrency]['eur'] = 1 / $nRate;
235            }
236            // Check if requested rates are available.
237            if (isset($aCurrencies[$parameters['base']][$parameters['target']])) {
238                return (float) $aCurrencies[$parameters['base']][$parameters['target']];
239            } else {
240                $app->logMsg(sprintf('API %s does not have base %s or target %s', $this->getParam('api'), $parameters['base'], $parameters['target']), LOG_WARNING, __FILE__, __LINE__);
241                return false;
242            }
243
244        default :
245            trigger_error('Unknown API: ' . $this->getParam('api'), E_USER_ERROR);
246            die;
247            break;
248        }
249    }
250}
251
252
Note: See TracBrowser for help on using the repository browser.