NumericParser::parse()   B
last analyzed

Complexity

Conditions 8
Paths 8

Size

Total Lines 17
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 10.3696

Importance

Changes 0
Metric Value
eloc 8
dl 0
loc 17
ccs 6
cts 9
cp 0.6667
rs 8.4444
c 0
b 0
f 0
cc 8
nc 8
nop 2
crap 10.3696
1
<?php
2
3
declare(strict_types=1);
4
5
namespace EngineWorks\DBAL\Internal;
6
7
/**
8
 * This class parses a string expression as a number or as in plain english (as need to put inside a sql statement)
9
 *
10
 * @internal
11
 */
12
class NumericParser
13
{
14
    use ConvertObjectToStringMethod;
1 ignored issue
show
introduced by
The trait EngineWorks\DBAL\Interna...ertObjectToStringMethod requires some properties which are not provided by EngineWorks\DBAL\Internal\NumericParser: $value, $name
Loading history...
15
16
    /**
17
     * Contains the running locale information
18
     * @var array{decimal_point: string, thousands_sep: string, currency_symbol: string}|null
19
     */
20
    private $localeConv = null;
21
22
    /**
23
     * @param mixed $value
24
     * @param bool $asInteger
25
     * @return int|float
26
     */
27 317
    public function parse($value, bool $asInteger)
28
    {
29
        // return simple numeric data
30 317
        if (is_bool($value) || is_int($value) || is_float($value)) {
31
            return ($asInteger) ? intval($value) : floatval($value);
32
        }
33
34
        // is object, convert to string
35 317
        if (is_object($value)) {
36
            $value = $this->convertObjectToString($value);
37
        }
38
        // is not string, early exit with 0
39 317
        if (! is_string($value)) {
40
            return 0;
41
        }
42 317
        $value = $this->parseToEnglish(trim($value));
43 317
        return ($asInteger) ? intval($value) : floatval($value);
44
    }
45
46
    /**
47
     * @param mixed $value
48
     * @param bool $asInteger
49
     * @return string
50
     */
51 317
    public function parseAsEnglish($value, bool $asInteger): string
52
    {
53 317
        return $this->numberToEnglish((string) $this->parse($value, $asInteger));
54
    }
55
56
    /**
57
     * @return array{decimal_point: string, thousands_sep: string, currency_symbol: string}
58
     */
59 317
    protected function getLocaleInfo(): array
60
    {
61 317
        if (null === $this->localeConv) {
62 317
            $this->localeConv = $this->obtainLocaleInfo();
63
        }
64 317
        return $this->localeConv;
65
    }
66
67
    /**
68
     * @return array{decimal_point: string, thousands_sep: string, currency_symbol: string}
69
     */
70 317
    protected function obtainLocaleInfo(): array
71
    {
72 317
        if ('C' === setlocale(LC_NUMERIC, '0')) {
73
            // override to us_EN
74
            return ['decimal_point' => '.', 'thousands_sep' => ',', 'currency_symbol' => '$'];
75
        }
76
77 317
        $locale = localeconv();
78 317
        return [
79 317
            'decimal_point' => strval($locale['decimal_point'] ?? '.'),
80 317
            'thousands_sep' => strval($locale['thousands_sep'] ?? ','),
81 317
            'currency_symbol' => strval($locale['currency_symbol'] ?? '$'),
82 317
        ];
83
    }
84
85
    /**
86
     * Remove the thousand separator, currency symbol and white spaces.
87
     * Returns the resulting string if is numeric,  otherwise returns '0'
88
     *
89
     * @param string $value
90
     * @return string
91
     */
92 317
    protected function parseToEnglish(string $value): string
93
    {
94 317
        if (ctype_digit($value)) {
95 317
            return $value;
96
        }
97 297
        $localeConv = $this->getLocaleInfo();
98 297
        $replacements = [$localeConv['thousands_sep'], $localeConv['currency_symbol'], ' ', "\t"];
99 297
        $value = $this->numberToEnglish(str_replace($replacements, '', $value));
100 297
        return (! is_numeric($value)) ? '0' : $value;
101
    }
102
103
    /**
104
     * Change decimal point to a real point
105
     * @param string $value
106
     * @return string
107
     */
108 317
    protected function numberToEnglish(string $value): string
109
    {
110 317
        if ('.' !== $this->getDecimalPoint()) {
111 8
            return str_replace($this->getDecimalPoint(), '.', $value);
112
        }
113 317
        return $value;
114
    }
115
116 317
    protected function getDecimalPoint(): string
117
    {
118 317
        return $this->getLocaleInfo()['decimal_point'];
119
    }
120
}
121