Version: current

      1 <?php
      2 /**
      3  * Модуль получения официальных курсов валюты с сайта cbr.ru
      4  * Получает курсы USD и Euro через xml сервис с сайта cbr.ru, кеширует данные в течении указаного времени (10 часов)
      5  *
      6  * @author dvp
      7 */
      8 class PageInformerRates extends Extension {
      9
     10
     11     /**
     12      * Список валют для получения курсов
     13      */
     14     protected static $valutes = array(
     15         'USD' => 'R01235',
     16         'EUR' => 'R01239',
     17     );
     18
     19     /**
     20      * Время кеширования в секундах
     21      */
     22     protected static $expire = 36000; //  10 * 3600
     23
     24     /**
     25      * Кешированные данные погоды
     26      */
     27     protected $rates = false;
     28
     29     /**
     30      * Устанавливает время жизни кеша
     31      * вызов в конфиге: PageInformerWeather::SetExpire(2);
     32      *
     33      * @param $hours    int время жизни кеша в часах
     34      */
     35     public static function SetExpire($hours) {
     36         self::$expire = $hours * 3600;
     37     }
     38
     39     /**
     40      * Устанавливает новый список валют для загрузки
     41      *
     42      * @param array $valutes
     43      */
     44     public static function SetValutes($valutes) {
     45         self::$valutes = $valutes;
     46     }
     47
     48     /**
     49      * Возвращает объект с описанием курса валют
     50      * Формат ответа:
     51      *   Date $Date - дата выставления курсов
     52      *   DataObjectSet $Rates - список курсов валют
     53      * Формат одного курса валюты:
     54      *   Date $Date - дата выставления курса
     55      *   string $Name - международное обозначение валюты (USD, EUR, ...)
     56      *   float $Rate - курс валюты
     57      *   float $Delta - разница с предыдущим днем
     58      *   int $DeltaSign - флаг было повышение или понижение курса 1 - повышение, -1 - понижение
     59      *   string $DeltaClass - класс для строки валюты up - если было повышение, down - иначе
     60      *
     61      * @return ArrayData
     62      */
     63     public function ExchangeRate() {
     64         if (!$this->_getRate())
     65             return false;
     66         return ($this->rates) ? new ArrayData($this->rates) : false;
     67     }
     68
     69     /**
     70      * Получает данные курсов валют с кэшированием
     71      * Производит запрос данных с сайта cbr.ru и кеширует их в текущем сайте
     72      *
     73      * @return bool
     74      */
     75     private function _getRate() {
     76         if ($this->rates) return true;
     77
     78         $cache_path = TEMP_FOLDER . '/cache_exchangerate';
     79
     80         // использовать кешированные данные?
     81         if(!isset($_GET['flush']) && @file_exists($cache_path) && @filemtime($cache_path) + self::$expire > time()) {
     82             $this->rates = unserialize(file_get_contents($cache_path));
     83             if (is_array($this->rates) && count($this->rates) > 0) return true;
     84         }
     85
     86         // получить данные с cbr
     87         //http://www.cbr.ru/scripts/XML_dynamic.asp?date_req1=02/03/2001&date_req2=14/03/2001&VAL_NM_RQ=R01235
     88
     89         $day_end = date('d/m/Y');
     90         $day_start = date('d/m/Y',(time()-60*60*24*7));
     91
     92         $this->rates = array(
     93             'Date' => DBField::create('Date', date('Y-m-d')),
     94             'Rates' => new DataObjectSet(),
     95         );
     96
     97         $all = true;
     98         foreach (self::$valutes as $value => $code) {
     99             $info = @file_get_contents("http://www.cbr.ru/scripts/XML_dynamic.asp?date_req1={$day_start}&date_req2={$day_end}&VAL_NM_RQ={$code}");
    100             if ($info) {
    101                 $xml = simplexml_load_string($info);
    102
    103                 if ($xml) {
    104                     $result = array();
    105                     foreach ($xml as $el) {
    106                         $result[] = array(
    107                             'Date' => (string) $el->attributes()->Date,
    108                             'Value' => floatval(str_replace(',', '.', (string) $el->Value))
    109                         );
    110                     }
    111
    112                     $count = count($result);
    113                     if ($count > 0) {
    114                         $record = array(
    115                             'Date' => DBField::create('Date', $result[$count-1]['Date']),
    116                             'Name' => $value,
    117                             'Rate' => sprintf('%.2f', $result[$count-1]['Value']),
    118                             'Delta' => ($count > 1) ? (sprintf('%.4f', $result[$count-1]['Value'] - $result[$count-2]['Value'])) : 0,
    119                         );
    120                         $record['DeltaSign'] = ($record['Delta'] > 0) ? 1 : -1;
    121                         $record['DeltaClass'] = ($record['Delta'] > 0) ? 'up' : 'down';
    122
    123                         $this->rates['Rates']->push(new ArrayData($record));
    124                         $this->rates['Date'] = $record['Date'];
    125                     }
    126                 }
    127             }
    128             else {
    129                 $all = false;
    130             }
    131         }
    132
    133         if ($this->rates['Rates']->Count() > 0) {
    134             if ($all)
    135                 file_put_contents($cache_path, serialize($this->rates));
    136             return true;
    137         }
    138         $this->rates = false;
    139         return false;
    140     }
    141
    142 }
    143

[Raise a SilverStripe Framework issue/bug](https://github.com/silverstripe/silverstripe-framework/issues/new)
- [Raise a SilverStripe CMS issue/bug](https://github.com/silverstripe/silverstripe-cms/issues/new)
- Please use the Silverstripe Forums to ask development related questions. -