diff --git a/psalm.xml b/psalm.xml index df40fdc3..851497c0 100644 --- a/psalm.xml +++ b/psalm.xml @@ -34,6 +34,11 @@ + + + + + diff --git a/src/View/Helper/NumberFormat.php b/src/View/Helper/NumberFormat.php index 4b4c0648..4af2f02b 100644 --- a/src/View/Helper/NumberFormat.php +++ b/src/View/Helper/NumberFormat.php @@ -13,18 +13,25 @@ use function serialize; /** - * View helper for formatting dates. + * View helper for formatting numbers. */ class NumberFormat extends AbstractHelper { use DeprecatedAbstractHelperHierarchyTrait; /** - * number of decimals to use. + * The maximum number of decimals to use. * * @var int */ - protected $decimals; + protected $maxDecimals; + + /** + * The minimum number of decimals to use. + * + * @var int + */ + protected $minDecimals; /** * NumberFormat style to use @@ -50,7 +57,7 @@ class NumberFormat extends AbstractHelper /** * Text attributes. * - * @var array + * @var array */ protected $textAttributes = []; @@ -64,12 +71,14 @@ class NumberFormat extends AbstractHelper /** * Format a number * - * @param int|float $number - * @param int|null $formatStyle - * @param int|null $formatType - * @param string|null $locale - * @param int|null $decimals - * @param array|null $textAttributes + * @param int|float $number + * @param int|null $formatStyle + * @param int|null $formatType + * @param string|null $locale + * @param int|null $maxDecimals + * @param array $textAttributes + * @param int|float $number + * @param int|null $minDecimals * @return string */ public function __invoke( @@ -77,8 +86,9 @@ public function __invoke( $formatStyle = null, $formatType = null, $locale = null, - $decimals = null, - ?array $textAttributes = null + $maxDecimals = null, + ?array $textAttributes = null, + $minDecimals = null ) { if (null === $locale) { $locale = $this->getLocale(); @@ -89,15 +99,22 @@ public function __invoke( if (null === $formatType) { $formatType = $this->getFormatType(); } - if (! is_int($decimals) || $decimals < 0) { - $decimals = $this->getDecimals(); + if (! is_int($minDecimals) || $minDecimals < 0) { + $minDecimals = $this->getMinDecimals(); + } + if (! is_int($maxDecimals) || $maxDecimals < 0) { + $maxDecimals = $this->getMaxDecimals(); + } + if (($maxDecimals !== null) && ($minDecimals === null)) { + // Fallback to old behavior + $minDecimals = $maxDecimals; } if (! is_array($textAttributes)) { $textAttributes = $this->getTextAttributes(); } $formatterId = md5( - $formatStyle . "\0" . $locale . "\0" . $decimals . "\0" + $formatStyle . "\0" . $locale . "\0" . ($minDecimals ?? '') . "\0" . ($maxDecimals ?? '') . "\0" . md5(serialize($textAttributes)) ); @@ -106,9 +123,12 @@ public function __invoke( } else { $formatter = new NumberFormatter($locale, $formatStyle); - if ($decimals !== null) { - $formatter->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $decimals); - $formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $decimals); + if ($minDecimals !== null) { + $formatter->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $minDecimals); + } + + if ($maxDecimals !== null) { + $formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $maxDecimals); } foreach ($textAttributes as $textAttribute => $value) { @@ -173,14 +193,39 @@ public function getFormatType() } /** - * Set number of decimals to use instead of the default. + * Set number of decimals (both min & max) to use instead of the default. * * @param int $decimals * @return $this */ public function setDecimals($decimals) { - $this->decimals = $decimals; + $this->minDecimals = $decimals; + $this->maxDecimals = $decimals; + return $this; + } + + /** + * Set the maximum number of decimals to use instead of the default. + * + * @param int $maxDecimals + * @return $this + */ + public function setMaxDecimals($maxDecimals) + { + $this->maxDecimals = $maxDecimals; + return $this; + } + + /** + * Set the minimum number of decimals to use instead of the default. + * + * @param int $minDecimals + * @return $this + */ + public function setMinDecimals($minDecimals) + { + $this->minDecimals = $minDecimals; return $this; } @@ -191,7 +236,27 @@ public function setDecimals($decimals) */ public function getDecimals() { - return $this->decimals; + return $this->maxDecimals; + } + + /** + * Get the maximum number of decimals. + * + * @return int + */ + public function getMaxDecimals() + { + return $this->maxDecimals; + } + + /** + * Get the minimum number of decimals. + * + * @return int + */ + public function getMinDecimals() + { + return $this->minDecimals; } /** @@ -221,7 +286,7 @@ public function getLocale() } /** - * @return array + * @return array */ public function getTextAttributes() { @@ -229,7 +294,7 @@ public function getTextAttributes() } /** - * @param array $textAttributes + * @param array $textAttributes * @return $this */ public function setTextAttributes(array $textAttributes) diff --git a/src/View/HelperTrait.php b/src/View/HelperTrait.php index 7c05fe84..26b68ba8 100644 --- a/src/View/HelperTrait.php +++ b/src/View/HelperTrait.php @@ -22,7 +22,7 @@ * @method string countryCodeDataList(?string $locale = null, array $dataListAttributes = []) * @method string currencyFormat(float $number, string|null $currencyCode = null, bool|null $showDecimals = null, string|null $locale = null, string|null $pattern = null) * @method string dateFormat(\DateTimeInterface|\IntlCalendar|int|array $date, int $dateType = IntlDateFormatter::NONE, int $timeType = IntlDateFormatter::NONE, string|null $locale = null, string|null $pattern = null) - * @method string numberFormat(int|float $number, int|null $formatStyle = null, int|null $formatType = null, string|null $locale = null, int|null $decimals = null, array|null $textAttributes = null) + * @method string numberFormat(int|float $number, int|null $formatStyle = null, int|null $formatType = null, string|null $locale = null, int|null $maxDecimals = null, array|null $textAttributes = null, int|null $minDecimals = null) * @method string plural(array|string $strings, int $number) * @method string translate(string $message, string|null $textDomain = null, string|null $locale = null) * @method string translatePlural(string $singular, string $plural, int $number, string|null $textDomain = null, string|null $locale = null) diff --git a/test/View/Helper/NumberFormatTest.php b/test/View/Helper/NumberFormatTest.php index 8286d1e5..7c49a822 100644 --- a/test/View/Helper/NumberFormatTest.php +++ b/test/View/Helper/NumberFormatTest.php @@ -22,8 +22,8 @@ protected function setUp(): void $this->helper = new NumberFormatHelper(); } - /** @return array, 5: float, 6: string}> */ - public static function currencyTestsDataProvider(): array + /** @return array, 5: int|null, 6: float, 7: string}> */ + public static function numberTestsDataProvider(): array { return [ [ @@ -32,6 +32,7 @@ public static function currencyTestsDataProvider(): array NumberFormatter::TYPE_DOUBLE, null, [], + null, 1234567.891234567890000, '1.234.567,891', ], @@ -41,6 +42,7 @@ public static function currencyTestsDataProvider(): array NumberFormatter::TYPE_DOUBLE, 6, [], + null, 1234567.891234567890000, '1.234.567,891235', ], @@ -50,6 +52,7 @@ public static function currencyTestsDataProvider(): array NumberFormatter::TYPE_DOUBLE, null, [], + null, 1234567.891234567890000, '123.456.789 %', ], @@ -59,6 +62,7 @@ public static function currencyTestsDataProvider(): array NumberFormatter::TYPE_DOUBLE, 1, [], + null, 1234567.891234567890000, '123.456.789,1 %', ], @@ -68,6 +72,7 @@ public static function currencyTestsDataProvider(): array NumberFormatter::TYPE_DOUBLE, null, [], + null, 1234567.891234560000, '1,23456789123456E6', ], @@ -77,6 +82,7 @@ public static function currencyTestsDataProvider(): array NumberFormatter::TYPE_DOUBLE, null, [], + null, 1234567.891234567890000, '1 234 567,891', ], @@ -86,6 +92,7 @@ public static function currencyTestsDataProvider(): array NumberFormatter::TYPE_DOUBLE, null, [], + null, 1234567.891234567890000, '123 456 789 %', ], @@ -95,6 +102,7 @@ public static function currencyTestsDataProvider(): array NumberFormatter::TYPE_DOUBLE, null, [], + null, 1234567.891234560000, '1,23456789123456E6', ], @@ -104,6 +112,7 @@ public static function currencyTestsDataProvider(): array NumberFormatter::TYPE_DOUBLE, null, [], + null, 1234567.891234567890000, '1,234,567.891', ], @@ -113,6 +122,7 @@ public static function currencyTestsDataProvider(): array NumberFormatter::TYPE_DOUBLE, null, [], + null, 1234567.891234567890000, '123,456,789%', ], @@ -122,6 +132,7 @@ public static function currencyTestsDataProvider(): array NumberFormatter::TYPE_DOUBLE, null, [], + null, 1234567.891234560000, '1.23456789123456E6', ], @@ -133,22 +144,44 @@ public static function currencyTestsDataProvider(): array [ NumberFormatter::NEGATIVE_PREFIX => 'MINUS', ], + null, -1234567.891234567890000, 'MINUS123,456,789%', ], + [ + 'de_DE', + NumberFormatter::DECIMAL, + NumberFormatter::TYPE_DOUBLE, + 5, + [], + 0, + 1234567.891234567890000, + '1.234.567,89123', + ], + [ + 'de_DE', + NumberFormatter::DECIMAL, + NumberFormatter::TYPE_DOUBLE, + 5, + [], + 0, + 1234567, + '1.234.567', + ], ]; } /** * @param array $textAttributes */ - #[DataProvider('currencyTestsDataProvider')] + #[DataProvider('numberTestsDataProvider')] public function testBasic( string $locale, int $formatStyle, int $formatType, ?int $decimals, array $textAttributes, + ?int $minDecimals, float $number, string $expected ): void { @@ -158,29 +191,32 @@ public function testBasic( $formatType, $locale, $decimals, - $textAttributes + $textAttributes, + $minDecimals )); } /** * @param array $textAttributes */ - #[DataProvider('currencyTestsDataProvider')] + #[DataProvider('numberTestsDataProvider')] public function testSettersProvideDefaults( string $locale, int $formatStyle, int $formatType, ?int $decimals, array $textAttributes, + ?int $minDecimals, float $number, string $expected ): void { $this->helper ->setLocale($locale) ->setFormatStyle($formatStyle) - ->setDecimals($decimals) + ->setMaxDecimals($decimals) ->setFormatType($formatType) - ->setTextAttributes($textAttributes); + ->setTextAttributes($textAttributes) + ->setMinDecimals($minDecimals); self::assertMbStringEquals($expected, $this->helper->__invoke($number)); }