allow vendord
All checks were successful
Build, Push and Deploy / build-and-push (push) Successful in 3m3s
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 16s
Build, Push and Deploy / deploy-staging (push) Successful in 32s
Build, Push and Deploy / deploy-production (push) Has been skipped
Build, Push and Deploy / cleanup (push) Successful in 1s

This commit is contained in:
2026-03-30 14:54:57 +07:00
parent 66aed7c4e8
commit b5e3a778ce
21316 changed files with 2777892 additions and 13 deletions

152
vendor/moneyphp/money/src/Calculator.php vendored Normal file
View File

@@ -0,0 +1,152 @@
<?php
declare(strict_types=1);
namespace Money;
use Money\Exception\InvalidArgumentException;
/**
* Money calculations abstracted away from the Money value object.
*
* @internal the calculator component is an internal detail of this library: it is only supposed to be replaced if
* your system requires a custom architecture for operating on large numbers.
*/
interface Calculator
{
/**
* Compare a to b.
*
* Retrieves a negative value if $a < $b.
* Retrieves a positive value if $a > $b.
* Retrieves zero if $a == $b
*
* @phpstan-param numeric-string $a
* @phpstan-param numeric-string $b
*
* @phpstan-pure
*/
public static function compare(string $a, string $b): int;
/**
* Add added to amount.
*
* @phpstan-param numeric-string $amount
* @phpstan-param numeric-string $addend
*
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public static function add(string $amount, string $addend): string;
/**
* Subtract subtrahend from amount.
*
* @phpstan-param numeric-string $amount
* @phpstan-param numeric-string $subtrahend
*
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public static function subtract(string $amount, string $subtrahend): string;
/**
* Multiply amount with multiplier.
*
* @phpstan-param numeric-string $amount
* @phpstan-param numeric-string $multiplier
*
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public static function multiply(string $amount, string $multiplier): string;
/**
* Divide amount with divisor.
*
* @phpstan-param numeric-string $amount
* @phpstan-param numeric-string $divisor
*
* @phpstan-return numeric-string
*
* @throws InvalidArgumentException when $divisor is zero.
*
* @phpstan-pure
*/
public static function divide(string $amount, string $divisor): string;
/**
* Round number to following integer.
*
* @phpstan-param numeric-string $number
*
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public static function ceil(string $number): string;
/**
* Round number to preceding integer.
*
* @phpstan-param numeric-string $number
*
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public static function floor(string $number): string;
/**
* Returns the absolute value of the number.
*
* @phpstan-param numeric-string $number
*
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public static function absolute(string $number): string;
/**
* Round number, use rounding mode for tie-breaker.
*
* @phpstan-param numeric-string $number
* @phpstan-param Money::ROUND_* $roundingMode
*
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public static function round(string $number, int $roundingMode): string;
/**
* Share amount among ratio / total portions.
*
* @phpstan-param numeric-string $amount
* @phpstan-param numeric-string $ratio
* @phpstan-param numeric-string $total
*
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public static function share(string $amount, string $ratio, string $total): string;
/**
* Get the modulus of an amount.
*
* @phpstan-param numeric-string $amount
* @phpstan-param numeric-string $divisor
*
* @phpstan-return numeric-string
*
* @throws InvalidArgumentException when $divisor is zero.
*
* @phpstan-pure
*/
public static function mod(string $amount, string $divisor): string;
}

View File

@@ -0,0 +1,227 @@
<?php
declare(strict_types=1);
namespace Money\Calculator;
use InvalidArgumentException as CoreInvalidArgumentException;
use Money\Calculator;
use Money\Exception\InvalidArgumentException;
use Money\Money;
use Money\Number;
use function bcadd;
use function bccomp;
use function bcdiv;
use function bcmod;
use function bcmul;
use function bcsub;
use function ltrim;
use function str_contains;
final class BcMathCalculator implements Calculator
{
private const SCALE = 14;
/** @phpstan-pure */
public static function compare(string $a, string $b): int
{
return bccomp($a, $b, self::SCALE);
}
/** @phpstan-pure */
public static function add(string $amount, string $addend): string
{
$scale = str_contains($amount . $addend, '.') ? self::SCALE : 0;
return bcadd($amount, $addend, $scale);
}
/** @phpstan-pure */
public static function subtract(string $amount, string $subtrahend): string
{
$scale = str_contains($amount . $subtrahend, '.') ? self::SCALE : 0;
return bcsub($amount, $subtrahend, $scale);
}
/** @phpstan-pure */
public static function multiply(string $amount, string $multiplier): string
{
return bcmul($amount, $multiplier, self::SCALE);
}
/**
* @phpstan-pure
*/
public static function divide(string $amount, string $divisor): string
{
if (bccomp($divisor, '0', self::SCALE) === 0) {
throw InvalidArgumentException::divisionByZero();
}
return bcdiv($amount, $divisor, self::SCALE);
}
/** @phpstan-pure */
public static function ceil(string $number): string
{
$number = Number::fromString($number);
if ($number->isInteger()) {
return $number->__toString();
}
if ($number->isNegative()) {
return bcadd($number->__toString(), '0', 0);
}
return bcadd($number->__toString(), '1', 0);
}
/** @phpstan-pure */
public static function floor(string $number): string
{
$number = Number::fromString($number);
if ($number->isInteger()) {
return $number->__toString();
}
if ($number->isNegative()) {
return bcadd($number->__toString(), '-1', 0);
}
return bcadd($number->__toString(), '0', 0);
}
/**
* @phpstan-pure
*/
public static function absolute(string $number): string
{
return ltrim($number, '-');
}
/**
* @phpstan-param Money::ROUND_* $roundingMode
*
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public static function round(string $number, int $roundingMode): string
{
$number = Number::fromString($number);
if ($number->isInteger()) {
return $number->__toString();
}
if ($number->isHalf() === false) {
return self::roundDigit($number);
}
if ($roundingMode === Money::ROUND_HALF_UP) {
return bcadd(
$number->__toString(),
$number->getIntegerRoundingMultiplier(),
0
);
}
if ($roundingMode === Money::ROUND_HALF_DOWN) {
return bcadd($number->__toString(), '0', 0);
}
if ($roundingMode === Money::ROUND_HALF_EVEN) {
if ($number->isCurrentEven()) {
return bcadd($number->__toString(), '0', 0);
}
return bcadd(
$number->__toString(),
$number->getIntegerRoundingMultiplier(),
0
);
}
if ($roundingMode === Money::ROUND_HALF_ODD) {
if ($number->isCurrentEven()) {
return bcadd(
$number->__toString(),
$number->getIntegerRoundingMultiplier(),
0
);
}
return bcadd($number->__toString(), '0', 0);
}
if ($roundingMode === Money::ROUND_HALF_POSITIVE_INFINITY) {
if ($number->isNegative()) {
return bcadd($number->__toString(), '0', 0);
}
return bcadd(
$number->__toString(),
$number->getIntegerRoundingMultiplier(),
0
);
}
if ($roundingMode === Money::ROUND_HALF_NEGATIVE_INFINITY) {
if ($number->isNegative()) {
return bcadd(
$number->__toString(),
$number->getIntegerRoundingMultiplier(),
0
);
}
return bcadd(
$number->__toString(),
'0',
0
);
}
throw new CoreInvalidArgumentException('Unknown rounding mode');
}
/**
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
private static function roundDigit(Number $number): string
{
if ($number->isCloserToNext()) {
return bcadd(
$number->__toString(),
$number->getIntegerRoundingMultiplier(),
0
);
}
return bcadd($number->__toString(), '0', 0);
}
/** @phpstan-pure */
public static function share(string $amount, string $ratio, string $total): string
{
return self::floor(bcdiv(bcmul($amount, $ratio, self::SCALE), $total, self::SCALE));
}
/**
* @phpstan-pure
*/
public static function mod(string $amount, string $divisor): string
{
if (bccomp($divisor, '0') === 0) {
throw InvalidArgumentException::moduloByZero();
}
return bcmod($amount, $divisor);
}
}

View File

@@ -0,0 +1,334 @@
<?php
declare(strict_types=1);
namespace Money\Calculator;
use InvalidArgumentException as CoreInvalidArgumentException;
use Money\Calculator;
use Money\Exception\InvalidArgumentException;
use Money\Money;
use Money\Number;
use function gmp_add;
use function gmp_cmp;
use function gmp_div_q;
use function gmp_div_qr;
use function gmp_init;
use function gmp_mod;
use function gmp_mul;
use function gmp_neg;
use function gmp_strval;
use function gmp_sub;
use function ltrim;
use function str_pad;
use function str_replace;
use function strlen;
use function substr;
use const GMP_ROUND_MINUSINF;
use const STR_PAD_LEFT;
/**
* @phpstan-immutable
*
* Important: the {@see GmpCalculator} is not optimized for decimal operations, as GMP
* is designed to operate on large integers. Consider using this only if your
* system does not have `ext-bcmath` installed.
*/
final class GmpCalculator implements Calculator
{
private const SCALE = 14;
/** @phpstan-pure */
public static function compare(string $a, string $b): int
{
$aNum = Number::fromString($a);
$bNum = Number::fromString($b);
if ($aNum->isDecimal() || $bNum->isDecimal()) {
$integersCompared = gmp_cmp($aNum->getIntegerPart(), $bNum->getIntegerPart());
if ($integersCompared !== 0) {
return $integersCompared;
}
$aNumFractional = $aNum->getFractionalPart() === '' ? '0' : $aNum->getFractionalPart();
$bNumFractional = $bNum->getFractionalPart() === '' ? '0' : $bNum->getFractionalPart();
return gmp_cmp($aNumFractional, $bNumFractional);
}
return gmp_cmp($a, $b);
}
/** @phpstan-pure */
public static function add(string $amount, string $addend): string
{
return gmp_strval(gmp_add($amount, $addend));
}
/** @phpstan-pure */
public static function subtract(string $amount, string $subtrahend): string
{
return gmp_strval(gmp_sub($amount, $subtrahend));
}
/** @phpstan-pure */
public static function multiply(string $amount, string $multiplier): string
{
$multiplier = Number::fromString($multiplier);
if ($multiplier->isDecimal()) {
$decimalPlaces = strlen($multiplier->getFractionalPart());
$multiplierBase = $multiplier->getIntegerPart();
$negativeZero = $multiplierBase === '-0';
if ($negativeZero) {
$multiplierBase = '-';
}
if ($multiplierBase) {
$multiplierBase .= $multiplier->getFractionalPart();
} else {
$multiplierBase = ltrim($multiplier->getFractionalPart(), '0');
}
$resultBase = gmp_strval(gmp_mul(gmp_init($amount), gmp_init($multiplierBase)));
if ($resultBase === '0') {
return '0';
}
$result = substr($resultBase, $decimalPlaces * -1);
$resultLength = strlen($result);
if ($decimalPlaces > $resultLength) {
return '0.' . str_pad('', $decimalPlaces - $resultLength, '0') . $result;
}
$finalResult = substr($resultBase, 0, $decimalPlaces * -1) . '.' . $result;
if ($negativeZero) {
// @phpstan-ignore possiblyImpure.functionCall (see https://github.com/phpstan/phpstan/issues/11884)
$finalResult = str_replace('-.', '-0.', $finalResult);
}
return $finalResult;
}
return gmp_strval(gmp_mul(gmp_init($amount), gmp_init((string) $multiplier)));
}
/** @phpstan-pure */
public static function divide(string $amount, string $divisor): string
{
if (self::compare($divisor, '0') === 0) {
throw InvalidArgumentException::divisionByZero();
}
$divisor = Number::fromString($divisor);
if ($divisor->isDecimal()) {
$decimalPlaces = strlen($divisor->getFractionalPart());
$divisorBase = $divisor->getIntegerPart();
$negativeZero = $divisorBase === '-0';
if ($negativeZero) {
$divisorBase = '-';
}
if ($divisor->getIntegerPart()) {
$divisor = new Number($divisorBase . $divisor->getFractionalPart());
} else {
$divisor = new Number(ltrim($divisor->getFractionalPart(), '0'));
}
$amount = gmp_strval(gmp_mul(gmp_init($amount), gmp_init('1' . str_pad('', $decimalPlaces, '0'))));
}
[$integer, $remainder] = gmp_div_qr(gmp_init($amount), gmp_init((string) $divisor));
if (gmp_cmp($remainder, '0') === 0) {
return gmp_strval($integer);
}
$divisionOfRemainder = gmp_strval(
gmp_div_q(
gmp_mul($remainder, gmp_init('1' . str_pad('', self::SCALE, '0'))),
gmp_init((string) $divisor),
GMP_ROUND_MINUSINF
)
);
if ($divisionOfRemainder[0] === '-') {
$divisionOfRemainder = substr($divisionOfRemainder, 1);
}
return gmp_strval($integer) . '.' . str_pad($divisionOfRemainder, self::SCALE, '0', STR_PAD_LEFT);
}
/** @phpstan-pure */
public static function ceil(string $number): string
{
$number = Number::fromString($number);
if ($number->isInteger()) {
return $number->__toString();
}
if ($number->isNegative()) {
return self::add($number->getIntegerPart(), '0');
}
return self::add($number->getIntegerPart(), '1');
}
/** @phpstan-pure */
public static function floor(string $number): string
{
$number = Number::fromString($number);
if ($number->isInteger()) {
return $number->__toString();
}
if ($number->isNegative()) {
return self::add($number->getIntegerPart(), '-1');
}
return self::add($number->getIntegerPart(), '0');
}
/**
* @phpstan-pure
*/
public static function absolute(string $number): string
{
return ltrim($number, '-');
}
/**
* @phpstan-param Money::ROUND_* $roundingMode
*
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public static function round(string $number, int $roundingMode): string
{
$number = Number::fromString($number);
if ($number->isInteger()) {
return $number->__toString();
}
if ($number->isHalf() === false) {
return self::roundDigit($number);
}
if ($roundingMode === Money::ROUND_HALF_UP) {
return self::add(
$number->getIntegerPart(),
$number->getIntegerRoundingMultiplier()
);
}
if ($roundingMode === Money::ROUND_HALF_DOWN) {
return self::add($number->getIntegerPart(), '0');
}
if ($roundingMode === Money::ROUND_HALF_EVEN) {
if ($number->isCurrentEven()) {
return self::add($number->getIntegerPart(), '0');
}
return self::add(
$number->getIntegerPart(),
$number->getIntegerRoundingMultiplier()
);
}
if ($roundingMode === Money::ROUND_HALF_ODD) {
if ($number->isCurrentEven()) {
return self::add(
$number->getIntegerPart(),
$number->getIntegerRoundingMultiplier()
);
}
return self::add($number->getIntegerPart(), '0');
}
if ($roundingMode === Money::ROUND_HALF_POSITIVE_INFINITY) {
if ($number->isNegative()) {
return self::add(
$number->getIntegerPart(),
'0'
);
}
return self::add(
$number->getIntegerPart(),
$number->getIntegerRoundingMultiplier()
);
}
if ($roundingMode === Money::ROUND_HALF_NEGATIVE_INFINITY) {
if ($number->isNegative()) {
return self::add(
$number->getIntegerPart(),
$number->getIntegerRoundingMultiplier()
);
}
return self::add(
$number->getIntegerPart(),
'0'
);
}
throw new CoreInvalidArgumentException('Unknown rounding mode');
}
/**
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
private static function roundDigit(Number $number): string
{
if ($number->isCloserToNext()) {
return self::add(
$number->getIntegerPart(),
$number->getIntegerRoundingMultiplier()
);
}
return self::add($number->getIntegerPart(), '0');
}
/** @phpstan-pure */
public static function share(string $amount, string $ratio, string $total): string
{
return self::floor(self::divide(self::multiply($amount, $ratio), $total));
}
/** @phpstan-pure */
public static function mod(string $amount, string $divisor): string
{
if (self::compare($divisor, '0') === 0) {
throw InvalidArgumentException::moduloByZero();
}
// gmp_mod() only calculates non-negative integers, so we use absolutes
$remainder = gmp_mod(self::absolute($amount), self::absolute($divisor));
// If the amount was negative, we negate the result of the modulus operation
$amount = Number::fromString($amount);
if ($amount->isNegative()) {
$remainder = gmp_neg($remainder);
}
return gmp_strval($remainder);
}
}

