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 not given.
26	 *
27	 * @var string
28	 */
29	public $messageMissingFormula;
30
31	/**
32	 * Error message if the formula is invalid.
33	 *
34	 * @var string
35	 */
36	public $messageInvalidFormula;
37
38	/**
39	 * Error message if the formula contains a condition that is not defined in the "conditions" array.
40	 *
41	 * @var string
42	 */
43	public $messageMissingCondition;
44
45	/**
46	 * Error message if the "conditions" array contains a condition that is not used in the formula.
47	 *
48	 * @var string
49	 */
50	public $messageUnusedCondition;
51
52	/**
53	 * Error message if several triggers are compared with "and".
54	 *
55	 * @var string
56	 */
57	public $messageAndWithSeveralTriggers;
58
59	/**
60	 * Validates the given condition formula and checks if the given conditions match the formula.
61	 *
62	 * @param array $object
63	 *
64	 * @return bool
65	 */
66	public function validate($object) {
67		if ($object['evaltype'] == CONDITION_EVAL_TYPE_AND) {
68			// get triggers count in formula
69			$trigger_count = 0;
70			foreach ($object['conditions'] as $condition) {
71				if (array_key_exists('conditiontype', $condition) && array_key_exists('operator', $condition)
72						&& $condition['conditiontype'] == CONDITION_TYPE_TRIGGER
73						&& $condition['operator'] == CONDITION_OPERATOR_EQUAL) {
74					$trigger_count++;
75				}
76			}
77
78			// check if multiple triggers are compared with AND
79			if ($trigger_count > 1) {
80				$this->error($this->messageAndWithSeveralTriggers);
81
82				return false;
83			}
84		}
85
86		// validate only custom expressions
87		if ($object['evaltype'] != CONDITION_EVAL_TYPE_EXPRESSION) {
88			return true;
89		}
90
91		if (!array_key_exists('formula', $object)) {
92			$this->error($this->messageMissingFormula);
93
94			return false;
95		}
96
97		// check if the formula is valid
98		$parser = new CConditionFormula();
99		if (!$parser->parse($object['formula'])) {
100			$this->error($this->messageInvalidFormula, $object['formula'], $parser->error);
101
102			return false;
103		}
104
105		// check that all conditions used in the formula are defined in the "conditions" array
106		$conditions = zbx_toHash($object['conditions'], 'formulaid');
107		$constants = array_unique(zbx_objectValues($parser->constants, 'value'));
108		foreach ($constants as $constant) {
109			if (!array_key_exists($constant, $conditions)) {
110				$this->error($this->messageMissingCondition, $constant, $object['formula']);
111
112				return false;
113			}
114
115			unset($conditions[$constant]);
116		}
117
118		// check that the "conditions" array has no unused conditions
119		if ($conditions) {
120			$condition = reset($conditions);
121			$this->error($this->messageUnusedCondition, $condition['formulaid'], $object['formula']);
122
123			return false;
124		}
125
126		return true;
127	}
128}
129