new appraoch
This commit is contained in:
21
pancake/system/vendor/moneyphp/money/LICENSE
vendored
Executable file
21
pancake/system/vendor/moneyphp/money/LICENSE
vendored
Executable file
@@ -0,0 +1,21 @@
|
||||
Copyright (c) 2011-2016 Mathias Verraes
|
||||
Copyright (c) 2016 Márk Sági-Kazár <mark.sagikazar@gmail.com>
|
||||
Copyright (c) 2016 Frederik Bosch <f.bosch@genkgo.nl>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
95
pancake/system/vendor/moneyphp/money/composer.json
vendored
Executable file
95
pancake/system/vendor/moneyphp/money/composer.json
vendored
Executable file
@@ -0,0 +1,95 @@
|
||||
{
|
||||
"name": "moneyphp/money",
|
||||
"description": "PHP implementation of Fowler's Money pattern",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"money",
|
||||
"vo",
|
||||
"value object"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Mathias Verraes",
|
||||
"email": "mathias@verraes.net",
|
||||
"homepage": "http://verraes.net"
|
||||
},
|
||||
{
|
||||
"name": "Márk Sági-Kazár",
|
||||
"email": "mark.sagikazar@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Frederik Bosch",
|
||||
"email": "f.bosch@genkgo.nl"
|
||||
}
|
||||
],
|
||||
"homepage": "http://moneyphp.org",
|
||||
"require": {
|
||||
"php": ">=5.6",
|
||||
"ext-json": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"ext-bcmath": "*",
|
||||
"ext-gmp": "*",
|
||||
"ext-intl": "*",
|
||||
"cache/taggable-cache": "^0.4.0",
|
||||
"doctrine/instantiator": "^1.0.5",
|
||||
"florianv/exchanger": "^1.0",
|
||||
"florianv/swap": "^3.0",
|
||||
"friends-of-phpspec/phpspec-code-coverage": "^3.1.1 || ^4.3",
|
||||
"moneyphp/iso-currencies": "^3.2.1",
|
||||
"php-http/message": "^1.4",
|
||||
"php-http/mock-client": "^1.0.0",
|
||||
"phpspec/phpspec": "^3.4.3",
|
||||
"phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.18 || ^8.5",
|
||||
"psr/cache": "^1.0",
|
||||
"symfony/phpunit-bridge": "^4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-bcmath": "Calculate without integer limits",
|
||||
"ext-gmp": "Calculate without integer limits",
|
||||
"ext-intl": "Format Money objects with intl",
|
||||
"florianv/exchanger": "Exchange rates library for PHP",
|
||||
"florianv/swap": "Exchange rates library for PHP",
|
||||
"psr/cache-implementation": "Used for Currency caching"
|
||||
},
|
||||
"minimum-stability": "dev",
|
||||
"prefer-stable": true,
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Money\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"Tests\\Money\\": "tests/",
|
||||
"spec\\Money\\": "spec/"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"allow-plugins": {
|
||||
"dealerdirect/phpcodesniffer-composer-installer": true,
|
||||
"ergebnis/composer-normalize": true
|
||||
},
|
||||
"sort-packages": true
|
||||
},
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.x-dev"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"clean": "rm -rf build/ vendor/",
|
||||
"test": [
|
||||
"vendor/bin/phpspec run",
|
||||
"vendor/bin/phpunit -v"
|
||||
],
|
||||
"test-coverage": [
|
||||
"vendor/bin/phpspec run -c phpspec.ci.yml",
|
||||
"vendor/bin/phpunit -v --coverage-text --coverage-clover=build/unit_coverage.xml"
|
||||
],
|
||||
"update-currencies": [
|
||||
"cp vendor/moneyphp/iso-currencies/resources/current.php resources/currency.php",
|
||||
"php resources/generate-money-factory.php"
|
||||
]
|
||||
}
|
||||
}
|
||||
1255
pancake/system/vendor/moneyphp/money/resources/currency.php
vendored
Executable file
1255
pancake/system/vendor/moneyphp/money/resources/currency.php
vendored
Executable file
File diff suppressed because it is too large
Load Diff
61
pancake/system/vendor/moneyphp/money/resources/generate-money-factory.php
vendored
Executable file
61
pancake/system/vendor/moneyphp/money/resources/generate-money-factory.php
vendored
Executable file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
require __DIR__.'/../vendor/autoload.php';
|
||||
|
||||
use Money\Currencies;
|
||||
|
||||
$buffer = <<<PHP
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
/**
|
||||
* This is a generated file. Do not edit it manually!
|
||||
*
|
||||
PHPDOC
|
||||
*/
|
||||
trait MoneyFactory
|
||||
{
|
||||
/**
|
||||
* Convenience factory method for a Money object.
|
||||
*
|
||||
* <code>
|
||||
* \$fiveDollar = Money::USD(500);
|
||||
* </code>
|
||||
*
|
||||
* @param string \$method
|
||||
* @param array \$arguments
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @throws \InvalidArgumentException If amount is not integer(ish)
|
||||
*/
|
||||
public static function __callStatic(\$method, \$arguments)
|
||||
{
|
||||
return new Money(\$arguments[0], new Currency(\$method));
|
||||
}
|
||||
}
|
||||
|
||||
PHP;
|
||||
|
||||
$methodBuffer = '';
|
||||
|
||||
$currencies = new Currencies\AggregateCurrencies([
|
||||
new Currencies\ISOCurrencies(),
|
||||
new Currencies\BitcoinCurrencies(),
|
||||
]);
|
||||
|
||||
$currencies = iterator_to_array($currencies);
|
||||
|
||||
usort($currencies, function (\Money\Currency $a, \Money\Currency $b) {
|
||||
return strcmp($a->getCode(), $b->getCode());
|
||||
});
|
||||
|
||||
/** @var \Money\Currency[] $currencies */
|
||||
foreach ($currencies as $currency) {
|
||||
$methodBuffer .= sprintf(" * @method static Money %s(string|int \$amount)\n", $currency->getCode());
|
||||
}
|
||||
|
||||
$buffer = str_replace('PHPDOC', rtrim($methodBuffer), $buffer);
|
||||
|
||||
file_put_contents(__DIR__.'/../src/MoneyFactory.php', $buffer);
|
||||
127
pancake/system/vendor/moneyphp/money/src/Calculator.php
vendored
Executable file
127
pancake/system/vendor/moneyphp/money/src/Calculator.php
vendored
Executable file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
/**
|
||||
* Money calculations abstracted away from the Money value object.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
interface Calculator
|
||||
{
|
||||
/**
|
||||
* Returns whether the calculator is supported in
|
||||
* the current server environment.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function supported();
|
||||
|
||||
/**
|
||||
* Compare a to b.
|
||||
*
|
||||
* @param string $a
|
||||
* @param string $b
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function compare($a, $b);
|
||||
|
||||
/**
|
||||
* Add added to amount.
|
||||
*
|
||||
* @param string $amount
|
||||
* @param string $addend
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function add($amount, $addend);
|
||||
|
||||
/**
|
||||
* Subtract subtrahend from amount.
|
||||
*
|
||||
* @param string $amount
|
||||
* @param string $subtrahend
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function subtract($amount, $subtrahend);
|
||||
|
||||
/**
|
||||
* Multiply amount with multiplier.
|
||||
*
|
||||
* @param string $amount
|
||||
* @param int|float|string $multiplier
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function multiply($amount, $multiplier);
|
||||
|
||||
/**
|
||||
* Divide amount with divisor.
|
||||
*
|
||||
* @param string $amount
|
||||
* @param int|float|string $divisor
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function divide($amount, $divisor);
|
||||
|
||||
/**
|
||||
* Round number to following integer.
|
||||
*
|
||||
* @param string $number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function ceil($number);
|
||||
|
||||
/**
|
||||
* Round number to preceding integer.
|
||||
*
|
||||
* @param string $number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function floor($number);
|
||||
|
||||
/**
|
||||
* Returns the absolute value of the number.
|
||||
*
|
||||
* @param string $number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function absolute($number);
|
||||
|
||||
/**
|
||||
* Round number, use rounding mode for tie-breaker.
|
||||
*
|
||||
* @param int|float|string $number
|
||||
* @param int $roundingMode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function round($number, $roundingMode);
|
||||
|
||||
/**
|
||||
* Share amount among ratio / total portions.
|
||||
*
|
||||
* @param string $amount
|
||||
* @param int|float|string $ratio
|
||||
* @param int|float|string $total
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function share($amount, $ratio, $total);
|
||||
|
||||
/**
|
||||
* Get the modulus of an amount.
|
||||
*
|
||||
* @param string $amount
|
||||
* @param int|float|string $divisor
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function mod($amount, $divisor);
|
||||
}
|
||||
241
pancake/system/vendor/moneyphp/money/src/Calculator/BcMathCalculator.php
vendored
Executable file
241
pancake/system/vendor/moneyphp/money/src/Calculator/BcMathCalculator.php
vendored
Executable file
@@ -0,0 +1,241 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Calculator;
|
||||
|
||||
use Money\Calculator;
|
||||
use Money\Money;
|
||||
use Money\Number;
|
||||
|
||||
/**
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class BcMathCalculator implements Calculator
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $scale;
|
||||
|
||||
/**
|
||||
* @param int $scale
|
||||
*/
|
||||
public function __construct($scale = 14)
|
||||
{
|
||||
$this->scale = $scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function supported()
|
||||
{
|
||||
return extension_loaded('bcmath');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function compare($a, $b)
|
||||
{
|
||||
return bccomp($a, $b, $this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add($amount, $addend)
|
||||
{
|
||||
return (string) Number::fromString(bcadd($amount, $addend, $this->scale));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @param $amount
|
||||
* @param $subtrahend
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function subtract($amount, $subtrahend)
|
||||
{
|
||||
return (string) Number::fromString(bcsub($amount, $subtrahend, $this->scale));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function multiply($amount, $multiplier)
|
||||
{
|
||||
$multiplier = Number::fromNumber($multiplier);
|
||||
|
||||
return bcmul($amount, (string) $multiplier, $this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divide($amount, $divisor)
|
||||
{
|
||||
$divisor = Number::fromNumber($divisor);
|
||||
|
||||
return bcdiv($amount, (string) $divisor, $this->scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function ceil($number)
|
||||
{
|
||||
$number = Number::fromNumber($number);
|
||||
|
||||
if ($number->isInteger()) {
|
||||
return (string) $number;
|
||||
}
|
||||
|
||||
if ($number->isNegative()) {
|
||||
return bcadd((string) $number, '0', 0);
|
||||
}
|
||||
|
||||
return bcadd((string) $number, '1', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function floor($number)
|
||||
{
|
||||
$number = Number::fromNumber($number);
|
||||
|
||||
if ($number->isInteger()) {
|
||||
return (string) $number;
|
||||
}
|
||||
|
||||
if ($number->isNegative()) {
|
||||
return bcadd((string) $number, '-1', 0);
|
||||
}
|
||||
|
||||
return bcadd($number, '0', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function absolute($number)
|
||||
{
|
||||
return ltrim($number, '-');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function round($number, $roundingMode)
|
||||
{
|
||||
$number = Number::fromNumber($number);
|
||||
|
||||
if ($number->isInteger()) {
|
||||
return (string) $number;
|
||||
}
|
||||
|
||||
if ($number->isHalf() === false) {
|
||||
return $this->roundDigit($number);
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_UP === $roundingMode) {
|
||||
return bcadd(
|
||||
(string) $number,
|
||||
$number->getIntegerRoundingMultiplier(),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_DOWN === $roundingMode) {
|
||||
return bcadd((string) $number, '0', 0);
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_EVEN === $roundingMode) {
|
||||
if ($number->isCurrentEven()) {
|
||||
return bcadd((string) $number, '0', 0);
|
||||
}
|
||||
|
||||
return bcadd(
|
||||
(string) $number,
|
||||
$number->getIntegerRoundingMultiplier(),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_ODD === $roundingMode) {
|
||||
if ($number->isCurrentEven()) {
|
||||
return bcadd(
|
||||
(string) $number,
|
||||
$number->getIntegerRoundingMultiplier(),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
return bcadd((string) $number, '0', 0);
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_POSITIVE_INFINITY === $roundingMode) {
|
||||
if ($number->isNegative()) {
|
||||
return bcadd((string) $number, '0', 0);
|
||||
}
|
||||
|
||||
return bcadd(
|
||||
(string) $number,
|
||||
$number->getIntegerRoundingMultiplier(),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_NEGATIVE_INFINITY === $roundingMode) {
|
||||
if ($number->isNegative()) {
|
||||
return bcadd(
|
||||
(string) $number,
|
||||
$number->getIntegerRoundingMultiplier(),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
return bcadd(
|
||||
(string) $number,
|
||||
'0',
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Unknown rounding mode');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function roundDigit(Number $number)
|
||||
{
|
||||
if ($number->isCloserToNext()) {
|
||||
return bcadd(
|
||||
(string) $number,
|
||||
$number->getIntegerRoundingMultiplier(),
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
return bcadd((string) $number, '0', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function share($amount, $ratio, $total)
|
||||
{
|
||||
return $this->floor(bcdiv(bcmul($amount, $ratio, $this->scale), $total, $this->scale));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mod($amount, $divisor)
|
||||
{
|
||||
return bcmod($amount, $divisor);
|
||||
}
|
||||
}
|
||||
322
pancake/system/vendor/moneyphp/money/src/Calculator/GmpCalculator.php
vendored
Executable file
322
pancake/system/vendor/moneyphp/money/src/Calculator/GmpCalculator.php
vendored
Executable file
@@ -0,0 +1,322 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Calculator;
|
||||
|
||||
use Money\Calculator;
|
||||
use Money\Money;
|
||||
use Money\Number;
|
||||
|
||||
/**
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class GmpCalculator implements Calculator
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $scale;
|
||||
|
||||
/**
|
||||
* @param int $scale
|
||||
*/
|
||||
public function __construct($scale = 14)
|
||||
{
|
||||
$this->scale = $scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function supported()
|
||||
{
|
||||
return extension_loaded('gmp');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function compare($a, $b)
|
||||
{
|
||||
$aNum = Number::fromNumber($a);
|
||||
$bNum = Number::fromNumber($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);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add($amount, $addend)
|
||||
{
|
||||
return gmp_strval(gmp_add($amount, $addend));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function subtract($amount, $subtrahend)
|
||||
{
|
||||
return gmp_strval(gmp_sub($amount, $subtrahend));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function multiply($amount, $multiplier)
|
||||
{
|
||||
$multiplier = Number::fromNumber($multiplier);
|
||||
|
||||
if ($multiplier->isDecimal()) {
|
||||
$decimalPlaces = strlen($multiplier->getFractionalPart());
|
||||
$multiplierBase = $multiplier->getIntegerPart();
|
||||
|
||||
if ($multiplierBase) {
|
||||
$multiplierBase .= $multiplier->getFractionalPart();
|
||||
} else {
|
||||
$multiplierBase = ltrim($multiplier->getFractionalPart(), '0');
|
||||
}
|
||||
|
||||
$resultBase = gmp_strval(gmp_mul(gmp_init($amount), gmp_init($multiplierBase)));
|
||||
|
||||
if ('0' === $resultBase) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
$result = substr($resultBase, $decimalPlaces * -1);
|
||||
$resultLength = strlen($result);
|
||||
if ($decimalPlaces > $resultLength) {
|
||||
return '0.'.str_pad('', $decimalPlaces - $resultLength, '0').$result;
|
||||
}
|
||||
|
||||
return substr($resultBase, 0, $decimalPlaces * -1).'.'.$result;
|
||||
}
|
||||
|
||||
return gmp_strval(gmp_mul(gmp_init($amount), gmp_init((string) $multiplier)));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divide($amount, $divisor)
|
||||
{
|
||||
$divisor = Number::fromNumber($divisor);
|
||||
|
||||
if ($divisor->isDecimal()) {
|
||||
$decimalPlaces = strlen($divisor->getFractionalPart());
|
||||
|
||||
if ($divisor->getIntegerPart()) {
|
||||
$divisor = new Number($divisor->getIntegerPart().$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'))));
|
||||
}
|
||||
|
||||
list($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('', $this->scale, '0'))),
|
||||
gmp_init((string) $divisor),
|
||||
GMP_ROUND_MINUSINF
|
||||
)
|
||||
);
|
||||
|
||||
if ($divisionOfRemainder[0] === '-') {
|
||||
$divisionOfRemainder = substr($divisionOfRemainder, 1);
|
||||
}
|
||||
|
||||
return gmp_strval($integer).'.'.str_pad($divisionOfRemainder, $this->scale, '0', STR_PAD_LEFT);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function ceil($number)
|
||||
{
|
||||
$number = Number::fromNumber($number);
|
||||
|
||||
if ($number->isInteger()) {
|
||||
return (string) $number;
|
||||
}
|
||||
|
||||
if ($number->isNegative()) {
|
||||
return $this->add($number->getIntegerPart(), '0');
|
||||
}
|
||||
|
||||
return $this->add($number->getIntegerPart(), '1');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function floor($number)
|
||||
{
|
||||
$number = Number::fromNumber($number);
|
||||
|
||||
if ($number->isInteger()) {
|
||||
return (string) $number;
|
||||
}
|
||||
|
||||
if ($number->isNegative()) {
|
||||
return $this->add($number->getIntegerPart(), '-1');
|
||||
}
|
||||
|
||||
return $this->add($number->getIntegerPart(), '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function absolute($number)
|
||||
{
|
||||
return ltrim($number, '-');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function round($number, $roundingMode)
|
||||
{
|
||||
$number = Number::fromNumber($number);
|
||||
|
||||
if ($number->isInteger()) {
|
||||
return (string) $number;
|
||||
}
|
||||
|
||||
if ($number->isHalf() === false) {
|
||||
return $this->roundDigit($number);
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_UP === $roundingMode) {
|
||||
return $this->add(
|
||||
$number->getIntegerPart(),
|
||||
$number->getIntegerRoundingMultiplier()
|
||||
);
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_DOWN === $roundingMode) {
|
||||
return $this->add($number->getIntegerPart(), '0');
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_EVEN === $roundingMode) {
|
||||
if ($number->isCurrentEven()) {
|
||||
return $this->add($number->getIntegerPart(), '0');
|
||||
}
|
||||
|
||||
return $this->add(
|
||||
$number->getIntegerPart(),
|
||||
$number->getIntegerRoundingMultiplier()
|
||||
);
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_ODD === $roundingMode) {
|
||||
if ($number->isCurrentEven()) {
|
||||
return $this->add(
|
||||
$number->getIntegerPart(),
|
||||
$number->getIntegerRoundingMultiplier()
|
||||
);
|
||||
}
|
||||
|
||||
return $this->add($number->getIntegerPart(), '0');
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_POSITIVE_INFINITY === $roundingMode) {
|
||||
if ($number->isNegative()) {
|
||||
return $this->add(
|
||||
$number->getIntegerPart(),
|
||||
'0'
|
||||
);
|
||||
}
|
||||
|
||||
return $this->add(
|
||||
$number->getIntegerPart(),
|
||||
$number->getIntegerRoundingMultiplier()
|
||||
);
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_NEGATIVE_INFINITY === $roundingMode) {
|
||||
if ($number->isNegative()) {
|
||||
return $this->add(
|
||||
$number->getIntegerPart(),
|
||||
$number->getIntegerRoundingMultiplier()
|
||||
);
|
||||
}
|
||||
|
||||
return $this->add(
|
||||
$number->getIntegerPart(),
|
||||
'0'
|
||||
);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Unknown rounding mode');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function roundDigit(Number $number)
|
||||
{
|
||||
if ($number->isCloserToNext()) {
|
||||
return $this->add(
|
||||
$number->getIntegerPart(),
|
||||
$number->getIntegerRoundingMultiplier()
|
||||
);
|
||||
}
|
||||
|
||||
return $this->add($number->getIntegerPart(), '0');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function share($amount, $ratio, $total)
|
||||
{
|
||||
return $this->floor($this->divide($this->multiply($amount, $ratio), $total));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mod($amount, $divisor)
|
||||
{
|
||||
// gmp_mod() only calculates non-negative integers, so we use absolutes
|
||||
$remainder = gmp_mod($this->absolute($amount), $this->absolute($divisor));
|
||||
|
||||
// If the amount was negative, we negate the result of the modulus operation
|
||||
$amount = Number::fromNumber($amount);
|
||||
|
||||
if ($amount->isNegative()) {
|
||||
$remainder = gmp_neg($remainder);
|
||||
}
|
||||
|
||||
return gmp_strval($remainder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @test
|
||||
*/
|
||||
public function it_divides_bug538()
|
||||
{
|
||||
$this->assertSame('-4.54545454545455', $this->getCalculator()->divide('-500', 110));
|
||||
}
|
||||
}
|
||||
197
pancake/system/vendor/moneyphp/money/src/Calculator/PhpCalculator.php
vendored
Executable file
197
pancake/system/vendor/moneyphp/money/src/Calculator/PhpCalculator.php
vendored
Executable file
@@ -0,0 +1,197 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Calculator;
|
||||
|
||||
use Money\Calculator;
|
||||
use Money\Money;
|
||||
use Money\Number;
|
||||
|
||||
/**
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class PhpCalculator implements Calculator
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function supported()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function compare($a, $b)
|
||||
{
|
||||
return ($a < $b) ? -1 : (($a > $b) ? 1 : 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function add($amount, $addend)
|
||||
{
|
||||
$result = $amount + $addend;
|
||||
|
||||
$this->assertInteger($result);
|
||||
|
||||
return (string) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function subtract($amount, $subtrahend)
|
||||
{
|
||||
$result = $amount - $subtrahend;
|
||||
|
||||
$this->assertInteger($result);
|
||||
|
||||
return (string) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function multiply($amount, $multiplier)
|
||||
{
|
||||
$result = $amount * $multiplier;
|
||||
|
||||
$this->assertIntegerBounds($result);
|
||||
|
||||
return (string) Number::fromNumber($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function divide($amount, $divisor)
|
||||
{
|
||||
$result = $amount / $divisor;
|
||||
|
||||
$this->assertIntegerBounds($result);
|
||||
|
||||
return (string) Number::fromNumber($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function ceil($number)
|
||||
{
|
||||
return $this->castInteger(ceil($number));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function floor($number)
|
||||
{
|
||||
return $this->castInteger(floor($number));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function absolute($number)
|
||||
{
|
||||
$result = ltrim($number, '-');
|
||||
|
||||
$this->assertIntegerBounds($result);
|
||||
|
||||
return (string) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function round($number, $roundingMode)
|
||||
{
|
||||
if (Money::ROUND_HALF_POSITIVE_INFINITY === $roundingMode) {
|
||||
$number = Number::fromNumber($number);
|
||||
|
||||
if ($number->isHalf()) {
|
||||
return $this->castInteger(ceil((string) $number));
|
||||
}
|
||||
|
||||
return $this->castInteger(round((string) $number, 0, Money::ROUND_HALF_UP));
|
||||
}
|
||||
|
||||
if (Money::ROUND_HALF_NEGATIVE_INFINITY === $roundingMode) {
|
||||
$number = Number::fromNumber($number);
|
||||
|
||||
if ($number->isHalf()) {
|
||||
return $this->castInteger(floor((string) $number));
|
||||
}
|
||||
|
||||
return $this->castInteger(round((string) $number, 0, Money::ROUND_HALF_DOWN));
|
||||
}
|
||||
|
||||
return $this->castInteger(round($number, 0, $roundingMode));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function share($amount, $ratio, $total)
|
||||
{
|
||||
return $this->castInteger(floor($amount * $ratio / $total));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function mod($amount, $divisor)
|
||||
{
|
||||
$result = $amount % $divisor;
|
||||
|
||||
$this->assertIntegerBounds($result);
|
||||
|
||||
return (string) $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that an integer value didn't become something else
|
||||
* (after some arithmetic operation).
|
||||
*
|
||||
* @param int $amount
|
||||
*
|
||||
* @throws \OverflowException If integer overflow occured
|
||||
* @throws \UnderflowException If integer underflow occured
|
||||
*/
|
||||
private function assertIntegerBounds($amount)
|
||||
{
|
||||
if ($amount > PHP_INT_MAX) {
|
||||
throw new \OverflowException('You overflowed the maximum allowed integer (PHP_INT_MAX)');
|
||||
} elseif ($amount < ~PHP_INT_MAX) {
|
||||
throw new \UnderflowException('You underflowed the minimum allowed integer (PHP_INT_MAX)');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Casts an amount to integer ensuring that an overflow/underflow did not occur.
|
||||
*
|
||||
* @param int $amount
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function castInteger($amount)
|
||||
{
|
||||
$this->assertIntegerBounds($amount);
|
||||
|
||||
return (string) intval($amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that integer remains integer after arithmetic operations.
|
||||
*
|
||||
* @param int $amount
|
||||
*/
|
||||
private function assertInteger($amount)
|
||||
{
|
||||
if (filter_var($amount, FILTER_VALIDATE_INT) === false) {
|
||||
throw new \UnexpectedValueException('The result of arithmetic operation is not an integer');
|
||||
}
|
||||
}
|
||||
}
|
||||
48
pancake/system/vendor/moneyphp/money/src/Converter.php
vendored
Executable file
48
pancake/system/vendor/moneyphp/money/src/Converter.php
vendored
Executable file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
/**
|
||||
* Provides a way to convert Money to Money in another Currency using an exchange rate.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class Converter
|
||||
{
|
||||
/**
|
||||
* @var Currencies
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
/**
|
||||
* @var Exchange
|
||||
*/
|
||||
private $exchange;
|
||||
|
||||
public function __construct(Currencies $currencies, Exchange $exchange)
|
||||
{
|
||||
$this->currencies = $currencies;
|
||||
$this->exchange = $exchange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $roundingMode
|
||||
*
|
||||
* @return Money
|
||||
*/
|
||||
public function convert(Money $money, Currency $counterCurrency, $roundingMode = Money::ROUND_HALF_UP)
|
||||
{
|
||||
$baseCurrency = $money->getCurrency();
|
||||
$ratio = $this->exchange->quote($baseCurrency, $counterCurrency)->getConversionRatio();
|
||||
|
||||
$baseCurrencySubunit = $this->currencies->subunitFor($baseCurrency);
|
||||
$counterCurrencySubunit = $this->currencies->subunitFor($counterCurrency);
|
||||
$subunitDifference = $baseCurrencySubunit - $counterCurrencySubunit;
|
||||
|
||||
$ratio = (string) Number::fromFloat($ratio)->base10($subunitDifference);
|
||||
|
||||
$counterValue = $money->multiply($ratio, $roundingMode);
|
||||
|
||||
return new Money($counterValue->getAmount(), $counterCurrency);
|
||||
}
|
||||
}
|
||||
29
pancake/system/vendor/moneyphp/money/src/Currencies.php
vendored
Executable file
29
pancake/system/vendor/moneyphp/money/src/Currencies.php
vendored
Executable file
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
use Money\Exception\UnknownCurrencyException;
|
||||
|
||||
/**
|
||||
* Implement this to provide a list of currencies.
|
||||
*
|
||||
* @author Mathias Verraes
|
||||
*/
|
||||
interface Currencies extends \IteratorAggregate
|
||||
{
|
||||
/**
|
||||
* Checks whether a currency is available in the current context.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function contains(Currency $currency);
|
||||
|
||||
/**
|
||||
* Returns the subunit for a currency.
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @throws UnknownCurrencyException If currency is not available in the current context
|
||||
*/
|
||||
public function subunitFor(Currency $currency);
|
||||
}
|
||||
77
pancake/system/vendor/moneyphp/money/src/Currencies/AggregateCurrencies.php
vendored
Executable file
77
pancake/system/vendor/moneyphp/money/src/Currencies/AggregateCurrencies.php
vendored
Executable file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Currencies;
|
||||
|
||||
use Money\Currencies;
|
||||
use Money\Currency;
|
||||
use Money\Exception\UnknownCurrencyException;
|
||||
|
||||
/**
|
||||
* Aggregates several currency repositories.
|
||||
*
|
||||
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
|
||||
*/
|
||||
final class AggregateCurrencies implements Currencies
|
||||
{
|
||||
/**
|
||||
* @var Currencies[]
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
/**
|
||||
* @param Currencies[] $currencies
|
||||
*/
|
||||
public function __construct(array $currencies)
|
||||
{
|
||||
foreach ($currencies as $c) {
|
||||
if (false === $c instanceof Currencies) {
|
||||
throw new \InvalidArgumentException('All currency repositories must implement '.Currencies::class);
|
||||
}
|
||||
}
|
||||
|
||||
$this->currencies = $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function contains(Currency $currency)
|
||||
{
|
||||
foreach ($this->currencies as $currencies) {
|
||||
if ($currencies->contains($currency)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function subunitFor(Currency $currency)
|
||||
{
|
||||
foreach ($this->currencies as $currencies) {
|
||||
if ($currencies->contains($currency)) {
|
||||
return $currencies->subunitFor($currency);
|
||||
}
|
||||
}
|
||||
|
||||
throw new UnknownCurrencyException('Cannot find currency '.$currency->getCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
$iterator = new \AppendIterator();
|
||||
|
||||
foreach ($this->currencies as $currencies) {
|
||||
$iterator->append($currencies->getIterator());
|
||||
}
|
||||
|
||||
return $iterator;
|
||||
}
|
||||
}
|
||||
46
pancake/system/vendor/moneyphp/money/src/Currencies/BitcoinCurrencies.php
vendored
Executable file
46
pancake/system/vendor/moneyphp/money/src/Currencies/BitcoinCurrencies.php
vendored
Executable file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Currencies;
|
||||
|
||||
use Money\Currencies;
|
||||
use Money\Currency;
|
||||
use Money\Exception\UnknownCurrencyException;
|
||||
|
||||
/**
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class BitcoinCurrencies implements Currencies
|
||||
{
|
||||
const CODE = 'XBT';
|
||||
|
||||
const SYMBOL = "\xC9\x83";
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function contains(Currency $currency)
|
||||
{
|
||||
return self::CODE === $currency->getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function subunitFor(Currency $currency)
|
||||
{
|
||||
if ($currency->getCode() !== self::CODE) {
|
||||
throw new UnknownCurrencyException($currency->getCode().' is not bitcoin and is not supported by this currency repository');
|
||||
}
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator([new Currency(self::CODE)]);
|
||||
}
|
||||
}
|
||||
95
pancake/system/vendor/moneyphp/money/src/Currencies/CachedCurrencies.php
vendored
Executable file
95
pancake/system/vendor/moneyphp/money/src/Currencies/CachedCurrencies.php
vendored
Executable file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Currencies;
|
||||
|
||||
use Cache\Taggable\TaggableItemInterface;
|
||||
use Money\Currencies;
|
||||
use Money\Currency;
|
||||
use Psr\Cache\CacheItemPoolInterface;
|
||||
|
||||
/**
|
||||
* Cache the result of currency checking.
|
||||
*
|
||||
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
|
||||
*/
|
||||
final class CachedCurrencies implements Currencies
|
||||
{
|
||||
/**
|
||||
* @var Currencies
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
/**
|
||||
* @var CacheItemPoolInterface
|
||||
*/
|
||||
private $pool;
|
||||
|
||||
public function __construct(Currencies $currencies, CacheItemPoolInterface $pool)
|
||||
{
|
||||
$this->currencies = $currencies;
|
||||
$this->pool = $pool;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function contains(Currency $currency)
|
||||
{
|
||||
$item = $this->pool->getItem('currency|availability|'.$currency->getCode());
|
||||
|
||||
if (false === $item->isHit()) {
|
||||
$item->set($this->currencies->contains($currency));
|
||||
|
||||
if ($item instanceof TaggableItemInterface) {
|
||||
$item->addTag('currency.availability');
|
||||
}
|
||||
|
||||
$this->pool->save($item);
|
||||
}
|
||||
|
||||
return $item->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function subunitFor(Currency $currency)
|
||||
{
|
||||
$item = $this->pool->getItem('currency|subunit|'.$currency->getCode());
|
||||
|
||||
if (false === $item->isHit()) {
|
||||
$item->set($this->currencies->subunitFor($currency));
|
||||
|
||||
if ($item instanceof TaggableItemInterface) {
|
||||
$item->addTag('currency.subunit');
|
||||
}
|
||||
|
||||
$this->pool->save($item);
|
||||
}
|
||||
|
||||
return $item->get();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new \CallbackFilterIterator(
|
||||
$this->currencies->getIterator(),
|
||||
function (Currency $currency) {
|
||||
$item = $this->pool->getItem('currency|availability|'.$currency->getCode());
|
||||
$item->set(true);
|
||||
|
||||
if ($item instanceof TaggableItemInterface) {
|
||||
$item->addTag('currency.availability');
|
||||
}
|
||||
|
||||
$this->pool->save($item);
|
||||
|
||||
return true;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
73
pancake/system/vendor/moneyphp/money/src/Currencies/CurrencyList.php
vendored
Executable file
73
pancake/system/vendor/moneyphp/money/src/Currencies/CurrencyList.php
vendored
Executable file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Currencies;
|
||||
|
||||
use Money\Currencies;
|
||||
use Money\Currency;
|
||||
use Money\Exception\UnknownCurrencyException;
|
||||
|
||||
/**
|
||||
* A list of custom currencies.
|
||||
*
|
||||
* @author George Mponos <gmponos@gmail.com>
|
||||
*/
|
||||
final class CurrencyList implements Currencies
|
||||
{
|
||||
/**
|
||||
* Map of currencies indexed by code.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
public function __construct(array $currencies)
|
||||
{
|
||||
foreach ($currencies as $currencyCode => $subunit) {
|
||||
if (empty($currencyCode) || !is_string($currencyCode)) {
|
||||
throw new \InvalidArgumentException(sprintf('Currency code must be a string and not empty. "%s" given', $currencyCode));
|
||||
}
|
||||
|
||||
if (!is_int($subunit) || $subunit < 0) {
|
||||
throw new \InvalidArgumentException(sprintf('Currency %s does not have a valid minor unit. Must be a positive integer.', $currencyCode));
|
||||
}
|
||||
}
|
||||
|
||||
$this->currencies = $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function contains(Currency $currency)
|
||||
{
|
||||
return isset($this->currencies[$currency->getCode()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function subunitFor(Currency $currency)
|
||||
{
|
||||
if (!$this->contains($currency)) {
|
||||
throw new UnknownCurrencyException('Cannot find currency '.$currency->getCode());
|
||||
}
|
||||
|
||||
return $this->currencies[$currency->getCode()];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator(
|
||||
array_map(
|
||||
function ($code) {
|
||||
return new Currency($code);
|
||||
},
|
||||
array_keys($this->currencies)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
102
pancake/system/vendor/moneyphp/money/src/Currencies/ISOCurrencies.php
vendored
Executable file
102
pancake/system/vendor/moneyphp/money/src/Currencies/ISOCurrencies.php
vendored
Executable file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Currencies;
|
||||
|
||||
use Money\Currencies;
|
||||
use Money\Currency;
|
||||
use Money\Exception\UnknownCurrencyException;
|
||||
|
||||
/**
|
||||
* List of supported ISO 4217 currency codes and names.
|
||||
*
|
||||
* @author Mathias Verraes
|
||||
*/
|
||||
final class ISOCurrencies implements Currencies
|
||||
{
|
||||
/**
|
||||
* Map of known currencies indexed by code.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private static $currencies;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function contains(Currency $currency)
|
||||
{
|
||||
return isset($this->getCurrencies()[$currency->getCode()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function subunitFor(Currency $currency)
|
||||
{
|
||||
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.
|
||||
*
|
||||
* @return int
|
||||
*
|
||||
* @throws UnknownCurrencyException If currency is not available in the current context
|
||||
*/
|
||||
public function numericCodeFor(Currency $currency)
|
||||
{
|
||||
if (!$this->contains($currency)) {
|
||||
throw new UnknownCurrencyException('Cannot find ISO currency '.$currency->getCode());
|
||||
}
|
||||
|
||||
return $this->getCurrencies()[$currency->getCode()]['numericCode'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Traversable
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator(
|
||||
array_map(
|
||||
function ($code) {
|
||||
return new Currency($code);
|
||||
},
|
||||
array_keys($this->getCurrencies())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a map of known currencies indexed by code.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
private function getCurrencies()
|
||||
{
|
||||
if (null === self::$currencies) {
|
||||
self::$currencies = $this->loadCurrencies();
|
||||
}
|
||||
|
||||
return self::$currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function loadCurrencies()
|
||||
{
|
||||
$file = __DIR__.'/../../resources/currency.php';
|
||||
|
||||
if (file_exists($file)) {
|
||||
return require $file;
|
||||
}
|
||||
|
||||
throw new \RuntimeException('Failed to load currency ISO codes.');
|
||||
}
|
||||
}
|
||||
87
pancake/system/vendor/moneyphp/money/src/Currency.php
vendored
Executable file
87
pancake/system/vendor/moneyphp/money/src/Currency.php
vendored
Executable file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
/**
|
||||
* Currency Value Object.
|
||||
*
|
||||
* Holds Currency specific data.
|
||||
*
|
||||
* @author Mathias Verraes
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
final class Currency implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* Currency code.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $code;
|
||||
|
||||
/**
|
||||
* @param string $code
|
||||
*/
|
||||
public function __construct($code)
|
||||
{
|
||||
if (!is_string($code)) {
|
||||
throw new \InvalidArgumentException('Currency code should be string');
|
||||
}
|
||||
|
||||
if ($code === '') {
|
||||
throw new \InvalidArgumentException('Currency code should not be empty string');
|
||||
}
|
||||
|
||||
$this->code = $code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currency code.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCode()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this currency is the same as an other.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function equals(Currency $other)
|
||||
{
|
||||
return $this->code === $other->code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether this currency is available in the passed context.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isAvailableWithin(Currencies $currencies)
|
||||
{
|
||||
return $currencies->contains($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
}
|
||||
130
pancake/system/vendor/moneyphp/money/src/CurrencyPair.php
vendored
Executable file
130
pancake/system/vendor/moneyphp/money/src/CurrencyPair.php
vendored
Executable file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
/**
|
||||
* Currency Pair holding a base, a counter currency and a conversion ratio.
|
||||
*
|
||||
* @author Mathias Verraes
|
||||
*
|
||||
* @see http://en.wikipedia.org/wiki/Currency_pair
|
||||
*/
|
||||
final class CurrencyPair implements \JsonSerializable
|
||||
{
|
||||
/**
|
||||
* Currency to convert from.
|
||||
*
|
||||
* @var Currency
|
||||
*/
|
||||
private $baseCurrency;
|
||||
|
||||
/**
|
||||
* Currency to convert to.
|
||||
*
|
||||
* @var Currency
|
||||
*/
|
||||
private $counterCurrency;
|
||||
|
||||
/**
|
||||
* @var float
|
||||
*/
|
||||
private $conversionRatio;
|
||||
|
||||
/**
|
||||
* @param float $conversionRatio
|
||||
*
|
||||
* @throws \InvalidArgumentException If conversion ratio is not numeric
|
||||
*/
|
||||
public function __construct(Currency $baseCurrency, Currency $counterCurrency, $conversionRatio)
|
||||
{
|
||||
if (!is_numeric($conversionRatio)) {
|
||||
throw new \InvalidArgumentException('Conversion ratio must be numeric');
|
||||
}
|
||||
|
||||
$this->counterCurrency = $counterCurrency;
|
||||
$this->baseCurrency = $baseCurrency;
|
||||
$this->conversionRatio = (float) $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"
|
||||
*
|
||||
* @return CurrencyPair
|
||||
*
|
||||
* @throws \InvalidArgumentException Format of $iso is invalid
|
||||
*/
|
||||
public static function createFromIso($iso)
|
||||
{
|
||||
$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));
|
||||
}
|
||||
|
||||
return new self(new Currency($matches[1]), new Currency($matches[2]), $matches[3]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the counter currency.
|
||||
*
|
||||
* @return Currency
|
||||
*/
|
||||
public function getCounterCurrency()
|
||||
{
|
||||
return $this->counterCurrency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the base currency.
|
||||
*
|
||||
* @return Currency
|
||||
*/
|
||||
public function getBaseCurrency()
|
||||
{
|
||||
return $this->baseCurrency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the conversion ratio.
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function getConversionRatio()
|
||||
{
|
||||
return $this->conversionRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if an other CurrencyPair has the same parameters as this.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function equals(CurrencyPair $other)
|
||||
{
|
||||
return
|
||||
$this->baseCurrency->equals($other->baseCurrency)
|
||||
&& $this->counterCurrency->equals($other->counterCurrency)
|
||||
&& $this->conversionRatio === $other->conversionRatio
|
||||
;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return [
|
||||
'baseCurrency' => $this->baseCurrency,
|
||||
'counterCurrency' => $this->counterCurrency,
|
||||
'ratio' => $this->conversionRatio,
|
||||
];
|
||||
}
|
||||
}
|
||||
12
pancake/system/vendor/moneyphp/money/src/Exception.php
vendored
Executable file
12
pancake/system/vendor/moneyphp/money/src/Exception.php
vendored
Executable file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
/**
|
||||
* Common interface for all exceptions thrown by this library.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
interface Exception
|
||||
{
|
||||
}
|
||||
14
pancake/system/vendor/moneyphp/money/src/Exception/FormatterException.php
vendored
Executable file
14
pancake/system/vendor/moneyphp/money/src/Exception/FormatterException.php
vendored
Executable file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Exception;
|
||||
|
||||
use Money\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when a Money object cannot be formatted into a string.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class FormatterException extends \RuntimeException implements Exception
|
||||
{
|
||||
}
|
||||
14
pancake/system/vendor/moneyphp/money/src/Exception/ParserException.php
vendored
Executable file
14
pancake/system/vendor/moneyphp/money/src/Exception/ParserException.php
vendored
Executable file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Exception;
|
||||
|
||||
use Money\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when a string cannot be parsed to a Money object.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class ParserException extends \RuntimeException implements Exception
|
||||
{
|
||||
}
|
||||
14
pancake/system/vendor/moneyphp/money/src/Exception/UnknownCurrencyException.php
vendored
Executable file
14
pancake/system/vendor/moneyphp/money/src/Exception/UnknownCurrencyException.php
vendored
Executable file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Exception;
|
||||
|
||||
use Money\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when trying to get ISO currency that does not exists.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class UnknownCurrencyException extends \DomainException implements Exception
|
||||
{
|
||||
}
|
||||
30
pancake/system/vendor/moneyphp/money/src/Exception/UnresolvableCurrencyPairException.php
vendored
Executable file
30
pancake/system/vendor/moneyphp/money/src/Exception/UnresolvableCurrencyPairException.php
vendored
Executable file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Exception;
|
||||
|
||||
use Money\Currency;
|
||||
use Money\Exception;
|
||||
|
||||
/**
|
||||
* Thrown when there is no currency pair (rate) available for the given currencies.
|
||||
*
|
||||
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
|
||||
*/
|
||||
final class UnresolvableCurrencyPairException extends \InvalidArgumentException implements Exception
|
||||
{
|
||||
/**
|
||||
* Creates an exception from Currency objects.
|
||||
*
|
||||
* @return UnresolvableCurrencyPairException
|
||||
*/
|
||||
public static function createFromCurrencies(Currency $baseCurrency, Currency $counterCurrency)
|
||||
{
|
||||
$message = sprintf(
|
||||
'Cannot resolve a currency pair for currencies: %s/%s',
|
||||
$baseCurrency->getCode(),
|
||||
$counterCurrency->getCode()
|
||||
);
|
||||
|
||||
return new self($message);
|
||||
}
|
||||
}
|
||||
22
pancake/system/vendor/moneyphp/money/src/Exchange.php
vendored
Executable file
22
pancake/system/vendor/moneyphp/money/src/Exchange.php
vendored
Executable file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
use Money\Exception\UnresolvableCurrencyPairException;
|
||||
|
||||
/**
|
||||
* Provides a way to get exchange rate from a third-party source and return a currency pair.
|
||||
*
|
||||
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
|
||||
*/
|
||||
interface Exchange
|
||||
{
|
||||
/**
|
||||
* Returns a currency pair for the passed currencies with the rate coming from a third-party source.
|
||||
*
|
||||
* @return CurrencyPair
|
||||
*
|
||||
* @throws UnresolvableCurrencyPairException When there is no currency pair (rate) available for the given currencies
|
||||
*/
|
||||
public function quote(Currency $baseCurrency, Currency $counterCurrency);
|
||||
}
|
||||
47
pancake/system/vendor/moneyphp/money/src/Exchange/ExchangerExchange.php
vendored
Executable file
47
pancake/system/vendor/moneyphp/money/src/Exchange/ExchangerExchange.php
vendored
Executable file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Provides a way to get exchange rate from a third-party source and return a currency pair.
|
||||
*
|
||||
* @author Maksim (Ellrion) Platonov <ellrion11@gmail.com>
|
||||
*/
|
||||
final class ExchangerExchange implements Exchange
|
||||
{
|
||||
/**
|
||||
* @var ExchangeRateProvider
|
||||
*/
|
||||
private $exchanger;
|
||||
|
||||
public function __construct(ExchangeRateProvider $exchanger)
|
||||
{
|
||||
$this->exchanger = $exchanger;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function quote(Currency $baseCurrency, Currency $counterCurrency)
|
||||
{
|
||||
try {
|
||||
$query = new ExchangeRateQuery(
|
||||
new ExchangerCurrencyPair($baseCurrency->getCode(), $counterCurrency->getCode())
|
||||
);
|
||||
$rate = $this->exchanger->getExchangeRate($query);
|
||||
} catch (ExchangerException $e) {
|
||||
throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency);
|
||||
}
|
||||
|
||||
return new CurrencyPair($baseCurrency, $counterCurrency, $rate->getValue());
|
||||
}
|
||||
}
|
||||
42
pancake/system/vendor/moneyphp/money/src/Exchange/FixedExchange.php
vendored
Executable file
42
pancake/system/vendor/moneyphp/money/src/Exchange/FixedExchange.php
vendored
Executable file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
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).
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class FixedExchange implements Exchange
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $list;
|
||||
|
||||
public function __construct(array $list)
|
||||
{
|
||||
$this->list = $list;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function quote(Currency $baseCurrency, Currency $counterCurrency)
|
||||
{
|
||||
if (isset($this->list[$baseCurrency->getCode()][$counterCurrency->getCode()])) {
|
||||
return new CurrencyPair(
|
||||
$baseCurrency,
|
||||
$counterCurrency,
|
||||
$this->list[$baseCurrency->getCode()][$counterCurrency->getCode()]
|
||||
);
|
||||
}
|
||||
|
||||
throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency);
|
||||
}
|
||||
}
|
||||
195
pancake/system/vendor/moneyphp/money/src/Exchange/IndirectExchange.php
vendored
Executable file
195
pancake/system/vendor/moneyphp/money/src/Exchange/IndirectExchange.php
vendored
Executable file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Exchange;
|
||||
|
||||
use Money\Calculator;
|
||||
use Money\Calculator\BcMathCalculator;
|
||||
use Money\Calculator\GmpCalculator;
|
||||
use Money\Calculator\PhpCalculator;
|
||||
use Money\Currencies;
|
||||
use Money\Currency;
|
||||
use Money\CurrencyPair;
|
||||
use Money\Exception\UnresolvableCurrencyPairException;
|
||||
use Money\Exchange;
|
||||
|
||||
/**
|
||||
* Provides a way to get an exchange rate through a minimal set of intermediate conversions.
|
||||
*
|
||||
* @author Michael Cordingley <Michael.Cordingley@gmail.com>
|
||||
*/
|
||||
final class IndirectExchange implements Exchange
|
||||
{
|
||||
/**
|
||||
* @var Calculator
|
||||
*/
|
||||
private static $calculator;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $calculators = [
|
||||
BcMathCalculator::class,
|
||||
GmpCalculator::class,
|
||||
PhpCalculator::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* @var Currencies
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
/**
|
||||
* @var Exchange
|
||||
*/
|
||||
private $exchange;
|
||||
|
||||
public function __construct(Exchange $exchange, Currencies $currencies)
|
||||
{
|
||||
$this->exchange = $exchange;
|
||||
$this->currencies = $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $calculator
|
||||
*/
|
||||
public static function registerCalculator($calculator)
|
||||
{
|
||||
if (is_a($calculator, Calculator::class, true) === false) {
|
||||
throw new \InvalidArgumentException('Calculator must implement '.Calculator::class);
|
||||
}
|
||||
|
||||
array_unshift(self::$calculators, $calculator);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function quote(Currency $baseCurrency, Currency $counterCurrency)
|
||||
{
|
||||
try {
|
||||
return $this->exchange->quote($baseCurrency, $counterCurrency);
|
||||
} catch (UnresolvableCurrencyPairException $exception) {
|
||||
$rate = array_reduce($this->getConversions($baseCurrency, $counterCurrency), function ($carry, CurrencyPair $pair) {
|
||||
return static::getCalculator()->multiply($carry, $pair->getConversionRatio());
|
||||
}, '1.0');
|
||||
|
||||
return new CurrencyPair($baseCurrency, $counterCurrency, $rate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CurrencyPair[]
|
||||
*
|
||||
* @throws UnresolvableCurrencyPairException
|
||||
*/
|
||||
private function getConversions(Currency $baseCurrency, Currency $counterCurrency)
|
||||
{
|
||||
$startNode = $this->initializeNode($baseCurrency);
|
||||
$startNode->discovered = true;
|
||||
|
||||
$nodes = [$baseCurrency->getCode() => $startNode];
|
||||
|
||||
$frontier = new \SplQueue();
|
||||
$frontier->enqueue($startNode);
|
||||
|
||||
while ($frontier->count()) {
|
||||
/** @var \stdClass $currentNode */
|
||||
$currentNode = $frontier->dequeue();
|
||||
|
||||
/** @var Currency $currentCurrency */
|
||||
$currentCurrency = $currentNode->currency;
|
||||
|
||||
if ($currentCurrency->equals($counterCurrency)) {
|
||||
return $this->reconstructConversionChain($nodes, $currentNode);
|
||||
}
|
||||
|
||||
/** @var Currency $candidateCurrency */
|
||||
foreach ($this->currencies as $candidateCurrency) {
|
||||
if (!isset($nodes[$candidateCurrency->getCode()])) {
|
||||
$nodes[$candidateCurrency->getCode()] = $this->initializeNode($candidateCurrency);
|
||||
}
|
||||
|
||||
/** @var \stdClass $node */
|
||||
$node = $nodes[$candidateCurrency->getCode()];
|
||||
|
||||
if (!$node->discovered) {
|
||||
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 $exception) {
|
||||
// Not a neighbor. Move on.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \stdClass
|
||||
*/
|
||||
private function initializeNode(Currency $currency)
|
||||
{
|
||||
$node = new \stdClass();
|
||||
|
||||
$node->currency = $currency;
|
||||
$node->discovered = false;
|
||||
$node->parent = null;
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CurrencyPair[]
|
||||
*/
|
||||
private function reconstructConversionChain(array $currencies, \stdClass $goalNode)
|
||||
{
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Calculator
|
||||
*/
|
||||
private function getCalculator()
|
||||
{
|
||||
if (null === self::$calculator) {
|
||||
self::$calculator = self::initializeCalculator();
|
||||
}
|
||||
|
||||
return self::$calculator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Calculator
|
||||
*
|
||||
* @throws \RuntimeException If cannot find calculator for money calculations
|
||||
*/
|
||||
private static function initializeCalculator()
|
||||
{
|
||||
$calculators = self::$calculators;
|
||||
|
||||
foreach ($calculators as $calculator) {
|
||||
/** @var Calculator $calculator */
|
||||
if ($calculator::supported()) {
|
||||
return new $calculator();
|
||||
}
|
||||
}
|
||||
|
||||
throw new \RuntimeException('Cannot find calculator for money calculations');
|
||||
}
|
||||
}
|
||||
46
pancake/system/vendor/moneyphp/money/src/Exchange/ReversedCurrenciesExchange.php
vendored
Executable file
46
pancake/system/vendor/moneyphp/money/src/Exchange/ReversedCurrenciesExchange.php
vendored
Executable file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Exchange;
|
||||
|
||||
use Money\Currency;
|
||||
use Money\CurrencyPair;
|
||||
use Money\Exception\UnresolvableCurrencyPairException;
|
||||
use Money\Exchange;
|
||||
|
||||
/**
|
||||
* Tries the reverse of the currency pair if one is not available.
|
||||
*
|
||||
* Note: adding nested ReversedCurrenciesExchange could cause a huge performance hit.
|
||||
*
|
||||
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
|
||||
*/
|
||||
final class ReversedCurrenciesExchange implements Exchange
|
||||
{
|
||||
/**
|
||||
* @var Exchange
|
||||
*/
|
||||
private $exchange;
|
||||
|
||||
public function __construct(Exchange $exchange)
|
||||
{
|
||||
$this->exchange = $exchange;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function quote(Currency $baseCurrency, Currency $counterCurrency)
|
||||
{
|
||||
try {
|
||||
return $this->exchange->quote($baseCurrency, $counterCurrency);
|
||||
} catch (UnresolvableCurrencyPairException $exception) {
|
||||
try {
|
||||
$currencyPair = $this->exchange->quote($counterCurrency, $baseCurrency);
|
||||
|
||||
return new CurrencyPair($baseCurrency, $counterCurrency, 1 / $currencyPair->getConversionRatio());
|
||||
} catch (UnresolvableCurrencyPairException $inversedException) {
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
42
pancake/system/vendor/moneyphp/money/src/Exchange/SwapExchange.php
vendored
Executable file
42
pancake/system/vendor/moneyphp/money/src/Exchange/SwapExchange.php
vendored
Executable file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Provides a way to get exchange rate from a third-party source and return a currency pair.
|
||||
*
|
||||
* @author Márk Sági-Kazár <mark.sagikazar@gmail.com>
|
||||
*/
|
||||
final class SwapExchange implements Exchange
|
||||
{
|
||||
/**
|
||||
* @var Swap
|
||||
*/
|
||||
private $swap;
|
||||
|
||||
public function __construct(Swap $swap)
|
||||
{
|
||||
$this->swap = $swap;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function quote(Currency $baseCurrency, Currency $counterCurrency)
|
||||
{
|
||||
try {
|
||||
$rate = $this->swap->latest($baseCurrency->getCode().'/'.$counterCurrency->getCode());
|
||||
} catch (ExchangerException $e) {
|
||||
throw UnresolvableCurrencyPairException::createFromCurrencies($baseCurrency, $counterCurrency);
|
||||
}
|
||||
|
||||
return new CurrencyPair($baseCurrency, $counterCurrency, $rate->getValue());
|
||||
}
|
||||
}
|
||||
56
pancake/system/vendor/moneyphp/money/src/Formatter/AggregateMoneyFormatter.php
vendored
Executable file
56
pancake/system/vendor/moneyphp/money/src/Formatter/AggregateMoneyFormatter.php
vendored
Executable file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Formatter;
|
||||
|
||||
use Money\Exception\FormatterException;
|
||||
use Money\Money;
|
||||
use Money\MoneyFormatter;
|
||||
|
||||
/**
|
||||
* Formats a Money object using other Money formatters.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class AggregateMoneyFormatter implements MoneyFormatter
|
||||
{
|
||||
/**
|
||||
* @var MoneyFormatter[]
|
||||
*/
|
||||
private $formatters = [];
|
||||
|
||||
/**
|
||||
* @param MoneyFormatter[] $formatters
|
||||
*/
|
||||
public function __construct(array $formatters)
|
||||
{
|
||||
if (empty($formatters)) {
|
||||
throw new \InvalidArgumentException(sprintf('Initialize an empty %s is not possible', self::class));
|
||||
}
|
||||
|
||||
foreach ($formatters as $currencyCode => $formatter) {
|
||||
if (false === $formatter instanceof MoneyFormatter) {
|
||||
throw new \InvalidArgumentException('All formatters must implement '.MoneyFormatter::class);
|
||||
}
|
||||
|
||||
$this->formatters[$currencyCode] = $formatter;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function format(Money $money)
|
||||
{
|
||||
$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);
|
||||
}
|
||||
}
|
||||
87
pancake/system/vendor/moneyphp/money/src/Formatter/BitcoinMoneyFormatter.php
vendored
Executable file
87
pancake/system/vendor/moneyphp/money/src/Formatter/BitcoinMoneyFormatter.php
vendored
Executable file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Formatter;
|
||||
|
||||
use Money\Currencies;
|
||||
use Money\Currencies\BitcoinCurrencies;
|
||||
use Money\Exception\FormatterException;
|
||||
use Money\Money;
|
||||
use Money\MoneyFormatter;
|
||||
use Money\Number;
|
||||
|
||||
/**
|
||||
* Formats Money to Bitcoin currency.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class BitcoinMoneyFormatter implements MoneyFormatter
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $fractionDigits;
|
||||
|
||||
/**
|
||||
* @var Currencies
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
/**
|
||||
* @param int $fractionDigits
|
||||
*/
|
||||
public function __construct($fractionDigits, Currencies $currencies)
|
||||
{
|
||||
$this->fractionDigits = $fractionDigits;
|
||||
$this->currencies = $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function format(Money $money)
|
||||
{
|
||||
if (BitcoinCurrencies::CODE !== $money->getCurrency()->getCode()) {
|
||||
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, strpos($formatted, '.'));
|
||||
} elseif ($this->fractionDigits > $subunit) {
|
||||
$formatted .= str_pad('', $this->fractionDigits - $subunit, '0');
|
||||
} elseif ($this->fractionDigits < $subunit) {
|
||||
$lastDigit = strpos($formatted, '.') + $this->fractionDigits + 1;
|
||||
$formatted = substr($formatted, 0, $lastDigit);
|
||||
}
|
||||
|
||||
$formatted = BitcoinCurrencies::SYMBOL.$formatted;
|
||||
|
||||
if (true === $negative) {
|
||||
$formatted = '-'.$formatted;
|
||||
}
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
}
|
||||
59
pancake/system/vendor/moneyphp/money/src/Formatter/DecimalMoneyFormatter.php
vendored
Executable file
59
pancake/system/vendor/moneyphp/money/src/Formatter/DecimalMoneyFormatter.php
vendored
Executable file
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Formatter;
|
||||
|
||||
use Money\Currencies;
|
||||
use Money\Money;
|
||||
use Money\MoneyFormatter;
|
||||
|
||||
/**
|
||||
* Formats a Money object as a decimal string.
|
||||
*
|
||||
* @author Teoh Han Hui <teohhanhui@gmail.com>
|
||||
*/
|
||||
final class DecimalMoneyFormatter implements MoneyFormatter
|
||||
{
|
||||
/**
|
||||
* @var Currencies
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
public function __construct(Currencies $currencies)
|
||||
{
|
||||
$this->currencies = $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function format(Money $money)
|
||||
{
|
||||
$valueBase = $money->getAmount();
|
||||
$negative = false;
|
||||
|
||||
if ($valueBase[0] === '-') {
|
||||
$negative = true;
|
||||
$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 === true) {
|
||||
$formatted = '-'.$formatted;
|
||||
}
|
||||
|
||||
return $formatted;
|
||||
}
|
||||
}
|
||||
65
pancake/system/vendor/moneyphp/money/src/Formatter/IntlLocalizedDecimalFormatter.php
vendored
Executable file
65
pancake/system/vendor/moneyphp/money/src/Formatter/IntlLocalizedDecimalFormatter.php
vendored
Executable file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Formatter;
|
||||
|
||||
use Money\Currencies;
|
||||
use Money\Money;
|
||||
use Money\MoneyFormatter;
|
||||
|
||||
/**
|
||||
* Formats a Money object using intl extension.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class IntlLocalizedDecimalFormatter implements MoneyFormatter
|
||||
{
|
||||
/**
|
||||
* @var \NumberFormatter
|
||||
*/
|
||||
private $formatter;
|
||||
|
||||
/**
|
||||
* @var Currencies
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
public function __construct(\NumberFormatter $formatter, Currencies $currencies)
|
||||
{
|
||||
$this->formatter = $formatter;
|
||||
$this->currencies = $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function format(Money $money)
|
||||
{
|
||||
$valueBase = $money->getAmount();
|
||||
$negative = false;
|
||||
|
||||
if ($valueBase[0] === '-') {
|
||||
$negative = true;
|
||||
$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 === true) {
|
||||
$formatted = '-'.$formatted;
|
||||
}
|
||||
|
||||
return $this->formatter->format($formatted);
|
||||
}
|
||||
}
|
||||
65
pancake/system/vendor/moneyphp/money/src/Formatter/IntlMoneyFormatter.php
vendored
Executable file
65
pancake/system/vendor/moneyphp/money/src/Formatter/IntlMoneyFormatter.php
vendored
Executable file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Formatter;
|
||||
|
||||
use Money\Currencies;
|
||||
use Money\Money;
|
||||
use Money\MoneyFormatter;
|
||||
|
||||
/**
|
||||
* Formats a Money object using intl extension.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class IntlMoneyFormatter implements MoneyFormatter
|
||||
{
|
||||
/**
|
||||
* @var \NumberFormatter
|
||||
*/
|
||||
private $formatter;
|
||||
|
||||
/**
|
||||
* @var Currencies
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
public function __construct(\NumberFormatter $formatter, Currencies $currencies)
|
||||
{
|
||||
$this->formatter = $formatter;
|
||||
$this->currencies = $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function format(Money $money)
|
||||
{
|
||||
$valueBase = $money->getAmount();
|
||||
$negative = false;
|
||||
|
||||
if ($valueBase[0] === '-') {
|
||||
$negative = true;
|
||||
$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 === true) {
|
||||
$formatted = '-'.$formatted;
|
||||
}
|
||||
|
||||
return $this->formatter->formatCurrency($formatted, $money->getCurrency()->getCode());
|
||||
}
|
||||
}
|
||||
613
pancake/system/vendor/moneyphp/money/src/Money.php
vendored
Executable file
613
pancake/system/vendor/moneyphp/money/src/Money.php
vendored
Executable file
@@ -0,0 +1,613 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
use Money\Calculator\BcMathCalculator;
|
||||
use Money\Calculator\GmpCalculator;
|
||||
use Money\Calculator\PhpCalculator;
|
||||
|
||||
/**
|
||||
* Money Value Object.
|
||||
*
|
||||
* @author Mathias Verraes
|
||||
*
|
||||
* @psalm-immutable
|
||||
*/
|
||||
final class Money implements \JsonSerializable
|
||||
{
|
||||
use MoneyFactory;
|
||||
|
||||
const ROUND_HALF_UP = PHP_ROUND_HALF_UP;
|
||||
|
||||
const ROUND_HALF_DOWN = PHP_ROUND_HALF_DOWN;
|
||||
|
||||
const ROUND_HALF_EVEN = PHP_ROUND_HALF_EVEN;
|
||||
|
||||
const ROUND_HALF_ODD = PHP_ROUND_HALF_ODD;
|
||||
|
||||
const ROUND_UP = 5;
|
||||
|
||||
const ROUND_DOWN = 6;
|
||||
|
||||
const ROUND_HALF_POSITIVE_INFINITY = 7;
|
||||
|
||||
const ROUND_HALF_NEGATIVE_INFINITY = 8;
|
||||
|
||||
/**
|
||||
* Internal value.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $amount;
|
||||
|
||||
/**
|
||||
* @var Currency
|
||||
*/
|
||||
private $currency;
|
||||
|
||||
/**
|
||||
* @var Calculator
|
||||
*/
|
||||
private static $calculator;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $calculators = [
|
||||
BcMathCalculator::class,
|
||||
GmpCalculator::class,
|
||||
PhpCalculator::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* @param int|string $amount Amount, expressed in the smallest units of $currency (eg cents)
|
||||
*
|
||||
* @throws \InvalidArgumentException If amount is not integer
|
||||
*/
|
||||
public function __construct($amount, Currency $currency)
|
||||
{
|
||||
if (filter_var($amount, FILTER_VALIDATE_INT) === false) {
|
||||
$numberFromString = Number::fromString($amount);
|
||||
if (!$numberFromString->isInteger()) {
|
||||
throw new \InvalidArgumentException('Amount must be an integer(ish) value');
|
||||
}
|
||||
|
||||
$amount = $numberFromString->getIntegerPart();
|
||||
}
|
||||
|
||||
$this->amount = (string) $amount;
|
||||
$this->currency = $currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Money instance based on the current one using the Currency.
|
||||
*
|
||||
* @param int|string $amount
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @throws \InvalidArgumentException If amount is not integer
|
||||
*/
|
||||
private function newInstance($amount)
|
||||
{
|
||||
return new self($amount, $this->currency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a Money has the same Currency as this.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isSameCurrency(Money $other)
|
||||
{
|
||||
return $this->currency->equals($other->currency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a Money has the same currency as this.
|
||||
*
|
||||
* @throws \InvalidArgumentException If $other has a different currency
|
||||
*/
|
||||
private function assertSameCurrency(Money $other)
|
||||
{
|
||||
if (!$this->isSameCurrency($other)) {
|
||||
throw new \InvalidArgumentException('Currencies must be identical');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the value represented by this object equals to the other.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function equals(Money $other)
|
||||
{
|
||||
return $this->isSameCurrency($other) && $this->amount === $other->amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function compare(Money $other)
|
||||
{
|
||||
$this->assertSameCurrency($other);
|
||||
|
||||
return $this->getCalculator()->compare($this->amount, $other->amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the value represented by this object is greater than the other.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function greaterThan(Money $other)
|
||||
{
|
||||
return $this->compare($other) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Money\Money $other
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function greaterThanOrEqual(Money $other)
|
||||
{
|
||||
return $this->compare($other) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the value represented by this object is less than the other.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function lessThan(Money $other)
|
||||
{
|
||||
return $this->compare($other) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Money\Money $other
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function lessThanOrEqual(Money $other)
|
||||
{
|
||||
return $this->compare($other) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value represented by this object.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getAmount()
|
||||
{
|
||||
return $this->amount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currency of this object.
|
||||
*
|
||||
* @return Currency
|
||||
*/
|
||||
public function getCurrency()
|
||||
{
|
||||
return $this->currency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Money object that represents
|
||||
* the sum of this and an other Money object.
|
||||
*
|
||||
* @param Money[] $addends
|
||||
*
|
||||
* @return Money
|
||||
*/
|
||||
public function add(Money ...$addends)
|
||||
{
|
||||
$amount = $this->amount;
|
||||
$calculator = $this->getCalculator();
|
||||
|
||||
foreach ($addends as $addend) {
|
||||
$this->assertSameCurrency($addend);
|
||||
|
||||
$amount = $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.
|
||||
*
|
||||
* @param Money[] $subtrahends
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public function subtract(Money ...$subtrahends)
|
||||
{
|
||||
$amount = $this->amount;
|
||||
$calculator = $this->getCalculator();
|
||||
|
||||
foreach ($subtrahends as $subtrahend) {
|
||||
$this->assertSameCurrency($subtrahend);
|
||||
|
||||
$amount = $calculator->subtract($amount, $subtrahend->amount);
|
||||
}
|
||||
|
||||
return new self($amount, $this->currency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the operand is integer or float.
|
||||
*
|
||||
* @param float|int|string $operand
|
||||
*
|
||||
* @throws \InvalidArgumentException If $operand is neither integer nor float
|
||||
*/
|
||||
private function assertOperand($operand)
|
||||
{
|
||||
if (!is_numeric($operand)) {
|
||||
throw new \InvalidArgumentException(sprintf('Operand should be a numeric value, "%s" given.', is_object($operand) ? get_class($operand) : gettype($operand)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that rounding mode is a valid integer value.
|
||||
*
|
||||
* @param int $roundingMode
|
||||
*
|
||||
* @throws \InvalidArgumentException If $roundingMode is not valid
|
||||
*/
|
||||
private function assertRoundingMode($roundingMode)
|
||||
{
|
||||
if (!in_array(
|
||||
$roundingMode, [
|
||||
self::ROUND_HALF_DOWN, self::ROUND_HALF_EVEN, self::ROUND_HALF_ODD,
|
||||
self::ROUND_HALF_UP, self::ROUND_UP, self::ROUND_DOWN,
|
||||
self::ROUND_HALF_POSITIVE_INFINITY, self::ROUND_HALF_NEGATIVE_INFINITY,
|
||||
], true
|
||||
)) {
|
||||
throw new \InvalidArgumentException('Rounding mode should be Money::ROUND_HALF_DOWN | '.'Money::ROUND_HALF_EVEN | Money::ROUND_HALF_ODD | '.'Money::ROUND_HALF_UP | Money::ROUND_UP | Money::ROUND_DOWN'.'Money::ROUND_HALF_POSITIVE_INFINITY | Money::ROUND_HALF_NEGATIVE_INFINITY');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Money object that represents
|
||||
* the multiplied value by the given factor.
|
||||
*
|
||||
* @param float|int|string $multiplier
|
||||
* @param int $roundingMode
|
||||
*
|
||||
* @return Money
|
||||
*/
|
||||
public function multiply($multiplier, $roundingMode = self::ROUND_HALF_UP)
|
||||
{
|
||||
$this->assertOperand($multiplier);
|
||||
$this->assertRoundingMode($roundingMode);
|
||||
|
||||
$product = $this->round($this->getCalculator()->multiply($this->amount, $multiplier), $roundingMode);
|
||||
|
||||
return $this->newInstance($product);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Money object that represents
|
||||
* the divided value by the given factor.
|
||||
*
|
||||
* @param float|int|string $divisor
|
||||
* @param int $roundingMode
|
||||
*
|
||||
* @return Money
|
||||
*/
|
||||
public function divide($divisor, $roundingMode = self::ROUND_HALF_UP)
|
||||
{
|
||||
$this->assertOperand($divisor);
|
||||
$this->assertRoundingMode($roundingMode);
|
||||
|
||||
$divisor = (string) Number::fromNumber($divisor);
|
||||
|
||||
if ($this->getCalculator()->compare($divisor, '0') === 0) {
|
||||
throw new \InvalidArgumentException('Division by zero');
|
||||
}
|
||||
|
||||
$quotient = $this->round($this->getCalculator()->divide($this->amount, $divisor), $roundingMode);
|
||||
|
||||
return $this->newInstance($quotient);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new Money object that represents
|
||||
* the remainder after dividing the value by
|
||||
* the given factor.
|
||||
*
|
||||
* @return Money
|
||||
*/
|
||||
public function mod(Money $divisor)
|
||||
{
|
||||
$this->assertSameCurrency($divisor);
|
||||
|
||||
return new self($this->getCalculator()->mod($this->amount, $divisor->amount), $this->currency);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate the money according to a list of ratios.
|
||||
*
|
||||
* @return Money[]
|
||||
*/
|
||||
public function allocate(array $ratios)
|
||||
{
|
||||
if (count($ratios) === 0) {
|
||||
throw new \InvalidArgumentException('Cannot allocate to none, ratios cannot be an empty 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 = $this->getCalculator()->share($this->amount, $ratio, $total);
|
||||
$results[$key] = $this->newInstance($share);
|
||||
$remainder = $this->getCalculator()->subtract($remainder, $share);
|
||||
}
|
||||
|
||||
if ($this->getCalculator()->compare($remainder, '0') === 0) {
|
||||
return $results;
|
||||
}
|
||||
|
||||
$fractions = array_map(function ($ratio) use ($total) {
|
||||
$share = ($ratio / $total) * $this->amount;
|
||||
|
||||
return $share - floor($share);
|
||||
}, $ratios);
|
||||
|
||||
while ($this->getCalculator()->compare($remainder, '0') > 0) {
|
||||
$index = !empty($fractions) ? array_keys($fractions, max($fractions))[0] : 0;
|
||||
$results[$index]->amount = $this->getCalculator()->add($results[$index]->amount, '1');
|
||||
$remainder = $this->getCalculator()->subtract($remainder, '1');
|
||||
unset($fractions[$index]);
|
||||
}
|
||||
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocate the money among N targets.
|
||||
*
|
||||
* @param int $n
|
||||
*
|
||||
* @return Money[]
|
||||
*
|
||||
* @throws \InvalidArgumentException If number of targets is not an integer
|
||||
*/
|
||||
public function allocateTo($n)
|
||||
{
|
||||
if (!is_int($n)) {
|
||||
throw new \InvalidArgumentException('Number of targets must be an integer');
|
||||
}
|
||||
|
||||
if ($n <= 0) {
|
||||
throw new \InvalidArgumentException('Cannot allocate to none, target must be greater than zero');
|
||||
}
|
||||
|
||||
return $this->allocate(array_fill(0, $n, 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function ratioOf(Money $money)
|
||||
{
|
||||
if ($money->isZero()) {
|
||||
throw new \InvalidArgumentException('Cannot calculate a ratio of zero');
|
||||
}
|
||||
|
||||
return $this->getCalculator()->divide($this->amount, $money->amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $amount
|
||||
* @param int $rounding_mode
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function round($amount, $rounding_mode)
|
||||
{
|
||||
$this->assertRoundingMode($rounding_mode);
|
||||
|
||||
if ($rounding_mode === self::ROUND_UP) {
|
||||
return $this->getCalculator()->ceil($amount);
|
||||
}
|
||||
|
||||
if ($rounding_mode === self::ROUND_DOWN) {
|
||||
return $this->getCalculator()->floor($amount);
|
||||
}
|
||||
|
||||
return $this->getCalculator()->round($amount, $rounding_mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Money
|
||||
*/
|
||||
public function absolute()
|
||||
{
|
||||
return $this->newInstance($this->getCalculator()->absolute($this->amount));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Money
|
||||
*/
|
||||
public function negative()
|
||||
{
|
||||
return $this->newInstance(0)->subtract($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value represented by this object is zero.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isZero()
|
||||
{
|
||||
return $this->getCalculator()->compare($this->amount, 0) === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value represented by this object is positive.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isPositive()
|
||||
{
|
||||
return $this->getCalculator()->compare($this->amount, 0) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the value represented by this object is negative.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isNegative()
|
||||
{
|
||||
return $this->getCalculator()->compare($this->amount, 0) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return [
|
||||
'amount' => $this->amount,
|
||||
'currency' => $this->currency->jsonSerialize(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Money $first
|
||||
* @param Money ...$collection
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function min(self $first, self ...$collection)
|
||||
{
|
||||
$min = $first;
|
||||
|
||||
foreach ($collection as $money) {
|
||||
if ($money->lessThan($min)) {
|
||||
$min = $money;
|
||||
}
|
||||
}
|
||||
|
||||
return $min;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Money $first
|
||||
* @param Money ...$collection
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function max(self $first, self ...$collection)
|
||||
{
|
||||
$max = $first;
|
||||
|
||||
foreach ($collection as $money) {
|
||||
if ($money->greaterThan($max)) {
|
||||
$max = $money;
|
||||
}
|
||||
}
|
||||
|
||||
return $max;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Money $first
|
||||
* @param Money ...$collection
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function sum(self $first, self ...$collection)
|
||||
{
|
||||
return $first->add(...$collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Money $first
|
||||
* @param Money ...$collection
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
public static function avg(self $first, self ...$collection)
|
||||
{
|
||||
return $first->add(...$collection)->divide(func_num_args());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $calculator
|
||||
*/
|
||||
public static function registerCalculator($calculator)
|
||||
{
|
||||
if (is_a($calculator, Calculator::class, true) === false) {
|
||||
throw new \InvalidArgumentException('Calculator must implement '.Calculator::class);
|
||||
}
|
||||
|
||||
array_unshift(self::$calculators, $calculator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Calculator
|
||||
*
|
||||
* @throws \RuntimeException If cannot find calculator for money calculations
|
||||
*/
|
||||
private static function initializeCalculator()
|
||||
{
|
||||
$calculators = self::$calculators;
|
||||
|
||||
foreach ($calculators as $calculator) {
|
||||
/** @var Calculator $calculator */
|
||||
if ($calculator::supported()) {
|
||||
return new $calculator();
|
||||
}
|
||||
}
|
||||
|
||||
throw new \RuntimeException('Cannot find calculator for money calculations');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Calculator
|
||||
*/
|
||||
private function getCalculator()
|
||||
{
|
||||
if (null === self::$calculator) {
|
||||
self::$calculator = self::initializeCalculator();
|
||||
}
|
||||
|
||||
return self::$calculator;
|
||||
}
|
||||
}
|
||||
208
pancake/system/vendor/moneyphp/money/src/MoneyFactory.php
vendored
Executable file
208
pancake/system/vendor/moneyphp/money/src/MoneyFactory.php
vendored
Executable file
@@ -0,0 +1,208 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
/**
|
||||
* This is a generated file. Do not edit it manually!
|
||||
*
|
||||
* @method static Money AED(string|int $amount)
|
||||
* @method static Money ALL(string|int $amount)
|
||||
* @method static Money AMD(string|int $amount)
|
||||
* @method static Money ANG(string|int $amount)
|
||||
* @method static Money AOA(string|int $amount)
|
||||
* @method static Money ARS(string|int $amount)
|
||||
* @method static Money AUD(string|int $amount)
|
||||
* @method static Money AWG(string|int $amount)
|
||||
* @method static Money AZN(string|int $amount)
|
||||
* @method static Money BAM(string|int $amount)
|
||||
* @method static Money BBD(string|int $amount)
|
||||
* @method static Money BDT(string|int $amount)
|
||||
* @method static Money BGN(string|int $amount)
|
||||
* @method static Money BHD(string|int $amount)
|
||||
* @method static Money BIF(string|int $amount)
|
||||
* @method static Money BMD(string|int $amount)
|
||||
* @method static Money BND(string|int $amount)
|
||||
* @method static Money BOB(string|int $amount)
|
||||
* @method static Money BOV(string|int $amount)
|
||||
* @method static Money BRL(string|int $amount)
|
||||
* @method static Money BSD(string|int $amount)
|
||||
* @method static Money BTN(string|int $amount)
|
||||
* @method static Money BWP(string|int $amount)
|
||||
* @method static Money BYN(string|int $amount)
|
||||
* @method static Money BZD(string|int $amount)
|
||||
* @method static Money CAD(string|int $amount)
|
||||
* @method static Money CDF(string|int $amount)
|
||||
* @method static Money CHE(string|int $amount)
|
||||
* @method static Money CHF(string|int $amount)
|
||||
* @method static Money CHW(string|int $amount)
|
||||
* @method static Money CLF(string|int $amount)
|
||||
* @method static Money CLP(string|int $amount)
|
||||
* @method static Money CNY(string|int $amount)
|
||||
* @method static Money COP(string|int $amount)
|
||||
* @method static Money COU(string|int $amount)
|
||||
* @method static Money CRC(string|int $amount)
|
||||
* @method static Money CUC(string|int $amount)
|
||||
* @method static Money CUP(string|int $amount)
|
||||
* @method static Money CVE(string|int $amount)
|
||||
* @method static Money CZK(string|int $amount)
|
||||
* @method static Money DJF(string|int $amount)
|
||||
* @method static Money DKK(string|int $amount)
|
||||
* @method static Money DOP(string|int $amount)
|
||||
* @method static Money DZD(string|int $amount)
|
||||
* @method static Money EGP(string|int $amount)
|
||||
* @method static Money ERN(string|int $amount)
|
||||
* @method static Money ETB(string|int $amount)
|
||||
* @method static Money EUR(string|int $amount)
|
||||
* @method static Money FJD(string|int $amount)
|
||||
* @method static Money FKP(string|int $amount)
|
||||
* @method static Money GBP(string|int $amount)
|
||||
* @method static Money GEL(string|int $amount)
|
||||
* @method static Money GHS(string|int $amount)
|
||||
* @method static Money GIP(string|int $amount)
|
||||
* @method static Money GMD(string|int $amount)
|
||||
* @method static Money GNF(string|int $amount)
|
||||
* @method static Money GTQ(string|int $amount)
|
||||
* @method static Money GYD(string|int $amount)
|
||||
* @method static Money HKD(string|int $amount)
|
||||
* @method static Money HNL(string|int $amount)
|
||||
* @method static Money HRK(string|int $amount)
|
||||
* @method static Money HTG(string|int $amount)
|
||||
* @method static Money HUF(string|int $amount)
|
||||
* @method static Money IDR(string|int $amount)
|
||||
* @method static Money ILS(string|int $amount)
|
||||
* @method static Money INR(string|int $amount)
|
||||
* @method static Money IQD(string|int $amount)
|
||||
* @method static Money IRR(string|int $amount)
|
||||
* @method static Money ISK(string|int $amount)
|
||||
* @method static Money JMD(string|int $amount)
|
||||
* @method static Money JOD(string|int $amount)
|
||||
* @method static Money JPY(string|int $amount)
|
||||
* @method static Money KES(string|int $amount)
|
||||
* @method static Money KGS(string|int $amount)
|
||||
* @method static Money KHR(string|int $amount)
|
||||
* @method static Money KMF(string|int $amount)
|
||||
* @method static Money KPW(string|int $amount)
|
||||
* @method static Money KRW(string|int $amount)
|
||||
* @method static Money KWD(string|int $amount)
|
||||
* @method static Money KYD(string|int $amount)
|
||||
* @method static Money KZT(string|int $amount)
|
||||
* @method static Money LAK(string|int $amount)
|
||||
* @method static Money LBP(string|int $amount)
|
||||
* @method static Money LKR(string|int $amount)
|
||||
* @method static Money LRD(string|int $amount)
|
||||
* @method static Money LSL(string|int $amount)
|
||||
* @method static Money LYD(string|int $amount)
|
||||
* @method static Money MAD(string|int $amount)
|
||||
* @method static Money MDL(string|int $amount)
|
||||
* @method static Money MGA(string|int $amount)
|
||||
* @method static Money MKD(string|int $amount)
|
||||
* @method static Money MMK(string|int $amount)
|
||||
* @method static Money MNT(string|int $amount)
|
||||
* @method static Money MOP(string|int $amount)
|
||||
* @method static Money MRU(string|int $amount)
|
||||
* @method static Money MUR(string|int $amount)
|
||||
* @method static Money MVR(string|int $amount)
|
||||
* @method static Money MWK(string|int $amount)
|
||||
* @method static Money MXN(string|int $amount)
|
||||
* @method static Money MXV(string|int $amount)
|
||||
* @method static Money MYR(string|int $amount)
|
||||
* @method static Money MZN(string|int $amount)
|
||||
* @method static Money NAD(string|int $amount)
|
||||
* @method static Money NGN(string|int $amount)
|
||||
* @method static Money NIO(string|int $amount)
|
||||
* @method static Money NOK(string|int $amount)
|
||||
* @method static Money NPR(string|int $amount)
|
||||
* @method static Money NZD(string|int $amount)
|
||||
* @method static Money OMR(string|int $amount)
|
||||
* @method static Money PAB(string|int $amount)
|
||||
* @method static Money PEN(string|int $amount)
|
||||
* @method static Money PGK(string|int $amount)
|
||||
* @method static Money PHP(string|int $amount)
|
||||
* @method static Money PKR(string|int $amount)
|
||||
* @method static Money PLN(string|int $amount)
|
||||
* @method static Money PYG(string|int $amount)
|
||||
* @method static Money QAR(string|int $amount)
|
||||
* @method static Money RON(string|int $amount)
|
||||
* @method static Money RSD(string|int $amount)
|
||||
* @method static Money RUB(string|int $amount)
|
||||
* @method static Money RWF(string|int $amount)
|
||||
* @method static Money SAR(string|int $amount)
|
||||
* @method static Money SBD(string|int $amount)
|
||||
* @method static Money SCR(string|int $amount)
|
||||
* @method static Money SDG(string|int $amount)
|
||||
* @method static Money SEK(string|int $amount)
|
||||
* @method static Money SGD(string|int $amount)
|
||||
* @method static Money SHP(string|int $amount)
|
||||
* @method static Money SLL(string|int $amount)
|
||||
* @method static Money SOS(string|int $amount)
|
||||
* @method static Money SRD(string|int $amount)
|
||||
* @method static Money SSP(string|int $amount)
|
||||
* @method static Money STN(string|int $amount)
|
||||
* @method static Money SVC(string|int $amount)
|
||||
* @method static Money SYP(string|int $amount)
|
||||
* @method static Money SZL(string|int $amount)
|
||||
* @method static Money THB(string|int $amount)
|
||||
* @method static Money TJS(string|int $amount)
|
||||
* @method static Money TMT(string|int $amount)
|
||||
* @method static Money TND(string|int $amount)
|
||||
* @method static Money TOP(string|int $amount)
|
||||
* @method static Money TRY(string|int $amount)
|
||||
* @method static Money TTD(string|int $amount)
|
||||
* @method static Money TWD(string|int $amount)
|
||||
* @method static Money TZS(string|int $amount)
|
||||
* @method static Money UAH(string|int $amount)
|
||||
* @method static Money UGX(string|int $amount)
|
||||
* @method static Money USD(string|int $amount)
|
||||
* @method static Money USN(string|int $amount)
|
||||
* @method static Money UYI(string|int $amount)
|
||||
* @method static Money UYU(string|int $amount)
|
||||
* @method static Money UYW(string|int $amount)
|
||||
* @method static Money UZS(string|int $amount)
|
||||
* @method static Money VES(string|int $amount)
|
||||
* @method static Money VND(string|int $amount)
|
||||
* @method static Money VUV(string|int $amount)
|
||||
* @method static Money WST(string|int $amount)
|
||||
* @method static Money XAF(string|int $amount)
|
||||
* @method static Money XAG(string|int $amount)
|
||||
* @method static Money XAU(string|int $amount)
|
||||
* @method static Money XBA(string|int $amount)
|
||||
* @method static Money XBB(string|int $amount)
|
||||
* @method static Money XBC(string|int $amount)
|
||||
* @method static Money XBD(string|int $amount)
|
||||
* @method static Money XBT(string|int $amount)
|
||||
* @method static Money XCD(string|int $amount)
|
||||
* @method static Money XDR(string|int $amount)
|
||||
* @method static Money XOF(string|int $amount)
|
||||
* @method static Money XPD(string|int $amount)
|
||||
* @method static Money XPF(string|int $amount)
|
||||
* @method static Money XPT(string|int $amount)
|
||||
* @method static Money XSU(string|int $amount)
|
||||
* @method static Money XTS(string|int $amount)
|
||||
* @method static Money XUA(string|int $amount)
|
||||
* @method static Money XXX(string|int $amount)
|
||||
* @method static Money YER(string|int $amount)
|
||||
* @method static Money ZAR(string|int $amount)
|
||||
* @method static Money ZMW(string|int $amount)
|
||||
* @method static Money ZWL(string|int $amount)
|
||||
*/
|
||||
trait MoneyFactory
|
||||
{
|
||||
/**
|
||||
* Convenience factory method for a Money object.
|
||||
*
|
||||
* <code>
|
||||
* $fiveDollar = Money::USD(500);
|
||||
* </code>
|
||||
*
|
||||
* @param string $method
|
||||
* @param array $arguments
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @throws \InvalidArgumentException If amount is not integer(ish)
|
||||
*/
|
||||
public static function __callStatic($method, $arguments)
|
||||
{
|
||||
return new Money($arguments[0], new Currency($method));
|
||||
}
|
||||
}
|
||||
20
pancake/system/vendor/moneyphp/money/src/MoneyFormatter.php
vendored
Executable file
20
pancake/system/vendor/moneyphp/money/src/MoneyFormatter.php
vendored
Executable file
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
/**
|
||||
* Formats Money objects.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
interface MoneyFormatter
|
||||
{
|
||||
/**
|
||||
* Formats a Money object as string.
|
||||
*
|
||||
* @return string
|
||||
*
|
||||
* Exception\FormatterException
|
||||
*/
|
||||
public function format(Money $money);
|
||||
}
|
||||
23
pancake/system/vendor/moneyphp/money/src/MoneyParser.php
vendored
Executable file
23
pancake/system/vendor/moneyphp/money/src/MoneyParser.php
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
/**
|
||||
* Parses a string into a Money object.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
interface MoneyParser
|
||||
{
|
||||
/**
|
||||
* Parses a string into a Money object (including currency).
|
||||
*
|
||||
* @param string $money
|
||||
* @param Currency|string|null $forceCurrency
|
||||
*
|
||||
* @return Money
|
||||
*
|
||||
* @throws Exception\ParserException
|
||||
*/
|
||||
public function parse($money, $forceCurrency = null);
|
||||
}
|
||||
331
pancake/system/vendor/moneyphp/money/src/Number.php
vendored
Executable file
331
pancake/system/vendor/moneyphp/money/src/Number.php
vendored
Executable file
@@ -0,0 +1,331 @@
|
||||
<?php
|
||||
|
||||
namespace Money;
|
||||
|
||||
/**
|
||||
* Represents a numeric value.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class Number
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $integerPart;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $fractionalPart;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private static $numbers = [0 => 1, 1 => 1, 2 => 1, 3 => 1, 4 => 1, 5 => 1, 6 => 1, 7 => 1, 8 => 1, 9 => 1];
|
||||
|
||||
/**
|
||||
* @param string $integerPart
|
||||
* @param string $fractionalPart
|
||||
*/
|
||||
public function __construct($integerPart, $fractionalPart = '')
|
||||
{
|
||||
if ('' === $integerPart && '' === $fractionalPart) {
|
||||
throw new \InvalidArgumentException('Empty number is invalid');
|
||||
}
|
||||
|
||||
$this->integerPart = $this->parseIntegerPart((string) $integerPart);
|
||||
$this->fractionalPart = $this->parseFractionalPart((string) $fractionalPart);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $number
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function fromString($number)
|
||||
{
|
||||
$decimalSeparatorPosition = strpos($number, '.');
|
||||
if ($decimalSeparatorPosition === false) {
|
||||
return new self($number, '');
|
||||
}
|
||||
|
||||
return new self(
|
||||
substr($number, 0, $decimalSeparatorPosition),
|
||||
rtrim(substr($number, $decimalSeparatorPosition + 1), '0')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float $number
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function fromFloat($number)
|
||||
{
|
||||
if (is_float($number) === false) {
|
||||
throw new \InvalidArgumentException('Floating point value expected');
|
||||
}
|
||||
|
||||
return self::fromString(sprintf('%.14F', $number));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param float|int|string $number
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public static function fromNumber($number)
|
||||
{
|
||||
if (is_float($number)) {
|
||||
return self::fromString(sprintf('%.14F', $number));
|
||||
}
|
||||
|
||||
if (is_int($number)) {
|
||||
return new self($number);
|
||||
}
|
||||
|
||||
if (is_string($number)) {
|
||||
return self::fromString($number);
|
||||
}
|
||||
|
||||
throw new \InvalidArgumentException('Valid numeric value expected');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isDecimal()
|
||||
{
|
||||
return $this->fractionalPart !== '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isInteger()
|
||||
{
|
||||
return $this->fractionalPart === '';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isHalf()
|
||||
{
|
||||
return $this->fractionalPart === '5';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isCurrentEven()
|
||||
{
|
||||
$lastIntegerPartNumber = $this->integerPart[strlen($this->integerPart) - 1];
|
||||
|
||||
return $lastIntegerPartNumber % 2 === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isCloserToNext()
|
||||
{
|
||||
if ($this->fractionalPart === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->fractionalPart[0] >= 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
if ($this->fractionalPart === '') {
|
||||
return $this->integerPart;
|
||||
}
|
||||
|
||||
return $this->integerPart.'.'.$this->fractionalPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isNegative()
|
||||
{
|
||||
return $this->integerPart[0] === '-';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIntegerPart()
|
||||
{
|
||||
return $this->integerPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getFractionalPart()
|
||||
{
|
||||
return $this->fractionalPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getIntegerRoundingMultiplier()
|
||||
{
|
||||
if ($this->integerPart[0] === '-') {
|
||||
return '-1';
|
||||
}
|
||||
|
||||
return '1';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function base10($number)
|
||||
{
|
||||
if (!is_int($number)) {
|
||||
throw new \InvalidArgumentException('Expecting integer');
|
||||
}
|
||||
|
||||
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)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function parseIntegerPart($number)
|
||||
{
|
||||
if ('' === $number || '0' === $number) {
|
||||
return '0';
|
||||
}
|
||||
|
||||
if ('-' === $number) {
|
||||
return '-0';
|
||||
}
|
||||
|
||||
$nonZero = false;
|
||||
|
||||
for ($position = 0, $characters = strlen($number); $position < $characters; ++$position) {
|
||||
$digit = $number[$position];
|
||||
|
||||
if (!isset(static::$numbers[$digit]) && !(0 === $position && '-' === $digit)) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid integer part %1$s. Invalid digit %2$s found', $number, $digit));
|
||||
}
|
||||
|
||||
if (false === $nonZero && '0' === $digit) {
|
||||
throw new \InvalidArgumentException('Leading zeros are not allowed');
|
||||
}
|
||||
|
||||
$nonZero = true;
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private static function parseFractionalPart($number)
|
||||
{
|
||||
if ('' === $number) {
|
||||
return $number;
|
||||
}
|
||||
|
||||
for ($position = 0, $characters = strlen($number); $position < $characters; ++$position) {
|
||||
$digit = $number[$position];
|
||||
if (!isset(static::$numbers[$digit])) {
|
||||
throw new \InvalidArgumentException(sprintf('Invalid fractional part %1$s. Invalid digit %2$s found', $number, $digit));
|
||||
}
|
||||
}
|
||||
|
||||
return $number;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $moneyValue
|
||||
* @param int $targetDigits
|
||||
* @param int $havingDigits
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function roundMoneyValue($moneyValue, $targetDigits, $havingDigits)
|
||||
{
|
||||
$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) {
|
||||
$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;
|
||||
}
|
||||
}
|
||||
63
pancake/system/vendor/moneyphp/money/src/PHPUnit/Comparator.php
vendored
Executable file
63
pancake/system/vendor/moneyphp/money/src/PHPUnit/Comparator.php
vendored
Executable file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace Money\PHPUnit;
|
||||
|
||||
use Money\Currencies\AggregateCurrencies;
|
||||
use Money\Currencies\BitcoinCurrencies;
|
||||
use Money\Currencies\ISOCurrencies;
|
||||
use Money\Formatter\IntlMoneyFormatter;
|
||||
use Money\Money;
|
||||
use SebastianBergmann\Comparator\ComparisonFailure;
|
||||
|
||||
/**
|
||||
* 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());
|
||||
*/
|
||||
final class Comparator extends \SebastianBergmann\Comparator\Comparator
|
||||
{
|
||||
/**
|
||||
* @var IntlMoneyFormatter
|
||||
*/
|
||||
private $formatter;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
|
||||
$currencies = new AggregateCurrencies([
|
||||
new ISOCurrencies(),
|
||||
new BitcoinCurrencies(),
|
||||
]);
|
||||
|
||||
$numberFormatter = new \NumberFormatter('en_US', \NumberFormatter::CURRENCY);
|
||||
$this->formatter = new IntlMoneyFormatter($numberFormatter, $currencies);
|
||||
}
|
||||
|
||||
public function accepts($expected, $actual)
|
||||
{
|
||||
return $expected instanceof Money && $actual instanceof Money;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Money $expected
|
||||
* @param Money $actual
|
||||
* @param float $delta
|
||||
* @param bool $canonicalize
|
||||
* @param bool $ignoreCase
|
||||
*/
|
||||
public function assertEquals(
|
||||
$expected,
|
||||
$actual,
|
||||
$delta = 0.0,
|
||||
$canonicalize = false,
|
||||
$ignoreCase = false,
|
||||
array &$processed = []
|
||||
) {
|
||||
if (!$expected->equals($actual)) {
|
||||
throw new ComparisonFailure($expected, $actual, $this->formatter->format($expected), $this->formatter->format($actual), false, 'Failed asserting that two Money objects are equal.');
|
||||
}
|
||||
}
|
||||
}
|
||||
58
pancake/system/vendor/moneyphp/money/src/Parser/AggregateMoneyParser.php
vendored
Executable file
58
pancake/system/vendor/moneyphp/money/src/Parser/AggregateMoneyParser.php
vendored
Executable file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Parser;
|
||||
|
||||
use Money\Currency;
|
||||
use Money\Exception;
|
||||
use Money\MoneyParser;
|
||||
|
||||
/**
|
||||
* Parses a string into a Money object using other parsers.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class AggregateMoneyParser implements MoneyParser
|
||||
{
|
||||
/**
|
||||
* @var MoneyParser[]
|
||||
*/
|
||||
private $parsers = [];
|
||||
|
||||
/**
|
||||
* @param MoneyParser[] $parsers
|
||||
*/
|
||||
public function __construct(array $parsers)
|
||||
{
|
||||
if (empty($parsers)) {
|
||||
throw new \InvalidArgumentException(sprintf('Initialize an empty %s is not possible', self::class));
|
||||
}
|
||||
|
||||
foreach ($parsers as $parser) {
|
||||
if (false === $parser instanceof MoneyParser) {
|
||||
throw new \InvalidArgumentException('All parsers must implement '.MoneyParser::class);
|
||||
}
|
||||
|
||||
$this->parsers[] = $parser;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse($money, $forceCurrency = null)
|
||||
{
|
||||
if ($forceCurrency !== null && !$forceCurrency instanceof Currency) {
|
||||
@trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED);
|
||||
$forceCurrency = new Currency($forceCurrency);
|
||||
}
|
||||
|
||||
foreach ($this->parsers as $parser) {
|
||||
try {
|
||||
return $parser->parse($money, $forceCurrency);
|
||||
} catch (Exception\ParserException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception\ParserException(sprintf('Unable to parse %s', $money));
|
||||
}
|
||||
}
|
||||
82
pancake/system/vendor/moneyphp/money/src/Parser/BitcoinMoneyParser.php
vendored
Executable file
82
pancake/system/vendor/moneyphp/money/src/Parser/BitcoinMoneyParser.php
vendored
Executable file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Parser;
|
||||
|
||||
use Money\Currencies\BitcoinCurrencies;
|
||||
use Money\Currency;
|
||||
use Money\Exception\ParserException;
|
||||
use Money\Money;
|
||||
use Money\MoneyParser;
|
||||
|
||||
/**
|
||||
* Parses Bitcoin currency to Money.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class BitcoinMoneyParser implements MoneyParser
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $fractionDigits;
|
||||
|
||||
/**
|
||||
* @param int $fractionDigits
|
||||
*/
|
||||
public function __construct($fractionDigits)
|
||||
{
|
||||
$this->fractionDigits = $fractionDigits;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse($money, $forceCurrency = null)
|
||||
{
|
||||
if (is_string($money) === false) {
|
||||
throw new ParserException('Formatted raw money should be string, e.g. $1.00');
|
||||
}
|
||||
|
||||
if (strpos($money, BitcoinCurrencies::SYMBOL) === false) {
|
||||
throw new ParserException('Value cannot be parsed as Bitcoin');
|
||||
}
|
||||
|
||||
if ($forceCurrency === null) {
|
||||
$forceCurrency = new Currency(BitcoinCurrencies::CODE);
|
||||
}
|
||||
|
||||
/*
|
||||
* This conversion is only required whilst currency can be either a string or a
|
||||
* Currency object.
|
||||
*/
|
||||
$currency = $forceCurrency;
|
||||
if (!$currency instanceof Currency) {
|
||||
@trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED);
|
||||
$currency = new Currency($currency);
|
||||
}
|
||||
|
||||
$decimal = str_replace(BitcoinCurrencies::SYMBOL, '', $money);
|
||||
$decimalSeparator = strpos($decimal, '.');
|
||||
|
||||
if (false !== $decimalSeparator) {
|
||||
$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);
|
||||
}
|
||||
}
|
||||
100
pancake/system/vendor/moneyphp/money/src/Parser/DecimalMoneyParser.php
vendored
Executable file
100
pancake/system/vendor/moneyphp/money/src/Parser/DecimalMoneyParser.php
vendored
Executable file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Parser;
|
||||
|
||||
use Money\Currencies;
|
||||
use Money\Currency;
|
||||
use Money\Exception\ParserException;
|
||||
use Money\Money;
|
||||
use Money\MoneyParser;
|
||||
use Money\Number;
|
||||
|
||||
/**
|
||||
* Parses a decimal string into a Money object.
|
||||
*
|
||||
* @author Teoh Han Hui <teohhanhui@gmail.com>
|
||||
*/
|
||||
final class DecimalMoneyParser implements MoneyParser
|
||||
{
|
||||
const DECIMAL_PATTERN = '/^(?P<sign>-)?(?P<digits>0|[1-9]\d*)?\.?(?P<fraction>\d+)?$/';
|
||||
|
||||
/**
|
||||
* @var Currencies
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
public function __construct(Currencies $currencies)
|
||||
{
|
||||
$this->currencies = $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse($money, $forceCurrency = null)
|
||||
{
|
||||
if (!is_string($money)) {
|
||||
throw new ParserException('Formatted raw money should be string, e.g. 1.00');
|
||||
}
|
||||
|
||||
if (null === $forceCurrency) {
|
||||
throw new ParserException('DecimalMoneyParser cannot parse currency symbols. Use forceCurrency argument');
|
||||
}
|
||||
|
||||
/*
|
||||
* This conversion is only required whilst currency can be either a string or a
|
||||
* Currency object.
|
||||
*/
|
||||
$currency = $forceCurrency;
|
||||
if (!$currency instanceof Currency) {
|
||||
@trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED);
|
||||
$currency = new Currency($currency);
|
||||
}
|
||||
|
||||
$decimal = trim($money);
|
||||
|
||||
if ($decimal === '') {
|
||||
return new Money(0, $currency);
|
||||
}
|
||||
|
||||
$subunit = $this->currencies->subunitFor($currency);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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, $currency);
|
||||
}
|
||||
}
|
||||
94
pancake/system/vendor/moneyphp/money/src/Parser/IntlLocalizedDecimalParser.php
vendored
Executable file
94
pancake/system/vendor/moneyphp/money/src/Parser/IntlLocalizedDecimalParser.php
vendored
Executable file
@@ -0,0 +1,94 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Parser;
|
||||
|
||||
use Money\Currencies;
|
||||
use Money\Currency;
|
||||
use Money\Exception\ParserException;
|
||||
use Money\Money;
|
||||
use Money\MoneyParser;
|
||||
use Money\Number;
|
||||
|
||||
/**
|
||||
* Parses a string into a Money object using intl extension.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class IntlLocalizedDecimalParser implements MoneyParser
|
||||
{
|
||||
/**
|
||||
* @var \NumberFormatter
|
||||
*/
|
||||
private $formatter;
|
||||
|
||||
/**
|
||||
* @var Currencies
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
public function __construct(\NumberFormatter $formatter, Currencies $currencies)
|
||||
{
|
||||
$this->formatter = $formatter;
|
||||
$this->currencies = $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse($money, $forceCurrency = null)
|
||||
{
|
||||
if (!is_string($money)) {
|
||||
throw new ParserException('Formatted raw money should be string, e.g. $1.00');
|
||||
}
|
||||
|
||||
if (null === $forceCurrency) {
|
||||
throw new ParserException('IntlLocalizedDecimalParser cannot parse currency symbols. Use forceCurrency argument');
|
||||
}
|
||||
|
||||
$decimal = $this->formatter->parse($money);
|
||||
|
||||
if (false === $decimal) {
|
||||
throw new ParserException('Cannot parse '.$money.' to Money. '.$this->formatter->getErrorMessage());
|
||||
}
|
||||
|
||||
/*
|
||||
* This conversion is only required whilst currency can be either a string or a
|
||||
* Currency object.
|
||||
*/
|
||||
if (!$forceCurrency instanceof Currency) {
|
||||
@trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED);
|
||||
$forceCurrency = new Currency($forceCurrency);
|
||||
}
|
||||
|
||||
$decimal = (string) $decimal;
|
||||
$subunit = $this->currencies->subunitFor($forceCurrency);
|
||||
$decimalPosition = strpos($decimal, '.');
|
||||
|
||||
if (false !== $decimalPosition) {
|
||||
$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, $forceCurrency);
|
||||
}
|
||||
}
|
||||
97
pancake/system/vendor/moneyphp/money/src/Parser/IntlMoneyParser.php
vendored
Executable file
97
pancake/system/vendor/moneyphp/money/src/Parser/IntlMoneyParser.php
vendored
Executable file
@@ -0,0 +1,97 @@
|
||||
<?php
|
||||
|
||||
namespace Money\Parser;
|
||||
|
||||
use Money\Currencies;
|
||||
use Money\Currency;
|
||||
use Money\Exception\ParserException;
|
||||
use Money\Money;
|
||||
use Money\MoneyParser;
|
||||
use Money\Number;
|
||||
|
||||
/**
|
||||
* Parses a string into a Money object using intl extension.
|
||||
*
|
||||
* @author Frederik Bosch <f.bosch@genkgo.nl>
|
||||
*/
|
||||
final class IntlMoneyParser implements MoneyParser
|
||||
{
|
||||
/**
|
||||
* @var \NumberFormatter
|
||||
*/
|
||||
private $formatter;
|
||||
|
||||
/**
|
||||
* @var Currencies
|
||||
*/
|
||||
private $currencies;
|
||||
|
||||
public function __construct(\NumberFormatter $formatter, Currencies $currencies)
|
||||
{
|
||||
$this->formatter = $formatter;
|
||||
$this->currencies = $currencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function parse($money, $forceCurrency = null)
|
||||
{
|
||||
if (!is_string($money)) {
|
||||
throw new ParserException('Formatted raw money should be string, e.g. $1.00');
|
||||
}
|
||||
|
||||
$currency = null;
|
||||
$decimal = $this->formatter->parseCurrency($money, $currency);
|
||||
|
||||
if (false === $decimal) {
|
||||
throw new ParserException('Cannot parse '.$money.' to Money. '.$this->formatter->getErrorMessage());
|
||||
}
|
||||
|
||||
if (null !== $forceCurrency) {
|
||||
$currency = $forceCurrency;
|
||||
} else {
|
||||
$currency = new Currency($currency);
|
||||
}
|
||||
|
||||
/*
|
||||
* This conversion is only required whilst currency can be either a string or a
|
||||
* Currency object.
|
||||
*/
|
||||
if (!$currency instanceof Currency) {
|
||||
@trigger_error('Passing a currency as string is deprecated since 3.1 and will be removed in 4.0. Please pass a '.Currency::class.' instance instead.', E_USER_DEPRECATED);
|
||||
$currency = new Currency($currency);
|
||||
}
|
||||
|
||||
$decimal = (string) $decimal;
|
||||
$subunit = $this->currencies->subunitFor($currency);
|
||||
$decimalPosition = strpos($decimal, '.');
|
||||
|
||||
if (false !== $decimalPosition) {
|
||||
$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, $currency);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user