1 | <?php |
||
29 | class CurrencyFormatter extends NumberFormatter |
||
30 | { |
||
31 | /** |
||
32 | * @var string|null |
||
33 | */ |
||
34 | protected $currency_column; |
||
35 | |||
36 | /** |
||
37 | * @var array |
||
38 | */ |
||
39 | protected $default_params = [ |
||
40 | 'decimals' => 2, |
||
41 | 'locale' => null, |
||
42 | 'pattern' => null, |
||
43 | 'currency_code' => null, |
||
44 | 'disableUseOfNonBreakingSpaces' => false |
||
45 | ]; |
||
46 | |||
47 | /** |
||
48 | * @throws Exception\ExtensionNotLoadedException if ext/intl is not present |
||
49 | */ |
||
50 | 12 | public function __construct(array $params = []) |
|
51 | { |
||
52 | 12 | parent::__construct($params); |
|
53 | 12 | } |
|
54 | |||
55 | 6 | protected function loadFormatterId(string $formatterId): void |
|
56 | { |
||
57 | 6 | $locale = $this->params['locale']; |
|
58 | 6 | $formatter = new IntlNumberFormatter( |
|
59 | 6 | $locale, |
|
60 | 6 | IntlNumberFormatter::CURRENCY |
|
61 | ); |
||
62 | 6 | $formatter->setAttribute(IntlNumberFormatter::FRACTION_DIGITS, $this->params['decimals']); |
|
63 | 6 | if ($this->params['pattern'] !== null) { |
|
64 | $formatter->setPattern($this->params['pattern']); |
||
65 | } |
||
66 | 6 | $this->initWhitespaceSeparator($formatter); |
|
67 | 6 | $this->formatters[$formatterId] = $formatter; |
|
68 | 6 | } |
|
69 | |||
70 | /** |
||
71 | * Currency format a number. |
||
72 | * |
||
73 | * @throws Exception\RuntimeException |
||
74 | * |
||
75 | * @param float|string|int $number |
||
76 | * |
||
77 | * @return string |
||
78 | */ |
||
79 | 6 | public function format($number, ArrayObject $row = null): string |
|
80 | { |
||
81 | 6 | $locale = $this->params['locale']; |
|
82 | |||
83 | //$formatterId = md5($locale); |
||
84 | 6 | $formatterId = $locale . (string) $this->params['pattern']; |
|
85 | |||
86 | 6 | if (!array_key_exists($formatterId, $this->formatters)) { |
|
87 | 6 | $this->loadFormatterId($formatterId); |
|
88 | } |
||
89 | |||
90 | 6 | if ($this->currency_column !== null) { |
|
91 | 1 | if (!isset($row[$this->currency_column])) { |
|
92 | throw new Exception\RuntimeException(__METHOD__ . " Cannot determine currency code based on column '{$this->currency_column}'."); |
||
93 | } |
||
94 | 1 | $value = $this->formatters[$formatterId]->formatCurrency( |
|
95 | 1 | (float) $number, |
|
96 | 1 | $row[$this->currency_column] |
|
97 | ); |
||
98 | } else { |
||
99 | 5 | if ($this->params['currency_code'] == '') { |
|
100 | 3 | throw new Exception\RuntimeException(__METHOD__ . ' Currency code must be set prior to use the currency formatter'); |
|
101 | } |
||
102 | |||
103 | 2 | $value = $this->formatters[$formatterId]->formatCurrency( |
|
104 | 2 | (float) $number, |
|
105 | 2 | $this->params['currency_code'] |
|
106 | ); |
||
107 | } |
||
108 | |||
109 | 3 | if (intl_is_failure($this->formatters[$formatterId]->getErrorCode())) { |
|
110 | $this->throwNumberFormatterException($this->formatters[$formatterId], $number); |
||
111 | } |
||
112 | |||
113 | 3 | return $value; |
|
114 | } |
||
115 | |||
116 | /** |
||
117 | * Parse a. |
||
118 | * |
||
119 | * @param string $value |
||
120 | * |
||
121 | * @return array|null |
||
122 | */ |
||
123 | 1 | public function parse($value) |
|
124 | { |
||
125 | 1 | $locale = $this->params['locale']; |
|
126 | //$formatterId = md5($locale); |
||
127 | 1 | $formatterId = $locale; |
|
128 | 1 | if (!array_key_exists($formatterId, $this->formatters)) { |
|
129 | $this->loadFormatterId($formatterId); |
||
130 | } |
||
131 | // Currency will be passed as reference |
||
132 | // setting it to null prevent eventual warning |
||
133 | 1 | $currency = null; |
|
134 | 1 | $result = $this->formatters[$formatterId]->parseCurrency($value, $currency); |
|
135 | |||
136 | 1 | if ($result === false) { |
|
137 | return null; |
||
138 | } |
||
139 | |||
140 | 1 | return ['value' => $result, 'currency' => $currency]; |
|
141 | } |
||
142 | |||
143 | /** |
||
144 | * The 3-letter ISO 4217 currency code indicating the currency to use. |
||
145 | * |
||
146 | * @throws Exception\InvalidArgumentException |
||
147 | * |
||
148 | * @param string|RowColumn $currencyCode |
||
149 | */ |
||
150 | 4 | public function setCurrencyCode($currencyCode): self |
|
161 | |||
162 | 6 | protected function initWhitespaceSeparator(IntlNumberFormatter $formatter): void |
|
163 | { |
||
164 | 6 | parent::initWhitespaceSeparator($formatter); |
|
165 | 6 | if ($this->params['disableUseOfNonBreakingSpaces'] === true |
|
175 | |||
176 | /** |
||
177 | * Get the 3-letter ISO 4217 currency code indicating the currency to use. |
||
178 | * |
||
179 | * @return string|RowColumn |
||
180 | */ |
||
181 | 1 | public function getCurrencyCode() |
|
185 | } |
||
186 |