1 | <?php |
||
2 | /** |
||
3 | * Amount.php |
||
4 | * Copyright (c) 2019 [email protected] |
||
5 | * |
||
6 | * This file is part of Firefly III (https://github.com/firefly-iii). |
||
7 | * |
||
8 | * This program is free software: you can redistribute it and/or modify |
||
9 | * it under the terms of the GNU Affero General Public License as |
||
10 | * published by the Free Software Foundation, either version 3 of the |
||
11 | * License, or (at your option) any later version. |
||
12 | * |
||
13 | * This program is distributed in the hope that it will be useful, |
||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
16 | * GNU Affero General Public License for more details. |
||
17 | * |
||
18 | * You should have received a copy of the GNU Affero General Public License |
||
19 | * along with this program. If not, see <https://www.gnu.org/licenses/>. |
||
20 | */ |
||
21 | declare(strict_types=1); |
||
22 | |||
23 | namespace FireflyIII\Import\Converter; |
||
24 | |||
25 | use Log; |
||
26 | |||
27 | /** |
||
28 | * Class Amount. |
||
29 | * |
||
30 | * @deprecated |
||
31 | * @codeCoverageIgnore |
||
32 | */ |
||
33 | class Amount implements ConverterInterface |
||
0 ignored issues
–
show
|
|||
34 | { |
||
35 | /** |
||
36 | * Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. |
||
37 | * - Jamie Zawinski. |
||
38 | * |
||
39 | * @param $value |
||
40 | * |
||
41 | * @return string |
||
42 | */ |
||
43 | public function convert($value): string |
||
44 | { |
||
45 | if (null === $value) { |
||
46 | return '0'; |
||
47 | } |
||
48 | Log::debug(sprintf('Start with amount "%s"', $value)); |
||
49 | $original = $value; |
||
50 | $value = $this->stripAmount((string) $value); |
||
51 | $decimal = null; |
||
52 | |||
53 | if ($this->decimalIsDot($value)) { |
||
54 | $decimal = '.'; |
||
55 | Log::debug(sprintf('Decimal character in "%s" seems to be a dot.', $value)); |
||
56 | } |
||
57 | |||
58 | if ($this->decimalIsComma($value)) { |
||
59 | $decimal = ','; |
||
60 | Log::debug(sprintf('Decimal character in "%s" seems to be a comma.', $value)); |
||
61 | } |
||
62 | |||
63 | // decimal character is null? find out if "0.1" or ".1" or "0,1" or ",1" |
||
64 | if ($this->alternativeDecimalSign($value)) { |
||
65 | $decimal = $this->getAlternativeDecimalSign($value); |
||
66 | } |
||
67 | |||
68 | // decimal character still null? Search from the left for '.',',' or ' '. |
||
69 | if (null === $decimal) { |
||
70 | $decimal = $this->findFromLeft($value); |
||
71 | } |
||
72 | |||
73 | // if decimal is dot, replace all comma's and spaces with nothing |
||
74 | if (null !== $decimal) { |
||
75 | $value = $this->replaceDecimal($decimal, $value); |
||
76 | Log::debug(sprintf('Converted amount from "%s" to "%s".', $original, $value)); |
||
77 | } |
||
78 | |||
79 | if (null === $decimal) { |
||
80 | // replace all: |
||
81 | $search = ['.', ' ', ',']; |
||
82 | $value = str_replace($search, '', $value); |
||
83 | Log::debug(sprintf('No decimal character found. Converted amount from "%s" to "%s".', $original, $value)); |
||
84 | } |
||
85 | if (strpos($value, '.') === 0) { |
||
86 | $value = '0' . $value; |
||
87 | } |
||
88 | |||
89 | if (is_numeric($value)) { |
||
90 | Log::debug(sprintf('Final NUMERIC value is: "%s"', $value)); |
||
91 | |||
92 | return $value; |
||
93 | } |
||
94 | // @codeCoverageIgnoreStart |
||
95 | Log::debug(sprintf('Final value is: "%s"', $value)); |
||
96 | $formatted = sprintf('%01.12f', $value); |
||
97 | Log::debug(sprintf('Is formatted to : "%s"', $formatted)); |
||
98 | |||
99 | return $formatted; |
||
100 | // @codeCoverageIgnoreEnd |
||
101 | } |
||
102 | |||
103 | /** |
||
104 | * Check if the value has a dot or comma on an alternative place, |
||
105 | * catching strings like ",1" or ".5". |
||
106 | * |
||
107 | * @param string $value |
||
108 | * |
||
109 | * @return bool |
||
110 | */ |
||
111 | private function alternativeDecimalSign(string $value): bool |
||
112 | { |
||
113 | $length = strlen($value); |
||
114 | $altPosition = $length - 2; |
||
115 | |||
116 | return $length > 1 && ('.' === $value[$altPosition] || ',' === $value[$altPosition]); |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * Helper function to see if the decimal separator is a comma. |
||
121 | * |
||
122 | * @param string $value |
||
123 | * |
||
124 | * @return bool |
||
125 | */ |
||
126 | private function decimalIsComma(string $value): bool |
||
127 | { |
||
128 | $length = strlen($value); |
||
129 | $decimalPosition = $length - 3; |
||
130 | |||
131 | return $length > 2 && ',' === $value[$decimalPosition]; |
||
132 | } |
||
133 | |||
134 | /** |
||
135 | * Helper function to see if the decimal separator is a dot. |
||
136 | * |
||
137 | * @param string $value |
||
138 | * |
||
139 | * @return bool |
||
140 | */ |
||
141 | private function decimalIsDot(string $value): bool |
||
142 | { |
||
143 | $length = strlen($value); |
||
144 | $decimalPosition = $length - 3; |
||
145 | |||
146 | return ($length > 2 && '.' === $value[$decimalPosition]) || ($length > 2 && strpos($value, '.') > $decimalPosition); |
||
147 | } |
||
148 | |||
149 | /** |
||
150 | * Search from the left for decimal sign. |
||
151 | * |
||
152 | * @param string $value |
||
153 | * |
||
154 | * @return string |
||
155 | */ |
||
156 | private function findFromLeft(string $value): ?string |
||
157 | { |
||
158 | $decimal = null; |
||
159 | Log::debug('Decimal is still NULL, probably number with >2 decimals. Search for a dot.'); |
||
160 | $res = strrpos($value, '.'); |
||
161 | if (!(false === $res)) { |
||
162 | // blandly assume this is the one. |
||
163 | Log::debug(sprintf('Searched from the left for "." in amount "%s", assume this is the decimal sign.', $value)); |
||
164 | $decimal = '.'; |
||
165 | } |
||
166 | |||
167 | return $decimal; |
||
168 | } |
||
169 | |||
170 | /** |
||
171 | * Returns the alternative decimal point used, such as a dot or a comma, |
||
172 | * from strings like ",1" or "0.5". |
||
173 | * |
||
174 | * @param string $value |
||
175 | * |
||
176 | * @return string |
||
177 | */ |
||
178 | private function getAlternativeDecimalSign(string $value): string |
||
179 | { |
||
180 | $length = strlen($value); |
||
181 | $altPosition = $length - 2; |
||
182 | |||
183 | return $value[$altPosition]; |
||
184 | |||
185 | } |
||
186 | |||
187 | /** |
||
188 | * Replaces other characters like thousand separators with nothing to make the decimal separator the only special |
||
189 | * character in the string. |
||
190 | * |
||
191 | * @param string $decimal |
||
192 | * @param string $value |
||
193 | * |
||
194 | * @return string |
||
195 | */ |
||
196 | private function replaceDecimal(string $decimal, string $value): string |
||
197 | { |
||
198 | $search = [',', ' ']; // default when decimal sign is a dot. |
||
199 | if (',' === $decimal) { |
||
200 | $search = ['.', ' ']; |
||
201 | } |
||
202 | $value = str_replace($search, '', $value); |
||
203 | |||
204 | /** @noinspection CascadeStringReplacementInspection */ |
||
205 | $value = str_replace(',', '.', $value); |
||
206 | |||
207 | return $value; |
||
208 | } |
||
209 | |||
210 | /** |
||
211 | * Strip amount from weird characters. |
||
212 | * |
||
213 | * @param string $value |
||
214 | * |
||
215 | * @return string |
||
216 | */ |
||
217 | private function stripAmount(string $value): string |
||
218 | { |
||
219 | if (0 === strpos($value, '--')) { |
||
220 | $value = substr($value, 2); |
||
221 | } |
||
222 | // have to strip the € because apparantly the Postbank (DE) thinks "1.000,00 €" is a normal way to format a number. |
||
223 | $value = trim((string) str_replace(['€'], '', $value)); |
||
224 | $str = preg_replace('/[^\-\(\)\.\,0-9 ]/', '', $value); |
||
225 | $len = strlen($str); |
||
226 | if ('(' === $str[0] && ')' === $str[$len - 1]) { |
||
227 | $str = '-' . substr($str, 1, $len - 2); |
||
228 | } |
||
229 | |||
230 | Log::debug(sprintf('Stripped "%s" away to "%s"', $value, $str)); |
||
231 | |||
232 | return $str; |
||
233 | } |
||
234 | } |
||
235 |
This interface has been deprecated. The supplier of the interface has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the interface will be removed and what other interface to use instead.