From 695955b8fa3d38a2316eb76bde164e1f1f884085 Mon Sep 17 00:00:00 2001 From: Benjamin Morel Date: Mon, 20 Aug 2018 23:07:07 +0200 Subject: [PATCH] Money::formatTo() can now format amount as a whole number --- composer.json | 2 +- src/Money.php | 12 +++++++++--- tests/MoneyTest.php | 26 ++++++++++++++++++-------- 3 files changed, 28 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index 9f8c14c..1e8d1c6 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "license": "MIT", "require": { "php": ">=7.1", - "brick/math": "~0.6.2 || 0.7.*" + "brick/math": "~0.7.3" }, "require-dev": { "phpunit/phpunit": "7.*", diff --git a/src/Money.php b/src/Money.php index 42ebe91..e1e86c9 100644 --- a/src/Money.php +++ b/src/Money.php @@ -634,7 +634,7 @@ public function convertedTo($currency, $exchangeRate, Context $context = null, i * Note that NumberFormatter internally represents values using floating point arithmetic, * so discrepancies can appear when formatting very large monetary values. * - * @param \NumberFormatter $formatter + * @param \NumberFormatter $formatter The formatter to format with. * * @return string */ @@ -652,15 +652,21 @@ public function formatWith(\NumberFormatter $formatter) : string * Note that this method uses NumberFormatter, which internally represents values using floating point arithmetic, * so discrepancies can appear when formatting very large monetary values. * - * @param string $locale + * @param string $locale The locale to format to. + * @param bool $allowWholeNumber Whether to allow formatting as a whole number if the amount has no fraction. * * @return string */ - public function formatTo(string $locale) : string + public function formatTo(string $locale, bool $allowWholeNumber = false) : string { $scale = $this->amount->getScale(); $formatter = new \NumberFormatter($locale, \NumberFormatter::CURRENCY); + + if ($allowWholeNumber && ! $this->amount->hasNonZeroFractionalPart()) { + $scale = 0; + } + $formatter->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, $scale); $formatter->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $scale); diff --git a/tests/MoneyTest.php b/tests/MoneyTest.php index 022cd58..7921c90 100644 --- a/tests/MoneyTest.php +++ b/tests/MoneyTest.php @@ -884,13 +884,14 @@ public function providerFormatWith() /** * @dataProvider providerFormatTo * - * @param array $money The money to test. - * @param string $locale The target locale. - * @param string $expected The expected output. + * @param array $money The money to test. + * @param string $locale The target locale. + * @param bool $allowWholeNumber Whether to allow formatting as a whole number if the amount has no fraction. + * @param string $expected The expected output. */ - public function testFormatTo(array $money, $locale, $expected) + public function testFormatTo(array $money, $locale, $allowWholeNumber, $expected) { - $this->assertSame($expected, Money::of(...$money)->formatTo($locale)); + $this->assertSame($expected, Money::of(...$money)->formatTo($locale, $allowWholeNumber)); } /** @@ -899,9 +900,18 @@ public function testFormatTo(array $money, $locale, $expected) public function providerFormatTo() { return [ - [['1.23', 'USD'], 'en_US', '$1.23'], - [['1.23', 'USD'], 'fr_FR', '1,23 $US'], - [['1.23', 'EUR'], 'fr_FR', '1,23 €'], + [['1.23', 'USD'], 'en_US', false, '$1.23'], + [['1.23', 'USD'], 'fr_FR', false, '1,23 $US'], + [['1.23', 'EUR'], 'fr_FR', false, '1,23 €'], + [['1.234', 'EUR', new CustomContext(3)], 'fr_FR', false, '1,234 €'], + [['234.0', 'EUR', new CustomContext(1)], 'fr_FR', false, '234,0 €'], + [['234.0', 'EUR', new CustomContext(1)], 'fr_FR', true, '234 €'], + [['234.00', 'GBP'], 'en_GB', false, '£234.00'], + [['234.00', 'GBP'], 'en_GB', true, '£234'], + [['234.000', 'EUR', new CustomContext(3)], 'fr_FR', false, '234,000 €'], + [['234.000', 'EUR', new CustomContext(3)], 'fr_FR', true, '234 €'], + [['234.001', 'GBP', new CustomContext(3)], 'en_GB', false, '£234.001'], + [['234.001', 'GBP', new CustomContext(3)], 'en_GB', true, '£234.001'], ]; }