78
vendor/moneyphp/money/src/Converter.php vendored Normal file
View File

@@ -0,0 +1,78 @@
<?php
declare(strict_types=1);
namespace Money;
use InvalidArgumentException;
use function sprintf;
/**
* Provides a way to convert Money to Money in another Currency using an exchange rate.
*/
final class Converter
{
public function __construct(private readonly Currencies $currencies, private readonly Exchange $exchange)
{
}
/**
* @param Money::ROUND_* $roundingMode
*/
public function convert(Money $money, Currency $counterCurrency, int $roundingMode = Money::ROUND_HALF_UP): Money
{
return $this->convertAgainstCurrencyPair(
$money,
$this->exchange->quote(
$money->getCurrency(),
$counterCurrency
),
$roundingMode
);
}
/**
* @param Money::ROUND_* $roundingMode
*
* @return array{0: Money, 1: CurrencyPair}
*/
public function convertAndReturnWithCurrencyPair(Money $money, Currency $counterCurrency, int $roundingMode = Money::ROUND_HALF_UP): array
{
$pair = $this->exchange->quote(
$money->getCurrency(),
$counterCurrency
);
return [$this->convertAgainstCurrencyPair($money, $pair, $roundingMode), $pair];
}
/**
* @param Money::ROUND_* $roundingMode
*/
public function convertAgainstCurrencyPair(Money $money, CurrencyPair $currencyPair, int $roundingMode = Money::ROUND_HALF_UP): Money
{
if (! $money->getCurrency()->equals($currencyPair->getBaseCurrency())) {
throw new InvalidArgumentException(
sprintf(
'Expecting to convert against base currency %s, but got %s instead',
$money->getCurrency()->getCode(),
$currencyPair->getBaseCurrency()->getCode()
)
);
}
$ratio = $currencyPair->getConversionRatio();
$baseCurrencySubunit = $this->currencies->subunitFor($currencyPair->getBaseCurrency());
$counterCurrencySubunit = $this->currencies->subunitFor($currencyPair->getCounterCurrency());
$subunitDifference = $baseCurrencySubunit - $counterCurrencySubunit;
$ratio = Number::fromString($ratio)
->base10($subunitDifference)
->__toString();
$counterValue = $money->multiply($ratio, $roundingMode);
return new Money($counterValue->getAmount(), $currencyPair->getCounterCurrency());
}
}

View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace Money;
use IteratorAggregate;
use Money\Exception\UnknownCurrencyException;
use Traversable;
/**
* Implement this to provide a list of currencies.
*
* @extends IteratorAggregate<int|string, Currency>
*/
interface Currencies extends IteratorAggregate
{
/**
* Checks whether a currency is available in the current context.
*/
public function contains(Currency $currency): bool;
/**
* Returns the subunit for a currency.
*
* @throws UnknownCurrencyException If currency is not available in the current context.
*/
public function subunitFor(Currency $currency): int;
/**
* @return Traversable<int|string, Currency>
*/
public function getIterator(): Traversable;
}

View File

@@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
namespace Money\Currencies;
use AppendIterator;
use IteratorIterator;
use Money\Currencies;
use Money\Currency;
use Money\Exception\UnknownCurrencyException;
use Traversable;
/**
* Aggregates several currency repositories.
*/
final class AggregateCurrencies implements Currencies
{
/**
* @param Currencies[] $currencies
*/
public function __construct(private readonly array $currencies)
{
}
public function contains(Currency $currency): bool
{
foreach ($this->currencies as $currencies) {
if ($currencies->contains($currency)) {
return true;
}
}
return false;
}
public function subunitFor(Currency $currency): int
{
foreach ($this->currencies as $currencies) {
if ($currencies->contains($currency)) {
return $currencies->subunitFor($currency);
}
}
throw new UnknownCurrencyException('Cannot find currency ' . $currency->getCode());
}
/** {@inheritDoc} */
public function getIterator(): Traversable
{
$iterator = new AppendIterator();
foreach ($this->currencies as $currencies) {
$iterator->append(new IteratorIterator($currencies->getIterator()));
}
return $iterator;
}
}

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace Money\Currencies;
use ArrayIterator;
use Money\Currencies;
use Money\Currency;
use Money\Exception\UnknownCurrencyException;
use Traversable;
final class BitcoinCurrencies implements Currencies
{
public const CODE = 'XBT';
public const SYMBOL = "\xC9\x83";
public function contains(Currency $currency): bool
{
return $currency->getCode() === self::CODE;
}
public function subunitFor(Currency $currency): int
{
if ($currency->getCode() !== self::CODE) {
throw new UnknownCurrencyException($currency->getCode() . ' is not bitcoin and is not supported by this currency repository');
}
return 8;
}
/** {@inheritDoc} */
public function getIterator(): Traversable
{
return new ArrayIterator([new Currency(self::CODE)]);
}
}

View File

@@ -0,0 +1,79 @@
<?php
declare(strict_types=1);
namespace Money\Currencies;
use ArrayIterator;
use Cache\TagInterop\TaggableCacheItemInterface;
use CallbackFilterIterator;
use Money\Currencies;
use Money\Currency;
use Psr\Cache\CacheItemPoolInterface;
use Traversable;
use function iterator_to_array;
/**
* Cache the result of currency checking.
*/
final class CachedCurrencies implements Currencies
{
public function __construct(private readonly Currencies $currencies, private readonly CacheItemPoolInterface $pool)
{
}
public function contains(Currency $currency): bool
{
$item = $this->pool->getItem('currency|availability|' . $currency->getCode());
if ($item->isHit() === false) {
$item->set($this->currencies->contains($currency));
if ($item instanceof TaggableCacheItemInterface) {
$item->setTags(['currency.availability']);
}
$this->pool->save($item);
}
return (bool) $item->get();
}
public function subunitFor(Currency $currency): int
{
$item = $this->pool->getItem('currency|subunit|' . $currency->getCode());
if ($item->isHit() === false) {
$item->set($this->currencies->subunitFor($currency));
if ($item instanceof TaggableCacheItemInterface) {
$item->setTags(['currency.subunit']);
}
$this->pool->save($item);
}
return (int) $item->get();
}
/** {@inheritDoc} */
public function getIterator(): Traversable
{
return new CallbackFilterIterator(
new ArrayIterator(iterator_to_array($this->currencies->getIterator())),
function (Currency $currency): bool {
$item = $this->pool->getItem('currency|availability|' . $currency->getCode());
$item->set(true);
if ($item instanceof TaggableCacheItemInterface) {
$item->setTags(['currency.availability']);
}
$this->pool->save($item);
return true;
}
);
}
}

View File

@@ -0,0 +1,95 @@
<?php
declare(strict_types=1);
namespace Money\Currencies;
use ArrayIterator;
use Money\Currencies;
use Money\Currency;
use Money\Exception\UnknownCurrencyException;
use RuntimeException;
use Traversable;
use function array_keys;
use function array_map;
use function is_file;
/**
* List of supported Crypto Currencies codes and names using Binance as resource.
*/
final class CryptoCurrencies implements Currencies
{
/**
* Map of known currencies indexed by code.
*
* @phpstan-var non-empty-array<non-empty-string, array{
* symbol: non-empty-string,
* minorUnit: non-negative-int
* }>|null
*/
private static array|null $currencies = null;
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'];
}
/**
* @phpstan-return Traversable<int, Currency>
*/
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.
*
* @phpstan-return non-empty-array<non-empty-string, array{
* symbol: non-empty-string,
* minorUnit: non-negative-int
* }>
*/
private function getCurrencies(): array
{
if (self::$currencies === null) {
self::$currencies = $this->loadCurrencies();
}
return self::$currencies;
}
/**
* @phpstan-return non-empty-array<non-empty-string, array{
* symbol: non-empty-string,
* minorUnit: non-negative-int
* }>
*/
private function loadCurrencies(): array
{
$file = __DIR__ . '/../../resources/binance.php';
if (is_file($file)) {
return require $file;
}
throw new RuntimeException('Failed to load currency ISO codes.');
}
}

View File

@@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace Money\Currencies;
use ArrayIterator;
use Money\Currencies;
use Money\Currency;
use Money\Exception\UnknownCurrencyException;
use Traversable;
use function array_keys;
use function array_map;
/**
* A list of custom currencies.
*/
final class CurrencyList implements Currencies
{
/**
* Map of currencies and their sub-units indexed by code.
*
* @phpstan-var array<non-empty-string, int>
*/
private array $currencies;
/** @phpstan-param array<non-empty-string, non-negative-int> $currencies */
public function __construct(array $currencies)
{
$this->currencies = $currencies;
}
public function contains(Currency $currency): bool
{
return isset($this->currencies[$currency->getCode()]);
}
public function subunitFor(Currency $currency): int
{
if (! $this->contains($currency)) {
throw new UnknownCurrencyException('Cannot find currency ' . $currency->getCode());
}
return $this->currencies[$currency->getCode()];
}
/** {@inheritDoc} */
public function getIterator(): Traversable
{
return new ArrayIterator(
array_map(
static function ($code) {
return new Currency($code);
},
array_keys($this->currencies)
)
);
}
}

View File

@@ -0,0 +1,115 @@
<?php
declare(strict_types=1);
namespace Money\Currencies;
use ArrayIterator;
use Money\Currencies;
use Money\Currency;
use Money\Exception\UnknownCurrencyException;
use RuntimeException;
use Traversable;
use function array_keys;
use function array_map;
use function is_file;
/**
* List of supported ISO 4217 currency codes and names.
*/
final class ISOCurrencies implements Currencies
{
/**
* Map of known currencies indexed by code.
*
* @phpstan-var non-empty-array<non-empty-string, array{
* alphabeticCode: non-empty-string,
* currency: non-empty-string,
* minorUnit: non-negative-int,
* numericCode: positive-int
* }>|null
*/
private static array|null $currencies = null;
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'];
}
/**
* @phpstan-return Traversable<int, Currency>
*/
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.
*
* @phpstan-return non-empty-array<non-empty-string, array{
* alphabeticCode: non-empty-string,
* currency: non-empty-string,
* minorUnit: non-negative-int,
* numericCode: positive-int
* }>
*/
private function getCurrencies(): array
{
if (self::$currencies === null) {
self::$currencies = $this->loadCurrencies();
}
return self::$currencies;
}
/**
* @phpstan-return non-empty-array<non-empty-string, array{
* alphabeticCode: non-empty-string,
* currency: non-empty-string,
* minorUnit: non-negative-int,
* numericCode: positive-int
* }>
*/
private function loadCurrencies(): array
{
$file = __DIR__ . '/../../resources/currency.php';
if (is_file($file)) {
return require $file;
}
throw new RuntimeException('Failed to load currency ISO codes.');
}
}

64
vendor/moneyphp/money/src/Currency.php vendored Normal file
View File

@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
namespace Money;
use JsonSerializable;
use function strtoupper;
/**
* Currency Value Object.
*
* Holds Currency specific data.
*
* @phpstan-immutable
*/
final class Currency implements JsonSerializable
{
/**
* Currency code.
*
* @phpstan-var non-empty-string
*/
private string $code;
/**
* @phpstan-param non-empty-string $code
*
* @phpstan-pure
*/
public function __construct(string $code)
{
$this->code = strtoupper($code);
}
/**
* Returns the currency code.
*
* @phpstan-return non-empty-string
*/
public function getCode(): string
{
return $this->code;
}
/**
* Checks whether this currency is the same as an other.
*/
public function equals(Currency $other): bool
{
return $this->code === $other->code;
}
public function __toString(): string
{
return $this->code;
}
public function jsonSerialize(): string
{
return $this->code;
}
}

View File

@@ -0,0 +1,105 @@
<?php
declare(strict_types=1);
namespace Money;
use InvalidArgumentException;
use JsonSerializable;
use function assert;
use function is_numeric;
use function preg_match;
use function sprintf;
/**
* Currency Pair holding a base, a counter currency and a conversion ratio.
*
* @see http://en.wikipedia.org/wiki/Currency_pair
*/
final class CurrencyPair implements JsonSerializable
{
/**
* @phpstan-param numeric-string $conversionRatio
*/
public function __construct(
private readonly Currency $baseCurrency,
private readonly Currency $counterCurrency,
private readonly string $conversionRatio
) {
}
/**
* Creates a new Currency Pair based on "EUR/USD 1.2500" form representation.
*
* @param string $iso String representation of the form "EUR/USD 1.2500"
*
* @throws InvalidArgumentException Format of $iso is invalid.
*/
public static function createFromIso(string $iso): CurrencyPair
{
$currency = '([A-Z]{2,3})';
$ratio = '([0-9]*\.?[0-9]+)'; // @see http://www.regular-expressions.info/floatingpoint.html
$pattern = '#' . $currency . '/' . $currency . ' ' . $ratio . '#';
$matches = [];
if (! preg_match($pattern, $iso, $matches)) {
throw new InvalidArgumentException(sprintf('Cannot create currency pair from ISO string "%s", format of string is invalid', $iso));
}
assert(is_numeric($matches[3]));
return new self(new Currency($matches[1]), new Currency($matches[2]), $matches[3]);
}
/**
* Returns the counter currency.
*/
public function getCounterCurrency(): Currency
{
return $this->counterCurrency;
}
/**
* Returns the base currency.
*/
public function getBaseCurrency(): Currency
{
return $this->baseCurrency;
}
/**
* Returns the conversion ratio.
*
* @phpstan-return numeric-string
*/
public function getConversionRatio(): string
{
return $this->conversionRatio;
}
/**
* Checks if another CurrencyPair has the same parameters as this.
*/
public function equals(CurrencyPair $other): bool
{
return $this->baseCurrency->equals($other->baseCurrency)
&& $this->counterCurrency->equals($other->counterCurrency)
&& $this->conversionRatio === $other->conversionRatio;
}
/**
* {@inheritDoc}
*
* @phpstan-return array{baseCurrency: Currency, counterCurrency: Currency, ratio: numeric-string}
*/
public function jsonSerialize(): array
{
return [
'baseCurrency' => $this->baseCurrency,
'counterCurrency' => $this->counterCurrency,
'ratio' => $this->conversionRatio,
];
}
}

12
vendor/moneyphp/money/src/Exception.php vendored Normal file
View File

