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
22require_once dirname(__FILE__).'/include/config.inc.php';
23require_once dirname(__FILE__).'/include/hosts.inc.php';
24require_once dirname(__FILE__).'/include/items.inc.php';
25require_once dirname(__FILE__).'/include/forms.inc.php';
26
27$page['title'] = _('Configuration of item prototypes');
28$page['file'] = 'disc_prototypes.php';
29$page['scripts'] = ['effects.js', 'class.cviewswitcher.js', 'items.js'];
30
31require_once dirname(__FILE__).'/include/page_header.php';
32
33$paramsFieldName = getParamFieldNameByType(getRequest('type', 0));
34
35// VAR	TYPE	OPTIONAL	FLAGS	VALIDATION	EXCEPTION
36$fields = [
37	'parent_discoveryid' =>			[T_ZBX_INT, O_MAND, P_SYS,	DB_ID,		null],
38	'itemid' =>						[T_ZBX_INT, O_OPT, P_SYS,	DB_ID,		'(isset({form}) && ({form} == "update"))'],
39	'interfaceid' =>				[T_ZBX_INT, O_OPT, P_SYS,	DB_ID,		null, _('Interface')],
40	'name' =>						[T_ZBX_STR, O_OPT, null,	NOT_EMPTY,	'isset({add}) || isset({update})',
41		_('Name')
42	],
43	'description' =>				[T_ZBX_STR, O_OPT, null,	null,		'isset({add}) || isset({update})'],
44	'key' =>						[T_ZBX_STR, O_OPT, null,	NOT_EMPTY,	'isset({add}) || isset({update})',
45		_('Key')
46	],
47	'delay' =>						[T_ZBX_INT, O_OPT, null,	BETWEEN(0, SEC_PER_DAY),
48		'(isset({add}) || isset({update}))'.
49			' && (isset({type}) && ({type} != '.ITEM_TYPE_TRAPPER.' && {type} != '.ITEM_TYPE_SNMPTRAP.'))',
50		_('Update interval (in sec)')
51	],
52	'delay_flex' =>					[T_ZBX_STR, O_OPT, null,	null,			null],
53	'status' =>						[T_ZBX_INT, O_OPT, null,	IN(ITEM_STATUS_ACTIVE), null],
54	'type' =>						[T_ZBX_INT, O_OPT, null,
55		IN([-1, ITEM_TYPE_ZABBIX, ITEM_TYPE_SNMPV1, ITEM_TYPE_TRAPPER, ITEM_TYPE_SIMPLE, ITEM_TYPE_SNMPV2C,
56			ITEM_TYPE_INTERNAL, ITEM_TYPE_SNMPV3, ITEM_TYPE_ZABBIX_ACTIVE, ITEM_TYPE_AGGREGATE, ITEM_TYPE_EXTERNAL,
57			ITEM_TYPE_DB_MONITOR, ITEM_TYPE_IPMI, ITEM_TYPE_SSH, ITEM_TYPE_TELNET, ITEM_TYPE_JMX, ITEM_TYPE_CALCULATED,
58			ITEM_TYPE_SNMPTRAP]
59		),
60		'isset({add}) || isset({update})'
61	],
62	'value_type' =>					[T_ZBX_INT, O_OPT, null,	IN('0,1,2,3,4'), 'isset({add}) || isset({update})'],
63	'data_type' =>					[T_ZBX_INT, O_OPT, null,
64		IN(ITEM_DATA_TYPE_DECIMAL.','.ITEM_DATA_TYPE_OCTAL.','.ITEM_DATA_TYPE_HEXADECIMAL.','.ITEM_DATA_TYPE_BOOLEAN),
65		'(isset({add}) || isset({update})) && (isset({value_type}) && ({value_type} == '.ITEM_VALUE_TYPE_UINT64.'))'
66	],
67	'valuemapid' =>					[T_ZBX_INT, O_OPT, null,	DB_ID,
68		'(isset({add}) || isset({update})) && isset({value_type})'.
69			' && '.IN(ITEM_VALUE_TYPE_FLOAT.','.ITEM_VALUE_TYPE_UINT64, 'value_type')
70	],
71	'authtype' =>					[T_ZBX_INT, O_OPT, null,	IN(ITEM_AUTHTYPE_PASSWORD.','.ITEM_AUTHTYPE_PUBLICKEY),
72		'(isset({add}) || isset({update})) && isset({type}) && ({type} == '.ITEM_TYPE_SSH.')'
73	],
74	'username' =>					[T_ZBX_STR, O_OPT, null,	NOT_EMPTY,
75		'(isset({add}) || isset({update})) && isset({type}) && '.IN(ITEM_TYPE_SSH.','.ITEM_TYPE_TELNET, 'type'),
76		_('User name')
77	],
78	'password' =>					[T_ZBX_STR, O_OPT, null,	null,
79		'(isset({add}) || isset({update})) && isset({type}) && '.IN(ITEM_TYPE_SSH.','.ITEM_TYPE_TELNET, 'type')
80	],
81	'publickey' =>					[T_ZBX_STR, O_OPT, null,	null,
82		'(isset({add}) || isset({update})) && isset({type})'.
83			' && ({type}) == '.ITEM_TYPE_SSH.' && ({authtype}) == '.ITEM_AUTHTYPE_PUBLICKEY
84	],
85	'privatekey' =>					[T_ZBX_STR, O_OPT, null,	null,
86		'(isset({add}) || isset({update})) && isset({type})'.
87			' && ({type}) == '.ITEM_TYPE_SSH.' && ({authtype}) == '.ITEM_AUTHTYPE_PUBLICKEY
88	],
89	$paramsFieldName =>				[T_ZBX_STR, O_OPT, null,	NOT_EMPTY,
90		'(isset({add}) || isset({update})) && isset({type})'.
91			' && '.IN(ITEM_TYPE_SSH.','.ITEM_TYPE_DB_MONITOR.','.ITEM_TYPE_TELNET.','.ITEM_TYPE_CALCULATED, 'type'),
92		getParamFieldLabelByType(getRequest('type', 0))
93	],
94	'snmp_community' =>				[T_ZBX_STR, O_OPT, null,	NOT_EMPTY,
95		'(isset({add}) || isset({update})) && isset({type}) && '.IN(ITEM_TYPE_SNMPV1.','.ITEM_TYPE_SNMPV2C, 'type'),
96		_('SNMP community')
97	],
98	'snmp_oid' =>					[T_ZBX_STR, O_OPT, null,	NOT_EMPTY,
99		'(isset({add}) || isset({update})) && isset({type})'.
100			' && '.IN(ITEM_TYPE_SNMPV1.','.ITEM_TYPE_SNMPV2C.','.ITEM_TYPE_SNMPV3, 'type'),
101		_('SNMP OID')
102	],
103	'port' =>						[T_ZBX_STR, O_OPT, null,	BETWEEN(0, 65535),
104		'(isset({add}) || isset({update})) && isset({type})'.
105			' && '.IN(ITEM_TYPE_SNMPV1.','.ITEM_TYPE_SNMPV2C.','.ITEM_TYPE_SNMPV3, 'type'),
106		_('Port')
107	],
108	'snmpv3_securitylevel' =>		[T_ZBX_INT, O_OPT, null,	IN('0,1,2'),
109		'(isset({add}) || isset({update})) && (isset({type}) && ({type} == '.ITEM_TYPE_SNMPV3.'))'
110	],
111	'snmpv3_contextname' =>		[T_ZBX_STR, O_OPT, null,	null,
112		'(isset({add}) || isset({update})) && (isset({type}) && ({type} == '.ITEM_TYPE_SNMPV3.'))'
113	],
114	'snmpv3_securityname' =>		[T_ZBX_STR, O_OPT, null,	null,
115		'(isset({add}) || isset({update})) && (isset({type}) && ({type} == '.ITEM_TYPE_SNMPV3.'))'
116	],
117	'snmpv3_authprotocol' =>		[T_ZBX_INT, O_OPT, null,	IN(ITEM_AUTHPROTOCOL_MD5.','.ITEM_AUTHPROTOCOL_SHA),
118		'(isset({add}) || isset({update})) && (isset({type})'.
119			' && ({type} == '.ITEM_TYPE_SNMPV3.') && ({snmpv3_securitylevel} == '.ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV.
120			' || {snmpv3_securitylevel} == '.ITEM_SNMPV3_SECURITYLEVEL_AUTHNOPRIV.'))'
121	],
122	'snmpv3_authpassphrase' =>		[T_ZBX_STR, O_OPT, null,	null,
123		'(isset({add}) || isset({update})) && (isset({type})'.
124			' && ({type} == '.ITEM_TYPE_SNMPV3.') && ({snmpv3_securitylevel} == '.ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV.
125			' || {snmpv3_securitylevel} == '.ITEM_SNMPV3_SECURITYLEVEL_AUTHNOPRIV.'))'
126	],
127	'snmpv3_privprotocol' =>		[T_ZBX_INT, O_OPT, null,	IN(ITEM_PRIVPROTOCOL_DES.','.ITEM_PRIVPROTOCOL_AES),
128		'(isset({add}) || isset({update})) && (isset({type}) && ({type} == '.ITEM_TYPE_SNMPV3.')'.
129			' && ({snmpv3_securitylevel} == '.ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV.'))'
130	],
131	'snmpv3_privpassphrase' =>		[T_ZBX_STR, O_OPT, null,	null,
132		'(isset({add}) || isset({update})) && (isset({type}) && ({type} == '.ITEM_TYPE_SNMPV3.')'.
133			' && ({snmpv3_securitylevel} == '.ITEM_SNMPV3_SECURITYLEVEL_AUTHPRIV.'))'
134	],
135	'ipmi_sensor' =>				[T_ZBX_STR, O_OPT, P_NO_TRIM,	NOT_EMPTY,
136		'(isset({add}) || isset({update})) && (isset({type}) && ({type} == '.ITEM_TYPE_IPMI.'))', _('IPMI sensor')
137	],
138	'trapper_hosts' =>				[T_ZBX_STR, O_OPT, null,	null,
139		'(isset({add}) || isset({update})) && isset({type}) && ({type} == 2)'
140	],
141	'units' =>						[T_ZBX_STR, O_OPT, null,	null,
142		'(isset({add}) || isset({update})) && isset({value_type})'.
143			' && '.IN('0,3', 'value_type').' (isset({data_type}) && ({data_type} != '.ITEM_DATA_TYPE_BOOLEAN.'))'
144	],
145	'multiplier' =>					[T_ZBX_INT, O_OPT, null,	null,		null],
146	'delta' =>						[T_ZBX_INT, O_OPT, null,	IN('0,1,2'),
147		'(isset({add}) || isset({update})) && isset({value_type})'.
148			' && '.IN('0,3', 'value_type').' (isset({data_type}) && ({data_type} != '.ITEM_DATA_TYPE_BOOLEAN.'))'
149	],
150	'formula' =>					[T_ZBX_DBL_STR, O_OPT, null,
151		'({value_type} == 0 && {} != 0) || ({value_type} == 3 && {} > 0)',
152		'(isset({add}) || isset({update})) && isset({multiplier}) && {multiplier} == 1', _('Custom multiplier')
153	],
154	'logtimefmt' =>					[T_ZBX_STR, O_OPT, null,	null,
155		'(isset({add}) || isset({update})) && (isset({value_type}) && ({value_type} == 2))'
156	],
157	'group_itemid' =>				[T_ZBX_INT, O_OPT, null,	DB_ID,		null],
158	'new_application' =>			[T_ZBX_STR, O_OPT, null,	null,		'isset({add}) || isset({update})'],
159	'applications' =>				[T_ZBX_INT, O_OPT, null,	DB_ID,		null],
160	'new_application_prototype' =>	[T_ZBX_STR, O_OPT, null,	null,
161		'isset({parent_discoveryid}) && (isset({add}) || isset({update}))'
162	],
163	'application_prototypes' =>		[T_ZBX_STR, O_OPT, null,	null,		null],
164	'history' =>					[T_ZBX_INT, O_OPT, null,	BETWEEN(0, 65535), 'isset({add}) || isset({update})',
165		_('History storage period')
166	],
167	'trends' =>						[T_ZBX_INT, O_OPT, null,	BETWEEN(0, 65535),
168		'(isset({add}) || isset({update})) && isset({value_type})'.
169			' && '.IN(ITEM_VALUE_TYPE_FLOAT.','.ITEM_VALUE_TYPE_UINT64, 'value_type'),
170		_('Trend storage period')
171	],
172	// actions
173	'action' =>						[T_ZBX_STR, O_OPT, P_SYS|P_ACT,
174		IN('"itemprototype.massdelete","itemprototype.massdisable","itemprototype.massenable"'), null
175	],
176	'add' =>						[T_ZBX_STR, O_OPT, P_SYS|P_ACT, null,	null],
177	'update' =>						[T_ZBX_STR, O_OPT, P_SYS|P_ACT, null,	null],
178	'clone' =>						[T_ZBX_STR, O_OPT, P_SYS|P_ACT, null,	null],
179	'delete' =>						[T_ZBX_STR, O_OPT, P_SYS|P_ACT, null,	null],
180	'cancel' =>						[T_ZBX_STR, O_OPT, P_SYS,	null,		null],
181	'form' =>						[T_ZBX_STR, O_OPT, P_SYS,	null,		null],
182	'form_refresh' =>				[T_ZBX_INT, O_OPT, null,	null,		null],
183	// filter
184	'filter_set' =>					[T_ZBX_STR, O_OPT, P_SYS,	null,		null],
185	// sort and sortorder
186	'sort' =>						[T_ZBX_STR, O_OPT, P_SYS,
187		IN('"delay","history","key_","name","status","trends","type"'), null
188	],
189	'sortorder' =>					[T_ZBX_STR, O_OPT, P_SYS, IN('"'.ZBX_SORT_DOWN.'","'.ZBX_SORT_UP.'"'),	null]
190];
191check_fields($fields);
192
193$_REQUEST['params'] = getRequest($paramsFieldName, '');
194unset($_REQUEST[$paramsFieldName]);
195
196// permissions
197$discoveryRule = API::DiscoveryRule()->get([
198	'output' => ['hostid'],
199	'itemids' => getRequest('parent_discoveryid'),
200	'editable' => true
201]);
202$discoveryRule = reset($discoveryRule);
203if (!$discoveryRule) {
204	access_deny();
205}
206
207$itemPrototypeId = getRequest('itemid');
208if ($itemPrototypeId && !API::ItemPrototype()->isWritable([$itemPrototypeId])) {
209	access_deny();
210}
211
212/*
213 * Actions
214 */
215if (hasRequest('delete') && hasRequest('itemid')) {
216	DBstart();
217	$result = API::ItemPrototype()->delete([getRequest('itemid')]);
218	$result = DBend($result);
219
220	if ($result) {
221		uncheckTableRows(getRequest('parent_discoveryid'));
222	}
223	show_messages($result, _('Item prototype deleted'), _('Cannot delete item prototype'));
224
225	unset($_REQUEST['itemid'], $_REQUEST['form']);
226}
227elseif (isset($_REQUEST['clone']) && isset($_REQUEST['itemid'])) {
228	unset($_REQUEST['itemid']);
229	$_REQUEST['form'] = 'clone';
230}
231elseif (hasRequest('add') || hasRequest('update')) {
232	$applications = getRequest('applications', []);
233	$application = reset($applications);
234	if ($application == 0) {
235		array_shift($applications);
236	}
237
238	$result = true;
239	DBstart();
240
241	if (!zbx_empty($_REQUEST['new_application'])) {
242		$new_appid = API::Application()->create([
243			'name' => $_REQUEST['new_application'],
244			'hostid' => $discoveryRule['hostid']
245		]);
246		if ($new_appid) {
247			$new_appid = reset($new_appid['applicationids']);
248			$applications[$new_appid] = $new_appid;
249		}
250		else {
251			$result = false;
252		}
253	}
254
255	/*
256	 * Intially validate "delay_flex" field one by one to make sure it does not have interval separator ";".
257	 * Skip empty fields and convert "delay_flex" array to string glued with ";" which is later validated through API.
258	 */
259	$delay_flex = '';
260	$intervals = [];
261
262	if (getRequest('delay_flex')) {
263		foreach (getRequest('delay_flex') as $interval) {
264			if ($interval['type'] == ITEM_DELAY_FLEX_TYPE_FLEXIBLE) {
265				if ($interval['delay'] === '' && $interval['period'] === '') {
266					continue;
267				}
268
269				if (strpos($interval['delay'], ';') !== false) {
270					$result = false;
271					info(_s('Invalid interval "%1$s".', $interval['delay']));
272					break;
273				}
274				elseif (strpos($interval['period'], ';') !== false) {
275					$result = false;
276					info(_s('Invalid interval "%1$s".', $interval['period']));
277					break;
278				}
279
280				$intervals[] = $interval['delay'].'/'.$interval['period'];
281			}
282			else {
283				if ($interval['schedule'] === '') {
284					continue;
285				}
286
287				if (strpos($interval['schedule'], ';') !== false) {
288					$result = false;
289					info(_s('Invalid interval "%1$s".', $interval['schedule']));
290					break;
291				}
292
293				$intervals[] = $interval['schedule'];
294			}
295		}
296
297		if ($intervals) {
298			$delay_flex = join(';', $intervals);
299		}
300	}
301
302	if ($result) {
303		$application_prototypes = getRequest('application_prototypes', []);
304		$application_prototype = reset($application_prototypes);
305
306		if ($application_prototype === '0') {
307			array_shift($application_prototypes);
308		}
309
310		if ($application_prototypes) {
311			foreach ($application_prototypes as &$application_prototype) {
312				$application_prototype = ['name' => $application_prototype];
313			}
314			unset($application_prototype);
315		}
316
317		$new_application_prototype = getRequest('new_application_prototype', '');
318		if ($new_application_prototype !== '') {
319			$application_prototypes[] = ['name' => $new_application_prototype];
320		}
321
322		$item = [
323			'name'			=> getRequest('name'),
324			'description'	=> getRequest('description'),
325			'key_'			=> getRequest('key'),
326			'hostid'		=> $discoveryRule['hostid'],
327			'interfaceid'	=> getRequest('interfaceid'),
328			'delay'			=> getRequest('delay'),
329			'status'		=> getRequest('status', ITEM_STATUS_DISABLED),
330			'type'			=> getRequest('type'),
331			'snmp_community' => getRequest('snmp_community'),
332			'snmp_oid'		=> getRequest('snmp_oid'),
333			'value_type'	=> getRequest('value_type'),
334			'trapper_hosts'	=> getRequest('trapper_hosts'),
335			'port'			=> getRequest('port'),
336			'history'		=> getRequest('history'),
337			'trends'		=> getRequest('trends'),
338			'units'			=> getRequest('units'),
339			'multiplier'	=> getRequest('multiplier', 0),
340			'delta'			=> getRequest('delta'),
341			'snmpv3_contextname' => getRequest('snmpv3_contextname'),
342			'snmpv3_securityname' => getRequest('snmpv3_securityname'),
343			'snmpv3_securitylevel' => getRequest('snmpv3_securitylevel'),
344			'snmpv3_authprotocol' => getRequest('snmpv3_authprotocol'),
345			'snmpv3_authpassphrase' => getRequest('snmpv3_authpassphrase'),
346			'snmpv3_privprotocol' => getRequest('snmpv3_privprotocol'),
347			'snmpv3_privpassphrase' => getRequest('snmpv3_privpassphrase'),
348			'formula'		=> getRequest('formula', '1'),
349			'logtimefmt'	=> getRequest('logtimefmt'),
350			'valuemapid'	=> getRequest('valuemapid'),
351			'authtype'		=> getRequest('authtype'),
352			'username'		=> getRequest('username'),
353			'password'		=> getRequest('password'),
354			'publickey'		=> getRequest('publickey'),
355			'privatekey'	=> getRequest('privatekey'),
356			'params'		=> getRequest('params'),
357			'ipmi_sensor'	=> getRequest('ipmi_sensor'),
358			'data_type'		=> getRequest('data_type'),
359			'ruleid'		=> getRequest('parent_discoveryid'),
360			'delay_flex'	=> $delay_flex
361		];
362
363		if (hasRequest('update')) {
364			$itemId = getRequest('itemid');
365
366			$dbItem = API::ItemPrototype()->get([
367				'output' => ['type', 'snmp_community', 'snmp_oid', 'hostid', 'name', 'key_', 'delay',
368					'history', 'trends', 'status', 'value_type', 'trapper_hosts', 'units', 'multiplier', 'delta',
369					'snmpv3_securityname', 'snmpv3_securitylevel', 'snmpv3_authpassphrase', 'snmpv3_privpassphrase',
370					'formula', 'logtimefmt', 'templateid', 'valuemapid', 'delay_flex', 'params', 'ipmi_sensor',
371					'data_type', 'authtype', 'username', 'password', 'publickey', 'privatekey',	'interfaceid', 'port',
372					'description', 'snmpv3_authprotocol', 'snmpv3_privprotocol', 'snmpv3_contextname'
373				],
374				'selectApplications' => ['applicationid'],
375				'selectApplicationPrototypes' => ['name'],
376				'itemids' => [$itemId]
377			]);
378
379			// unset snmpv3 fields
380			if ($item['snmpv3_securitylevel'] == ITEM_SNMPV3_SECURITYLEVEL_NOAUTHNOPRIV) {
381				$item['snmpv3_authprotocol'] = ITEM_AUTHPROTOCOL_MD5;
382				$item['snmpv3_privprotocol'] = ITEM_PRIVPROTOCOL_DES;
383			}
384			elseif ($item['snmpv3_securitylevel'] == ITEM_SNMPV3_SECURITYLEVEL_AUTHNOPRIV) {
385				$item['snmpv3_privprotocol'] = ITEM_PRIVPROTOCOL_DES;
386			}
387
388			$dbItem = $dbItem[0];
389
390			$item = CArrayHelper::unsetEqualValues($item, $dbItem);
391			$item['itemid'] = $itemId;
392
393			$dbItem['applications'] = zbx_objectValues($dbItem['applications'], 'applicationid');
394
395			// compare applications
396			natsort($dbItem['applications']);
397			natsort($applications);
398
399			if (array_values($dbItem['applications']) !== array_values($applications)) {
400				$item['applications'] = $applications;
401			}
402
403			// compare application prototypes
404			$db_application_prototype_names = zbx_objectValues($dbItem['applicationPrototypes'], 'name');
405			natsort($db_application_prototype_names);
406
407			$application_prototype_names = zbx_objectValues($application_prototypes, 'name');
408			natsort($application_prototype_names);
409
410			if (array_values($db_application_prototype_names) !== array_values($application_prototype_names)) {
411				$item['applicationPrototypes'] = $application_prototypes;
412			}
413
414			$result = API::ItemPrototype()->update($item);
415		}
416		else {
417			$item['applications'] = $applications;
418			$item['applicationPrototypes'] = $application_prototypes;
419
420			$result = API::ItemPrototype()->create($item);
421		}
422	}
423
424	$result = DBend($result);
425
426	if (hasRequest('add')) {
427		show_messages($result, _('Item prototype added'), _('Cannot add item prototype'));
428	}
429	else {
430		show_messages($result, _('Item prototype updated'), _('Cannot update item prototype'));
431	}
432
433	if ($result) {
434		unset($_REQUEST['itemid'], $_REQUEST['form']);
435		uncheckTableRows(getRequest('parent_discoveryid'));
436	}
437}
438elseif (hasRequest('action') && str_in_array(getRequest('action'), ['itemprototype.massenable', 'itemprototype.massdisable']) && hasRequest('group_itemid')) {
439	$groupItemId = getRequest('group_itemid');
440	$enable = (getRequest('action') == 'itemprototype.massenable');
441
442	DBstart();
443	$result = $enable ? activate_item($groupItemId) : disable_item($groupItemId);
444	$result = DBend($result);
445
446	$updated = count($groupItemId);
447
448	$messageSuccess = $enable
449		? _n('Item prototype enabled', 'Item prototypes enabled', $updated)
450		: _n('Item prototype disabled', 'Item prototypes disabled', $updated);
451	$messageFailed = $enable
452		? _n('Cannot enable item prototype', 'Cannot enable item prototypes', $updated)
453		: _n('Cannot disable item prototype', 'Cannot disable item prototypes', $updated);
454
455	if ($result) {
456		uncheckTableRows(getRequest('parent_discoveryid'));
457	}
458	show_messages($result, $messageSuccess, $messageFailed);
459}
460elseif (hasRequest('action') && getRequest('action') == 'itemprototype.massdelete' && hasRequest('group_itemid')) {
461	DBstart();
462
463	$result = API::ItemPrototype()->delete(getRequest('group_itemid'));
464	$result = DBend($result);
465
466	if ($result) {
467		uncheckTableRows(getRequest('parent_discoveryid'));
468	}
469	show_messages($result, _('Item prototypes deleted'), _('Cannot delete item prototypes'));
470}
471
472/*
473 * Display
474 */
475if (isset($_REQUEST['form'])) {
476	$itemPrototype = [];
477	if (hasRequest('itemid')) {
478		$itemPrototype = API::ItemPrototype()->get([
479			'itemids' => getRequest('itemid'),
480			'output' => [
481				'itemid', 'type', 'snmp_community', 'snmp_oid', 'hostid', 'name', 'key_', 'delay', 'history',
482				'trends', 'status', 'value_type', 'trapper_hosts', 'units', 'multiplier', 'delta',
483				'snmpv3_securityname', 'snmpv3_securitylevel', 'snmpv3_authpassphrase', 'snmpv3_privpassphrase',
484				'formula', 'logtimefmt', 'templateid', 'valuemapid', 'delay_flex', 'params', 'ipmi_sensor',
485				'data_type', 'authtype', 'username', 'password', 'publickey', 'privatekey',
486				'interfaceid', 'port', 'description', 'snmpv3_authprotocol', 'snmpv3_privprotocol', 'snmpv3_contextname'
487			]
488		]);
489		$itemPrototype = reset($itemPrototype);
490	}
491
492	$data = getItemFormData($itemPrototype);
493	$data['config'] = select_config();
494
495	// Sort interfaces to be listed starting with one selected as 'main'.
496	CArrayHelper::sort($data['interfaces'], [
497		['field' => 'main', 'order' => ZBX_SORT_DOWN]
498	]);
499
500	// render view
501	$itemView = new CView('configuration.item.prototype.edit', $data);
502	$itemView->render();
503	$itemView->show();
504}
505else {
506	$sortField = getRequest('sort', CProfile::get('web.'.$page['file'].'.sort', 'name'));
507	$sortOrder = getRequest('sortorder', CProfile::get('web.'.$page['file'].'.sortorder', ZBX_SORT_UP));
508
509	CProfile::update('web.'.$page['file'].'.sort', $sortField, PROFILE_TYPE_STR);
510	CProfile::update('web.'.$page['file'].'.sortorder', $sortOrder, PROFILE_TYPE_STR);
511
512	$config = select_config();
513
514	$data = [
515		'form' => getRequest('form'),
516		'parent_discoveryid' => getRequest('parent_discoveryid'),
517		'hostid' => $discoveryRule['hostid'],
518		'sort' => $sortField,
519		'sortorder' => $sortOrder
520	];
521
522	$data['items'] = API::ItemPrototype()->get([
523		'discoveryids' => $data['parent_discoveryid'],
524		'output' => API_OUTPUT_EXTEND,
525		'editable' => true,
526		'selectApplications' => API_OUTPUT_EXTEND,
527		'sortfield' => $sortField,
528		'limit' => $config['search_limit'] + 1
529	]);
530
531	foreach ($data['items'] as &$item) {
532		if ($item['value_type'] == ITEM_VALUE_TYPE_STR || $item['value_type'] == ITEM_VALUE_TYPE_LOG
533				|| $item['value_type'] == ITEM_VALUE_TYPE_TEXT) {
534			$item['trends'] = '';
535		}
536
537		if ($item['type'] == ITEM_TYPE_TRAPPER || $item['type'] == ITEM_TYPE_SNMPTRAP) {
538			$item['delay'] = '';
539		}
540	}
541	unset($item);
542
543	$data['items'] = CMacrosResolverHelper::resolveItemNames($data['items']);
544
545	order_result($data['items'], $sortField, $sortOrder);
546
547	$url = (new CUrl('disc_prototypes.php'))
548		->setArgument('parent_discoveryid', $data['parent_discoveryid']);
549
550	$data['paging'] = getPagingLine($data['items'], $sortOrder, $url);
551
552	// render view
553	$itemView = new CView('configuration.item.prototype.list', $data);
554	$itemView->render();
555	$itemView->show();
556}
557
558require_once dirname(__FILE__).'/include/page_footer.php';
559