= <= > < == !=), Ternär (a ? b : c) und die Funktionen * sqrt, pow, abs, min, max, round, floor, ceil. * * Damit rechnet das Plugin mit GENAU DER Formel, die in Directus hinterlegt * ist – Änderungen an der Formel wirken automatisch mit. */ if (!defined('ABSPATH')) exit; /** Zerlegt den Ausdruck in Tokens. */ function skrift_formel_tokens($ausdruck) { $s = (string) $ausdruck; $s = str_replace('Math.', '', $s); // Math.sqrt(...) → sqrt(...) $s = preg_replace('/%(\w+)%/', '$1', $s); // %qty% → qty $tokens = array(); $pos = 0; $len = strlen($s); while ($pos < $len) { $c = $s[$pos]; if (ctype_space($c)) { $pos++; continue; } if (ctype_digit($c) || ($c === '.' && $pos + 1 < $len && ctype_digit($s[$pos + 1]))) { $start = $pos; while ($pos < $len && (ctype_digit($s[$pos]) || $s[$pos] === '.')) $pos++; $tokens[] = array('num', (float) substr($s, $start, $pos - $start)); continue; } if (ctype_alpha($c) || $c === '_') { $start = $pos; while ($pos < $len && (ctype_alnum($s[$pos]) || $s[$pos] === '_')) $pos++; $tokens[] = array('id', substr($s, $start, $pos - $start)); continue; } $zwei = substr($s, $pos, 2); if (in_array($zwei, array('>=', '<=', '==', '!='), true)) { $tokens[] = array('op', $zwei); $pos += 2; continue; } $tokens[] = array('op', $c); $pos++; } return $tokens; } function skrift_formel_ist($t, $i, $wert) { return $i < count($t) && $t[$i][0] === 'op' && $t[$i][1] === $wert; } function skrift_formel_fn($name, $args) { $a0 = isset($args[0]) ? (float) $args[0] : 0.0; switch ($name) { case 'sqrt': return $a0 < 0 ? 0.0 : sqrt($a0); case 'pow': return pow($a0, isset($args[1]) ? (float) $args[1] : 0.0); case 'abs': return abs($a0); case 'min': return empty($args) ? 0.0 : min($args); case 'max': return empty($args) ? 0.0 : max($args); case 'round': return round($a0); case 'floor': return floor($a0); case 'ceil': return ceil($a0); } return 0.0; } function skrift_formel_primary(&$i, $t, $v) { if ($i >= count($t)) return 0.0; $tk = $t[$i]; if ($tk[0] === 'num') { $i++; return $tk[1]; } if ($tk[0] === 'id') { $name = $tk[1]; $i++; if (skrift_formel_ist($t, $i, '(')) { $i++; $args = array(); if (!skrift_formel_ist($t, $i, ')')) { $args[] = skrift_formel_ternary($i, $t, $v); while (skrift_formel_ist($t, $i, ',')) { $i++; $args[] = skrift_formel_ternary($i, $t, $v); } } if (skrift_formel_ist($t, $i, ')')) $i++; return skrift_formel_fn($name, $args); } return isset($v[$name]) ? (float) $v[$name] : 0.0; } if ($tk[0] === 'op' && $tk[1] === '(') { $i++; $r = skrift_formel_ternary($i, $t, $v); if (skrift_formel_ist($t, $i, ')')) $i++; return $r; } $i++; return 0.0; } function skrift_formel_unary(&$i, $t, $v) { if (skrift_formel_ist($t, $i, '-')) { $i++; return -skrift_formel_unary($i, $t, $v); } if (skrift_formel_ist($t, $i, '+')) { $i++; return skrift_formel_unary($i, $t, $v); } return skrift_formel_primary($i, $t, $v); } function skrift_formel_mul(&$i, $t, $v) { $l = skrift_formel_unary($i, $t, $v); while (skrift_formel_ist($t, $i, '*') || skrift_formel_ist($t, $i, '/')) { $op = $t[$i][1]; $i++; $r = skrift_formel_unary($i, $t, $v); $l = $op === '*' ? $l * $r : ($r == 0 ? 0.0 : $l / $r); } return $l; } function skrift_formel_add(&$i, $t, $v) { $l = skrift_formel_mul($i, $t, $v); while (skrift_formel_ist($t, $i, '+') || skrift_formel_ist($t, $i, '-')) { $op = $t[$i][1]; $i++; $r = skrift_formel_mul($i, $t, $v); $l = $op === '+' ? $l + $r : $l - $r; } return $l; } function skrift_formel_compare(&$i, $t, $v) { $l = skrift_formel_add($i, $t, $v); while ($i < count($t) && $t[$i][0] === 'op' && in_array($t[$i][1], array('>=', '<=', '==', '!=', '>', '<'), true)) { $op = $t[$i][1]; $i++; $r = skrift_formel_add($i, $t, $v); switch ($op) { case '>=': $l = $l >= $r; break; case '<=': $l = $l <= $r; break; case '>': $l = $l > $r; break; case '<': $l = $l < $r; break; case '==': $l = $l == $r; break; case '!=': $l = $l != $r; break; } } return $l; } function skrift_formel_ternary(&$i, $t, $v) { $c = skrift_formel_compare($i, $t, $v); if (skrift_formel_ist($t, $i, '?')) { $i++; $a = skrift_formel_ternary($i, $t, $v); if (skrift_formel_ist($t, $i, ':')) $i++; $b = skrift_formel_ternary($i, $t, $v); return $c ? $a : $b; } return $c; } /** Wertet den Ausdruck aus. Bei Problemen wird $fallback zurückgegeben. */ function skrift_formel_eval($ausdruck, $vars, $fallback = 1.0) { if (!is_string($ausdruck) || trim($ausdruck) === '') return $fallback; try { $t = skrift_formel_tokens($ausdruck); $i = 0; $r = (float) skrift_formel_ternary($i, $t, $vars); if (!is_finite($r)) return $fallback; return $r; } catch (Throwable $e) { return $fallback; } }