| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 
 | <?php
/*
** Copyright (C) 2001-2025 Zabbix SIA
**
** This program is free software: you can redistribute it and/or modify it under the terms of
** the GNU Affero General Public License as published by the Free Software Foundation, version 3.
**
** 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 Affero General Public License for more details.
**
** You should have received a copy of the GNU Affero General Public License along with this program.
** If not, see <https://www.gnu.org/licenses/>.
**/
/**
 * Class to convert calculated item keys.
 */
class C52CalculatedItemConverter extends C52TriggerExpressionConverter {
	/**
	 * Item key parser.
	 *
	 * @var CItemKey
	 */
	protected $item_key_parser;
	/**
	 * Function parser.
	 *
	 * @var C10FunctionParser
	 */
	protected $function_parser;
	public function __construct() {
		$this->parser = new C10TriggerExpression([
			'allow_func_only' => true,
			'calculated' => true
		]);
		$this->item_key_parser = new CItemKey();
		$this->function_parser = new C10FunctionParser();
		$this->standalone_functions = getStandaloneFunctions();
	}
	/**
	 * Convert calculated item formula to 5.4 syntax.
	 *
	 * @param string $formula  Calculated item formula to convert.
	 *
	 * @return string
	 */
	public function convert($item) {
		$expression = preg_replace("/[\\r\\n\\t]/", '', $item['params']);
		if ($this->parser->parse($expression) === false) {
			return $item;
		}
		$functions = $this->parser->result->getTokensByType(C10TriggerExprParserResult::TOKEN_TYPE_FUNCTION);
		$this->hanged_refs = $this->checkHangedFunctionsPerHost($functions);
		for ($i = count($functions) - 1; $i >= 0; $i--) {
			$fn = $functions[$i]['data'] + ['host' => '', 'item' => ''];
			$query = $fn['functionParams'][0];
			$colon_pos = strpos($query, ':');
			$bracket_pos = strpos($query, '[');
			if ($colon_pos !== false && ($bracket_pos === false || $colon_pos < $bracket_pos)) {
				list($host_name, $item_key) = explode(':', $query, 2);
			}
			else {
				$host_name = '';
				$item_key = $query;
			}
			if ($this->item_key_parser->parse($item_key) === CParser::PARSE_SUCCESS) {
				array_shift($fn['functionParams']);
				array_shift($fn['functionParamsRaw']['parameters']);
				[$new_expr] = $this->convertFunction($fn, $host_name, $item_key);
				$expression = substr_replace($expression, $new_expr, $functions[$i]['pos'], $functions[$i]['length']);
			}
		}
		$item['params'] = $expression;
		return $item;
	}
	/**
	 * Check if each particular host reference would be linked through at least one functions according to the new
	 * trigger expression syntax.
	 *
	 * @param array $tokens
	 *
	 * @return array
	 */
	protected function checkHangedFunctionsPerHost(array $tokens): array {
		$hanged_refs = ['' => false];
		foreach ($tokens as $token) {
			$host_name = '';
			$fn = $token['data'];
			$item_key = $fn['functionParams'][0];
			$host_delimiter_pos = strpos($item_key, ':');
			if ($host_delimiter_pos === false || $host_delimiter_pos > strpos($item_key, '[')) {
				continue;
			}
			$host_name = substr($item_key, 0, $host_delimiter_pos);
			if (!array_key_exists($host_name, $hanged_refs)) {
				$hanged_refs[$host_name] = false;
			}
			if (!in_array($fn['functionName'], $this->standalone_functions)) {
				$hanged_refs[$host_name] = true;
			}
		}
		return $hanged_refs;
	}
}
 |