%PDF- %PDF-
| Direktori : /proc/self/root/proc/10576/cwd/home/bitrix/www/bitrix/modules/bizproc/classes/general/ |
| Current File : //proc/self/root/proc/10576/cwd/home/bitrix/www/bitrix/modules/bizproc/classes/general/calc.php |
<?
class CBPCalc
{
private $activity;
private $arErrorsList = array();
private static $weekHolidays;
private static $yearHolidays;
private static $startWorkDay;
private static $endWorkDay;
public function __construct($activity)
{
/** @var CBPActivity activity */
$this->activity = $activity;
}
private function GetVariableValue($variable)
{
$variable = trim($variable);
if (!preg_match(CBPActivity::ValuePattern, $variable))
return null;
return $this->activity->ParseValue($variable);
}
private function SetError($errnum, $errstr = '')
{
$this->arErrorsList[] = array($errnum, str_replace('#STR#', $errstr, $this->arAvailableErrors[$errnum]));
}
public function GetErrors()
{
return $this->arErrorsList;
}
/*
Return array of polish notation
array(
key => array(value, self::Operation | self::Variable | self::Constant)
)
*/
private function GetPolishNotation($text)
{
$text = trim($text);
if (substr($text, 0, 1) === '=')
$text = substr($text, 1);
if (strpos($text, '{{=') === 0 && substr($text, -2) == '}}')
{
$text = substr($text, 3);
$text = substr($text, 0, -2);
}
if (strlen($text) <= 0)
{
$this->SetError(1);
return false;
}
$arPolishNotation = array();
$arStack = array();
$prev = '';
$preg = '/
\s*\(\s* |
\s*\)\s* |
\s*,\s* | # Combine ranges of variables
\s*;\s* | # Combine ranges of variables
\s*=\s* |
\s*<=\s* |
\s*>=\s* |
\s*<>\s* |
\s*<\s* |
\s*>\s* |
\s*&\s* | # String concatenation
\s*\+\s* | # Addition or unary plus
\s*-\s* |
\s*\*\s* |
\s*\/\s* |
\s*\^\s* | # Exponentiation
\s*%\s* | # Percent
\s*[\d\.]+\s* | # Numbers
\s*\'[^\']*\'\s* | # String constants in apostrophes
\s*"[^"]*"\s* | # String constants in quotes
(\s*\w+\s*\(\s*) | # Function names
\s*'.CBPActivity::ValueInternalPattern.'\s* | # Variables
(?<error>.+) # Any erroneous substring
/xi';
while (preg_match($preg, $text, $match))
{
if (isset($match['error']))
{
$this->SetError(2, $match['error']);
return false;
}
$str = trim($match[0]);
if ($str === ",")
$str = ";";
if (isset($match[1]) && $match[1])
{
$str = strtolower($str);
list($name, $left) = explode('(', $str);
$name = trim($name);
if (isset($this->arAvailableFunctions[$name]))
{
if (!$arStack)
{
array_unshift($arStack, array($name, $this->arPriority['f']));
}
else
{
while ($this->arPriority['f'] <= $arStack[0][1])
{
$op = array_shift($arStack);
$arPolishNotation[] = array($op[0], self::Operation);
if (!$arStack)
break;
}
array_unshift($arStack, array($name, $this->arPriority['f']));
}
}
else
{
$this->SetError(3, $name);
return false;
}
$str = '(';
}
if ($str == '-' || $str == '+')
{
if ($prev == '' || in_array($prev, array('(', ';', '=', '<=', '>=', '<>', '<', '>', '&', '+', '-', '*', '/', '^')))
$str .= 'm';
}
$prev = $str;
switch ($str)
{
case '(':
array_unshift($arStack, array('(', $this->arPriority['(']));
break;
case ')':
while ($op = array_shift($arStack))
{
if ($op[0] == '(')
break;
$arPolishNotation[] = array($op[0], self::Operation);
}
if ($op == null)
{
$this->SetError(4);
return false;
}
break;
case ';' : case '=' : case '<=': case '>=':
case '<>': case '<' : case '>' : case '&' :
case '+' : case '-' : case '+m': case '-m':
case '*' : case '/' : case '^' : case '%' :
if (!$arStack)
{
array_unshift($arStack, array($str, $this->arPriority[$str]));
break;
}
while ($this->arPriority[$str] <= $arStack[0][1])
{
$op = array_shift($arStack);
$arPolishNotation[] = array($op[0], self::Operation);
if (!$arStack)
break;
}
array_unshift($arStack, array($str, $this->arPriority[$str]));
break;
default:
if (substr($str, 0, 1) == '0' || (int) $str)
{
$arPolishNotation[] = array((float)$str, self::Constant);
break;
}
if (substr($str, 0, 1) == '"' || substr($str, 0, 1) == "'")
{
$arPolishNotation[] = array(substr($str, 1, -1), self::Constant);
break;
}
$arPolishNotation[] = array($str, self::Variable);
}
$text = substr($text, strlen($match[0]));
}
while ($op = array_shift($arStack))
{
if ($op[0] == '(')
{
$this->SetError(5);
return false;
}
$arPolishNotation[] = array($op[0], self::Operation);
}
return $arPolishNotation;
}
public function Calculate($text)
{
if (!$arPolishNotation = $this->GetPolishNotation($text))
return null;
$stack = array();
foreach ($arPolishNotation as $item)
{
switch ($item[1])
{
case self::Constant:
array_unshift($stack, $item[0]);
break;
case self::Variable:
array_unshift($stack, $this->GetVariableValue($item[0]));
break;
case self::Operation:
switch ($item[0])
{
case ';':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
if (!is_array($arg1) || !isset($arg1[0]))
$arg1 = array($arg1);
$arg1[] = $arg2;
array_unshift($stack, $arg1);
break;
case '=':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 == $arg2);
break;
case '<=':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 <= $arg2);
break;
case '>=':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 >= $arg2);
break;
case '<>':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 != $arg2);
break;
case '<':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 < $arg2);
break;
case '>':
$arg2 = array_shift($stack);
$arg1 = array_shift($stack);
array_unshift($stack, $arg1 > $arg2);
break;
case '&':
$arg2 = (string) array_shift($stack);
$arg1 = (string) array_shift($stack);
array_unshift($stack, $arg1 . $arg2);
break;
case '+':
$arg2 = (float) array_shift($stack);
$arg1 = (float) array_shift($stack);
array_unshift($stack, $arg1 + $arg2);
break;
case '-':
$arg2 = (float) array_shift($stack);
$arg1 = (float) array_shift($stack);
array_unshift($stack, $arg1 - $arg2);
break;
case '+m':
$arg = (float) array_shift($stack);
array_unshift($stack, $arg);
break;
case '-m':
$arg = (float) array_shift($stack);
array_unshift($stack, (-$arg));
break;
case '*':
$arg2 = (float) array_shift($stack);
$arg1 = (float) array_shift($stack);
array_unshift($stack, $arg1 * $arg2);
break;
case '/':
$arg2 = (float) array_shift($stack);
$arg1 = (float) array_shift($stack);
if (0 == $arg2)
{
$this->SetError(6);
return null;
}
array_unshift($stack, $arg1 / $arg2);
break;
case '^':
$arg2 = (float) array_shift($stack);
$arg1 = (float) array_shift($stack);
array_unshift($stack, pow($arg1, $arg2));
break;
case '%':
$arg = (float) array_shift($stack);
array_unshift($stack, $arg / 100);
break;
default:
$func = $this->arAvailableFunctions[$item[0]]['func'];
if ($this->arAvailableFunctions[$item[0]]['args'])
{
$arg = array_shift($stack);
$val = $this->$func($arg);
}
else
{
$val = $this->$func();
}
$error = is_float($val) && (is_nan($val) || is_infinite($val));
if ($error)
{
$this->SetError(8, $item[0]);
return null;
}
array_unshift($stack, $val);
}
}
}
if (count($stack) > 1)
{
$this->SetError(7);
return null;
}
return array_shift($stack);
}
private function ArrgsToArray($args)
{
if (!is_array($args))
return array($args);
$result = array();
foreach ($args as $arg)
{
if (!is_array($arg))
{
$result[] = $arg;
}
else
{
foreach ($this->ArrgsToArray($arg) as $val)
$result[] = $val;
}
}
return $result;
}
private function FunctionAbs($num)
{
return abs((float) $num);
}
private function FunctionAnd($args)
{
if (!is_array($args))
return (boolean) $args;
$args = $this->ArrgsToArray($args);
foreach ($args as $arg)
{
if (!$arg)
return false;
}
return true;
}
private function FunctionDateAdd($args)
{
if (!is_array($args))
$args = array($args);
$ar = $this->ArrgsToArray($args);
$date = array_shift($ar);
$interval = array_shift($ar);
if (($date = $this->makeTimestamp($date)) === false)
return null;
if (($interval == null) || (strlen($interval) <= 0))
return $date;
// 1Y2M3D4H5I6S, -4 days 5 hours, 1month, 5h
$interval = trim($interval);
$bMinus = false;
if (substr($interval, 0, 1) === "-")
{
$interval = substr($interval, 1);
$bMinus = true;
}
static $arMap = array("y" => "YYYY", "year" => "YYYY", "years" => "YYYY",
"m" => "MM", "month" => "MM", "months" => "MM",
"d" => "DD", "day" => "DD", "days" => "DD",
"h" => "HH", "hour" => "HH", "hours" => "HH",
"i" => "MI", "min" => "MI", "minute" => "MI", "minutes" => "MI",
"s" => "SS", "sec" => "SS", "second" => "SS", "seconds" => "SS",
);
$arInterval = array();
while (preg_match('/\s*([\d]+)\s*([a-z]+)\s*/i', $interval, $match))
{
$match2 = strtolower($match[2]);
if (array_key_exists($match2, $arMap))
$arInterval[$arMap[$match2]] = ($bMinus ? -intval($match[1]) : intval($match[1]));
$p = strpos($interval, $match[0]);
$interval = substr($interval, $p + strlen($match[0]));
}
$newDate = AddToTimeStamp($arInterval, $date);
return ConvertTimeStamp($newDate, "FULL");
}
private function FunctionWorkDateAdd($args)
{
if (!is_array($args))
$args = array($args);
$ar = $this->ArrgsToArray($args);
$date = array_shift($ar);
$paramInterval = array_shift($ar);
if (($date = $this->makeTimestamp($date)) === false)
return null;
if (($paramInterval == null) || (strlen($paramInterval) <= 0) || !CModule::IncludeModule('calendar'))
return $date;
$paramInterval = trim($paramInterval);
$multiplier = 1;
if (substr($paramInterval, 0, 1) === "-")
{
$paramInterval = substr($paramInterval, 1);
$multiplier = -1;
}
$workDayInterval = $this->getWorkDayInterval();
$intervalMap = array("d" => $workDayInterval, "day" => $workDayInterval, "days" => $workDayInterval,
"h" => 3600, "hour" => 3600, "hours" => 3600,
"i" => 60, "min" => 60, "minute" => 60, "minutes" => 60,
);
$interval = 0;
while (preg_match('/\s*([\d]+)\s*([a-z]+)\s*/i', $paramInterval, $match))
{
$match2 = strtolower($match[2]);
if (array_key_exists($match2, $intervalMap))
$interval += intval($match[1]) * $intervalMap[$match2];
$p = strpos($paramInterval, $match[0]);
$paramInterval = substr($paramInterval, $p + strlen($match[0]));
}
$date = $this->getNearestWorkTime($date, $multiplier);
if ($interval)
{
$days = (int) floor($interval / $workDayInterval);
$hours = $interval % $workDayInterval;
$remainTimestamp = $this->getWorkDayRemainTimestamp($date, $multiplier);
if ($days)
$date = $this->addWorkDay($date, $days * $multiplier);
if ($hours > $remainTimestamp)
{
$date += $multiplier < 0 ? -$remainTimestamp -60 : $remainTimestamp + 60;
$date = $this->getNearestWorkTime($date, $multiplier) + (($hours - $remainTimestamp) * $multiplier);
}
else
$date += $multiplier * $hours;
}
return ConvertTimeStamp($date, "FULL");
}
private function makeTimestamp($date)
{
if (!$date)
return false;
if (intval($date)."!" === $date."!")
return $date;
if (($result = MakeTimeStamp($date, FORMAT_DATETIME)) === false)
{
if (($result = MakeTimeStamp($date, FORMAT_DATE)) === false)
{
if (($result = MakeTimeStamp($date, "YYYY-MM-DD HH:MI:SS")) === false)
{
$result = MakeTimeStamp($date, "YYYY-MM-DD");
}
}
}
return $result;
}
private function getWorkDayTimestamp($date)
{
return date('H', $date) * 3600 + date('i', $date) * 60;
}
private function getWorkDayRemainTimestamp($date, $multiplier = 1)
{
$dayTs = $this->getWorkDayTimestamp($date);
list ($startSeconds, $endSeconds) = $this->getCalendarWorkTime();
return $multiplier < 0 ? $dayTs - $startSeconds :$endSeconds - $dayTs;
}
private function getWorkDayInterval()
{
list ($startSeconds, $endSeconds) = $this->getCalendarWorkTime();
return $endSeconds - $startSeconds;
}
private function isHoliday($date)
{
list($weekHolidays, $yearHolidays) = $this->getCalendarHolidays();
$dayOfWeek = date('w', $date);
if (in_array($dayOfWeek, $weekHolidays))
return true;
$dayOfYear = date('j.n', $date);
if (in_array($dayOfYear, $yearHolidays, true))
return true;
return false;
}
private function isWorkTime($date)
{
$dayTs = $this->getWorkDayTimestamp($date);
list ($startSeconds, $endSeconds) = $this->getCalendarWorkTime();
return ($dayTs >= $startSeconds && $dayTs <= $endSeconds);
}
private function getNearestWorkTime($date, $multiplier = 1)
{
$reverse = $multiplier < 0;
list ($startSeconds, $endSeconds) = $this->getCalendarWorkTime();
$dayTimeStamp = $this->getWorkDayTimestamp($date);
if ($this->isHoliday($date))
{
$date -= $dayTimeStamp;
$date += $reverse? -86400 + $endSeconds : $startSeconds;
$dayTimeStamp = $reverse? $endSeconds : $startSeconds;
}
if (!$this->isWorkTime($date))
{
$date -= $dayTimeStamp;
if ($dayTimeStamp < $startSeconds)
{
$date += $reverse? -86400 + $endSeconds : $startSeconds;
}
else
{
$date += $reverse? $endSeconds : 86400 + $startSeconds;
}
}
if ($this->isHoliday($date))
$date = $this->addWorkDay($date, $reverse? -1 : 1);
return $date;
}
private function addWorkDay($date, $days)
{
$delta = 86400;
if ($days < 0)
$delta *= -1;
$days = abs($days);
$iterations = 0;
while ($days > 0 && $iterations < 1000)
{
++$iterations;
$date += $delta;
if ($this->isHoliday($date))
continue;
--$days;
}
return $date;
}
private function getCalendarHolidays()
{
if (static::$yearHolidays === null)
{
$calendarSettings = CCalendar::GetSettings();
$weekHolidays = array(0, 6);
$yearHolidays = array();
if (isset($calendarSettings['week_holidays']))
{
$weekDays = array('SU' => 0, 'MO' => 1, 'TU' => 2, 'WE' => 3, 'TH' => 4, 'FR' => 5, 'SA' => 6);
$weekHolidays = array();
foreach ($calendarSettings['week_holidays'] as $day)
$weekHolidays[] = $weekDays[$day];
}
if (isset($calendarSettings['year_holidays']))
{
foreach (explode(',', $calendarSettings['year_holidays']) as $yearHoliday)
{
$ardate = explode('.', trim($yearHoliday));
if (count($ardate) == 2 && $ardate[0] && $ardate[1])
$yearHolidays[] = (int)$ardate[0].'.'.(int)$ardate[1];
}
}
static::$weekHolidays = $weekHolidays;
static::$yearHolidays = $yearHolidays;
}
return array(static::$weekHolidays, static::$yearHolidays);
}
private function getCalendarWorkTime()
{
if (static::$startWorkDay === null)
{
$startSeconds = 0;
$endSeconds = 24 * 3600 - 1;
$calendarSettings = CCalendar::GetSettings();
if (!empty($calendarSettings['work_time_start']))
{
$time = explode('.', $calendarSettings['work_time_start']);
$startSeconds = $time[0] * 3600;
if (!empty($time[1]))
$startSeconds += $time[1] * 60;
}
if (!empty($calendarSettings['work_time_end']))
{
$time = explode('.', $calendarSettings['work_time_end']);
$endSeconds = $time[0] * 3600;
if (!empty($time[1]))
$endSeconds += $time[1] * 60;
}
static::$startWorkDay = $startSeconds;
static::$endWorkDay = $endSeconds;
}
return array(static::$startWorkDay, static::$endWorkDay);
}
private function FunctionAddWorkDays($args)
{
if (!is_array($args))
$args = array($args);
$ar = $this->ArrgsToArray($args);
$date = array_shift($ar);
$days = (int) array_shift($ar);
if (($date = $this->makeTimestamp($date)) === false)
return null;
if ($days === 0 || !CModule::IncludeModule('calendar'))
return $date;
$date = $this->addWorkDay($date, $days);
return ConvertTimeStamp($date, "FULL");
}
private function FunctionIsWorkDay($args)
{
if (!CModule::IncludeModule('calendar'))
return null;
if (!is_array($args))
$args = array($args);
$ar = $this->ArrgsToArray($args);
$date = array_shift($ar);
if (($date = $this->makeTimestamp($date)) === false)
return null;
return !$this->isHoliday($date);
}
private function FunctionIsWorkTime($args)
{
if (!CModule::IncludeModule('calendar'))
return null;
if (!is_array($args))
$args = array($args);
$ar = $this->ArrgsToArray($args);
$date = array_shift($ar);
if (($date = $this->makeTimestamp($date)) === false)
return null;
return !$this->isHoliday($date) && $this->isWorkTime($date);
}
private function FunctionDateDiff($args)
{
if (!is_array($args))
$args = array($args);
$ar = $this->ArrgsToArray($args);
$date1 = array_shift($ar);
$date2 = array_shift($ar);
$format = array_shift($ar);
if ($date1 == null || $date2 == null)
return null;
$df = $GLOBALS["DB"]->DateFormatToPHP(FORMAT_DATETIME);
$df2 = $GLOBALS["DB"]->DateFormatToPHP(FORMAT_DATE);
$date1Formatted = \DateTime::createFromFormat($df, $date1);
if ($date1Formatted === false)
{
$date1Formatted = \DateTime::createFromFormat($df2, $date1);
if ($date1Formatted)
{
$date1Formatted->setTime(0, 0);
}
}
$date2Formatted = \DateTime::createFromFormat($df, $date2);
if ($date2Formatted === false)
{
$date2Formatted = \DateTime::createFromFormat($df2, $date2);
if ($date2Formatted)
{
$date2Formatted->setTime(0, 0);
}
}
if ($date1Formatted === false || $date2Formatted === false)
{
return null;
}
$interval = $date1Formatted->diff($date2Formatted);
return $interval === false? null : $interval->format($format);
}
private function FunctionDate($args)
{
$ar = $this->ArrgsToArray($args);
$format = array_shift($ar);
$date = array_shift($ar);
if (!$format || !is_string($format))
{
return null;
}
$ts = $date ? $this->makeTimestamp($date) : time();
if (!$ts)
{
return null;
}
return date($format, $ts);
}
private function FunctionFalse()
{
return false;
}
private function FunctionIf($args)
{
if (!is_array($args))
return null;
$expression = (boolean) array_shift($args);
$ifTrue = array_shift($args);
$ifFalse = array_shift($args);
return $expression ? $ifTrue : $ifFalse;
}
private function FunctionIntval($num)
{
return intval($num);
}
private function FunctionFloatval($num)
{
return floatval($num);
}
private function FunctionNumberFormat($args)
{
$ar = $this->ArrgsToArray($args);
$number = (float) array_shift($ar);
$decimals = (int) (array_shift($ar) ?: 0);
$decPoint = array_shift($ar);
if ($decPoint === null)
{
$decPoint = '.';
}
$decPoint = (string) $decPoint;
$thousandsSeparator = array_shift($ar);
if ($thousandsSeparator === null)
{
$thousandsSeparator = ',';
}
$thousandsSeparator = (string) $thousandsSeparator;
return number_format($number, $decimals, $decPoint, $thousandsSeparator);
}
private function FunctionMin($args)
{
if (!is_array($args))
return (float) $args;
foreach ($args as &$arg)
$arg = (float) $arg;
$args = $this->ArrgsToArray($args);
return min($args);
}
private function FunctionMax($args)
{
if (!is_array($args))
return (float) $args;
foreach ($args as &$arg)
$arg = (float) $arg;
$args = $this->ArrgsToArray($args);
return max($args);
}
private function FunctionRand($args)
{
$ar = $this->ArrgsToArray($args);
$min = (int)array_shift($ar);
$max = (int)array_shift($ar);
if (!$max)
{
$max = mt_getrandmax();
}
return mt_rand($min, $max);
}
private function FunctionRandString($args)
{
$ar = $this->ArrgsToArray($args);
$len = (int)array_shift($ar);
return \randString($len);
}
private function FunctionRound($args)
{
$ar = $this->ArrgsToArray($args);
$val = (float)array_shift($ar);
$precision = (int)array_shift($ar);
return round($val, $precision);
}
private function FunctionCeil($num)
{
return ceil($num);
}
private function FunctionFloor($num)
{
return floor($num);
}
private function FunctionNot($arg)
{
return !((boolean) $arg);
}
private function FunctionOr($args)
{
if (!is_array($args))
return (boolean) $args;
$args = $this->ArrgsToArray($args);
foreach ($args as $arg)
{
if ($arg)
return true;
}
return false;
}
private function FunctionSubstr($args)
{
if (!is_array($args))
$args = array($args);
$ar = $this->ArrgsToArray($args);
$str = array_shift($ar);
$pos = array_shift($ar);
$len = array_shift($ar);
if (($str == null) || ($str === ""))
return null;
if ($pos == null)
$pos = 0;
if ($len != null)
return substr($str, $pos, $len);
return substr($str, $pos);
}
private function FunctionStrpos($args)
{
$ar = $this->ArrgsToArray($args);
$haystack = (string)array_shift($ar);
$needle = (string)array_shift($ar);
$offset = (int)array_shift($ar);
return strpos($haystack, $needle, $offset);
}
private function FunctionStrlen($args)
{
$ar = $this->ArrgsToArray($args);
$str = array_shift($ar);
if (!is_scalar($str))
{
return null;
}
$str = (string) $str;
return strlen($str);
}
private function FunctionUrlencode($args)
{
$ar = $this->ArrgsToArray($args);
$str = array_shift($ar);
if (!is_scalar($str))
{
if (is_array($str))
{
$str = implode(", ", CBPHelper::MakeArrayFlat($str));
}
else
{
return null;
}
}
$str = (string) $str;
return urlencode($str);
}
private function FunctionConvert($args)
{
if (!is_array($args))
$args = array($args);
$ar = $this->ArrgsToArray($args);
$val = array_shift($ar);
$type = array_shift($ar);
$attr = array_shift($ar);
$type = strtolower($type);
if ($type === 'printableuserb24')
{
$result = array();
$users = CBPHelper::StripUserPrefix($val);
if (!is_array($users))
$users = array($users);
foreach ($users as $userId)
{
$db = CUser::GetByID($userId);
if ($ar = $db->GetNext())
{
$ix = randString(5);
$attr = (!empty($attr) ? 'href="'.$attr.'"' : 'href="#" onClick="return false;"');
$result[] = '<a class="feed-post-user-name" id="bp_'.$userId.'_'.$ix.'" '.$attr.' bx-post-author-id="'.$userId.'" bx-post-author-gender="'.$ar['PERSONAL_GENDER'].'" bx-tooltip-user-id="'.$userId.'">'.CUser::FormatName(CSite::GetNameFormat(false), $ar, false).'</a>';
}
}
$result = implode(", ", $result);
}
elseif ($type == 'printableuser')
{
$result = array();
$users = CBPHelper::StripUserPrefix($val);
if (!is_array($users))
$users = array($users);
foreach ($users as $userId)
{
$db = CUser::GetByID($userId);
if ($ar = $db->GetNext())
$result[] = CUser::FormatName(CSite::GetNameFormat(false), $ar, false);
}
$result = implode(", ", $result);
}
else
{
$result = $val;
}
return $result;
}
private function FunctionTrue()
{
return true;
}
private function FunctionMerge($args)
{
if (!is_array($args))
$args = array();
foreach ($args as &$a)
{
$a = (array)$a;
}
return call_user_func_array('array_merge', $args);
}
// Operation priority
private $arPriority = array(
'(' => 0, ')' => 1, ';' => 2, '=' => 3, '<' => 3, '>' => 3,
'<=' => 3, '>=' => 3, '<>' => 3, '&' => 4, '+' => 5, '-' => 5,
'*' => 6, '/' => 6, '^' => 7, '%' => 8, '-m' => 9, '+m' => 9,
' ' => 10, ':' => 11, 'f' => 12,
);
// Allowable functions
private $arAvailableFunctions = array(
'abs' => array('args' => true, 'func' => 'FunctionAbs'),
'and' => array('args' => true, 'func' => 'FunctionAnd'),
'date' => array('args' => true, 'func' => 'FunctionDate'),
'dateadd' => array('args' => true, 'func' => 'FunctionDateAdd'),
'datediff' => array('args' => true, 'func' => 'FunctionDateDiff'),
'false' => array('args' => false, 'func' => 'FunctionFalse'),
'if' => array('args' => true, 'func' => 'FunctionIf'),
'intval' => array('args' => true, 'func' => 'FunctionIntval'),
'floatval' => array('args' => true, 'func' => 'FunctionFloatval'),
'numberformat' => array('args' => true, 'func' => 'FunctionNumberFormat'),
'min' => array('args' => true, 'func' => 'FunctionMin'),
'max' => array('args' => true, 'func' => 'FunctionMax'),
'rand' => array('args' => true, 'func' => 'FunctionRand'),
'round' => array('args' => true, 'func' => 'FunctionRound'),
'ceil' => array('args' => true, 'func' => 'FunctionCeil'),
'floor' => array('args' => true, 'func' => 'FunctionFloor'),
'not' => array('args' => true, 'func' => 'FunctionNot'),
'or' => array('args' => true, 'func' => 'FunctionOr'),
'substr' => array('args' => true, 'func' => 'FunctionSubstr'),
'strpos' => array('args' => true, 'func' => 'FunctionStrpos'),
'strlen' => array('args' => true, 'func' => 'FunctionStrlen'),
'randstring' => array('args' => true, 'func' => 'FunctionRandString'),
'true' => array('args' => false, 'func' => 'FunctionTrue'),
'convert' => array('args' => true, 'func' => 'FunctionConvert'),
'merge' => array('args' => true, 'func' => 'FunctionMerge'),
'addworkdays' => array('args' => true, 'func' => 'FunctionAddWorkDays'),
'workdateadd' => array('args' => true, 'func' => 'FunctionWorkDateAdd'),
'isworkday' => array('args' => true, 'func' => 'FunctionIsWorkDay'),
'isworktime' => array('args' => true, 'func' => 'FunctionIsWorkTime'),
'urlencode' => array('args' => true, 'func' => 'FunctionUrlencode'),
);
// Allowable errors
private $arAvailableErrors = array(
0 => 'Incorrect variable name - "#STR#"',
1 => 'Empty',
2 => 'Syntax error "#STR#"',
3 => 'Unknown function "#STR#"',
4 => 'Unmatched closing bracket ")"',
5 => 'Unmatched opening bracket "("',
6 => 'Division by zero',
7 => 'Incorrect order of operands',
8 => 'Incorrect arguments of function "#STR#"',
);
const Operation = 0;
const Variable = 1;
const Constant = 2;
}