[TASK] Update php-cs-fixer to 2.5.0
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Utility / MathUtility.php
1 <?php
2 namespace TYPO3\CMS\Core\Utility;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 /**
18 * Class with helper functions for mathematical calculations
19 */
20 class MathUtility
21 {
22 /**
23 * Forces the integer $theInt into the boundaries of $min and $max. If the $theInt is FALSE then the $defaultValue is applied.
24 *
25 * @param int $theInt Input value
26 * @param int $min Lower limit
27 * @param int $max Higher limit
28 * @param int $defaultValue Default value if input is FALSE.
29 * @return int The input value forced into the boundaries of $min and $max
30 */
31 public static function forceIntegerInRange($theInt, $min, $max = 2000000000, $defaultValue = 0)
32 {
33 // Returns $theInt as an integer in the integerspace from $min to $max
34 $theInt = (int)$theInt;
35 // If the input value is zero after being converted to integer,
36 // defaultValue may set another default value for it.
37 if ($defaultValue && !$theInt) {
38 $theInt = $defaultValue;
39 }
40 if ($theInt < $min) {
41 $theInt = $min;
42 }
43 if ($theInt > $max) {
44 $theInt = $max;
45 }
46 return $theInt;
47 }
48
49 /**
50 * Returns $theInt if it is greater than zero, otherwise returns zero.
51 *
52 * @param int $theInt Integer string to process
53 * @return int
54 */
55 public static function convertToPositiveInteger($theInt)
56 {
57 $theInt = (int)$theInt;
58 if ($theInt < 0) {
59 $theInt = 0;
60 }
61 return $theInt;
62 }
63
64 /**
65 * Tests if the input can be interpreted as integer.
66 *
67 * Note: Integer casting from objects or arrays is considered undefined and thus will return false.
68 *
69 * @see http://php.net/manual/en/language.types.integer.php#language.types.integer.casting.from-other
70 * @param mixed $var Any input variable to test
71 * @return bool Returns TRUE if string is an integer
72 */
73 public static function canBeInterpretedAsInteger($var)
74 {
75 if ($var === '' || is_object($var) || is_array($var)) {
76 return false;
77 }
78 return (string)(int)$var === (string)$var;
79 }
80
81 /**
82 * Tests if the input can be interpreted as float.
83 *
84 * Note: Float casting from objects or arrays is considered undefined and thus will return false.
85 *
86 * @see http://www.php.net/manual/en/language.types.float.php, section "Formally" for the notation
87 * @param mixed $var Any input variable to test
88 * @return bool Returns TRUE if string is a float
89 */
90 public static function canBeInterpretedAsFloat($var)
91 {
92 $pattern_lnum = '[0-9]+';
93 $pattern_dnum = '([0-9]*[\.]' . $pattern_lnum . ')|(' . $pattern_lnum . '[\.][0-9]*)';
94 $pattern_exp_dnum = '[+-]?((' . $pattern_lnum . '|' . $pattern_dnum . ')([eE][+-]?' . $pattern_lnum . ')?)';
95
96 if ($var === '' || is_object($var) || is_array($var)) {
97 return false;
98 }
99
100 $matches = preg_match('/^' . $pattern_exp_dnum . '$/', $var);
101 return $matches === 1;
102 }
103
104 /**
105 * Calculates the input by +,-,*,/,%,^ with priority to + and -
106 *
107 * @param string $string Input string, eg "123 + 456 / 789 - 4
108 * @return int Calculated value. Or error string.
109 * @see \TYPO3\CMS\Core\Utility\MathUtility::calculateWithParentheses()
110 */
111 public static function calculateWithPriorityToAdditionAndSubtraction($string)
112 {
113 // Removing all whitespace
114 $string = preg_replace('/[[:space:]]*/', '', $string);
115 // Ensuring an operator for the first entrance
116 $string = '+' . $string;
117 $qm = '\\*\\/\\+-^%';
118 $regex = '([' . $qm . '])([' . $qm . ']?[0-9\\.]*)';
119 // Split the expression here:
120 $reg = [];
121 preg_match_all('/' . $regex . '/', $string, $reg);
122 reset($reg[2]);
123 $number = 0;
124 $Msign = '+';
125 $err = '';
126 $buffer = (float)current($reg[2]);
127 // Advance pointer
128 $regSliced = array_slice($reg[2], 1, null, true);
129 foreach ($regSliced as $k => $v) {
130 $v = (float)$v;
131 $sign = $reg[1][$k];
132 if ($sign === '+' || $sign === '-') {
133 $Msign === '-' ? ($number -= $buffer) : ($number += $buffer);
134 $Msign = $sign;
135 $buffer = $v;
136 } else {
137 if ($sign === '/') {
138 if ($v) {
139 $buffer /= $v;
140 } else {
141 $err = 'dividing by zero';
142 }
143 }
144 if ($sign === '%') {
145 if ($v) {
146 $buffer %= $v;
147 } else {
148 $err = 'dividing by zero';
149 }
150 }
151 if ($sign === '*') {
152 $buffer *= $v;
153 }
154 if ($sign === '^') {
155 $buffer = pow($buffer, $v);
156 }
157 }
158 }
159 $number = $Msign === '-' ? ($number -= $buffer) : ($number += $buffer);
160 return $err ? 'ERROR: ' . $err : $number;
161 }
162
163 /**
164 * Calculates the input with parenthesis levels
165 *
166 * @param string $string Input string, eg "(123 + 456) / 789 - 4
167 * @return int Calculated value. Or error string.
168 * @see calculateWithPriorityToAdditionAndSubtraction(), \TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer::stdWrap()
169 */
170 public static function calculateWithParentheses($string)
171 {
172 $securC = 100;
173 do {
174 $valueLenO = strcspn($string, '(');
175 $valueLenC = strcspn($string, ')');
176 if ($valueLenC == strlen($string) || $valueLenC < $valueLenO) {
177 $value = self::calculateWithPriorityToAdditionAndSubtraction(substr($string, 0, $valueLenC));
178 $string = $value . substr($string, ($valueLenC + 1));
179 return $string;
180 }
181 $string = substr($string, 0, $valueLenO) . self::calculateWithParentheses(substr($string, ($valueLenO + 1)));
182
183 // Security:
184 $securC--;
185 if ($securC <= 0) {
186 break;
187 }
188 } while ($valueLenO < strlen($string));
189 return $string;
190 }
191
192 /**
193 * Checks whether the given number $value is an integer in the range [$minimum;$maximum]
194 *
195 * @param int $value Integer value to check
196 * @param int $minimum Lower boundary of the range
197 * @param int $maximum Upper boundary of the range
198 * @return bool
199 */
200 public static function isIntegerInRange($value, $minimum, $maximum)
201 {
202 $value = filter_var($value, FILTER_VALIDATE_INT, [
203 'options' => [
204 'min_range' => $minimum,
205 'max_range' => $maximum
206 ]
207 ]);
208 $isInRange = is_int($value);
209 return $isInRange;
210 }
211 }