Skip to content

Commit

Permalink
Merge pull request #35 from GoteoFoundation/feat/update-exchanges
Browse files Browse the repository at this point in the history
[feat] Update exchanges
  • Loading branch information
subiabre authored Nov 26, 2024
2 parents 5785f59 + e6be82a commit 8daec98
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 64 deletions.
107 changes: 55 additions & 52 deletions src/Library/Economy/Currency/EuropeanCentralBankExchange.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

namespace App\Library\Economy\Currency;

use App\Entity\Money as EntityMoney;
use App\Entity\Money;
use App\Library\Economy\MoneyService;
use Brick\Math\RoundingMode;
use Brick\Money\CurrencyConverter;
use Brick\Money\ExchangeRateProvider;
use Brick\Money\ExchangeRateProvider\BaseCurrencyProvider;
use Brick\Money\ExchangeRateProvider\ConfigurableProvider;
use Brick\Money\MoneyContainer;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Contracts\Cache\CacheInterface;
use Symfony\Contracts\Cache\ItemInterface;
Expand All @@ -20,6 +20,9 @@
*/
class EuropeanCentralBankExchange implements ExchangeInterface
{
public const NAME = 'european_central_bank';
public const WEIGHT = 100;

public const ISO_4217 = 'EUR';

/**
Expand Down Expand Up @@ -53,59 +56,62 @@ public function __construct()
$provider->setExchangeRate(self::ISO_4217, $rate['currency'], $rate['rate']);
}

$this->date = $this->getDataUpdatedDate($data['@attributes']['time']);
$this->date = $this->parseECBTime($data['@attributes']['time']);
$this->provider = new BaseCurrencyProvider($provider, self::ISO_4217);
$this->converter = new CurrencyConverter($this->provider);
}

private function getDataLatest(): array
public function getName(): string
{
$data = \simplexml_load_file(self::ECB_DATA);
if (!$data) {
throw new \Exception('Could not retrieve XML data');
}

return \json_decode(\json_encode($data), true)['Cube']['Cube'];
return self::NAME;
}

private function getDataCached(): array
public function getWeight(): int
{
$data = $this->cache->get($this->getName(), function (ItemInterface $item): array {
$item->expiresAfter(self::ECB_DATA_TTL);
return self::WEIGHT;
}

return $this->getDataLatest();
});
public function convert(Money $money, string $toCurrency): Money
{
$converted = $this->converter->convert(
MoneyService::toBrick($money),
$toCurrency,
null,
RoundingMode::HALF_EVEN
);

if (!$data) {
throw new \Exception('Could not retrieve cached data');
}
return new Money(
$converted->getMinorAmount()->toInt(),
$converted->getCurrency()->getCurrencyCode()
);
}

return $data;
public function getConversionRate(string $fromCurrency, string $toCurrency): float
{
return $this->provider->getExchangeRate($fromCurrency, $toCurrency)->toFloat();
}

private function getDataUpdatedDate(string $time): \DateTimeInterface
public function getConversionDate(string $fromCurrency, string $toCurrency): \DateTimeInterface
{
return \DateTime::createFromFormat(
\DateTimeInterface::RFC3339,
sprintf('%sT16:00:00+01:00', $time),
new \DateTimeZone(self::ECB_TIMEZONE)
);
$this->provider->getExchangeRate($fromCurrency, $toCurrency);

return $this->date;
}

public function getData(): array
{
try {
$cachedData = $this->getDataCached();
$cachedDate = $this->parseECBTime($cachedData['@attributes']['time']);

$currentDate = new \DateTime('now', new \DateTimeZone(self::ECB_TIMEZONE));
$currentDayAt16 = (new \DateTime('now', new \DateTimeZone(self::ECB_TIMEZONE)))->setTime(16, 0);
$cachedDate = $this->getDataUpdatedDate($cachedData['@attributes']['time']);

if (
$currentDate > $currentDayAt16
&& $cachedDate < $currentDayAt16
) {
$this->cache->delete($this->getName());
$this->cache->delete(self::NAME);
$cachedData = $this->getDataCached();
}

Expand All @@ -115,40 +121,37 @@ public function getData(): array
}
}

public function getName(): string
{
return 'european_central_bank';
}

public function getWeight(): int
private function parseECBTime(string $time): \DateTimeInterface
{
return 100;
return \DateTime::createFromFormat(
\DateTimeInterface::RFC3339,
\sprintf('%sT16:00:00+01:00', $time),
new \DateTimeZone(self::ECB_TIMEZONE)
);
}

public function convert(MoneyContainer $money, string $toCurrency): EntityMoney
private function getDataLatest(): array
{
$converted = $this->converter->convert(
$money,
$toCurrency,
null,
RoundingMode::HALF_EVEN
);
$data = \simplexml_load_file(self::ECB_DATA);
if (!$data) {
throw new \Exception('Could not retrieve XML data');
}

return new EntityMoney(
$converted->getMinorAmount()->toInt(),
$converted->getCurrency()->getCurrencyCode()
);
return \json_decode(\json_encode($data), true)['Cube']['Cube'];
}

public function getConversionRate(string $fromCurrency, string $toCurrency): float
private function getDataCached(): array
{
return $this->provider->getExchangeRate($fromCurrency, $toCurrency)->toFloat();
}
$data = $this->cache->get(self::NAME, function (ItemInterface $item): array {
$item->expiresAfter(self::ECB_DATA_TTL);

public function getConversionDate(string $fromCurrency, string $toCurrency): \DateTimeInterface
{
$this->provider->getExchangeRate($fromCurrency, $toCurrency);
return $this->getDataLatest();
});

return $this->date;
if (!$data) {
throw new \Exception('Could not retrieve cached data');
}

return $data;
}
}
7 changes: 3 additions & 4 deletions src/Library/Economy/Currency/ExchangeInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

use App\Entity\Money;
use Brick\Money\Exception\CurrencyConversionException;
use Brick\Money\MoneyContainer;

interface ExchangeInterface
{
Expand All @@ -19,14 +18,14 @@ public function getName(): string;
public function getWeight(): int;

/**
* @param MoneyContainer $money The money to be converted
* @param string $toCurrency The currency to convert to
* @param Money $money The money to be converted
* @param string $toCurrency The currency to convert to
*
* @return Money The converted Money
*
* @throws CurrencyConversionException If the exchange rate is not available
*/
public function convert(MoneyContainer $money, string $toCurrency): Money;
public function convert(Money $money, string $toCurrency): Money;

/**
* @param string $fromCurrency The currency to convert from
Expand Down
12 changes: 6 additions & 6 deletions src/Library/Economy/Currency/ExchangeLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class ExchangeLocator
{
/**
* @var ExchangeInterface[]
* @var array<string, ExchangeInterface>
*/
private array $exchanges;

Expand All @@ -33,9 +33,9 @@ public function __construct(iterable $exchanges)
}

