Skip to content

Commit

Permalink
feat(CurrencyInterface): for more customize
Browse files Browse the repository at this point in the history
  • Loading branch information
h4kuna committed Jul 27, 2024
1 parent 0ca1e0d commit 9003ab9
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 39 deletions.
25 changes: 21 additions & 4 deletions src/Currency/Property.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,43 @@

namespace h4kuna\Exchange\Currency;

use Stringable;
use h4kuna\Exchange\CurrencyInterface;

class Property implements Stringable
class Property implements CurrencyInterface
{
/** @deprecated become private, use getRate() method */
public float $rate;

/** @deprecated become private, use getCode() method */
public string $code;


public function __construct(
public int $foreign,
public float $home,
public string $code,
string $code,
)
{
$this->code = $code;
$this->rate = $this->foreign === 0 ? 0.0 : $this->home / $this->foreign;
}


public function __toString(): string
public function getRate(): float
{
return $this->rate;
}


public function getCode(): string
{
return $this->code;
}


public function __toString(): string
{
return $this->getCode();
}

}
15 changes: 15 additions & 0 deletions src/CurrencyInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?php declare(strict_types=1);

namespace h4kuna\Exchange;

interface CurrencyInterface
{
function getRate(): float;


/**
* Recommend to use ISO 4217
* @see https://en.wikipedia.org/wiki/ISO_4217
*/
function getCode(): string;
}
4 changes: 2 additions & 2 deletions src/Download/SourceDownload.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@ public function execute(Source $sourceExchange, ?DateTimeInterface $date): Ratin
$properties = [];
foreach ($sourceData->properties as $item) {
$property = $sourceExchange->createProperty($item);
if ($property->rate === 0.0 || ($this->allowedCurrencies !== [] && isset($this->allowedCurrencies[$property->code]) === false)) {
if ($property->getRate() === 0.0 || ($this->allowedCurrencies !== [] && isset($this->allowedCurrencies[$property->getCode()]) === false)) {
continue;
}

$properties[$property->code] = $property;
$properties[$property->getCode()] = $property;
}

return new RatingList($sourceData->date, $date, $expire, $properties);
Expand Down
4 changes: 2 additions & 2 deletions src/Driver/Source.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

use DateTimeInterface;
use DateTimeZone;
use h4kuna\Exchange\Currency\Property;
use h4kuna\Exchange\CurrencyInterface;
use h4kuna\Exchange\Download\SourceData;
use Psr\Http\Message\ResponseInterface;

Expand All @@ -19,6 +19,6 @@ function getTimeZone(): DateTimeZone;
function createSourceData(ResponseInterface $response): SourceData;


function createProperty(mixed $row): Property;
function createProperty(mixed $row): CurrencyInterface;

}
30 changes: 16 additions & 14 deletions src/Exchange.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,39 +3,41 @@
namespace h4kuna\Exchange;

use ArrayAccess;
use h4kuna\Exchange\Currency\Property;
use h4kuna\Exchange\Exceptions\UnknownCurrencyException;
use h4kuna\Exchange\RatingList\RatingListInterface;
use IteratorAggregate;

/**
* @template T of CurrencyInterface
* @since 2009-06-22 - version 0.5
* @implements IteratorAggregate<string, Property>
* @implements ArrayAccess<string, Property>
* @implements IteratorAggregate<string, T>
* @implements ArrayAccess<string, T>
* properties become readonly
*/
class Exchange implements IteratorAggregate, ArrayAccess
{
private Property $from;
private CurrencyInterface $from;

private Property $to;
private CurrencyInterface $to;


public function __construct(
string $from,
string|CurrencyInterface $from,
public RatingListInterface $ratingList,
?string $to = null,
string|CurrencyInterface|null $to = null,
)
{
$this->from = $this->get($from);
$this->to = $to === null ? $this->from : $this->get($to);
$this->from = $from instanceof CurrencyInterface ? $from : $this->get($from);
$this->to = $to === null
? $this->from
: ($to instanceof CurrencyInterface ? $to : $this->get($to));
}


/**
* @throws UnknownCurrencyException
*/
public function get(string $code): Property
public function get(string $code): CurrencyInterface
{
return $this->ratingList->getSafe($code);
}
Expand All @@ -53,20 +55,20 @@ public function change(float|int|null $price, ?string $from = null, ?string $to
$from = $this->getFrom($from);
$to = $this->getTo($to);
if ($to !== $from) {
$price *= $from->rate / $to->rate;
$price *= $from->getRate() / $to->getRate();
}

return (float) $price;
}


public function getFrom(?string $from = null): Property
public function getFrom(?string $from = null): CurrencyInterface
{
return $from === null ? $this->from : $this->ratingList->get($from);
}


public function getTo(?string $to = null): Property
public function getTo(?string $to = null): CurrencyInterface
{
return $to === null ? $this->to : $this->ratingList->get($to);
}
Expand All @@ -84,7 +86,7 @@ public function offsetExists(mixed $offset): bool
}


public function offsetGet(mixed $offset): Property
public function offsetGet(mixed $offset): CurrencyInterface
{
return $this->get($offset);
}
Expand Down
12 changes: 11 additions & 1 deletion src/ExchangeFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\RequestFactoryInterface;

/**
* @template T of CurrencyInterface
* @implements ExchangeFactoryInterface<T>
*/
final class ExchangeFactory implements ExchangeFactoryInterface
{
private RatingListCache $ratingListCache;
Expand Down Expand Up @@ -49,17 +53,23 @@ private static function createRatingListCache(
}


/**
* @return Exchange<T>
*/
public function create(
?string $from = null,
?string $to = null,
?CacheEntity $cacheEntity = null,
): Exchange
{
return new Exchange(
/** @var Exchange<T> $exchange */
$exchange = new Exchange(
$from ?? $this->from,
$this->ratingListCache->build($cacheEntity ?? new CacheEntity()),
$to ?? $this->to,
);

return $exchange;
}


Expand Down
6 changes: 6 additions & 0 deletions src/ExchangeFactoryInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@

use h4kuna\Exchange\RatingList\CacheEntity;

/**
* @template T of CurrencyInterface
*/
interface ExchangeFactoryInterface
{
/**
* @return Exchange<T>
*/
public function create(
?string $from = null,
?string $to = null,
Expand Down
12 changes: 6 additions & 6 deletions src/RatingList/RatingList.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use ArrayIterator;
use DateTime;
use DateTimeImmutable;
use h4kuna\Exchange\Currency\Property;
use h4kuna\Exchange\CurrencyInterface;
use h4kuna\Exchange\Exceptions\FrozenMethodException;
use h4kuna\Exchange\Exceptions\UnknownCurrencyException;

Expand All @@ -15,7 +15,7 @@
final class RatingList implements RatingListInterface
{
/**
* @param array<string, Property> $properties
* @param array<string, CurrencyInterface> $properties
*/
public function __construct(
private DateTimeImmutable $date,
Expand All @@ -34,21 +34,21 @@ public function getRequest(): ?DateTimeImmutable


/**
* @return ArrayIterator<string, Property>
* @return ArrayIterator<string, CurrencyInterface>
*/
public function getIterator(): ArrayIterator
{
return new ArrayIterator($this->properties);
}


public function offsetGet(mixed $offset): Property
public function offsetGet(mixed $offset): CurrencyInterface
{
return $this->get($offset);
}


public function get(string $code): Property
public function get(string $code): CurrencyInterface
{
// no check if exist for fast
return $this->properties[$code];
Expand All @@ -67,7 +67,7 @@ public function offsetUnset(mixed $offset): void
}


public function getSafe(string $code): Property
public function getSafe(string $code): CurrencyInterface
{
$code = strtoupper($code);
if ($this->offsetExists($code) === false) {
Expand Down
10 changes: 5 additions & 5 deletions src/RatingList/RatingListInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@
use ArrayAccess;
use DateTime;
use DateTimeImmutable;
use h4kuna\Exchange\Currency\Property;
use h4kuna\Exchange\CurrencyInterface;
use h4kuna\Exchange\Exceptions\UnknownCurrencyException;
use IteratorAggregate;

/**
* @extends IteratorAggregate<string, Property>
* @extends ArrayAccess<string, Property>
* @extends IteratorAggregate<string, CurrencyInterface>
* @extends ArrayAccess<string, CurrencyInterface>
*/
interface RatingListInterface extends IteratorAggregate, ArrayAccess
{

/**
* check currency if exist before use, then error undefined index
*/
function get(string $code): Property;
function get(string $code): CurrencyInterface;


/**
* @throws UnknownCurrencyException
*/
function getSafe(string $code): Property;
function getSafe(string $code): CurrencyInterface;


function getRequest(): ?DateTimeImmutable;
Expand Down
2 changes: 1 addition & 1 deletion tests/src/Currency/PropertyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ final class PropertyTest extends TestCase
public function testBasic(): void
{
$property = new Property(10, 1, 'DOO');
Assert::same(.1, $property->rate);
Assert::same(.1, $property->getRate());
Assert::same('DOO', (string) $property);
}

Expand Down
9 changes: 6 additions & 3 deletions tests/src/ExchangeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public function testIteratorAggregate(): void
public function testArrayAccess(): void
{
$exchange = self::createExchange();
Assert::same('EUR', $exchange['EUR']->code);
Assert::same('EUR', $exchange['EUR']->getCode());
Assert::true(isset($exchange['EUR']));
Assert::false(isset($exchange['CCC']));

Expand All @@ -82,7 +82,7 @@ public function testArrayAccess(): void
Assert::exception(fn () => $exchange->get('AAA'), UnknownCurrencyException::class);
}


/** @return Exchange<Property> */
private static function createExchange(): Exchange
{
$ratingList = new RatingList(new \DateTimeImmutable(), null, null, [
Expand Down Expand Up @@ -110,7 +110,10 @@ private static function createExchange(): Exchange

$ratingListCache = new RatingListCache($ratingListCache, $sourceDownload);

return new Exchange('EUR', $ratingListCache->build(new CacheEntity()));
/** @var Exchange<Property> $exchange */
$exchange = new Exchange('EUR', $ratingListCache->build(new CacheEntity()));

return $exchange;
}
}

Expand Down
2 changes: 1 addition & 1 deletion tests/src/RatingList/RatingListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function testBasic(): void
'USD' => new Property(10, 130, 'USD'),
]);

Assert::same(26.0, $ratingList['EUR']->rate);
Assert::same(26.0, $ratingList['EUR']->getRate());

Assert::exception(fn () => $ratingList->getSafe(''), UnknownCurrencyException::class, '[empty string]');
Assert::exception(fn () => $ratingList->getSafe('AAA'), UnknownCurrencyException::class, 'AAA');
Expand Down

0 comments on commit 9003ab9

Please sign in to comment.