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
22/**
23 * @var CView $this
24 */
25
26// indicator of sort field
27$sort_div = (new CSpan())->addClass(($data['sortorder'] === ZBX_SORT_DOWN) ? ZBX_STYLE_ARROW_DOWN : ZBX_STYLE_ARROW_UP);
28
29$url_details = $data['allowed_ui_problems']
30	? (new CUrl('tr_events.php'))
31		->setArgument('triggerid', '')
32		->setArgument('eventid', '')
33	: null;
34
35$show_timeline = ($data['sortfield'] === 'clock' && $data['fields']['show_timeline']);
36$show_recovery_data = in_array($data['fields']['show'], [TRIGGERS_OPTION_RECENT_PROBLEM, TRIGGERS_OPTION_ALL]);
37
38$header_time = new CColHeader(($data['sortfield'] === 'clock') ? [_('Time'), $sort_div] : _('Time'));
39
40if ($show_timeline) {
41	$header = [
42		$header_time->addClass(ZBX_STYLE_RIGHT),
43		(new CColHeader())->addClass(ZBX_STYLE_TIMELINE_TH),
44		(new CColHeader())->addClass(ZBX_STYLE_TIMELINE_TH)
45	];
46}
47else {
48	$header = [$header_time];
49}
50
51$show_opdata = $data['fields']['show_opdata'];
52
53$table = (new CTableInfo())
54	->setHeader(array_merge($header, [
55		$show_recovery_data ? _('Recovery time') : null,
56		$show_recovery_data ? _('Status') : null,
57		_('Info'),
58		($data['sortfield'] === 'host') ? [_('Host'), $sort_div] : _('Host'),
59		[
60			($data['sortfield'] === 'name') ? [_('Problem'), $sort_div] : _('Problem'),
61			' &bullet; ',
62			($data['sortfield'] === 'severity') ? [_('Severity'), $sort_div] : _('Severity')
63		],
64		($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) ? _('Operational data') : null,
65		_('Duration'),
66		_('Ack'),
67		_('Actions'),
68		$data['fields']['show_tags'] ? _('Tags') : null
69	]));
70
71$today = strtotime('today');
72$last_clock = 0;
73
74if ($data['data']['problems']) {
75	$triggers_hosts = makeTriggersHostsList($data['data']['triggers_hosts']);
76}
77
78$allowed = [
79	'ui_problems' => $data['allowed_ui_problems'],
80	'add_comments' => $data['allowed_add_comments'],
81	'change_severity' => $data['allowed_change_severity'],
82	'acknowledge' => $data['allowed_acknowledge']
83];
84
85foreach ($data['data']['problems'] as $eventid => $problem) {
86	$trigger = $data['data']['triggers'][$problem['objectid']];
87
88	$allowed['close'] = ($trigger['manual_close'] == ZBX_TRIGGER_MANUAL_CLOSE_ALLOWED && $data['allowed_close']);
89	$can_be_closed = $allowed['close'];
90
91	if ($problem['r_eventid'] != 0) {
92		$value = TRIGGER_VALUE_FALSE;
93		$value_str = _('RESOLVED');
94		$value_clock = $problem['r_clock'];
95		$can_be_closed = false;
96	}
97	else {
98		$in_closing = false;
99
100		foreach ($problem['acknowledges'] as $acknowledge) {
101			if (($acknowledge['action'] & ZBX_PROBLEM_UPDATE_CLOSE) == ZBX_PROBLEM_UPDATE_CLOSE) {
102				$in_closing = true;
103				$can_be_closed = false;
104				break;
105			}
106		}
107
108		$value = $in_closing ? TRIGGER_VALUE_FALSE : TRIGGER_VALUE_TRUE;
109		$value_str = $in_closing ? _('CLOSING') : _('PROBLEM');
110		$value_clock = $in_closing ? time() : $problem['clock'];
111	}
112
113	$cell_clock = ($problem['clock'] >= $today)
114		? zbx_date2str(TIME_FORMAT_SECONDS, $problem['clock'])
115		: zbx_date2str(DATE_TIME_FORMAT_SECONDS, $problem['clock']);
116
117	if ($url_details !== null) {
118		$url_details
119			->setArgument('triggerid', $problem['objectid'])
120			->setArgument('eventid', $problem['eventid']);
121		$cell_clock = new CCol(new CLink($cell_clock, $url_details));
122	}
123	else {
124		$cell_clock = new CCol($cell_clock);
125	}
126
127	$is_acknowledged = ($problem['acknowledged'] == EVENT_ACKNOWLEDGED);
128
129	if ($show_recovery_data) {
130		if ($problem['r_eventid'] != 0) {
131			$cell_r_clock = ($problem['r_clock'] >= $today)
132				? zbx_date2str(TIME_FORMAT_SECONDS, $problem['r_clock'])
133				: zbx_date2str(DATE_TIME_FORMAT_SECONDS, $problem['r_clock']);
134			$cell_r_clock = (new CCol($url_details !== null ? new CLink($cell_r_clock, $url_details) : $cell_r_clock))
135				->addClass(ZBX_STYLE_NOWRAP)
136				->addClass(ZBX_STYLE_RIGHT);
137		}
138		else {
139			$cell_r_clock = '';
140		}
141
142		$cell_status = new CSpan($value_str);
143
144		// Add colors and blinking to span depending on configuration and trigger parameters.
145		addTriggerValueStyle($cell_status, $value, $value_clock, $is_acknowledged);
146	}
147
148	// Info.
149	$info_icons = [];
150	if ($problem['r_eventid'] != 0) {
151		if ($problem['correlationid'] != 0) {
152			$info_icons[] = makeInformationIcon(
153				array_key_exists($problem['correlationid'], $data['data']['correlations'])
154					? _s('Resolved by correlation rule "%1$s".',
155						$data['data']['correlations'][$problem['correlationid']]['name']
156					)
157					: _('Resolved by correlation rule.')
158			);
159		}
160		elseif ($problem['userid'] != 0) {
161			$info_icons[] = makeInformationIcon(
162				array_key_exists($problem['userid'], $data['data']['users'])
163					? _s('Resolved by user "%1$s".', getUserFullname($data['data']['users'][$problem['userid']]))
164					: _('Resolved by inaccessible user.')
165			);
166		}
167	}
168
169	if (array_key_exists('suppression_data', $problem) && $problem['suppression_data']) {
170		$info_icons[] = makeSuppressedProblemIcon($problem['suppression_data']);
171	}
172
173	$opdata = null;
174	if ($show_opdata != OPERATIONAL_DATA_SHOW_NONE) {
175
176		// operational data
177		if ($trigger['opdata'] === '') {
178			if ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) {
179				$opdata = (new CCol(CScreenProblem::getLatestValues($trigger['items'])))->addClass('latest-values');
180			}
181		} else {
182			$opdata = CMacrosResolverHelper::resolveTriggerOpdata(
183				[
184					'triggerid' => $trigger['triggerid'],
185					'expression' => $trigger['expression'],
186					'opdata' => $trigger['opdata'],
187					'clock' => ($problem['r_eventid'] != 0) ? $problem['r_clock'] : $problem['clock'],
188					'ns' => ($problem['r_eventid'] != 0) ? $problem['r_ns'] : $problem['ns']
189				],
190				[
191					'events' => true,
192					'html' => true
193				]
194			);
195
196			if ($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY) {
197				$opdata = (new CCol($opdata))
198					->addClass('opdata')
199					->addClass(ZBX_STYLE_WORDWRAP);
200			}
201		}
202	}
203
204	$problem_link = [
205		(new CLinkAction($problem['name']))
206			->setMenuPopup(CMenuPopupHelper::getTrigger($trigger['triggerid'], $problem['eventid']))
207			->setAttribute('aria-label', _xs('%1$s, Severity, %2$s', 'screen reader',
208				$problem['name'], getSeverityName($problem['severity'])
209			))
210	];
211
212	if ($show_opdata == OPERATIONAL_DATA_SHOW_WITH_PROBLEM && $opdata) {
213		$problem_link = array_merge($problem_link, [' (', $opdata, ')']);
214	}
215
216	$description = (new CCol($problem_link));
217
218	$description_style = getSeverityStyle($problem['severity']);
219
220	if ($value == TRIGGER_VALUE_TRUE) {
221		$description->addClass($description_style);
222	}
223
224	if (!$show_recovery_data
225			&& (($is_acknowledged && $data['config']['problem_ack_style'])
226				|| (!$is_acknowledged && $data['config']['problem_unack_style']))) {
227		// blinking
228		$duration = time() - $problem['clock'];
229		$blink_period = timeUnitToSeconds($data['config']['blink_period']);
230
231		if ($blink_period != 0 && $duration < $blink_period) {
232			$description
233				->addClass('blink')
234				->setAttribute('data-time-to-blink', $blink_period - $duration)
235				->setAttribute('data-toggle-class', ZBX_STYLE_BLINK_HIDDEN);
236		}
237	}
238
239	if ($show_timeline) {
240		if ($last_clock != 0) {
241			CScreenProblem::addTimelineBreakpoint($table, $last_clock, $problem['clock'], $data['sortorder']);
242		}
243		$last_clock = $problem['clock'];
244
245		$row = [
246			$cell_clock->addClass(ZBX_STYLE_TIMELINE_DATE),
247			(new CCol())
248				->addClass(ZBX_STYLE_TIMELINE_AXIS)
249				->addClass(ZBX_STYLE_TIMELINE_DOT),
250			(new CCol())->addClass(ZBX_STYLE_TIMELINE_TD)
251		];
252	}
253	else {
254		$row = [
255			$cell_clock
256				->addClass(ZBX_STYLE_NOWRAP)
257				->addClass(ZBX_STYLE_RIGHT)
258		];
259	}
260
261	// Create acknowledge link.
262	$problem_update_link = ($allowed['add_comments'] || $allowed['change_severity'] || $allowed['acknowledge']
263			|| $can_be_closed)
264		? (new CLink($is_acknowledged ? _('Yes') : _('No')))
265			->addClass($is_acknowledged ? ZBX_STYLE_GREEN : ZBX_STYLE_RED)
266			->addClass(ZBX_STYLE_LINK_ALT)
267			->onClick('acknowledgePopUp('.json_encode(['eventids' => [$problem['eventid']]]).', this);')
268		: (new CSpan($is_acknowledged ? _('Yes') : _('No')))->addClass(
269			$is_acknowledged ? ZBX_STYLE_GREEN : ZBX_STYLE_RED
270		);
271
272	$table->addRow(array_merge($row, [
273		$show_recovery_data ? $cell_r_clock : null,
274		$show_recovery_data ? $cell_status : null,
275		makeInformationList($info_icons),
276		$triggers_hosts[$trigger['triggerid']],
277		$description,
278		($show_opdata == OPERATIONAL_DATA_SHOW_SEPARATELY ) ? $opdata : null,
279		(new CCol(
280			(new CLinkAction(zbx_date2age($problem['clock'], ($problem['r_eventid'] != 0) ? $problem['r_clock'] : 0)))
281				->setAjaxHint(CHintBoxHelper::getEventList($trigger['triggerid'], $eventid, $show_timeline,
282					$data['fields']['show_tags'], $data['fields']['tags'], $data['fields']['tag_name_format'],
283					$data['fields']['tag_priority']
284				))
285		))->addClass(ZBX_STYLE_NOWRAP),
286		$problem_update_link,
287		makeEventActionsIcons($problem['eventid'], $data['data']['actions'], $data['data']['users']),
288		$data['fields']['show_tags'] ? $data['data']['tags'][$problem['eventid']] : null
289	]));
290}
291
292if ($data['info'] !== '') {
293	$table->setFooter([
294		(new CCol($data['info']))
295			->setColSpan($table->getNumCols())
296			->addClass(ZBX_STYLE_LIST_TABLE_FOOTER)
297	]);
298}
299
300$output = [
301	'name' => $data['name'],
302	'body' => $table->toString()
303];
304
305if (($messages = getMessages()) !== null) {
306	$output['messages'] = $messages->toString();
307}
308
309if ($data['user']['debug_mode'] == GROUP_DEBUG_MODE_ENABLED) {
310	CProfiler::getInstance()->stop();
311	$output['debug'] = CProfiler::getInstance()->make()->toString();
312}
313
314echo json_encode($output);
315