Settings_CurrencyUpdate_NBP_BankModel::getRates()   F
last analyzed

Complexity

Conditions 27
Paths 15004

Size

Total Lines 91
Code Lines 62

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 68.9265

Importance

Changes 0
Metric Value
eloc 62
dl 0
loc 91
ccs 35
cts 57
cp 0.614
rs 0
c 0
b 0
f 0
cc 27
nc 15004
nop 3
crap 68.9265

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * @copyright YetiForce S.A.
4
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
5
 * @author    Maciej Stencel <[email protected]>
6
 */
7
8
/**
9
 * Class for connection to Narodowy Bank Polski currency exchange rates.
10
 */
11
class Settings_CurrencyUpdate_NBP_BankModel extends Settings_CurrencyUpdate_AbstractBank_Model
12
{
13
	// Returns bank name
14
15 1
	public function getName()
16
	{
17 1
		return 'NBP';
18
	}
19
20
	// Returns url sources from where exchange rates are taken from
21
22 1
	public function getSource()
23
	{
24 1
		return ['http://nbp.pl/kursy/xml/LastA.xml'];
25
	}
26
27
	// Returns list of currencies supported by this bank
28
29 2
	public function getSupportedCurrencies()
30
	{
31 2
		$supportedCurrencies = [];
32 2
		$supportedCurrencies[Settings_CurrencyUpdate_Module_Model::getCRMCurrencyName($this->getMainCurrencyCode())] = $this->getMainCurrencyCode();
33 2
		$dateCur = date('Y-m-d', strtotime('last monday'));
34 2
		$tableUrl = 'http://api.nbp.pl/api/exchangerates/tables/a/';
35
36 2
		$numberOfDays = 1;
37 2
		$iterationsLimit = 60;
38 2
		$stateA = false;
39 2
		while (!$stateA) {
40 2
			$url = $tableUrl . $dateCur . '/?format=json';
41
			try {
42 2
				\App\Log::beginProfile("GET|NBP::getSupportedCurrencies|{$url}", 'CurrencyUpdate');
43 2
				$tryTable = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->get($url, ['timeout' => 20, 'connect_timeout' => 10]);
44 2
				\App\Log::endProfile("GET|NBP::getSupportedCurrencies|{$url}", 'CurrencyUpdate');
45 2
				if (200 == $tryTable->getStatusCode()) {
46
					$stateA = true;
47
					$tableBody = $tryTable->getBody();
48
				}
49
			} catch (\Throwable $ex) {
50
				\App\Log::info('Error during downloading table: ' . PHP_EOL . $ex->__toString() . PHP_EOL, 'CurrencyUpdate');
51 2
			}
52
			if (!$stateA) {
53
				$newDate = strtotime("-$numberOfDays day", strtotime($dateCur));
54
				$dateCur = date('Y-m-d', $newDate);
55
				++$numberOfDays;
56
				if ($numberOfDays > $iterationsLimit) {
57
					throw new \App\Exceptions\IntegrationException('ERR_ITERATIONS_LIMIT_EXCEEDED');
58
				}
59
			}
60 2
		}
61 2
		if ($stateA && $tableBody) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $tableBody does not seem to be defined for all execution paths leading up to this point.
Loading history...
62 2
			$json = \App\Json::decode($tableBody);
63 2
			if (!empty($json) && !empty($json[0]) && !empty($json[0]['rates'])) {
64 2
				foreach ($json[0]['rates'] as $rawCurrency) {
65
					if (empty($rawCurrency['currency'])) {
66
						continue;
67 2
					}
68 2
					if ('XDR' === $rawCurrency['code']) {
69
						continue;
70 2
					}
71
					$supportedCurrencies[Settings_CurrencyUpdate_Module_Model::getCRMCurrencyName($rawCurrency['code'])] = $rawCurrency['code'];
72
				}
73
			} else {
74
				\App\Log::error('Cannot parse server response' . $tableBody, __METHOD__);
75
			}
76
		} else {
77
			throw new \App\Exceptions\IntegrationException('ERR_CANNOT_CONNECT_TO_REMOTE' . $tableBody);
78 2
		}
79
		return $supportedCurrencies;
80
	}
81
82
	// Returns banks main currency
83 2
84
	public function getMainCurrencyCode()
85 2
	{
86
		return 'PLN';
87
	}
88
89
	/**
90
	 * Fetch exchange rates.
91
	 *
92
	 * @param <Array> $currencies        - list of systems active currencies
0 ignored issues
show
Documentation Bug introduced by
The doc comment <Array> at position 0 could not be parsed: Unknown type name '<' at position 0 in <Array>.
Loading history...
93
	 * @param <Date>  $date              - date for which exchange is fetched
94
	 * @param bool    $cron              - if true then it is fired by server and crms currency conversion rates are updated
95 1
	 * @param mixed   $otherCurrencyCode
96
	 * @param mixed   $dateParam
97 1
	 */
98 1
	public function getRates($otherCurrencyCode, $dateParam, $cron = false)