@@ -0,0 +1,12 @@
<?php
declare(strict_types=1);
namespace Money;
/**
* Common interface for all exceptions thrown by this library.
*/
interface Exception
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Money\Exception;
final class CurrencyMismatchException extends InvalidArgumentException
{
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Money\Exception;
final class DivisionByZeroException extends InvalidArgumentException
{
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace Money\Exception;
use Money\Exception;
use RuntimeException;
/**
* Thrown when a Money object cannot be formatted into a string.
*/
final class FormatterException extends RuntimeException implements Exception
{
}

View File

@@ -0,0 +1,32 @@
<?php
declare(strict_types=1);
namespace Money\Exception;
use InvalidArgumentException as CoreInvalidArgumentException;
use Money\Exception;
/**
* @internal
*/
class InvalidArgumentException extends CoreInvalidArgumentException implements Exception
{
/** @phpstan-pure */
public static function divisionByZero(): DivisionByZeroException
{
return new DivisionByZeroException('Cannot compute division with a zero divisor');
}
/** @phpstan-pure */
public static function moduloByZero(): ModuloByZeroException
{
return new ModuloByZeroException('Cannot compute modulo with a zero divisor');
}
/** @phpstan-pure */
public static function currencyMismatch(): CurrencyMismatchException
{
return new CurrencyMismatchException('Currencies must be identical');
}
}

View File

@@ -0,0 +1,9 @@
<?php
declare(strict_types=1);
namespace Money\Exception;
final class ModuloByZeroException extends InvalidArgumentException
{
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace Money\Exception;
use Money\Exception;
use RuntimeException;
/**
* Thrown when a string cannot be parsed to a Money object.
*/
final class ParserException extends RuntimeException implements Exception
{
}

View File

@@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace Money\Exception;
use DomainException;
use Money\Exception;
/**
* Thrown when trying to get ISO currency that does not exists.
*/
final class UnknownCurrencyException extends DomainException implements Exception
{
}

View File

@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace Money\Exception;
use InvalidArgumentException;
use Money\Currency;
use Money\Exception;
use function sprintf;
/**
* Thrown when there is no currency pair (rate) available for the given currencies.
*/
final class UnresolvableCurrencyPairException extends InvalidArgumentException implements Exception
{
/**
* Creates an exception from Currency objects.
*/
public static function createFromCurrencies(Currency $baseCurrency, Currency $counterCurrency): UnresolvableCurrencyPairException
{
$message = sprintf(
'Cannot resolve a currency pair for currencies: %s/%s',
$baseCurrency->getCode(),
$counterCurrency->getCode()
);
return new self($message);
}
}

20
vendor/moneyphp/money/src/Exchange.php vendored Normal file
View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace Money;
use Money\Exception\UnresolvableCurrencyPairException;
/**
* Provides a way to get exchange rate from a third-party source and return a currency pair.
*/
interface Exchange
{
/**
* Returns a currency pair for the passed currencies with the rate coming from a third-party source.
*
* @throws UnresolvableCurrencyPairException When there is no currency pair (rate) available for the given currencies.
*/
public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair;
}

View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Money\Exchange;
use Exchanger\Contract\ExchangeRateProvider;
use Exchanger\CurrencyPair as ExchangerCurrencyPair;
use Exchanger\Exception\Exception as ExchangerException;
use Exchanger\ExchangeRateQuery;
use Money\Currency;
use Money\CurrencyPair;
use Money\Exception\UnresolvableCurrencyPairException;
use Money\Exchange;
use function sprintf;
/**
* Provides a way to get exchange rate from a third-party source and return a currency pair.
*/
final class ExchangerExchange implements Exchange
{
public function __construct(private readonly ExchangeRateProvider $exchanger)
{
}
public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair
{
try {
$query = new ExchangeRateQuery(
new ExchangerCurrencyPair($baseCurrency->getCode(), $counterCurrency->getCode())
);
$rate = $this->exchanger->getExchangeRate($query);
} catch (ExchangerException) {
throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency);
}
$rateValue = sprintf('%.14F', $rate->getValue());
return new CurrencyPair($baseCurrency, $counterCurrency, $rateValue);
}
}

View File

@@ -0,0 +1,34 @@
<?php
declare(strict_types=1);
namespace Money\Exchange;
use Money\Currency;
use Money\CurrencyPair;
use Money\Exception\UnresolvableCurrencyPairException;
use Money\Exchange;
/**
* Provides a way to get exchange rate from a static list (array).
*/
final class FixedExchange implements Exchange
{
/** @phpstan-param array<non-empty-string, array<non-empty-string, numeric-string>> $list */
public function __construct(private readonly array $list)
{
}
public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair
{
if (isset($this->list[$baseCurrency->getCode()][$counterCurrency->getCode()])) {
return new CurrencyPair(
$baseCurrency,
$counterCurrency,
$this->list[$baseCurrency->getCode()][$counterCurrency->getCode()]
);
}
throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency);
}
}

View File

@@ -0,0 +1,124 @@
<?php
declare(strict_types=1);
namespace Money\Exchange;
use Money\Currencies;
use Money\Currency;
use Money\CurrencyPair;
use Money\Exception\UnresolvableCurrencyPairException;
use Money\Exchange;
use Money\Money;
use SplQueue;
use function array_reduce;
use function array_reverse;
/**
* Provides a way to get an exchange rate through a minimal set of intermediate conversions.
*/
final class IndirectExchange implements Exchange
{
public function __construct(private readonly Exchange $exchange, private readonly Currencies $currencies)
{
}
public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair
{
try {
return $this->exchange->quote($baseCurrency, $counterCurrency);
} catch (UnresolvableCurrencyPairException) {
$rate = array_reduce(
$this->getConversions($baseCurrency, $counterCurrency),
/**
* @phpstan-param numeric-string $carry
*
* @phpstan-return numeric-string
*/
static function (string $carry, CurrencyPair $pair) {
$calculator = Money::getCalculator();
return $calculator::multiply($carry, $pair->getConversionRatio());
},
'1.0'
);
return new CurrencyPair($baseCurrency, $counterCurrency, $rate);
}
}
/**
* @return CurrencyPair[]
*
* @throws UnresolvableCurrencyPairException
*/
private function getConversions(Currency $baseCurrency, Currency $counterCurrency): array
{
$startNode = new IndirectExchangeQueuedItem($baseCurrency);
$startNode->discovered = true;
/** @phpstan-var array<non-empty-string, IndirectExchangeQueuedItem> $nodes */
$nodes = [$baseCurrency->getCode() => $startNode];
/** @psam-var SplQueue<IndirectExchangeQueuedItem> $frontier */
$frontier = new SplQueue();
$frontier->enqueue($startNode);
while ($frontier->count()) {
/** @phpstan-var IndirectExchangeQueuedItem $currentNode */
$currentNode = $frontier->dequeue();
$currentCurrency = $currentNode->currency;
if ($currentCurrency->equals($counterCurrency)) {
return $this->reconstructConversionChain($nodes, $currentNode);
}
foreach ($this->currencies as $candidateCurrency) {
if (! isset($nodes[$candidateCurrency->getCode()])) {
$nodes[$candidateCurrency->getCode()] = new IndirectExchangeQueuedItem($candidateCurrency);
}
$node = $nodes[$candidateCurrency->getCode()];
if ($node->discovered) {
continue;
}
try {
// Check if the candidate is a neighbor. This will throw an exception if it isn't.
$this->exchange->quote($currentCurrency, $candidateCurrency);
$node->discovered = true;
$node->parent = $currentNode;
$frontier->enqueue($node);
} catch (UnresolvableCurrencyPairException) {
// Not a neighbor. Move on.
}
}
}
throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency);
}
/**
* @phpstan-param array<non-empty-string, IndirectExchangeQueuedItem> $currencies
*
* @return CurrencyPair[]
* @phpstan-return list<CurrencyPair>
*/
private function reconstructConversionChain(array $currencies, IndirectExchangeQueuedItem $goalNode): array
{
$current = $goalNode;
$conversions = [];
while ($current->parent) {
$previous = $currencies[$current->parent->currency->getCode()];
$conversions[] = $this->exchange->quote($previous->currency, $current->currency);
$current = $previous;
}
return array_reverse($conversions);
}
}

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Money\Exchange;
use Money\Currency;
/** @internal for sole consumption by {@see IndirectExchange} */
final class IndirectExchangeQueuedItem
{
public bool $discovered = false;
public self|null $parent = null;
public function __construct(public Currency $currency)
{
}
}

View File

@@ -0,0 +1,44 @@
<?php
declare(strict_types=1);
namespace Money\Exchange;
use Money\Currency;
use Money\CurrencyPair;
use Money\Exception\UnresolvableCurrencyPairException;
use Money\Exchange;
use Money\Money;
/**
* Tries the reverse of the currency pair if one is not available.
*
* Note: adding nested ReversedCurrenciesExchange could cause a huge performance hit.
*/
final class ReversedCurrenciesExchange implements Exchange
{
public function __construct(private readonly Exchange $exchange)
{
}
public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair
{
try {
return $this->exchange->quote($baseCurrency, $counterCurrency);
} catch (UnresolvableCurrencyPairException $exception) {
$calculator = Money::getCalculator();
try {
$currencyPair = $this->exchange->quote($counterCurrency, $baseCurrency);
return new CurrencyPair(
$baseCurrency,
$counterCurrency,
$calculator::divide('1', $currencyPair->getConversionRatio())
);
} catch (UnresolvableCurrencyPairException) {
throw $exception;
}
}
}
}

View File

@@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace Money\Exchange;
use Exchanger\Exception\Exception as ExchangerException;
use Money\Currency;
use Money\CurrencyPair;
use Money\Exception\UnresolvableCurrencyPairException;
use Money\Exchange;
use Swap\Swap;
use function sprintf;
/**
* Provides a way to get exchange rate from a third-party source and return a currency pair.
*/
final class SwapExchange implements Exchange
{
public function __construct(private readonly Swap $swap)
{
}
public function quote(Currency $baseCurrency, Currency $counterCurrency): CurrencyPair
{
try {
$rate = $this->swap->latest($baseCurrency->getCode() . '/' . $counterCurrency->getCode());
} catch (ExchangerException) {
throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency);
}
$rateValue = sprintf('%.14F', $rate->getValue());
return new CurrencyPair($baseCurrency, $counterCurrency, $rateValue);
}
}

View File

@@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace Money\Formatter;
use Money\Exception\FormatterException;
use Money\Money;
use Money\MoneyFormatter;
/**
* Formats a Money object using other Money formatters.
*/
final class AggregateMoneyFormatter implements MoneyFormatter
{
/**
* @var MoneyFormatter[] indexed by currency code
* @phpstan-var non-empty-array<non-empty-string, MoneyFormatter> indexed by currency code
*/
private array $formatters;
/**
* @param MoneyFormatter[] $formatters indexed by currency code
* @phpstan-param non-empty-array<non-empty-string, MoneyFormatter> $formatters indexed by currency code
*/
public function __construct(array $formatters)
{
$this->formatters = $formatters;
}
public function format(Money $money): string
{
$currencyCode = $money->getCurrency()->getCode();
if (isset($this->formatters[$currencyCode])) {
return $this->formatters[$currencyCode]->format($money);
}
if (isset($this->formatters['*'])) {
return $this->formatters['*']->format($money);
}
throw new FormatterException('No formatter found for currency ' . $currencyCode);
}
}

View File

@@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
namespace Money\Formatter;
use Money\Currencies;
use Money\Currencies\BitcoinCurrencies;
use Money\Exception\FormatterException;
use Money\Money;
use Money\MoneyFormatter;
use Money\Number;
use function str_pad;
use function strlen;
use function strpos;
use function substr;
/**
* Formats Money to Bitcoin currency.
*/
final class BitcoinMoneyFormatter implements MoneyFormatter
{
public function __construct(private readonly int $fractionDigits, private readonly Currencies $currencies)
{
}
public function format(Money $money): string
{
if ($money->getCurrency()->getCode() !== BitcoinCurrencies::CODE) {
throw new FormatterException('Bitcoin Formatter can only format Bitcoin currency');
}
$valueBase = $money->getAmount();
$negative = false;
if ($valueBase[0] === '-') {
$negative = true;
$valueBase = substr($valueBase, 1);
}
$subunit = $this->currencies->subunitFor($money->getCurrency());
$valueBase = Number::roundMoneyValue($valueBase, $this->fractionDigits, $subunit);
$valueLength = strlen($valueBase);
if ($valueLength > $subunit) {
$formatted = substr($valueBase, 0, $valueLength - $subunit);
if ($subunit) {
$formatted .= '.';
$formatted .= substr($valueBase, $valueLength - $subunit);
}
} else {
$formatted = '0.' . str_pad('', $subunit - $valueLength, '0') . $valueBase;
}
if ($this->fractionDigits === 0) {
$formatted = substr($formatted, 0, (int) strpos($formatted, '.'));
} elseif ($this->fractionDigits > $subunit) {
$formatted .= str_pad('', $this->fractionDigits - $subunit, '0');
} elseif ($this->fractionDigits < $subunit) {
$lastDigit = (int) strpos($formatted, '.') + $this->fractionDigits + 1;
$formatted = substr($formatted, 0, $lastDigit);
}
$formatted = BitcoinCurrencies::SYMBOL . $formatted;
if ($negative) {
$formatted = '-' . $formatted;
}
return $formatted;
}
}

View File

@@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
namespace Money\Formatter;
use Money\Currencies;
use Money\Money;
use Money\MoneyFormatter;
use function assert;
use function str_pad;
use function strlen;
use function substr;
/**
* Formats a Money object as a decimal string.
*/
final class DecimalMoneyFormatter implements MoneyFormatter
{
public function __construct(private readonly Currencies $currencies)
{
}
/**
* @phpstan-return numeric-string
*/
public function format(Money $money): string
{
$valueBase = $money->getAmount();
$negative = $valueBase[0] === '-';
if ($negative) {
$valueBase = substr($valueBase, 1);
}
$subunit = $this->currencies->subunitFor($money->getCurrency());
$valueLength = strlen($valueBase);
if ($valueLength > $subunit) {
$formatted = substr($valueBase, 0, $valueLength - $subunit);
$decimalDigits = substr($valueBase, $valueLength - $subunit);
if (strlen($decimalDigits) > 0) {
$formatted .= '.' . $decimalDigits;
}
} else {
$formatted = '0.' . str_pad('', $subunit - $valueLength, '0') . $valueBase;
}
if ($negative) {
$formatted = '-' . $formatted;
}
assert($formatted !== '');
return $formatted;
}
}

View File

@@ -0,0 +1,60 @@
<?php
declare(strict_types=1);
namespace Money\Formatter;
use Money\Currencies;
use Money\Money;
use Money\MoneyFormatter;
use NumberFormatter;
use function assert;
use function is_string;
use function str_pad;
use function strlen;
use function substr;
/**
* Formats a Money object using intl extension.
*/
final class IntlLocalizedDecimalFormatter implements MoneyFormatter
{
public function __construct(private readonly NumberFormatter $formatter, private readonly Currencies $currencies)
{
}
public function format(Money $money): string
{
$valueBase = $money->getAmount();
$negative = $valueBase[0] === '-';
if ($negative) {
$valueBase = substr($valueBase, 1);
}
$subunit = $this->currencies->subunitFor($money->getCurrency());
$valueLength = strlen($valueBase);
if ($valueLength > $subunit) {
$formatted = substr($valueBase, 0, $valueLength - $subunit);
$decimalDigits = substr($valueBase, $valueLength - $subunit);
if (strlen($decimalDigits) > 0) {
$formatted .= '.' . $decimalDigits;
}
} else {
$formatted = '0.' . str_pad('', $subunit - $valueLength, '0') . $valueBase;
}
if ($negative) {
$formatted = '-' . $formatted;
}
$formatted = $this->formatter->format((float) $formatted);
assert(is_string($formatted) && $formatted !== '');
return $formatted;
}
}

View File

@@ -0,0 +1,59 @@
<?php
declare(strict_types=1);
namespace Money\Formatter;
use Money\Currencies;
use Money\Money;
use Money\MoneyFormatter;
use NumberFormatter;
use function assert;
use function str_pad;
use function strlen;
use function substr;
/**
* Formats a Money object using intl extension.
*/
final class IntlMoneyFormatter implements MoneyFormatter
{
public function __construct(private readonly NumberFormatter $formatter, private readonly Currencies $currencies)
{
}
public function format(Money $money): string
{
$valueBase = $money->getAmount();
$negative = $valueBase[0] === '-';
if ($negative) {
$valueBase = substr($valueBase, 1);
}
$subunit = $this->currencies->subunitFor($money->getCurrency());
$valueLength = strlen($valueBase);
if ($valueLength > $subunit) {
$formatted = substr($valueBase, 0, $valueLength - $subunit);
$decimalDigits = substr($valueBase, $valueLength - $subunit);
if (strlen($decimalDigits) > 0) {
$formatted .= '.' . $decimalDigits;
}
} else {
$formatted = '0.' . str_pad('', $subunit - $valueLength, '0') . $valueBase;
}
if ($negative) {
$formatted = '-' . $formatted;
}
$formatted = $this->formatter->formatCurrency((float) $formatted, $money->getCurrency()->getCode());
assert($formatted !== '');
return $formatted;
}
}

561
vendor/moneyphp/money/src/Money.php vendored Normal file
View File

