Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
75.86% covered (warning)
75.86%
22 / 29
37.50% covered (danger)
37.50%
3 / 8
CRAP
0.00% covered (danger)
0.00%
0 / 1
Decimal
75.86% covered (warning)
75.86%
22 / 29
37.50% covered (danger)
37.50%
3 / 8
21.06
0.00% covered (danger)
0.00%
0 / 1
 __construct
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
2.03
 __toString
0.00% covered (danger)
0.00%
0 / 3
0.00% covered (danger)
0.00%
0 / 1
6
 raw
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isset
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
2
 localize
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
3.03
 currency
85.71% covered (warning)
85.71%
6 / 7
0.00% covered (danger)
0.00%
0 / 1
3.03
 json
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getFormatter
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
3
1<?php
2
3declare(strict_types=1);
4
5namespace Cosray\Value;
6
7use Cosray\Exception\RuntimeException;
8use Cosray\Field\Field;
9use Cosray\Field\Owner;
10use NumberFormatter;
11use Override;
12
13class Decimal extends Value
14{
15    public readonly ?float $value;
16
17    public function __construct(Owner $owner, Field $field, ValueContext $context)
18    {
19        parent::__construct($owner, $field, $context);
20
21        $value = $this->value();
22
23        if (is_numeric($value)) {
24            $this->value = floatval($value);
25        } else {
26            $this->value = null;
27        }
28    }
29
30    #[Override]
31    public function __toString(): string
32    {
33        if ($this->value === null) {
34            return '';
35        }
36
37        return (string) $this->value;
38    }
39
40    #[Override]
41    public function raw(): ?float
42    {
43        return $this->value;
44    }
45
46    #[Override]
47    public function isset(): bool
48    {
49        return isset($this->value) ? true : false;
50    }
51
52    public function localize(?int $digits = 2, ?string $locale = null): string
53    {
54        if ($this->value) {
55            $formatter = $this->getFormatter(NumberFormatter::DECIMAL, $digits, $locale);
56            $formatted = $formatter->format($this->value);
57
58            return $formatted !== false
59                ? $formatted
60                : throw new RuntimeException('Decimal formatting failed: ' . $formatter->getErrorMessage());
61        }
62
63        return '';
64    }
65
66    public function currency(string $currency, ?int $digits = 2, ?string $locale = null): string
67    {
68        if ($this->value) {
69            $formatter = $this->getFormatter(NumberFormatter::CURRENCY, $digits, $locale);
70            $formatted = $formatter->formatCurrency($this->value, $currency);
71
72            return $formatted !== false
73                ? $formatted
74                : throw new RuntimeException('Currency formatting failed: ' . $formatter->getErrorMessage());
75        }
76
77        return '';
78    }
79
80    #[Override]
81    public function json(): mixed
82    {
83        return $this->value;
84    }
85
86    protected function getFormatter(int $style, ?int $digits, ?string $locale = null): NumberFormatter
87    {
88        $formatter = new NumberFormatter($locale ?: $this->locale->id, $style);
89
90        if ($digits !== null) {
91            $formatter->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $digits);
92        }
93
94        return $formatter;
95    }
96}