PluginProbe
TablePress – Tables in WordPress made easy / 3.0
TablePress – Tables in WordPress made easy v3.0
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 2.4.4 All 44 releases
← All changes | libraries/evalmath.class.php +257 -226 1.9.23.0 View file →
@@ -1,11 +1,12 @@
1 1 <?php
2 2 /**
3 - * EvalMath - Safely evaluate math expressions
3 + * EvalMath - Safely evaluate math expressions.
4 4 *
5 5 * Based on EvalMath by Miles Kaufmann, with modifications by Petr Skoda.
6 - * @link https://github.com/moodle/moodle/blob/4efc3d4096bc1d29e9d77f9af7194b2babfa2821/lib/evalmath/evalmath.class.php
7 6 *
7 + * @link https://github.com/moodle/moodle/blob/master/lib/evalmath/evalmath.class.php
8 + *
8 9 * @package TablePress
9 10 * @subpackage Formulas
10 11 * @author Miles Kaufmann, Petr Skoda, Tobias Bäthge
11 12 * @since 1.0.0
@@ -15,8 +16,9 @@
15 16 defined( 'ABSPATH' ) || die( 'No direct script access allowed!' );
16 17
17 18 /**
18 19 * Class to safely evaluate math expressions.
20 + *
19 21 * @package TablePress
20 22 * @subpackage Formulas
21 23 * @since 1.0.0
22 24 */
@@ -24,66 +26,84 @@
24 26
25 27 /**
26 28 * Pattern used for a valid function or variable name.
27 29 *
28 - * Note, var and func names are case insensitive.
30 + * Note, variable and function names are case insensitive.
29 31 *
30 32 * @since 1.0.0
31 - * @var string
32 33 */
33 - protected static $name_pattern = '[a-z][a-z0-9_]*';
34 + protected static string $name_pattern = '[a-z][a-z0-9_]*';
34 35
35 36 /**
36 37 * Whether to suppress errors and warnings.
37 38 *
38 39 * @since 1.0.0
39 - * @var boolean
40 40 */
41 - public $suppress_errors = false;
41 + public bool $suppress_errors = false;
42 42
43 43 /**
44 44 * The last error message that was raised.
45 45 *
46 46 * @since 1.0.0
47 - * @var string
48 47 */
49 - public $last_error = '';
48 + public string $last_error = '';
50 49
51 50 /**
52 51 * Variables (including constants).
53 52 *
54 53 * @since 1.0.0
55 - * @var array
54 + * @var array<string, mixed>
56 55 */
57 - protected $variables = array();
56 + public array $variables = array();
58 57
59 58 /**
60 59 * User-defined functions.
61 60 *
62 61 * @since 1.0.0
63 - * @var array
62 + * @var array<string, mixed>
64 63 */
65 - protected $functions = array();
64 + protected array $functions = array();
66 65
67 66 /**
68 67 * Constants.
69 68 *
70 69 * @since 1.0.0
71 - * @var array
70 + * @var array<string, mixed>
72 71 */
73 - protected $constants = array();
72 + protected array $constants = array();
74 73
75 74 /**
76 75 * Built-in functions.
77 76 *
78 77 * @since 1.0.0
79 - * @var array
78 + * @var string[]
80 79 */
81 - protected $builtin_functions = array(
82 - 'sin', 'sinh', 'arcsin', 'asin', 'arcsinh', 'asinh',
83 - 'cos', 'cosh', 'arccos', 'acos', 'arccosh', 'acosh',
84 - 'tan', 'tanh', 'arctan', 'atan', 'arctanh', 'atanh',
85 - 'sqrt', 'abs', 'ln', 'log10', 'exp', 'floor', 'ceil',
80 + protected array $builtin_functions = array(
81 + 'sin',
82 + 'sinh',
83 + 'arcsin',
84 + 'asin',
85 + 'arcsinh',
86 + 'asinh',
87 + 'cos',
88 + 'cosh',
89 + 'arccos',
90 + 'acos',
91 + 'arccosh',
92 + 'acosh',
93 + 'tan',
94 + 'tanh',
95 + 'arctan',
96 + 'atan',
97 + 'arctanh',
98 + 'atanh',
99 + 'sqrt',
100 + 'abs',
101 + 'ln',
102 + 'log10',
103 + 'exp',
104 + 'floor',
105 + 'ceil',
86 106 );
87 107
88 108 /**
89 109 * Emulated functions.
@@ -88,35 +108,36 @@
88 108 /**
89 109 * Emulated functions.
90 110 *
91 111 * @since 1.0.0
92 - * @var array
112 + * @var array<string, int[]>
93 113 */
94 - protected $calc_functions = array(
95 - 'average' => array( -1 ),
96 - 'mean' => array( -1 ),
97 - 'median' => array( -1 ),
98 - 'mode' => array( -1 ),
99 - 'range' => array( -1 ),
100 - 'max' => array( -1 ),
101 - 'min' => array( -1 ),
102 - 'mod' => array( 2 ),
103 - 'pi' => array( 0 ),
104 - 'power' => array( 2 ),
105 - 'log' => array( 1, 2 ),
106 - 'round' => array( 1, 2 ),
107 - 'number_format' => array( 1, 2 ),
114 + protected array $calc_functions = array(
115 + 'average' => array( -1 ),
116 + 'mean' => array( -1 ),
117 + 'median' => array( -1 ),
118 + 'mode' => array( -1 ),
119 + 'range' => array( -1 ),
120 + 'max' => array( -1 ),
121 + 'min' => array( -1 ),
122 + 'mod' => array( 2 ),
123 + 'pi' => array( 0 ),
124 + 'power' => array( 2 ),
125 + 'log' => array( 1, 2 ),
126 + 'round' => array( 1, 2 ),
127 + 'number_format' => array( 1, 2 ),
108 128 'number_format_eu' => array( 1, 2 ),
109 - 'sum' => array( -1 ),
110 - 'product' => array( -1 ),
111 - 'rand_int' => array( 2 ),
112 - 'rand_float' => array( 0 ),
113 - 'arctan2' => array( 2 ),
114 - 'atan2' => array( 2 ),
115 - 'if' => array( 3 ),
116 - 'not' => array( 1 ),
117 - 'and' => array( -1 ),
118 - 'or' => array( -1 ),
129 + 'sum' => array( -1 ),
130 + 'counta' => array( -1 ),
131 + 'product' => array( -1 ),
132 + 'rand_int' => array( 2 ),
133 + 'rand_float' => array( 0 ),
134 + 'arctan2' => array( 2 ),
135 + 'atan2' => array( 2 ),
136 + 'if' => array( 3 ),
137 + 'not' => array( 1 ),
138 + 'and' => array( -1 ),
139 + 'or' => array( -1 ),
119 140 );
120 141
121 142 /**
122 143 * Class constructor.
@@ -123,9 +144,9 @@
123 144 *
124 145 * @since 1.0.0
125 146 */
126 147 public function __construct() {
127 - // Sets default constants.
148 + // Set default constants.
128 149 $this->variables['pi'] = pi();
129 150 $this->variables['e'] = exp( 1 );
130 151 }
131 152
@@ -134,16 +155,16 @@
134 155 *
135 156 * @since 1.0.0
136 157 *
137 158 * @param string $expression The expression that shall be evaluated.
138 - * @return string Evaluated expression.
159 + * @return string|false Evaluated expression or false on error.
139 160 */
140 - public function evaluate( $expression ) {
161 + public function evaluate( $expression ) /* : string|false */ {
141 162 return $this->pfx( $this->nfx( $expression ) );
142 163 }
143 164
144 165 /**
145 - * Evaluate a math expression or formula, and check it for variable an function assignments.
166 + * Evaluate a math expression or formula, and check it for variable and function assignments.
146 167 *
147 168 * @since 1.0.0
148 169 *
149 170 * @param string $expression The expression that shall be evaluated.
@@ -148,9 +169,9 @@
148 169 *
149 170 * @param string $expression The expression that shall be evaluated.
150 171 * @return string|bool Evaluated expression, true on successful function assignment, or false on error.
151 172 */
152 - public function assign_and_evaluate( $expression ) {
173 + public function assign_and_evaluate( $expression ) /* : string|bool */ {
153 174 $this->last_error = '';
154 175 $expression = trim( $expression );
155 176 $expression = rtrim( $expression, ';' );
156 177
@@ -161,17 +182,17 @@
161 182 return $this->raise_error( 'cannot_assign_to_constant', $matches[1] );
162 183 }
163 184 // Evaluate the assignment.
164 185 $tmp = $this->pfx( $this->nfx( $matches[2] ) );
165 - if ( fales === $tmp ) {
186 + if ( false === $tmp ) {
166 187 return false;
167 188 }
168 - // If it could be evaluated, add it to the variable array,
189 + // If it could be evaluated, add it to the variable array, ...
169 190 $this->variables[ $matches[1] ] = $tmp;
170 - // and return the resulting value.
191 + // ... and return the resulting value.
171 192 return $tmp;
172 193
173 - // Is the expression a function assignment?
194 + // Is the expression a function assignment?
174 195 } elseif ( 1 === preg_match( '/^\s*(' . self::$name_pattern . ')\s*\(\s*(' . self::$name_pattern . '(?:\s*,\s*' . self::$name_pattern . ')*)\s*\)\s*=\s*(.+)$/', $expression, $matches ) ) {
175 196 // Get the function name.
176 197 $function_name = $matches[1];
177 198 // Make sure it isn't a built-in function -- we can't redefine those.
@@ -187,9 +208,10 @@
187 208 if ( false === $stack ) {
188 209 return false;
189 210 }
190 211 // Freeze the state of the non-argument variables.
191 - for ( $i = 0; $i < count( $stack ); $i++ ) {
212 + $stack_count = count( $stack );
213 + for ( $i = 0; $i < $stack_count; $i++ ) {
192 214 $token = $stack[ $i ];
193 215 if ( 1 === preg_match( '/^' . self::$name_pattern . '$/', $token ) && ! in_array( $token, $args, true ) ) {
194 216 if ( array_key_exists( $token, $this->variables ) ) {
195 217 $stack[ $i ] = $this->variables[ $token ];
@@ -200,9 +222,9 @@
200 222 }
201 223 $this->functions[ $function_name ] = array( 'args' => $args, 'func' => $stack );
202 224 return true;
203 225
204 - // No variable or function assignment, so straight-up evaluation.
226 + // No variable or function assignment, so straight-up evaluation.
205 227 } else {
206 228 return $this->evaluate( $expression );
207 229 }
208 230 }
@@ -211,11 +233,11 @@
211 233 * Return all user-defined variables and values.
212 234 *
213 235 * @since 1.0.0
214 236 *
215 - * @return array User-defined variables and values.
237 + * @return array<string, mixed> User-defined variables and values.
216 238 */
217 - public function variables() {
239 + public function variables(): array {
218 240 return $this->variables;
219 241 }
220 242
221 243 /**
@@ -222,11 +244,11 @@
222 244 * Return all user-defined functions with their arguments.
223 245 *
224 246 * @since 1.0.0
225 247 *
226 - * @return array User-defined functions.
248 + * @return array<int, string> User-defined functions.
227 249 */
228 - public function functions() {
250 + public function functions(): array {
229 251 $output = array();
230 252 foreach ( $this->functions as $name => $data ) {
231 253 $output[] = $name . '( ' . implode( ', ', $data['args'] ) . ' )';
232 254 }
@@ -242,27 +264,25 @@
242 264 *
243 265 * @since 1.0.0
244 266 *
245 267 * @param string $expression Math expression that shall be converted.
246 - * @return array|false Converted expression or false on error.
268 + * @return mixed[]|false Converted expression or false on error.
247 269 */
248 - protected function nfx( $expression ) {
270 + protected function nfx( $expression ) /* : mixed[]|false */ {
249 271 $index = 0;
250 - $stack = new EvalMath_Stack;
251 - $output = array(); // postfix form of expression, to be passed to pfx()
272 + $stack = new EvalMath_Stack();
273 + $output = array(); // postfix form of expression, to be passed to pfx().
252 274 $expression = trim( strtolower( $expression ) );
253 275
254 - $ops = array( '+', '-', '*', '/', '^', '_', '>', '<', '=' );
255 - // Right-associative operator?
256 - $ops_r = array( '+' => 0, '-' => 0, '*' => 0, '/' => 0, '^' => 1, '>' => 0, '<' => 0, '=' => 0 );
257 - // Operator precedence.
258 - $ops_p = array( '+' => 0, '-' => 0, '*' => 1, '/' => 1, '_' => 1, '^' => 2, '>' => 0, '<' => 0, '=' => 0 );
276 + $ops = array( '+', '-', '*', '/', '^', '_', '>', '<', '=', '%' );
277 + $ops_r = array( '+' => 0, '-' => 0, '*' => 0, '/' => 0, '^' => 1, '>' => 0, '<' => 0, '=' => 0, '%' => 0 ); // Right-associative operator?
278 + $ops_p = array( '+' => 0, '-' => 0, '*' => 1, '/' => 1, '_' => 1, '^' => 2, '>' => 0, '<' => 0, '=' => 0, '%' => 1 ); // Operator precedence.
259 279
260 280 // We use this in syntax-checking the expression and determining when a - (minus) is a negation.
261 281 $expecting_operator = false;
262 282
263 283 // Make sure the characters are all good.
264 - if ( 1 === preg_match( '/[^\w\s+*^\/()\.,-<>=]/', $expression, $matches ) ) {
284 + if ( 1 === preg_match( '/[^\%\w\s+*^\/()\.,-<>=]/', $expression, $matches ) ) {
265 285 return $this->raise_error( 'illegal_character_general', $matches[0] );
266 286 }
267 287
268 288 // Infinite Loop for the conversion.
@@ -275,34 +295,36 @@
275 295 // Is it a negation instead of a minus (in a subtraction)?
276 296 if ( '-' === $op && ! $expecting_operator ) {
277 297 // Put a negation on the stack.
278 298 $stack->push( '_' );
279 - $index++;
299 + ++$index;
280 300 } elseif ( '_' === $op ) {
281 301 // We have to explicitly deny underscores (as they mean negation), because they are legal on the stack.
282 302 return $this->raise_error( 'illegal_character_underscore' );
283 303
284 - // Are we putting an operator on the stack?
304 + // Are we putting an operator on the stack?
285 305 } elseif ( ( in_array( $op, $ops, true ) || $ex ) && $expecting_operator ) {
286 306 // Are we expecting an operator but have a number/variable/function/opening parethesis?
287 307 if ( $ex ) {
288 308 // It's an implicit multiplication.
289 309 $op = '*';
290 - $index--;
310 + --$index;
291 311 }
292 - // Heart of the algorithm:
312 + // Heart of the algorithm: .
313 + // phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
293 314 while ( $stack->count > 0 && ( $o2 = $stack->last() ) && in_array( $o2, $ops, true ) && ( $ops_r[ $op ] ? $ops_p[ $op ] < $ops_p[ $o2 ] : $ops_p[ $op ] <= $ops_p[ $o2 ] ) ) {
294 315 // Pop stuff off the stack into the output.
295 316 $output[] = $stack->pop();
296 317 }
297 - // Many thanks: https://en.wikipedia.org/wiki/Reverse_Polish_notation
298 - $stack->push( $op ); // finally put OUR operator onto the stack
299 - $index++;
318 + // Many thanks: https://en.wikipedia.org/wiki/Reverse_Polish_notation .
319 + $stack->push( $op ); // Finally put OUR operator onto the stack.
320 + ++$index;
300 321 $expecting_operator = false;
301 322
302 - // Ready to close a parenthesis?
323 + // Ready to close a parenthesis?
303 324 } elseif ( ')' === $op && $expecting_operator ) {
304 325 // Pop off the stack back to the last (.
326 + // phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
305 327 while ( '(' !== ( $o2 = $stack->pop() ) ) {
306 328 if ( is_null( $o2 ) ) {
307 329 return $this->raise_error( 'unexpected_closing_bracket' );
308 330 } else {
@@ -310,20 +332,20 @@
310 332 }
311 333 }
312 334
313 335 // Did we just close a function?
314 - if ( 1 === preg_match( '/^(' . self::$name_pattern . ')\($/', $stack->last( 2 ), $matches ) ) {
336 + if ( 1 === preg_match( '/^(' . self::$name_pattern . ')\($/', (string) $stack->last( 2 ), $matches ) ) {
315 337 // Get the function name.
316 338 $function_name = $matches[1];
317 339 // See how many arguments there were (cleverly stored on the stack, thank you).
318 340 $arg_count = $stack->pop();
319 - $fn = $stack->pop();
341 + $stack->pop(); // $fn
320 342 // Send function to output.
321 343 $output[] = array( 'function_name' => $function_name, 'arg_count' => $arg_count );
322 344 // Check the argument count, depending on what type of function we have.
323 345 if ( in_array( $function_name, $this->builtin_functions, true ) ) {
324 346 // Built-in functions.
325 - if ( $arg_count > 1 ) {
347 + if ( $arg_count > 1 ) { // @phpstan-ignore greater.alwaysFalse
326 348 $error_data = array( 'expected' => 1, 'given' => $arg_count );
327 349 return $this->raise_error( 'wrong_number_of_arguments', $error_data );
328 350 }
329 351 } elseif ( array_key_exists( $function_name, $this->calc_functions ) ) {
@@ -328,17 +350,18 @@
328 350 }
329 351 } elseif ( array_key_exists( $function_name, $this->calc_functions ) ) {
330 352 // Calc-emulation functions.
331 353 $counts = $this->calc_functions[ $function_name ];
332 - if ( in_array( -1, $counts, true ) && $arg_count > 0 ) {
354 + // @phpstan-ignore greater.alwaysFalse, booleanAnd.alwaysFalse
355 + if ( in_array( -1, $counts, true ) && $arg_count > 0 ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedIf
333 356 // Everything is fine, we expected an indefinite number arguments and got some.
334 - } elseif ( ! in_array( $arg_count, $counts, true ) ) {
357 + } elseif ( ! in_array( $arg_count, $counts, true ) ) { // @phpstan-ignore function.impossibleType
335 358 $error_data = array( 'expected' => implode( '/', $this->calc_functions[ $function_name ] ), 'given' => $arg_count );
336 359 return $this->raise_error( 'wrong_number_of_arguments', $error_data );
337 360 }
338 361 } elseif ( array_key_exists( $function_name, $this->functions ) ) {
339 362 // User-defined functions.
340 - if ( count( $this->functions[ $function_name ]['args'] ) !== $arg_count ) {
363 + if ( count( $this->functions[ $function_name ]['args'] ) !== $arg_count ) { // @phpstan-ignore notIdentical.alwaysTrue
341 364 $error_data = array( 'expected' => count( $this->functions[ $function_name ]['args'] ), 'given' => $arg_count );
342 365 return $this->raise_error( 'wrong_number_of_arguments', $error_data );
343 366 }
344 367 } else {
@@ -345,12 +368,13 @@
345 368 // Did we somehow push a non-function on the stack? This should never happen.
346 369 return $this->raise_error( 'internal_error' );
347 370 }
348 371 }
349 - $index++;
372 + ++$index;
350 373
351 - // Did we just finish a function argument?
374 + // Did we just finish a function argument?
352 375 } elseif ( ',' === $op && $expecting_operator ) {
376 + // phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
353 377 while ( '(' !== ( $o2 = $stack->pop() ) ) {
354 378 if ( is_null( $o2 ) ) {
355 379 // Oops, never had a (.
356 380 return $this->raise_error( 'unexpected_comma' );
@@ -359,23 +383,23 @@
359 383 $output[] = $o2;
360 384 }
361 385 }
362 386 // Make sure there was a function.
363 - if ( 0 === preg_match( '/^(' . self::$name_pattern . ')\($/', $stack->last( 2 ), $matches ) ) {
387 + if ( 0 === preg_match( '/^(' . self::$name_pattern . ')\($/', (string) $stack->last( 2 ), $matches ) ) {
364 388 return $this->raise_error( 'unexpected_comma' );
365 389 }
366 390 // Increment the argument count.
367 - $stack->push( $stack->pop() + 1 );
391 + $stack->push( $stack->pop() + 1 ); // @phpstan-ignore binaryOp.invalid
368 392 // Put the ( back on, we'll need to pop back to it again.
369 393 $stack->push( '(' );
370 - $index++;
394 + ++$index;
371 395 $expecting_operator = false;
372 396
373 397 } elseif ( '(' === $op && ! $expecting_operator ) {
374 398 $stack->push( '(' ); // That was easy.
375 - $index++;
399 + ++$index;
376 400
377 - // Do we now have a function/variable/number?
401 + // Do we now have a function/variable/number?
378 402 } elseif ( $ex && ! $expecting_operator ) {
379 403 $expecting_operator = true;
380 404 $value = $match[1];
381 405 // May be a function, or variable with implicit multiplication against parentheses...
@@ -385,9 +409,9 @@
385 409 $stack->push( $value );
386 410 $stack->push( 1 );
387 411 $stack->push( '(' );
388 412 $expecting_operator = false;
389 - // It's a variable with implicit multiplication.
413 + // It's a variable with implicit multiplication.
390 414 } else {
391 415 $value = $matches[1];
392 416 $output[] = $value;
393 417 }
@@ -402,12 +426,12 @@
402 426 if ( '(' !== $stack->last() || 1 !== $stack->last( 2 ) ) {
403 427 return $this->raise_error( 'unexpected_closing_bracket' );
404 428 }
405 429 // Did we just close a function?
406 - if ( 1 === preg_match( '/^(' . self::$name_pattern . ')\($/', $stack->last( 3 ), $matches ) ) {
430 + if ( 1 === preg_match( '/^(' . self::$name_pattern . ')\($/', (string) $stack->last( 3 ), $matches ) ) {
407 431 $stack->pop(); // (
408 432 $stack->pop(); // 1
409 - $fn = $stack->pop();
433 + $stack->pop(); // $fn
410 434 // Get the function name.
411 435 $function_name = $matches[1];
412 436 if ( isset( $this->calc_functions[ $function_name ] ) ) {
413 437 // Custom calc-emulation function.
@@ -421,19 +445,19 @@
421 445 return $this->raise_error( 'wrong_number_of_arguments', $error_data );
422 446 }
423 447 // Send function to output.
424 448 $output[] = array( 'function_name' => $function_name, 'arg_count' => 0 );
425 - $index++;
449 + ++$index;
426 450 $expecting_operator = true;
427 451 } else {
428 452 return $this->raise_error( 'unexpected_closing_bracket' );
429 453 }
430 454
431 - // Miscellaneous error checking.
455 + // Miscellaneous error checking.
432 456 } elseif ( in_array( $op, $ops, true ) && ! $expecting_operator ) {
433 457 return $this->raise_error( 'unexpected_operator', $op );
434 458
435 - // I don't even want to know what you did to get here.
459 + // I don't even want to know what you did to get here.
436 460 } else {
437 461 return $this->raise_error( 'an_unexpected_error_occurred' );
438 462 }
439 463
@@ -447,13 +471,14 @@
447 471 }
448 472
449 473 // Step the index past whitespace (pretty much turns whitespace into implicit multiplication if no operator is there).
450 474 while ( ' ' === substr( $expression, $index, 1 ) ) {
451 - $index++;
475 + ++$index;
452 476 }
453 477 } // while ( true )
454 478
455 479 // Pop everything off the stack and push onto output.
480 + // phpcs:ignore Generic.CodeAnalysis.AssignmentInCondition.FoundInWhileCondition
456 481 while ( ! is_null( $op = $stack->pop() ) ) {
457 482 if ( '(' === $op ) {
458 483 // If there are (s on the stack, ()s were unbalanced.
459 484 return $this->raise_error( 'expecting_a_closing_bracket' );
@@ -468,18 +493,18 @@
468 493 * Evaluate postfix notation.
469 494 *
470 495 * @since 1.0.0
471 496 *
472 - * @param array|false $tokens [description]
473 - * @param array $variables Optional. [description]
474 - * @return mixed [description]
497 + * @param array<int, string|mixed[]>|false $tokens [description].
498 + * @param array<string, mixed> $variables Optional. [description].
499 + * @return mixed [description].
475 500 */
476 - protected function pfx( $tokens, array $variables = array() ) {
501 + protected function pfx( $tokens, array $variables = array() ) /* : mixed */ {
477 502 if ( false === $tokens ) {
478 503 return false;
479 504 }
480 505
481 - $stack = new EvalMath_Stack;
506 + $stack = new EvalMath_Stack();
482 507
483 508 foreach ( $tokens as $token ) {
484 509 // If the token is a function, pop arguments off the stack, hand them to the function, and push the result back on.
485 510 if ( is_array( $token ) ) { // it's a function!
@@ -485,10 +510,11 @@
485 510 if ( is_array( $token ) ) { // it's a function!
486 511 $function_name = $token['function_name'];
487 512 $count = $token['arg_count'];
488 513
489 - // Built-in function.
490 514 if ( in_array( $function_name, $this->builtin_functions, true ) ) {
515 + // Built-in function.
516 +
491 517 $op1 = $stack->pop();
492 518 if ( is_null( $op1 ) ) {
493 519 return $this->raise_error( 'internal_error' );
494 520 }
@@ -498,12 +524,13 @@
498 524 if ( 'ln' === $function_name ) {
499 525 $function_name = 'log';
500 526 }
501 527 // Perfectly safe eval().
528 + // phpcs:ignore Squiz.PHP.Eval.Discouraged
502 529 eval( '$stack->push( ' . $function_name . '( $op1 ) );' );
530 + } elseif ( array_key_exists( $function_name, $this->calc_functions ) ) {
531 + // Calc-emulation function.
503 532
504 - // Calc-emulation function.
505 - } elseif ( array_key_exists( $function_name, $this->calc_functions ) ) {
506 533 // Get function arguments.
507 534 $args = array();
508 535 for ( $i = $count - 1; $i >= 0; $i-- ) {
509 536 $arg = $stack->pop();
@@ -526,16 +553,16 @@
526 553 $function_name = 'average';
527 554 } elseif ( 'arctan2' === $function_name ) {
528 555 $function_name = 'atan2';
529 556 }
530 - $result = call_user_func_array( array( 'EvalMath_Functions', $function_name ), array_reverse( $args ) );
557 + $result = EvalMath_Functions::$function_name( ...array_reverse( $args ) );
531 558 if ( false === $result ) {
532 559 return $this->raise_error( 'internal_error' );
533 560 }
534 561 $stack->push( $result );
562 + } elseif ( array_key_exists( $function_name, $this->functions ) ) {
563 + // User-defined function.
535 564
536 - // User-defined function.
537 - } elseif ( array_key_exists( $function_name, $this->functions ) ) {
538 565 // Get function arguments.
539 566 $args = array();
540 567 for ( $i = count( $this->functions[ $function_name ]['args'] ) - 1; $i >= 0; $i-- ) {
541 568 $arg = $stack->pop();
@@ -544,14 +571,13 @@
544 571 } else {
545 572 $args[ $this->functions[ $function_name ]['args'][ $i ] ] = $arg;
546 573 }
547 574 }
548 - // yay... recursion!
549 - $stack->push( $this->pfx( $this->functions[ $function_name ]['func'], $args ) );
575 + // Recursion.
576 + $stack->push( $this->pfx( $this->functions[ $function_name ]['func'], $args ) ); // @phpstan-ignore argument.type
550 577 }
551 -
552 - // If the token is a binary operator, pop two values off the stack, do the operation, and push the result back on.
553 - } elseif ( in_array( $token, array( '+', '-', '*', '/', '^', '>', '<', '=' ), true ) ) {
578 + } elseif ( in_array( $token, array( '+', '-', '*', '/', '^', '>', '<', '=', '%' ), true ) ) {
579 + // If the token is a binary operator, pop two values off the stack, do the operation, and push the result back on.
554 580 $op2 = $stack->pop();
555 581 if ( is_null( $op2 ) ) {
556 582 return $this->raise_error( 'internal_error' );
557 583 }
@@ -584,27 +610,29 @@
584 610 case '<':
585 611 $stack->push( (int) ( $op1 < $op2 ) );
586 612 break;
587 613 case '=':
614 + // phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison,Universal.Operators.StrictComparisons.LooseEqual
588 615 $stack->push( (int) ( $op1 == $op2 ) ); // Don't use === as the variable type can differ (int/double/bool).
589 616 break;
617 + case '%':
618 + $stack->push( $op1 % $op2 );
619 + break;
590 620 }
591 -
592 - // If the token is a unary operator, pop one value off the stack, do the operation, and push it back on.
593 621 } elseif ( '_' === $token ) {
622 + // If the token is a unary operator, pop one value off the stack, do the operation, and push it back on.
594 623 $stack->push( -1 * $stack->pop() );
595 -
596 - // If the token is a number or variable, push it on the stack.
624 + } elseif ( is_numeric( $token ) ) {
625 + // If the token is a number, push it on the stack.
626 + $stack->push( $token );
627 + } elseif ( array_key_exists( $token, $this->variables ) ) {
628 + // If the token is a variable, push it on the stack.
629 + $stack->push( $this->variables[ $token ] );
630 + } elseif ( array_key_exists( $token, $variables ) ) {
631 + // If the token is a variable, push it on the stack.
632 + $stack->push( $variables[ $token ] );
597 633 } else {
598 - if ( is_numeric( $token ) ) {
599 - $stack->push( $token );
600 - } elseif ( array_key_exists( $token, $this->variables ) ) {
601 - $stack->push( $this->variables[ $token ] );
602 - } elseif ( array_key_exists( $token, $variables ) ) {
603 - $stack->push( $variables[ $token ] );
604 - } else {
605 - return $this->raise_error( 'undefined_variable', $token );
606 - }
634 + return $this->raise_error( 'undefined_variable', $token );
607 635 }
608 636 }
609 637 // When we're out of tokens, the stack should have a single element, the final result.
610 638 if ( 1 !== $stack->count ) {
@@ -617,18 +645,17 @@
617 645 * Raise an error.
618 646 *
619 647 * @since 1.0.0
620 648 *
621 - * @param string $message Error message.
622 - * @param array|string $error_data Optional. Additional error data.
623 - * @return bool False, to stop evaluation.
649 + * @param string $message Error message.
650 + * @param mixed[]|string $error_data Optional. Additional error data.
651 + * @return false False, to stop evaluation.
624 652 */
625 - protected function raise_error( $message, $error_data = null ) {
653 + protected function raise_error( $message, $error_data = null ): bool {
626 654 $this->last_error = $this->get_error_string( $message, $error_data );
627 655 return false;
628 656 }
629 657
630 -
631 658 /**
632 659 * Get a translated string for an error message.
633 660 *
634 661 * @since 1.0.0
@@ -635,13 +662,13 @@
635 662 *
636 663 * @link https://github.com/moodle/moodle/blob/13264f35057d2f37374ec3e0e8ad4070f4676bd7/lang/en/mathslib.php
637 664 * @link https://github.com/moodle/moodle/blob/8e54ce9717c19f768b95f4332f70e3180ffafc46/lib/moodlelib.php#L6323
638 665 *
639 - * @param string $identifier Identifier of the string.
640 - * @param array|string $error_data Optional. Additional error data.
666 + * @param string $identifier Identifier of the string.
667 + * @param mixed[]|string $error_data Optional. Additional error data.
641 668 * @return string Translated string.
642 669 */
643 - protected function get_error_string( $identifier, $error_data = null ) {
670 + protected function get_error_string( $identifier, $error_data = null ): string {
644 671 $strings = array();
645 672 $strings['an_unexpected_error_occurred'] = 'an unexpected error occurred';
646 673 $strings['cannot_assign_to_constant'] = 'cannot assign to constant \'{$error_data}\'';
647 674 $strings['cannot_redefine_builtin_function'] = 'cannot redefine built-in function \'{$error_data}()\'';
@@ -657,9 +684,9 @@
657 684 $strings['unexpected_comma'] = 'unexpected comma';
658 685 $strings['unexpected_operator'] = 'unexpected operator \'{$error_data}\'';
659 686 $strings['wrong_number_of_arguments'] = 'wrong number of arguments ({$error_data->given} given, {$error_data->expected} expected)';
660 687
661 - $string = $strings[ $identifier ];
688 + $a_string = $strings[ $identifier ];
662 689
663 690 if ( null !== $error_data ) {
664 691 if ( is_array( $error_data ) ) {
665 692 $search = array();
@@ -683,16 +710,16 @@
683 710 $search[] = '{$error_data->' . $key . '}';
684 711 $replace[] = (string) $value;
685 712 }
686 713 if ( $search ) {
687 - $string = str_replace( $search, $replace, $string );
714 + $a_string = str_replace( $search, $replace, $a_string );
688 715 }
689 716 } else {
690 - $string = str_replace( '{$error_data}', (string) $error_data, $string );
717 + $a_string = str_replace( '{$error_data}', (string) $error_data, $a_string );
691 718 }
692 719 }
693 720
694 - return $string;
721 + return $a_string;
695 722 }
696 723
697 724 } // class EvalMath
698 725
@@ -697,29 +724,29 @@
697 724 } // class EvalMath
698 725
699 726 /**
700 727 * Stack for the postfix/infix conversion of math expressions.
728 + *
701 729 * @package TablePress
702 730 * @subpackage Formulas
703 731 * @since 1.0.0
704 732 */
705 -class EvalMath_Stack {
733 +class EvalMath_Stack { // phpcs:ignore Generic.Files.OneObjectStructurePerFile.MultipleFound,Generic.Classes.OpeningBraceSameLine.ContentAfterBrace
706 734
707 735 /**
708 736 * The stack.
709 737 *
710 738 * @since 1.0.0
711 - * @var array
739 + * @var mixed[]
712 740 */
713 - protected $stack = array();
741 + protected array $stack = array();
714 742
715 743 /**
716 744 * Number of items on the stack.
717 745 *
718 746 * @since 1.0.0
719 - * @var int
720 747 */
721 - public $count = 0;
748 + public int $count = 0;
722 749
723 750 /**
724 751 * Push an item onto the stack.
725 752 *
@@ -726,11 +753,11 @@
726 753 * @since 1.0.0
727 754 *
728 755 * @param mixed $value The item that is pushed onto the stack.
729 756 */
730 - public function push( $value ) {
757 + public function push( $value ): void {
731 758 $this->stack[ $this->count ] = $value;
732 - $this->count++;
759 + ++$this->count;
733 760 }
734 761
735 762 /**
736 763 * Pop an item from the top of the stack.
@@ -736,13 +763,13 @@
736 763 * Pop an item from the top of the stack.
737 764 *
738 765 * @since 1.0.0
739 766 *
740 - * @return mixed The item that is popped from the stack.
767 + * @return mixed|null The item that is popped from the stack.
741 768 */
742 - public function pop() {
769 + public function pop() /* : mixed|null */ {
743 770 if ( $this->count > 0 ) {
744 - $this->count--;
771 + --$this->count;
745 772 return $this->stack[ $this->count ];
746 773 }
747 774 return null;
748 775 }
@@ -752,11 +779,11 @@
752 779 *
753 780 * @since 1.0.0
754 781 *
755 782 * @param int $n Count from the end of the stack.
756 - * @return mixed The item that is popped from the stack.
783 + * @return mixed|null The item that is popped from the stack.
757 784 */
758 - public function last( $n = 1 ) {
785 + public function last( $n = 1 ) /* : mixed|null */ {
759 786 if ( ( $this->count - $n ) >= 0 ) {
760 787 return $this->stack[ $this->count - $n ];
761 788 }
762 789 return null;
@@ -765,21 +792,21 @@
765 792 } // class EvalMath_Stack
766 793
767 794 /**
768 795 * Common math functions, prepared for usage in EvalMath.
796 + *
769 797 * @package TablePress
770 798 * @subpackage EvalMath
771 799 * @since 1.0.0
772 800 */
773 -class EvalMath_Functions {
801 +class EvalMath_Functions { // phpcs:ignore Generic.Files.OneObjectStructurePerFile.MultipleFound,Generic.Classes.OpeningBraceSameLine.ContentAfterBrace
774 802
775 803 /**
776 804 * Seed for the generation of random numbers.
777 805 *
778 806 * @since 1.0.0
779 - * @var string
780 807 */
781 - protected static $random_seed = null;
808 + protected static ?string $random_seed = null;
782 809
783 810 /**
784 811 * Choose from two values based on an if-condition.
785 812 *
@@ -786,15 +813,15 @@
786 813 * "if" is not a valid function name, which is why it's prefixed with "func_".
787 814 *
788 815 * @since 1.0.0
789 816 *
790 - * @param double|int $condition Condition.
791 - * @param double|int $then Return value if the condition is true.
792 - * @param double|int $else Return value if the condition is false.
817 + * @param double|int $condition Condition.
818 + * @param double|int $statement Return value if the condition is true.
819 + * @param double|int $alternative Return value if the condition is false.
793 820 * @return double|int Result of the if check.
794 821 */
795 - public static function func_if( $condition, $then, $else ) {
796 - return ( (bool) $condition ? $then : $else );
822 + public static function func_if( $condition, $statement, $alternative ) /* : float|int */ {
823 + return ( (bool) $condition ? $statement : $alternative );
797 824 }
798 825
799 826 /**
800 827 * Return the negation (boolean "not") of a value.
@@ -805,9 +832,9 @@
805 832 *
806 833 * @param double|int $value Value to be negated.
807 834 * @return int Negated value (0 for false, 1 for true).
808 835 */
809 - public static function func_not( $value ) {
836 + public static function func_not( $value ): int {
810 837 return (int) ! (bool) $value;
811 838 }
812 839
813 840 /**
@@ -816,13 +843,12 @@
816 843 * "and" is not a valid function name, which is why it's prefixed with "func_".
817 844 *
818 845 * @since 1.0.0
819 846 *
820 - * @param double|int $args Values for which the conjunction shall be calculated.
847 + * @param double|int ...$args Values for which the conjunction shall be calculated.
821 848 * @return int Conjunction of the passed arguments.
822 849 */
823 - public static function func_and( $args ) {
824 - $args = func_get_args();
850 + public static function func_and( ...$args ): int {
825 851 foreach ( $args as $value ) {
826 852 if ( ! $value ) {
827 853 return 0;
828 854 }
@@ -836,13 +862,12 @@
836 862 * "or" is not a valid function name, which is why it's prefixed with "func_".
837 863 *
838 864 * @since 1.0.0
839 865 *
840 - * @param double|int $args Values for which the disjunction shall be calculated.
866 + * @param double|int ...$args Values for which the disjunction shall be calculated.
841 867 * @return int Disjunction of the passed arguments.
842 868 */
843 - public static function func_or( $args ) {
844 - $args = func_get_args();
869 + public static function func_or( ...$args ): int {
845 870 foreach ( $args as $value ) {
846 871 if ( $value ) {
847 872 return 1;
848 873 }
@@ -856,9 +881,9 @@
856 881 * @since 1.0.0
857 882 *
858 883 * @return double Rounded value of Pi.
859 884 */
860 - public static function pi() {
885 + public static function pi(): float {
861 886 return pi();
862 887 }
863 888
864 889 /**
@@ -865,26 +890,36 @@
865 890 * Calculate the sum of the arguments.
866 891 *
867 892 * @since 1.0.0
868 893 *
869 - * @param double|int $args Values for which the sum shall be calculated.
894 + * @param double|int ...$args Values for which the sum shall be calculated.
870 895 * @return double|int Sum of the passed arguments.
871 896 */
872 - public static function sum( $args ) {
873 - $args = func_get_args();
897 + public static function sum( ...$args ) /* : float|int */ {
874 898 return array_sum( $args );
875 899 }
876 900
877 901 /**
902 + * Count the number of non-empty arguments.
903 + *
904 + * @since 1.10.0
905 + *
906 + * @param double|int ...$args Values for which the number of non-empty elements shall be counted.
907 + * @return int Counted number of non-empty elements in the passed values.
908 + */
909 + public static function counta( ...$args ): int {
910 + return count( array_filter( $args ) );
911 + }
912 +
913 + /**
878 914 * Calculate the product of the arguments.
879 915 *
880 916 * @since 1.0.0
881 917 *
882 - * @param double|int $args Values for which the product shall be calculated.
918 + * @param double|int ...$args Values for which the product shall be calculated.
883 919 * @return double|int Product of the passed arguments.
884 920 */
885 - public static function product( $args ) {
886 - $args = func_get_args();
921 + public static function product( ...$args ) /* : float|int */ {
887 922 return array_product( $args );
888 923 }
889 924
890 925 /**
@@ -891,14 +926,17 @@
891 926 * Calculate the average/mean value of the arguments.
892 927 *
893 928 * @since 1.0.0
894 929 *
895 - * @param double|int $args Values for which the average shall be calculated.
930 + * @param double|int ...$args Values for which the average shall be calculated.
896 931 * @return double|int Average value of the passed arguments.
897 932 */
898 - public static function average( $args ) {
899 - $args = func_get_args();
900 - return ( call_user_func_array( array( 'self', 'sum' ), $args ) / count( $args ) );
933 + public static function average( ...$args ) /* : float|int */ {
934 + // Catch division by zero.
935 + if ( 0 === count( $args ) ) {
936 + return 0;
937 + }
938 + return array_sum( $args ) / count( $args );
901 939 }
902 940
903 941 /**
904 942 * Calculate the median of the arguments.
@@ -906,16 +944,15 @@
906 944 * For even counts of arguments, the upper median is returned.
907 945 *
908 946 * @since 1.0.0
909 947 *
910 - * @param double|int $args Values for which the median shall be calculated.
948 + * @param array<int, double|int> ...$args Values for which the median shall be calculated.
911 949 * @return double|int Median of the passed arguments.
912 950 */
913 - public static function median( $args ) {
914 - $args = func_get_args();
951 + public static function median( array ...$args ) /* : float|int */ {
915 952 sort( $args );
916 - $middle = floor( count( $args ) / 2 ); // Upper median for even counts.
917 - return $args[ $middle ];
953 + $middle = intdiv( count( $args ), 2 ); // Upper median for even counts.
954 + return $args[ $middle ]; // @phpstan-ignore return.type
918 955 }
919 956
920 957 /**
921 958 * Calculate the mode of the arguments.
@@ -921,17 +958,15 @@
921 958 * Calculate the mode of the arguments.
922 959 *
923 960 * @since 1.0.0
924 961 *
925 - * @param double|int $args Values for which the mode shall be calculated.
962 + * @param array<int, double|int> ...$args Values for which the mode shall be calculated.
926 963 * @return double|int Mode of the passed arguments.
927 964 */
928 - public static function mode( $args ) {
929 - $args = func_get_args();
930 - $values = array_count_values( $args );
965 + public static function mode( ...$args ) /* : float|int */ {
966 + $values = array_count_values( $args ); // @phpstan-ignore argument.type
931 967 asort( $values );
932 - end( $values );
933 - return key( $values );
968 + return array_key_last( $values ); // @phpstan-ignore return.type
934 969 }
935 970
936 971 /**
937 972 * Calculate the range of the arguments.
@@ -937,13 +972,12 @@
937 972 * Calculate the range of the arguments.
938 973 *
939 974 * @since 1.0.0
940 975 *
941 - * @param double|int $args Values for which the range shall be calculated.
976 + * @param double|int ...$args Values for which the range shall be calculated.
942 977 * @return double|int Range of the passed arguments.
943 978 */
944 - public static function range( $args ) {
945 - $args = func_get_args();
979 + public static function range( ...$args ) /* : float|int */ {
946 980 sort( $args );
947 981 return end( $args ) - reset( $args );
948 982 }
949 983
@@ -951,14 +985,13 @@
951 985 * Find the maximum value of the arguments.
952 986 *
953 987 * @since 1.0.0
954 988 *
955 - * @param double|int $args Values for which the maximum value shall be found.
989 + * @param double|int ...$args Values for which the maximum value shall be found.
956 990 * @return double|int Maximum value of the passed arguments.
957 991 */
958 - public static function max( $args ) {
959 - $args = func_get_args();
960 - return max( $args );
992 + public static function max( ...$args ) /* : float|int */ {
993 + return max( $args ); // @phpstan-ignore argument.type
961 994 }
962 995
963 996 /**
964 997 * Find the minimum value of the arguments.
@@ -964,14 +997,13 @@
964 997 * Find the minimum value of the arguments.
965 998 *
966 999 * @since 1.0.0
967 1000 *
968 - * @param double|int $args Values for which the minimum value shall be found.
1001 + * @param double|int ...$args Values for which the minimum value shall be found.
969 1002 * @return double|int Minimum value of the passed arguments.
970 1003 */
971 - public static function min( $args ) {
972 - $args = func_get_args();
973 - return min( $args );
1004 + public static function min( ...$args ) /* : float|int */ {
1005 + return min( $args ); // @phpstan-ignore argument.type
974 1006 }
975 1007
976 1008 /**
977 1009 * Calculate the remainder of a division of two numbers.
@@ -979,11 +1011,11 @@
979 1011 * @since 1.0.0
980 1012 *
981 1013 * @param double|int $op1 First number (dividend).
982 1014 * @param double|int $op2 Second number (divisor).
983 - * @return double|int Remainer of the division (dividend / divisor).
1015 + * @return int Remainder of the division (dividend / divisor).
984 1016 */
985 - public static function mod( $op1, $op2 ) {
1017 + public static function mod( $op1, $op2 ): int {
986 1018 return $op1 % $op2;
987 1019 }
988 1020
989 1021 /**
@@ -994,9 +1026,9 @@
994 1026 * @param double|int $base Base.
995 1027 * @param double|int $exponent Exponent.
996 1028 * @return double|int Power base^exponent.
997 1029 */
998 - public static function power( $base, $exponent ) {
1030 + public static function power( $base, $exponent ) /* : float|int */ {
999 1031 return pow( $base, $exponent );
1000 1032 }
1001 1033
1002 1034 /**
@@ -1007,9 +1039,9 @@
1007 1039 * @param double|int $number Number.
1008 1040 * @param double|int $base Optional. Base for the logarithm. Default e (for the natural logarithm).
1009 1041 * @return double Logarithm of the number to the base.
1010 1042 */
1011 - public static function log( $number, $base = M_E ) {
1043 + public static function log( $number, $base = M_E ): float {
1012 1044 return log( $number, $base );
1013 1045 }
1014 1046
1015 1047 /**
@@ -1022,9 +1054,9 @@
1022 1054 * @param double|int $op1 First number.
1023 1055 * @param double|int $op2 Second number.
1024 1056 * @return double Arc tangent of two numbers, similar to arc tangent of $op1/op$ except for the sign.
1025 1057 */
1026 - public static function atan2( $op1, $op2 ) {
1058 + public static function atan2( $op1, $op2 ): float {
1027 1059 return atan2( $op1, $op2 );
1028 1060 }
1029 1061
1030 1062 /**
@@ -1032,12 +1064,12 @@
1032 1064 *
1033 1065 * @since 1.0.0
1034 1066 *
1035 1067 * @param double|int $value Number to be rounded.
1036 - * @param double|int $decimals Optional. Number of decimals after the comma after the rounding.
1068 + * @param int $decimals Optional. Number of decimals after the comma after the rounding.
1037 1069 * @return double Rounded number.
1038 1070 */
1039 - public static function round( $value, $decimals = 0 ) {
1071 + public static function round( $value, $decimals = 0 ): float {
1040 1072 return round( $value, $decimals );
1041 1073 }
1042 1074
1043 1075 /**
@@ -1047,12 +1079,12 @@
1047 1079 *
1048 1080 * @since 1.0.0
1049 1081 *
1050 1082 * @param double|int $value Number to be rounded and formatted.
1051 - * @param double|int $decimals Optional. Number of decimals after the decimal separator after the rounding.
1052 - * @return double Formatted number.
1083 + * @param int $decimals Optional. Number of decimals after the decimal separator after the rounding.
1084 + * @return string Formatted number.
1053 1085 */
1054 - public static function number_format( $value, $decimals = 0 ) {
1086 + public static function number_format( $value, $decimals = 0 ): string {
1055 1087 return number_format( $value, $decimals, '.', ',' );
1056 1088 }
1057 1089
1058 1090 /**
@@ -1062,12 +1094,12 @@
1062 1094 *
1063 1095 * @since 1.0.0
1064 1096 *
1065 1097 * @param double|int $value Number to be rounded and formatted.
1066 - * @param double|int $decimals Optional. Number of decimals after the decimal separator after the rounding.
1067 - * @return double Formatted number.
1098 + * @param int $decimals Optional. Number of decimals after the decimal separator after the rounding.
1099 + * @return string Formatted number.
1068 1100 */
1069 - public static function number_format_eu( $value, $decimals = 0 ) {
1101 + public static function number_format_eu( $value, $decimals = 0 ): string {
1070 1102 return number_format( $value, $decimals, ',', ' ' );
1071 1103 }
1072 1104
1073 1105 /**
@@ -1074,11 +1106,11 @@
1074 1106 * Set the seed for the generation of random numbers.
1075 1107 *
1076 1108 * @since 1.0.0
1077 1109 *
1078 - * @param string The seed.
1110 + * @param string $random_seed The seed.
1079 1111 */
1080 - protected static function _set_random_seed( $random_seed ) {
1112 + protected static function _set_random_seed( $random_seed ): void {
1081 1113 self::$random_seed = $random_seed;
1082 1114 }
1083 1115
1084 1116 /**
@@ -1087,14 +1119,13 @@
1087 1119 * @since 1.0.0
1088 1120 *
1089 1121 * @return string The seed.
1090 1122 */
1091 - protected static function _get_random_seed() {
1123 + protected static function _get_random_seed(): string {
1092 1124 if ( is_null( self::$random_seed ) ) {
1093 1125 return microtime();
1094 - } else {
1095 - return self::$random_seed;
1096 1126 }
1127 + return self::$random_seed;
1097 1128 }
1098 1129
1099 1130 /**
1100 1131 * Get a random integer from a range.
@@ -1104,9 +1135,9 @@
1104 1135 * @param int $min Minimum value for the range.
1105 1136 * @param int $max Maximum value for the range.
1106 1137 * @return int Random integer from the range [$min, $max].
1107 1138 */
1108 - public static function rand_int( $min, $max ) {
1139 + public static function rand_int( $min, $max ): int {
1109 1140 // Swap min and max value if min is bigger than max.
1110 1141 if ( $min > $max ) {
1111 1142 $tmp = $max;
1112 1143 $max = $min;
@@ -1112,19 +1143,19 @@
1112 1143 $max = $min;
1113 1144 $min = $tmp;
1114 1145 unset( $tmp );
1115 1146 }
1116 - $number_characters = ceil( log( $max + 1 - $min, '16' ) );
1147 + $number_characters = (int) ceil( log( $max + 1 - $min, 16 ) );
1117 1148 $md5string = md5( self::_get_random_seed() );
1118 1149 $offset = 0;
1119 1150 do {
1120 - while ( ( $offset + $number_characters ) > strlen( $md5string ) ) {
1151 + while ( ( $offset + $number_characters ) > strlen( $md5string ) ) { // phpcs:ignore Squiz.PHP.DisallowSizeFunctionsInLoops.Found
1121 1152 $md5string .= md5( $md5string );
1122 1153 }
1123 - $randomno = hexdec( substr( $md5string, $offset, $number_characters ) );
1154 + $random_number = (int) hexdec( substr( $md5string, $offset, $number_characters ) );
1124 1155 $offset += $number_characters;
1125 - } while ( ( $min + $randomno ) > $max );
1126 - return $min + $randomno;
1156 + } while ( ( $min + $random_number ) > $max );
1157 + return $min + $random_number;
1127 1158 }
1128 1159
1129 1160 /**
1130 1161 * Get a random double value from a range [0, 1].
@@ -1132,10 +1163,10 @@
1132 1163 * @since 1.0.0
1133 1164 *
1134 1165 * @return double Random number from the range [0, 1].
1135 1166 */
1136 - public static function rand_float() {
1167 + public static function rand_float(): float {
1137 1168 $random_values = unpack( 'v', md5( self::_get_random_seed(), true ) );
1138 - return array_shift( $random_values ) / 65536;
1169 + return array_shift( $random_values ) / 65536; // @phpstan-ignore argument.type
1139 1170 }
1140 1171
1141 1172 } // class EvalMath_Functions