ExchangeRateProvider::ExchangeRate()   A
last analyzed

Complexity

Conditions 3
Paths 3

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
dl 0
loc 19
rs 9.6333
c 0
b 0
f 0
nc 3
nop 2
1
<?php
2
3
4
/***
5
 * the sole purpose of this class is to provide an exchange rate
6
 * from currency 1 to currency 2.
7
 * It can provide number that reads as follows:
8
 *
9
 * If I exchange 1 USD I will get EUR 0.8
10
 * This is the exchange rate.
11
 *
12
 * So, how many do I get of the "to" currency
13
 * when I have one "from" currency.
14
 *
15
 *
16
 * @authors: Nicolaas [at] Sunny Side Up .co.nz
17
 * @package: ecommerce
18
 * @sub-package: money
19
 **/
20
21
class ExchangeRateProvider extends Object
22
{
23
    /**
24
     * cache of exchange rates.
25
     *
26
     * @var array
27
     */
28
    private static $_memory_cache = array();
29
30
    /**
31
     * adds a bit of additional cost to account for the exchange cost.
32
     *
33
     * @var floatval
34
     */
35
    protected $exchangeCostMultiplier = 1.05;
36
37
    /**
38
     * Get the exchange rate.
39
     *
40
     * @param string $fromCode e.g. NZD
41
     * @param string $toCode   e.g. USD
42
     *
43
     * @return float
44
     * @return float
45
     */
46
    public function ExchangeRate($fromCode, $toCode)
47
    {
48
        $fromCode = strtoupper($fromCode);
49
        $toCode = strtoupper($toCode);
50
        $cacheCode = $fromCode.'_'.$toCode;
51
        if (isset(self::$_memory_cache[$cacheCode])) {
52
            return self::$_memory_cache[$cacheCode];
53
        } else {
54
            if ($value = Session::get($cacheCode)) {
55
                self::$_memory_cache[$cacheCode] = $value;
56
            } else {
57
                $value = $this->getRate($fromCode, $toCode);
58
                self::$_memory_cache[$cacheCode] = $value;
59
                Session::set($cacheCode, $value);
60
            }
61
        }
62
63
        return self::$_memory_cache[$cacheCode];
64
    }
65
66
    /**
67
     * gets a rate from a FROM and a TO currency.
68
     * see https://free.currencyconverterapi.com/ for limitations
69
     *
70
     * @param string $fromCode - UPPERCASE Code, e.g. NZD
71
     * @param string $toCode   - UPPERCASE Code, e.g. EUR
72
     *
73
     * @return float - returns exchange rate
74
     */
75
    protected function getRate($fromCode, $toCode)
76
    {
77
        $rate = 0;
78
        $reference = $fromCode.'_'.$toCode;
79
        $url = 'http://free.currencyconverterapi.com/api/v5/convert?q='.$reference.'&compact=y';
80
        if (($ch = @curl_init())) {
81
            $timeout = 5; // set to zero for no timeout
82
            curl_setopt($ch, CURLOPT_URL, "$url");
83
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
84
            curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
85
            $record = curl_exec($ch);
86
            curl_close($ch);
87
        }
88
        if (!$record) {
0 ignored issues
show
Bug introduced by
The variable $record does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
89
            $record = file_get_contents($url);
90
        }
91
92
        if ($record) {
93
            $currencyData = json_decode($record);
94
            $rate = $currencyData->$reference->val;
95
            if (!$rate) {
96
                user_error('There was a problem retrieving the exchange rate.');
97
            }
98
        }
99
        if ($rate != 1) {
100
            $rate = $rate * $this->exchangeCostMultiplier;
101
        }
102
103
        return $rate;
104
    }
105
}
106