craftcms / cms

Build bespoke content experiences with Craft.
https://craftcms.com
Other
3.28k stars 635 forks source link

Currency formatter InvalidConfigException #6277

Closed samhibberd closed 4 years ago

samhibberd commented 4 years ago

Description

Running into an odd error (reported in the commerce repo https://github.com/craftcms/commerce/issues/1541) but it think it might be an issue with the core.

Looks to be caused when a string rather than float / number is passed to the currency formatter:

Craft::$app->getFormatter()->asCurrency('26.3')

Throws:

The default currency code for the formatter is not defined.

Error suggests the config exception is thrown from the asCurrencyStringFallback()

Steps to reproduce

  1. Tested by calling the above formatter in a custom module init.
  2. Exception thrown

Additional info

> yii\base\InvalidConfigException: The default currency code for the formatter is not defined. in /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/i18n/Formatter.php:2076
> Stack trace:
> #0 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/i18n/Formatter.php(1275): yii\i18n\Formatter->asCurrencyStringFallback('26.3', NULL)
> #1 /Users/samhibberd/Sites/beta.findarace.com/vendor/craftcms/cms/src/i18n/Formatter.php(257): yii\i18n\Formatter->asCurrency('26.3', NULL, Array, Array)
> #2 /Users/samhibberd/Sites/beta.findarace.com/modules/findarace/src/Findarace.php(113): craft\i18n\Formatter->asCurrency('26.3')
> #3 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/base/BaseObject.php(109): modules\findarace\Findarace->init()
> #4 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/base/Module.php(158): yii\base\BaseObject->__construct(Array)
> #5 /Users/samhibberd/Sites/beta.findarace.com/modules/findarace/src/Findarace.php(95): yii\base\Module->__construct('findarace', Object(craft\web\Application), Array)
> #6 [internal function]: modules\findarace\Findarace->__construct('findarace', Object(craft\web\Application), Array)
> #7 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/di/Container.php(392): ReflectionClass->newInstanceArgs(Array)
> #8 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/di/Container.php(159): yii\di\Container->build('modules\\findara...', Array, Array)
> #9 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/BaseYii.php(365): yii\di\Container->get('modules\\findara...', Array, Array)
> #10 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/base/Module.php(427): yii\BaseYii::createObject(Array, Array)
> #11 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/base/Application.php(315): yii\base\Module->getModule('findarace')
> #12 /Users/samhibberd/Sites/beta.findarace.com/vendor/craftcms/cms/src/web/Application.php(118): yii\base\Application->bootstrap()
> #13 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/base/Application.php(273): craft\web\Application->bootstrap()
> #14 /Users/samhibberd/Sites/beta.findarace.com/vendor/craftcms/cms/src/web/Application.php(100): yii\base\Application->init()
> #15 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/base/BaseObject.php(109): craft\web\Application->init()
> #16 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/base/Application.php(206): yii\base\BaseObject->__construct(Array)
> #17 /Users/samhibberd/Sites/beta.findarace.com/vendor/craftcms/cms/src/web/Application.php(90): yii\base\Application->__construct(Array)
> #18 [internal function]: craft\web\Application->__construct(Array)
> #19 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/di/Container.php(400): ReflectionClass->newInstanceArgs(Array)
> #20 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/di/Container.php(159): yii\di\Container->build('craft\\web\\Appli...', Array, Array)
> #21 /Users/samhibberd/Sites/beta.findarace.com/vendor/yiisoft/yii2/BaseYii.php(365): yii\di\Container->get('craft\\web\\Appli...', Array, Array)
> #22 /Users/samhibberd/Sites/beta.findarace.com/vendor/craftcms/cms/bootstrap/bootstrap.php(241): yii\BaseYii::createObject(Array)
> #23 /Users/samhibberd/Sites/beta.findarace.com/vendor/craftcms/cms/bootstrap/web.php(51): require('/Users/samhibbe...')
> #24 /Users/samhibberd/Sites/beta.findarace.com/web/index.php(20): require('/Users/samhibbe...')
> #25 /Users/samhibberd/.composer/vendor/weprovide/valet-plus/server.php(131): require('/Users/samhibbe...')
> #26 {main}
brandonkelly commented 4 years ago

I’m not able to reproduce this, but appears to be a Yii bug with isNormalizedValueMispresented(). Can be worked around by casting the value to a float, or passing the $currency argument.

samhibberd commented 4 years ago

@brandonkelly this one has cropped up again for me, I did some digging in the Yii slack channel and feedback suggested it could well be a configuration issue.

I have narrowed it down to decimal strings as it only throws the exception if passed a string with decimal '26.4' passing '26' without the decimal and it's all good.

And if I override the configuration (just using the example in the Yii docs) then the issue goes away, https://www.yiiframework.com/doc/guide/2.0/en/output-formatting#configuring-formatter

brandonkelly commented 4 years ago

The formatter config is provided by the locale, so not something we can tweak.

samhibberd commented 4 years ago

It doesn't look like the locale config is setting a currencyCode with \Yii::$app->getFormatter()->currencyCode returning null.

Should the locale not be setting that?

brandonkelly commented 4 years ago

We do in fact set that, if the Intl extension is not installed. Otherwise it’s not needed since the Intl extension will handle it automatically. Just tested and works as expected on my end.

What locale is your site set to? Most locales don’t actually specify a currency. en-GB does, though.

samhibberd commented 4 years ago

Set to en-GB

brandonkelly commented 4 years ago

Maybe something is wrong with your Intl extension, then.

samhibberd commented 4 years ago

It was, finally had a chance to get everything updated locally and all resolved, thanks.