99 1
	{
100 1
		$moduleModel = Settings_CurrencyUpdate_Module_Model::getCleanInstance();
101
		$selectedBank = $moduleModel->getActiveBankId();
102 1
		$yesterday = date('Y-m-d', strtotime('-1 day'));
103
		$dateCur = $dateParam;
104 1
		// check if data is correct, currency rates can be retrieved only for working days
105 1
		$lastWorkingDay = vtlib\Functions::getLastWorkingDay($yesterday);
106 1
107
		$today = date('Y-m-d');
108 1
		$mainCurrency = \App\Fields\Currency::getDefault()['currency_code'];
109 1
		$tableUrl = 'http://api.nbp.pl/api/exchangerates/tables/a/';
110 1
111 1
		$numberOfDays = 1;
112 1
		$iterationsLimit = 60;
113
		$stateA = false;
114 1
		while (!$stateA) {
115 1
			$url = $tableUrl . $dateCur . '/?format=json';
116 1
			try {
117 1
				\App\Log::beginProfile("GET|NBP|{$url}", __NAMESPACE__);
118
				$tryTable = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->get($url, ['timeout' => 20, 'connect_timeout' => 10]);
119
				\App\Log::endProfile("GET|NBP|{$url}", __NAMESPACE__);
120
				if (200 == $tryTable->getStatusCode()) {
121 1
					$stateA = true;
122
					$tableBody = $tryTable->getBody();
123
				}
124
			} catch (\Throwable $exc) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
125
			}
126
			if (false === $stateA) {
127
				$dateCur = strtotime("-$numberOfDays day", strtotime($dateCur));
128
				$dateCur = date('Y-m-d', $dateCur);
129
				++$numberOfDays;
130
				if ($numberOfDays > $iterationsLimit) {
131 1
					break;
132 1
				}
133
			}
134 1
		}
135
136 1
		$json = \App\Json::decode($tableBody);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $tableBody does not seem to be defined for all execution paths leading up to this point.
Loading history...
137
		$datePublicationOfFile = (string) $json[0]['effectiveDate'];
138
139
		$exchangeRate = 1.0;
140
		// if currency is diffrent than PLN we need to calculate rate for converting other currencies to this one from PLN
141
		if ($mainCurrency !== $this->getMainCurrencyCode()) {
142
			foreach ($json[0]['rates'] as $item) {
143 1
				if ($item['code'] === $mainCurrency) {
144 1
					$exchangeRate = (float) $item['mid'];
145 1
				}
146 1
			}
147 1
		}
148 1
		foreach ($json[0]['rates'] as $item) {
149 1
			$currency = $item['code'];
150 1
			foreach ($otherCurrencyCode as $key => $currId) {
151 1
				if ($key == $currency && $currency != $mainCurrency) {
152
					$exchange = $item['mid'];
153 1
					$exchangeVtiger = $exchangeRate / $exchange;
154 1
					$exchange = $exchangeRate ? ($exchange / $exchangeRate) : 0;
155 1
					if (true === $cron || ((strtotime($dateParam) == strtotime($today)) || (strtotime($dateParam) == strtotime($lastWorkingDay)))) {
156
						$moduleModel->setCRMConversionRate($currency, $exchangeVtiger);
157
					}
158
					$existingId = $moduleModel->getCurrencyRateId($currId, $datePublicationOfFile, $selectedBank);
159
					if ($existingId > 0) {
160
						$moduleModel->updateCurrencyRate($existingId, $exchange);
161
					} else {
162
						$moduleModel->addCurrencyRate($currId, $datePublicationOfFile, $exchange, $selectedBank);
163
					}
164 1
				}
165
			}
166
		}
167
168
		// currency diffrent than PLN, we need to add manually PLN rates
169
		if ($mainCurrency != $this->getMainCurrencyCode()) {
170
			$exchange = $exchangeRate ? (1.00000 / $exchangeRate) : 0;
171
			$mainCurrencyId = false;
172
			foreach ($otherCurrencyCode as $code => $id) {
173
				if ($code == $this->getMainCurrencyCode()) {
174
					$mainCurrencyId = $id;
175
				}
176
			}
177
178
			if ($mainCurrencyId) {
179
				if (true === $cron || ((strtotime($dateParam) == strtotime($today)) || (strtotime($dateParam) == strtotime($lastWorkingDay)))) {
180
					$moduleModel->setCRMConversionRate($this->getMainCurrencyCode(), $exchangeRate);
181
				}
182
183
				$existingId = $moduleModel->getCurrencyRateId($mainCurrencyId, $datePublicationOfFile, $selectedBank);
184
185
				if ($existingId > 0) {
186
					$moduleModel->updateCurrencyRate($existingId, $exchange);
187 1
				} else {
188
					$moduleModel->addCurrencyRate($mainCurrencyId, $datePublicationOfFile, $exchange, $selectedBank);
189
				}
190
			}
191
		}
192
	}
193
}
194