@@ -0,0 +1,561 @@
<?php
declare(strict_types=1);
namespace Money;
use JsonSerializable;
use Money\Calculator\BcMathCalculator;
use Money\Exception\InvalidArgumentException;
use function array_fill;
use function array_keys;
use function array_map;
use function array_sum;
use function count;
use function filter_var;
use function floor;
use function is_int;
use function max;
use function str_pad;
use function strlen;
use function substr;
use const FILTER_VALIDATE_INT;
use const PHP_ROUND_HALF_DOWN;
use const PHP_ROUND_HALF_EVEN;
use const PHP_ROUND_HALF_ODD;
use const PHP_ROUND_HALF_UP;
/**
* Money Value Object.
*/
final class Money implements JsonSerializable
{
use MoneyFactory;
public const ROUND_HALF_UP = PHP_ROUND_HALF_UP;
public const ROUND_HALF_DOWN = PHP_ROUND_HALF_DOWN;
public const ROUND_HALF_EVEN = PHP_ROUND_HALF_EVEN;
public const ROUND_HALF_ODD = PHP_ROUND_HALF_ODD;
public const ROUND_UP = 5;
public const ROUND_DOWN = 6;
public const ROUND_HALF_POSITIVE_INFINITY = 7;
public const ROUND_HALF_NEGATIVE_INFINITY = 8;
/**
* Internal value.
* Amount, expressed in the smallest currency units (eg cents).
*
* @phpstan-var numeric-string
*/
private string $amount;
/**
* @var class-string<Calculator>
*/
private static string $calculator = BcMathCalculator::class;
/**
* @param int|string $amount Amount, expressed in the smallest units of $currency (eg cents)
* @phpstan-param int|numeric-string $amount
*
* @throws InvalidArgumentException If amount is not integer(ish).
*
* @phpstan-pure
*/
public function __construct(int|string $amount, private readonly Currency $currency)
{
if (filter_var($amount, FILTER_VALIDATE_INT) === false) {
$numberFromString = Number::fromString((string) $amount);
if (! $numberFromString->isInteger()) {
throw new InvalidArgumentException('Amount must be an integer(ish) value');
}
$this->amount = $numberFromString->getIntegerPart();
return;
}
$this->amount = (string) $amount;
}
/**
* Checks whether a Money has the same Currency as this.
*/
public function isSameCurrency(Money ...$others): bool
{
foreach ($others as $other) {
// Note: non-strict equality is intentional here, since `Currency` is `final` and reliable.
if ($this->currency != $other->currency) {
return false;
}
}
return true;
}
/**
* Checks whether the value represented by this object equals to the other.
*
* @phpstan-pure
*/
public function equals(Money $other): bool
{
// Note: non-strict equality is intentional here, since `Currency` is `final` and reliable.
if ($this->currency != $other->currency) {
return false;
}
if ($this->amount === $other->amount) {
return true;
}
// @TODO do we want Money instance to be byte-equivalent when trailing zeroes exist? Very expensive!
// Assumption: Money#equals() is called **less** than other number-based comparisons, and probably
// only within test suites. Therefore, using complex normalization here is acceptable waste of performance.
return $this->compare($other) === 0;
}
/**
* Returns an integer less than, equal to, or greater than zero
* if the value of this object is considered to be respectively
* less than, equal to, or greater than the other.
*
* @phpstan-pure
*/
public function compare(Money $other): int
{
// Note: non-strict equality is intentional here, since `Currency` is `final` and reliable.
if ($this->currency != $other->currency) {
throw InvalidArgumentException::currencyMismatch();
}
// @phpstan-ignore impure.staticPropertyAccess, possiblyImpure.methodCall
return self::$calculator::compare($this->amount, $other->amount);
}
/**
* Checks whether the value represented by this object is greater than the other.
*
* @phpstan-pure
*/
public function greaterThan(Money $other): bool
{
return $this->compare($other) > 0;
}
/**
* @phpstan-pure
*/
public function greaterThanOrEqual(Money $other): bool
{
return $this->compare($other) >= 0;
}
/**
* Checks whether the value represented by this object is less than the other.
*
* @phpstan-pure
*/
public function lessThan(Money $other): bool
{
return $this->compare($other) < 0;
}
/**
* @phpstan-pure
*/
public function lessThanOrEqual(Money $other): bool
{
return $this->compare($other) <= 0;
}
/**
* Returns the value represented by this object - amount, expressed in the smallest currency units (eg cents).
*
* @phpstan-return numeric-string
*/
public function getAmount(): string
{
return $this->amount;
}
/**
* Returns the currency of this object.
*/
public function getCurrency(): Currency
{
return $this->currency;
}
/**
* Returns a new Money object that represents
* the sum of this and an other Money object.
*
* @phpstan-pure
*/
public function add(Money ...$addends): Money
{
$amount = $this->amount;
foreach ($addends as $addend) {
// Note: non-strict equality is intentional here, since `Currency` is `final` and reliable.
if ($this->currency != $addend->currency) {
throw InvalidArgumentException::currencyMismatch();
}
// @phpstan-ignore impure.staticPropertyAccess, possiblyImpure.methodCall
$amount = self::$calculator::add($amount, $addend->amount);
}
return new self($amount, $this->currency);
}
/**
* Returns a new Money object that represents
* the difference of this and an other Money object.
*
* @phpstan-pure
*/
public function subtract(Money ...$subtrahends): Money
{
$amount = $this->amount;
foreach ($subtrahends as $subtrahend) {
// Note: non-strict equality is intentional here, since `Currency` is `final` and reliable.
if ($this->currency != $subtrahend->currency) {
throw InvalidArgumentException::currencyMismatch();
}
// @phpstan-ignore impure.staticPropertyAccess, possiblyImpure.methodCall
$amount = self::$calculator::subtract($amount, $subtrahend->amount);
}
return new self($amount, $this->currency);
}
/**
* Returns a new Money object that represents
* the multiplied value by the given factor.
*
* @phpstan-param int|numeric-string $multiplier
* @phpstan-param self::ROUND_* $roundingMode
*/
public function multiply(int|string $multiplier, int $roundingMode = self::ROUND_HALF_UP): Money
{
if (is_int($multiplier)) {
$multiplier = (string) $multiplier;
}
$product = $this->round(self::$calculator::multiply($this->amount, $multiplier), $roundingMode);
return new self($product, $this->currency);
}
/**
* Returns a new Money object that represents
* the divided value by the given factor.
*
* @phpstan-param int|numeric-string $divisor
* @phpstan-param self::ROUND_* $roundingMode
*
* @phpstan-pure
*/
public function divide(int|string $divisor, int $roundingMode = self::ROUND_HALF_UP): Money
{
if (is_int($divisor)) {
$divisor = (string) $divisor;
}
// @phpstan-ignore impure.staticPropertyAccess, possiblyImpure.methodCall
$quotient = $this->round(self::$calculator::divide($this->amount, $divisor), $roundingMode);
return new self($quotient, $this->currency);
}
/**
* Returns a new Money object that represents
* the remainder after dividing the value by
* the given factor.
*/
public function mod(Money|int|string $divisor): Money
{
if ($divisor instanceof self) {
// Note: non-strict equality is intentional here, since `Currency` is `final` and reliable.
if ($this->currency != $divisor->currency) {
throw InvalidArgumentException::currencyMismatch();
}
$divisor = $divisor->amount;
} else {
$divisor = (string) Number::fromNumber($divisor);
}
return new self(self::$calculator::mod($this->amount, $divisor), $this->currency);
}
/**
* Allocate the money according to a list of ratios.
*
* @phpstan-param TRatios $ratios
*
* @return Money[]
* @phpstan-return (
* TRatios is list
* ? non-empty-list<Money>
* : non-empty-array<Money>
* )
*
* @template TRatios as non-empty-array<float|int>
*/
public function allocate(array $ratios): array
{
$remainder = $this->amount;
$results = [];
$total = array_sum($ratios);
if ($total <= 0) {
throw new InvalidArgumentException('Cannot allocate to none, sum of ratios must be greater than zero');
}
foreach ($ratios as $key => $ratio) {
if ($ratio < 0) {
throw new InvalidArgumentException('Cannot allocate to none, ratio must be zero or positive');
}
$share = self::$calculator::share($this->amount, (string) $ratio, (string) $total);
$results[$key] = new self($share, $this->currency);
$remainder = self::$calculator::subtract($remainder, $share);
}
if (self::$calculator::compare($remainder, '0') === 0) {
return $results;
}
$amount = $this->amount;
$fractions = array_map(static function (float|int $ratio) use ($total, $amount) {
$share = (float) $ratio / $total * (float) $amount;
return $share - floor($share);
}, $ratios);
while (self::$calculator::compare($remainder, '0') > 0) {
$index = $fractions !== [] ? array_keys($fractions, max($fractions))[0] : 0;
$results[$index] = new self(self::$calculator::add($results[$index]->amount, '1'), $results[$index]->currency);
$remainder = self::$calculator::subtract($remainder, '1');
unset($fractions[$index]);
}
return $results;
}
/**
* Allocate the money among N targets.
*
* @phpstan-param positive-int $n
*
* @return Money[]
* @phpstan-return non-empty-list<Money>
*
* @throws InvalidArgumentException If number of targets is not an integer.
*/
public function allocateTo(int $n): array
{
return $this->allocate(array_fill(0, $n, 1));
}
/**
* @phpstan-return numeric-string
*
* @throws InvalidArgumentException if the given $money is zero.
*/
public function ratioOf(Money $money): string
{
if ($money->isZero()) {
throw new InvalidArgumentException('Cannot calculate a ratio of zero');
}
// Note: non-strict equality is intentional here, since `Currency` is `final` and reliable.
if ($this->currency != $money->currency) {
throw InvalidArgumentException::currencyMismatch();
}
return self::$calculator::divide($this->amount, $money->amount);
}
/**
* @phpstan-param numeric-string $amount
* @phpstan-param self::ROUND_* $roundingMode
*
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
private function round(string $amount, int $roundingMode): string
{
if ($roundingMode === self::ROUND_UP) {
// @phpstan-ignore impure.staticPropertyAccess, possiblyImpure.methodCall
return self::$calculator::ceil($amount);
}
if ($roundingMode === self::ROUND_DOWN) {
// @phpstan-ignore impure.staticPropertyAccess, possiblyImpure.methodCall
return self::$calculator::floor($amount);
}
// @phpstan-ignore impure.staticPropertyAccess, possiblyImpure.methodCall
return self::$calculator::round($amount, $roundingMode);
}
/**
* Round to a specific unit.
*
* @phpstan-param non-negative-int $unit
* @phpstan-param self::ROUND_* $roundingMode
*/
public function roundToUnit(int $unit, int $roundingMode = self::ROUND_HALF_UP): self
{
if ($unit === 0) {
return $this;
}
$abs = self::$calculator::absolute($this->amount);
if (strlen($abs) < $unit) {
return new self('0', $this->currency);
}
$toBeRounded = substr($this->amount, 0, strlen($this->amount) - $unit) . '.' . substr($this->amount, $unit * -1);
$result = $this->round($toBeRounded, $roundingMode);
if ($result !== '0') {
$result .= str_pad('', $unit, '0');
}
return new self($result, $this->currency);
}
public function absolute(): Money
{
return new self(
self::$calculator::absolute($this->amount),
$this->currency
);
}
public function negative(): Money
{
return (new self(0, $this->currency))
->subtract($this);
}
/**
* Checks if the value represented by this object is zero.
*/
public function isZero(): bool
{
return self::$calculator::compare($this->amount, '0') === 0;
}
/**
* Checks if the value represented by this object is positive.
*/
public function isPositive(): bool
{
return self::$calculator::compare($this->amount, '0') > 0;
}
/**
* Checks if the value represented by this object is negative.
*/
public function isNegative(): bool
{
return self::$calculator::compare($this->amount, '0') < 0;
}
/**
* {@inheritDoc}
*
* @phpstan-return array{amount: string, currency: string}
*/
public function jsonSerialize(): array
{
return [
'amount' => $this->amount,
'currency' => $this->currency->jsonSerialize(),
];
}
/**
* @param Money $first
* @param Money ...$collection
*
* @phpstan-pure
*/
public static function min(self $first, self ...$collection): Money
{
$min = $first;
foreach ($collection as $money) {
if (! $money->lessThan($min)) {
continue;
}
$min = $money;
}
return $min;
}
/**
* @param Money $first
* @param Money ...$collection
*
* @phpstan-pure
*/
public static function max(self $first, self ...$collection): Money
{
$max = $first;
foreach ($collection as $money) {
if (! $money->greaterThan($max)) {
continue;
}
$max = $money;
}
return $max;
}
/** @phpstan-pure */
public static function sum(self $first, self ...$collection): Money
{
return $first->add(...$collection);
}
/** @phpstan-pure */
public static function avg(self $first, self ...$collection): Money
{
return $first->add(...$collection)->divide((string) (count($collection) + 1));
}
/** @phpstan-param class-string<Calculator> $calculator */
public static function registerCalculator(string $calculator): void
{
self::$calculator = $calculator;
}
/** @phpstan-return class-string<Calculator> */
public static function getCalculator(): string
{
return self::$calculator;
}
}

View File

