Merge branch 'MDL-75464-master' of https://github.com/meirzamoodle/moodle

This commit is contained in:
Paul Holden 2023-03-16 11:38:49 +00:00 committed by Sara Arjona
commit 95c5001ddb
4 changed files with 115 additions and 7 deletions

View File

@ -210,14 +210,14 @@ class EvalMath {
$output = array(); // postfix form of expression, to be passed to pfx()
$expr = trim(strtolower($expr));
// MDL-14274: new operators for comparison added.
$ops = array('+', '-', '*', '/', '^', '_', '>', '<', '<=', '>=', '==');
$ops_r = array('+'=>0,'-'=>0,'*'=>0,'/'=>0,'^'=>1); // right-associative operator?
$ops_p = array('+'=>0,'-'=>0,'*'=>1,'/'=>1,'_'=>1,'^'=>2, '>'=>3, '<'=>3, '<='=>3, '>='=>3, '=='=>3); // operator precedence
$ops = array('+', '-', '*', '/', '^', '_', '>', '<', '<=', '>=', '==', '%');
$ops_r = array('+'=>0,'-'=>0,'*'=>0,'/'=>0,'^'=>1, '%' => 0); // right-associative operator?
$ops_p = array('+'=>0,'-'=>0,'*'=>1,'/'=>1,'_'=>1,'^'=>2, '>'=>3, '<'=>3, '<='=>3, '>='=>3, '=='=>3, '%'=>1); // operator precedence
$expecting_op = false; // we use this in syntax-checking the expression
// and determining when a - is a negation
if (preg_match("/[^\w\s+*^\/()\.,-<>=]/", $expr, $matches)) { // make sure the characters are all good
if (preg_match("/[^\%\w\s+*^\/()\.,-<>=]/", $expr, $matches)) { // make sure the characters are all good
return $this->trigger(get_string('illegalcharactergeneral', 'mathslib', $matches[0]));
}
@ -433,7 +433,7 @@ class EvalMath {
$stack->push($this->pfx($this->f[$fnn]['func'], $args)); // yay... recursion!!!!
}
// if the token is a binary operator, pop two values off the stack, do the operation, and push the result back on
} elseif (in_array($token, array('+', '-', '*', '/', '^', '>', '<', '==', '<=', '>='), true)) {
} elseif (in_array($token, array('+', '-', '*', '/', '^', '>', '<', '==', '<=', '>=', '%'), true)) {
if (is_null($op2 = $stack->pop())) return $this->trigger(get_string('internalerror', 'mathslib'));
if (is_null($op1 = $stack->pop())) return $this->trigger(get_string('internalerror', 'mathslib'));
switch ($token) {
@ -458,6 +458,8 @@ class EvalMath {
$stack->push((int)($op1 <= $op2)); break;
case '>=':
$stack->push((int)($op1 >= $op2)); break;
case '%':
$stack->push($op1%$op2); break;
}
// if the token is a unary operator, pop one value off the stack, do the operation, and push it back on
} elseif ($token == "_") {

View File

@ -32,4 +32,21 @@ e.g. if (and(condition_1, condition_2, ... condition_n))
Changes by Raquel Ortega (MDL-76413)
* Avoid PHP 8.2: Partially-supported callable deprecations
* eg: call_user_func_array(array('self', 'sum'), $args to call_user_func_array(array(self::class, 'sum'), $args)
* eg: call_user_func_array(array('self', 'sum'), $args to call_user_func_array(array(self::class, 'sum'), $args)
Changes by Meirza (MDL-75464)
* EvalMath has unit tests in lib/tests/mathslib_test.php,
  since version 1.0.1, there are two additional tests:
  - shouldSupportModuloOperator()
  - shouldConsiderDoubleMinusAsPlus()
  To pass the test, some modifications must be made:
  - Adjust the test code so it can run properly by using \calc_formula.
  Please see the differences between the code in MDL-75464 and the upstream code.
  - In the dataprovider for both tests, add the formula in the first array with "=" at the first character.
  Before:
  ```
  'a%b', // 9%3 => 0
  ```
  After:
  ```
  '=a%b', // 9%3 => 0

View File

@ -317,4 +317,93 @@ class mathslib_test extends \basic_testcase {
$result = $formula->evaluate();
$this->assertTrue(is_float($result));
}
/**
* Tests the modulo operator.
*
* @covers calc_formula::evaluate
* @dataProvider moduloOperatorData
*
* @param string $formula
* @param array $values
* @param int|float $expectedResult
*/
public function shouldSupportModuloOperator($formula, $values, $expectedResult)
{
$formula = new calc_formula($formula);
$formula->set_params($values);
$this->assertEquals($expectedResult, $formula->evaluate());
}
/**
* Data provider for shouldSupportModuloOperator
*
* @return array
*/
public function moduloOperatorData() {
return array(
array(
'=a%b', // 9%3 => 0
array('a' => 9, 'b' => 3),
0
),
array(
'=a%b', // 10%3 => 1
array('a' => 10, 'b' => 3),
1
),
array(
'=10-a%(b+c*d)', // 10-10%(7-2*2) => 9
array('a' => '10', 'b' => 7, 'c' => -2, 'd' => 2),
9
)
);
}
/**
* Tests the double minus as plus.
*
* @covers calc_formula::evaluate
* @dataProvider doubleMinusData
*
* @param string $formula
* @param array $values
* @param int|float $expectedResult
*/
public function shouldConsiderDoubleMinusAsPlus($formula, $values, $expectedResult)
{
$formula = new calc_formula($formula);
$formula->set_params($values);
$this->assertEquals($expectedResult, $formula->evaluate());
}
/**
* Data provider for shouldConsiderDoubleMinusAsPlus
*
* @return array
*/
public function doubleMinusData() {
return array(
array(
'=a+b*c--d', // 1+2*3--4 => 1+6+4 => 11
array(
'a' => 1,
'b' => 2,
'c' => 3,
'd' => 4
),
11
),
array(
'=a+b*c--d', // 1+2*3---4 => 1+6-4 => 3
array(
'a' => 1,
'b' => 2,
'c' => 3,
'd' => -4
),
3
)
);
}
}

View File

@ -42,7 +42,7 @@
<location>evalmath</location>
<name>EvalMath</name>
<description>Class to safely evaluate math expressions.</description>
<version>1.0.0</version>
<version>1.0.1</version>
<license>BSD</license>
<repository>https://github.com/dbojdo/eval-math</repository>
<copyrights>