Passed
Push — main ( fa09fa...8e9cbd )
by Michael
07:25 queued 03:59
created

SanitizesNumbers::isPrecise()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 17
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 9
nc 2
nop 1
dl 0
loc 17
ccs 10
cts 10
cp 1
crap 3
rs 9.9666
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace MichaelRubel\ValueObjects\Concerns;
6
7
use LengthException;
8
9
trait SanitizesNumbers
10
{
11
    /**
12
     * @param  int|string|float|null  $number
13
     *
14
     * @return string
15
     */
16 137
    protected function sanitize(int|string|float|null $number): string
17
    {
18 137
        if (is_float($number) && ! $this->isPrecise($number)) {
19 13
            throw new LengthException('Float precision loss detected.');
20
        }
21
22 124
        $number = str($number)->replace(',', '.');
23
24 124
        $dots = $number->substrCount('.');
25
26 124
        if ($dots >= 2) {
27 10
            $number = $number
28 10
                ->replaceLast('.', ',')
29 10
                ->replace('.', '')
30 10
                ->replaceLast(',', '.');
31
        }
32
33 124
        return $number
34 124
            ->replaceMatches('/[^0-9.]/', '')
35 124
            ->toString();
36
    }
37
38
    /**
39
     * Determine whether the passed floating point number is precise.
40
     *
41
     * @param  float  $number
42
     *
43
     * @return bool
44
     */
45 59
    protected function isPrecise(float $number): bool
46
    {
47 59
        $numberAsString = str($number);
48
49 59
        $afterFloatingPoint = $numberAsString
50 59
            ->explode('.')
51 59
            ->get(1, '');
52
53 59
        $precisionPosition = str($afterFloatingPoint)->length();
54
55 59
        $roundedNumber = round($number, $precisionPosition);
56
57 59
        if ($roundedNumber === $number && $numberAsString->length() <= PHP_FLOAT_DIG) {
58 46
            return true;
59
        }
60
61 13
        return false;
62
    }
63
}
64