These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | declare(strict_types=1); |
||
4 | |||
5 | /* |
||
6 | * soluble-flexstore library |
||
7 | * |
||
8 | * @author Vanvelthem Sébastien |
||
9 | * @link https://github.com/belgattitude/soluble-flexstore |
||
10 | * @copyright Copyright (c) 2016-2017 Vanvelthem Sébastien |
||
11 | * @license MIT License https://github.com/belgattitude/soluble-flexstore/blob/master/LICENSE.md |
||
12 | * |
||
13 | */ |
||
14 | |||
15 | namespace Soluble\FlexStore\Formatter; |
||
16 | |||
17 | use Soluble\FlexStore\Exception; |
||
18 | use ArrayObject; |
||
19 | use NumberFormatter as IntlNumberFormatter; |
||
20 | |||
21 | /** |
||
22 | * columns |
||
23 | * - price: |
||
24 | * - formatter: |
||
25 | * - money |
||
26 | * - currency_code |
||
27 | * - locale. |
||
28 | */ |
||
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 |
|
151 | { |
||
152 | 4 | if ($currencyCode instanceof RowColumn) { |
|
153 | 2 | $this->currency_column = $currencyCode->getColumnName(); |
|
154 | 3 | } elseif (!is_string($currencyCode) || trim($currencyCode) === '') { |
|
155 | throw new Exception\InvalidArgumentException(__METHOD__ . ' Currency code must be an non empty string (or a RowColumn object)'); |
||
156 | } |
||
157 | 4 | $this->params['currency_code'] = $currencyCode; |
|
158 | |||
159 | 4 | return $this; |
|
160 | } |
||
161 | |||
162 | 6 | protected function initWhitespaceSeparator(IntlNumberFormatter $formatter): void |
|
163 | { |
||
164 | 6 | parent::initWhitespaceSeparator($formatter); |
|
165 | 6 | if ($this->params['disableUseOfNonBreakingSpaces'] === true |
|
166 | 1 | && in_array(bin2hex($formatter->getSymbol(IntlNumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL)), [ |
|
167 | 1 | self::NARROW_NO_BREAK_SPACE_HEX, |
|
168 | 1 | self::NO_BREAK_SPACE_HEX |
|
169 | 6 | ], true)) { |
|
0 ignored issues
–
show
Coding Style
introduced
by
Loading history...
|
|||
170 | |||
171 | 1 | $formatter->setSymbol(IntlNumberFormatter::MONETARY_GROUPING_SEPARATOR_SYMBOL, ' '); |
|
172 | // This does not work on php 7.3 (bug) ! |
||
173 | //$formatter->setSymbol(IntlNumberFormatter::MONETARY_SEPARATOR_SYMBOL, ' '); |
||
174 | |||
0 ignored issues
–
show
|
|||
175 | } |
||
176 | 6 | } |
|
177 | |||
178 | /** |
||
179 | * Get the 3-letter ISO 4217 currency code indicating the currency to use. |
||
180 | * |
||
181 | * @return string|RowColumn |
||
182 | */ |
||
183 | 1 | public function getCurrencyCode() |
|
184 | { |
||
185 | 1 | return $this->params['currency_code']; |
|
186 | } |
||
187 | } |
||
188 |