1<?php declare(strict_types = 1);
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// Visibility box javascript is already added. It should not be added in popup response.
27define('CVISIBILITYBOX_JAVASCRIPT_INSERTED', 1);
28define('IS_TEXTAREA_MAXLENGTH_JS_INSERTED', 1);
29
30// Create form.
31$form = (new CForm())
32	->setId('massupdate-form')
33	->setName('massupdate-form')
34	->setAttribute('aria-labeledby', ZBX_STYLE_PAGE_TITLE)
35	->addVar('ids', $data['ids'])
36	->addVar('action', $data['action'])
37	->addVar('prototype', $data['prototype'])
38	->addVar('update', '1')
39	->addVar('location_url', $data['location_url'])
40	->addVar('context', $data['context'], uniqid('context_'))
41	->disablePasswordAutofill();
42
43// Create item form list.
44$item_form_list = (new CFormList('item-form-list'))
45	// Append type to form list.
46	->addRow(
47		(new CVisibilityBox('visible[type]', 'type', _('Original')))
48			->setLabel(_('Type'))
49			->setAttribute('autofocus', 'autofocus'),
50		(new CSelect('type'))
51			->setId('type')
52			->setValue(ITEM_TYPE_ZABBIX)
53			->addOptions(CSelect::createOptionsFromArray($data['item_types']))
54	);
55
56// Append hosts interface select to form list.
57if ($data['single_host_selected'] && $data['context'] === 'host') {
58	$item_form_list->addRow(
59		(new CVisibilityBox('visible[interfaceid]', 'interfaceDiv', _('Original')))
60			->setLabel(_('Host interface'))
61			->setAttribute('data-multiple-interface-types', $data['multiple_interface_types']),
62		(new CDiv([
63			getInterfaceSelect($data['interfaces'])
64				->setId('interface-select')
65				->setValue('0')
66				->addClass(ZBX_STYLE_ZSELECT_HOST_INTERFACE),
67			(new CSpan(_('No interface found')))
68				->addClass(ZBX_STYLE_RED)
69				->setId('interface_not_defined')
70				->addStyle('display: none;')
71		]))->setId('interfaceDiv'),
72		'interface_row'
73	);
74}
75
76$item_form_list
77	// Append JMX endpoint to form list.
78	->addRow(
79		(new CVisibilityBox('visible[jmx_endpoint]', 'jmx_endpoint', _('Original')))->setLabel(_('JMX endpoint')),
80		(new CTextBox('jmx_endpoint', ZBX_DEFAULT_JMX_ENDPOINT))->setAdaptiveWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
81	)
82	// Append ITEM_TYPE_HTTPAGENT URL field.
83	->addRow(
84		(new CVisibilityBox('visible[url]', 'url', _('Original')))->setLabel(_('URL')),
85		(new CTextBox('url', '', false, DB::getFieldLength('items', 'url')))
86			->setAdaptiveWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
87	)
88	// Append ITEM_TYPE_HTTPAGENT Request body type.
89	->addRow(
90		(new CVisibilityBox('visible[post_type]', 'post_type_container', _('Original')))
91			->setLabel(_('Request body type')),
92		(new CDiv(
93			(new CRadioButtonList('post_type', (int) DB::getDefault('items', 'post_type')))
94				->addValue(_('Raw data'), ZBX_POSTTYPE_RAW)
95				->addValue(_('JSON data'), ZBX_POSTTYPE_JSON)
96				->addValue(_('XML data'), ZBX_POSTTYPE_XML)
97				->setModern(true)
98		))->setId('post_type_container')
99	)
100	->addRow(
101		(new CVisibilityBox('visible[timeout]', 'timeout', _('Original')))->setLabel(_('Timeout')),
102		(new CTextBox('timeout', DB::getDefault('items', 'timeout')))->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
103	)
104	// Append ITEM_TYPE_HTTPAGENT Request body.
105	->addRow(
106		(new CVisibilityBox('visible[posts]', 'posts', _('Original')))->setLabel(_('Request body')),
107		(new CTextArea('posts', ''))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
108	);
109
110// Append ITEM_TYPE_HTTPAGENT Headers fields.
111$headers = (new CTag('script', true))->setAttribute('type', 'text/json');
112$headers->items = [json_encode([['name' => '', 'value' => '']])];
113
114$item_form_list
115	->addRow(
116		(new CVisibilityBox('visible[headers]', 'headers_pairs', _('Original')))->setLabel(_('Headers')),
117		(new CDiv([
118			(new CTable())
119				->addStyle('width: 100%;')
120				->setHeader(['', _('Name'), '', _('Value'), ''])
121				->addRow((new CRow)->setAttribute('data-insert-point', 'append'))
122				->setFooter(new CRow(
123					(new CCol(
124						(new CButton(null, _('Add')))
125							->addClass(ZBX_STYLE_BTN_LINK)
126							->setAttribute('data-row-action', 'add_row')
127					))->setColSpan(5)
128				)),
129			(new CTag('script', true))
130				->setAttribute('type', 'text/x-jquery-tmpl')
131				->addItem(new CRow([
132					(new CCol((new CDiv)->addClass(ZBX_STYLE_DRAG_ICON)))->addClass(ZBX_STYLE_TD_DRAG_ICON),
133					(new CTextBox('headers[name][#{index}]', '#{name}'))->setWidth(ZBX_TEXTAREA_HTTP_PAIR_NAME_WIDTH),
134					'&rArr;',
135					(new CTextBox('headers[value][#{index}]', '#{value}', false, 2000))
136						->setWidth(ZBX_TEXTAREA_HTTP_PAIR_VALUE_WIDTH),
137					(new CButton(null, _('Remove')))
138						->addClass(ZBX_STYLE_BTN_LINK)
139						->setAttribute('data-row-action', 'remove_row')
140				])),
141			$headers
142		]))
143			->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
144			->setId('headers_pairs')
145			->setAttribute('data-sortable-pairs-table', '1')
146			->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
147	)
148	// Append value type to form list.
149	->addRow(
150		(new CVisibilityBox('visible[value_type]', 'value_type', _('Original')))
151			->setLabel(_('Type of information')),
152		(new CSelect('value_type'))
153			->setId('value_type')
154			->setValue(ITEM_VALUE_TYPE_UINT64)
155			->addOptions(CSelect::createOptionsFromArray([
156				ITEM_VALUE_TYPE_UINT64 => _('Numeric (unsigned)'),
157				ITEM_VALUE_TYPE_FLOAT => _('Numeric (float)'),
158				ITEM_VALUE_TYPE_STR => _('Character'),
159				ITEM_VALUE_TYPE_LOG => _('Log'),
160				ITEM_VALUE_TYPE_TEXT => _('Text')
161			]))
162	)
163	// Append units to form list.
164	->addRow(
165		(new CVisibilityBox('visible[units]', 'units', _('Original')))->setLabel(_('Units')),
166		(new CTextBox('units', ''))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
167	)
168	// Append authtype to form list.
169	->addRow(
170		(new CVisibilityBox('visible[authtype]', 'authtype', _('Original')))->setLabel(_('Authentication method')),
171		(new CSelect('authtype'))
172			->setId('authtype')
173			->setValue(ITEM_AUTHTYPE_PASSWORD)
174			->addOptions(CSelect::createOptionsFromArray([
175				ITEM_AUTHTYPE_PASSWORD => _('Password'),
176				ITEM_AUTHTYPE_PUBLICKEY => _('Public key')
177			]))
178	)
179	// Append username to form list.
180	->addRow(
181		(new CVisibilityBox('visible[username]', 'username', _('Original')))
182			->setLabel(_('User name')),
183		(new CTextBox('username', ''))
184			->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
185			->disableAutocomplete()
186	)
187	// Append publickey to form list.
188	->addRow(
189		(new CVisibilityBox('visible[publickey]', 'publickey', _('Original')))->setLabel(_('Public key file')),
190		(new CTextBox('publickey', ''))->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
191	)
192	// Append privatekey to form list.
193	->addRow(
194		(new CVisibilityBox('visible[privatekey]', 'privatekey', _('Original')))->setLabel(_('Private key file')),
195		(new CTextBox('privatekey', ''))->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
196	)
197	// Append password to form list.
198	->addRow(
199		(new CVisibilityBox('visible[password]', 'password', _('Original')))->setLabel(_('Password')),
200		(new CTextBox('password', ''))
201			->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
202			->disableAutocomplete()
203	);
204
205// Create preprocessing form list.
206$preprocessing_form_list = (new CFormList('preprocessing-form-list'))
207	// Append item pre-processing to form list.
208	->addRow(
209		(new CVisibilityBox('visible[preprocessing]', 'preprocessing_div', _('Original')))
210			->setLabel(_('Preprocessing steps')),
211		(new CDiv(getItemPreprocessing($form, [], false, $data['preprocessing_types'])))
212			->setId('preprocessing_div')
213	);
214
215// Prepare Update interval for form list.
216$update_interval = (new CTable())
217	->setId('update_interval')
218	->addRow([_('Delay'),
219		(new CDiv((new CTextBox('delay', ZBX_ITEM_DELAY_DEFAULT))->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)))
220	]);
221
222$custom_intervals = (new CTable())
223	->setId('custom_intervals')
224	->setHeader([
225		new CColHeader(_('Type')),
226		new CColHeader(_('Interval')),
227		new CColHeader(_('Period')),
228		(new CColHeader(_('Action')))->setWidth(50)
229	])
230	->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR);
231
232foreach ($data['delay_flex'] as $i => $delay_flex) {
233	$type_input = (new CRadioButtonList('delay_flex['.$i.'][type]', (int) $delay_flex['type']))
234		->addValue(_('Flexible'), ITEM_DELAY_FLEXIBLE)
235		->addValue(_('Scheduling'), ITEM_DELAY_SCHEDULING)
236		->setModern(true);
237
238	if ($delay_flex['type'] == ITEM_DELAY_FLEXIBLE) {
239		$delay_input = (new CTextBox('delay_flex['.$i.'][delay]', $delay_flex['delay']))
240			->setAdaptiveWidth(100)
241			->setAttribute('placeholder', ZBX_ITEM_FLEXIBLE_DELAY_DEFAULT);
242		$period_input = (new CTextBox('delay_flex['.$i.'][period]', $delay_flex['period']))
243			->setAdaptiveWidth(110)
244			->setAttribute('placeholder', ZBX_DEFAULT_INTERVAL);
245		$schedule_input = (new CTextBox('delay_flex['.$i.'][schedule]'))
246			->setAttribute('placeholder', ZBX_ITEM_SCHEDULING_DEFAULT)
247			->addStyle('max-width:100px;width:100%;display: none;');
248	}
249	else {
250		$delay_input = (new CTextBox('delay_flex['.$i.'][delay]'))
251			->setAdaptiveWidth(100)
252			->setAttribute('placeholder', ZBX_ITEM_FLEXIBLE_DELAY_DEFAULT)
253			->addStyle('display: none;');
254		$period_input = (new CTextBox('delay_flex['.$i.'][period]'))
255			->setAdaptiveWidth(110)
256			->setAttribute('placeholder', ZBX_DEFAULT_INTERVAL)
257			->addStyle('display: none;');
258		$schedule_input = (new CTextBox('delay_flex['.$i.'][schedule]', $delay_flex['schedule']))
259			->setAdaptiveWidth(100)
260			->setAttribute('placeholder', ZBX_ITEM_SCHEDULING_DEFAULT);
261	}
262
263	$button = (new CButton('delay_flex['.$i.'][remove]', _('Remove')))
264		->addClass(ZBX_STYLE_BTN_LINK)
265		->addClass('element-table-remove');
266
267	$custom_intervals->addRow([$type_input, [$delay_input, $schedule_input], $period_input, $button], 'form_row');
268}
269
270$custom_intervals->addRow([(new CButton('interval_add', _('Add')))
271	->addClass(ZBX_STYLE_BTN_LINK)
272	->addClass('element-table-add')]);
273
274$update_interval->addRow(
275	(new CRow([
276		(new CCol(_('Custom intervals')))->addStyle('vertical-align: top;'),
277		new CCol($custom_intervals)
278	]))
279);
280
281// Append update interval to form list.
282$item_form_list
283	// Append delay to form list.
284	->addRow(
285		(new CVisibilityBox('visible[delay]', 'update_interval_div', _('Original')))->setLabel(_('Update interval')),
286		(new CDiv($update_interval))->setId('update_interval_div')
287	)
288	// Append history to form list.
289	->addRow(
290		(new CVisibilityBox('visible[history]', 'history_div', _('Original')))
291			->setLabel(_('History storage period')),
292		(new CDiv([
293			(new CRadioButtonList('history_mode', ITEM_STORAGE_CUSTOM))
294				->addValue(_('Do not keep history'), ITEM_STORAGE_OFF)
295				->addValue(_('Storage period'), ITEM_STORAGE_CUSTOM)
296				->setModern(true),
297			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
298			(new CTextBox('history', DB::getDefault('items', 'history')))
299				->setWidth(ZBX_TEXTAREA_TINY_WIDTH)
300				->setAriaRequired()
301		]))
302			->addClass('wrap-multiple-controls')
303			->setId('history_div')
304	)
305	// Append trends to form list.
306	->addRow(
307		(new CVisibilityBox('visible[trends]', 'trends_div', _('Original')))->setLabel(_('Trend storage period')),
308		(new CDiv([
309			(new CRadioButtonList('trends_mode', ITEM_STORAGE_CUSTOM))
310				->addValue(_('Do not keep trends'), ITEM_STORAGE_CUSTOM)
311				->addValue(_('Storage period'), ITEM_STORAGE_CUSTOM)
312				->setModern(true),
313			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
314			(new CTextBox('trends', DB::getDefault('items', 'trends')))
315				->setWidth(ZBX_TEXTAREA_TINY_WIDTH)
316				->setAriaRequired()
317		]))
318			->addClass('wrap-multiple-controls')
319			->setId('trends_div')
320	);
321
322// Append status to form list.
323$item_form_list->addRow(
324	(new CVisibilityBox('visible[status]', 'status', _('Original')))
325		->setLabel($data['prototype'] ? _('Create enabled') : _('Status')),
326	(new CRadioButtonList('status', ITEM_STATUS_ACTIVE))
327		->addValue($data['prototype'] ? _('Yes') : item_status2str(ITEM_STATUS_ACTIVE), ITEM_STATUS_ACTIVE)
328		->addValue($data['prototype'] ? _('No') : item_status2str(ITEM_STATUS_DISABLED), ITEM_STATUS_DISABLED)
329		->setModern(true)
330);
331
332if ($data['prototype']) {
333	$item_form_list->addRow(
334		(new CVisibilityBox('visible[discover]', 'discover', _('Original')))->setLabel(_('Discover')),
335		(new CRadioButtonList('discover', ZBX_PROTOTYPE_DISCOVER))
336			->addValue(_('Yes'), ZBX_PROTOTYPE_DISCOVER)
337			->addValue(_('No'), ZBX_PROTOTYPE_NO_DISCOVER)
338			->setModern(true)
339	);
340}
341
342// Append logtime to form list.
343$item_form_list->addRow(
344	(new CVisibilityBox('visible[logtimefmt]', 'logtimefmt', _('Original')))->setLabel(_('Log time format')),
345	(new CTextBox('logtimefmt', ''))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
346);
347
348// Append value map select when only one host or template is selected.
349if ($data['single_host_selected'] && ($data['context'] === 'template' || !$data['discovered_host'])) {
350	$item_form_list->addRow(
351		(new CVisibilityBox('visible[valuemapid]', 'valuemapid_div', _('Original')))->setLabel(_('Value mapping')),
352		(new CDiv([
353			(new CMultiSelect([
354				'name' => 'valuemapid',
355				'object_name' => 'valuemaps',
356				'multiple' => false,
357				'data' => [],
358				'popup' => [
359					'parameters' => [
360						'srctbl' => 'valuemaps',
361						'srcfld1' => 'valuemapid',
362						'dstfrm' => $form->getName(),
363						'dstfld1' => 'valuemapid',
364						'hostids' => [$data['hostid']],
365						'context' => $data['context'],
366						'editable' => true
367					]
368				]
369			]))
370				->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
371		]))->setId('valuemapid_div')
372	);
373}
374
375$item_form_list->addRow(
376		(new CVisibilityBox('visible[allow_traps]', 'allow_traps', _('Original')))->setLabel(_('Enable trapping')),
377		(new CRadioButtonList('allow_traps', HTTPCHECK_ALLOW_TRAPS_OFF))
378			->addValue(_('Yes'), HTTPCHECK_ALLOW_TRAPS_ON)
379			->addValue(_('No'), HTTPCHECK_ALLOW_TRAPS_OFF)
380			->setModern(true)
381	)
382	->addRow(
383		(new CVisibilityBox('visible[trapper_hosts]', 'trapper_hosts', _('Original')))->setLabel(_('Allowed hosts')),
384		(new CTextBox('trapper_hosts', ''))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
385	);
386
387// Append master item select to form list.
388if ($data['single_host_selected']) {
389	if (!$data['prototype']) {
390		$master_item = (new CDiv([
391			(new CMultiSelect([
392				'name' => 'master_itemid',
393				'object_name' => 'items',
394				'multiple' => false,
395				'data' => [],
396				'popup' => [
397					'parameters' => [
398						'srctbl' => 'items',
399						'srcfld1' => 'itemid',
400						'dstfrm' => $form->getName(),
401						'dstfld1' => 'master_itemid',
402						'hostid' => $data['hostid'],
403						'only_hostid' => $data['hostid'],
404						'webitems' => true
405					]
406				]
407			]))
408				->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
409				->setAriaRequired(true)
410		]))->setId('master_item');
411	}
412	else {
413		$master_item = [
414			(new CTextBox('master_itemname', '', true))
415				->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
416				->setAriaRequired(),
417			(new CVar('master_itemid', '', 'master_itemid'))
418		];
419
420		$master_item[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
421		$master_item[] = (new CButton('button', _('Select')))
422			->addClass(ZBX_STYLE_BTN_GREY)
423			->removeId()
424			->onClick('return PopUp("popup.generic",'.
425				json_encode([
426					'srctbl' => 'items',
427					'srcfld1' => 'itemid',
428					'srcfld2' => 'name',
429					'dstfrm' => $form->getName(),
430					'dstfld1' => 'master_itemid',
431					'dstfld2' => 'master_itemname',
432					'only_hostid' => $data['hostid'],
433					'with_webitems' => 1,
434					'normal_only' => 1
435				]).', null, this);'
436			);
437
438		$master_item[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
439		$master_item[] = (new CButton('button', _('Select prototype')))
440			->addClass(ZBX_STYLE_BTN_GREY)
441			->removeId()
442			->onClick('return PopUp("popup.generic",'.
443				json_encode([
444					'srctbl' => 'item_prototypes',
445					'srcfld1' => 'itemid',
446					'srcfld2' => 'name',
447					'dstfrm' => $form->getName(),
448					'dstfld1' => 'master_itemid',
449					'dstfld2' => 'master_itemname',
450					'parent_discoveryid' => $data['parent_discoveryid']
451				]).', null, this);'
452			);
453	}
454
455	$item_form_list->addRow(
456		(new CVisibilityBox('visible[master_itemid]', 'master_item', _('Original')))->setLabel(_('Master item')),
457		(new CDiv([
458			(new CVar('master_itemname')),
459			$master_item
460		]))->setId('master_item')
461	);
462}
463
464// Append description to form list.
465$item_form_list->addRow(
466	(new CVisibilityBox('visible[description]', 'description', _('Original')))->setLabel(_('Description')),
467	(new CTextArea('description', ''))
468		->setAdaptiveWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
469		->setMaxlength(DB::getFieldLength('items', 'description'))
470);
471
472/*
473 * Tags tab
474 */
475$tags_form_list = (new CFormList('tags-form-list'))
476	->addRow(
477		(new CVisibilityBox('visible[tags]', 'tags-div', _('Original')))->setLabel(_('Tags')),
478		(new CDiv([
479			(new CRadioButtonList('mass_update_tags', ZBX_ACTION_ADD))
480				->addValue(_('Add'), ZBX_ACTION_ADD)
481				->addValue(_('Replace'), ZBX_ACTION_REPLACE)
482				->addValue(_('Remove'), ZBX_ACTION_REMOVE)
483				->setModern(true)
484				->addStyle('margin-bottom: 10px;'),
485			renderTagTable([['tag' => '', 'value' => '']])
486				->setHeader([_('Name'), _('Value'), _('Action')])
487				->setId('tags-table')
488		]))->setId('tags-div')
489	);
490
491$tabs = (new CTabView())
492	->addTab('item_tab', $data['prototype'] ? _('Item prototype') : _('Item'), $item_form_list)
493	->addTab('tags_tab', _('Tags'), $tags_form_list)
494	->addTab('preprocessing_tab', _('Preprocessing'), $preprocessing_form_list)
495	->setSelected(0);
496
497// Append tabs to form.
498$form->addItem($tabs);
499
500$form->addItem(new CJsScript($this->readJsFile('popup.massupdate.tmpl.js.php')));
501$form->addItem(new CJsScript($this->readJsFile('popup.massupdate.item.js.php', $data)));
502$form->addItem(new CJsScript($this->readJsFile('../../../include/views/js/item.preprocessing.js.php')));
503$form->addItem(new CJsScript($this->readJsFile('../../../include/views/js/editabletable.js.php')));
504$form->addItem(new CJsScript($this->readJsFile('../../../include/views/js/itemtest.js.php')));
505
506$output = [
507	'header' => $data['title'],
508	'body' => $form->toString(),
509	'buttons' => [
510		[
511			'title' => _('Update'),
512			'class' => '',
513			'keepOpen' => true,
514			'isSubmit' => true,
515			'action' => 'return submitPopup(overlay);'
516		]
517	]
518];
519
520$output['script_inline'] = $this->readJsFile('popup.massupdate.js.php');
521$output['script_inline'] .= getPagePostJs();
522
523if ($data['user']['debug_mode'] == GROUP_DEBUG_MODE_ENABLED) {
524	CProfiler::getInstance()->stop();
525	$output['debug'] = CProfiler::getInstance()->make()->toString();
526}
527
528echo json_encode($output);
529