new appraoch
This commit is contained in:
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());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user