ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
ilDclExpressionParser Class Reference

Class ilDclExpressionParser. More...

+ Collaboration diagram for ilDclExpressionParser:

Public Member Functions

 __construct ($expression, ilDclBaseRecordModel $record, ilDclBaseFieldModel $field)
 
 parse ()
 Parse expression and return result. More...
 

Static Public Member Functions

static getOperators ()
 
static getFunctions ()
 

Data Fields

const N_DECIMALS = 1
 
const SCIENTIFIC_NOTATION_UPPER = 1000000000000
 
const SCIENTIFIC_NOTATION_LOWER = 0.000000001
 

Protected Member Functions

 formatScientific ($value)
 
 isMathToken ($token)
 Check if a given token is a math expression. More...
 
 calculateFunctions ($token)
 Execute any math functions inside a token. More...
 
 getFunctionArgs ($index, array $data)
 Helper method to return the function and its arguments from a preg_replace_all $result array. More...
 
 substituteFieldValues (array $tokens)
 Given an array of tokens, replace each token that is a placeholder (e.g. More...
 
 parseMath (array $tokens)
 Parse a math expression. More...
 
 calculateFunction ($function, array $args=array())
 Calculate a function with its arguments. More...
 
 calculate ($operator, $left, $right)
 

Protected Attributes

 $record
 
 $field
 
 $expression
 

Static Protected Attributes

static $operators
 
static $cache_tokens = array()
 
static $cache_fields = array()
 
static $cache_math_tokens = array()
 
static $cache_math_function_tokens = array()
 
static $functions
 

Detailed Description

Constructor & Destructor Documentation

◆ __construct()

ilDclExpressionParser::__construct (   $expression,
ilDclBaseRecordModel  $record,
ilDclBaseFieldModel  $field 
)
Parameters
string$expression
ilDclBaseRecordModel$record
ilDclBaseFieldModel$field

Definition at line 70 of file class.ilDclExpressionParser.php.

References $expression, $field, and $record.

71  {
72  $this->expression = $expression;
73  $this->record = $record;
74  $this->field = $field;
75  }

Member Function Documentation

◆ calculate()

ilDclExpressionParser::calculate (   $operator,
  $left,
  $right 
)
protected
Parameters
string$operator
float$left
float$right
Returns
float|number
Exceptions
ilException

Definition at line 430 of file class.ilDclExpressionParser.php.

References $result.

Referenced by parseMath().

431  {
432  switch ($operator) {
433  case '+':
434  $result = $left + $right;
435  break;
436  case '-':
437  $result = $left - $right;
438  break;
439  case '*':
440  $result = $left * $right;
441  break;
442  case '/':
443  $result = ($right == 0) ? 0 : $left / $right;
444  break;
445  case '^':
446  $result = pow($left, $right);
447  break;
448  default:
449  throw new ilException("Unrecognized operator '$operator'");
450  }
451 
452  return $result;
453  }
$result
+ Here is the caller graph for this function:

◆ calculateFunction()

ilDclExpressionParser::calculateFunction (   $function,
array  $args = array() 
)
protected

Calculate a function with its arguments.

Parameters
$functionFunction name to calculate
array$argsArguments of function
Returns
float|int|number
Exceptions
ilException

Definition at line 403 of file class.ilDclExpressionParser.php.

Referenced by calculateFunctions().

404  {
405  switch ($function) {
406  case 'AVERAGE':
407  $count = count($args);
408 
409  return ($count) ? array_sum($args) / $count : 0;
410  case 'SUM':
411  return array_sum($args);
412  case 'MIN':
413  return min($args);
414  case 'MAX':
415  return max($args);
416  default:
417  throw new ilException("Unrecognized function '$function'");
418  }
419  }
+ Here is the caller graph for this function:

◆ calculateFunctions()

ilDclExpressionParser::calculateFunctions (   $token)
protected

Execute any math functions inside a token.

Parameters
string$token
Returns
string

Definition at line 195 of file class.ilDclExpressionParser.php.

References $result, PHPMailer\PHPMailer\$token, calculateFunction(), getFunctionArgs(), and substituteFieldValues().

Referenced by parse().

196  {
197  if (isset(self::$cache_math_function_tokens[$this->field->getId()][$token])) {
198  $result = self::$cache_math_function_tokens[$this->field->getId()][$token];
199  if ($result === false) {
200  return $token;
201  }
202  } else {
203  $pattern = '#';
204  foreach (self::getFunctions() as $function) {
205  $pattern .= "($function)\\(([^)]*)\\)|";
206  }
207  if (!preg_match_all(rtrim($pattern, '|') . '#', $token, $result)) {
208  // No functions found inside token, just return token again
209  self::$cache_math_function_tokens[$this->field->getId()][$token] = false;
210 
211  return $token;
212  }
213  }
214  // Function found inside token, calculate!
215  foreach ($result[0] as $k => $to_replace) {
216  $function_args = $this->getFunctionArgs($k, $result);
217  $function = $function_args['function'];
218  $args = $this->substituteFieldValues($function_args['args']);
219  $token = str_replace($to_replace, $this->calculateFunction($function, $args), $token);
220  }
221 
222  return $token;
223  }
$result
substituteFieldValues(array $tokens)
Given an array of tokens, replace each token that is a placeholder (e.g.
getFunctionArgs($index, array $data)
Helper method to return the function and its arguments from a preg_replace_all $result array...
calculateFunction($function, array $args=array())
Calculate a function with its arguments.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ formatScientific()

ilDclExpressionParser::formatScientific (   $value)
protected
Parameters
$value
Returns
string

Definition at line 129 of file class.ilDclExpressionParser.php.

Referenced by parse().

130  {
131  if (abs($value) >= self::SCIENTIFIC_NOTATION_UPPER) {
132  return sprintf("%e", $value);
133  }
134  if (abs($value) <= self::SCIENTIFIC_NOTATION_LOWER && $value != 0) {
135  return sprintf("%e", $value);
136  }
137  if (is_float($value)) {
138  return $value;
139  }
140 
141  return $value;
142  }
+ Here is the caller graph for this function:

◆ getFunctionArgs()

ilDclExpressionParser::getFunctionArgs (   $index,
array  $data 
)
protected

Helper method to return the function and its arguments from a preg_replace_all $result array.

Parameters
$index
array$data
Returns
array

Definition at line 234 of file class.ilDclExpressionParser.php.

References $i, and $index.

Referenced by calculateFunctions().

235  {
236  $return = array(
237  'function' => '',
238  'args' => array(),
239  );
240  for ($i = 1; $i < count($data); $i++) {
241  $_data = $data[$i];
242  if ($_data[$index]) {
243  $function = $_data[$index];
244  $args = explode(';', $data[$i + 1][$index]);
245  $return['function'] = $function;
246  $return['args'] = $args;
247  break;
248  }
249  }
250 
251  return $return;
252  }
$index
Definition: metadata.php:60
$i
Definition: disco.tpl.php:19
$data
Definition: bench.php:6
+ Here is the caller graph for this function:

◆ getFunctions()

static ilDclExpressionParser::getFunctions ( )
static
Returns
array

Definition at line 157 of file class.ilDclExpressionParser.php.

Referenced by ilDclFormulaFieldRepresentation\buildFieldCreationInput().

158  {
159  return self::$functions;
160  }
+ Here is the caller graph for this function:

◆ getOperators()

static ilDclExpressionParser::getOperators ( )
static
Returns
array

Definition at line 148 of file class.ilDclExpressionParser.php.

Referenced by ilDclFormulaFieldRepresentation\buildFieldCreationInput(), and ilDclTokenizer\getMathTokens().

149  {
150  return self::$operators;
151  }
+ Here is the caller graph for this function:

◆ isMathToken()

ilDclExpressionParser::isMathToken (   $token)
protected

Check if a given token is a math expression.

Parameters
string$token
Returns
bool

Definition at line 170 of file class.ilDclExpressionParser.php.

References $functions, $operators, $result, and PHPMailer\PHPMailer\$token.

Referenced by parse().

171  {
172  if (isset(self::$cache_math_tokens[$this->field->getId()][$token])) {
173  return self::$cache_math_tokens[$this->field->getId()][$token];
174  } else {
175  if (strpos($token, '"') === 0) {
176  return false;
177  }
178  $operators = array_keys(self::getOperators());
179  $functions = self::getFunctions();
180  $result = (bool) preg_match('#(\\' . implode("|\\", $operators) . '|' . implode('|', $functions) . ')#', $token);
181  self::$cache_math_tokens[$this->field->getId()][$token] = $result;
182 
183  return $result;
184  }
185  }
$result
+ Here is the caller graph for this function:

◆ parse()

ilDclExpressionParser::parse ( )

Parse expression and return result.

This method loops the tokens and checks if Token is of type string or math. Concatenates results to produce resulting string of parsed expression.

Exceptions
ilException
Returns
string

Definition at line 86 of file class.ilDclExpressionParser.php.

References PHPMailer\PHPMailer\$token, calculateFunctions(), formatScientific(), ilDclTokenizer\getMathTokens(), ilDclTokenizer\getTokens(), isMathToken(), parseMath(), and substituteFieldValues().

87  {
88  if (isset(self::$cache_tokens[$this->field->getId()])) {
89  $tokens = self::$cache_tokens[$this->field->getId()];
90  } else {
91  $tokens = ilDclTokenizer::getTokens($this->expression);
92  self::$cache_tokens[$this->field->getId()] = $tokens;
93  }
94  // ilUtil::sendInfo( "<pre>" . print_r($tokens, 1) . "</pre>");
95  $parsed = '';
96  foreach ($tokens as $token) {
97  if (empty($token)) {
98  continue;
99  }
100  if ($this->isMathToken($token)) {
101  $token = $this->calculateFunctions($token);
102  $math_tokens = ilDclTokenizer::getMathTokens($token);
103  $value = $this->parseMath($this->substituteFieldValues($math_tokens));
104 
105  $value = $this->formatScientific($value);
106 
107  $parsed .= $value;
108  } else {
109  // Token is a string, either a field placeholder [[Field name]] or a string starting with "
110  if (strpos($token, '"') === 0) {
111  $parsed .= strip_tags(trim($token, '"'));
112  } elseif (strpos($token, '[[') === 0) {
113  $parsed .= trim(strip_tags($this->substituteFieldValue($token)));
114  } else {
115  throw new ilException("Unrecognized string token: '$token'");
116  }
117  }
118  }
119 
120  return $parsed;
121  }
substituteFieldValues(array $tokens)
Given an array of tokens, replace each token that is a placeholder (e.g.
parseMath(array $tokens)
Parse a math expression.
isMathToken($token)
Check if a given token is a math expression.
calculateFunctions($token)
Execute any math functions inside a token.
static getTokens($expression)
Split expression by & (ignore escaped &-symbols with backslash)
static getMathTokens($math_expression)
Generate tokens for a math expression.
+ Here is the call graph for this function:

◆ parseMath()

ilDclExpressionParser::parseMath ( array  $tokens)
protected

Parse a math expression.

Parameters
array$tokens
Returns
null
Exceptions
Exception

Definition at line 322 of file class.ilDclExpressionParser.php.

References $operators, $result, PHPMailer\PHPMailer\$token, and calculate().

Referenced by parse().

323  {
324  $operators = self::$operators;
325  $precedence = 0;
326  $stack = new ilDclStack();
327  $precedences = new ilDclStack();
328  $in_bracket = false;
329  foreach ($tokens as $token) {
330  if (empty($token) or is_null($token)) {
331  $token = 0;
332  }
333  if (is_numeric($token) or $token === '(') {
334  $stack->push($token);
335  if ($token === '(') {
336  $in_bracket = true;
337  }
338  } elseif (in_array($token, array_keys($operators))) {
339  $new_precedence = $operators[$token]['precedence'];
340  if ($new_precedence > $precedence || $in_bracket) {
341  // Precedence of operator is higher, push operator on stack
342  $stack->push($token);
343  $precedences->push($new_precedence);
344  $precedence = $new_precedence;
345  } else {
346  // Precedence is equal or lower, calculate result on stack
347  while ($new_precedence <= $precedence && $stack->count() > 1) {
348  $right = (float) $stack->pop();
349  $operator = $stack->pop();
350  $left = (float) $stack->pop();
351  $result = $this->calculate($operator, $left, $right);
352  $stack->push($result);
353  $precedence = $precedences->pop();
354  }
355  $stack->push($token);
356  $precedence = $new_precedence;
357  $precedences->push($new_precedence);
358  }
359  } elseif ($token === ')') {
360  // Need to calculate stack back to opening bracket
361  $_tokens = array();
362  $elem = $stack->pop();
363  while ($elem !== '(' && !$stack->isEmpty()) {
364  $_tokens[] = $elem;
365  $elem = $stack->pop();
366  }
367  // Get result within brackets recursive and push to stack
368  $stack->push($this->parseMath(array_reverse($_tokens)));
369  $in_bracket = false;
370  } else {
371  throw new ilException("Unrecognized token '$token'");
372  }
373  // $stack->debug();
374  }
375  // If one element is left on stack, we are done. Otherwise calculate
376  if ($stack->count() == 1) {
377  $result = $stack->pop();
378 
379  return (ctype_digit((string) $result)) ? $result : number_format($result, self::N_DECIMALS, '.', "'");
380  } else {
381  while ($stack->count() >= 2) {
382  $right = $stack->pop();
383  $operator = $stack->pop();
384  $left = $stack->count() ? $stack->pop() : 0;
385  $stack->push($this->calculate($operator, $left, $right));
386  }
387  $result = $stack->pop();
388 
389  return $result;
390  }
391  }
$result
calculate($operator, $left, $right)
Class ilDclStack.
parseMath(array $tokens)
Parse a math expression.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ substituteFieldValues()

ilDclExpressionParser::substituteFieldValues ( array  $tokens)
protected

Given an array of tokens, replace each token that is a placeholder (e.g.

[[Field name]]) with it's value

Parameters
array$tokens
Returns
array

Definition at line 262 of file class.ilDclExpressionParser.php.

References $DIC, $field, $lng, $table, PHPMailer\PHPMailer\$token, and ilDclCache\getTableCache().

Referenced by calculateFunctions(), and parse().

263  {
264  $replaced = array();
265  foreach ($tokens as $token) {
266  if (strpos($token, '[[') === 0) {
267  $replaced[] = $this->substituteFieldValue($token);
268  } else {
269  $replaced[] = $token;
270  }
271  }
272 
273  return $replaced;
274  }
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Field Documentation

◆ $cache_fields

ilDclExpressionParser::$cache_fields = array()
staticprotected

Definition at line 44 of file class.ilDclExpressionParser.php.

◆ $cache_math_function_tokens

ilDclExpressionParser::$cache_math_function_tokens = array()
staticprotected

Definition at line 52 of file class.ilDclExpressionParser.php.

◆ $cache_math_tokens

ilDclExpressionParser::$cache_math_tokens = array()
staticprotected

Definition at line 48 of file class.ilDclExpressionParser.php.

◆ $cache_tokens

ilDclExpressionParser::$cache_tokens = array()
staticprotected

Definition at line 40 of file class.ilDclExpressionParser.php.

◆ $expression

ilDclExpressionParser::$expression
protected

Definition at line 25 of file class.ilDclExpressionParser.php.

Referenced by __construct().

◆ $field

ilDclExpressionParser::$field
protected

Definition at line 21 of file class.ilDclExpressionParser.php.

Referenced by __construct(), and substituteFieldValues().

◆ $functions

ilDclExpressionParser::$functions
staticprotected
Initial value:
= array(
'SUM',
'AVERAGE',
'MIN',
'MAX',
)

Definition at line 57 of file class.ilDclExpressionParser.php.

Referenced by isMathToken().

◆ $operators

ilDclExpressionParser::$operators
staticprotected
Initial value:
= array(
'+' => array('precedence' => 1),
'-' => array('precedence' => 1),
'*' => array('precedence' => 2),
'/' => array('precedence' => 2),
'^' => array('precedence' => 3),
)

Definition at line 30 of file class.ilDclExpressionParser.php.

Referenced by isMathToken(), and parseMath().

◆ $record

ilDclExpressionParser::$record
protected

Definition at line 17 of file class.ilDclExpressionParser.php.

Referenced by __construct().

◆ N_DECIMALS

const ilDclExpressionParser::N_DECIMALS = 1

Definition at line 11 of file class.ilDclExpressionParser.php.

◆ SCIENTIFIC_NOTATION_LOWER

const ilDclExpressionParser::SCIENTIFIC_NOTATION_LOWER = 0.000000001

Definition at line 13 of file class.ilDclExpressionParser.php.

◆ SCIENTIFIC_NOTATION_UPPER

const ilDclExpressionParser::SCIENTIFIC_NOTATION_UPPER = 1000000000000

Definition at line 12 of file class.ilDclExpressionParser.php.


The documentation for this class was generated from the following file: