����JFIF��x�x����'
Server IP : 78.140.185.180 / Your IP : 3.145.179.147 Web Server : LiteSpeed System : Linux cpanel13.v.fozzy.com 4.18.0-513.11.1.lve.el8.x86_64 #1 SMP Thu Jan 18 16:21:02 UTC 2024 x86_64 User : builderbox ( 1072) PHP Version : 7.3.33 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/builderbox/www/vendor/moneyphp/money/src/Exchange/ |
Upload File : |
<?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; /** * @param Exchange $exchange * @param Currencies $currencies */ 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); } } /** * @param Currency $baseCurrency * @param Currency $counterCurrency * * @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); } /** * @param Currency $currency * * @return \stdClass */ private function initializeNode(Currency $currency) { $node = new \stdClass(); $node->currency = $currency; $node->discovered = false; $node->parent = null; return $node; } /** * @param array $currencies * @param \stdClass $goalNode * * @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'); } }