@@ -0,0 +1,616 @@
<?php
declare(strict_types=1);
namespace Money;
use InvalidArgumentException;
/**
* This is a generated file. Do not edit it manually!
*
* @method static Money ONETHOUSANDCAT(numeric-string|int $amount)
* @method static Money ONETHOUSANDCHEEMS(numeric-string|int $amount)
* @method static Money ONETHOUSANDSATS(numeric-string|int $amount)
* @method static Money ONEINCH(numeric-string|int $amount)
* @method static Money ONEMBABYDOGE(numeric-string|int $amount)
* @method static Money A(numeric-string|int $amount)
* @method static Money AAVE(numeric-string|int $amount)
* @method static Money ACA(numeric-string|int $amount)
* @method static Money ACE(numeric-string|int $amount)
* @method static Money ACH(numeric-string|int $amount)
* @method static Money ACM(numeric-string|int $amount)
* @method static Money ACT(numeric-string|int $amount)
* @method static Money ACX(numeric-string|int $amount)
* @method static Money ADA(numeric-string|int $amount)
* @method static Money ADX(numeric-string|int $amount)
* @method static Money AED(numeric-string|int $amount)
* @method static Money AEUR(numeric-string|int $amount)
* @method static Money AEVO(numeric-string|int $amount)
* @method static Money AFN(numeric-string|int $amount)
* @method static Money AGLD(numeric-string|int $amount)
* @method static Money AI(numeric-string|int $amount)
* @method static Money AIXBT(numeric-string|int $amount)
* @method static Money ALCX(numeric-string|int $amount)
* @method static Money ALGO(numeric-string|int $amount)
* @method static Money ALICE(numeric-string|int $amount)
* @method static Money ALL(numeric-string|int $amount)
* @method static Money ALPHA(numeric-string|int $amount)
* @method static Money ALPINE(numeric-string|int $amount)
* @method static Money ALT(numeric-string|int $amount)
* @method static Money AMD(numeric-string|int $amount)
* @method static Money AMP(numeric-string|int $amount)
* @method static Money ANIME(numeric-string|int $amount)
* @method static Money ANKR(numeric-string|int $amount)
* @method static Money AOA(numeric-string|int $amount)
* @method static Money APE(numeric-string|int $amount)
* @method static Money API3(numeric-string|int $amount)
* @method static Money APT(numeric-string|int $amount)
* @method static Money AR(numeric-string|int $amount)
* @method static Money ARB(numeric-string|int $amount)
* @method static Money ARDR(numeric-string|int $amount)
* @method static Money ARK(numeric-string|int $amount)
* @method static Money ARKM(numeric-string|int $amount)
* @method static Money ARPA(numeric-string|int $amount)
* @method static Money ARS(numeric-string|int $amount)
* @method static Money ASR(numeric-string|int $amount)
* @method static Money ASTR(numeric-string|int $amount)
* @method static Money ATA(numeric-string|int $amount)
* @method static Money ATM(numeric-string|int $amount)
* @method static Money ATOM(numeric-string|int $amount)
* @method static Money AUCTION(numeric-string|int $amount)
* @method static Money AUD(numeric-string|int $amount)
* @method static Money AUDIO(numeric-string|int $amount)
* @method static Money AVA(numeric-string|int $amount)
* @method static Money AVAX(numeric-string|int $amount)
* @method static Money AWE(numeric-string|int $amount)
* @method static Money AWG(numeric-string|int $amount)
* @method static Money AXL(numeric-string|int $amount)
* @method static Money AXS(numeric-string|int $amount)
* @method static Money AZN(numeric-string|int $amount)
* @method static Money BABY(numeric-string|int $amount)
* @method static Money BAKE(numeric-string|int $amount)
* @method static Money BAM(numeric-string|int $amount)
* @method static Money BANANA(numeric-string|int $amount)
* @method static Money BANANAS31(numeric-string|int $amount)
* @method static Money BAND(numeric-string|int $amount)
* @method static Money BAR(numeric-string|int $amount)
* @method static Money BAT(numeric-string|int $amount)
* @method static Money BB(numeric-string|int $amount)
* @method static Money BBD(numeric-string|int $amount)
* @method static Money BCH(numeric-string|int $amount)
* @method static Money BDT(numeric-string|int $amount)
* @method static Money BEAMX(numeric-string|int $amount)
* @method static Money BEL(numeric-string|int $amount)
* @method static Money BERA(numeric-string|int $amount)
* @method static Money BGN(numeric-string|int $amount)
* @method static Money BHD(numeric-string|int $amount)
* @method static Money BICO(numeric-string|int $amount)
* @method static Money BIF(numeric-string|int $amount)
* @method static Money BIFI(numeric-string|int $amount)
* @method static Money BIGTIME(numeric-string|int $amount)
* @method static Money BIO(numeric-string|int $amount)
* @method static Money BLUR(numeric-string|int $amount)
* @method static Money BMD(numeric-string|int $amount)
* @method static Money BMT(numeric-string|int $amount)
* @method static Money BNB(numeric-string|int $amount)
* @method static Money BND(numeric-string|int $amount)
* @method static Money BNSOL(numeric-string|int $amount)
* @method static Money BNT(numeric-string|int $amount)
* @method static Money BOB(numeric-string|int $amount)
* @method static Money BOME(numeric-string|int $amount)
* @method static Money BONK(numeric-string|int $amount)
* @method static Money BOV(numeric-string|int $amount)
* @method static Money BRL(numeric-string|int $amount)
* @method static Money BROCCOLI714(numeric-string|int $amount)
* @method static Money BSD(numeric-string|int $amount)
* @method static Money BSW(numeric-string|int $amount)
* @method static Money BTC(numeric-string|int $amount)
* @method static Money BTN(numeric-string|int $amount)
* @method static Money BTTC(numeric-string|int $amount)
* @method static Money BWP(numeric-string|int $amount)
* @method static Money BYN(numeric-string|int $amount)
* @method static Money BZD(numeric-string|int $amount)
* @method static Money C98(numeric-string|int $amount)
* @method static Money CAD(numeric-string|int $amount)
* @method static Money CAKE(numeric-string|int $amount)
* @method static Money CATI(numeric-string|int $amount)
* @method static Money CDF(numeric-string|int $amount)
* @method static Money CELO(numeric-string|int $amount)
* @method static Money CELR(numeric-string|int $amount)
* @method static Money CETUS(numeric-string|int $amount)
* @method static Money CFX(numeric-string|int $amount)
* @method static Money CGPT(numeric-string|int $amount)
* @method static Money CHE(numeric-string|int $amount)
* @method static Money CHESS(numeric-string|int $amount)
* @method static Money CHF(numeric-string|int $amount)
* @method static Money CHR(numeric-string|int $amount)
* @method static Money CHW(numeric-string|int $amount)
* @method static Money CHZ(numeric-string|int $amount)
* @method static Money CITY(numeric-string|int $amount)
* @method static Money CKB(numeric-string|int $amount)
* @method static Money CLF(numeric-string|int $amount)
* @method static Money CLP(numeric-string|int $amount)
* @method static Money CNY(numeric-string|int $amount)
* @method static Money COMP(numeric-string|int $amount)
* @method static Money COOKIE(numeric-string|int $amount)
* @method static Money COP(numeric-string|int $amount)
* @method static Money COS(numeric-string|int $amount)
* @method static Money COTI(numeric-string|int $amount)
* @method static Money COU(numeric-string|int $amount)
* @method static Money COW(numeric-string|int $amount)
* @method static Money CRC(numeric-string|int $amount)
* @method static Money CRV(numeric-string|int $amount)
* @method static Money CTK(numeric-string|int $amount)
* @method static Money CTSI(numeric-string|int $amount)
* @method static Money CUP(numeric-string|int $amount)
* @method static Money CVC(numeric-string|int $amount)
* @method static Money CVE(numeric-string|int $amount)
* @method static Money CVX(numeric-string|int $amount)
* @method static Money CYBER(numeric-string|int $amount)
* @method static Money CZK(numeric-string|int $amount)
* @method static Money D(numeric-string|int $amount)
* @method static Money DAI(numeric-string|int $amount)
* @method static Money DASH(numeric-string|int $amount)
* @method static Money DATA(numeric-string|int $amount)
* @method static Money DCR(numeric-string|int $amount)
* @method static Money DEGO(numeric-string|int $amount)
* @method static Money DENT(numeric-string|int $amount)
* @method static Money DEXE(numeric-string|int $amount)
* @method static Money DF(numeric-string|int $amount)
* @method static Money DGB(numeric-string|int $amount)
* @method static Money DIA(numeric-string|int $amount)
* @method static Money DJF(numeric-string|int $amount)
* @method static Money DKK(numeric-string|int $amount)
* @method static Money DODO(numeric-string|int $amount)
* @method static Money DOGE(numeric-string|int $amount)
* @method static Money DOGS(numeric-string|int $amount)
* @method static Money DOP(numeric-string|int $amount)
* @method static Money DOT(numeric-string|int $amount)
* @method static Money DUSK(numeric-string|int $amount)
* @method static Money DYDX(numeric-string|int $amount)
* @method static Money DYM(numeric-string|int $amount)
* @method static Money DZD(numeric-string|int $amount)
* @method static Money EDU(numeric-string|int $amount)
* @method static Money EGLD(numeric-string|int $amount)
* @method static Money EGP(numeric-string|int $amount)
* @method static Money EIGEN(numeric-string|int $amount)
* @method static Money ENA(numeric-string|int $amount)
* @method static Money ENJ(numeric-string|int $amount)
* @method static Money ENS(numeric-string|int $amount)
* @method static Money EPIC(numeric-string|int $amount)
* @method static Money ERN(numeric-string|int $amount)
* @method static Money ETB(numeric-string|int $amount)
* @method static Money ETC(numeric-string|int $amount)
* @method static Money ETH(numeric-string|int $amount)
* @method static Money ETHFI(numeric-string|int $amount)
* @method static Money EUR(numeric-string|int $amount)
* @method static Money EURI(numeric-string|int $amount)
* @method static Money FARM(numeric-string|int $amount)
* @method static Money FDUSD(numeric-string|int $amount)
* @method static Money FET(numeric-string|int $amount)
* @method static Money FIDA(numeric-string|int $amount)
* @method static Money FIL(numeric-string|int $amount)
* @method static Money FIO(numeric-string|int $amount)
* @method static Money FIS(numeric-string|int $amount)
* @method static Money FJD(numeric-string|int $amount)
* @method static Money FKP(numeric-string|int $amount)
* @method static Money FLM(numeric-string|int $amount)
* @method static Money FLOKI(numeric-string|int $amount)
* @method static Money FLOW(numeric-string|int $amount)
* @method static Money FLUX(numeric-string|int $amount)
* @method static Money FORM(numeric-string|int $amount)
* @method static Money FORTH(numeric-string|int $amount)
* @method static Money FTT(numeric-string|int $amount)
* @method static Money FUN(numeric-string|int $amount)
* @method static Money FXS(numeric-string|int $amount)
* @method static Money G(numeric-string|int $amount)
* @method static Money GALA(numeric-string|int $amount)
* @method static Money GAS(numeric-string|int $amount)
* @method static Money GBP(numeric-string|int $amount)
* @method static Money GEL(numeric-string|int $amount)
* @method static Money GHS(numeric-string|int $amount)
* @method static Money GHST(numeric-string|int $amount)
* @method static Money GIP(numeric-string|int $amount)
* @method static Money GLM(numeric-string|int $amount)
* @method static Money GLMR(numeric-string|int $amount)
* @method static Money GMD(numeric-string|int $amount)
* @method static Money GMT(numeric-string|int $amount)
* @method static Money GMX(numeric-string|int $amount)
* @method static Money GNF(numeric-string|int $amount)
* @method static Money GNO(numeric-string|int $amount)
* @method static Money GNS(numeric-string|int $amount)
* @method static Money GPS(numeric-string|int $amount)
* @method static Money GRT(numeric-string|int $amount)
* @method static Money GTC(numeric-string|int $amount)
* @method static Money GTQ(numeric-string|int $amount)
* @method static Money GUN(numeric-string|int $amount)
* @method static Money GYD(numeric-string|int $amount)
* @method static Money HAEDAL(numeric-string|int $amount)
* @method static Money HBAR(numeric-string|int $amount)
* @method static Money HEI(numeric-string|int $amount)
* @method static Money HFT(numeric-string|int $amount)
* @method static Money HIFI(numeric-string|int $amount)
* @method static Money HIGH(numeric-string|int $amount)
* @method static Money HIVE(numeric-string|int $amount)
* @method static Money HKD(numeric-string|int $amount)
* @method static Money HMSTR(numeric-string|int $amount)
* @method static Money HNL(numeric-string|int $amount)
* @method static Money HOOK(numeric-string|int $amount)
* @method static Money HOT(numeric-string|int $amount)
* @method static Money HTG(numeric-string|int $amount)
* @method static Money HUF(numeric-string|int $amount)
* @method static Money HUMA(numeric-string|int $amount)
* @method static Money HYPER(numeric-string|int $amount)
* @method static Money ICP(numeric-string|int $amount)
* @method static Money ICX(numeric-string|int $amount)
* @method static Money ID(numeric-string|int $amount)
* @method static Money IDEX(numeric-string|int $amount)
* @method static Money IDR(numeric-string|int $amount)
* @method static Money ILS(numeric-string|int $amount)
* @method static Money ILV(numeric-string|int $amount)
* @method static Money IMX(numeric-string|int $amount)
* @method static Money INIT(numeric-string|int $amount)
* @method static Money INJ(numeric-string|int $amount)
* @method static Money INR(numeric-string|int $amount)
* @method static Money IO(numeric-string|int $amount)
* @method static Money IOST(numeric-string|int $amount)
* @method static Money IOTA(numeric-string|int $amount)
* @method static Money IOTX(numeric-string|int $amount)
* @method static Money IQ(numeric-string|int $amount)
* @method static Money IQD(numeric-string|int $amount)
* @method static Money IRR(numeric-string|int $amount)
* @method static Money ISK(numeric-string|int $amount)
* @method static Money JASMY(numeric-string|int $amount)
* @method static Money JMD(numeric-string|int $amount)
* @method static Money JOD(numeric-string|int $amount)
* @method static Money JOE(numeric-string|int $amount)
* @method static Money JPY(numeric-string|int $amount)
* @method static Money JST(numeric-string|int $amount)
* @method static Money JTO(numeric-string|int $amount)
* @method static Money JUP(numeric-string|int $amount)
* @method static Money JUV(numeric-string|int $amount)
* @method static Money KAIA(numeric-string|int $amount)
* @method static Money KAITO(numeric-string|int $amount)
* @method static Money KAVA(numeric-string|int $amount)
* @method static Money KDA(numeric-string|int $amount)
* @method static Money KERNEL(numeric-string|int $amount)
* @method static Money KES(numeric-string|int $amount)
* @method static Money KGS(numeric-string|int $amount)
* @method static Money KHR(numeric-string|int $amount)
* @method static Money KMD(numeric-string|int $amount)
* @method static Money KMF(numeric-string|int $amount)
* @method static Money KMNO(numeric-string|int $amount)
* @method static Money KNC(numeric-string|int $amount)
* @method static Money KPW(numeric-string|int $amount)
* @method static Money KRW(numeric-string|int $amount)
* @method static Money KSM(numeric-string|int $amount)
* @method static Money KWD(numeric-string|int $amount)
* @method static Money KYD(numeric-string|int $amount)
* @method static Money KZT(numeric-string|int $amount)
* @method static Money LAK(numeric-string|int $amount)
* @method static Money LAYER(numeric-string|int $amount)
* @method static Money LAZIO(numeric-string|int $amount)
* @method static Money LBP(numeric-string|int $amount)
* @method static Money LDO(numeric-string|int $amount)
* @method static Money LEVER(numeric-string|int $amount)
* @method static Money LINK(numeric-string|int $amount)
* @method static Money LISTA(numeric-string|int $amount)
* @method static Money LKR(numeric-string|int $amount)
* @method static Money LOKA(numeric-string|int $amount)
* @method static Money LPT(numeric-string|int $amount)
* @method static Money LQTY(numeric-string|int $amount)
* @method static Money LRC(numeric-string|int $amount)
* @method static Money LRD(numeric-string|int $amount)
* @method static Money LSK(numeric-string|int $amount)
* @method static Money LSL(numeric-string|int $amount)
* @method static Money LTC(numeric-string|int $amount)
* @method static Money LTO(numeric-string|int $amount)
* @method static Money LUMIA(numeric-string|int $amount)
* @method static Money LUNA(numeric-string|int $amount)
* @method static Money LUNC(numeric-string|int $amount)
* @method static Money LYD(numeric-string|int $amount)
* @method static Money MAD(numeric-string|int $amount)
* @method static Money MAGIC(numeric-string|int $amount)
* @method static Money MANA(numeric-string|int $amount)
* @method static Money MANTA(numeric-string|int $amount)
* @method static Money MASK(numeric-string|int $amount)
* @method static Money MAV(numeric-string|int $amount)
* @method static Money MBL(numeric-string|int $amount)
* @method static Money MBOX(numeric-string|int $amount)
* @method static Money MDL(numeric-string|int $amount)
* @method static Money MDT(numeric-string|int $amount)
* @method static Money ME(numeric-string|int $amount)
* @method static Money MEME(numeric-string|int $amount)
* @method static Money METIS(numeric-string|int $amount)
* @method static Money MGA(numeric-string|int $amount)
* @method static Money MINA(numeric-string|int $amount)
* @method static Money MKD(numeric-string|int $amount)
* @method static Money MKR(numeric-string|int $amount)
* @method static Money MLN(numeric-string|int $amount)
* @method static Money MMK(numeric-string|int $amount)
* @method static Money MNT(numeric-string|int $amount)
* @method static Money MOP(numeric-string|int $amount)
* @method static Money MOVE(numeric-string|int $amount)
* @method static Money MOVR(numeric-string|int $amount)
* @method static Money MRU(numeric-string|int $amount)
* @method static Money MTL(numeric-string|int $amount)
* @method static Money MUBARAK(numeric-string|int $amount)
* @method static Money MUR(numeric-string|int $amount)
* @method static Money MVR(numeric-string|int $amount)
* @method static Money MWK(numeric-string|int $amount)
* @method static Money MXN(numeric-string|int $amount)
* @method static Money MXV(numeric-string|int $amount)
* @method static Money MYR(numeric-string|int $amount)
* @method static Money MZN(numeric-string|int $amount)
* @method static Money NAD(numeric-string|int $amount)
* @method static Money NEAR(numeric-string|int $amount)
* @method static Money NEIRO(numeric-string|int $amount)
* @method static Money NEO(numeric-string|int $amount)
* @method static Money NEXO(numeric-string|int $amount)
* @method static Money NFP(numeric-string|int $amount)
* @method static Money NGN(numeric-string|int $amount)
* @method static Money NIL(numeric-string|int $amount)
* @method static Money NIO(numeric-string|int $amount)
* @method static Money NKN(numeric-string|int $amount)
* @method static Money NMR(numeric-string|int $amount)
* @method static Money NOK(numeric-string|int $amount)
* @method static Money NOT(numeric-string|int $amount)
* @method static Money NPR(numeric-string|int $amount)
* @method static Money NTRN(numeric-string|int $amount)
* @method static Money NXPC(numeric-string|int $amount)
* @method static Money NZD(numeric-string|int $amount)
* @method static Money OG(numeric-string|int $amount)
* @method static Money OGN(numeric-string|int $amount)
* @method static Money OM(numeric-string|int $amount)
* @method static Money OMNI(numeric-string|int $amount)
* @method static Money OMR(numeric-string|int $amount)
* @method static Money ONDO(numeric-string|int $amount)
* @method static Money ONE(numeric-string|int $amount)
* @method static Money ONG(numeric-string|int $amount)
* @method static Money ONT(numeric-string|int $amount)
* @method static Money OP(numeric-string|int $amount)
* @method static Money ORCA(numeric-string|int $amount)
* @method static Money ORDI(numeric-string|int $amount)
* @method static Money OSMO(numeric-string|int $amount)
* @method static Money OXT(numeric-string|int $amount)
* @method static Money PAB(numeric-string|int $amount)
* @method static Money PARTI(numeric-string|int $amount)
* @method static Money PAXG(numeric-string|int $amount)
* @method static Money PEN(numeric-string|int $amount)
* @method static Money PENDLE(numeric-string|int $amount)
* @method static Money PENGU(numeric-string|int $amount)
* @method static Money PEOPLE(numeric-string|int $amount)
* @method static Money PEPE(numeric-string|int $amount)
* @method static Money PERP(numeric-string|int $amount)
* @method static Money PGK(numeric-string|int $amount)
* @method static Money PHA(numeric-string|int $amount)
* @method static Money PHB(numeric-string|int $amount)
* @method static Money PHP(numeric-string|int $amount)
* @method static Money PIVX(numeric-string|int $amount)
* @method static Money PIXEL(numeric-string|int $amount)
* @method static Money PKR(numeric-string|int $amount)
* @method static Money PLN(numeric-string|int $amount)
* @method static Money PNUT(numeric-string|int $amount)
* @method static Money POL(numeric-string|int $amount)
* @method static Money POLYX(numeric-string|int $amount)
* @method static Money POND(numeric-string|int $amount)
* @method static Money PORTAL(numeric-string|int $amount)
* @method static Money PORTO(numeric-string|int $amount)
* @method static Money POWR(numeric-string|int $amount)
* @method static Money PROM(numeric-string|int $amount)
* @method static Money PSG(numeric-string|int $amount)
* @method static Money PUNDIX(numeric-string|int $amount)
* @method static Money PYG(numeric-string|int $amount)
* @method static Money PYR(numeric-string|int $amount)
* @method static Money PYTH(numeric-string|int $amount)
* @method static Money QAR(numeric-string|int $amount)
* @method static Money QI(numeric-string|int $amount)
* @method static Money QKC(numeric-string|int $amount)
* @method static Money QNT(numeric-string|int $amount)
* @method static Money QTUM(numeric-string|int $amount)
* @method static Money QUICK(numeric-string|int $amount)
* @method static Money RAD(numeric-string|int $amount)
* @method static Money RARE(numeric-string|int $amount)
* @method static Money RAY(numeric-string|int $amount)
* @method static Money RDNT(numeric-string|int $amount)
* @method static Money RED(numeric-string|int $amount)
* @method static Money REI(numeric-string|int $amount)
* @method static Money RENDER(numeric-string|int $amount)
* @method static Money REQ(numeric-string|int $amount)
* @method static Money REZ(numeric-string|int $amount)
* @method static Money RIF(numeric-string|int $amount)
* @method static Money RLC(numeric-string|int $amount)
* @method static Money RON(numeric-string|int $amount)
* @method static Money RONIN(numeric-string|int $amount)
* @method static Money ROSE(numeric-string|int $amount)
* @method static Money RPL(numeric-string|int $amount)
* @method static Money RSD(numeric-string|int $amount)
* @method static Money RSR(numeric-string|int $amount)
* @method static Money RUB(numeric-string|int $amount)
* @method static Money RUNE(numeric-string|int $amount)
* @method static Money RVN(numeric-string|int $amount)
* @method static Money RWF(numeric-string|int $amount)
* @method static Money S(numeric-string|int $amount)
* @method static Money SAGA(numeric-string|int $amount)
* @method static Money SAND(numeric-string|int $amount)
* @method static Money SANTOS(numeric-string|int $amount)
* @method static Money SAR(numeric-string|int $amount)
* @method static Money SBD(numeric-string|int $amount)
* @method static Money SC(numeric-string|int $amount)
* @method static Money SCR(numeric-string|int $amount)
* @method static Money SCRT(numeric-string|int $amount)
* @method static Money SDG(numeric-string|int $amount)
* @method static Money SEI(numeric-string|int $amount)
* @method static Money SEK(numeric-string|int $amount)
* @method static Money SFP(numeric-string|int $amount)
* @method static Money SGD(numeric-string|int $amount)
* @method static Money SHELL(numeric-string|int $amount)
* @method static Money SHIB(numeric-string|int $amount)
* @method static Money SHP(numeric-string|int $amount)
* @method static Money SIGN(numeric-string|int $amount)
* @method static Money SKL(numeric-string|int $amount)
* @method static Money SLE(numeric-string|int $amount)
* @method static Money SLF(numeric-string|int $amount)
* @method static Money SLP(numeric-string|int $amount)
* @method static Money SNX(numeric-string|int $amount)
* @method static Money SOL(numeric-string|int $amount)
* @method static Money SOLV(numeric-string|int $amount)
* @method static Money SOPH(numeric-string|int $amount)
* @method static Money SOS(numeric-string|int $amount)
* @method static Money SPELL(numeric-string|int $amount)
* @method static Money SRD(numeric-string|int $amount)
* @method static Money SSP(numeric-string|int $amount)
* @method static Money SSV(numeric-string|int $amount)
* @method static Money STEEM(numeric-string|int $amount)
* @method static Money STG(numeric-string|int $amount)
* @method static Money STN(numeric-string|int $amount)
* @method static Money STO(numeric-string|int $amount)
* @method static Money STORJ(numeric-string|int $amount)
* @method static Money STRAX(numeric-string|int $amount)
* @method static Money STRK(numeric-string|int $amount)
* @method static Money STX(numeric-string|int $amount)
* @method static Money SUI(numeric-string|int $amount)
* @method static Money SUN(numeric-string|int $amount)
* @method static Money SUPER(numeric-string|int $amount)
* @method static Money SUSHI(numeric-string|int $amount)
* @method static Money SVC(numeric-string|int $amount)
* @method static Money SXP(numeric-string|int $amount)
* @method static Money SXT(numeric-string|int $amount)
* @method static Money SYN(numeric-string|int $amount)
* @method static Money SYP(numeric-string|int $amount)
* @method static Money SYRUP(numeric-string|int $amount)
* @method static Money SYS(numeric-string|int $amount)
* @method static Money SZL(numeric-string|int $amount)
* @method static Money T(numeric-string|int $amount)
* @method static Money TAO(numeric-string|int $amount)
* @method static Money TFUEL(numeric-string|int $amount)
* @method static Money THB(numeric-string|int $amount)
* @method static Money THE(numeric-string|int $amount)
* @method static Money THETA(numeric-string|int $amount)
* @method static Money TIA(numeric-string|int $amount)
* @method static Money TJS(numeric-string|int $amount)
* @method static Money TKO(numeric-string|int $amount)
* @method static Money TLM(numeric-string|int $amount)
* @method static Money TMT(numeric-string|int $amount)
* @method static Money TND(numeric-string|int $amount)
* @method static Money TNSR(numeric-string|int $amount)
* @method static Money TON(numeric-string|int $amount)
* @method static Money TOP(numeric-string|int $amount)
* @method static Money TRB(numeric-string|int $amount)
* @method static Money TRU(numeric-string|int $amount)
* @method static Money TRUMP(numeric-string|int $amount)
* @method static Money TRX(numeric-string|int $amount)
* @method static Money TRY(numeric-string|int $amount)
* @method static Money TST(numeric-string|int $amount)
* @method static Money TTD(numeric-string|int $amount)
* @method static Money TURBO(numeric-string|int $amount)
* @method static Money TUSD(numeric-string|int $amount)
* @method static Money TUT(numeric-string|int $amount)
* @method static Money TWD(numeric-string|int $amount)
* @method static Money TWT(numeric-string|int $amount)
* @method static Money TZS(numeric-string|int $amount)
* @method static Money UAH(numeric-string|int $amount)
* @method static Money UGX(numeric-string|int $amount)
* @method static Money UMA(numeric-string|int $amount)
* @method static Money UNI(numeric-string|int $amount)
* @method static Money USD(numeric-string|int $amount)
* @method static Money USD1(numeric-string|int $amount)
* @method static Money USDC(numeric-string|int $amount)
* @method static Money USDP(numeric-string|int $amount)
* @method static Money USDT(numeric-string|int $amount)
* @method static Money USN(numeric-string|int $amount)
* @method static Money USTC(numeric-string|int $amount)
* @method static Money USUAL(numeric-string|int $amount)
* @method static Money UTK(numeric-string|int $amount)
* @method static Money UYI(numeric-string|int $amount)
* @method static Money UYU(numeric-string|int $amount)
* @method static Money UYW(numeric-string|int $amount)
* @method static Money UZS(numeric-string|int $amount)
* @method static Money VANA(numeric-string|int $amount)
* @method static Money VANRY(numeric-string|int $amount)
* @method static Money VED(numeric-string|int $amount)
* @method static Money VELODROME(numeric-string|int $amount)
* @method static Money VES(numeric-string|int $amount)
* @method static Money VET(numeric-string|int $amount)
* @method static Money VIC(numeric-string|int $amount)
* @method static Money VIRTUAL(numeric-string|int $amount)
* @method static Money VND(numeric-string|int $amount)
* @method static Money VOXEL(numeric-string|int $amount)
* @method static Money VTHO(numeric-string|int $amount)
* @method static Money VUV(numeric-string|int $amount)
* @method static Money W(numeric-string|int $amount)
* @method static Money WAN(numeric-string|int $amount)
* @method static Money WAXP(numeric-string|int $amount)
* @method static Money WBETH(numeric-string|int $amount)
* @method static Money WBTC(numeric-string|int $amount)
* @method static Money WCT(numeric-string|int $amount)
* @method static Money WIF(numeric-string|int $amount)
* @method static Money WIN(numeric-string|int $amount)
* @method static Money WLD(numeric-string|int $amount)
* @method static Money WOO(numeric-string|int $amount)
* @method static Money WST(numeric-string|int $amount)
* @method static Money XAD(numeric-string|int $amount)
* @method static Money XAF(numeric-string|int $amount)
* @method static Money XAG(numeric-string|int $amount)
* @method static Money XAI(numeric-string|int $amount)
* @method static Money XAU(numeric-string|int $amount)
* @method static Money XBA(numeric-string|int $amount)
* @method static Money XBB(numeric-string|int $amount)
* @method static Money XBC(numeric-string|int $amount)
* @method static Money XBD(numeric-string|int $amount)
* @method static Money XBT(numeric-string|int $amount)
* @method static Money XCD(numeric-string|int $amount)
* @method static Money XCG(numeric-string|int $amount)
* @method static Money XDR(numeric-string|int $amount)
* @method static Money XEC(numeric-string|int $amount)
* @method static Money XLM(numeric-string|int $amount)
* @method static Money XNO(numeric-string|int $amount)
* @method static Money XOF(numeric-string|int $amount)
* @method static Money XPD(numeric-string|int $amount)
* @method static Money XPF(numeric-string|int $amount)
* @method static Money XPT(numeric-string|int $amount)
* @method static Money XRP(numeric-string|int $amount)
* @method static Money XSU(numeric-string|int $amount)
* @method static Money XTS(numeric-string|int $amount)
* @method static Money XTZ(numeric-string|int $amount)
* @method static Money XUA(numeric-string|int $amount)
* @method static Money XUSD(numeric-string|int $amount)
* @method static Money XVG(numeric-string|int $amount)
* @method static Money XVS(numeric-string|int $amount)
* @method static Money XXX(numeric-string|int $amount)
* @method static Money YER(numeric-string|int $amount)
* @method static Money YFI(numeric-string|int $amount)
* @method static Money YGG(numeric-string|int $amount)
* @method static Money ZAR(numeric-string|int $amount)
* @method static Money ZEC(numeric-string|int $amount)
* @method static Money ZEN(numeric-string|int $amount)
* @method static Money ZIL(numeric-string|int $amount)
* @method static Money ZK(numeric-string|int $amount)
* @method static Money ZMW(numeric-string|int $amount)
* @method static Money ZRO(numeric-string|int $amount)
* @method static Money ZRX(numeric-string|int $amount)
* @method static Money ZWG(numeric-string|int $amount)
* @psalm-immutable
*/
trait MoneyFactory
{
/**
* Convenience factory method for a Money object.
*
* <code>
* $fiveDollar = Money::USD(500);
* </code>
*
* @param non-empty-string $method
* @param array{numeric-string|int} $arguments
*
* @throws InvalidArgumentException If amount is not integer(ish).
*
* @psalm-pure
*/
public static function __callStatic(string $method, array $arguments): Money
{
return new Money($arguments[0], new Currency($method));
}
}

