home *** CD-ROM | disk | FTP | other *** search
/ Cricao de Sites - 650 Layouts Prontos / WebMasters.iso / Servidores / xampp-win32-1.6.7-installer.exe / php / PEAR / Services / ExchangeRates.php < prev    next >
Encoding:
PHP Script  |  2008-07-02  |  13.2 KB  |  348 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2003 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at                              |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Author: Marshall Roch <marshall@exclupen.com>                        |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: ExchangeRates.php,v 1.7 2005/06/23 20:29:20 cross Exp $
  20.  
  21. /**
  22.  * @package Services_ExchangeRates
  23.  * @category Services
  24.  */
  25.  
  26. /**#@+
  27.  * Error codes
  28.  */
  29. define('SERVICES_EXCHANGERATES_ERROR_RETURN', 1);
  30. define('SERVICES_EXCHANGERATES_ERROR_DIE', 8);
  31. define('SERVICES_EXCHANGERATES_ERROR_INVALID_DRIVER', 101);
  32. define('SERVICES_EXCHANGERATES_ERROR_INVALID_CURRENCY', 102);
  33. define('SERVICES_EXCHANGERATES_ERROR_CONVERSION_ERROR', 103);
  34. define('SERVICES_EXCHANGERATES_ERROR_RETRIEVAL_FAILED', 104);
  35. /**#@-*/
  36.  
  37. /**
  38.  * Exchange Rate package
  39.  *
  40.  * This package converts back and forth between different currencies, in any 
  41.  * combination.  All data used is updated automatically from interchangable
  42.  * sources.  That is, if there is a source publishing exchange rates that
  43.  * isn't supported yet, you could write a driver and use that source
  44.  * seamlessly with the rest of the package.
  45.  *
  46.  * Disclaimer: The rates are nominal quotations - neither buying nor 
  47.  * selling rates - and are intended for statistical or analytical 
  48.  * purposes. Rates available from financial institutions will differ.
  49.  *
  50.  * The United Nations Economic Commission for Europe is implementing new web
  51.  * services.  Keep an eye on progress here: http://www.unemed.org/edocs/index.htm
  52.  *
  53.  * @todo Add locale support for different currency formatting
  54.  *
  55.  * @example ExchangeRates/docs/example.php
  56.  *
  57.  * @author Marshall Roch <marshall@exclupen.com>
  58.  * @author Colin Ross <cross@php.net>
  59.  * @copyright Copyright 2003 Marshall Roch
  60.  * @license http://www.php.net/license/2_02.txt PHP License 2.0
  61.  * @package Services_ExchangeRates
  62.  */
  63. class Services_ExchangeRates {
  64.  
  65.    /**
  66.     * Sets the number of places to round the currencies to at the end
  67.     * @access private
  68.     * @var int
  69.     */
  70.     var $_roundToDecimal = 2;
  71.  
  72.    /**
  73.     * Determines whether the returned conversion is rounded or not
  74.     * @access private
  75.     * @var bool
  76.     */
  77.     var $_roundAutomatically = true;
  78.     
  79.    /**
  80.     * Defines single character used to separate each group of thousands in returned conversion
  81.     * @access private
  82.     * @var string
  83.     */
  84.     var $_thousandsSeparator = ",";
  85.     
  86.    /**
  87.     * Defines single character to use as a decimal place in returned conversion
  88.     * @access private
  89.     * @var string
  90.     */
  91.     var $_decimalCharacter = ".";
  92.     
  93.    /**
  94.     * Sets the path to where cache files are stored (don't forget the trailing slash!)
  95.     * @access private
  96.     * @var string
  97.     */
  98.     var $_cacheDirectory = '/tmp/';
  99.     
  100.    /**
  101.     * Sets the length (in seconds) to cache the exchange rate data. This information
  102.     * is updated daily. Default is 1 hour.
  103.     * @access private
  104.     * @var int
  105.     */
  106.     var $_cacheLengthRates = 3600;
  107.     
  108.    /**
  109.     * Sets the length (in seconds) to cache the list of currencies.  This information
  110.     * is very rarely updated. Default is 4 weeks.
  111.     * @access private
  112.     * @var int
  113.     */
  114.     var $_cacheLengthCurrencies = 2419200;
  115.     
  116.    /**
  117.     * Sets the length (in seconds) to cache the list of countries.  This information
  118.     * is very rarely updated. Default is 4 weeks.
  119.     * @access private
  120.     * @var int
  121.     */
  122.     var $_cacheLengthCountries = 2419200;
  123.     
  124.    /**
  125.     * PEAR error mode (when raiseError is called)
  126.     *
  127.     * @see setToDebug()
  128.     * @access private
  129.     * @var int
  130.     */
  131.     var $_pearErrorMode = SERVICES_EXCHANGERATES_ERROR_RETURN;
  132.     
  133.    /**
  134.     * Constructor
  135.     *
  136.     * This method overrides any default settings based on the $options
  137.     * parameter and retrieves feed data from the cache or their sources.
  138.     *
  139.     * $options is an associative array:
  140.     * <code>
  141.     * $options = array(
  142.     *     'roundToDecimal'        => number of decimal places to round to (int),
  143.     *     'roundAutomatically'    => whether to automatically round to 
  144.     *                                $roundToDecimal digits (bool),
  145.     *     'thousandsSeparator'    => character to separate every 1000 (string),
  146.     *     'decimalCharacter'      => character for decimal place (string),
  147.     *     'cacheDirectory'        => path (with trailing slash) to store cache 
  148.     *                                files (string),
  149.     *     'cacheLengthRates'      => length of time to cache exchange rates 
  150.     *                                file (int),
  151.     *     'cacheLengthCurrencies' => length of time to cache currency 
  152.     *                                list (int),
  153.     *     'cacheLengthCountries'  => length of time to cache country list (int),
  154.     *     'pearErrorMode'         => pear error mode (int));
  155.     * </code>
  156.     *
  157.     * @param string Driver name (filename minus 'Rates_' and .php) for exchange rate feed
  158.     * @param string Driver name for currency code list
  159.     * @param string Driver name for country code list (not yet used for anything)
  160.     * @param array  Array to override default settings
  161.     */
  162.     function Services_ExchangeRates($ratesSource = 'ECB', 
  163.                                     $currencySource = 'UN', 
  164.                                     $countrySource = 'UN',
  165.                                     $options = array(NULL)) {
  166.                                
  167.         $availableOptions = array('roundToDecimal',
  168.                                   'roundAutomatically',
  169.                                   'thousandsSeparator',
  170.                                   'decimalCharacter',
  171.                                   'cacheDirectory',
  172.                                   'cacheLengthRates',
  173.                                   'cacheLengthCurrencies',
  174.                                   'cacheLengthCountries');
  175.                                   
  176.         foreach($options as $key => $value) {
  177.             if(in_array($key, $availableOptions)) {
  178.                 $property = '_'.$key;
  179.                 $this->$property = $value;
  180.             }
  181.         }
  182.     
  183.         $rateData = $this->retrieveData('Rates_' . $ratesSource, $this->_cacheLengthRates);       
  184.         $this->rates = $rateData['rates'];
  185.         $this->ratesUpdated = $rateData['date'];
  186.         $this->ratesSource = $rateData['source'];
  187.         
  188.         $this->currencies = $this->retrieveData('Currencies_' . $currencySource, $this->_cacheLengthCurrencies);
  189.         
  190.         // not yet implimented, here for future features:
  191.         // $this->countries = $this->retrieveData('Countries_' . $countriesSource, $this->_cacheLengthCountries);
  192.         
  193.         $this->validCurrencies = $this->getValidCurrencies($this->currencies, $this->rates);  
  194.         
  195.     }
  196.     
  197.    /**
  198.     * Factory
  199.     *
  200.     * Includes the necessary driver, instantiates the class, retrieves the feed,
  201.     * and returns an associative array.
  202.     *
  203.     * @param string Driver filename (minus .php; this includes 'Rates_', etc.)
  204.     * @param int Cache length
  205.     * @return array Associative array containing the data requested
  206.     */
  207.     function retrieveData($source, $cacheLength) {
  208.         include_once("Services/ExchangeRates/${source}.php");
  209.         $classname = "Services_ExchangeRates_${source}";
  210.         if (!class_exists($classname)) {
  211.             return $this->raiseError("No driver exists for the source ${source}... aborting.", SERVICES_EXCHANGERATES_ERROR_INVALID_DRIVER);
  212.         }
  213.         $class = new $classname;
  214.          
  215.         return $class->retrieve($cacheLength, $this->_cacheDirectory);
  216.     }
  217.           
  218.    /**
  219.     * Get list of currencies with known exchange rates
  220.     *
  221.     * Creates an array of currency codes and their names, based on
  222.     * overlapping elements in $rates and $currencies.
  223.     *
  224.     * @param array Array of currency codes to currency names
  225.     * @param array Array of currency codes to exchange rates
  226.     * @return array Array of currency codes to currency names that have a known exchange rate (sorted alphabetically)
  227.     */
  228.     function getValidCurrencies($currencies, $rates) {      
  229.         // loop through list of currencies
  230.         $validCurrencies = array();
  231.         foreach ($currencies as $code => $currency) {
  232.             // check to see if that currency has a known exchange rate
  233.             if (in_array($code, array_keys($rates))) {
  234.                 // if so, add it to the array to return
  235.                 $validCurrencies[$code] = $currency;
  236.             }
  237.         }
  238.         asort($validCurrencies);
  239.         return $validCurrencies;
  240.     }
  241.     
  242.     function isValidCurrency($code) {
  243.         if (!in_array($code, array_keys($this->validCurrencies))) {
  244.             $this->raiseError('Error: Invalid currency: ' . $code, SERVICES_EXCHANGERATES_ERROR_INVALID_CURRENCY);
  245.             return false;
  246.         }
  247.         
  248.         return true;
  249.     }
  250.     
  251.    /**
  252.     * Convert currencies
  253.     *
  254.     * @param string Currency code of original currency
  255.     * @param string Currency code of target currency
  256.     * @param double Amount of original currency to convert
  257.     * @param boolean Format the final currency (add commas, round, etc.)
  258.     * @return mixed Currency converted to $to
  259.     */
  260.     function convert($from, $to, $amount, $format = true) {
  261.     
  262.         if ($this->isValidCurrency($from) && $this->isValidCurrency($to)) {
  263.    
  264.             // Convert $from to whatever the base currency of the
  265.             // exchange rate feed is.
  266.             $base = (1 / $this->rates[$from]) * $amount;
  267.             // Convert from base currency to $to
  268.             $final = $this->rates[$to] * $base;
  269.             return ($format) ? $this->format($final) : $final;
  270.         }
  271.         $this->raiseError('Unable to convert!', SERVICES_EXCHANGERATES_ERROR_CONVERSION_ERROR);
  272.         return false;
  273.         
  274.     }
  275.     
  276.    /**
  277.     * Formats the converted currency
  278.     *
  279.     * This method adds $this->_thousandsSeparator between every group of thousands,
  280.     * and rounds to $this->_roundToDecimal decimal places.  Use the $options parameter
  281.     * on the constructor to set these values.
  282.     * 
  283.     * @param double Number to format
  284.     * @param mixed  Number of decimal places to round to (null for default)
  285.     * @param mixed  Character to use for decimal point (null for default)
  286.     * @param mixed  Character to use for thousands separator (null for default)
  287.     * @return string Formatted currency
  288.     */
  289.     function format($amount, $roundTo = null, $decChar = null, $sep = null) {
  290.         $roundTo = (($this->_roundAutomatically) ?
  291.                    (($roundTo == null) ? $this->_roundToDecimal : $roundTo) :
  292.                    '');
  293.         $decChar  = ($decChar == null) ? $this->_decimalCharacter : $decChar;
  294.         $sep = ($sep == null) ? $this->_thousandsSeparator : $sep;
  295.         
  296.         return number_format($amount, $roundTo, $decChar, $sep);
  297.     }
  298.     /**
  299.      * Get all rates as compared to a reference currency
  300.      * 
  301.      * Returns an associative array with currency codes as keys and 
  302.      * formated rates as values, as computed against a reference currency.
  303.      * 
  304.      * @param string $referenceCurrency Reference currency code
  305.      * @return array List of currencies => rates
  306.      * @see Services_ExchangeRates::convert()
  307.      * @access public
  308.      */
  309.     function getRates ($referenceCurrency)
  310.     {
  311.         $rates = array();
  312.         foreach ($this->validCurrencies as $code => $name) {
  313.             $rates[$code] = $this->convert($referenceCurrency, $code, 1, false);
  314.         }
  315.         ksort($rates);
  316.         return $rates;
  317.     }
  318.    /**
  319.     * Set to debug mode
  320.     *
  321.     * When an error is found, the script will stop and the message will be displayed
  322.     * (in debug mode only).
  323.     */
  324.     function setToDebug()
  325.     {
  326.         $this->_pearErrorMode = SERVICES_EXCHANGERATES_ERROR_DIE;
  327.     }
  328.     
  329.    /**
  330.     * Trigger a PEAR error
  331.     *
  332.     * To improve performances, the PEAR.php file is included dynamically.
  333.     * The file is so included only when an error is triggered. So, in most
  334.     * cases, the file isn't included and performance is much better.
  335.     *
  336.     * @param string error message
  337.     * @param int error code
  338.     */
  339.     function raiseError($msg, $code)
  340.     {
  341.         include_once('PEAR.php');
  342.         PEAR::raiseError($msg, $code, $this->_pearErrorMode);
  343.     }
  344.     
  345. }
  346.  
  347. ?>
  348.