<?php
class ExchangeRate {
private array $rates = [];
private string $base;
private string $cacheFile;
private int $cacheLifetime = 14400;
public function __construct(
Currency $base, string $url, string $cache, int $lifetime
) {
$this->cacheFile = $cache;
$this->cacheLifetime = $lifetime;
$url = $base->replace( $url, '{{currency}}' );
if( $this->expired( $cache ) ) {
$this->fetch( $url, $cache );
} else {
$this->fetch( $cache, $cache );
}
}
public function convert( Money $money, Currency $targetCurrency ): Money {
return $money->convert( $this, $targetCurrency );
}
public function rate( Currency $source, Currency $target ): float {
$sourceRate = $this->rateFor( $source );
$targetRate = $this->rateFor( $target );
return $targetRate / $sourceRate;
}
public function clearCache(): void {
if( file_exists( $this->cacheFile ) ) {
unlink( $this->cacheFile );
}
}
private function expired( string $cache ): bool {
return
!file_exists( $cache ) ||
(time() - filemtime( $cache )) > $this->cacheLifetime;
}
private function fetch( string $source, string $cache ): void {
$response = @file_get_contents( $source );
if( is_string( $response ) ) {
$payload = json_decode( $response, true );
if( isset( $payload['rates'] ) ) {
$this->rates = $payload['rates'];
$this->rates[ 'CAD' ] = 1.0;
if( $source !== $cache ) {
file_put_contents( $cache, json_encode( $payload ) );
}
}
}
}
private function rateFor( Currency $currency ): float {
return (float)$this->rates[ $currency->toString() ];
}
}