30 '+' =>
array(
'precedence' => 1 ),
31 '-' =>
array(
'precedence' => 1 ),
32 '*' =>
array(
'precedence' => 2 ),
33 '/' =>
array(
'precedence' => 2 ),
34 '^' =>
array(
'precedence' => 3 ),
84 if (isset(self::$cache_tokens[$this->field->getId()])) {
85 $tokens = self::$cache_tokens[$this->field->getId()];
88 self::$cache_tokens[$this->field->getId()] = $tokens;
92 foreach ($tokens as $token) {
106 if (strpos($token,
'"') === 0) {
107 $parsed .= strip_tags(trim($token,
'"'));
108 } elseif (strpos($token,
'[[') === 0) {
109 $parsed .= trim(strip_tags($this->substituteFieldValue($token)));
111 throw new ilException(
"Unrecognized string token: '$token'");
126 if (abs($value) >= self::SCIENTIFIC_NOTATION_UPPER) {
127 return sprintf(
"%e", $value);
129 if (abs($value) <= self::SCIENTIFIC_NOTATION_LOWER && $value != 0 ) {
130 return sprintf(
"%e", $value);
132 if (is_float($value)) {
144 return self::$operators;
152 return self::$functions;
164 if (isset(self::$cache_math_tokens[$this->field->getId()][$token])) {
165 return self::$cache_math_tokens[$this->field->getId()][$token];
167 if (strpos($token,
'"') === 0) {
170 $operators = array_keys(self::getOperators());
173 self::$cache_math_tokens[$this->field->getId()][$token] =
$result;
188 if (isset(self::$cache_math_function_tokens[$this->field->getId()][$token])) {
189 $result = self::$cache_math_function_tokens[$this->field->getId()][$token];
195 foreach (self::getFunctions() as $function) {
196 $pattern .=
"($function)\\(([^)]*)\\)|";
198 if (!preg_match_all(rtrim($pattern,
'|') .
'#', $token,
$result)) {
200 self::$cache_math_function_tokens[$this->field->getId()][$token] =
false;
206 foreach (
$result[0] as $k => $to_replace) {
208 $function = $function_args[
'function'];
210 $token = str_replace($to_replace, $this->
calculateFunction($function, $args), $token);
230 for ($i = 1; $i < count($data); $i ++) {
232 if ($_data[$index]) {
233 $function = $_data[$index];
234 $args = explode(
';', $data[$i + 1][$index]);
235 $return[
'function'] = $function;
236 $return[
'args'] = $args;
254 foreach ($tokens as $token) {
255 if (strpos($token,
'[[') === 0) {
256 $replaced[] = $this->substituteFieldValue($token);
258 $replaced[] = $token;
274 protected function substituteFieldValue($placeholder) {
275 if (isset(self::$cache_fields[$placeholder])) {
276 $field = self::$cache_fields[$placeholder];
279 $field_title = preg_replace(
'#^\[\[(.*)\]\]#',
"$1", $placeholder);
280 $field = $table->getFieldByTitle($field_title);
283 $field = $table->getField($field_title);
290 $lng->loadLanguageModule(
'dcl');
292 throw new ilException(sprintf(
$lng->txt(
'dcl_err_formula_field_not_found'), $field_title));
295 self::$cache_fields[$placeholder] =
$field;
298 return $this->record->getRecordFieldHTML(
$field->getId());
316 foreach ($tokens as $token) {
317 if (empty($token) OR is_null($token)) {
320 if (is_numeric($token) OR $token ===
'(') {
321 $stack->push($token);
322 if ($token ===
'(') {
325 } elseif (in_array($token, array_keys(
$operators))) {
326 $new_precedence =
$operators[$token][
'precedence'];
327 if ($new_precedence > $precedence || $in_bracket) {
329 $stack->push($token);
330 $precedences->push($new_precedence);
331 $precedence = $new_precedence;
334 while ($new_precedence <= $precedence && $stack->count() > 1) {
335 $right = (float)$stack->pop();
336 $operator = $stack->pop();
337 $left = (float)$stack->pop();
340 $precedence = $precedences->pop();
342 $stack->push($token);
343 $precedence = $new_precedence;
344 $precedences->push($new_precedence);
346 } elseif ($token ===
')') {
349 $elem = $stack->pop();
350 while ($elem !==
'(' && !$stack->isEmpty()) {
352 $elem = $stack->pop();
355 $stack->push($this->
parseMath(array_reverse($_tokens)));
358 throw new ilException(
"Unrecognized token '$token'");
363 if ($stack->count() == 1) {
366 return (ctype_digit((
string)
$result)) ?
$result : number_format($result, self::N_DECIMALS,
'.',
"'");
369 while ($stack->count() >= 2) {
370 $right = $stack->pop();
371 $operator = $stack->pop();
372 $left = $stack->count() ? $stack->pop() : 0;
373 $stack->push($this->
calculate($operator, $left, $right));
394 $count = count($args);
396 return ($count) ? array_sum($args) / $count : 0;
398 return array_sum($args);
404 throw new ilException(
"Unrecognized function '$function'");
417 protected function calculate($operator, $left, $right) {
429 $result = ($right == 0) ? 0 : $left / $right;
435 throw new ilException(
"Unrecognized operator '$operator'");
Class ilDclBaseFieldModel.
static $cache_math_function_tokens
Class ilDclExpressionParser.
parse()
Parse expression and return result.
Base class for ILIAS Exception handling.
calculate($operator, $left, $right)
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...
__construct($expression, ilDclBaseRecordModel $record, ilDclBaseFieldModel $field)
static getTableCache($table_id=0)
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 $cache_math_tokens
static getTokens($expression)
Split expression by & (ignore escaped &-symbols with backslash)
static getMathTokens($math_expression)
Generate tokens for a math expression.
Create styles array
The data for the language used.
const SCIENTIFIC_NOTATION_UPPER
Class ilDclBaseRecordModel.
calculateFunction($function, array $args=array())
Calculate a function with its arguments.
const SCIENTIFIC_NOTATION_LOWER