PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
tablepress / libraries / vendor / PhpSpreadsheet / Calculation / Engine / FormattedNumber.php

FormattedNumber.php in TablePress – Tables in WordPress made easy 3.4, at libraries/vendor/PhpSpreadsheet/Calculation/Engine/FormattedNumber.php

140 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TablePress\PhpOffice\PhpSpreadsheet\Calculation\Engine;
4
5 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Calculation;
6 use TablePress\PhpOffice\PhpSpreadsheet\Shared\StringHelper;
7
8 class FormattedNumber
9 {
10 /** Constants */
11 /** Regular Expressions */
12 private const STRING_REGEXP_FRACTION = '~^\s*(-?)((\d*)\s+)?(\d+\/\d+)\s*$~';
13
14 private const STRING_REGEXP_PERCENT = '~^(?:(?: *(?<PrefixedSign>[-+])? *\% *(?<PrefixedSign2>[-+])? *(?<PrefixedValue>[0-9]+\.?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?<PostfixedSign>[-+])? *(?<PostfixedValue>[0-9]+\.?[0-9]*(?:E[-+]?[0-9]*)?) *\% *))$~i';
15
16 // preg_quoted string for major currency symbols, with a %s for locale currency
17 private const CURRENCY_CONVERSION_LIST = '\$€£¥%s';
18
19 /**
20 * Identify whether a string contains a formatted numeric value,
21 * and convert it to a numeric if it is.
22 *
23 * @param float|string $operand string value to test
24 */
25 public static function convertToNumberIfFormatted(&$operand): bool
26 {
27 return self::convertToNumberIfNumeric($operand)
28 || self::convertToNumberIfFraction($operand)
29 || self::convertToNumberIfPercent($operand)
30 || self::convertToNumberIfCurrency($operand);
31 }
32
33 /**
34 * Identify whether a string contains a numeric value,
35 * and convert it to a numeric if it is.
36 *
37 * @param float|string $operand string value to test
38 */
39 public static function convertToNumberIfNumeric(&$operand): bool
40 {
41 $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator(), '/');
42 $value = preg_replace(['/(\d)' . $thousandsSeparator . '(\d)/u', '/([+-])\s+(\d)/u'], ['$1$2', '$1$2'], trim("$operand"));
43 $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator(), '/');
44 $value = preg_replace(['/(\d)' . $decimalSeparator . '(\d)/u', '/([+-])\s+(\d)/u'], ['$1.$2', '$1$2'], $value ?? '');
45
46 if (is_numeric($value)) {
47 $operand = (float) $value;
48
49 return true;
50 }
51
52 return false;
53 }
54
55 /**
56 * Identify whether a string contains a fractional numeric value,
57 * and convert it to a numeric if it is.
58 *
59 * @param string $operand string value to test
60 */
61 public static function convertToNumberIfFraction(&$operand): bool
62 {
63 if (is_string($operand) && preg_match(self::STRING_REGEXP_FRACTION, $operand, $match)) {
64 $sign = ($match[1] === '-') ? '-' : '+';
65 $wholePart = ($match[3] === '') ? '' : ($sign . $match[3]);
66 $fractionFormula = '=' . $wholePart . $sign . $match[4];
67 /** @var string */
68 $operandx = Calculation::getInstance()->_calculateFormulaValue($fractionFormula);
69 $operand = $operandx;
70
71 return true;
72 }
73
74 return false;
75 }
76
77 /**
78 * Identify whether a string contains a percentage, and if so,
79 * convert it to a numeric.
80 *
81 * @param float|string $operand string value to test
82 */
83 public static function convertToNumberIfPercent(&$operand): bool
84 {
85 $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator(), '/');
86 $value = preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', trim("$operand"));
87 $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator(), '/');
88 $value = preg_replace(['/(\d)' . $decimalSeparator . '(\d)/u', '/([+-])\s+(\d)/u'], ['$1.$2', '$1$2'], $value ?? '');
89
90 $match = [];
91 if ($value !== null && preg_match(self::STRING_REGEXP_PERCENT, $value, $match, PREG_UNMATCHED_AS_NULL)) {
92 //Calculate the percentage
93 $sign = ($match['PrefixedSign'] ?? $match['PrefixedSign2'] ?? $match['PostfixedSign']) ?? '';
94 $operand = (float) ($sign . ($match['PostfixedValue'] ?? $match['PrefixedValue'])) / 100;
95
96 return true;
97 }
98
99 return false;
100 }
101
102 /**
103 * Identify whether a string contains a currency value, and if so,
104 * convert it to a numeric.
105 *
106 * @param float|string $operand string value to test
107 */
108 public static function convertToNumberIfCurrency(&$operand): bool
109 {
110 $currencyRegexp = self::currencyMatcherRegexp();
111 $thousandsSeparator = preg_quote(StringHelper::getThousandsSeparator(), '/');
112 $value = preg_replace('/(\d)' . $thousandsSeparator . '(\d)/u', '$1$2', "$operand");
113
114 $match = [];
115 if ($value !== null && preg_match($currencyRegexp, $value, $match, PREG_UNMATCHED_AS_NULL)) {
116 //Determine the sign
117 $sign = ($match['PrefixedSign'] ?? $match['PrefixedSign2'] ?? $match['PostfixedSign']) ?? '';
118 $decimalSeparator = StringHelper::getDecimalSeparator();
119 //Cast to a float
120 $intermediate = (string) ($match['PostfixedValue'] ?? $match['PrefixedValue']);
121 $intermediate = str_replace($decimalSeparator, '.', $intermediate);
122 if (is_numeric($intermediate)) {
123 $operand = (float) ($sign . str_replace($decimalSeparator, '.', $intermediate));
124
125 return true;
126 }
127 }
128
129 return false;
130 }
131
132 public static function currencyMatcherRegexp(): string
133 {
134 $currencyCodes = sprintf(self::CURRENCY_CONVERSION_LIST, preg_quote(StringHelper::getCurrencyCode(), '/'));
135 $decimalSeparator = preg_quote(StringHelper::getDecimalSeparator(), '/');
136
137 return '~^(?:(?: *(?<PrefixedSign>[-+])? *(?<PrefixedCurrency>[' . $currencyCodes . ']) *(?<PrefixedSign2>[-+])? *(?<PrefixedValue>[0-9]+[' . $decimalSeparator . ']?[0-9*]*(?:E[-+]?[0-9]*)?) *)|(?: *(?<PostfixedSign>[-+])? *(?<PostfixedValue>[0-9]+' . $decimalSeparator . '?[0-9]*(?:E[-+]?[0-9]*)?) *(?<PostfixedCurrency>[' . $currencyCodes . ']) *))$~ui';
138 }
139 }
140