Skip to content

Commit

Permalink
Fix ISOCurrencies
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardogobbosouza committed Dec 2, 2024
1 parent a46113c commit 843a7a6
Show file tree
Hide file tree
Showing 4 changed files with 177 additions and 13 deletions.
86 changes: 86 additions & 0 deletions src/Currencies/ISOCurrencies.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

namespace Cknow\Money\Currencies;

use ArrayIterator;
use Money\Currencies;
use Money\Currency;
use Money\Exception\UnknownCurrencyException;
use Traversable;

class ISOCurrencies implements Currencies
{
/**
* @var array
*/
private static $currencies;

public function contains(Currency $currency): bool
{
return isset($this->getCurrencies()[$currency->getCode()]);
}

public function subunitFor(Currency $currency): int
{
if (! $this->contains($currency)) {
throw new UnknownCurrencyException('Cannot find ISO currency '.$currency->getCode());
}

return $this->getCurrencies()[$currency->getCode()]['minorUnit'];
}

/**
* Returns the numeric code for a currency.
*
* @throws UnknownCurrencyException If currency is not available in the current context.
*/
public function numericCodeFor(Currency $currency): int
{
if (! $this->contains($currency)) {
throw new UnknownCurrencyException('Cannot find ISO currency '.$currency->getCode());
}

return $this->getCurrencies()[$currency->getCode()]['numericCode'];
}

#[\ReturnTypeWillChange]
public function getIterator(): Traversable
{
return new ArrayIterator(
array_map(
static function ($code) {
return new Currency($code);
},
array_keys($this->getCurrencies())
)
);
}

/**
* Returns a map of known currencies indexed by code.
*
* @return array
*/
public function getCurrencies()
{
if (self::$currencies === null) {
self::$currencies = $this->loadCurrencies();
}

return self::$currencies;
}

/**
* @return array
*/
protected function loadCurrencies()
{
$file = config('money.isoCurrenciesPath');

if (file_exists($file)) {
return require $file;
}

throw new \RuntimeException('Failed to load currency ISO codes.');
}
}
13 changes: 2 additions & 11 deletions src/CurrenciesTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

namespace Cknow\Money;

use Cknow\Money\Currencies\ISOCurrencies;
use InvalidArgumentException;
use Money\Currencies;
use Money\Currencies\AggregateCurrencies;
use Money\Currencies\BitcoinCurrencies;
use Money\Currencies\CurrencyList;
use Money\Currencies\ISOCurrencies;
use Money\Currency;

trait CurrenciesTrait
Expand All @@ -22,11 +22,6 @@ trait CurrenciesTrait
*/
protected static $currencies;

/**
* @var array
*/
protected static $ISOCurrencies;

/**
* Parse currency.
*
Expand Down Expand Up @@ -84,11 +79,7 @@ public static function setDefaultCurrency($currency)
*/
public static function getISOCurrencies()
{
if (! isset(static::$ISOCurrencies) && is_file($file = config('money.isoCurrenciesPath'))) {
static::$ISOCurrencies = require $file;
}

return static::$ISOCurrencies;
return (new ISOCurrencies())->getCurrencies();
}

/**
Expand Down
86 changes: 86 additions & 0 deletions tests/Currencies/ISOCurrenciesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php

namespace Cknow\Money\Tests\Currencies;

use Cknow\Money\Currencies\ISOCurrencies;
use Cknow\Money\Tests\TestCase;

class ISOCurrenciesTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
}

public function testContains()
{
$currencies = new ISOCurrencies();
static::assertTrue($currencies->contains(new \Money\Currency('EUR')));
static::assertTrue($currencies->contains(new \Money\Currency('USD')));
}

public function testSubunitFor()
{
$currencies = new ISOCurrencies();
static::assertEquals(2, $currencies->subunitFor(new \Money\Currency('EUR')));
static::assertEquals(2, $currencies->subunitFor(new \Money\Currency('USD')));
}

public function testSubunitForInvalidCurrency()
{
$this->expectException(\Money\Exception\UnknownCurrencyException::class);
$this->expectExceptionMessage('Cannot find ISO currency XYZ');

$currencies = new ISOCurrencies();
$currencies->subunitFor(new \Money\Currency('XYZ'));
}

public function testNumericCodeFor()
{
$currencies = new ISOCurrencies();
static::assertEquals(978, $currencies->numericCodeFor(new \Money\Currency('EUR')));
static::assertEquals(840, $currencies->numericCodeFor(new \Money\Currency('USD')));
}

public function testNumericCodeForInvalidCurrency()
{
$this->expectException(\Money\Exception\UnknownCurrencyException::class);
$this->expectExceptionMessage('Cannot find ISO currency XYZ');

$currencies = new ISOCurrencies();
$currencies->numericCodeFor(new \Money\Currency('XYZ'));
}

public function testLoadCurrencies()
{
$currencies = new ISOCurrencies();
static::assertContainsOnlyInstancesOf(\Money\Currency::class, $currencies->getIterator());
}

public function testGetCurrencies()
{
$currencies = new ISOCurrencies();

static::assertIsArray($currencies->getCurrencies());
static::assertArrayHasKey('EUR', $currencies->getCurrencies());
static::assertArrayHasKey('USD', $currencies->getCurrencies());
static::assertArrayNotHasKey('XYZ', $currencies->getCurrencies());
}

public function testInvalidConfigCurrenciesPath()
{
config(['money.isoCurrenciesPath' => null]);

$this->expectException(\RuntimeException::class);
$this->expectExceptionMessage('Failed to load currency ISO codes.');

$currencies = new ISOCurrencies();

$reflection = new \ReflectionObject($currencies);
$property = $reflection->getProperty('currencies');
$property->setAccessible(true);
$property->setValue($currencies, null);

$currencies->getCurrencies();
}
}
5 changes: 3 additions & 2 deletions tests/CurrenciesTraitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace Cknow\Money\Tests;

use Cknow\Money\Currencies\ISOCurrencies;
use Cknow\Money\CurrenciesTrait;
use Money\Currency;
use stdClass;
Expand Down Expand Up @@ -139,7 +140,7 @@ public function testSetCurrenciesDefaultCurrenciesConfig()
$mock = $this->getMockForTrait(CurrenciesTrait::class);
$mock->setCurrencies([]);

static::assertInstanceOf(\Money\Currencies\ISOCurrencies::class, $mock->getCurrencies());
static::assertInstanceOf(ISOCurrencies::class, $mock->getCurrencies());
}

public function testSetCurrenciesAllISOCurrencies()
Expand All @@ -150,7 +151,7 @@ public function testSetCurrenciesAllISOCurrencies()
]);

static::assertEquals(
new \Money\Currencies\AggregateCurrencies([new \Money\Currencies\ISOCurrencies()]),
new \Money\Currencies\AggregateCurrencies([new ISOCurrencies()]),
$mock->getCurrencies()
);
}
Expand Down

0 comments on commit 843a7a6

Please sign in to comment.