View File

@@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace Money;
/**
* Formats Money objects.
*/
interface MoneyFormatter
{
/**
* Formats a Money object as string.
*
* @phpstan-return non-empty-string
*
* Exception\FormatterException
*/
public function format(Money $money): string;
}

View File

@@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Money;
/**
* Parses a string into a Money object.
*/
interface MoneyParser
{
/**
* Parses a string into a Money object (including currency).
*
* @throws Exception\ParserException
*/
public function parse(string $money, Currency|null $fallbackCurrency = null): Money;
}

330
vendor/moneyphp/money/src/Number.php vendored Normal file
View File

@@ -0,0 +1,330 @@
<?php
declare(strict_types=1);
namespace Money;
use InvalidArgumentException;
use function abs;
use function explode;
use function is_int;
use function ltrim;
use function min;
use function rtrim;
use function sprintf;
use function str_pad;
use function strlen;
use function substr;
/**
* Represents a numeric value.
*
* @internal this is an internal utility of the library, and may vary at any time. It is mostly used to internally validate
* that a number is represented at digits, but by improving type system integration, we may be able to completely
* get rid of it.
*
* @phpstan-immutable
*/
final class Number
{
/** @phpstan-var numeric-string */
private string $integerPart;
/** @phpstan-var numeric-string|'' */
private string $fractionalPart;
private const NUMBERS = [0 => 1, 1 => 1, 2 => 1, 3 => 1, 4 => 1, 5 => 1, 6 => 1, 7 => 1, 8 => 1, 9 => 1];
/**
* @phpstan-pure
*/
public function __construct(string $integerPart, string $fractionalPart = '')
{
if ($integerPart === '' && $fractionalPart === '') {
throw new InvalidArgumentException('Empty number is invalid');
}
$this->integerPart = self::parseIntegerPart($integerPart);
$this->fractionalPart = self::parseFractionalPart($fractionalPart);
}
/** @phpstan-pure */
public static function fromString(string $number): self
{
$portions = explode('.', $number, 2);
return new self(
$portions[0],
rtrim($portions[1] ?? '', '0')
);
}
/** @phpstan-pure */
public static function fromFloat(float $number): self
{
return self::fromString(sprintf('%.14F', $number));
}
/** @phpstan-pure */
public static function fromNumber(int|string $number): self
{
if (is_int($number)) {
return new self((string) $number);
}
return self::fromString($number);
}
/**
* @phpstan-pure
*/
public function isDecimal(): bool
{
return $this->fractionalPart !== '';
}
/**
* @phpstan-pure
*/
public function isInteger(): bool
{
return $this->fractionalPart === '';
}
/**
* @phpstan-pure
*/
public function isHalf(): bool
{
return $this->fractionalPart === '5';
}
/**
* @phpstan-pure
*/
public function isCurrentEven(): bool
{
$lastIntegerPartNumber = (int) $this->integerPart[strlen($this->integerPart) - 1];
return $lastIntegerPartNumber % 2 === 0;
}
/**
* @phpstan-pure
*/
public function isCloserToNext(): bool
{
if ($this->fractionalPart === '') {
return false;
}
return $this->fractionalPart[0] >= 5;
}
/**
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public function __toString(): string
{
if ($this->fractionalPart === '') {
return $this->integerPart;
}
return $this->integerPart . '.' . $this->fractionalPart;
}
/**
* @phpstan-pure
*/
public function isNegative(): bool
{
return $this->integerPart[0] === '-';
}
/**
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public function getIntegerPart(): string
{
return $this->integerPart;
}
/**
* @phpstan-return numeric-string|''
*
* @phpstan-pure
*/
public function getFractionalPart(): string
{
return $this->fractionalPart;
}
/**
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
public function getIntegerRoundingMultiplier(): string
{
if ($this->integerPart[0] === '-') {
return '-1';
}
return '1';
}
public function base10(int $number): self
{
if ($this->integerPart === '0' && ! $this->fractionalPart) {
return $this;
}
$sign = '';
$integerPart = $this->integerPart;
if ($integerPart[0] === '-') {
$sign = '-';
$integerPart = substr($integerPart, 1);
}
if ($number >= 0) {
$integerPart = ltrim($integerPart, '0');
$lengthIntegerPart = strlen($integerPart);
$integers = $lengthIntegerPart - min($number, $lengthIntegerPart);
$zeroPad = $number - min($number, $lengthIntegerPart);
return new self(
$sign . substr($integerPart, 0, $integers),
rtrim(str_pad('', $zeroPad, '0') . substr($integerPart, $integers) . $this->fractionalPart, '0')
);
}
$number = abs($number);
$lengthFractionalPart = strlen($this->fractionalPart);
$fractions = $lengthFractionalPart - min($number, $lengthFractionalPart);
$zeroPad = $number - min($number, $lengthFractionalPart);
return new self(
$sign . ltrim($integerPart . substr($this->fractionalPart, 0, $lengthFractionalPart - $fractions) . str_pad('', $zeroPad, '0'), '0'),
substr($this->fractionalPart, $lengthFractionalPart - $fractions)
);
}
/**
* @phpstan-return numeric-string
*
* @phpstan-pure
*/
private static function parseIntegerPart(string $number): string
{
if ($number === '' || $number === '0') {
return '0';
}
if ($number === '-' || $number === '-0') {
return '-0';
}
// Happy path performance optimization: number can be used as-is if it is within
// the platform's integer capabilities.
if ($number === (string) (int) $number) {
return $number;
}
$nonZero = false;
for ($position = 0, $characters = strlen($number); $position < $characters; ++$position) {
$digit = $number[$position];
if (! isset(self::NUMBERS[$digit]) && ! ($position === 0 && $digit === '-')) {
throw new InvalidArgumentException(sprintf('Invalid integer part %1$s. Invalid digit %2$s found', $number, $digit));
}
if ($digit === '-') {
continue;
}
if ($nonZero === false && $digit === '0') {
throw new InvalidArgumentException('Leading zeros are not allowed');
}
$nonZero = true;
}
return $number;
}
/**
* @phpstan-return numeric-string|''
*
* @phpstan-pure
*/
private static function parseFractionalPart(string $number): string
{
if ($number === '') {
return $number;
}
$intFraction = (int) $number;
// Happy path performance optimization: number can be used as-is if it is within
// the platform's integer capabilities, and it starts with zeroes only.
if ($intFraction > 0 && ltrim($number, '0') === (string) $intFraction) {
return $number;
}
for ($position = 0, $characters = strlen($number); $position < $characters; ++$position) {
$digit = $number[$position];
if (! isset(self::NUMBERS[$digit])) {
throw new InvalidArgumentException(sprintf('Invalid fractional part %1$s. Invalid digit %2$s found', $number, $digit));
}
}
return $number;
}
/**
* @phpstan-pure
*/
public static function roundMoneyValue(string $moneyValue, int $targetDigits, int $havingDigits): string
{
$valueLength = strlen($moneyValue);
$shouldRound = $targetDigits < $havingDigits && $valueLength - $havingDigits + $targetDigits > 0;
if ($shouldRound && $moneyValue[$valueLength - $havingDigits + $targetDigits] >= 5) {
$position = $valueLength - $havingDigits + $targetDigits;
$addend = 1;
while ($position > 0) {
// @phpstan-ignore possiblyImpure.methodCall (no idea what it thinks this)
$newValue = (string) ((int) $moneyValue[$position - 1] + $addend);
if ($newValue >= 10) {
$moneyValue[$position - 1] = $newValue[1];
$addend = $newValue[0];
--$position;
if ($position === 0) {
$moneyValue = $addend . $moneyValue;
}
} else {
if ($moneyValue[$position - 1] === '-') {
$moneyValue[$position - 1] = $newValue[0];
$moneyValue = '-' . $moneyValue;
} else {
$moneyValue[$position - 1] = $newValue[0];
}
break;
}
}
}
return $moneyValue;
}
}

