Passed
Push — master ( efcf76...979b87 )
by Alessandro
01:30
created

CurrencyConverterComponent::getRates()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 4.0582

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 20
ccs 11
cts 13
cp 0.8462
rs 9.2
cc 4
eloc 11
nc 6
nop 0
crap 4.0582
1
<?php
2
3
namespace CurrencyConverter\Controller\Component;
4
5
use Cake\Controller\Component;
6
use Cake\Datasource\ConnectionManager;
7
use Cake\ORM\TableRegistry;
8
use Cake\Database\Schema\TableSchema;
9
10
class CurrencyConverterComponent extends Component
11
{
12
    private $fromCurrency;
13
14
    private $toCurrency;
15
16
    private $amount;
17
18
    private $hourDifference;
19
20
    private $saveIntoDb;
21
22
    private $dataSource;
23
24
    private $rate;
25
26
    private $currencyTable;
27
28
    /**
29
     * Convertion function
30
     *
31
     * @param string $fromCurrency the starting currency that user wants to convert to.
32
     * @param string $toCurrency the ending currency that user wants to convert to.
33
     * @param float $amount the amount to convert.
34
     * @param boolean $saveIntoDb if develop wants to store convertion rate for use it without resending data to yahoo service.
35
     * @param int $hourDifference the hour difference to check if the last convertion is passed, if yes make a new call to yahoo finance api.
36
     * @param string $dataSource which dataSOurce need to use
37
     * @return float the total amount converted into the new currency
38
     */
39 8
    public function convert(
40
        $fromCurrency, 
41
        $toCurrency, 
42
        $amount, 
43
        $saveIntoDb = true, 
44
        $hourDifference = 1, 
45
        $dataSource = 'default'
46
    ) {
47 8
        $this->fromCurrency = $fromCurrency;
48 8
        $this->toCurrency = $toCurrency;
49 8
        $this->amount = $amount;
50 8
        $this->saveIntoDb = $saveIntoDb;
51 8
        $this->hourDifference = $hourDifference;
52 8
        $this->dataSource = $dataSource;
53 8
        $this->rate = 0;
54
55 8
        if($this->fromCurrency != $this->toCurrency){
56 7
            $this->fixFromToCurrency();
57
            
58 7
            if($this->saveIntoDb == true){
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
59 5
                $this->currencyTable = TableRegistry::get('CurrencyConverter', [
60 5
                    'className' => 'CurrencyConverter\Model\Table\CurrencyConvertersTable',
61
                    'table' => 'currency_converter'
62 5
                ]);
63
64 5
                $this->ensureIfExistTable();
65 5
                $this->saveIntoDatabase();
66
67 5
                return $this->calculateValue();
68
            }
69
            
70 2
            $this->rate = $this->getRates($this->fromCurrency, $this->toCurrency);
0 ignored issues
show
Unused Code introduced by
The call to CurrencyConverterComponent::getRates() has too many arguments starting with $this->fromCurrency.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
71
72 2
            return $this->calculateValue();
73
        }
74
        
75 1
        return number_format((double)$this->amount, 2, '.', '');
76
    }
77
78 7
    private function fixFromToCurrency()
79
    {
80 7
        if ($this->fromCurrency == "PDS"){
81 1
            $this->fromCurrency = "GBP";
82 1
        }
83
84 7
        if ($this->toCurrency == "PDS"){
85 1
            $this->toCurrency = "GBP";
86 1
        }
87 7
    }
88
89 5
    private function saveIntoDatabase()
90
    {
91 5
        $query = $this->currencyTable->find('all')
92 5
            ->where(['fromCurrency' => $this->fromCurrency, 'toCurrency' => $this->toCurrency ]);
93
94 5
        $query->hydrate(false);
0 ignored issues
show
Deprecated Code introduced by
The method Cake\ORM\Query::hydrate() has been deprecated with message: 3.4.0 Use enableHydration()/isHydrationEnabled() instead.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
95 5
        $result =  $query->toArray();
96
97 5
        foreach ($result as $row){
98 2
            $lastUpdated = $row['modified'];
99
100 2
            $now = date('Y-m-d H:i:s');
101 2
            $dStart = new \DateTime($now);
102 2
            $diff = $dStart->diff($lastUpdated);
103
104 2
            if ($this->ensureNeedToUpdateDatabase($diff, $row)) {
105
                $this->updateDatabase($row);
106
            } else {
107 2
                $this->rate = $row['rates'];
108
            }
109 5
        }
110
111 5
        if (count($result) <= 0) {
112 3
            $this->insertIntoDatabase();
113 3
        }
114 5
    }
115
116
    private function updateDatabase($row)
117
    {
118
        $this->rate = $this->getRates($this->fromCurrency, $this->toCurrency);
0 ignored issues
show
Unused Code introduced by
The call to CurrencyConverterComponent::getRates() has too many arguments starting with $this->fromCurrency.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
119
120
        $data = [
121
            'fromCurrency'=> $this->fromCurrency,
122
            'toCurrency'  => $this->toCurrency,
123
            'rates'       => $this->rate,
124
            'modified'    => date('Y-m-d H:i:s'),
125
        ];
126
127
        $entity = $this->currencyTable->get($row['id']); 
128
        $this->currencyTable->patchEntity($entity, $data);
129
        $this->currencyTable->save($entity);
130
    }
131
132 3
    private function insertIntoDatabase()
133
    {
134 3
        $this->rate = $this->getRates();
135
136
        $data = [
137 3
            'fromCurrency' => $this->fromCurrency,
138 3
            'toCurrency'   => $this->toCurrency,
139 3
            'rates'        => $this->rate,
140 3
            'created'      => date('Y-m-d H:i:s'),
141 3
            'modified'     => date('Y-m-d H:i:s'),
142 3
        ];
143
144 3
        $entity = $this->currencyTable->newEntity($data);
145 3
        $this->currencyTable->save($entity);
146 3
    }
147
148 2
    private function ensureNeedToUpdateDatabase($diff, $row)
149
    {
150
        return (
151 2
            ((int)$diff->y >= 1) || 
152 2
            ((int)$diff->m >= 1) || 
153 2
            ((int)$diff->d >= 1) || 
154 2
            ((int)$diff->h >= $this->hourDifference) || 
155 2
            ((double)$row['rates'] == 0)
156 2
        );
157
    }
158
159 5
    private function getRates(){
160 5
        $url = 'http://api.fixer.io/latest?base=' . $this->fromCurrency . '&symbols=' . $this->toCurrency;
161
162 5
        $handle = @fopen($url, 'r');
163
164 5
        if ($handle) {
165 5
            $result = fgets($handle, 4096);
166 5
            fclose($handle);
167 5
        }
168
169 5
        if (isset($result)) {
170 5
            $conversion = json_decode($result, true);
171
172 5
            if (isset($conversion['rates'][$this->toCurrency])) {
173 5
                return $conversion['rates'][$this->toCurrency];
174
            }
175
        }
176
        
177
        return $this->rate = 0;
178
    }
179
180 5
    private function ensureIfExistTable(){
181 5
        $autoIncrement = 'AUTO_INCREMENT';
182
183 5
        $db = ConnectionManager::get($this->dataSource);
184 5
        $config = $db->config();
185
186 5
        if (strpos($config['dsn'], 'sqlite') !== false) {
187 5
            $autoIncrement = 'AUTOINCREMENT';
188 5
        }
189
190
        $sql = 'CREATE TABLE IF NOT EXISTS `currency_converters` (
191 5
          `id` integer PRIMARY KEY ' . $autoIncrement . ',
192
          `fromCurrency` varchar(5) NOT NULL,
193
          `toCurrency` varchar(5) NOT NULL,
194
          `rates` varchar(10) NOT NULL,
195
          `created` datetime NOT NULL,
196
          `modified` datetime NOT NULL
197 5
        );';
198
199 5
        return $db->query($sql);
200
    }
201
202 7
    private function calculateValue()
203
    {
204 7
        $value = (double)$this->rate * (double)$this->amount;
205 7
        return number_format((double)$value, 2, '.', '');
206
    }
207
}
208