Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
100.00% |
11 / 11 |
|
100.00% |
6 / 6 |
CRAP | |
100.00% |
1 / 1 |
FrmtrNumber | |
100.00% |
11 / 11 |
|
100.00% |
6 / 6 |
10 | |
100.00% |
1 / 1 |
setUseGroupingSeparator | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
format | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
createFormatter | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
useGroupingSeparator | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
2 | |||
getRoundingMode | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setRoundingMode | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 |
1 | <?php |
2 | |
3 | /** |
4 | * @author: Doug Wilbourne (dougwilbourne@gmail.com) |
5 | */ |
6 | |
7 | declare(strict_types=1); |
8 | |
9 | namespace pvc\frmtr\numeric; |
10 | |
11 | use NumberFormatter; |
12 | use pvc\frmtr\err\InvalidRoundingModeException; |
13 | use pvc\frmtr\Frmtr; |
14 | |
15 | /** |
16 | * Class FrmtrNumber |
17 | * @extends Frmtr<float|int> |
18 | */ |
19 | abstract class FrmtrNumber extends Frmtr |
20 | { |
21 | /** |
22 | * @var array<int> |
23 | */ |
24 | protected array $validRoundingModes = [ |
25 | NumberFormatter::ROUND_CEILING, |
26 | NumberFormatter::ROUND_FLOOR, |
27 | NumberFormatter::ROUND_DOWN, |
28 | NumberFormatter::ROUND_UP, |
29 | NumberFormatter::ROUND_HALFEVEN, |
30 | NumberFormatter::ROUND_HALFDOWN, |
31 | NumberFormatter::ROUND_HALFUP, |
32 | ]; |
33 | |
34 | /** |
35 | * @var int |
36 | * I think HALFUP is more common in most people's minds instead of the actual default of ROUND_HALFEVEN |
37 | */ |
38 | protected int $roundingMode = NumberFormatter::ROUND_HALFUP; |
39 | |
40 | protected bool $useGroupingSeparator = true; |
41 | |
42 | /** |
43 | * @param bool $useGroupingSeparator |
44 | */ |
45 | public function setUseGroupingSeparator(bool $useGroupingSeparator): void |
46 | { |
47 | $this->useGroupingSeparator = $useGroupingSeparator; |
48 | } |
49 | |
50 | /** |
51 | * @function format |
52 | * @param float|int $value |
53 | * @return string |
54 | */ |
55 | public function format($value): string |
56 | { |
57 | /** |
58 | * in theory, NumberFormatter can return false. Convert to empty string if it fails.... |
59 | */ |
60 | return ($this->createFormatter()->format($value) ?: ''); |
61 | } |
62 | |
63 | /** |
64 | * createFormatter |
65 | * default type of formatter is Decimal, which covers both integers and floats. The currency formatter |
66 | * creates a different type. |
67 | * @return NumberFormatter |
68 | */ |
69 | protected function createFormatter(): NumberFormatter |
70 | { |
71 | $formatter = new NumberFormatter((string)$this->getLocale(), NumberFormatter::DECIMAL); |
72 | $formatter->setAttribute(NumberFormatter::GROUPING_USED, ($this->useGroupingSeparator() !== 0 ? 1 : 0)); |
73 | $formatter->setAttribute(NumberFormatter::ROUNDING_MODE, $this->getRoundingMode()); |
74 | return $formatter; |
75 | } |
76 | |
77 | /** |
78 | * @return int |
79 | * return an int because that is the data type required for the GROUPING_USED attribute of NumberFormatter |
80 | */ |
81 | public function useGroupingSeparator(): int |
82 | { |
83 | return ($this->useGroupingSeparator ? 1 : 0); |
84 | } |
85 | |
86 | /** |
87 | * getRoundingMode |
88 | * @return int |
89 | */ |
90 | public function getRoundingMode(): int |
91 | { |
92 | return $this->roundingMode; |
93 | } |
94 | |
95 | /** |
96 | * setRoundingMode |
97 | * @param int $roundingMode |
98 | * @throws InvalidRoundingModeException |
99 | */ |
100 | public function setRoundingMode(int $roundingMode): void |
101 | { |
102 | if (!in_array($roundingMode, $this->validRoundingModes)) { |
103 | throw new InvalidRoundingModeException(); |
104 | } |
105 | $this->roundingMode = $roundingMode; |
106 | } |
107 | } |