View File

@@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
namespace Money\PHPUnit;
use Money\Currencies\AggregateCurrencies;
use Money\Currencies\BitcoinCurrencies;
use Money\Currencies\ISOCurrencies;
use Money\Formatter\IntlMoneyFormatter;
use Money\Money;
use NumberFormatter;
use SebastianBergmann\Comparator\ComparisonFailure;
use function assert;
/**
* The comparator is for comparing Money objects in PHPUnit tests.
*
* Add this to your bootstrap file:
*
* \SebastianBergmann\Comparator\Factory::getInstance()->register(new \Money\PHPUnit\Comparator());
*
* @internal do not use within your sources: this comparator is only to be used within the test suite of this library
*/
final class Comparator extends \SebastianBergmann\Comparator\Comparator
{
private IntlMoneyFormatter $formatter;
public function __construct()
{
$currencies = new AggregateCurrencies([
new ISOCurrencies(),
new BitcoinCurrencies(),
]);
$numberFormatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$this->formatter = new IntlMoneyFormatter($numberFormatter, $currencies);
}
/** {@inheritDoc} */
public function accepts(mixed $expected, mixed $actual): bool
{
return $expected instanceof Money && $actual instanceof Money;
}
/**
* {@inheritDoc}
*
* @param float $delta
* @param bool $canonicalize
* @param bool $ignoreCase
*/
public function assertEquals(
mixed $expected,
mixed $actual,
$delta = 0.0,
$canonicalize = false,
$ignoreCase = false
): void {
assert($expected instanceof Money);
assert($actual instanceof Money);
if (! $expected->equals($actual)) {
throw new ComparisonFailure($expected, $actual, $this->formatter->format($expected), $this->formatter->format($actual), 'Failed asserting that two Money objects are equal.');
}
}
}

View File

@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);
namespace Money\Parser;
use Money\Currency;
use Money\Exception;
use Money\Money;
use Money\MoneyParser;
use function sprintf;
/**
* Parses a string into a Money object using other parsers.
*/
final class AggregateMoneyParser implements MoneyParser
{
/**
* @param MoneyParser[] $parsers
* @phpstan-param non-empty-array<MoneyParser> $parsers
*/
public function __construct(private readonly array $parsers)
{
}
public function parse(string $money, Currency|null $fallbackCurrency = null): Money
{
foreach ($this->parsers as $parser) {
try {
return $parser->parse($money, $fallbackCurrency);
} catch (Exception\ParserException) {
}
}
throw new Exception\ParserException(sprintf('Unable to parse %s', $money));
}
}

View File

@@ -0,0 +1,61 @@
<?php
declare(strict_types=1);
namespace Money\Parser;
use Money\Currencies\BitcoinCurrencies;
use Money\Currency;
use Money\Exception\ParserException;
use Money\Money;
use Money\MoneyParser;
use function ltrim;
use function rtrim;
use function str_pad;
use function str_replace;
use function strlen;
use function strpos;
use function substr;
/**
* Parses Bitcoin currency to Money.
*/
final class BitcoinMoneyParser implements MoneyParser
{
public function __construct(private readonly int $fractionDigits)
{
}
public function parse(string $money, Currency|null $fallbackCurrency = null): Money
{
if (strpos($money, BitcoinCurrencies::SYMBOL) === false) {
throw new ParserException('Value cannot be parsed as Bitcoin');
}
$currency = $fallbackCurrency ?? new Currency(BitcoinCurrencies::CODE);
$decimal = str_replace(BitcoinCurrencies::SYMBOL, '', $money);
$decimalSeparator = strpos($decimal, '.');
if ($decimalSeparator !== false) {
$decimal = rtrim($decimal, '0');
$lengthDecimal = strlen($decimal);
$decimal = str_replace('.', '', $decimal);
$decimal .= str_pad('', ($lengthDecimal - $decimalSeparator - $this->fractionDigits - 1) * -1, '0');
} else {
$decimal .= str_pad('', $this->fractionDigits, '0');
}
if (substr($decimal, 0, 1) === '-') {
$decimal = '-' . ltrim(substr($decimal, 1), '0');
} else {
$decimal = ltrim($decimal, '0');
}
if ($decimal === '') {
$decimal = '0';
}
return new Money($decimal, $currency);
}
}

View File

@@ -0,0 +1,85 @@
<?php
declare(strict_types=1);
namespace Money\Parser;
use Money\Currencies;
use Money\Currency;
use Money\Exception\ParserException;
use Money\Money;
use Money\MoneyParser;
use Money\Number;
use function ltrim;
use function preg_match;
use function sprintf;
use function str_pad;
use function strlen;
use function substr;
use function trim;
/**
* Parses a decimal string into a Money object.
*/
final class DecimalMoneyParser implements MoneyParser
{
public const DECIMAL_PATTERN = '/^(?P<sign>-)?(?P<digits>\d+)?\.?(?P<fraction>\d+)?$/';
public function __construct(private readonly Currencies $currencies)
{
}
public function parse(string $money, Currency|null $fallbackCurrency = null): Money
{
if ($fallbackCurrency === null) {
throw new ParserException('DecimalMoneyParser cannot parse currency symbols. Use fallbackCurrency argument');
}
$decimal = trim($money);
if ($decimal === '') {
return new Money(0, $fallbackCurrency);
}
if (! preg_match(self::DECIMAL_PATTERN, $decimal, $matches) || ! isset($matches['digits'])) {
throw new ParserException(sprintf('Cannot parse "%s" to Money.', $decimal));
}
$negative = isset($matches['sign']) && $matches['sign'] === '-';
$decimal = $matches['digits'];
if ($negative) {
$decimal = '-' . $decimal;
}
$subunit = $this->currencies->subunitFor($fallbackCurrency);
if (isset($matches['fraction'])) {
$fractionDigits = strlen($matches['fraction']);
$decimal .= $matches['fraction'];
$decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits);
if ($fractionDigits > $subunit) {
$decimal = substr($decimal, 0, $subunit - $fractionDigits);
} elseif ($fractionDigits < $subunit) {
$decimal .= str_pad('', $subunit - $fractionDigits, '0');
}
} else {
$decimal .= str_pad('', $subunit, '0');
}
if ($negative) {
$decimal = '-' . ltrim(substr($decimal, 1), '0');
} else {
$decimal = ltrim($decimal, '0');
}
if ($decimal === '' || $decimal === '-') {
$decimal = '0';
}
return new Money($decimal, $fallbackCurrency);
}
}

View File

@@ -0,0 +1,74 @@
<?php
declare(strict_types=1);
namespace Money\Parser;
use Money\Currencies;
use Money\Currency;
use Money\Exception\ParserException;
use Money\Money;
use Money\MoneyParser;
use Money\Number;
use NumberFormatter;
use function ltrim;
use function str_pad;
use function str_replace;
use function strlen;
use function strpos;
use function substr;
/**
* Parses a string into a Money object using intl extension.
*/
final class IntlLocalizedDecimalParser implements MoneyParser
{
public function __construct(private readonly NumberFormatter $formatter, private readonly Currencies $currencies)
{
}
public function parse(string $money, Currency|null $fallbackCurrency = null): Money
{
if ($fallbackCurrency === null) {
throw new ParserException('IntlLocalizedDecimalParser cannot parse currency symbols. Use forceCurrency argument');
}
$decimal = $this->formatter->parse($money);
if ($decimal === false) {
throw new ParserException('Cannot parse ' . $money . ' to Money. ' . $this->formatter->getErrorMessage());
}
$decimal = (string) $decimal;
$subunit = $this->currencies->subunitFor($fallbackCurrency);
$decimalPosition = strpos($decimal, '.');
if ($decimalPosition !== false) {
$decimalLength = strlen($decimal);
$fractionDigits = $decimalLength - $decimalPosition - 1;
$decimal = str_replace('.', '', $decimal);
$decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits);
if ($fractionDigits > $subunit) {
$decimal = substr($decimal, 0, $decimalPosition + $subunit);
} elseif ($fractionDigits < $subunit) {
$decimal .= str_pad('', $subunit - $fractionDigits, '0');
}
} else {
$decimal .= str_pad('', $subunit, '0');
}
if ($decimal[0] === '-') {
$decimal = '-' . ltrim(substr($decimal, 1), '0');
} else {
$decimal = ltrim($decimal, '0');
}
if ($decimal === '') {
$decimal = '0';
}
return new Money($decimal, $fallbackCurrency);
}
}

View File

@@ -0,0 +1,80 @@
<?php
declare(strict_types=1);
namespace Money\Parser;
use Money\Currencies;
use Money\Currency;
use Money\Exception\ParserException;
use Money\Money;
use Money\MoneyParser;
use Money\Number;
use NumberFormatter;
use function assert;
use function ltrim;
use function str_pad;
use function str_replace;
use function strlen;
use function strpos;
use function substr;
/**
* Parses a string into a Money object using intl extension.
*/
final class IntlMoneyParser implements MoneyParser
{
public function __construct(private readonly NumberFormatter $formatter, private readonly Currencies $currencies)
{
}
public function parse(string $money, Currency|null $fallbackCurrency = null): Money
{
$currency = '';
// phpcs:ignore
/** @var string|float|bool|null $decimal */
$decimal = $this->formatter->parseCurrency($money, $currency);
if ($decimal === false || $decimal === null) {
throw new ParserException('Cannot parse ' . $money . ' to Money. ' . $this->formatter->getErrorMessage());
}
if ($fallbackCurrency === null) {
assert($currency !== '');
$fallbackCurrency = new Currency($currency);
}
$decimal = (string) $decimal;
$subunit = $this->currencies->subunitFor($fallbackCurrency);
$decimalPosition = strpos($decimal, '.');
if ($decimalPosition !== false) {
$decimalLength = strlen($decimal);
$fractionDigits = $decimalLength - $decimalPosition - 1;
$decimal = str_replace('.', '', $decimal);
$decimal = Number::roundMoneyValue($decimal, $subunit, $fractionDigits);
if ($fractionDigits > $subunit) {
$decimal = substr($decimal, 0, $decimalPosition + $subunit);
} elseif ($fractionDigits < $subunit) {
$decimal .= str_pad('', $subunit - $fractionDigits, '0');
}
} else {
$decimal .= str_pad('', $subunit, '0');
}
if ($decimal[0] === '-') {
$decimal = '-' . ltrim(substr($decimal, 1), '0');
} else {
$decimal = ltrim($decimal, '0');
}
if ($decimal === '') {
$decimal = '0';
}
return new Money($decimal, $fallbackCurrency);
}
}

428
vendor/moneyphp/money/src/Teller.php vendored Normal file
View File

