private function func(Token $func, &$args) { $functions = array("abs" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return abs($a); }), "acos" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return acos($a); }), "acosh" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return acosh($a); }), "addMonths" => array(2, array(Token::T_NUMBER, Token::T_DATE), Token::T_DATE, function ($a, $b) { return Expression::addMonths($a, $b); }), "asin" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return asin($a); }), "asinh" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return asinh($a); }), "atan" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return atan($a); }), "atan2" => array(2, array(Token::T_NUMBER, Token::T_NUMBER), Token::T_NUMBER, function ($a, $b) { return atan2($a, $b); }), "atanh" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return atanh($a); }), "ceil" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return ceil($a); }), "concat" => array(-1, array(Token::T_TEXT), Token::T_TEXT, function ($a) { $s = ''; foreach ($a as $v) { $s .= isset($v) ? $v : ''; } return $s; }), "cos" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return cos($a); }), "cosh" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return cosh($a); }), "count" => array(-1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { $c = 0; foreach ($a as $v) { if (isset($v)) { $c += 1; } } return $c; }), "day" => array(1, array(Token::T_DATE), Token::T_NUMBER, function ($a) { return (double) $a->format('d'); }), "exp" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return exp($a); }), "firstDayOfMonth" => array(1, array(Token::T_DATE), Token::T_DATE, function ($a) { return Expression::firstDayOfMonth($a); }), "floor" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return floor($a); }), "fullmonth" => array(1, array(Token::T_DATE), Token::T_TEXT, function ($a) { $months = array("janvier", "février", "mars", "avril", "mai", "juin", "juillet", "août", "septembre", "octobre", "novembre", "décembre"); return $months[(int) $a->format('m') - 1] . ' ' . $a->format('Y'); }), "get" => array(2, array(Token::T_ARRAY, Token::T_NUMBER), Token::T_TEXT, function ($a, $b) { return isset($a[$b - 1]) ? $a[$b - 1] : ""; }), "lastday" => array(2, array(Token::T_NUMBER, Token::T_NUMBER), Token::T_NUMBER, function ($a, $b) { return Expression::lastDay($b, $a); }), "lastDayOfMonth" => array(1, array(Token::T_DATE), Token::T_DATE, function ($a) { return Expression::lastDayOfMonth($a); }), "length" => array(1, array(Token::T_TEXT), Token::T_NUMBER, function ($a) { return mb_strlen($a, 'utf8'); }), "log" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return log($a); }), "log10" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return log10($a); }), "lower" => array(1, array(Token::T_TEXT), Token::T_TEXT, function ($a) { return strtolower($a); }), "match" => array(2, array(Token::T_TEXT, Token::T_TEXT), Token::T_BOOLEAN, function ($a, $b) { return preg_match($a, $b); }), "max" => array(2, array(Token::T_NUMBER, Token::T_NUMBER), Token::T_NUMBER, function ($a, $b) { return max($a, $b); }), "min" => array(2, array(Token::T_NUMBER, Token::T_NUMBER), Token::T_NUMBER, function ($a, $b) { return min($a, $b); }), "money" => array(1, array(Token::T_NUMBER), Token::T_TEXT, function ($a) { return (string) number_format($a, 2, ",", " "); }), "month" => array(1, array(Token::T_DATE), Token::T_NUMBER, function ($a) { return (double) $a->format('m'); }), "nextWorkDay" => array(1, array(Token::T_DATE), Token::T_DATE, function ($a) { return Expression::nextWorkingDay($a); }), "pow" => array(2, array(Token::T_NUMBER, Token::T_NUMBER), Token::T_NUMBER, function ($a, $b) { return pow($a, $b); }), "rand" => array(0, array(), Token::T_NUMBER, function () { return rand(); }), "replace" => array(3, array(Token::T_TEXT, Token::T_TEXT, Token::T_TEXT), Token::T_TEXT, function ($a, $b, $c) { return str_replace($a, $b, $c); }), "round" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return round($a); }), "sin" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return sin($a); }), "sinh" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return sinh($a); }), "size" => array(1, array(Token::T_ARRAY), Token::T_NUMBER, function ($a) { return count($a); }), "split" => array(2, array(Token::T_TEXT, Token::T_TEXT), Token::T_ARRAY, function ($a, $b) { return explode($a, $b); }), "sqrt" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return sqrt($a); }), "substr" => array(3, array(Token::T_TEXT, Token::T_NUMBER, Token::T_NUMBER), Token::T_TEXT, function ($a, $b, $c) { return substr($a, $b - 1, $c); }), "sum" => array(-1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { $s = 0; foreach ($a as $v) { if (isset($v)) { $s += $v; } } return $s; }), "tan" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return tan($a); }), "tanh" => array(1, array(Token::T_NUMBER), Token::T_NUMBER, function ($a) { return tanh($a); }), "upper" => array(1, array(Token::T_TEXT), Token::T_TEXT, function ($a) { return strtoupper($a); }), "workdays" => array(2, array(Token::T_DATE, Token::T_DATE), Token::T_NUMBER, function ($a, $b) { return Expression::workdays($a, $b); }), "year" => array(1, array(Token::T_DATE), Token::T_NUMBER, function ($a) { return (double) $a->format('Y'); })); if ($func->value == "defined") { if (count($args) < 1) { throw new \Exception("Illegal number (" . count($args) . ") of operands for function" . $func); } $arg = array_pop($args); if ($arg->isVariable()) { return new Token(Token::T_BOOLEAN, false); } if ($arg->value === null || $arg->value == "") { return new Token(Token::T_BOOLEAN, false); } return new Token(Token::T_BOOLEAN, true); } if (!isset($functions[$func->value])) { throw new \Exception("Unknown function : " . $func); } $argc = $functions[$func->value][0]; $variableArgsCount = false; if ($argc == -1) { $argc = count($args); $variableArgsCount = true; } if (count($args) < $argc) { throw new \Exception("Illegal number (" . count($args) . ") of operands for function" . $func); } $argv = array(); for (; $argc > 0; --$argc) { $arg = array_pop($args); if (!$variableArgsCount) { if ($arg->isVariable()) { return new Token(Token::T_UNDEFINED, array($arg)); } $type = $functions[$func->value][1][$argc - 1]; if ($arg->type != $type) { $expected = ""; switch ($type) { case Token::T_NUMBER: $expected = "number"; break; case Token::T_DATE: $expected = "date"; break; case Token::T_BOOLEAN: $expected = "boolean"; break; case Token::T_TEXT: $expected = "text"; break; case Token::T_ARRAY: $expected = "array"; break; } throw new \Exception("Illegal type for argument '" . $arg . "' : operand must be a " . $expected . " for " . $func); } array_unshift($argv, $arg->value); } else { if ($arg->isVariable()) { unset($arg->value); } else { array_unshift($argv, $arg->value); } } } if ($variableArgsCount) { $argv = array($argv); } return new Token($functions[$func->value][2], call_user_func_array($functions[$func->value][3], $argv)); }