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
26require_once dirname(__FILE__).'/js/configuration.item.list.js.php';
27
28$widget = (new CWidget())
29	->setTitle(_('Items'))
30	->setControls(
31		(new CTag('nav', true,
32			(new CList())->addItem(
33				($data['hostid'] != 0)
34					? new CRedirectButton(_('Create item'), (new CUrl('items.php'))
35						->setArgument('form', 'create')
36						->setArgument('hostid', $data['hostid'])
37						->setArgument('context', $data['context'])
38						->getUrl()
39					)
40					: (new CButton('form',
41						($data['context'] === 'host')
42							? _('Create item (select host first)')
43							: _('Create item (select template first)')
44					))->setEnabled(false)
45			)
46		))->setAttribute('aria-label', _('Content controls'))
47	);
48
49if ($data['hostid'] != 0) {
50	$widget->setNavigation(getHostNavigation('items', $data['hostid']));
51}
52
53$widget->addItem(new CPartial('configuration.filter.items', [
54	'filter_data' => $data['filter_data'],
55	'subfilter' => $data['subfilter'],
56	'context' => $data['context']
57]));
58
59$url = (new CUrl('items.php'))
60	->setArgument('context', $data['context'])
61	->getUrl();
62
63// create form
64$itemForm = (new CForm('post', $url))
65	->setName('items')
66	->addVar('checkbox_hash', $data['checkbox_hash'])
67	->addVar('context', $data['context']);
68
69if (!empty($data['hostid'])) {
70	$itemForm->addVar('hostid', $data['hostid']);
71}
72
73// create table
74$itemTable = (new CTableInfo())
75	->setHeader([
76		(new CColHeader(
77			(new CCheckBox('all_items'))->onClick("checkAll('".$itemForm->getName()."', 'all_items', 'group_itemid');")
78		))->addClass(ZBX_STYLE_CELL_WIDTH),
79		_('Wizard'),
80		($data['hostid'] == 0)
81			? ($data['context'] === 'host')
82				? _('Host')
83				: _('Template')
84			: null,
85		make_sorting_header(_('Name'), 'name', $data['sort'], $data['sortorder'], $url),
86		_('Triggers'),
87		make_sorting_header(_('Key'), 'key_', $data['sort'], $data['sortorder'], $url),
88		make_sorting_header(_('Interval'), 'delay', $data['sort'], $data['sortorder'], $url),
89		make_sorting_header(_('History'), 'history', $data['sort'], $data['sortorder'], $url),
90		make_sorting_header(_('Trends'), 'trends', $data['sort'], $data['sortorder'], $url),
91		make_sorting_header(_('Type'), 'type', $data['sort'], $data['sortorder'], $url),
92		make_sorting_header(_('Status'), 'status', $data['sort'], $data['sortorder'], $url),
93		_('Tags'),
94		($data['context'] === 'host') ? _('Info') : null
95	]);
96
97$current_time = time();
98
99$data['itemTriggers'] = CMacrosResolverHelper::resolveTriggerExpressions($data['itemTriggers'], [
100	'html' => true,
101	'sources' => ['expression', 'recovery_expression'],
102	'context' => $data['context']
103]);
104
105$update_interval_parser = new CUpdateIntervalParser(['usermacros' => true]);
106
107foreach ($data['items'] as $item) {
108	// description
109	$description = [];
110	$description[] = makeItemTemplatePrefix($item['itemid'], $data['parent_templates'], ZBX_FLAG_DISCOVERY_NORMAL,
111		$data['allowed_ui_conf_templates']
112	);
113
114	if (!empty($item['discoveryRule'])) {
115		$description[] = (new CLink(CHtml::encode($item['discoveryRule']['name']),
116			(new CUrl('disc_prototypes.php'))
117				->setArgument('parent_discoveryid', $item['discoveryRule']['itemid'])
118				->setArgument('context', $data['context'])
119		))
120			->addClass(ZBX_STYLE_LINK_ALT)
121			->addClass(ZBX_STYLE_ORANGE);
122		$description[] = NAME_DELIMITER;
123	}
124
125	if ($item['type'] == ITEM_TYPE_DEPENDENT) {
126		if ($item['master_item']['type'] == ITEM_TYPE_HTTPTEST) {
127			$description[] = CHtml::encode($item['master_item']['name_expanded']);
128		}
129		else {
130			$description[] = (new CLink(CHtml::encode($item['master_item']['name_expanded']),
131				(new CUrl('items.php'))
132					->setArgument('form', 'update')
133					->setArgument('hostid', $item['hostid'])
134					->setArgument('itemid', $item['master_item']['itemid'])
135					->setArgument('context', $data['context'])
136			))
137				->addClass(ZBX_STYLE_LINK_ALT)
138				->addClass(ZBX_STYLE_TEAL);
139		}
140
141		$description[] = NAME_DELIMITER;
142	}
143
144	$description[] = new CLink(CHtml::encode($item['name_expanded']),
145		(new CUrl('items.php'))
146			->setArgument('form', 'update')
147			->setArgument('hostid', $item['hostid'])
148			->setArgument('itemid', $item['itemid'])
149			->setArgument('context', $data['context'])
150	);
151
152	// status
153	$status = new CCol((new CLink(
154			itemIndicator($item['status'], $item['state']),
155			(new CUrl('items.php'))
156				->setArgument('group_itemid[]', $item['itemid'])
157				->setArgument('hostid', $item['hostid'])
158				->setArgument('action', ($item['status'] == ITEM_STATUS_DISABLED)
159					? 'item.massenable'
160					: 'item.massdisable'
161				)
162				->setArgument('context', $data['context'])
163				->getUrl()
164		))
165		->addClass(ZBX_STYLE_LINK_ACTION)
166		->addClass(itemIndicatorStyle($item['status'], $item['state']))
167		->addSID()
168	);
169
170	// triggers info
171	$triggerHintTable = (new CTableInfo())->setHeader([_('Severity'), _('Name'), _('Expression'), _('Status')]);
172
173	foreach ($item['triggers'] as $num => &$trigger) {
174		$trigger = $data['itemTriggers'][$trigger['triggerid']];
175
176		$trigger_description = [];
177		$trigger_description[] = makeTriggerTemplatePrefix($trigger['triggerid'], $data['trigger_parent_templates'],
178			ZBX_FLAG_DISCOVERY_NORMAL, $data['allowed_ui_conf_templates']
179		);
180
181		$trigger['hosts'] = zbx_toHash($trigger['hosts'], 'hostid');
182
183		if ($trigger['flags'] == ZBX_FLAG_DISCOVERY_CREATED) {
184			$trigger_description[] = new CSpan(CHtml::encode($trigger['description']));
185		}
186		else {
187			$trigger_description[] = new CLink(
188				CHtml::encode($trigger['description']),
189				(new CUrl('triggers.php'))
190					->setArgument('form', 'update')
191					->setArgument('hostid', key($trigger['hosts']))
192					->setArgument('triggerid', $trigger['triggerid'])
193					->setArgument('context', $data['context'])
194			);
195		}
196
197		if ($trigger['state'] == TRIGGER_STATE_UNKNOWN) {
198			$trigger['error'] = '';
199		}
200
201		if ($trigger['recovery_mode'] == ZBX_RECOVERY_MODE_RECOVERY_EXPRESSION) {
202			$expression = [
203				_('Problem'), ': ', $trigger['expression'], BR(),
204				_('Recovery'), ': ', $trigger['recovery_expression']
205			];
206		}
207		else {
208			$expression = $trigger['expression'];
209		}
210
211		$triggerHintTable->addRow([
212			getSeverityCell($trigger['priority']),
213			$trigger_description,
214			(new CDiv($expression))->addClass(ZBX_STYLE_WORDWRAP),
215			(new CSpan(triggerIndicator($trigger['status'], $trigger['state'])))
216				->addClass(triggerIndicatorStyle($trigger['status'], $trigger['state']))
217		]);
218	}
219	unset($trigger);
220
221	if ($triggerHintTable->getNumRows()) {
222		$triggerInfo = (new CLinkAction(_('Triggers')))->setHint($triggerHintTable);
223		$triggerInfo = [$triggerInfo];
224		$triggerInfo[] = CViewHelper::showNum($triggerHintTable->getNumRows());
225
226		$triggerHintTable = [];
227	}
228	else {
229		$triggerInfo = '';
230	}
231
232	$wizard = (new CSpan(
233		(new CButton(null))
234			->addClass(ZBX_STYLE_ICON_WZRD_ACTION)
235			->setMenuPopup(CMenuPopupHelper::getItem(['itemid' => $item['itemid'], 'context' => $data['context']]))
236	))->addClass(ZBX_STYLE_REL_CONTAINER);
237
238	if (in_array($item['value_type'], [ITEM_VALUE_TYPE_STR, ITEM_VALUE_TYPE_LOG, ITEM_VALUE_TYPE_TEXT])) {
239		$item['trends'] = '';
240	}
241	else if ($item['flags'] == ZBX_FLAG_DISCOVERY_CREATED) {
242		$wizard = '';
243	}
244
245	// Hide zeros for trapper, SNMP trap and dependent items.
246	if ($item['type'] == ITEM_TYPE_TRAPPER || $item['type'] == ITEM_TYPE_SNMPTRAP
247			|| $item['type'] == ITEM_TYPE_DEPENDENT
248			|| ($item['type'] == ITEM_TYPE_ZABBIX_ACTIVE && strncmp($item['key_'], 'mqtt.get', 8) === 0)) {
249		$item['delay'] = '';
250	}
251	elseif ($update_interval_parser->parse($item['delay']) == CParser::PARSE_SUCCESS) {
252		$item['delay'] = $update_interval_parser->getDelay();
253	}
254
255	// info
256	if ($data['context'] === 'host') {
257		$info_icons = [];
258
259		if ($item['status'] == ITEM_STATUS_ACTIVE && !zbx_empty($item['error'])) {
260			$info_icons[] = makeErrorIcon($item['error']);
261		}
262
263		// discovered item lifetime indicator
264		if ($item['flags'] == ZBX_FLAG_DISCOVERY_CREATED && $item['itemDiscovery']['ts_delete'] != 0) {
265			$info_icons[] = getItemLifetimeIndicator($current_time, $item['itemDiscovery']['ts_delete']);
266		}
267	}
268
269	$itemTable->addRow([
270		new CCheckBox('group_itemid['.$item['itemid'].']', $item['itemid']),
271		$wizard,
272		($data['hostid'] == 0) ? $item['host'] : null,
273		$description,
274		$triggerInfo,
275		(new CDiv(CHtml::encode($item['key_'])))->addClass(ZBX_STYLE_WORDWRAP),
276		$item['delay'],
277		$item['history'],
278		$item['trends'],
279		item_type2str($item['type']),
280		$status,
281		$data['tags'][$item['itemid']],
282		($data['context'] === 'host') ? makeInformationList($info_icons) : null
283	]);
284}
285
286$button_list = [
287	'item.massenable' => ['name' => _('Enable'), 'confirm' => _('Enable selected items?')],
288	'item.massdisable' => ['name' => _('Disable'), 'confirm' => _('Disable selected items?')]
289];
290
291if ($data['context'] === 'host') {
292	$massclearhistory = [
293		'name' => _('Clear history'),
294		'confirm' => _('Delete history of selected items?'),
295		'disabled' => $data['is_template']
296	];
297
298	if ($data['config']['compression_status']) {
299		unset($massclearhistory['confirm']);
300	}
301
302	$button_list += [
303		'item.masscheck_now' => ['name' => _('Execute now'), 'disabled' => $data['is_template']],
304		'item.massclearhistory' => $massclearhistory
305	];
306}
307
308$button_list += [
309	'item.masscopyto' => ['name' => _('Copy')],
310	'popup.massupdate.item' => [
311		'content' => (new CButton('', _('Mass update')))
312			->onClick("return openMassupdatePopup(this, 'popup.massupdate.item');")
313			->addClass(ZBX_STYLE_BTN_ALT)
314			->removeAttribute('id')
315	],
316	'item.massdelete' => ['name' => _('Delete'), 'confirm' => _('Delete selected items?')]
317];
318
319// Append table to form.
320$itemForm->addItem([$itemTable, $data['paging'], new CActionButtonList('action', 'group_itemid', $button_list,
321	$data['checkbox_hash']
322)]);
323
324// Append form to widget.
325$widget->addItem($itemForm);
326
327$widget->show();
328