1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace CurrencyConverter\View\Helper; |
4
|
|
|
|
5
|
|
|
use Cake\View\Helper; |
6
|
|
|
use Cake\ORM\TableRegistry; |
7
|
|
|
use Cake\I18n\Time; |
8
|
|
|
|
9
|
|
|
/** |
10
|
|
|
* @property \Cake\View\Helper\HtmlHelper $Html |
11
|
|
|
* @property \Cake\View\Helper\FormHelper $Form |
12
|
|
|
* @property \Cake\View\Helper\NumberHelper $Number |
13
|
|
|
*/ |
14
|
|
View Code Duplication |
class CurrencyConverterHelper extends Helper |
|
|
|
|
15
|
|
|
{ |
16
|
|
|
/** |
17
|
|
|
* CurrencyratesTable Object |
18
|
|
|
* @var \Cake\ORM\Table |
19
|
|
|
*/ |
20
|
|
|
private $_currencyratesTable; |
21
|
|
|
|
22
|
|
|
/** |
23
|
|
|
* Default settings |
24
|
|
|
* |
25
|
|
|
* @var array |
26
|
|
|
*/ |
27
|
|
|
protected $_defaultConfig = [ |
28
|
|
|
'database' => 2, // Use database to store rate |
29
|
|
|
'refresh' => 24, // Time interval for refreshing rate in database |
30
|
|
|
'decimal' => 2, // Number of decimal to use for convert number |
31
|
|
|
]; |
32
|
|
|
|
33
|
|
|
/** |
34
|
|
|
* @param array $config |
35
|
|
|
* @return void |
36
|
|
|
*/ |
37
|
|
|
public function initialize(array $config = []) { |
38
|
|
|
|
39
|
|
|
$config = $this->getConfig(); |
40
|
|
|
|
41
|
|
|
$this->database = $config['database']; |
|
|
|
|
42
|
|
|
$this->refresh = $config['refresh']; |
|
|
|
|
43
|
|
|
$this->decimal = $config['decimal']; |
|
|
|
|
44
|
|
|
|
45
|
|
|
$this->_currencyratesTable = TableRegistry::get('CurrencyConverter.Currencyrates'); |
|
|
|
|
46
|
|
|
} |
47
|
|
|
|
48
|
|
|
/** |
49
|
|
|
* Convert method take an amount as first parameter and convert it using $from currency and $to currency. |
50
|
|
|
* |
51
|
|
|
* @param float|string $amount the amount to convert. |
52
|
|
|
* @param string $from currency to convert from |
53
|
|
|
* @param string $to currency to convert to |
54
|
|
|
* @return float $amount converted |
55
|
|
|
*/ |
56
|
|
|
public function convert($amount, $from, $to) |
57
|
|
|
{ |
58
|
|
|
$amount = floatval($amount); |
59
|
|
|
$rate = $this->getRateToUse($from, $to); |
60
|
|
|
|
61
|
|
|
return $convert = $this->_formatConvert($rate * $amount); |
|
|
|
|
62
|
|
|
} |
63
|
|
|
|
64
|
|
|
/** |
65
|
|
|
* Rate method return the rate of two currencies |
66
|
|
|
* |
67
|
|
|
* @param string $from currency to get the rate from |
68
|
|
|
* @param string $to currency to get the rate to |
69
|
|
|
* @return float|null $rate |
70
|
|
|
*/ |
71
|
|
|
public function rate($from, $to) |
72
|
|
|
{ |
73
|
|
|
return $this->getRateToUse($from, $to); |
74
|
|
|
} |
75
|
|
|
|
76
|
|
|
/** |
77
|
|
|
* getRateToUse return rate to use |
78
|
|
|
* Using $from and $to parameters representing currency to deal with and the configuration settings |
79
|
|
|
* This method save or update currencyrates Table if necesseray too. |
80
|
|
|
* |
81
|
|
|
* @param string $from currency to get the rate from |
82
|
|
|
* @param string $to currency to get the rate to |
83
|
|
|
* @return float|null $rate |
84
|
|
|
*/ |
85
|
|
|
public function getRateToUse($from, $to) |
86
|
|
|
{ |
87
|
|
|
if ($from == $to) return 1; |
88
|
|
|
if ($this->database) { |
89
|
|
|
// Get a currency rate from table |
90
|
|
|
$result = $this->_currencyratesTable->find('all')->where(['from_currency' => $from, 'to_currency' => $to])->first(); |
91
|
|
|
// If currency rate is in table and it doesn't have to be updated |
92
|
|
|
if ($result && $result->modified->wasWithinLast($this->refresh . ' hours')) return $rate = $result->rate; |
|
|
|
|
93
|
|
|
// If currency rate is in table and it have to be updated |
94
|
|
|
if ($result && !$result->modified->wasWithinLast($this->refresh . ' hours')) { |
95
|
|
|
if ($rate = $this->_getRateFromAPI($from, $to)) { |
96
|
|
|
$result->rate = $rate; |
97
|
|
|
$this->_currencyratesTable->save($result); |
|
|
|
|
98
|
|
|
} |
99
|
|
|
return $rate; |
100
|
|
|
} |
101
|
|
|
// If currency rate isn't in table |
102
|
|
|
if (!$result) { |
103
|
|
|
if ($rate = $this->_getRateFromAPI($from, $to)) { |
104
|
|
|
$entity = $this->_currencyratesTable->newEntity([ |
105
|
|
|
'from_currency' => $from, |
106
|
|
|
'to_currency' => $to, |
107
|
|
|
'rate' => $rate |
108
|
|
|
]); |
109
|
|
|
$this->_currencyratesTable->save($entity); |
110
|
|
|
} |
111
|
|
|
return $rate; |
112
|
|
|
} |
113
|
|
|
} |
114
|
|
|
|
115
|
|
|
return $this->_getRateFromAPI($from, $to); |
116
|
|
|
} |
117
|
|
|
|
118
|
|
|
/** |
119
|
|
|
* Format float number using configuration |
120
|
|
|
* |
121
|
|
|
* @return floatval |
122
|
|
|
*/ |
123
|
|
|
private function _formatConvert($number) |
124
|
|
|
{ |
125
|
|
|
return number_format($number, $this->decimal); |
126
|
|
|
} |
127
|
|
|
|
128
|
|
|
/** |
129
|
|
|
* Call free.currencyconverterapi.com API to get a rate for one currency to an other one currency |
130
|
|
|
* |
131
|
|
|
* @param string $from the currency |
132
|
|
|
* @param string $to the currency |
133
|
|
|
* @return int|null $rate |
134
|
|
|
*/ |
135
|
|
|
private function _getRateFromAPI($from, $to) |
136
|
|
|
{ |
137
|
|
|
$rate = null; |
138
|
|
|
|
139
|
|
|
$url = 'https://free.currencyconverterapi.com/api/v5/convert?q=' . $from . '_' . $to . '&compact=ultra'; |
140
|
|
|
$request = @fopen($url, 'r'); |
141
|
|
|
|
142
|
|
|
if ($request) { |
143
|
|
|
$response = fgets($request, 4096); |
144
|
|
|
fclose($request); |
145
|
|
|
|
146
|
|
|
$response = json_decode($response, true); |
147
|
|
|
if (isset($response[$from . '_' . $to])) { |
148
|
|
|
$rate = $response[$from . '_' . $to]; |
149
|
|
|
} |
150
|
|
|
} |
151
|
|
|
|
152
|
|
|
return $rate; |
153
|
|
|
} |
154
|
|
|
} |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.