@@ -0,0 +1,428 @@
<?php
declare(strict_types=1);
namespace Money;
use function is_float;
final class Teller
{
use TellerFactory;
/**
* @param Money::ROUND_* $roundingMode
*/
public function __construct(
private readonly Currency $currency,
private readonly MoneyParser $parser,
private readonly MoneyFormatter $formatter,
private readonly int $roundingMode = Money::ROUND_HALF_UP
) {
}
/**
* Are two monetary amounts equal to each other?
*
* @param mixed $amount a monetary amount
* @param mixed $other another monetary amount
*/
public function equals(mixed $amount, mixed $other): bool
{
return $this->convertToMoney($amount)->equals(
$this->convertToMoney($other)
);
}
/**
* Returns an integer less than, equal to, or greater than zero if a
* monetary amount is respectively less than, equal to, or greater than
* another.
*
* @param mixed $amount a monetary amount
* @param mixed $other another monetary amount
*/
public function compare(mixed $amount, mixed $other): int
{
return $this->convertToMoney($amount)->compare(
$this->convertToMoney($other)
);
}
/**
* Is one monetary amount greater than another?
*
* @param mixed $amount a monetary amount
* @param mixed $other another monetary amount
*/
public function greaterThan(mixed $amount, mixed $other): bool
{
return $this->convertToMoney($amount)->greaterThan(
$this->convertToMoney($other)
);
}
/**
* Is one monetary amount greater than or equal to another?
*
* @param mixed $amount a monetary amount
* @param mixed $other another monetary amount
*/
public function greaterThanOrEqual(mixed $amount, mixed $other): bool
{
return $this->convertToMoney($amount)->greaterThanOrEqual(
$this->convertToMoney($other)
);
}
/**
* Is one monetary amount less than another?
*
* @param mixed $amount a monetary amount
* @param mixed $other another monetary amount
*/
public function lessThan(mixed $amount, mixed $other): bool
{
return $this->convertToMoney($amount)->lessThan(
$this->convertToMoney($other)
);
}
/**
* Is one monetary amount less than or equal to another?
*
* @param mixed $amount a monetary amount
* @param mixed $other another monetary amount
*/
public function lessThanOrEqual(mixed $amount, mixed $other): bool
{
return $this->convertToMoney($amount)->lessThanOrEqual(
$this->convertToMoney($other)
);
}
/**
* Adds a series of monetary amounts to each other in sequence.
*
* @param mixed $amount a monetary amount
* @param mixed $other another monetary amount
* @param mixed $others subsequent other monetary amounts
*
* @return string the calculated monetary amount
*/
public function add(mixed $amount, mixed $other, mixed ...$others): string
{
return $this->convertToString(
$this->convertToMoney($amount)->add(
$this->convertToMoney($other),
...$this->convertToMoneyArray($others)
)
);
}
/**
* Subtracts a series of monetary amounts from each other in sequence.
*
* @param mixed $amount a monetary amount
* @param mixed $other another monetary amount
* @param mixed $others subsequent monetary amounts
*/
public function subtract(mixed $amount, mixed $other, mixed ...$others): string
{
return $this->convertToString(
$this->convertToMoney($amount)->subtract(
$this->convertToMoney($other),
...$this->convertToMoneyArray($others)
)
);
}
/**
* Multiplies a monetary amount by a factor.
*
* @param mixed $amount a monetary amount
* @param int|float|numeric-string $multiplier the multiplier
*/
public function multiply(mixed $amount, int|float|string $multiplier): string
{
$multiplier = is_float($multiplier) ? Number::fromFloat($multiplier) : Number::fromNumber($multiplier);
return $this->convertToString(
$this->convertToMoney($amount)->multiply(
(string) $multiplier,
$this->roundingMode
)
);
}
/**
* Divides a monetary amount by a divisor.
*
* @param mixed $amount a monetary amount
* @param int|float|numeric-string $divisor the divisor
*/
public function divide(mixed $amount, int|float|string $divisor): string
{
$divisor = is_float($divisor) ? Number::fromFloat($divisor) : Number::fromNumber($divisor);
return $this->convertToString(
$this->convertToMoney($amount)->divide(
(string) $divisor,
$this->roundingMode
)
);
}
/**
* Mods a monetary amount by a divisor.
*
* @param mixed $amount a monetary amount
* @param int|float|numeric-string $divisor the divisor
*/
public function mod(mixed $amount, int|float|string $divisor): string
{
$divisor = is_float($divisor) ? Number::fromFloat($divisor) : Number::fromNumber($divisor);
return $this->convertToString(
$this->convertToMoney($amount)->mod(
$this->convertToMoney((string) $divisor)
)
);
}
/**
* Allocates a monetary amount according to an array of ratios.
*
* @param mixed $amount a monetary amount
* @param non-empty-array<array-key, float|int> $ratios an array of ratios
*
* @return string[] the calculated monetary amounts
*/
public function allocate(mixed $amount, array $ratios): array
{
return $this->convertToStringArray(
$this->convertToMoney($amount)->allocate($ratios)
);
}
/**
* Allocates a monetary amount among N targets.
*
* @param mixed $amount a monetary amount
* @phpstan-param positive-int $n the number of targets
*
* @return string[] the calculated monetary amounts
*/
public function allocateTo(mixed $amount, int $n): array
{
return $this->convertToStringArray(
$this->convertToMoney($amount)->allocateTo($n)
);
}
/**
* Determines the ratio of one monetary amount to another.
*
* @param mixed $amount a monetary amount
* @param mixed $other another monetary amount
*/
public function ratioOf(mixed $amount, mixed $other): string
{
return $this->convertToString(
$this->convertToMoney($amount)->ratioOf(
$this->convertToMoney($other)
)
);
}
/**
* Returns an absolute monetary amount.
*
* @param mixed $amount a monetary amount
*/
public function absolute(mixed $amount): string
{
return $this->convertToString(
$this->convertToMoney($amount)->absolute()
);
}
/**
* Returns the negative of an amount; note that this will convert negative
* amounts to positive ones.
*
* @param mixed $amount a monetary amount
*/
public function negative(mixed $amount): string
{
return $this->convertToString(
$this->convertToMoney($amount)->negative()
);
}
/**
* Is a monetary amount equal to zero?
*
* @param mixed $amount a monetary amount
*/
public function isZero(mixed $amount): bool
{
return $this->convertToMoney($amount)->isZero();
}
/**
* Is a monetary amount greater than zero?
*
* @param mixed $amount a monetary amount
*/
public function isPositive(mixed $amount): bool
{
return $this->convertToMoney($amount)->isPositive();
}
/**
* Is a monetary amount less than zero?
*
* @param mixed $amount a monetary amount
*/
public function isNegative(mixed $amount): bool
{
return $this->convertToMoney($amount)->isNegative();
}
/**
* Returns the lowest of a series of monetary amounts.
*
* @param mixed $amount a monetary amount
* @param mixed ...$amounts additional monetary amounts
*/
public function min(mixed $amount, mixed ...$amounts): string
{
return $this->convertToString(
Money::min(
$this->convertToMoney($amount),
...$this->convertToMoneyArray($amounts)
)
);
}
/**
* Returns the highest of a series of monetary amounts.
*
* @param mixed $amount a monetary amount
* @param mixed ...$amounts additional monetary amounts
*/
public function max(mixed $amount, mixed ...$amounts): string
{
return $this->convertToString(
Money::max(
$this->convertToMoney($amount),
...$this->convertToMoneyArray($amounts)
)
);
}
/**
* Returns the sum of a series of monetary amounts.
*
* @param mixed $amount a monetary amount
* @param mixed ...$amounts additional monetary amounts
*/
public function sum(mixed $amount, mixed ...$amounts): string
{
return $this->convertToString(
Money::sum(
$this->convertToMoney($amount),
...$this->convertToMoneyArray($amounts)
)
);
}
/**
* Returns the average of a series of monetary amounts.
*
* @param mixed $amount a monetary amount
* @param mixed ...$amounts additional monetary amounts
*/
public function avg(mixed $amount, mixed ...$amounts): string
{
return $this->convertToString(
Money::avg(
$this->convertToMoney($amount),
...$this->convertToMoneyArray($amounts)
)
);
}
/**
* Converts a monetary amount to a Money object.
*
* @param mixed $amount a monetary amount
*/
public function convertToMoney(mixed $amount): Money
{
return $this->parser->parse((string) $amount, $this->currency);
}
/**
* Converts an array of monetary amounts to an array of Money objects.
*
* @param array<int|string, mixed> $amounts an array of monetary amounts
*
* @return Money[]
*/
public function convertToMoneyArray(array $amounts): array
{
$converted = [];
/** @var mixed $amount */
foreach ($amounts as $key => $amount) {
$converted[$key] = $this->convertToMoney($amount);
}
return $converted;
}
/**
* Converts a monetary amount into a Money object, then into a string.
*
* @param mixed $amount typically a Money object, int, float, or string
* representing a monetary amount
*/
public function convertToString(mixed $amount): string
{
if ($amount instanceof Money === false) {
$amount = $this->convertToMoney($amount);
}
return $this->formatter->format($amount);
}
/**
* Converts an array of monetary amounts into Money objects, then into
* strings.
*
* @param array<int|string, mixed> $amounts an array of monetary amounts
*
* @return string[]
*/
public function convertToStringArray(array $amounts): array
{
$converted = [];
/** @var mixed $amount */
foreach ($amounts as $key => $amount) {
$converted[$key] = $this->convertToString($amount);
}
return $converted;
}
/**
* Returns a "zero" monetary amount.
*/
public function zero(): string
{
return '0.00';
}
}

View File

@@ -0,0 +1,629 @@
<?php
declare(strict_types=1);
namespace Money;
use Money\Currencies\ISOCurrencies;
use Money\Formatter\DecimalMoneyFormatter;
use Money\Parser\DecimalMoneyParser;
use function array_shift;
/**
* This is a generated file. Do not edit it manually!
*
* @method static Teller ONETHOUSANDCAT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ONETHOUSANDCHEEMS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ONETHOUSANDSATS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ONEINCH(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ONEMBABYDOGE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller A(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AAVE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ACA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ACE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ACH(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ACM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ACT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ACX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ADA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ADX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AED(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AEUR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AEVO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AFN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AGLD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AIXBT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ALCX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ALGO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ALICE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ALL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ALPHA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ALPINE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ALT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AMD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AMP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ANIME(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ANKR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AOA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller APE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller API3(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller APT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ARB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ARDR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ARK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ARKM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ARPA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ARS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ASR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ASTR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ATA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ATM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ATOM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AUCTION(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AUD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AUDIO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AVA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AVAX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AWE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AWG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AXL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AXS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller AZN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BABY(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BAKE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BAM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BANANA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BANANAS31(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BAND(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BAR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BAT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BBD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BCH(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BDT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BEAMX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BEL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BERA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BGN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BHD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BICO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BIF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BIFI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BIGTIME(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BIO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BLUR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BMD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BMT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BNB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BND(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BNSOL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BNT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BOB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BOME(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BONK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BOV(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BRL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BROCCOLI714(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BSD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BSW(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BTC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BTN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BTTC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BWP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BYN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller BZD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller C98(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CAD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CAKE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CATI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CDF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CELO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CELR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CETUS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CFX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CGPT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CHE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CHESS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CHF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CHR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CHW(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CHZ(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CITY(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CKB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CLF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CLP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CNY(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller COMP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller COOKIE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller COP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller COS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller COTI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller COU(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller COW(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CRC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CRV(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CTK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CTSI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CUP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CVC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CVE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CVX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CYBER(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller CZK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller D(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DAI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DASH(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DATA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DCR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DEGO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DENT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DEXE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DGB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DIA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DJF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DKK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DODO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DOGE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DOGS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DOP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DOT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DUSK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DYDX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DYM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller DZD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller EDU(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller EGLD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller EGP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller EIGEN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ENA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ENJ(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ENS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller EPIC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ERN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ETB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ETC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ETH(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ETHFI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller EUR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller EURI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FARM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FDUSD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FET(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FIDA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FIL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FIO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FIS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FJD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FKP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FLM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FLOKI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FLOW(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FLUX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FORM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FORTH(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FTT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FUN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller FXS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller G(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GALA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GAS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GBP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GEL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GHS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GHST(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GIP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GLM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GLMR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GMD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GMT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GMX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GNF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GNO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GNS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GPS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GRT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GTC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GTQ(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GUN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller GYD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HAEDAL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HBAR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HEI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HFT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HIFI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HIGH(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HIVE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HKD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HMSTR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HNL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HOOK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HOT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HTG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HUF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HUMA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller HYPER(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ICP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ICX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ID(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller IDEX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller IDR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ILS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ILV(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller IMX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller INIT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller INJ(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller INR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller IO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller IOST(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller IOTA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller IOTX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller IQ(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller IQD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller IRR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ISK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller JASMY(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller JMD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller JOD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller JOE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller JPY(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller JST(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller JTO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller JUP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller JUV(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KAIA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KAITO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KAVA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KDA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KERNEL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KES(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KGS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KHR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KMD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KMF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KMNO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KNC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KPW(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KRW(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KSM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KWD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KYD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller KZT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LAK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LAYER(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LAZIO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LBP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LDO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LEVER(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LINK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LISTA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LKR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LOKA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LPT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LQTY(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LRC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LRD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LSK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LSL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LTC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LTO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LUMIA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LUNA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LUNC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller LYD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MAD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MAGIC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MANA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MANTA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MASK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MAV(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MBL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MBOX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MDL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MDT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ME(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MEME(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller METIS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MGA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MINA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MKD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MKR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MLN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MMK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MNT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MOP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MOVE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MOVR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MRU(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MTL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MUBARAK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MUR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MVR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MWK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MXN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MXV(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MYR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller MZN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NAD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NEAR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NEIRO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NEO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NEXO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NFP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NGN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NIL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NIO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NKN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NMR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NOK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NOT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NPR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NTRN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NXPC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller NZD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller OG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller OGN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller OM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller OMNI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller OMR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ONDO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ONE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ONG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ONT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller OP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ORCA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ORDI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller OSMO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller OXT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PAB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PARTI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PAXG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PEN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PENDLE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PENGU(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PEOPLE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PEPE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PERP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PGK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PHA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PHB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PHP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PIVX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PIXEL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PKR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PLN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PNUT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller POL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller POLYX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller POND(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PORTAL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PORTO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller POWR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PROM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PSG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PUNDIX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PYG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PYR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller PYTH(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller QAR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller QI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller QKC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller QNT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller QTUM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller QUICK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RAD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RARE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RAY(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RDNT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RED(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller REI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RENDER(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller REQ(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller REZ(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RIF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RLC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RON(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RONIN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ROSE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RPL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RSD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RSR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RUB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RUNE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RVN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller RWF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller S(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SAGA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SAND(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SANTOS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SAR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SBD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SCR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SCRT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SDG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SEI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SEK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SFP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SGD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SHELL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SHIB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SHP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SIGN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SKL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SLE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SLF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SLP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SNX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SOL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SOLV(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SOPH(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SOS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SPELL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SRD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SSP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SSV(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller STEEM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller STG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller STN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller STO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller STORJ(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller STRAX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller STRK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller STX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SUI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SUN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SUPER(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SUSHI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SVC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SXP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SXT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SYN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SYP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SYRUP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SYS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller SZL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller T(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TAO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TFUEL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller THB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller THE(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller THETA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TIA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TJS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TKO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TLM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TMT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TND(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TNSR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TON(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TOP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TRB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TRU(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TRUMP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TRX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TRY(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TST(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TTD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TURBO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TUSD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TUT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TWD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TWT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller TZS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller UAH(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller UGX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller UMA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller UNI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller USD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller USD1(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller USDC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller USDP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller USDT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller USN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller USTC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller USUAL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller UTK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller UYI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller UYU(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller UYW(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller UZS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VANA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VANRY(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VED(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VELODROME(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VES(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VET(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VIC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VIRTUAL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VND(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VOXEL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VTHO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller VUV(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller W(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller WAN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller WAXP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller WBETH(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller WBTC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller WCT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller WIF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller WIN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller WLD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller WOO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller WST(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XAD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XAF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XAG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XAI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XAU(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XBA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XBB(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XBC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XBD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XBT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XCD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XCG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XDR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XEC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XLM(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XNO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XOF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XPD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XPF(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XPT(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XRP(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XSU(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XTS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XTZ(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XUA(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XUSD(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XVG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XVS(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller XXX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller YER(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller YFI(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller YGG(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ZAR(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ZEC(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ZEN(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ZIL(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ZK(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ZMW(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ZRO(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ZRX(int $roundingMode = Money::ROUND_HALF_UP)
* @method static Teller ZWG(int $roundingMode = Money::ROUND_HALF_UP)
* @psalm-immutable
*/
trait TellerFactory
{
/**
* Convenience factory method for a Teller object.
*
* <code>
* $teller = Teller::USD();
* </code>
*
* @param non-empty-string $method
* @param array{0?: Money::ROUND_*} $arguments
*/
public static function __callStatic(string $method, array $arguments): Teller
{
$currency = new Currency($method);
$currencies = new ISOCurrencies();
$parser = new DecimalMoneyParser($currencies);
$formatter = new DecimalMoneyFormatter($currencies);
$roundingMode = empty($arguments)
? Money::ROUND_HALF_UP
: (int) array_shift($arguments);
return new Teller(
$currency,
$parser,
$formatter,
$roundingMode
);
}
}