/**
* @return ExchangeInterface[]
* @return array<string, ExchangeInterface>
*/
public function getExchanges(): array
public function getAll(): array
{
return $this->exchanges;
}
Expand All @@ -45,10 +45,10 @@ public function getExchanges(): array
*
* @throws \Exception When the $name does not match to that of an implemented Exchange
*/
public function getExchange(string $name): ExchangeInterface
public function getByName(string $name): ExchangeInterface
{
if (!\array_key_exists($name, $this->exchanges)) {
throw new \Exception("No such Exchange with the name $name");
throw new \Exception("No such Exchange with the name '$name'");
}

return $this->exchanges[$name];
Expand All @@ -60,7 +60,7 @@ public function getExchange(string $name): ExchangeInterface
*
* @throws CurrencyConversionException If the exchange rate is not available
*/
public function getExchangeFor(string $source, string $target): ExchangeInterface
public function get(string $source, string $target): ExchangeInterface
{
foreach ($this->exchanges as $exchange) {
try {
Expand Down
4 changes: 2 additions & 2 deletions src/Library/Economy/MoneyService.php
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ private function convert(Money $money, string $toCurrency): Brick\Money
return self::toBrick($money);
}

$exchange = $this->exchangeLocator->getExchangeFor($fromCurrency, $toCurrency);
$exchange = $this->exchangeLocator->get($fromCurrency, $toCurrency);

return self::toBrick($exchange->convert(self::toBrick($money), $toCurrency));
return self::toBrick($exchange->convert($money, $toCurrency));
}
}

0 comments on commit 8daec98

Please sign in to comment.