Description
The issue is about the implementation of the method \Magento\Framework\Pricing\PriceCurrencyInterface::format()
.
Even though no conversion takes place during the formatting of the given amount, the method only works if a conversion rate from the base currency to the specified currency is configured.
There is no technical need for this limitation.
Preconditions
A currency code without a configured conversion rate to the base currency.
Steps to reproduce
Call the method \Magento\Directory\Model\PriceCurrency::format()
with a currency code without a configured conversion rate to the base currency.
Expected result
The specified amount should be formatted in the specified currency.
Actual result
The specified amount is surprisingly rendered in the base currency.
Further information
The method format()
looks like this:
public function format(
$amount,
$includeContainer = true,
$precision = self::DEFAULT_PRECISION,
$scope = null,
$currency = null
) {
return $this->getCurrency($scope, $currency)
->formatPrecision($amount, $precision, [], $includeContainer);
}
This problem occurs in the getCurrency()
method where the constraint that the currency needs a configured conversion rate is applies:
public function getCurrency($scope = null, $currency = null)
{
if ($currency instanceof Currency) {
$currentCurrency = $currency;
} elseif (is_string($currency)) {
$currency = $this->currencyFactory->create()
->load($currency);
$baseCurrency = $this->getStore($scope)
->getBaseCurrency();
$currentCurrency = $baseCurrency->getRate($currency) ? $currency : $baseCurrency;
} else {
$currentCurrency = $this->getStore($scope)
->getCurrentCurrency();
}
return $currentCurrency;
}
With a currency code the middle conditional branch is executed:
$currency = $this->currencyFactory->create()
->load($currency);
$baseCurrency = $this->getStore($scope)
->getBaseCurrency();
$currentCurrency = $baseCurrency->getRate($currency) ? $currency : $baseCurrency;
This rule makes sense in some contexts, but not in the context of formatting a currency value.
Proposed solution:
Extract the loading of the given currency into a separate method and call that from format()
instead of the current getCurrency()
method. This way there is no behavioral backward compatibility break for methods calling getCurrency()
elsewhere.