30 '+' => array(
'precedence' => 1),
31 '-' => array(
'precedence' => 1),
32 '*' => array(
'precedence' => 2),
33 '/' => array(
'precedence' => 2),
34 '^' => array(
'precedence' => 3),
63 if (isset(self::$cache_tokens[$this->field->getId()])) {
64 $tokens = self::$cache_tokens[$this->field->getId()];
67 self::$cache_tokens[$this->field->getId()] = $tokens;
70 foreach ($tokens as
$token) {
84 if (strpos($token,
'"') === 0) {
85 $parsed .= strip_tags(trim($token,
'"'));
86 } elseif (strpos($token,
'[[') === 0) {
87 $parsed .= trim(strip_tags($this->substituteFieldValue($token)));
89 throw new ilException(
"Unrecognized string token: '$token'");
103 if (abs($value) >= self::SCIENTIFIC_NOTATION_UPPER) {
104 return sprintf(
"%e", $value);
106 if (abs($value) <= self::SCIENTIFIC_NOTATION_LOWER && $value != 0) {
107 return sprintf(
"%e", $value);
114 return self::$operators;
119 return self::$functions;
127 if (isset(self::$cache_math_tokens[$this->field->getId()][
$token])) {
128 return self::$cache_math_tokens[$this->field->getId()][
$token];
130 if (strpos($token,
'"') === 0) {
133 $operators = array_keys(self::getOperators());
135 $result = (bool) preg_match(
139 self::$cache_math_tokens[$this->field->getId()][
$token] = $result;
150 if (isset(self::$cache_math_function_tokens[$this->field->getId()][
$token])) {
151 $result = self::$cache_math_function_tokens[$this->field->getId()][
$token];
152 if ($result ===
false) {
157 foreach (self::getFunctions() as $function) {
158 $pattern .=
"($function)\\(([^)]*)\\)|";
160 if (!preg_match_all(rtrim($pattern,
'|') .
'#', $token, $result)) {
162 self::$cache_math_function_tokens[$this->field->getId()][
$token] =
false;
168 foreach ($result[0] as $k => $to_replace) {
170 $function = $function_args[
'function'];
172 $token = str_replace($to_replace, $this->
calculateFunction($function, $args), $token);
187 for (
$i = 1;
$i < count($data);
$i++) {
189 if ($_data[$index]) {
190 $function = $_data[
$index];
191 $args = explode(
';', $data[
$i + 1][$index]);
192 $return[
'function'] = $function;
193 $return[
'args'] = $args;
207 foreach ($tokens as
$token) {
208 if (strpos($token,
'[[') === 0) {
209 $replaced[] = $this->substituteFieldValue($token);
222 protected function substituteFieldValue(
string $placeholder):
string 224 if (isset(self::$cache_fields[$placeholder])) {
225 $field = self::$cache_fields[$placeholder];
228 $field_title = preg_replace(
'#^\[\[(.*)\]\]#',
"$1", $placeholder);
229 $field = $table->getFieldByTitle($field_title);
230 if ($field === null) {
232 $field = $table->getField($field_title);
233 if ($field === null) {
239 $lng->loadLanguageModule(
'dcl');
241 throw new ilException(sprintf(
$lng->txt(
'dcl_err_formula_field_not_found'), $field_title));
244 self::$cache_fields[$placeholder] =
$field;
247 return $this->record->getRecordFieldFormulaValue($field->
getId());
261 foreach ($tokens as
$token) {
262 if (empty($token) or is_null($token)) {
265 if (is_numeric($token) or $token ===
'(') {
266 $stack->push($token);
267 if ($token ===
'(') {
270 } elseif (in_array($token, array_keys(
$operators))) {
272 if ($new_precedence > $precedence || $in_bracket) {
274 $stack->push($token);
275 $precedences->push($new_precedence);
276 $precedence = $new_precedence;
279 while ($new_precedence <= $precedence && $stack->count() > 1) {
280 $right = (float) $stack->pop();
281 $operator = $stack->pop();
282 $left = (float) $stack->pop();
283 $result = $this->
calculate($operator, $left, $right);
284 $stack->push($result);
285 $precedence = $precedences->pop();
287 $stack->push($token);
288 $precedence = $new_precedence;
289 $precedences->push($new_precedence);
291 } elseif ($token ===
')') {
294 $elem = $stack->pop();
295 while ($elem !==
'(' && !$stack->isEmpty()) {
297 $elem = $stack->pop();
300 $stack->push($this->
parseMath(array_reverse($_tokens)));
303 throw new ilException(
"Unrecognized token '$token'");
308 if ($stack->count() == 1) {
309 $result = $stack->pop();
311 return (ctype_digit((
string) $result)) ? $result : number_format($result, self::N_DECIMALS,
'.',
"'");
313 while ($stack->count() >= 2) {
314 $right = $stack->pop();
315 $operator = $stack->pop();
316 $left = $stack->count() ? $stack->pop() : 0;
317 $stack->push($this->
calculate($operator, $left, $right));
319 $result = $stack->pop();
334 $count = count($args);
336 return ($count) ? array_sum($args) / $count : 0;
338 return array_sum($args);
344 throw new ilException(
"Unrecognized function '$function'");
355 protected function calculate(
string $operator, $left, $right)
359 $result = $left + $right;
362 $result = $left - $right;
365 $result = $left * $right;
368 $result = ($right == 0) ? 0 : $left / $right;
371 $result = pow($left, $right);
374 throw new ilException(
"Unrecognized operator '$operator'");
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
parse()
Parse expression and return result.
ilDclBaseFieldModel $field
substituteFieldValues(array $tokens)
Given an array of tokens, replace each token that is a placeholder (e.g.
calculateFunction(string $function, array $args=array())
Calculate a function with its arguments.
ilDclBaseRecordModel $record
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getTokens(string $expression)
Split expression by & (ignore escaped &-symbols with backslash)
static array $cache_math_tokens
parseMath(array $tokens)
Parse a math expression.
static array $cache_math_function_tokens
static getTableCache(int $table_id=null)
getFunctionArgs(int $index, array $data)
Helper method to return the function and its arguments from a preg_replace_all $result array...
static getMathTokens(string $math_expression)
Generate tokens for a math expression.
calculateFunctions(string $token)
Execute any math functions inside a token.
static array $cache_fields
const SCIENTIFIC_NOTATION_UPPER
calculate(string $operator, $left, $right)
static array $cache_tokens
__construct(string $expression, ilDclBaseRecordModel $record, ilDclBaseFieldModel $field)
isMathToken(string $token)
Check if a given token is a math expression.
const SCIENTIFIC_NOTATION_LOWER