src/NetglueMoney/Service/CurrencyList.php
<?php
namespace NetglueMoney\Service;
use NetglueMoney\Money\Currency;
use NetglueMoney\Money\Money;
use NetglueMoney\Exception;
class CurrencyList
{
/**
* An array of allowed currencies.
* By default all currencies are allowed
* @var array
*/
protected $allow;
/**
* Default Currencies
* @var array
*/
protected $defaults;
/**
* Constructor populates allowed codes with defaults and optionally filters those passed as an argument
*
* @param array|NULL $allow An array of currency codes to allow
* @param array|NULL $deny An array of currency codes to remove from the allowed list,
* or remove from the defaults if no allow is set
* @return void
*/
public function __construct(?array $allow = null, ?array $deny = null)
{
$this->defaults = Currency::getAvailableCurrencies();
if (null !== $allow) {
$this->setAllow($allow);
}
if (null !== $deny) {
$this->remove($deny);
}
}
/**
* Set the allowed currencies to those provided
* @param array $allow
* @return self
*/
public function setAllow(array $allow)
{
$this->allow = null;
foreach ($allow as $code) {
$this->add($code);
}
return $this;
}
/**
* Return an array of all known currency codes
* @return array
*/
public function getKnown()
{
return $this->defaults;
}
/**
* Return the list of allowed codes
* @return array
*/
public function getAllow()
{
if (null !== $this->allow) {
return $this->allow;
}
return $this->defaults;
}
/**
* Whether the given code is allowed
* @param string $code
* @return bool
*/
public function isAllowed($code)
{
return in_array($code, $this->getAllow(), true);
}
/**
* Add a code to the allowed list
* @param string $code
* @return self
*/
public function add($code)
{
$code = $this->assertValidCode($code);
if (! is_array($this->allow)) {
$this->allow = [];
}
$this->allow[] = $code;
return $this;
}
/**
* Remove a currency code from the allow list
* @param array|string $code
* @return self
*/
public function remove($code)
{
if (is_array($code)) {
foreach ($code as $c) {
$this->remove($c);
}
return $this;
}
if (! is_array($this->allow)) {
$this->allow = $this->defaults;
}
$code = $this->assertValidCode($code);
if ($this->isAllowed($code)) {
if ($key = array_search($code, $this->allow)) {
unset($this->allow[$key]);
}
}
return $this;
}
/**
* Ensure the given code is a known valid code
* @param string|Currency|Money $code
* @return string Normalised code
* @throws Exception\ExceptionInterface
*/
protected function assertValidCode($code)
{
if ($code instanceof Money) {
$code = $code->getCurrency();
}
if ($code instanceof Currency) {
return (string) $code;
}
if (! is_string($code)) {
throw new Exception\InvalidArgumentException(sprintf(
'Currency code should be a string. Received %s',
gettype($code)
));
}
$code = trim(strtoupper($code));
if (! in_array($code, $this->defaults, true)) {
throw new Exception\InvalidCurrencyCodeException(sprintf(
'%s is not a valid ISO 4217 Currency code',
$code
));
}
return $code;
}
}