Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
FrmtrNumber
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
6 / 6
10
100.00% covered (success)
100.00%
1 / 1
 setUseGroupingSeparator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 format
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 createFormatter
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 useGroupingSeparator
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 getRoundingMode
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 setRoundingMode
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2
3/**
4 * @author: Doug Wilbourne (dougwilbourne@gmail.com)
5 */
6
7declare(strict_types=1);
8
9namespace pvc\frmtr\numeric;
10
11use NumberFormatter;
12use pvc\frmtr\err\InvalidRoundingModeException;
13use pvc\frmtr\Frmtr;
14
15/**
16 * Class FrmtrNumber
17 * @extends Frmtr<float|int>
18 */
19abstract 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}