1 | <?php |
||
2 | |||
3 | namespace ICanBoogie\CLDR\Numbers; |
||
4 | |||
5 | use function explode; |
||
6 | use function preg_match; |
||
7 | use function str_replace; |
||
8 | use function strpos; |
||
9 | use function strrpos; |
||
10 | use function substr; |
||
11 | |||
12 | /** |
||
13 | * @link https://unicode.org/reports/tr35/tr35-numbers.html#Number_Pattern_Character_Definitions |
||
14 | * |
||
15 | * @phpstan-type PatternArray array{ |
||
16 | * positive_prefix: string, |
||
17 | * positive_suffix: string, |
||
18 | * negative_prefix: string, |
||
19 | * negative_suffix: string, |
||
20 | * multiplier: int, |
||
21 | * decimal_digits: int, |
||
22 | * max_decimal_digits: int, |
||
23 | * integer_digits: int, |
||
24 | * group_size1: int, |
||
25 | * group_size2: int |
||
26 | * } |
||
27 | */ |
||
28 | final class NumberPatternParser |
||
29 | { |
||
30 | public const PATTERN_REGEX = '/^(.*?)[#,\.0]+(.*?)$/'; |
||
31 | |||
32 | /** |
||
33 | * @var array<string, int|string> |
||
34 | */ |
||
35 | private static array $initial_format = [ |
||
36 | |||
37 | 'positive_prefix' => '', |
||
38 | 'positive_suffix' => '', |
||
39 | 'negative_prefix' => '', |
||
40 | 'negative_suffix' => '', |
||
41 | 'multiplier' => 1, |
||
42 | 'decimal_digits' => 0, |
||
43 | 'max_decimal_digits' => 0, |
||
44 | 'integer_digits' => 0, |
||
45 | 'group_size1' => 0, |
||
46 | 'group_size2' => 0 |
||
47 | |||
48 | ]; |
||
49 | |||
50 | /** |
||
51 | * Parses a given string pattern. |
||
52 | * |
||
53 | * @param string $pattern |
||
54 | * |
||
55 | * @return PatternArray |
||
0 ignored issues
–
show
|
|||
56 | */ |
||
57 | public static function parse(string $pattern): array |
||
58 | { |
||
59 | $format = self::$initial_format; |
||
60 | |||
61 | self::parse_multiple_patterns($pattern, $format); |
||
62 | self::parse_multiplier($pattern, $format); |
||
63 | self::parse_decimal_part($pattern, $format); |
||
64 | self::parse_integer_part($pattern, $format); |
||
65 | self::parse_group_sizes($pattern, $format); |
||
66 | |||
67 | return $format; |
||
68 | } |
||
69 | |||
70 | /** |
||
71 | * @param string $pattern |
||
72 | * @param PatternArray $format |
||
73 | */ |
||
74 | private static function parse_multiple_patterns(string &$pattern, array &$format): void |
||
75 | { |
||
76 | $patterns = explode(';', $pattern); |
||
77 | |||
78 | if (preg_match(self::PATTERN_REGEX, $patterns[0], $matches)) { |
||
79 | $format['positive_prefix'] = $matches[1]; |
||
80 | $format['positive_suffix'] = $matches[2]; |
||
81 | } |
||
82 | |||
83 | if (isset($patterns[1]) && preg_match(self::PATTERN_REGEX, $patterns[1], $matches)) { |
||
84 | $format['negative_prefix'] = $matches[1]; |
||
85 | $format['negative_suffix'] = $matches[2]; |
||
86 | } else { |
||
87 | $format['negative_prefix'] = '-' . $format['positive_prefix']; |
||
88 | $format['negative_suffix'] = $format['positive_suffix']; |
||
89 | } |
||
90 | |||
91 | $pattern = $patterns[0]; |
||
92 | } |
||
93 | |||
94 | /** |
||
95 | * @param string $pattern |
||
96 | * @param PatternArray $format |
||
97 | */ |
||
98 | private static function parse_multiplier(string $pattern, array &$format): void |
||
99 | { |
||
100 | if (str_contains($pattern, '%')) { |
||
101 | $format['multiplier'] = 100; |
||
102 | } elseif (str_contains($pattern, '‰')) { |
||
103 | $format['multiplier'] = 1000; |
||
104 | } |
||
105 | } |
||
106 | |||
107 | /** |
||
108 | * @param string $pattern |
||
109 | * @param PatternArray $format |
||
110 | */ |
||
111 | private static function parse_decimal_part(string &$pattern, array &$format): void |
||
112 | { |
||
113 | $pos = strpos($pattern, '.'); |
||
114 | |||
115 | if ($pos !== false) { |
||
116 | $pos2 = strrpos($pattern, '0'); |
||
117 | $format['decimal_digits'] = $pos2 > $pos |
||
118 | ? $pos2 - $pos |
||
119 | : 0; |
||
120 | |||
121 | $pos3 = strrpos($pattern, '#'); |
||
122 | $format['max_decimal_digits'] = $pos3 >= $pos2 |
||
123 | ? $pos3 - $pos |
||
124 | : $format['decimal_digits']; |
||
125 | |||
126 | $pattern = substr($pattern, 0, $pos); |
||
127 | } |
||
128 | } |
||
129 | |||
130 | /** |
||
131 | * @param string $pattern |
||
132 | * @param PatternArray $format |
||
133 | */ |
||
134 | private static function parse_integer_part(string $pattern, array &$format): void |
||
135 | { |
||
136 | $p = str_replace(',', '', $pattern); |
||
137 | $pos = strpos($p, '0'); |
||
138 | |||
139 | $format['integer_digits'] = $pos !== false |
||
140 | ? strrpos($p, '0') - $pos + 1 |
||
141 | : 0; |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * @param string $pattern |
||
146 | * @param PatternArray $format |
||
147 | */ |
||
148 | private static function parse_group_sizes(string $pattern, array &$format): void |
||
149 | { |
||
150 | $p = str_replace('#', '0', $pattern); |
||
151 | $pos = strrpos($pattern, ','); |
||
152 | |||
153 | if ($pos !== false) { |
||
154 | $pos2 = strrpos(substr($p, 0, $pos), ','); |
||
155 | $format['group_size1'] = strrpos($p, '0') - $pos; |
||
156 | $format['group_size2'] = $pos2 !== false ? $pos - $pos2 - 1 : 0; |
||
157 | } |
||
158 | } |
||
159 | } |
||
160 |
The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g.
excluded_paths: ["lib/*"]
, you can move it to the dependency path list as follows:For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths