* @since 1.0.0 */ private static array $ecbCurrencies = []; /** * Constructor. * * @since 1.0.0 * @codeCoverageIgnore */ private function __construct() { } /** * Reset currency rates. * * Can be used in order to refresh them. Be careful currency rates only get updated once a day from the ECB website. * * @return void * * @since 1.0.0 */ public static function resetCurrencies() : void { self::$ecbCurrencies = []; } /** * Convert from EUR * * @param float $value Value to convert * @param string $to Output currency * * @return float * * @since 1.0.0 */ public static function fromEurTo(float $value, string $to) : float { $currencies = self::getEcbEuroRates(); $to = \strtoupper($to); if (!isset($currencies[$to])) { return -1.0; } return $value * $currencies[$to]; } /** * Get ECB currency rates. * * @return array * * @throws \Exception This exception is thrown if the XML is malformed * * @since 1.0.0 */ public static function getEcbEuroRates() : array { if (!empty(self::$ecbCurrencies)) { return self::$ecbCurrencies; } $request = new HttpRequest(new HttpUri('https://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml')); $request->setMethod(RequestMethod::GET); try { $xml = new \SimpleXMLElement(Rest::request($request)->getBody()); if (!(\property_exists($xml, 'Cube') && $xml->Cube !== null)) { throw new \Exception('Invalid xml path'); // @codeCoverageIgnore } $node = $xml->Cube->Cube->Cube; self::$ecbCurrencies = []; foreach ($node as $value) { /** @var null|array $attributes */ if (($attributes = $value->attributes()) === null) { continue; } self::$ecbCurrencies[\strtoupper((string) ($attributes['currency']))] = (float) ($attributes['rate']); } } catch (\Throwable $_) { self::$ecbCurrencies = []; // @codeCoverageIgnore } return self::$ecbCurrencies; } /** * Convert to EUR * * @param float $value Value to convert * @param string $from Input currency * * @return float * * @since 1.0.0 */ public static function fromToEur(float $value, string $from) : float { $currencies = self::getEcbEuroRates(); $from = \strtoupper($from); if (!isset($currencies[$from])) { return -1.0; } return $value / $currencies[$from]; } /** * Convert currency based on ECB reates * * @param float $value Value to convert * @param string $from Input currency * @param string $to Output currency * * @return float * * @since 1.0.0 */ public static function convertCurrency(float $value, string $from, string $to) : float { $currencies = self::getEcbEuroRates(); $from = \strtoupper($from); $to = \strtoupper($to); if ((!isset($currencies[$from]) && $from !== ISO4217CharEnum::_EUR) || (!isset($currencies[$to]) && $to !== ISO4217CharEnum::_EUR) ) { return -1.0; } if ($from !== ISO4217CharEnum::_EUR) { $value /= $currencies[$from]; } return $to === ISO4217CharEnum::_EUR ? $value : $value * $currencies[$to]; } }