1<?php
2/*
3** Zabbix
4** Copyright (C) 2001-2021 Zabbix SIA
5**
6** This program is free software; you can redistribute it and/or modify
7** it under the terms of the GNU General Public License as published by
8** the Free Software Foundation; either version 2 of the License, or
9** (at your option) any later version.
10**
11** This program is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14** GNU General Public License for more details.
15**
16** You should have received a copy of the GNU General Public License
17** along with this program; if not, write to the Free Software
18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19**/
20
21
22class CConditionValidator extends CValidator {
23
24	/**
25	 * Error message if the formula is invalid.
26	 *
27	 * @var string
28	 */
29	public $messageInvalidFormula;
30
31	/**
32	 * Error message if the formula contains a condition that is not defined in the "conditions" array.
33	 *
34	 * @var string
35	 */
36	public $messageMissingCondition;
37
38	/**
39	 * Error message if the "conditions" array contains a condition that is not used in the formula.
40	 *
41	 * @var string
42	 */
43	public $messageUnusedCondition;
44
45	/**
46	 * Error message if several triggers are compared with "and".
47	 *
48	 * @var string
49	 */
50	public $messageAndWithSeveralTriggers;
51
52	/**
53	 * Validates the given condition formula and checks if the given conditions match the formula.
54	 *
55	 * @param array $object
56	 *
57	 * @return bool
58	 */
59	public function validate($object) {
60		if ($object['evaltype'] == CONDITION_EVAL_TYPE_AND) {
61			// get triggers count in formula
62			$trigger_count = 0;
63			foreach ($object['conditions'] as $condition) {
64				if (array_key_exists('conditiontype', $condition) && array_key_exists('operator', $condition)
65						&& $condition['conditiontype'] == CONDITION_TYPE_TRIGGER
66						&& $condition['operator'] == CONDITION_OPERATOR_EQUAL) {
67					$trigger_count++;
68				}
69			}
70
71			// check if multiple triggers are compared with AND
72			if ($trigger_count > 1) {
73				$this->error($this->messageAndWithSeveralTriggers);
74
75				return false;
76			}
77		}
78
79		// validate only custom expressions
80		if ($object['evaltype'] != CONDITION_EVAL_TYPE_EXPRESSION) {
81			return true;
82		}
83
84		// check if the formula is valid
85		$parser = new CConditionFormula();
86		if (!$parser->parse($object['formula'])) {
87			$this->error($this->messageInvalidFormula, $object['formula'], $parser->error);
88
89			return false;
90		}
91
92		// check that all conditions used in the formula are defined in the "conditions" array
93		$conditions = zbx_toHash($object['conditions'], 'formulaid');
94		$constants = array_unique(zbx_objectValues($parser->constants, 'value'));
95		foreach ($constants as $constant) {
96			if (!array_key_exists($constant, $conditions)) {
97				$this->error($this->messageMissingCondition, $constant, $object['formula']);
98
99				return false;
100			}
101
102			unset($conditions[$constant]);
103		}
104
105		// check that the "conditions" array has no unused conditions
106		if ($conditions) {
107			$condition = reset($conditions);
108			$this->error($this->messageUnusedCondition, $condition['formulaid'], $object['formula']);
109
110			return false;
111		}
112
113		return true;
114	}
115}
116