Merge pull request #35 from GoteoFoundation/feat/update-exchanges
[feat] Update exchanges
This commit is contained in:
@@ -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;
|
||||
@@ -20,6 +20,9 @@ use Symfony\Contracts\Cache\ItemInterface;
|
||||
*/
|
||||
class EuropeanCentralBankExchange implements ExchangeInterface
|
||||
{
|
||||
public const NAME = 'european_central_bank';
|
||||
public const WEIGHT = 100;
|
||||
|
||||
public const ISO_4217 = 'EUR';
|
||||
|
||||
/**
|
||||
@@ -53,88 +56,31 @@ class EuropeanCentralBankExchange implements ExchangeInterface
|
||||
$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
|
||||
{
|
||||
$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'];
|
||||
}
|
||||
|
||||
private function getDataCached(): array
|
||||
{
|
||||
$data = $this->cache->get($this->getName(), function (ItemInterface $item): array {
|
||||
$item->expiresAfter(self::ECB_DATA_TTL);
|
||||
|
||||
return $this->getDataLatest();
|
||||
});
|
||||
|
||||
if (!$data) {
|
||||
throw new \Exception('Could not retrieve cached data');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function getDataUpdatedDate(string $time): \DateTimeInterface
|
||||
{
|
||||
return \DateTime::createFromFormat(
|
||||
\DateTimeInterface::RFC3339,
|
||||
sprintf('%sT16:00:00+01:00', $time),
|
||||
new \DateTimeZone(self::ECB_TIMEZONE)
|
||||
);
|
||||
}
|
||||
|
||||
public function getData(): array
|
||||
{
|
||||
try {
|
||||
$cachedData = $this->getDataCached();
|
||||
|
||||
$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());
|
||||
$cachedData = $this->getDataCached();
|
||||
}
|
||||
|
||||
return $cachedData;
|
||||
} catch (\Exception $e) {
|
||||
return $this->getDataLatest();
|
||||
}
|
||||
}
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return 'european_central_bank';
|
||||
return self::NAME;
|
||||
}
|
||||
|
||||
public function getWeight(): int
|
||||
{
|
||||
return 100;
|
||||
return self::WEIGHT;
|
||||
}
|
||||
|
||||
public function convert(MoneyContainer $money, string $toCurrency): EntityMoney
|
||||
public function convert(Money $money, string $toCurrency): Money
|
||||
{
|
||||
$converted = $this->converter->convert(
|
||||
$money,
|
||||
MoneyService::toBrick($money),
|
||||
$toCurrency,
|
||||
null,
|
||||
RoundingMode::HALF_EVEN
|
||||
);
|
||||
|
||||
return new EntityMoney(
|
||||
return new Money(
|
||||
$converted->getMinorAmount()->toInt(),
|
||||
$converted->getCurrency()->getCurrencyCode()
|
||||
);
|
||||
@@ -151,4 +97,61 @@ class EuropeanCentralBankExchange implements ExchangeInterface
|
||||
|
||||
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);
|
||||
|
||||
if (
|
||||
$currentDate > $currentDayAt16
|
||||
&& $cachedDate < $currentDayAt16
|
||||
) {
|
||||
$this->cache->delete(self::NAME);
|
||||
$cachedData = $this->getDataCached();
|
||||
}
|
||||
|
||||
return $cachedData;
|
||||
} catch (\Exception $e) {
|
||||
return $this->getDataLatest();
|
||||
}
|
||||
}
|
||||
|
||||
private function parseECBTime(string $time): \DateTimeInterface
|
||||
{
|
||||
return \DateTime::createFromFormat(
|
||||
\DateTimeInterface::RFC3339,
|
||||
\sprintf('%sT16:00:00+01:00', $time),
|
||||
new \DateTimeZone(self::ECB_TIMEZONE)
|
||||
);
|
||||
}
|
||||
|
||||
private function getDataLatest(): array
|
||||
{
|
||||
$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'];
|
||||
}
|
||||
|
||||
private function getDataCached(): array
|
||||
{
|
||||
$data = $this->cache->get(self::NAME, function (ItemInterface $item): array {
|
||||
$item->expiresAfter(self::ECB_DATA_TTL);
|
||||
|
||||
return $this->getDataLatest();
|
||||
});
|
||||
|
||||
if (!$data) {
|
||||
throw new \Exception('Could not retrieve cached data');
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace App\Library\Economy\Currency;
|
||||
|
||||
use App\Entity\Money;
|
||||
use Brick\Money\Exception\CurrencyConversionException;
|
||||
use Brick\Money\MoneyContainer;
|
||||
|
||||
interface ExchangeInterface
|
||||
{
|
||||
@@ -19,14 +18,14 @@ interface ExchangeInterface
|
||||
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
|
||||
|
||||
@@ -7,7 +7,7 @@ use Brick\Money\Exception\CurrencyConversionException;
|
||||
class ExchangeLocator
|
||||
{
|
||||
/**
|
||||
* @var ExchangeInterface[]
|
||||
* @var array<string, ExchangeInterface>
|
||||
*/
|
||||
private array $exchanges;
|
||||
|
||||
@@ -33,9 +33,9 @@ class ExchangeLocator
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ExchangeInterface[]
|
||||
* @return array<string, ExchangeInterface>
|
||||
*/
|
||||
public function getExchanges(): array
|
||||
public function getAll(): array
|
||||
{
|
||||
return $this->exchanges;
|
||||
}
|
||||
@@ -45,10 +45,10 @@ class ExchangeLocator
|
||||
*
|
||||
* @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];
|
||||
@@ -60,7 +60,7 @@ class ExchangeLocator
|
||||
*
|
||||
* @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 {
|
||||
|
||||
@@ -78,8 +78,8 @@ class MoneyService
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user