Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/zabbix/zabbix.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Vladishev <aleksander.vladishev@zabbix.com>2020-05-03 17:30:06 +0300
committerAlexander Vladishev <aleksander.vladishev@zabbix.com>2020-05-03 17:30:06 +0300
commit8d9be8910e07b28b4510482c0720425f8ed8233e (patch)
tree8e5ca25c795ad586db165fecff35c3f3cd61c19b /ui/app/controllers/CControllerPopupTriggerExpr.php
parente635eaceb24410622a928043971b8e9d89b1049b (diff)
A.F.I..... [ZBX-17667] moved "frontends/php" to "ui" directory
Diffstat (limited to 'ui/app/controllers/CControllerPopupTriggerExpr.php')
-rw-r--r--ui/app/controllers/CControllerPopupTriggerExpr.php749
1 files changed, 749 insertions, 0 deletions
diff --git a/ui/app/controllers/CControllerPopupTriggerExpr.php b/ui/app/controllers/CControllerPopupTriggerExpr.php
new file mode 100644
index 00000000000..65de11fcc28
--- /dev/null
+++ b/ui/app/controllers/CControllerPopupTriggerExpr.php
@@ -0,0 +1,749 @@
+<?php
+/*
+** Zabbix
+** Copyright (C) 2001-2020 Zabbix SIA
+**
+** This program is free software; you can redistribute it and/or modify
+** it under the terms of the GNU General Public License as published by
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+**/
+
+
+class CControllerPopupTriggerExpr extends CController {
+ private $metrics = [];
+ private $param1SecCount = [];
+ private $param1Sec = [];
+ private $param1Str = [];
+ private $param2SecCount = [];
+ private $param2SecMode = [];
+ private $param3SecVal = [];
+ private $param3SecPercent = [];
+ private $paramSecIntCount = [];
+ private $paramForecast = [];
+ private $paramTimeleft = [];
+ private $allowedTypesAny = [];
+ private $allowedTypesNumeric = [];
+ private $allowedTypesStr = [];
+ private $allowedTypesLog = [];
+ private $allowedTypesInt = [];
+ private $functions = [];
+ private $operators = [];
+
+ protected function init() {
+ $this->disableSIDvalidation();
+
+ $this->metrics = [
+ PARAM_TYPE_TIME => _('Time'),
+ PARAM_TYPE_COUNTS => _('Count')
+ ];
+
+ /*
+ * C - caption
+ * T - type
+ * M - metrics
+ * A - asterisk
+ */
+ $this->param1SecCount = [
+ 'last' => [
+ 'C' => _('Last of').' (T)',
+ 'T' => T_ZBX_INT,
+ 'M' => $this->metrics,
+ 'A' => true
+ ],
+ 'shift' => [
+ 'C' => _('Time shift'),
+ 'T' => T_ZBX_INT,
+ 'A' => false
+ ]
+ ];
+
+ $this->param1Sec = [
+ 'last' => [
+ 'C' => _('Last of').' (T)',
+ 'T' => T_ZBX_INT,
+ 'A' => true
+ ]
+ ];
+
+ $this->param1Str = [
+ 'pattern' => [
+ 'C' => 'T',
+ 'T' => T_ZBX_STR,
+ 'A' => false
+ ]
+ ];
+
+ $this->param2SecCount = [
+ 'pattern' => [
+ 'C' => 'V',
+ 'T' => T_ZBX_STR,
+ 'A' => false
+ ],
+ 'last' => [
+ 'C' => _('Last of').' (T)',
+ 'T' => T_ZBX_INT,
+ 'M' => $this->metrics,
+ 'A' => false
+ ]
+ ];
+
+ $this->param2SecMode = [
+ 'last' => [
+ 'C' => _('Last of').' (T)',
+ 'T' => T_ZBX_INT,
+ 'A' => true
+ ],
+ 'mode' => [
+ 'C' => 'Mode',
+ 'T' => T_ZBX_STR,
+ 'A' => false
+ ]
+ ];
+
+ $this->param3SecVal = [
+ 'last' => [
+ 'C' => _('Last of').' (T)',
+ 'T' => T_ZBX_INT,
+ 'M' => $this->metrics,
+ 'A' => true
+ ],
+ 'v' => [
+ 'C' => 'V',
+ 'T' => T_ZBX_STR,
+ 'A' => false
+ ],
+ 'o' => [
+ 'C' => 'O',
+ 'T' => T_ZBX_STR,
+ 'A' => false
+ ],
+ 'shift' => [
+ 'C' => _('Time shift'),
+ 'T' => T_ZBX_INT,
+ 'A' => false
+ ]
+ ];
+
+ $this->param3SecPercent = [
+ 'last' => [
+ 'C' => _('Last of').' (T)',
+ 'T' => T_ZBX_INT,
+ 'M' => $this->metrics,
+ 'A' => true
+ ],
+ 'shift' => [
+ 'C' => _('Time shift'),
+ 'T' => T_ZBX_INT,
+ 'A' => false
+ ],
+ 'p' => [
+ 'C' => _('Percentage').' (P)',
+ 'T' => T_ZBX_DBL,
+ 'A' => true
+ ]
+ ];
+
+ $this->paramSecIntCount = [
+ 'last' => [
+ 'C' => _('Last of').' (T)',
+ 'T' => T_ZBX_INT,
+ 'M' => $this->metrics,
+ 'A' => true
+ ],
+ 'mask' => [
+ 'C' => _('Mask'),
+ 'T' => T_ZBX_STR,
+ 'A' => true
+ ],
+ 'shift' => [
+ 'C' => _('Time shift'),
+ 'T' => T_ZBX_INT,
+ 'A' => false
+ ]
+ ];
+
+ $this->paramForecast = [
+ 'last' => [
+ 'C' => _('Last of').' (T)',
+ 'T' => T_ZBX_INT,
+ 'M' => $this->metrics,
+ 'A' => true
+ ],
+ 'shift' => [
+ 'C' => _('Time shift'),
+ 'T' => T_ZBX_INT,
+ 'A' => false
+ ],
+ 'time' => [
+ 'C' => _('Time').' (t)',
+ 'T' => T_ZBX_INT,
+ 'A' => true
+ ],
+ 'fit' => [
+ 'C' => _('Fit'),
+ 'T' => T_ZBX_STR,
+ 'A' => false
+ ],
+ 'mode' => [
+ 'C' => _('Mode'),
+ 'T' => T_ZBX_STR,
+ 'A' => false
+ ]
+ ];
+
+ $this->paramTimeleft = [
+ 'last' => [
+ 'C' => _('Last of').' (T)',
+ 'T' => T_ZBX_INT,
+ 'M' => $this->metrics,
+ 'A' => true
+ ],
+ 'shift' => [
+ 'C' => _('Time shift'),
+ 'T' => T_ZBX_INT,
+ 'A' => false
+ ],
+ 't' => [
+ 'C' => _('Threshold'),
+ 'T' => T_ZBX_DBL,
+ 'A' => true
+ ],
+ 'fit' => [
+ 'C' => _('Fit'),
+ 'T' => T_ZBX_STR,
+ 'A' => false
+ ]
+ ];
+
+ $this->allowedTypesAny = [
+ ITEM_VALUE_TYPE_FLOAT => 1,
+ ITEM_VALUE_TYPE_STR => 1,
+ ITEM_VALUE_TYPE_LOG => 1,
+ ITEM_VALUE_TYPE_UINT64 => 1,
+ ITEM_VALUE_TYPE_TEXT => 1
+ ];
+
+ $this->allowedTypesNumeric = [
+ ITEM_VALUE_TYPE_FLOAT => 1,
+ ITEM_VALUE_TYPE_UINT64 => 1
+ ];
+
+ $this->allowedTypesStr = [
+ ITEM_VALUE_TYPE_STR => 1,
+ ITEM_VALUE_TYPE_LOG => 1,
+ ITEM_VALUE_TYPE_TEXT => 1
+ ];
+
+ $this->allowedTypesLog = [
+ ITEM_VALUE_TYPE_LOG => 1
+ ];
+
+ $this->allowedTypesInt = [
+ ITEM_VALUE_TYPE_UINT64 => 1
+ ];
+
+ $this->functions = [
+ 'abschange' => [
+ 'description' => _('abschange() - Absolute difference between last and previous value'),
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'avg' => [
+ 'description' => _('avg() - Average value of a period T'),
+ 'params' => $this->param1SecCount,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'delta' => [
+ 'description' => _('delta() - Difference between MAX and MIN value of a period T'),
+ 'params' => $this->param1SecCount,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'change' => [
+ 'description' => _('change() - Difference between last and previous value'),
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'count' => [
+ 'description' => _('count() - Number of successfully retrieved values V (which fulfill operator O) for period T'),
+ 'params' => $this->param3SecVal,
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'diff' => [
+ 'description' => _('diff() - Difference between last and preceding values (1 - true, 0 - false)'),
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>']
+ ],
+ 'last' => [
+ 'description' => _('last() - Last (most recent) T value'),
+ 'params' => $this->param1SecCount,
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'max' => [
+ 'description' => _('max() - Maximum value for period T'),
+ 'params' => $this->param1SecCount,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'min' => [
+ 'description' => _('min() - Minimum value for period T'),
+ 'params' => $this->param1SecCount,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'percentile' => [
+ 'description' => _('percentile() - Percentile P of a period T'),
+ 'params' => $this->param3SecPercent,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'prev' => [
+ 'description' => _('prev() - Previous value'),
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'str' => [
+ 'description' => _('str() - Find string V in last (most recent) value (1 - found, 0 - not found)'),
+ 'params' => $this->param2SecCount,
+ 'allowed_types' => $this->allowedTypesStr,
+ 'operators' => ['=', '<>']
+ ],
+ 'strlen' => [
+ 'description' => _('strlen() - Length of last (most recent) T value in characters'),
+ 'params' => $this->param1SecCount,
+ 'allowed_types' => $this->allowedTypesStr,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'sum' => [
+ 'description' => _('sum() - Sum of values of a period T'),
+ 'params' => $this->param1SecCount,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'date' => [
+ 'description' => _('date() - Current date'),
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'dayofweek' => [
+ 'description' => _('dayofweek() - Day of week'),
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'dayofmonth' => [
+ 'description' => _('dayofmonth() - Day of month'),
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'fuzzytime' => [
+ 'description' => _('fuzzytime() - Difference between item value (as timestamp) and Zabbix server timestamp is less than or equal to T seconds (1 - true, 0 - false)'),
+ 'params' => $this->param1Sec,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>']
+ ],
+ 'regexp' => [
+ 'description' => _('regexp() - Regular expression V matching last value in period T (1 - match, 0 - no match)'),
+ 'params' => $this->param2SecCount,
+ 'allowed_types' => $this->allowedTypesStr,
+ 'operators' => ['=', '<>']
+ ],
+ 'iregexp' => [
+ 'description' => _('iregexp() - Regular expression V matching last value in period T (non case-sensitive; 1 - match, 0 - no match)'),
+ 'params' => $this->param2SecCount,
+ 'allowed_types' => $this->allowedTypesStr,
+ 'operators' => ['=', '<>']
+ ],
+ 'logeventid' => [
+ 'description' => _('logeventid() - Event ID of last log entry matching regular expression T (1 - match, 0 - no match)'),
+ 'params' => $this->param1Str,
+ 'allowed_types' => $this->allowedTypesLog,
+ 'operators' => ['=', '<>']
+ ],
+ 'logseverity' => [
+ 'description' => _('logseverity() - Log severity of the last log entry'),
+ 'allowed_types' => $this->allowedTypesLog,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'logsource' => [
+ 'description' => _('logsource() - Log source of the last log entry matching parameter T (1 - match, 0 - no match)'),
+ 'params' => $this->param1Str,
+ 'allowed_types' => $this->allowedTypesLog,
+ 'operators' => ['=', '<>']
+ ],
+ 'now' => [
+ 'description' => _('now() - Number of seconds since the Epoch'),
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'time' => [
+ 'description' => _('time() - Current time'),
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'nodata' => [
+ 'description' => _('nodata() - No data received during period of time T (1 - true, 0 - false), Mode (strict - ignore proxy time delay in sending data)'),
+ 'params' => $this->param2SecMode,
+ 'allowed_types' => $this->allowedTypesAny,
+ 'operators' => ['=', '<>']
+ ],
+ 'band' => [
+ 'description' => _('band() - Bitwise AND of last (most recent) T value and mask'),
+ 'params' => $this->paramSecIntCount,
+ 'allowed_types' => $this->allowedTypesInt,
+ 'operators' => ['=', '<>']
+ ],
+ 'forecast' => [
+ 'description' => _('forecast() - Forecast for next t seconds based on period T'),
+ 'params' => $this->paramForecast,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ],
+ 'timeleft' => [
+ 'description' => _('timeleft() - Time to reach threshold estimated based on period T'),
+ 'params' => $this->paramTimeleft,
+ 'allowed_types' => $this->allowedTypesNumeric,
+ 'operators' => ['=', '<>', '>', '<', '>=', '<=']
+ ]
+ ];
+
+ CArrayHelper::sort($this->functions, ['description']);
+
+ foreach ($this->functions as $function) {
+ foreach ($function['operators'] as $operator) {
+ $this->operators[$operator] = true;
+ }
+ }
+ }
+
+ protected function checkInput() {
+ $fields = [
+ 'dstfrm' => 'string|fatal',
+ 'dstfld1' => 'string|not_empty',
+ 'expression' => 'string',
+ 'itemid' => 'db items.itemid',
+ 'parent_discoveryid' => 'db items.itemid',
+ 'function' => 'in '.implode(',', array_keys($this->functions)),
+ 'operator' => 'in '.implode(',', array_keys($this->operators)),
+ 'params' => '',
+ 'paramtype' => 'in '.implode(',', [PARAM_TYPE_TIME, PARAM_TYPE_COUNTS]),
+ 'value' => 'string|not_empty',
+ 'hostid' => 'db hosts.hostid',
+ 'groupid' => 'db hosts_groups.hostgroupid',
+ 'add' => 'in 1'
+ ];
+
+ $ret = $this->validateInput($fields);
+
+ if (!$ret) {
+ $output = [];
+ if (($messages = getMessages()) !== null) {
+ $output['errors'] = $messages->toString();
+ }
+
+ if ($this->hasInput('add')) {
+ $this->setResponse(
+ (new CControllerResponseData(['main_block' => json_encode($output)]))->disableView()
+ );
+ }
+ else {
+ $ret = true;
+ }
+ }
+
+ return $ret;
+ }
+
+ protected function checkPermissions() {
+ return true;
+ }
+
+ protected function doAction() {
+ $itemid = $this->getInput('itemid', 0);
+ $function = $this->getInput('function', 'last');
+ $operator = $this->getInput('operator', '=');
+ $param_type = $this->getInput('paramtype', PARAM_TYPE_TIME);
+ $dstfld1 = $this->getInput('dstfld1');
+ $expression = $this->getInput('expression', '');
+ $params = $this->getInput('params', []);
+ $value = $this->getInput('value', 0);
+
+ // Opening the popup when editing an expression in the trigger constructor.
+ if (($dstfld1 === 'expr_temp' || $dstfld1 === 'recovery_expr_temp') && $expression !== '') {
+ $expression = utf8RawUrlDecode($expression);
+
+ $expression_data = new CTriggerExpression();
+ $result = $expression_data->parse($expression);
+
+ if ($result) {
+ $function_macro_tokens = $result->getTokensByType(
+ CTriggerExprParserResult::TOKEN_TYPE_FUNCTION_MACRO
+ );
+
+ if ($function_macro_tokens) {
+ $function_macro_token = $function_macro_tokens[0];
+ $function = $function_macro_token['data']['functionName'];
+
+ // Determine param type.
+ $params = $function_macro_token['data']['functionParams'];
+ $param_number = in_array($function, ['regexp', 'iregexp', 'str']) ? 1 : 0;
+ if (array_key_exists($param_number, $params) && is_string($params[$param_number])
+ && $params[$param_number] !== '' && $params[$param_number][0] === '#'
+ && !in_array($function, ['fuzzytime', 'nodata'])) {
+ $param_type = PARAM_TYPE_COUNTS;
+ $params[$param_number] = substr($params[$param_number], 1);
+ }
+ else {
+ $param_type = PARAM_TYPE_TIME;
+ }
+
+ /*
+ * Try to find an operator and a value.
+ * The value and operator can be extracted only if they immediately follow the item function macro.
+ */
+ $tokens = $result->getTokens();
+ foreach ($tokens as $key => $token) {
+ if ($token['type'] == CTriggerExprParserResult::TOKEN_TYPE_FUNCTION_MACRO) {
+ if (array_key_exists($key + 2, $tokens)
+ && $tokens[$key + 1]['type'] == CTriggerExprParserResult::TOKEN_TYPE_OPERATOR
+ && array_key_exists($function, $this->functions)
+ && in_array($tokens[$key + 1]['value'],
+ $this->functions[$function]['operators'])) {
+ $operator = $tokens[$key + 1]['value'];
+
+ $value = '';
+ $i = 2;
+
+ if (array_key_exists($key + 3, $tokens)
+ && $tokens[$key + 2]['type'] == CTriggerExprParserResult::TOKEN_TYPE_OPERATOR) {
+ $value .= $tokens[$key + 2]['value'];
+ $i++;
+ }
+
+ $value .= ($tokens[$key + $i]['type'] == CTriggerExprParserResult::TOKEN_TYPE_STRING)
+ ? $tokens[$key + $i]['data']['string']
+ : $tokens[$key + $i]['value'];
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ // Find the item.
+ $item = API::Item()->get([
+ 'output' => ['itemid', 'hostid', 'name', 'key_', 'value_type'],
+ 'selectHosts' => ['name'],
+ 'webitems' => true,
+ 'filter' => [
+ 'host' => $function_macro_token['data']['host'],
+ 'key_' => $function_macro_token['data']['item'],
+ 'flags' => null
+ ]
+ ]);
+
+ if (($item = reset($item)) !== false) {
+ $itemid = $item['itemid'];
+ }
+ else {
+ error(_('Unknown host item, no such item in selected host'));
+ }
+ }
+ }
+ }
+ // Opening an empty form or switching a function.
+ else {
+ $item = API::Item()->get([
+ 'output' => ['itemid', 'hostid', 'name', 'key_', 'value_type'],
+ 'selectHosts' => ['host', 'name'],
+ 'itemids' => $itemid,
+ 'webitems' => true,
+ 'filter' => ['flags' => null]
+ ]);
+
+ $item = reset($item);
+ }
+
+ if ($itemid) {
+ $items = CMacrosResolverHelper::resolveItemNames([$item]);
+ $item = $items[0];
+
+ $item_value_type = $item['value_type'];
+ $item_key = $item['key_'];
+ $item_host_data = reset($item['hosts']);
+ $description = $item_host_data['name'].NAME_DELIMITER.$item['name_expanded'];
+ }
+ else {
+ $item_key = '';
+ $description = '';
+ $item_value_type = null;
+ }
+
+ if ($param_type === null && array_key_exists($function, $this->functions)
+ && array_key_exists('params', $this->functions[$function])
+ && array_key_exists('M', $this->functions[$function]['params'])) {
+ $param_type = is_array($this->functions[$function]['params']['M'])
+ ? reset($this->functions[$function]['params']['M'])
+ : $this->functions[$function]['params']['M'];
+ }
+ elseif ($param_type === null) {
+ $param_type = PARAM_TYPE_TIME;
+ }
+
+ $data = [
+ 'parent_discoveryid' => $this->getInput('parent_discoveryid', ''),
+ 'dstfrm' => $this->getInput('dstfrm'),
+ 'dstfld1' => $dstfld1,
+ 'itemid' => $itemid,
+ 'value' => $value,
+ 'params' => $params,
+ 'paramtype' => $param_type,
+ 'item_description' => $description,
+ 'functions' => $this->functions,
+ 'function' => $function,
+ 'operator' => $operator,
+ 'item_key' => $item_key,
+ 'itemValueType' => $item_value_type,
+ 'selectedFunction' => null,
+ 'groupid' => $this->getInput('groupid', 0),
+ 'hostid' => $this->getInput('hostid', 0),
+ ];
+
+ // Check if submitted function is usable with selected item.
+ foreach ($data['functions'] as $id => $f) {
+ if (($data['itemValueType'] === null || array_key_exists($item_value_type, $f['allowed_types']))
+ && $id === $function) {
+ $data['selectedFunction'] = $id;
+ break;
+ }
+ }
+
+ if ($data['selectedFunction'] === null) {
+ $data['selectedFunction'] = 'last';
+ $data['function'] = 'last';
+ }
+
+ // Remove functions that not correspond to chosen item.
+ foreach ($data['functions'] as $id => $f) {
+ if ($data['itemValueType'] !== null && !array_key_exists($data['itemValueType'], $f['allowed_types'])) {
+ unset($data['functions'][$id]);
+
+ // Take first available function from list and change to first available operator for that function.
+ if ($id === $data['function']) {
+ $data['function'] = key($data['functions']);
+ $data['operator'] = reset($data['functions'][$data['function']]['operators']);
+ }
+ }
+ }
+
+ // Create and validate trigger expression before inserting it into textarea field.
+ if ($this->getInput('add', false)) {
+ try {
+ if ($data['item_description']) {
+ if ($data['paramtype'] == PARAM_TYPE_COUNTS
+ && array_key_exists('last', $data['params'])
+ && $data['params']['last'] !== '') {
+ $data['params']['last'] = zbx_is_int($data['params']['last'])
+ ? '#'.$data['params']['last']
+ : $data['params']['last'];
+ }
+ elseif ($data['paramtype'] == PARAM_TYPE_TIME && in_array($function, ['last', 'band', 'strlen'])) {
+ $data['params']['last'] = '';
+ }
+
+ // Quote function param.
+ $quoted_params = [];
+ foreach ($data['params'] as $param) {
+ $quoted_params[] = quoteFunctionParam($param);
+ }
+
+ $data['expression'] = sprintf('{%s:%s.%s(%s)}%s%s',
+ $item_host_data['host'],
+ $data['item_key'],
+ $function,
+ rtrim(implode(',', $quoted_params), ','),
+ $operator,
+ CTriggerExpression::quoteString($data['value'])
+ );
+
+ // Validate trigger expression.
+ $trigger_expression = new CTriggerExpression();
+
+ if ($trigger_expression->parse($data['expression'])) {
+ $expression_data = reset($trigger_expression->expressions);
+
+ // Validate trigger function.
+ $trigger_function_validator = new CFunctionValidator();
+ $is_valid = $trigger_function_validator->validate([
+ 'function' => $expression_data['function'],
+ 'functionName' => $expression_data['functionName'],
+ 'functionParamList' => $expression_data['functionParamList'],
+ 'valueType' => $data['itemValueType']
+ ]);
+
+ if ($is_valid === false) {
+ error($trigger_function_validator->getError());
+ }
+ }
+ else {
+ error($trigger_expression->error);
+ }
+
+ // Quote function param.
+ if (array_key_exists('insert', $data)) {
+ foreach ($data['params'] as $pnum => $param) {
+ $data['params'][$pnum] = quoteFunctionParam($param);
+ }
+ }
+ }
+ else {
+ error(_('Item not selected'));
+ }
+ }
+ catch (Exception $e) {
+ error($e->getMessage());
+ error(_('Cannot insert trigger expression'));
+ }
+
+ if (($messages = getMessages()) !== null) {
+ $output = [
+ 'errors' => $messages->toString()
+ ];
+ }
+ else {
+ $output = [
+ 'expression' => $data['expression'],
+ 'dstfld1' => $data['dstfld1'],
+ 'dstfrm' => $data['dstfrm']
+ ];
+ }
+
+ $this->setResponse(
+ (new CControllerResponseData(['main_block' => json_encode($output)]))->disableView()
+ );
+ }
+ else {
+ $this->setResponse(new CControllerResponseData(
+ $data + [
+ 'title' => _('Condition'),
+ 'errors' => hasErrorMesssages() ? getMessages() : null,
+ 'user' => [
+ 'debug_mode' => $this->getDebugMode()
+ ]
+ ]
+ ));
+ }
+ }
+}