Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
78.26% |
54 / 69 |
|
87.50% |
14 / 16 |
CRAP | |
0.00% |
0 / 1 |
FloatInt | |
78.26% |
54 / 69 |
|
87.50% |
14 / 16 |
52.84 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
toInt | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
4 | |||
setLocalization | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
setString | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
getAmount | |
84.62% |
11 / 13 |
|
0.00% |
0 / 1 |
7.18 | |||
getFloat | |
0.00% |
0 / 13 |
|
0.00% |
0 / 1 |
56 | |||
add | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
4 | |||
getInt | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
sub | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
4 | |||
mult | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
div | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
abs | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
pow | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
serialize | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
unserialize | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
setInt | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 |
1 | <?php |
2 | /** |
3 | * Jingga |
4 | * |
5 | * PHP Version 8.1 |
6 | * |
7 | * @package phpOMS\Stdlib |
8 | * @copyright Dennis Eichhorn |
9 | * @license OMS License 2.0 |
10 | * @version 1.0.0 |
11 | * @link https://jingga.app |
12 | */ |
13 | declare(strict_types=1); |
14 | |
15 | namespace phpOMS\Stdlib\Base; |
16 | |
17 | use phpOMS\Contract\SerializableInterface; |
18 | |
19 | /** |
20 | * FloatInt class. |
21 | * |
22 | * @package phpOMS\Stdlib |
23 | * @license OMS License 2.0 |
24 | * @link https://jingga.app |
25 | * @since 1.0.0 |
26 | */ |
27 | class FloatInt implements SerializableInterface |
28 | { |
29 | /** |
30 | * Max amount of decimals. |
31 | * |
32 | * @var int |
33 | * @since 1.0.0 |
34 | */ |
35 | public const MAX_DECIMALS = 4; |
36 | |
37 | /** |
38 | * Thousands separator. |
39 | * |
40 | * @var string |
41 | * @since 1.0.0 |
42 | */ |
43 | public string $thousands = ','; |
44 | |
45 | /** |
46 | * Decimal separator. |
47 | * |
48 | * @var string |
49 | * @since 1.0.0 |
50 | */ |
51 | public string $decimal = '.'; |
52 | |
53 | /** |
54 | * Value. |
55 | * |
56 | * @var int |
57 | * @since 1.0.0 |
58 | */ |
59 | public int $value = 0; |
60 | |
61 | /** |
62 | * Constructor. |
63 | * |
64 | * @param int|float|string $value Value |
65 | * @param string $thousands Thousands separator |
66 | * @param string $decimal Decimal separator |
67 | * |
68 | * @since 1.0.0 |
69 | */ |
70 | public function __construct(int | float | string $value = 0, string $thousands = ',', string $decimal = '.') |
71 | { |
72 | $this->value = \is_int($value) ? $value : self::toInt((string) $value); |
73 | $this->thousands = $thousands; |
74 | $this->decimal = $decimal; |
75 | } |
76 | |
77 | /** |
78 | * FloatInt to int. |
79 | * |
80 | * @param string $value FloatInt value |
81 | * @param string $thousands Thousands character |
82 | * @param string $decimal Decimal character |
83 | * |
84 | * @return int |
85 | * |
86 | * @throws \Exception this exception is thrown if an internal explode or substr error occurs |
87 | * |
88 | * @since 1.0.0 |
89 | */ |
90 | public static function toInt(string $value, string $thousands = ',', string $decimal = '.') : int |
91 | { |
92 | $split = \explode($decimal, $value); |
93 | |
94 | if ($split === false) { |
95 | throw new \Exception('Internal explode error.'); // @codeCoverageIgnore |
96 | } |
97 | |
98 | $left = $split[0]; |
99 | $left = \str_replace($thousands, '', $left); |
100 | $right = ''; |
101 | |
102 | if (\count($split) > 1) { |
103 | $right = $split[1]; |
104 | } |
105 | |
106 | $right = \substr($right, 0, self::MAX_DECIMALS); |
107 | if ($right === false) { |
108 | throw new \Exception('Internal substr error.'); // @codeCoverageIgnore |
109 | } |
110 | |
111 | return ((int) $left) * 10 ** self::MAX_DECIMALS + (int) \str_pad($right, self::MAX_DECIMALS, '0'); |
112 | } |
113 | |
114 | /** |
115 | * Set localization. |
116 | * |
117 | * @param string $thousands Thousands separator |
118 | * @param string $decimal Decimal separator |
119 | * |
120 | * @return FloatInt |
121 | * |
122 | * @since 1.0.0 |
123 | */ |
124 | public function setLocalization(string $thousands = ',', string $decimal = '.') : self |
125 | { |
126 | $this->thousands = $thousands; |
127 | $this->decimal = $decimal; |
128 | |
129 | return $this; |
130 | } |
131 | |
132 | /** |
133 | * Set value by string. |
134 | * |
135 | * @param string $value FloatInt value |
136 | * |
137 | * @return FloatInt |
138 | * |
139 | * @since 1.0.0 |
140 | */ |
141 | public function setString(string $value) : self |
142 | { |
143 | $this->value = self::toInt($value, $this->thousands, $this->decimal); |
144 | |
145 | return $this; |
146 | } |
147 | |
148 | /** |
149 | * Get money. |
150 | * |
151 | * @param null|int $decimals Precision (null = auto decimals) |
152 | * |
153 | * @return string |
154 | * |
155 | * @throws \Exception this exception is thrown if an internal substr error occurs |
156 | * |
157 | * @since 1.0.0 |
158 | */ |
159 | public function getAmount(?int $decimals = 2) : string |
160 | { |
161 | $isNegative = $this->value < 0 ? 1 : 0; |
162 | |
163 | $value = $this->value === 0 |
164 | ? \str_repeat('0', self::MAX_DECIMALS) |
165 | : (string) \round($this->value, -self::MAX_DECIMALS + $decimals); |
166 | |
167 | $left = \substr($value, 0, -self::MAX_DECIMALS + $isNegative); |
168 | |
169 | /** @var string $left */ |
170 | $left = $left === false ? '0' : $left; |
171 | $right = \substr($value, -self::MAX_DECIMALS + $isNegative); |
172 | |
173 | if ($right === false) { |
174 | throw new \Exception(); // @codeCoverageIgnore |
175 | } |
176 | |
177 | if ($decimals === null) { |
178 | $decimals = \strlen(\rtrim($right, '0')); |
179 | } |
180 | |
181 | return $decimals > 0 |
182 | ? \number_format((float) $left, 0, $this->decimal, $this->thousands) . $this->decimal . \substr($right, 0, $decimals) |
183 | : \str_pad($left, 1, '0'); |
184 | } |
185 | |
186 | /** |
187 | * Get money. |
188 | * |
189 | * @param null|int $decimals Precision (null = auto decimals) |
190 | * |
191 | * @return string |
192 | * |
193 | * @throws \Exception this exception is thrown if an internal substr error occurs |
194 | * |
195 | * @since 1.0.0 |
196 | */ |
197 | public function getFloat(?int $decimals = 2) : string |
198 | { |
199 | $isNegative = $this->value < 0 ? 1 : 0; |
200 | |
201 | $value = $this->value === 0 |
202 | ? \str_repeat('0', self::MAX_DECIMALS) |
203 | : (string) \round($this->value, -self::MAX_DECIMALS + $decimals); |
204 | |
205 | $left = \substr($value, 0, -self::MAX_DECIMALS + $isNegative); |
206 | |
207 | /** @var string $left */ |
208 | $left = $left === false ? '0' : $left; |
209 | $right = \substr($value, -self::MAX_DECIMALS + $isNegative); |
210 | |
211 | if ($right === false) { |
212 | throw new \Exception(); // @codeCoverageIgnore |
213 | } |
214 | |
215 | if ($decimals === null) { |
216 | $decimals = \strlen(\rtrim($right, '0')); |
217 | } |
218 | |
219 | return $decimals > 0 |
220 | ? \number_format((float) $left, 0, $this->decimal, '') . $this->decimal . \substr($right, 0, $decimals) |
221 | : \str_pad($left, 1, '0'); |
222 | } |
223 | |
224 | /** |
225 | * Add money. |
226 | * |
227 | * @param int|float|string|FloatInt $value Value to add |
228 | * |
229 | * @return FloatInt |
230 | * |
231 | * @since 1.0.0 |
232 | */ |
233 | public function add(int | float | string | self $value) : self |
234 | { |
235 | if (\is_string($value) || \is_float($value)) { |
236 | $this->value += self::toInt((string) $value, $this->thousands, $this->decimal); |
237 | } elseif (\is_int($value)) { |
238 | $this->value += $value; |
239 | } else { |
240 | $this->value += $value->getInt(); |
241 | } |
242 | |
243 | return $this; |
244 | } |
245 | |
246 | /** |
247 | * Get money value. |
248 | * |
249 | * @return int |
250 | * |
251 | * @since 1.0.0 |
252 | */ |
253 | public function getInt() : int |
254 | { |
255 | return $this->value; |
256 | } |
257 | |
258 | /** |
259 | * Sub money. |
260 | * |
261 | * @param int|float|string|FloatInt $value Value to subtract |
262 | * |
263 | * @return FloatInt |
264 | * |
265 | * @since 1.0.0 |
266 | */ |
267 | public function sub(int | float | string | self $value) : self |
268 | { |
269 | if (\is_string($value) || \is_float($value)) { |
270 | $this->value -= self::toInt((string) $value, $this->thousands, $this->decimal); |
271 | } elseif (\is_int($value)) { |
272 | $this->value -= $value; |
273 | } else { |
274 | $this->value -= $value->getInt(); |
275 | } |
276 | |
277 | return $this; |
278 | } |
279 | |
280 | /** |
281 | * Mult. |
282 | * |
283 | * @param int|float $value Value to multiply with |
284 | * |
285 | * @return FloatInt |
286 | * |
287 | * @since 1.0.0 |
288 | */ |
289 | public function mult(int | float $value) : self |
290 | { |
291 | $this->value = (int) ($this->value * $value); |
292 | |
293 | return $this; |
294 | } |
295 | |
296 | /** |
297 | * Div. |
298 | * |
299 | * @param int|float $value Value to divide by |
300 | * |
301 | * @return FloatInt |
302 | * |
303 | * @since 1.0.0 |
304 | */ |
305 | public function div(int | float $value) : self |
306 | { |
307 | $this->value = (int) ($this->value / $value); |
308 | |
309 | return $this; |
310 | } |
311 | |
312 | /** |
313 | * Abs. |
314 | * |
315 | * @return FloatInt |
316 | * |
317 | * @since 1.0.0 |
318 | */ |
319 | public function abs() : self |
320 | { |
321 | $this->value = \abs($this->value); |
322 | |
323 | return $this; |
324 | } |
325 | |
326 | /** |
327 | * Power. |
328 | * |
329 | * @param int|float $value Value to power |
330 | * |
331 | * @return FloatInt |
332 | * |
333 | * @since 1.0.0 |
334 | */ |
335 | public function pow(int | float $value) : self |
336 | { |
337 | $this->value = (int) ($this->value ** $value); |
338 | |
339 | return $this; |
340 | } |
341 | |
342 | /** |
343 | * Searialze. |
344 | * |
345 | * @return string |
346 | * |
347 | * @since 1.0.0 |
348 | */ |
349 | public function serialize() : string |
350 | { |
351 | return (string) $this->getInt(); |
352 | } |
353 | |
354 | /** |
355 | * Unserialize. |
356 | * |
357 | * @param int|string $value Value to unserialize |
358 | * |
359 | * @return void |
360 | * |
361 | * @since 1.0.0 |
362 | */ |
363 | public function unserialize(mixed $value) : void |
364 | { |
365 | $this->setInt((int) $value); |
366 | } |
367 | |
368 | /** |
369 | * Set money value. |
370 | * |
371 | * @param int $value Value |
372 | * |
373 | * @return FloatInt |
374 | * |
375 | * @since 1.0.0 |
376 | */ |
377 | public function setInt(int $value) : self |
378 | { |
379 | $this->value = $value; |
380 | |
381 | return $this; |
382 | } |
383 | } |