Skip to content

Commit b8bc8ca

Browse files
committed
Add currency conversion test, Reorder mothods
1 parent 4503454 commit b8bc8ca

File tree

9 files changed

+214
-103
lines changed

9 files changed

+214
-103
lines changed

phpunit.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
33
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
44
bootstrap="vendor/autoload.php"
5+
cacheResult="false"
56
colors="true">
67
<testsuites>
78
<testsuite name="Unit">

src/ECB.php

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,34 @@
44

55
class ECB
66
{
7+
/**
8+
* Official ECB daily exchange reference URL
9+
*/
10+
public const DEFAULT_ECB_REFERENCE_URL = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';
11+
712
/**
813
* URL of daily exchange reference data
914
*/
10-
protected string $exchange_reference_url = 'https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';
15+
protected string $exchange_reference_source;
16+
17+
/**
18+
* @param string $exchange_reference_source URL or file path of the daily exchange reference
19+
*/
20+
public function __construct(string $exchange_reference_source = self::DEFAULT_ECB_REFERENCE_URL)
21+
{
22+
$this->exchange_reference_source = $exchange_reference_source;
23+
}
1124

1225
/**
26+
* cURL wrapper to download remote resource
27+
*
28+
* @param string $url URL of the resource
29+
* @return string resource content
1330
* @throws ECBException
1431
*/
15-
private static function fetch(string $url): string
32+
public static function fetch(string $url): string
1633
{
17-
$unique_url = $url . '?' . uniqid('', true);
18-
$handle = curl_init($unique_url);
34+
$handle = curl_init($url);
1935
curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
2036
$data = curl_exec($handle);
2137

@@ -38,17 +54,19 @@ private static function fetch(string $url): string
3854
}
3955

4056
/**
57+
* Retrieve latest exchange reference data
58+
*
4159
* @return Currency[]
4260
* @throws ECBException
4361
*/
4462
public function getExchangeReferences(): array
4563
{
4664
$exchange_references = [];
4765

48-
if (preg_match('/^https?:\/\//', $this->exchange_reference_url) === 1) {
49-
$raw_xml_data = self::fetch($this->exchange_reference_url);
66+
if (preg_match('/^https?:\/\//', $this->exchange_reference_source) === 1) {
67+
$raw_xml_data = self::fetch($this->exchange_reference_source);
5068
} else {
51-
$raw_xml_data = file_get_contents($this->exchange_reference_url);
69+
$raw_xml_data = file_get_contents($this->exchange_reference_source);
5270

5371
if ($raw_xml_data === false) {
5472
throw new ECBException(ECBException::DATA_FETCH_FAILED, 'Failed to get file contents');
@@ -81,13 +99,13 @@ public function getExchangeReferences(): array
8199
return $exchange_references;
82100
}
83101

84-
public function getExchangeReferenceUrl(): string
102+
public function getExchangeReferenceSource(): string
85103
{
86-
return $this->exchange_reference_url;
104+
return $this->exchange_reference_source;
87105
}
88106

89-
public function setExchangeReferenceUrl(string $exchange_reference_url): void
107+
public function setExchangeReferenceSource(string $exchange_reference_source): void
90108
{
91-
$this->exchange_reference_url = $exchange_reference_url;
109+
$this->exchange_reference_source = $exchange_reference_source;
92110
}
93111
}

src/ECBConverter.php

Lines changed: 30 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public function __construct(ECB $ecb, string $cache_file = '.ecb_cache', int $ca
2525
/**
2626
* @throws ECBException
2727
*/
28-
public function checkFileCache(): void
28+
private function checkFileCache(): void
2929
{
3030
if (!file_exists($this->cache_file) || time() - filemtime($this->cache_file) > $this->cache_timeout) {
3131
$this->reloadExchangeReferences($this->ecb);
@@ -36,27 +36,9 @@ public function checkFileCache(): void
3636
}
3737

3838
/**
39-
* Converts foreign currency to euro
40-
*
4139
* @throws ECBException
4240
*/
43-
public function toEuro(float $amount, string $currency, ?int $precision = null)
44-
{
45-
return $this->convert($amount, $currency, function ($amount, $rate) use ($precision) {
46-
$value = $amount / $rate;
47-
48-
if (!is_null($precision)) {
49-
return round($value, $precision);
50-
} else {
51-
return $value;
52-
}
53-
});
54-
}
55-
56-
/**
57-
* @throws ECBException
58-
*/
59-
private function check(): void
41+
public function check(): void
6042
{
6143
if (!empty($this->cache_file)) {
6244
$this->checkFileCache();
@@ -88,7 +70,7 @@ public function list(bool $asArray = false): array
8870

8971
/**
9072
* @param string[]|string $currencies
91-
* @return string[]|string
73+
* @return float[]|float
9274
* @throws ECBException
9375
*/
9476
public function convert(float $amount, $currencies, callable $callback)
@@ -122,28 +104,48 @@ public function convert(float $amount, $currencies, callable $callback)
122104
}
123105

124106
/**
125-
* Reloads ECB exchange references
126-
*
107+
* Converts foreign currency to euro
108+
* @param string[]|string $currencies
109+
* @return float[]|float
127110
* @throws ECBException
128111
*/
129-
public function reloadExchangeReferences(ECB $ecb): void
112+
public function toEuro(float $amount, string $currencies, ?int $precision = null)
130113
{
131-
$this->exchange_data = $ecb->getExchangeReferences();
114+
return $this->convert($amount, $currencies, function ($amount, $rate) use ($precision) {
115+
$value = $amount / $rate;
116+
117+
if (!is_null($precision)) {
118+
return round($value, $precision);
119+
} else {
120+
return $value;
121+
}
122+
});
132123
}
133124

134125
/**
135126
* Converts euro to foreign currency
136-
*
127+
* @param string[]|string $currencies
128+
* @return float[]|float
137129
* @throws ECBException
138130
*/
139-
public function toForeign(float $amount, string $currency_code, ?int $precision = null)
131+
public function toForeign(float $amount, $currencies, ?int $precision = null)
140132
{
141-
return $this->convert($amount, $currency_code, function ($amount, $rate) use ($precision) {
133+
return $this->convert($amount, $currencies, function ($amount, $rate) use ($precision) {
142134
$val = $amount * $rate;
143135
return !is_null($precision) ? round($val, $precision) : $val;
144136
});
145137
}
146138

139+
/**
140+
* Reloads ECB exchange references
141+
*
142+
* @throws ECBException
143+
*/
144+
public function reloadExchangeReferences(ECB $ecb): void
145+
{
146+
$this->exchange_data = $ecb->getExchangeReferences();
147+
}
148+
147149
public function getECB(): ECB
148150
{
149151
return $this->ecb;

tests/CurrencyConversionTest.php

Lines changed: 0 additions & 24 deletions
This file was deleted.

tests/ECBConverterTest.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php declare(strict_types = 1);
2+
3+
use PHPUnit\Framework\TestCase;
4+
use Richardds\ECBAPI\ECB;
5+
use Richardds\ECBAPI\ECBConverter;
6+
7+
final class ECBConverterTest extends TestCase
8+
{
9+
private const LOCAL_EXCHANGE_REFERENCE_PATH = __DIR__ . '/data/eurofxref-daily-local.xml';
10+
11+
private ECB $ecb;
12+
13+
private ECBConverter $converter;
14+
15+
public function setUp(): void
16+
{
17+
$this->ecb = new ECB();
18+
$this->ecb->setExchangeReferenceSource(self::LOCAL_EXCHANGE_REFERENCE_PATH);
19+
20+
$this->converter = new ECBConverter($this->ecb);
21+
}
22+
23+
/**
24+
* @throws \Richardds\ECBAPI\ECBException
25+
*/
26+
public function testHasExchangeReference(): void
27+
{
28+
$references = $this->ecb->getExchangeReferences();
29+
$this->assertCount(31, $references);
30+
}
31+
32+
/**
33+
* @return float[][]
34+
*/
35+
public function provideConversionData(): array
36+
{
37+
return [
38+
[1.00, 0.92, 'USD'],
39+
[0.89, 0.82, 'USD'],
40+
[5.50, 5.08, 'USD'],
41+
42+
[1.00, 1.14, 'GBP'],
43+
[0.89, 1.02, 'GBP'],
44+
[5.50, 6.28, 'GBP'],
45+
];
46+
}
47+
48+
/**
49+
* @dataProvider provideConversionData
50+
* @throws \Richardds\ECBAPI\ECBException
51+
*/
52+
public function testCurrencyConversionResult(float $from, float $to, string $currency): void
53+
{
54+
$result = $this->converter->toEuro($from, $currency, 2);
55+
$this->assertEquals($to, $result);
56+
57+
$result = $this->converter->toForeign($result, $currency, 2);
58+
$this->assertEquals($from, $result);
59+
}
60+
}

tests/ECBTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php declare(strict_types = 1);
2+
3+
use PHPUnit\Framework\TestCase;
4+
use Richardds\ECBAPI\Currency;
5+
use Richardds\ECBAPI\ECB;
6+
7+
class ECBTest extends TestCase
8+
{
9+
/**
10+
* @var ECB
11+
*/
12+
private $ecbMock;
13+
14+
public function setUp(): void
15+
{
16+
$this->ecbMock = $this->getMockBuilder(ECB::class)
17+
->onlyMethods(['getExchangeReferences'])
18+
->getMock();
19+
20+
// Return exchange reference from eurofxref-daily-mock.xml
21+
$this->ecbMock->method('getExchangeReferences')
22+
->willReturn([
23+
new Currency('USD', 1.0826),
24+
new Currency('GBP', 0.876),
25+
]);
26+
}
27+
28+
public function testHasDefaultExchangeReferenceSource(): void
29+
{
30+
$source = $this->ecbMock->getExchangeReferenceSource();
31+
$this->assertEquals(ECB::DEFAULT_ECB_REFERENCE_URL, $source);
32+
}
33+
34+
/**
35+
* @throws \Richardds\ECBAPI\ECBException
36+
*/
37+
public function testHasExchangeReference(): void
38+
{
39+
$references = $this->ecbMock->getExchangeReferences();
40+
$this->assertCount(2, $references);
41+
}
42+
}

tests/data/eurofxref-daily-2023-01-17.xml

Lines changed: 0 additions & 40 deletions
This file was deleted.

0 commit comments

Comments
 (0)