Passed
Push — master ( 886777...848875 )
by Alessandro
03:57 queued 32s
created

CurrencyConverterComponent::getRates()   A

Complexity

Conditions 4
Paths 6

Size

Total Lines 21
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 4.0072

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 21
ccs 12
cts 13
cp 0.9231
rs 9.0534
cc 4
eloc 11
nc 6
nop 0
crap 4.0072
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 = (bool)$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) {
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();
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->enableHydration(false);
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();
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
    {
161 5
        $url = 'http://api.fixer.io/latest?base=' . $this->fromCurrency . '&symbols=' . $this->toCurrency;
162
163 5
        $handle = @fopen($url, 'r');
164
165 5
        if ($handle) {
166 4
            $result = fgets($handle, 4096);
167 4
            fclose($handle);
168 4
        }
169
170 5
        if (isset($result)) {
171 4
            $conversion = json_decode($result, true);
172
173 4
            if (isset($conversion['rates'][$this->toCurrency])) {
174 4
                return $conversion['rates'][$this->toCurrency];
175
            }
176
        }
177
        
178 1
        return $this->rate = 0;
179
    }
180
181 5
    private function ensureIfExistTable()
182
    {
183 5
        $autoIncrement = 'AUTO_INCREMENT';
184
185 5
        $db = ConnectionManager::get($this->dataSource);
186 5
        $config = $db->config();
187
188 5
        if (strpos($config['dsn'], 'sqlite') !== false) {
189 5
            $autoIncrement = 'AUTOINCREMENT';
190 5
        }
191
192
        $sql = 'CREATE TABLE IF NOT EXISTS `currency_converters` (
193 5
          `id` integer PRIMARY KEY ' . $autoIncrement . ',
194
          `fromCurrency` varchar(5) NOT NULL,
195
          `toCurrency` varchar(5) NOT NULL,
196
          `rates` varchar(10) NOT NULL,
197
          `created` datetime NOT NULL,
198
          `modified` datetime NOT NULL
199 5
        );';
200
201 5
        return $db->query($sql);
202 4
    }
203
204 7
    private function calculateValue()
205
    {
206 7
        $value = (double)$this->rate * (double)$this->amount;
207 7
        return number_format((double)$value, 2, '.', '');
208
    }
209
}
210