source: trunk/lib/Currency.inc.php @ 380

Last change on this file since 380 was 380, checked in by anonymous, 13 years ago

Begin using PHP 5 class features ('public static...'); updated Currency.inc.php to support Xurrency's JSON API

File size: 9.3 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-2010 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    var $_params = array(
44        'cache_result' => true,
45        'cache_dir' => '',
46        'cache_age' => 86400, // 24 hours.
47        'api_type' => 'json', // 'json' or 'soap'.
48        'api_url' => 'http://xurrency.com/api/%s/%s/%s',
49        'api_key' => '',
50    );
51   
52    /**
53     * Cart constructor.
54     */
55    function Currency($params=array())
56    {
57        $app =& App::getInstance();
58
59        // Set custom parameters.
60        $this->setParam($params);
61       
62        // Setup cache directory.
63        if ($this->getParam('cache_result')) {
64            if ('' == $this->getParam('cache_dir')) {
65                // Use a sane default cache directory.
66                $this->setParam(array('cache_dir' => '/tmp/xcache_' . md5(COMMON_BASE)));
67            }
68            if (!is_dir($this->getParam('cache_dir'))) {
69                $app->logMsg(sprintf('Creating cache_dir: %s', $this->getParam('cache_dir')), LOG_INFO, __FILE__, __LINE__);               
70                if (!mkdir($this->getParam('cache_dir'))) {
71                    $app->logMsg(sprintf('Could not create cache_dir: %s', $this->getParam('cache_dir')), LOG_WARNING, __FILE__, __LINE__);               
72                }
73            }
74        }
75    }
76
77    /**
78     * Set the params of this object.
79     *
80     * @param  array $params   Array of param keys and values to set.
81     */
82    function setParam($params=null)
83    {
84        if (isset($params) && is_array($params)) {
85            // Merge new parameters with old overriding only those passed.
86            $this->_params = array_merge($this->_params, $params);
87        }
88    }
89
90    /**
91     * Return the value of a parameter, if it exists.
92     *
93     * @access public
94     * @param string $param        Which parameter to return.
95     * @return mixed               Configured parameter value.
96     */
97    function getParam($param)
98    {
99        $app =& App::getInstance();
100   
101        if (isset($this->_params[$param])) {
102            return $this->_params[$param];
103        } else {
104            $app->logMsg(sprintf('Parameter is not set: %s', $param), LOG_DEBUG, __FILE__, __LINE__);
105            return null;
106        }
107    }
108   
109    /*
110    * Return the exchange value between the two given currencies for given amount.
111    *
112    * @access   public
113    * @param    float   $amount Base amount to convert from.
114    * @param    string  $base   3-letter currency code to convert from.
115    * @param    string  $target 3-letter currency code to convert to.
116    * @return   mixed   Float converted currency value, or false on error.
117    * @author   Quinn Comendant <quinn@strangecode.com>
118    * @version  1.0
119    * @since    05 May 2008 23:50:59
120    */
121    function getValue($amount, $base, $target)
122    {
123        if (false !== $rate = $this->getRate($base, $target)) {
124            return abs($rate * $amount);           
125        } else {
126            return false;
127        }
128    }
129   
130    /*
131    * Return the currency conversion rate as a ratio.
132    *
133    * @access   public
134    * @param    string  $base   3-letter currency code to convert from.
135    * @param    string  $target 3-letter currency code to convert to.
136    * @return   mixed   Float exchange rate value, or false on error.
137    * @author   Quinn Comendant <quinn@strangecode.com>
138    * @version  1.0
139    * @since    25 May 2011 01:26:24
140    */
141    function getRate($base, $target)
142    {
143        $app =& App::getInstance();
144
145        $cache_file_path = sprintf('%s/%s-to-%s', $this->getParam('cache_dir'), $base, $target);
146        $cache_file_mtime = @filemtime($cache_file_path);
147        if (!$this->getParam('cache_result') || !$cache_file_mtime || $cache_file_mtime < time() - $this->getParam('cache_age')) {
148            // Get fresh data and create cached file if missing or expired.
149            $app->logMsg(sprintf('Getting fresh currency exchange rate: %s-to-%s', $base, $target), LOG_DEBUG, __FILE__, __LINE__);
150            $value = $this->_performAPICall(array(
151                'amount' => '1',
152                'base' => $base,
153                'target' => $target
154            ));
155            if (false === $value || !is_numeric($value)) {
156                // Failed retrieving value. Use cached copy for now.
157                $app->logMsg(sprintf('Failed getting currency exchange rate: %s-to-%s, using cached copy', $base, $target), LOG_NOTICE, __FILE__, __LINE__);
158                if (!$value = file_get_contents($cache_file_path)) {
159                    $app->logMsg(sprintf('Failed reading cached exchange rate file: %s', $cache_file_path), LOG_ERR, __FILE__, __LINE__);
160                    return false;
161                }
162            } else if ($this->getParam('cache_result') && !filePutContents($cache_file_path, $value, LOCK_EX)) {
163                $app->logMsg(sprintf('Failed writing to target rate file: %s', $cache_file_path), LOG_ERR, __FILE__, __LINE__);
164                return false;
165            }
166        } else {
167            $app->logMsg(sprintf('Getting cached currency exchange rate: %s-to-%s', $base, $target), LOG_DEBUG, __FILE__, __LINE__);
168            if (!$value = file_get_contents($cache_file_path)) {
169                $app->logMsg(sprintf('Failed reading target rate file: %s', $cache_file_path), LOG_ERR, __FILE__, __LINE__);
170                return false;
171            }
172        }
173        $app->logMsg(sprintf('Found currency exchange rate: %s-to-%s = %s', $base, $target, $value), LOG_DEBUG, __FILE__, __LINE__);
174        return trim($value);
175    }
176   
177    /**
178     * @param  string
179     * @param  array
180     * @return mixed
181     * @access private
182     */
183    function _performAPICall($parameters=null)
184    {
185        $app =& App::getInstance();
186       
187        switch ($this->getParam('api_type')) {
188        case 'json' :
189            $api_url = $this->getParam('api_url');
190            if ('' != $this->getParam('api_key')) {
191                $api_url .= '?key=' . $this->getParam('api_key');
192            }
193            $json_response = file_get_contents(sprintf($api_url, $parameters['base'], $parameters['target'], $parameters['amount']));
194            $json = json_decode($json_response);
195            if (null === $json) {
196                $app->logMsg(sprintf('Could not decode JSON response: %s', getDump($json_response)), LOG_WARNING, __FILE__, __LINE__);
197                return false;
198            } else if ($json->status === 'fail') {
199                if ($json->code == 3) {
200                    $app->logMsg(sprintf('Xurrency error LimitReachedException: %s', $json->message), LOG_WARNING, __FILE__, __LINE__);
201                } elseif ($json->code == 2) {
202                    $app->logMsg(sprintf('Xurrency error InvalidCurrencies: %s', $json->message), LOG_WARNING, __FILE__, __LINE__);
203                } elseif ($json->code == 4 || $json->code == 5) {
204                    $app->logMsg(sprintf('Xurrency error InvalidKey: %s', $json->message), LOG_WARNING, __FILE__, __LINE__);
205                } else {
206                    $app->logMsg(sprintf('Xurrency unknown error: %s', $json->message), LOG_WARNING, __FILE__, __LINE__);
207                }
208                return false;
209            } else {
210                return $json->result->value;
211            }
212            break;
213
214        case 'soap' :
215            // Xurrency doesn't appear to support SOAP anymore, but we'll leave this here in case it comes back.
216
217            // Setup SOAP object.
218            require_once 'SOAP/Client.php';
219            $soap_client = new SOAP_Client($this->getParam('api_url'));
220            // Call API
221            $result = $soap_client->call('getValue', $parameters);
222            // Check for errors.
223            if (PEAR::isError($result)) {
224                $app->logMsg(sprintf('SOAP Pear error: %s', $result->getMessage()), LOG_WARNING, __FILE__, __LINE__);
225                return false;
226            }
227            return $result;
228            break;
229
230        default :
231            trigger_error('Unknown api_type: ' . $this->getParam('api_type'), E_USER_ERROR);
232            die;
233            break;
234        }
235    }
236}
237
238
239?>
Note: See TracBrowser for help on using the repository browser.