0a9d6b78a0bc6797e357eaafa91e6e0299cf6023
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Utility / MathUtility.php
1 <?php
2 namespace TYPO3\CMS\Core\Utility;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2011 Susanne Moog <typo3@susanne-moog.de>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * Class with helper functions for mathematical calculations
31 *
32 * @author Susanne Moog <typo3@susanne-moog.de>
33 * @package TYPO3
34 * @subpackage t3lib
35 */
36 final class MathUtility {
37
38 /**
39 * Forces the integer $theInt into the boundaries of $min and $max. If the $theInt is FALSE then the $defaultValue is applied.
40 *
41 * @param integer $theInt Input value
42 * @param integer $min Lower limit
43 * @param integer $max Higher limit
44 * @param integer $defaultValue Default value if input is FALSE.
45 * @return integer The input value forced into the boundaries of $min and $max
46 */
47 static public function forceIntegerInRange($theInt, $min, $max = 2000000000, $defaultValue = 0) {
48 // Returns $theInt as an integer in the integerspace from $min to $max
49 $theInt = intval($theInt);
50 // If the input value is zero after being converted to integer,
51 // defaultValue may set another default value for it.
52 if ($defaultValue && !$theInt) {
53 $theInt = $defaultValue;
54 }
55 if ($theInt < $min) {
56 $theInt = $min;
57 }
58 if ($theInt > $max) {
59 $theInt = $max;
60 }
61 return $theInt;
62 }
63
64 /**
65 * Returns $theInt if it is greater than zero, otherwise returns zero.
66 *
67 * @param integer $theInt Integer string to process
68 * @return integer
69 */
70 static public function convertToPositiveInteger($theInt) {
71 $theInt = intval($theInt);
72 if ($theInt < 0) {
73 $theInt = 0;
74 }
75 return $theInt;
76 }
77
78 /**
79 * Tests if the input can be interpreted as integer.
80 *
81 * Note: Integer casting from objects or arrays is considered undefined and thus will return false.
82 *
83 * @see http://php.net/manual/en/language.types.integer.php#language.types.integer.casting.from-other
84 * @param mixed $var Any input variable to test
85 * @return boolean Returns TRUE if string is an integer
86 */
87 static public function canBeInterpretedAsInteger($var) {
88 if ($var === '' || is_object($var) || is_array($var)) {
89 return FALSE;
90 }
91 return (string) intval($var) === (string) $var;
92 }
93
94 /**
95 * Calculates the input by +,-,*,/,%,^ with priority to + and -
96 *
97 * @param string $string Input string, eg "123 + 456 / 789 - 4
98 * @return integer Calculated value. Or error string.
99 * @see t3lib_utility_Math::calculateWithParentheses()
100 */
101 static public function calculateWithPriorityToAdditionAndSubtraction($string) {
102 // Removing all whitespace
103 $string = preg_replace('/[[:space:]]*/', '', $string);
104 // Ensuring an operator for the first entrance
105 $string = '+' . $string;
106 $qm = '\\*\\/\\+-^%';
107 $regex = '([' . $qm . '])([' . $qm . ']?[0-9\\.]*)';
108 // Split the expression here:
109 $reg = array();
110 preg_match_all('/' . $regex . '/', $string, $reg);
111 reset($reg[2]);
112 $number = 0;
113 $Msign = '+';
114 $err = '';
115 $buffer = doubleval(current($reg[2]));
116 // Advance pointer
117 next($reg[2]);
118 while (list($k, $v) = each($reg[2])) {
119 $v = doubleval($v);
120 $sign = $reg[1][$k];
121 if ($sign == '+' || $sign == '-') {
122 $Msign == '-' ? ($number -= $buffer) : ($number += $buffer);
123 $Msign = $sign;
124 $buffer = $v;
125 } else {
126 if ($sign == '/') {
127 if ($v) {
128 $buffer /= $v;
129 } else {
130 $err = 'dividing by zero';
131 }
132 }
133 if ($sign == '%') {
134 if ($v) {
135 $buffer %= $v;
136 } else {
137 $err = 'dividing by zero';
138 }
139 }
140 if ($sign == '*') {
141 $buffer *= $v;
142 }
143 if ($sign == '^') {
144 $buffer = pow($buffer, $v);
145 }
146 }
147 }
148 $number = $Msign == '-' ? ($number -= $buffer) : ($number += $buffer);
149 return $err ? 'ERROR: ' . $err : $number;
150 }
151
152 /**
153 * Calculates the input with parenthesis levels
154 *
155 * @param string $string Input string, eg "(123 + 456) / 789 - 4
156 * @return integer Calculated value. Or error string.
157 * @see calculateWithPriorityToAdditionAndSubtraction(), tslib_cObj::stdWrap()
158 */
159 static public function calculateWithParentheses($string) {
160 $securC = 100;
161 do {
162 $valueLenO = strcspn($string, '(');
163 $valueLenC = strcspn($string, ')');
164 if ($valueLenC == strlen($string) || $valueLenC < $valueLenO) {
165 $value = self::calculateWithPriorityToAdditionAndSubtraction(substr($string, 0, $valueLenC));
166 $string = $value . substr($string, ($valueLenC + 1));
167 return $string;
168 } else {
169 $string = substr($string, 0, $valueLenO) . self::calculateWithParentheses(substr($string, ($valueLenO + 1)));
170 }
171 // Security:
172 $securC--;
173 if ($securC <= 0) {
174 break;
175 }
176 } while ($valueLenO < strlen($string));
177 return $string;
178 }
179
180 /**
181 * Checks whether the given number $value is an integer in the range [$minimum;$maximum]
182 *
183 * @param integer $value Integer value to check
184 * @param integer $minimum Lower boundary of the range
185 * @param integer $maximum Upper boundary of the range
186 * @return boolean
187 */
188 static public function isIntegerInRange($value, $minimum, $maximum) {
189 $value = filter_var($value, FILTER_VALIDATE_INT, array(
190 'options' => array(
191 'min_range' => $minimum,
192 'max_range' => $maximum
193 )
194 ));
195 $isInRange = is_int($value);
196 return $isInRange;
197 }
198
199 }
200
201
202 ?>