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__).'/js/configuration.action.edit.js.php';
23
24$widget = (new CWidget())->setTitle(_('Actions'));
25
26// create form
27$actionForm = (new CForm())
28	->setName('action.edit')
29	->setAttribute('aria-labeledby', ZBX_STYLE_PAGE_TITLE)
30	->addVar('form', $data['form'])
31	->addVar('eventsource', $data['eventsource']);
32
33if ($data['actionid']) {
34	$actionForm->addVar('actionid', $data['actionid']);
35}
36
37// Action tab.
38$action_tab = (new CFormList())
39	->addRow(
40		(new CLabel(_('Name'), 'name'))->setAsteriskMark(),
41		(new CTextBox('name', $data['action']['name']))
42			->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
43			->setAriaRequired()
44			->setAttribute('autofocus', 'autofocus')
45	);
46
47// Create condition table.
48$condition_table = (new CTable(_('No conditions defined.')))
49	->setId('conditionTable')
50	->setAttribute('style', 'width: 100%;')
51	->setHeader([_('Label'), _('Name'), _('Action')]);
52
53$i = 0;
54
55if ($data['action']['filter']['conditions']) {
56	$actionConditionStringValues = actionConditionValueToString([$data['action']], $data['config']);
57
58	foreach ($data['action']['filter']['conditions'] as $cIdx => $condition) {
59		if (!isset($condition['conditiontype'])) {
60			$condition['conditiontype'] = 0;
61		}
62		if (!isset($condition['operator'])) {
63			$condition['operator'] = 0;
64		}
65		if (!isset($condition['value'])) {
66			$condition['value'] = '';
67		}
68		if (!array_key_exists('value2', $condition)) {
69			$condition['value2'] = '';
70		}
71		if (!str_in_array($condition['conditiontype'], $data['allowedConditions'])) {
72			continue;
73		}
74
75		$label = isset($condition['formulaid']) ? $condition['formulaid'] : num2letter($i);
76
77		$labelSpan = (new CSpan($label))
78			->addClass('label')
79			->setAttribute('data-conditiontype', $condition['conditiontype'])
80			->setAttribute('data-formulaid', $label);
81
82		$condition_table->addRow(
83			[
84				$labelSpan,
85				getConditionDescription($condition['conditiontype'], $condition['operator'],
86					$actionConditionStringValues[0][$cIdx], $condition['value2']
87				),
88				(new CCol([
89					(new CButton('remove', _('Remove')))
90						->onClick('javascript: removeCondition('.$i.');')
91						->addClass(ZBX_STYLE_BTN_LINK)
92						->removeId(),
93					new CVar('conditions['.$i.']', $condition)
94				]))->addClass(ZBX_STYLE_NOWRAP)
95			],
96			null, 'conditions_'.$i
97		);
98
99		$i++;
100	}
101}
102
103$formula = (new CTextBox('formula', $data['action']['filter']['formula']))
104	->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
105	->setId('formula')
106	->setAttribute('placeholder', 'A or (B and C) &hellip;');
107
108$calculationTypeComboBox = new CComboBox('evaltype', $data['action']['filter']['evaltype'],
109	'processTypeOfCalculation()',
110	[
111		CONDITION_EVAL_TYPE_AND_OR => _('And/Or'),
112		CONDITION_EVAL_TYPE_AND => _('And'),
113		CONDITION_EVAL_TYPE_OR => _('Or'),
114		CONDITION_EVAL_TYPE_EXPRESSION => _('Custom expression')
115	]
116);
117
118$action_tab->addRow(_('Type of calculation'), [
119	$calculationTypeComboBox,
120	(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
121	(new CSpan())->setId('conditionLabel'),
122	$formula
123]);
124$action_tab->addRow(_('Conditions'),
125	(new CDiv($condition_table))
126		->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
127		->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
128);
129
130// append new condition to form list
131$conditionTypeComboBox = new CComboBox('new_condition[conditiontype]', $data['new_condition']['conditiontype'], 'submit()');
132foreach ($data['allowedConditions'] as $key => $condition) {
133	$data['allowedConditions'][$key] = [
134		'name' => condition_type2str($condition),
135		'type' => $condition
136	];
137}
138order_result($data['allowedConditions'], 'name');
139foreach ($data['allowedConditions'] as $condition) {
140	$conditionTypeComboBox->addItem($condition['type'], $condition['name']);
141}
142
143$condition_operators_list = get_operators_by_conditiontype($data['new_condition']['conditiontype']);
144
145if (count($condition_operators_list) > 1) {
146	$condition_operator = new CComboBox('new_condition[operator]', $data['new_condition']['operator']);
147
148	foreach ($condition_operators_list as $operator) {
149		$condition_operator->addItem($operator, condition_operator2str($operator));
150	}
151}
152else {
153	$condition_operator = [new CVar('new_condition[operator]', $condition_operators_list[0]),
154		condition_operator2str($condition_operators_list[0])
155	];
156}
157
158$condition2 = null;
159
160switch ($data['new_condition']['conditiontype']) {
161	case CONDITION_TYPE_HOST_GROUP:
162		$condition = (new CMultiSelect([
163			'name' => 'new_condition[value][]',
164			'object_name' => 'hostGroup',
165			'default_value' => 0,
166			'popup' => [
167				'parameters' => [
168					'srctbl' => 'host_groups',
169					'srcfld1' => 'groupid',
170					'dstfrm' => $actionForm->getName(),
171					'dstfld1' => 'new_condition_value_',
172					'editable' => true
173				]
174			]
175		]))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
176		break;
177
178	case CONDITION_TYPE_TEMPLATE:
179		$condition = (new CMultiSelect([
180			'name' => 'new_condition[value][]',
181			'object_name' => 'templates',
182			'default_value' => 0,
183			'popup' => [
184				'parameters' => [
185					'srctbl' => 'templates',
186					'srcfld1' => 'hostid',
187					'srcfld2' => 'host',
188					'dstfrm' => $actionForm->getName(),
189					'dstfld1' => 'new_condition_value_',
190					'editable' => true
191				]
192			]
193		]))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
194		break;
195
196	case CONDITION_TYPE_HOST:
197		$condition = (new CMultiSelect([
198			'name' => 'new_condition[value][]',
199			'object_name' => 'hosts',
200			'default_value' => 0,
201			'popup' => [
202				'parameters' => [
203					'srctbl' => 'hosts',
204					'srcfld1' => 'hostid',
205					'dstfrm' => $actionForm->getName(),
206					'dstfld1' => 'new_condition_value_',
207					'editable' => true
208				]
209			]
210		]))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
211		break;
212
213	case CONDITION_TYPE_TRIGGER:
214		$condition = (new CMultiSelect([
215			'name' => 'new_condition[value][]',
216			'object_name' => 'triggers',
217			'default_value' => 0,
218			'popup' => [
219				'parameters' => [
220					'srctbl' => 'triggers',
221					'srcfld1' => 'triggerid',
222					'dstfrm' => $actionForm->getName(),
223					'dstfld1' => 'new_condition_value_',
224					'editable' => true,
225					'noempty' => true
226				]
227			]
228		]))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
229		break;
230
231	case CONDITION_TYPE_TRIGGER_NAME:
232		$condition = (new CTextBox('new_condition[value]', ''))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
233		break;
234
235	case CONDITION_TYPE_TIME_PERIOD:
236		$condition = (new CTextBox('new_condition[value]', ZBX_DEFAULT_INTERVAL))
237			->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
238		break;
239
240	case CONDITION_TYPE_TRIGGER_SEVERITY:
241		$severityNames = [];
242		for ($severity = TRIGGER_SEVERITY_NOT_CLASSIFIED; $severity < TRIGGER_SEVERITY_COUNT; $severity++) {
243			$severityNames[] = getSeverityName($severity, $data['config']);
244		}
245		$condition = new CComboBox('new_condition[value]', null, null, $severityNames);
246		break;
247
248	case CONDITION_TYPE_DRULE:
249		$condition = (new CMultiSelect([
250			'name' => 'new_condition[value][]',
251			'object_name' => 'drules',
252			'default_value' => 0,
253			'popup' => [
254				'parameters' => [
255					'srctbl' => 'drules',
256					'srcfld1' => 'druleid',
257					'dstfrm' => $actionForm->getName(),
258					'dstfld1' => 'new_condition_value_'
259				]
260			]
261		]))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
262		break;
263
264	case CONDITION_TYPE_DCHECK:
265		$action_tab->addItem(new CVar('new_condition[value]', '0'));
266		$condition = [
267			(new CTextBox('dcheck', '', true))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH),
268			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
269			(new CButton('btn1', _('Select')))
270				->addClass(ZBX_STYLE_BTN_GREY)
271				->onClick('return PopUp("popup.generic",'.
272					CJs::encodeJson([
273						'srctbl' => 'dchecks',
274						'srcfld1' => 'dcheckid',
275						'srcfld2' => 'name',
276						'dstfrm' => $actionForm->getName(),
277						'dstfld1' => 'new_condition_value',
278						'dstfld2' => 'dcheck',
279						'writeonly' => '1'
280					]).', null, this);'
281				)
282		];
283		break;
284
285	case CONDITION_TYPE_PROXY:
286		$condition = (new CMultiSelect([
287			'name' => 'new_condition[value]',
288			'object_name' => 'proxies',
289			'multiple' => false,
290			'default_value' => 0,
291			'popup' => [
292				'parameters' => [
293					'srctbl' => 'proxies',
294					'srcfld1' => 'proxyid',
295					'srcfld2' => 'host',
296					'dstfrm' => $actionForm->getName(),
297					'dstfld1' => 'new_condition_value'
298				]
299			]
300		]))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
301		break;
302
303	case CONDITION_TYPE_DHOST_IP:
304		$condition = (new CTextBox('new_condition[value]', '192.168.0.1-127,192.168.2.1'))
305			->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
306		break;
307
308	case CONDITION_TYPE_DSERVICE_TYPE:
309		$discoveryCheckTypes = discovery_check_type2str();
310		order_result($discoveryCheckTypes);
311
312		$condition = new CComboBox('new_condition[value]', null, null, $discoveryCheckTypes);
313		break;
314
315	case CONDITION_TYPE_DSERVICE_PORT:
316		$condition = (new CTextBox('new_condition[value]', '0-1023,1024-49151'))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
317		break;
318
319	case CONDITION_TYPE_DSTATUS:
320		$condition = new CComboBox('new_condition[value]');
321		foreach ([DOBJECT_STATUS_UP, DOBJECT_STATUS_DOWN, DOBJECT_STATUS_DISCOVER, DOBJECT_STATUS_LOST] as $stat) {
322			$condition->addItem($stat, discovery_object_status2str($stat));
323		}
324		break;
325
326	case CONDITION_TYPE_DOBJECT:
327		$condition = new CComboBox('new_condition[value]');
328		foreach ([EVENT_OBJECT_DHOST, EVENT_OBJECT_DSERVICE] as $object) {
329			$condition->addItem($object, discovery_object2str($object));
330		}
331		break;
332
333	case CONDITION_TYPE_DUPTIME:
334		$condition = (new CNumericBox('new_condition[value]', 600, 15))->setWidth(ZBX_TEXTAREA_NUMERIC_BIG_WIDTH);
335		break;
336
337	case CONDITION_TYPE_DVALUE:
338		$condition = (new CTextBox('new_condition[value]', ''))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
339		break;
340
341	case CONDITION_TYPE_APPLICATION:
342		$condition = (new CTextBox('new_condition[value]', ''))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
343		break;
344
345	case CONDITION_TYPE_HOST_NAME:
346		$condition = (new CTextBox('new_condition[value]', ''))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
347		break;
348
349	case CONDITION_TYPE_EVENT_TYPE:
350		$condition = new CComboBox('new_condition[value]', null, null, eventType());
351		break;
352
353	case CONDITION_TYPE_HOST_METADATA:
354		$condition = (new CTextBox('new_condition[value]', ''))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
355		break;
356
357	case CONDITION_TYPE_EVENT_TAG:
358		$condition = (new CTextBox('new_condition[value]', ''))
359			->setWidth(ZBX_TEXTAREA_TAG_WIDTH)
360			->setAttribute('placeholder', _('tag'));
361		break;
362
363	case CONDITION_TYPE_EVENT_TAG_VALUE:
364		$condition = (new CTextBox('new_condition[value]', ''))
365			->setWidth(ZBX_TEXTAREA_TAG_WIDTH)
366			->setAttribute('placeholder', _('value'));
367
368		$condition2 = (new CTextBox('new_condition[value2]', ''))
369			->setWidth(ZBX_TEXTAREA_TAG_WIDTH)
370			->setAttribute('placeholder', _('tag'));
371		break;
372
373	default:
374		$condition = null;
375}
376
377$action_tab->addRow(_('New condition'),
378	(new CDiv(
379		(new CTable())
380			->setAttribute('style', 'width: 100%;')
381			->addRow(
382				new CCol([
383					$conditionTypeComboBox,
384					(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
385					$condition2,
386					($condition2 === null) ? null : (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
387					$condition_operator,
388					(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
389					$condition
390				])
391			)
392			->addRow(
393				(new CSimpleButton(_('Add')))
394					->onClick('javascript: submitFormWithParam("'.$actionForm->getName().'", "add_condition", "1");')
395					->addClass(ZBX_STYLE_BTN_LINK)
396			)
397	))
398		->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
399		->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
400);
401
402$action_tab->addRow(_('Enabled'),
403	(new CCheckBox('status', ACTION_STATUS_ENABLED))->setChecked($data['action']['status'] == ACTION_STATUS_ENABLED)
404);
405
406// Operations tab.
407$operation_tab = new CFormList();
408
409if ($data['eventsource'] == EVENT_SOURCE_TRIGGERS || $data['eventsource'] == EVENT_SOURCE_INTERNAL) {
410	$operation_tab->addRow((new CLabel(_('Default operation step duration'), 'esc_period'))->setAsteriskMark(),
411		(new CTextBox('esc_period', $data['action']['esc_period']))
412			->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
413			->setAriaRequired()
414	);
415}
416
417$operation_tab
418	->addRow(_('Default subject'),
419		(new CTextBox('def_shortdata', $data['action']['def_shortdata']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
420	)
421	->addRow(_('Default message'),
422		(new CTextArea('def_longdata', $data['action']['def_longdata']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
423	);
424
425if ($data['eventsource'] == EVENT_SOURCE_TRIGGERS) {
426	$operation_tab->addRow(_('Pause operations for suppressed problems'),
427		(new CCheckBox('pause_suppressed', ACTION_PAUSE_SUPPRESSED_TRUE))
428			->setChecked($data['action']['pause_suppressed'] == ACTION_PAUSE_SUPPRESSED_TRUE)
429	);
430}
431
432// create operation table
433$operationsTable = (new CTable())->setAttribute('style', 'width: 100%;');
434if ($data['eventsource'] == EVENT_SOURCE_TRIGGERS || $data['eventsource'] == EVENT_SOURCE_INTERNAL) {
435	$operationsTable->setHeader([_('Steps'), _('Details'), _('Start in'), _('Duration'), _('Action')]);
436	$delays = count_operations_delay($data['action']['operations'], $data['action']['esc_period']);
437}
438else {
439	$operationsTable->setHeader([_('Details'), _('Action')]);
440}
441
442if ($data['action']['operations']) {
443	$actionOperationDescriptions = getActionOperationDescriptions([$data['action']], ACTION_OPERATION);
444
445	$default_message = [
446		'subject' => $data['action']['def_shortdata'],
447		'message' => $data['action']['def_longdata']
448	];
449
450	$action_operation_hints = getActionOperationHints($data['action']['operations'], $default_message);
451
452	$simple_interval_parser = new CSimpleIntervalParser();
453
454	foreach ($data['action']['operations'] as $operationid => $operation) {
455		if (!str_in_array($operation['operationtype'], $data['allowedOperations'][ACTION_OPERATION])) {
456			continue;
457		}
458		if (!isset($operation['opconditions'])) {
459			$operation['opconditions'] = [];
460		}
461		if (!isset($operation['mediatypeid'])) {
462			$operation['mediatypeid'] = 0;
463		}
464
465		$details = new CSpan($actionOperationDescriptions[0][$operationid]);
466
467		if (array_key_exists($operationid, $action_operation_hints) && $action_operation_hints[$operationid]) {
468			$details->setHint($action_operation_hints[$operationid]);
469		}
470
471		if ($data['eventsource'] == EVENT_SOURCE_TRIGGERS || $data['eventsource'] == EVENT_SOURCE_INTERNAL) {
472			$esc_steps_txt = null;
473			$esc_period_txt = null;
474			$esc_delay_txt = null;
475
476			if ($operation['esc_step_from'] < 1) {
477				$operation['esc_step_from'] = 1;
478			}
479
480			$esc_steps_txt = $operation['esc_step_from'].' - '.$operation['esc_step_to'];
481
482			// display N-N as N
483			$esc_steps_txt = ($operation['esc_step_from'] == $operation['esc_step_to'])
484				? $operation['esc_step_from']
485				: $operation['esc_step_from'].' - '.$operation['esc_step_to'];
486
487			$esc_period_txt = ($simple_interval_parser->parse($operation['esc_period']) == CParser::PARSE_SUCCESS
488					&& timeUnitToSeconds($operation['esc_period']) == 0)
489				? _('Default')
490				: $operation['esc_period'];
491
492			$esc_delay_txt = ($delays[$operation['esc_step_from']] === null)
493				? _('Unknown')
494				: ($delays[$operation['esc_step_from']] != 0
495					? convert_units(['value' => $delays[$operation['esc_step_from']], 'units' => 'uptime'])
496					: _('Immediately')
497				);
498
499			$operationRow = [
500				$esc_steps_txt,
501				$details,
502				$esc_delay_txt,
503				$esc_period_txt,
504				(new CCol(
505					new CHorList([
506						(new CSimpleButton(_('Edit')))
507							->onClick('javascript: submitFormWithParam('.
508								'"'.$actionForm->getName().'", "edit_operationid['.$operationid.']", "1"'.
509							');')
510							->addClass(ZBX_STYLE_BTN_LINK),
511						[
512							(new CButton('remove', _('Remove')))
513								->onClick('javascript: removeOperation('.$operationid.', '.ACTION_OPERATION.');')
514								->addClass(ZBX_STYLE_BTN_LINK)
515								->removeId(),
516							new CVar('operations['.$operationid.']', $operation)
517						]
518					])
519				))->addClass(ZBX_STYLE_NOWRAP)
520			];
521		}
522		else {
523			$operationRow = [
524				$details,
525				(new CCol(
526					new CHorList([
527						(new CSimpleButton(_('Edit')))
528							->onClick('javascript: submitFormWithParam('.
529								'"'.$actionForm->getName().'", "edit_operationid['.$operationid.']", "1"'.
530							');')
531							->addClass(ZBX_STYLE_BTN_LINK),
532						[
533							(new CButton('remove', _('Remove')))
534								->onClick('javascript: removeOperation('.$operationid.', '.ACTION_OPERATION.');')
535								->addClass(ZBX_STYLE_BTN_LINK)
536								->removeId(),
537							new CVar('operations['.$operationid.']', $operation)
538						]
539					])
540				))->addClass(ZBX_STYLE_NOWRAP)
541			];
542		}
543		$operationsTable->addRow($operationRow, null, 'operations_'.$operationid);
544
545		$operation['opmessage_grp'] = isset($operation['opmessage_grp'])
546			? zbx_toHash($operation['opmessage_grp'], 'usrgrpid')
547			: null;
548		$operation['opmessage_usr'] = isset($operation['opmessage_usr'])
549			? zbx_toHash($operation['opmessage_usr'], 'userid')
550			: null;
551		$operation['opcommand_grp'] = isset($operation['opcommand_grp'])
552			? zbx_toHash($operation['opcommand_grp'], 'groupid')
553			: null;
554		$operation['opcommand_hst'] = isset($operation['opcommand_hst'])
555			? zbx_toHash($operation['opcommand_hst'], 'hostid')
556			: null;
557	}
558}
559
560$footer = null;
561if (empty($data['new_operation'])) {
562	$footer = (new CSimpleButton(_('New')))
563		->onClick('javascript: submitFormWithParam("'.$actionForm->getName().'", "new_operation", "1");')
564		->addClass(ZBX_STYLE_BTN_LINK);
565}
566
567$operation_tab->addRow(_('Operations'),
568	(new CDiv([$operationsTable, $footer]))
569		->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
570		->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
571);
572
573// create new operation table
574if (!empty($data['new_operation'])) {
575	$new_operation_vars = [
576		new CVar('new_operation[actionid]', $data['actionid'])
577	];
578
579	$new_operation_formlist = (new CFormList())->setAttribute('style', 'width: 100%;');
580
581	if (isset($data['new_operation']['id'])) {
582		$new_operation_vars[] = new CVar('new_operation[id]', $data['new_operation']['id']);
583	}
584	if (isset($data['new_operation']['operationid'])) {
585		$new_operation_vars[] = new CVar('new_operation[operationid]', $data['new_operation']['operationid']);
586	}
587
588	if ($data['eventsource'] == EVENT_SOURCE_TRIGGERS || $data['eventsource'] == EVENT_SOURCE_INTERNAL) {
589		$stepFrom = (new CNumericBox('new_operation[esc_step_from]', $data['new_operation']['esc_step_from'], 5))
590			->setWidth(ZBX_TEXTAREA_NUMERIC_STANDARD_WIDTH);
591		$stepFrom->onChange('javascript:'.$stepFrom->getAttribute('onchange').' if (this.value == 0) this.value = 1;');
592
593		$new_operation_formlist->addRow(_('Steps'), [
594			$stepFrom,
595			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
596			'-',
597			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
598			(new CNumericBox('new_operation[esc_step_to]', $data['new_operation']['esc_step_to'], 5))
599				->setWidth(ZBX_TEXTAREA_NUMERIC_STANDARD_WIDTH),
600			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
601			_('(0 - infinitely)')
602		]);
603
604		$new_operation_formlist->addRow(_('Step duration'), [
605			(new CTextBox('new_operation[esc_period]', $data['new_operation']['esc_period']))
606				->setWidth(ZBX_TEXTAREA_SMALL_WIDTH),
607			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
608			_('(0 - use action default)')
609		]);
610	}
611
612	// if only one operation is available - show only the label
613	if (count($data['allowedOperations'][ACTION_OPERATION]) == 1) {
614		$operation = $data['allowedOperations'][ACTION_OPERATION][0];
615		$new_operation_formlist->addRow(_('Operation type'),
616			[operation_type2str($operation), new CVar('new_operation[operationtype]', $operation)]
617		);
618	}
619	// if multiple operation types are available, display a select
620	else {
621		$operationTypeComboBox = new CComboBox('new_operation[operationtype]',
622			$data['new_operation']['operationtype'], 'submit()'
623		);
624		foreach ($data['allowedOperations'][ACTION_OPERATION] as $operation) {
625			$operationTypeComboBox->addItem($operation, operation_type2str($operation));
626		}
627		$new_operation_formlist->addRow((new CLabel(_('Operation type'), 'new_operation[operationtype]')),
628			$operationTypeComboBox
629		);
630	}
631
632	switch ($data['new_operation']['operationtype']) {
633		case OPERATION_TYPE_ACK_MESSAGE:
634			if (!array_key_exists('opmessage', $data['new_operation'])) {
635				$data['new_operation']['opmessage'] = [
636					'default_msg'	=> 1,
637					'mediatypeid'	=> 0,
638					'subject'		=> ACTION_DEFAULT_SUBJ_ACKNOWLEDGE,
639					'message'		=> ACTION_DEFAULT_MSG_ACKNOWLEDGE
640				];
641			}
642			elseif (!array_key_exists('default_msg', $data['new_operation']['opmessage'])) {
643				$data['new_operation']['opmessage']['default_msg'] = 0;
644			}
645			break;
646
647		case OPERATION_TYPE_MESSAGE:
648			if (!isset($data['new_operation']['opmessage'])) {
649				$data['new_operation']['opmessage_usr'] = [];
650				$data['new_operation']['opmessage'] = ['default_msg' => 1, 'mediatypeid' => 0];
651
652				if ($data['eventsource'] == EVENT_SOURCE_TRIGGERS) {
653					$data['new_operation']['opmessage']['subject'] = ACTION_DEFAULT_SUBJ_PROBLEM;
654					$data['new_operation']['opmessage']['message'] = ACTION_DEFAULT_MSG_PROBLEM;
655				}
656				elseif ($data['eventsource'] == EVENT_SOURCE_DISCOVERY) {
657					$data['new_operation']['opmessage']['subject'] = ACTION_DEFAULT_SUBJ_DISCOVERY;
658					$data['new_operation']['opmessage']['message'] = ACTION_DEFAULT_MSG_DISCOVERY;
659				}
660				elseif ($data['eventsource'] == EVENT_SOURCE_AUTO_REGISTRATION) {
661					$data['new_operation']['opmessage']['subject'] = ACTION_DEFAULT_SUBJ_AUTOREG;
662					$data['new_operation']['opmessage']['message'] = ACTION_DEFAULT_MSG_AUTOREG;
663				}
664				else {
665					$data['new_operation']['opmessage']['subject'] = '';
666					$data['new_operation']['opmessage']['message'] = '';
667				}
668			}
669
670			if (!isset($data['new_operation']['opmessage']['default_msg'])) {
671				$data['new_operation']['opmessage']['default_msg'] = 0;
672			}
673
674			$usrgrpList = (new CTable())
675				->setAttribute('style', 'width: 100%;')
676				->setHeader([_('User group'), _('Action')]);
677
678			$addUsrgrpBtn = (new CButton(null, _('Add')))
679				->onClick('return PopUp("popup.generic",'.
680					CJs::encodeJson([
681						'srctbl' => 'usrgrp',
682						'srcfld1' => 'usrgrpid',
683						'srcfld2' => 'name',
684						'dstfrm' => $actionForm->getName(),
685						'dstfld1' => 'opmsgUsrgrpListFooter',
686						'multiselect' => '1'
687					]).', null, this);'
688				)
689				->addClass(ZBX_STYLE_BTN_LINK);
690			$usrgrpList->addRow(
691				(new CRow(
692					(new CCol($addUsrgrpBtn))->setColSpan(2)
693				))->setId('opmsgUsrgrpListFooter')
694			);
695
696			$userList = (new CTable())
697				->setAttribute('style', 'width: 100%;')
698				->setHeader([_('User'), _('Action')]);
699
700			$addUserBtn = (new CButton(null, _('Add')))
701				->onClick('return PopUp("popup.generic",'.
702					CJs::encodeJson([
703						'srctbl' => 'users',
704						'srcfld1' => 'userid',
705						'srcfld2' => 'fullname',
706						'dstfrm' => $actionForm->getName(),
707						'dstfld1' => 'opmsgUserListFooter',
708						'multiselect' => '1'
709					]).', null, this);'
710				)
711				->addClass(ZBX_STYLE_BTN_LINK);
712			$userList->addRow(
713				(new CRow(
714					(new CCol($addUserBtn))->setColSpan(2)
715				))->setId('opmsgUserListFooter')
716			);
717
718			// add participations
719			$usrgrpids = isset($data['new_operation']['opmessage_grp'])
720				? zbx_objectValues($data['new_operation']['opmessage_grp'], 'usrgrpid')
721				: [];
722
723			$userids = isset($data['new_operation']['opmessage_usr'])
724				? zbx_objectValues($data['new_operation']['opmessage_usr'], 'userid')
725				: [];
726
727			$usrgrps = API::UserGroup()->get([
728				'usrgrpids' => $usrgrpids,
729				'output' => ['name']
730			]);
731			order_result($usrgrps, 'name');
732
733			$users = API::User()->get([
734				'userids' => $userids,
735				'output' => ['userid', 'alias', 'name', 'surname']
736			]);
737			order_result($users, 'alias');
738
739			foreach ($users as &$user) {
740				$user['id'] = $user['userid'];
741				$user['name'] = getUserFullname($user);
742			}
743			unset($user);
744
745			$js_insert = 'addPopupValues('.
746				zbx_jsvalue(['object' => 'usrgrpid', 'values' => $usrgrps, 'parentId' => 'opmsgUsrgrpListFooter']).
747			');';
748			$js_insert .= 'addPopupValues('.
749				zbx_jsvalue(['object' => 'userid', 'values' => $users, 'parentId' => 'opmsgUserListFooter']).
750			');';
751			zbx_add_post_js($js_insert);
752
753			$new_operation_formlist
754				->addRow('', (new CLabel(_('At least one user or user group must be selected.')))->setAsteriskMark())
755				->addRow(_('Send to User groups'),
756					(new CDiv($usrgrpList))
757						->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
758						->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
759				)
760				->addRow(_('Send to Users'),
761					(new CDiv($userList))
762						->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
763						->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
764				);
765
766			$media_type_combobox = (new CComboBox('new_operation[opmessage][mediatypeid]',
767				$data['new_operation']['opmessage']['mediatypeid']
768			))->addItem(0, '- '._('All').' -');
769
770			foreach ($data['available_mediatypes'] as $value) {
771				$media_type_combobox->addItem($value['mediatypeid'], $value['description'], null, true,
772					($value['status'] == MEDIA_TYPE_STATUS_DISABLED) ? ZBX_STYLE_RED : null
773				);
774			}
775
776			$new_operation_formlist
777				->addRow(_('Send only to'), $media_type_combobox)
778				->addRow(_('Default message'),
779					(new CCheckBox('new_operation[opmessage][default_msg]'))
780						->setChecked($data['new_operation']['opmessage']['default_msg'] == 1)
781				)
782				->addRow(_('Subject'),
783					(new CTextBox('new_operation[opmessage][subject]', $data['new_operation']['opmessage']['subject']))
784						->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
785				)
786				->addRow(_('Message'),
787					(new CTextArea('new_operation[opmessage][message]', $data['new_operation']['opmessage']['message']))
788						->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
789				);
790			break;
791
792		case OPERATION_TYPE_COMMAND:
793			if (!isset($data['new_operation']['opcommand'])) {
794				$data['new_operation']['opcommand'] = [];
795			}
796
797			$data['new_operation']['opcommand']['type'] = isset($data['new_operation']['opcommand']['type'])
798				? $data['new_operation']['opcommand']['type'] : ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT;
799			$data['new_operation']['opcommand']['scriptid'] = isset($data['new_operation']['opcommand']['scriptid'])
800				? $data['new_operation']['opcommand']['scriptid'] : '';
801			$data['new_operation']['opcommand']['execute_on'] = isset($data['new_operation']['opcommand']['execute_on'])
802				? $data['new_operation']['opcommand']['execute_on'] : ZBX_SCRIPT_EXECUTE_ON_AGENT;
803			$data['new_operation']['opcommand']['publickey'] = isset($data['new_operation']['opcommand']['publickey'])
804				? $data['new_operation']['opcommand']['publickey'] : '';
805			$data['new_operation']['opcommand']['privatekey'] = isset($data['new_operation']['opcommand']['privatekey'])
806				? $data['new_operation']['opcommand']['privatekey'] : '';
807			$data['new_operation']['opcommand']['authtype'] = isset($data['new_operation']['opcommand']['authtype'])
808				? $data['new_operation']['opcommand']['authtype'] : ITEM_AUTHTYPE_PASSWORD;
809			$data['new_operation']['opcommand']['username'] = isset($data['new_operation']['opcommand']['username'])
810				? $data['new_operation']['opcommand']['username'] : '';
811			$data['new_operation']['opcommand']['password'] = isset($data['new_operation']['opcommand']['password'])
812				? $data['new_operation']['opcommand']['password'] : '';
813			$data['new_operation']['opcommand']['port'] = isset($data['new_operation']['opcommand']['port'])
814				? $data['new_operation']['opcommand']['port'] : '';
815			$data['new_operation']['opcommand']['command'] = isset($data['new_operation']['opcommand']['command'])
816				? $data['new_operation']['opcommand']['command'] : '';
817
818			$data['new_operation']['opcommand']['script'] = '';
819			if (!zbx_empty($data['new_operation']['opcommand']['scriptid'])) {
820				$userScripts = API::Script()->get([
821					'output' => ['name'],
822					'scriptids' => $data['new_operation']['opcommand']['scriptid']
823				]);
824				if ($userScripts) {
825					$data['new_operation']['opcommand']['script'] = $userScripts[0]['name'];
826				}
827			}
828
829			// add participations
830			if (!isset($data['new_operation']['opcommand_grp'])) {
831				$data['new_operation']['opcommand_grp'] = [];
832			}
833			if (!isset($data['new_operation']['opcommand_hst'])) {
834				$data['new_operation']['opcommand_hst'] = [];
835			}
836
837			$hosts = API::Host()->get([
838				'hostids' => zbx_objectValues($data['new_operation']['opcommand_hst'], 'hostid'),
839				'output' => ['hostid', 'name'],
840				'preservekeys' => true,
841				'editable' => true
842			]);
843
844			$data['new_operation']['opcommand_hst'] = array_values($data['new_operation']['opcommand_hst']);
845			foreach ($data['new_operation']['opcommand_hst'] as $ohnum => $cmd) {
846				$data['new_operation']['opcommand_hst'][$ohnum]['name'] = ($cmd['hostid'] > 0) ? $hosts[$cmd['hostid']]['name'] : '';
847			}
848			order_result($data['new_operation']['opcommand_hst'], 'name');
849
850			$groups = API::HostGroup()->get([
851				'groupids' => zbx_objectValues($data['new_operation']['opcommand_grp'], 'groupid'),
852				'output' => ['groupid', 'name'],
853				'preservekeys' => true,
854				'editable' => true
855			]);
856
857			$data['new_operation']['opcommand_grp'] = array_values($data['new_operation']['opcommand_grp']);
858			foreach ($data['new_operation']['opcommand_grp'] as $ognum => $cmd) {
859				$data['new_operation']['opcommand_grp'][$ognum]['name'] = $groups[$cmd['groupid']]['name'];
860			}
861			order_result($data['new_operation']['opcommand_grp'], 'name');
862
863			// js add commands
864			$host_values = zbx_jsvalue([
865				'object' => 'hostid',
866				'values' => $data['new_operation']['opcommand_hst'],
867				'parentId' => 'opCmdListFooter'
868			]);
869
870			$js_insert = 'addPopupValues('.$host_values.');';
871
872			$group_values = zbx_jsvalue([
873				'object' => 'groupid',
874				'values' => $data['new_operation']['opcommand_grp'],
875				'parentId' => 'opCmdListFooter'
876			]);
877
878			$js_insert .= 'addPopupValues('.$group_values.');';
879			zbx_add_post_js($js_insert);
880
881			// target list
882			$new_operation_formlist->addRow(
883				(new CLabel(_('Target list'), 'opCmdList'))->setAsteriskMark(),
884				(new CDiv(
885					(new CTable())
886						->setAttribute('style', 'width: 100%;')
887						->setHeader([_('Target'), _('Action')])
888						->addRow(
889							(new CRow(
890								(new CCol(
891									(new CButton('add', _('New')))
892										->onClick('javascript: showOpCmdForm(0, '.ACTION_OPERATION.');')
893										->addClass(ZBX_STYLE_BTN_LINK)
894								))->setColSpan(3)
895							))->setId('opCmdListFooter')
896						)
897				))
898					->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
899					->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
900					->setId('opCmdList')
901			);
902
903			$userScript = [
904				new CVar('new_operation[opcommand][scriptid]', $data['new_operation']['opcommand']['scriptid']),
905				(new CTextBox('new_operation[opcommand][script]', $data['new_operation']['opcommand']['script'], true))
906					->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
907					->setAriaRequired(),
908				(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
909				(new CButton('select_operation_opcommand_script', _('Select')))->addClass(ZBX_STYLE_BTN_GREY)
910			];
911
912			$new_operation_formlist
913				// type
914				->addRow(
915					(new CLabel(_('Type'), 'new_operation[opcommand][type]')),
916					(new CComboBox('new_operation[opcommand][type]',
917						$data['new_operation']['opcommand']['type'],
918						'showOpTypeForm('.ACTION_OPERATION.')',	[
919							ZBX_SCRIPT_TYPE_IPMI => _('IPMI'),
920							ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT => _('Custom script'),
921							ZBX_SCRIPT_TYPE_SSH => _('SSH'),
922							ZBX_SCRIPT_TYPE_TELNET => _('Telnet'),
923							ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT => _('Global script')
924						]
925					))
926				)
927				->addRow(
928					(new CLabel(_('Script name'), 'new_operation_opcommand_script'))->setAsteriskMark(),
929					(new CDiv($userScript))->addClass(ZBX_STYLE_NOWRAP)
930				)
931				// script
932				->addRow(
933					(new CLabel(_('Execute on'), 'new_operation[opcommand][execute_on]')),
934					(new CRadioButtonList('new_operation[opcommand][execute_on]',
935						(int) $data['new_operation']['opcommand']['execute_on']
936					))
937						->addValue(_('Zabbix agent'), ZBX_SCRIPT_EXECUTE_ON_AGENT)
938						->addValue(_('Zabbix server (proxy)'), ZBX_SCRIPT_EXECUTE_ON_PROXY)
939						->addValue(_('Zabbix server'), ZBX_SCRIPT_EXECUTE_ON_SERVER)
940						->setModern(true)
941				)
942				// ssh
943				->addRow(_('Authentication method'),
944					new CComboBox('new_operation[opcommand][authtype]',
945						$data['new_operation']['opcommand']['authtype'],
946						'showOpTypeAuth('.ACTION_OPERATION.')', [
947							ITEM_AUTHTYPE_PASSWORD => _('Password'),
948							ITEM_AUTHTYPE_PUBLICKEY => _('Public key')
949						]
950					)
951				)
952				->addRow(
953					(new CLabel(_('User name'), 'new_operation[opcommand][username]'))->setAsteriskMark(),
954					(new CTextBox('new_operation[opcommand][username]',
955						$data['new_operation']['opcommand']['username']
956					))
957						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
958						->setAriaRequired()
959						->disableAutocomplete()
960				)
961				->addRow(
962					(new CLabel(_('Public key file'), 'new_operation[opcommand][publickey]'))->setAsteriskMark(),
963					(new CTextBox('new_operation[opcommand][publickey]',
964						$data['new_operation']['opcommand']['publickey']
965					))
966						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
967						->setAriaRequired()
968				)
969				->addRow(
970					(new CLabel(_('Private key file'), 'new_operation[opcommand][privatekey]'))->setAsteriskMark(),
971					(new CTextBox('new_operation[opcommand][privatekey]',
972						$data['new_operation']['opcommand']['privatekey']
973					))
974						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
975						->setAriaRequired()
976				)
977				->addRow(_('Password'),
978					(new CTextBox('new_operation[opcommand][password]',
979						$data['new_operation']['opcommand']['password']
980					))
981						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
982						->disableAutocomplete()
983				)
984				// set custom id because otherwise they are set based on name (sick!) and produce duplicate ids
985				->addRow(_('Key passphrase'),
986					(new CTextBox('new_operation[opcommand][password]',
987						$data['new_operation']['opcommand']['password']
988					))
989						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
990						->setId('new_operation_opcommand_passphrase')
991						->disableAutocomplete()
992				)
993				// ssh && telnet
994				->addRow(_('Port'),
995					(new CTextBox('new_operation[opcommand][port]', $data['new_operation']['opcommand']['port']))
996						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
997				)
998				// command
999				->addRow(
1000					(new CLabel(_('Commands'), 'new_operation[opcommand][command]'))->setAsteriskMark(),
1001					(new CTextArea('new_operation[opcommand][command]', $data['new_operation']['opcommand']['command']))
1002						->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1003						->setAriaRequired()
1004				)
1005				->addRow(
1006					(new CLabel(_('Commands'), 'new_operation[opcommand][command]'))->setAsteriskMark(),
1007					(new CTextBox('new_operation[opcommand][command]', $data['new_operation']['opcommand']['command']))
1008						->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1009						->setId('new_operation_opcommand_command_ipmi')
1010						->setAriaRequired()
1011				);
1012			break;
1013
1014		case OPERATION_TYPE_HOST_ADD:
1015		case OPERATION_TYPE_HOST_REMOVE:
1016		case OPERATION_TYPE_HOST_ENABLE:
1017		case OPERATION_TYPE_HOST_DISABLE:
1018			$new_operation_vars[] = new CVar('new_operation[object]', 0);
1019			$new_operation_vars[] = new CVar('new_operation[objectid]', 0);
1020			$new_operation_vars[] = new CVar('new_operation[shortdata]', '');
1021			$new_operation_vars[] = new CVar('new_operation[longdata]', '');
1022			break;
1023
1024		case OPERATION_TYPE_GROUP_ADD:
1025		case OPERATION_TYPE_GROUP_REMOVE:
1026			$new_operation_formlist->addRow(
1027				(new CLabel(_('Host groups'), 'new_operation_groupids__ms'))->setAsteriskMark(),
1028				(new CMultiSelect([
1029					'name' => 'new_operation[groupids][]',
1030					'object_name' => 'hostGroup',
1031					'data' => $data['new_operation']['groups'],
1032					'popup' => [
1033						'parameters' => [
1034							'srctbl' => 'host_groups',
1035							'srcfld1' => 'groupid',
1036							'dstfrm' => $actionForm->getName(),
1037							'dstfld1' => 'new_operation_groupids_',
1038							'editable' => true
1039						]
1040					]
1041				]))
1042					->setAriaRequired()
1043					->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1044			);
1045			break;
1046
1047		case OPERATION_TYPE_TEMPLATE_ADD:
1048		case OPERATION_TYPE_TEMPLATE_REMOVE:
1049			$new_operation_formlist->addRow(
1050				(new CLabel(_('Templates'), 'new_operation_templateids__ms'))->setAsteriskMark(),
1051				(new CMultiSelect([
1052					'name' => 'new_operation[templateids][]',
1053					'object_name' => 'templates',
1054					'data' => $data['new_operation']['templates'],
1055					'popup' => [
1056						'parameters' => [
1057							'srctbl' => 'templates',
1058							'srcfld1' => 'hostid',
1059							'srcfld2' => 'host',
1060							'dstfrm' => $actionForm->getName(),
1061							'dstfld1' => 'new_operation_templateids_',
1062							'editable' => true
1063						]
1064					]
1065				]))
1066					->setAriaRequired()
1067					->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1068			);
1069			break;
1070
1071		case OPERATION_TYPE_HOST_INVENTORY:
1072			$new_operation_formlist->addRow(
1073				(new CLabel(_('Inventory mode'), 'new_operation[opinventory][inventory_mode]')),
1074				(new CRadioButtonList('new_operation[opinventory][inventory_mode]',
1075					(int) $data['new_operation']['opinventory']['inventory_mode']
1076				))
1077					->addValue(_('Manual'), HOST_INVENTORY_MANUAL)
1078					->addValue(_('Automatic'), HOST_INVENTORY_AUTOMATIC)
1079					->setModern(true)
1080			);
1081			break;
1082	}
1083
1084	// append operation conditions to form list
1085	if ($data['eventsource'] == 0) {
1086		if (!isset($data['new_operation']['opconditions'])) {
1087			$data['new_operation']['opconditions'] = [];
1088		}
1089		else {
1090			zbx_rksort($data['new_operation']['opconditions']);
1091		}
1092
1093		$allowed_opconditions = get_opconditions_by_eventsource($data['eventsource']);
1094		$grouped_opconditions = [];
1095
1096		$operationConditionsTable = (new CTable())
1097			->setAttribute('style', 'width: 100%;')
1098			->setId('operationConditionTable')
1099			->setHeader([_('Label'), _('Name'), _('Action')]);
1100
1101		$i = 0;
1102		foreach ($data['new_operation']['opconditions'] as $cIdx => $opcondition) {
1103			if (!isset($opcondition['conditiontype'])) {
1104				$opcondition['conditiontype'] = 0;
1105			}
1106			if (!isset($opcondition['operator'])) {
1107				$opcondition['operator'] = 0;
1108			}
1109			if (!isset($opcondition['value'])) {
1110				$opcondition['value'] = 0;
1111			}
1112			if (!str_in_array($opcondition['conditiontype'], $allowed_opconditions)) {
1113				continue;
1114			}
1115
1116			$label = num2letter($i);
1117			$cond_value = $opcondition['value'] ? _('Ack') : _('Not Ack');
1118			$labelCol = (new CCol($label))
1119				->addClass('label')
1120				->setAttribute('data-conditiontype', $opcondition['conditiontype'])
1121				->setAttribute('data-formulaid', $label);
1122			$operationConditionsTable->addRow([
1123					$labelCol,
1124					getConditionDescription($opcondition['conditiontype'], $opcondition['operator'], $cond_value, ''),
1125					(new CCol([
1126						(new CButton('remove', _('Remove')))
1127							->onClick('javascript: removeOperationCondition('.$i.');')
1128							->addClass(ZBX_STYLE_BTN_LINK)
1129							->removeId(),
1130						new CVar('new_operation[opconditions]['.$i.'][conditiontype]', $opcondition['conditiontype']),
1131						new CVar('new_operation[opconditions]['.$i.'][operator]', $opcondition['operator']),
1132						new CVar('new_operation[opconditions]['.$i.'][value]', $opcondition['value'])
1133					]))->addClass(ZBX_STYLE_NOWRAP)
1134				],
1135				null, 'opconditions_'.$i
1136			);
1137
1138			$i++;
1139		}
1140
1141		$calcTypeComboBox = new CComboBox('new_operation[evaltype]', $data['new_operation']['evaltype'], 'submit()', [
1142			CONDITION_EVAL_TYPE_AND_OR => _('And/Or'),
1143			CONDITION_EVAL_TYPE_AND => _('And'),
1144			CONDITION_EVAL_TYPE_OR => _('Or')
1145		]);
1146		$calcTypeComboBox->setId('operationEvaltype');
1147
1148		$new_operation_formlist->addRow(_('Type of calculation'), [
1149			$calcTypeComboBox,
1150			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
1151			(new CSpan())->setId('operationConditionLabel')
1152		]);
1153
1154		if (!hasRequest('new_opcondition')) {
1155			$operationConditionsTable->addRow((new CCol(
1156				(new CSimpleButton(_('New')))
1157					->onClick('javascript: submitFormWithParam("'.$actionForm->getName().'", "new_opcondition", "1");')
1158					->addClass(ZBX_STYLE_BTN_LINK)
1159			))->setColspan(3));
1160		}
1161		$new_operation_formlist->addRow(_('Conditions'),
1162			(new CDiv($operationConditionsTable))
1163				->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
1164				->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
1165		);
1166	}
1167
1168	// Append new operation condition to form list.
1169	if (hasRequest('new_opcondition')) {
1170		$newOperationConditionTable = (new CTable())->setAttribute('style', 'width: 100%;');
1171
1172		$allowedOpConditions = get_opconditions_by_eventsource($data['eventsource']);
1173
1174		$new_opcondition = getRequest('new_opcondition', []);
1175		if (!is_array($new_opcondition)) {
1176			$new_opcondition = [];
1177		}
1178
1179		if (empty($new_opcondition)) {
1180			$new_opcondition['conditiontype'] = CONDITION_TYPE_EVENT_ACKNOWLEDGED;
1181			$new_opcondition['operator'] = CONDITION_OPERATOR_LIKE;
1182			$new_opcondition['value'] = 0;
1183		}
1184
1185		if (!str_in_array($new_opcondition['conditiontype'], $allowedOpConditions)) {
1186			$new_opcondition['conditiontype'] = $allowedOpConditions[0];
1187		}
1188
1189		$condition_types = [];
1190		foreach ($allowedOpConditions as $opcondition) {
1191			$condition_types[$opcondition] = condition_type2str($opcondition);
1192		}
1193
1194		$operators = [];
1195		foreach (get_operators_by_conditiontype($new_opcondition['conditiontype']) as $operation_condition) {
1196			$operators[$operation_condition] = condition_operator2str($operation_condition);
1197		}
1198
1199		$rowCondition = [
1200			new CComboBox('new_opcondition[conditiontype]', $new_opcondition['conditiontype'], 'submit()',
1201				$condition_types
1202			),
1203			(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
1204			new CComboBox('new_opcondition[operator]', null, null, $operators)
1205		];
1206		if ($new_opcondition['conditiontype'] == CONDITION_TYPE_EVENT_ACKNOWLEDGED) {
1207			$rowCondition[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
1208			$rowCondition[] = new CComboBox('new_opcondition[value]', $new_opcondition['value'], null, [
1209				0 => _('Not Ack'),
1210				1 => _('Ack')
1211			]);
1212		}
1213		$newOperationConditionTable->addRow(new CCol($rowCondition));
1214
1215		$new_operation_formlist->addRow(_('Operation condition'),
1216			(new CDiv([
1217				$newOperationConditionTable,
1218				new CHorList([
1219					(new CSimpleButton(_('Add')))
1220						->onClick('javascript: submitFormWithParam('.
1221							'"'.$actionForm->getName().'", "add_opcondition", "1"'.
1222						');')
1223						->addClass(ZBX_STYLE_BTN_LINK),
1224					(new CSimpleButton(_('Cancel')))
1225						->onClick('javascript: submitFormWithParam('.
1226							'"'.$actionForm->getName().'", "cancel_new_opcondition", "1"'.
1227						');')
1228						->addClass(ZBX_STYLE_BTN_LINK)
1229				])
1230			]))
1231				->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
1232				->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
1233		);
1234	}
1235
1236	$operation_tab->addRow(_('Operation details'),
1237		(new CDiv([
1238			$new_operation_vars,
1239			$new_operation_formlist,
1240			new CHorList([
1241				(new CSimpleButton((isset($data['new_operation']['id'])) ? _('Update') : _('Add')))
1242					->onClick('javascript: submitFormWithParam("'.$actionForm->getName().'", "add_operation", "1");')
1243					->addClass(ZBX_STYLE_BTN_LINK),
1244				(new CSimpleButton(_('Cancel')))
1245					->onClick('javascript: submitFormWithParam('.
1246						'"'.$actionForm->getName().'", "cancel_new_operation", "1"'.
1247					');')
1248					->addClass(ZBX_STYLE_BTN_LINK)
1249			])
1250		]))
1251			->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
1252			->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
1253	);
1254}
1255
1256// Append tabs to form.
1257$action_tabs = (new CTabView())
1258	->addTab('actionTab', _('Action'), $action_tab)
1259	->addTab('operationTab', _('Operations'), $operation_tab);
1260
1261$bottom_note = _('At least one operation must exist.');
1262
1263// Recovery operation tab.
1264if ($data['eventsource'] == EVENT_SOURCE_TRIGGERS || $data['eventsource'] == EVENT_SOURCE_INTERNAL) {
1265	$bottom_note = _('At least one operation or recovery operation must exist.');
1266	$recovery_tab = (new CFormList())
1267		->addRow(_('Default subject'),
1268			(new CTextBox('r_shortdata', $data['action']['r_shortdata']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1269		)
1270		->addRow(_('Default message'),
1271			(new CTextArea('r_longdata', $data['action']['r_longdata']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1272		);
1273
1274	// Create operation table.
1275	$operationsTable = (new CTable())->setAttribute('style', 'width: 100%;');
1276	$operationsTable->setHeader([_('Details'), _('Action')]);
1277
1278	if ($data['action']['recovery_operations']) {
1279		$actionOperationDescriptions = getActionOperationDescriptions([$data['action']], ACTION_RECOVERY_OPERATION);
1280
1281		$default_message = [
1282			'subject' => $data['action']['r_shortdata'],
1283			'message' => $data['action']['r_longdata']
1284		];
1285
1286		$action_operation_hints = getActionOperationHints($data['action']['recovery_operations'], $default_message);
1287
1288		foreach ($data['action']['recovery_operations'] as $operationid => $operation) {
1289			if (!str_in_array($operation['operationtype'], $data['allowedOperations'][ACTION_RECOVERY_OPERATION])) {
1290				continue;
1291			}
1292			if (!isset($operation['opconditions'])) {
1293				$operation['opconditions'] = [];
1294			}
1295			if (!isset($operation['mediatypeid'])) {
1296				$operation['mediatypeid'] = 0;
1297			}
1298
1299			$details = new CSpan($actionOperationDescriptions[0][$operationid]);
1300
1301			if (array_key_exists($operationid, $action_operation_hints) && $action_operation_hints[$operationid]) {
1302				$details->setHint($action_operation_hints[$operationid]);
1303			}
1304
1305			$operationRow = [
1306				$details,
1307				(new CCol(
1308					new CHorList([
1309						(new CSimpleButton(_('Edit')))
1310							->onClick('javascript: submitFormWithParam('.
1311								'"'.$actionForm->getName().'", "edit_recovery_operationid['.$operationid.']", "1"'.
1312							');')
1313							->addClass(ZBX_STYLE_BTN_LINK),
1314						[
1315							(new CButton('remove', _('Remove')))
1316								->onClick(
1317									'javascript: removeOperation('.$operationid.', '.ACTION_RECOVERY_OPERATION.');'
1318								)
1319								->addClass(ZBX_STYLE_BTN_LINK)
1320								->removeId(),
1321							new CVar('recovery_operations['.$operationid.']', $operation)
1322						]
1323					])
1324				))->addClass(ZBX_STYLE_NOWRAP)
1325			];
1326			$operationsTable->addRow($operationRow, null, 'recovery_operations_'.$operationid);
1327
1328			$operation['opmessage_grp'] = isset($operation['opmessage_grp'])
1329				? zbx_toHash($operation['opmessage_grp'], 'usrgrpid')
1330				: null;
1331			$operation['opmessage_usr'] = isset($operation['opmessage_usr'])
1332				? zbx_toHash($operation['opmessage_usr'], 'userid')
1333				: null;
1334			$operation['opcommand_grp'] = isset($operation['opcommand_grp'])
1335				? zbx_toHash($operation['opcommand_grp'], 'groupid')
1336				: null;
1337			$operation['opcommand_hst'] = isset($operation['opcommand_hst'])
1338				? zbx_toHash($operation['opcommand_hst'], 'hostid')
1339				: null;
1340		}
1341	}
1342
1343	$footer = null;
1344	if (empty($data['new_recovery_operation'])) {
1345		$footer = (new CSimpleButton(_('New')))
1346			->onClick('javascript: submitFormWithParam("'.$actionForm->getName().'", "new_recovery_operation", "1");')
1347			->addClass(ZBX_STYLE_BTN_LINK);
1348	}
1349
1350	$recovery_tab->addRow(_('Operations'),
1351		(new CDiv([$operationsTable, $footer]))
1352			->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
1353			->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
1354	);
1355
1356	// create new operation table
1357	if (!empty($data['new_recovery_operation'])) {
1358		$new_recovery_operation_vars = [
1359			new CVar('new_recovery_operation[actionid]', $data['actionid'])
1360		];
1361
1362		$new_operation_formlist = (new CFormList())->setAttribute('style', 'width: 100%;');
1363
1364		if (isset($data['new_recovery_operation']['id'])) {
1365			$new_recovery_operation_vars[] = new CVar('new_recovery_operation[id]',
1366				$data['new_recovery_operation']['id']
1367			);
1368		}
1369		if (isset($data['new_recovery_operation']['operationid'])) {
1370			$new_recovery_operation_vars[] = new CVar('new_recovery_operation[operationid]',
1371				$data['new_recovery_operation']['operationid']
1372			);
1373		}
1374
1375		// if only one operation is available - show only the label
1376		if (count($data['allowedOperations'][ACTION_RECOVERY_OPERATION]) == 1) {
1377			$operation = $data['allowedOperations'][ACTION_RECOVERY_OPERATION][0];
1378			$new_operation_formlist->addRow(_('Operation type'),
1379				[operation_type2str($operation), new CVar('new_recovery_operation[operationtype]', $operation)]
1380			);
1381		}
1382		// if multiple operation types are available, display a select
1383		else {
1384			$operationTypeComboBox = new CComboBox('new_recovery_operation[operationtype]',
1385				$data['new_recovery_operation']['operationtype'], 'submit()'
1386			);
1387			foreach ($data['allowedOperations'][ACTION_RECOVERY_OPERATION] as $operation) {
1388				$operationTypeComboBox->addItem($operation, operation_type2str($operation));
1389			}
1390			$new_operation_formlist->addRow((new CLabel(_('Operation type'), 'new_recovery_operation[operationtype]')),
1391				$operationTypeComboBox
1392			);
1393		}
1394
1395		switch ($data['new_recovery_operation']['operationtype']) {
1396			case OPERATION_TYPE_MESSAGE:
1397				if (!array_key_exists('opmessage', $data['new_recovery_operation'])) {
1398					$data['new_recovery_operation']['opmessage_usr'] = [];
1399					$data['new_recovery_operation']['opmessage'] = ['default_msg' => 1, 'mediatypeid' => 0];
1400
1401					if ($data['eventsource'] == EVENT_SOURCE_TRIGGERS) {
1402						$data['new_recovery_operation']['opmessage']['subject'] = ACTION_DEFAULT_SUBJ_RECOVERY;
1403						$data['new_recovery_operation']['opmessage']['message'] = ACTION_DEFAULT_MSG_RECOVERY;
1404					}
1405					else {
1406						$data['new_recovery_operation']['opmessage']['subject'] = '';
1407						$data['new_recovery_operation']['opmessage']['message'] = '';
1408					}
1409				}
1410
1411				if (!array_key_exists('default_msg', $data['new_recovery_operation']['opmessage'])) {
1412					$data['new_recovery_operation']['opmessage']['default_msg'] = 0;
1413				}
1414
1415				if (!array_key_exists('mediatypeid', $data['new_recovery_operation']['opmessage'])) {
1416					$data['new_recovery_operation']['opmessage']['mediatypeid'] = 0;
1417				}
1418
1419				$usrgrpList = (new CTable())
1420					->setAttribute('style', 'width: 100%;')
1421					->setHeader([_('User group'), _('Action')]);
1422
1423				$addUsrgrpBtn = (new CButton(null, _('Add')))
1424					->onClick('return PopUp("popup.generic",'.
1425						CJs::encodeJson([
1426							'srctbl' => 'usrgrp',
1427							'srcfld1' => 'usrgrpid',
1428							'srcfld2' => 'name',
1429							'dstfrm' => $actionForm->getName(),
1430							'dstfld1' => 'recOpmsgUsrgrpListFooter',
1431							'multiselect' => '1'
1432						]).', null, this);'
1433					)
1434					->addClass(ZBX_STYLE_BTN_LINK);
1435				$usrgrpList->addRow(
1436					(new CRow(
1437						(new CCol($addUsrgrpBtn))->setColSpan(2)
1438					))->setId('recOpmsgUsrgrpListFooter')
1439				);
1440
1441				$userList = (new CTable())
1442					->setAttribute('style', 'width: 100%;')
1443					->setHeader([_('User'), _('Action')]);
1444
1445				$addUserBtn = (new CButton(null, _('Add')))
1446					->onClick('return PopUp("popup.generic",'.
1447						CJs::encodeJson([
1448							'srctbl' => 'users',
1449							'srcfld1' => 'userid',
1450							'srcfld2' => 'fullname',
1451							'dstfrm' => $actionForm->getName(),
1452							'dstfld1' => 'recOpmsgUserListFooter',
1453							'multiselect' => '1'
1454						]).', null, this);'
1455					)
1456					->addClass(ZBX_STYLE_BTN_LINK);
1457				$userList->addRow(
1458					(new CRow(
1459						(new CCol($addUserBtn))->setColSpan(2)
1460					))->setId('recOpmsgUserListFooter')
1461				);
1462
1463				// add participations
1464				$usrgrpids = isset($data['new_recovery_operation']['opmessage_grp'])
1465					? zbx_objectValues($data['new_recovery_operation']['opmessage_grp'], 'usrgrpid')
1466					: [];
1467
1468				$userids = isset($data['new_recovery_operation']['opmessage_usr'])
1469					? zbx_objectValues($data['new_recovery_operation']['opmessage_usr'], 'userid')
1470					: [];
1471
1472				$usrgrps = API::UserGroup()->get([
1473					'usrgrpids' => $usrgrpids,
1474					'output' => ['name']
1475				]);
1476				order_result($usrgrps, 'name');
1477
1478				$users = API::User()->get([
1479					'userids' => $userids,
1480					'output' => ['userid', 'alias', 'name', 'surname']
1481				]);
1482				order_result($users, 'alias');
1483
1484				foreach ($users as &$user) {
1485					$user['id'] = $user['userid'];
1486					$user['name'] = getUserFullname($user);
1487				}
1488				unset($user);
1489
1490				$js_insert = 'addPopupValues('.zbx_jsvalue(['object' => 'usrgrpid', 'values' => $usrgrps,
1491					'parentId' => 'recOpmsgUsrgrpListFooter']).
1492				');';
1493				$js_insert .= 'addPopupValues('.zbx_jsvalue(['object' => 'userid', 'values' => $users,
1494					'parentId' => 'recOpmsgUserListFooter']).
1495				');';
1496				zbx_add_post_js($js_insert);
1497
1498				$new_operation_formlist
1499					->addRow('',
1500						(new CLabel(_('At least one user or user group must be selected.')))
1501							->setAsteriskMark()
1502					)
1503					->addRow(_('Send to User groups'),
1504						(new CDiv($usrgrpList))
1505							->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
1506							->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
1507					)
1508					->addRow(_('Send to Users'),
1509						(new CDiv($userList))
1510							->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
1511							->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
1512					);
1513
1514				$media_type_combobox = new CComboBox('new_recovery_operation[opmessage][mediatypeid]',
1515					$data['new_recovery_operation']['opmessage']['mediatypeid']
1516				);
1517				$media_type_combobox->addItem(0, '- '._('All').' -');
1518				foreach ($data['available_mediatypes'] as $value) {
1519					$media_type_combobox->addItem($value['mediatypeid'], $value['description'], null, true,
1520						($value['status'] == MEDIA_TYPE_STATUS_DISABLED) ? ZBX_STYLE_RED : null
1521					);
1522				}
1523
1524				$new_operation_formlist
1525					->addRow(_('Send only to'), $media_type_combobox)
1526					->addRow(_('Default message'),
1527						(new CCheckBox('new_recovery_operation[opmessage][default_msg]'))
1528							->setChecked($data['new_recovery_operation']['opmessage']['default_msg'] == 1)
1529					)
1530					->addRow(_('Subject'),
1531						(new CTextBox('new_recovery_operation[opmessage][subject]',
1532							$data['new_recovery_operation']['opmessage']['subject']
1533						))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1534					)
1535					->addRow(_('Message'),
1536						(new CTextArea('new_recovery_operation[opmessage][message]',
1537							$data['new_recovery_operation']['opmessage']['message']
1538						))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1539					);
1540				break;
1541
1542			case OPERATION_TYPE_COMMAND:
1543				if (!isset($data['new_recovery_operation']['opcommand'])) {
1544					$data['new_recovery_operation']['opcommand'] = [];
1545				}
1546
1547				$data['new_recovery_operation']['opcommand']['type'] = isset($data['new_recovery_operation']['opcommand']['type'])
1548					? $data['new_recovery_operation']['opcommand']['type']
1549					: ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT;
1550				$data['new_recovery_operation']['opcommand']['scriptid'] = isset($data['new_recovery_operation']['opcommand']['scriptid'])
1551					? $data['new_recovery_operation']['opcommand']['scriptid']
1552					: '';
1553				$data['new_recovery_operation']['opcommand']['execute_on'] = isset($data['new_recovery_operation']['opcommand']['execute_on'])
1554					? $data['new_recovery_operation']['opcommand']['execute_on']
1555					: ZBX_SCRIPT_EXECUTE_ON_AGENT;
1556				$data['new_recovery_operation']['opcommand']['publickey'] = isset($data['new_recovery_operation']['opcommand']['publickey'])
1557					? $data['new_recovery_operation']['opcommand']['publickey']
1558					: '';
1559				$data['new_recovery_operation']['opcommand']['privatekey'] = isset($data['new_recovery_operation']['opcommand']['privatekey'])
1560					? $data['new_recovery_operation']['opcommand']['privatekey']
1561					: '';
1562				$data['new_recovery_operation']['opcommand']['authtype'] = isset($data['new_recovery_operation']['opcommand']['authtype'])
1563					? $data['new_recovery_operation']['opcommand']['authtype']
1564					: ITEM_AUTHTYPE_PASSWORD;
1565				$data['new_recovery_operation']['opcommand']['username'] = isset($data['new_recovery_operation']['opcommand']['username'])
1566					? $data['new_recovery_operation']['opcommand']['username']
1567					: '';
1568				$data['new_recovery_operation']['opcommand']['password'] = isset($data['new_recovery_operation']['opcommand']['password'])
1569					? $data['new_recovery_operation']['opcommand']['password']
1570					: '';
1571				$data['new_recovery_operation']['opcommand']['port'] = isset($data['new_recovery_operation']['opcommand']['port'])
1572					? $data['new_recovery_operation']['opcommand']['port']
1573					: '';
1574				$data['new_recovery_operation']['opcommand']['command'] = isset($data['new_recovery_operation']['opcommand']['command'])
1575					? $data['new_recovery_operation']['opcommand']['command']
1576					: '';
1577
1578				$data['new_recovery_operation']['opcommand']['script'] = '';
1579				if (!zbx_empty($data['new_recovery_operation']['opcommand']['scriptid'])) {
1580					$userScripts = API::Script()->get([
1581						'output' => ['name'],
1582						'scriptids' => $data['new_recovery_operation']['opcommand']['scriptid']
1583					]);
1584					if ($userScripts) {
1585						$data['new_recovery_operation']['opcommand']['script'] = $userScripts[0]['name'];
1586					}
1587				}
1588
1589				// add participations
1590				if (!isset($data['new_recovery_operation']['opcommand_grp'])) {
1591					$data['new_recovery_operation']['opcommand_grp'] = [];
1592				}
1593				if (!isset($data['new_recovery_operation']['opcommand_hst'])) {
1594					$data['new_recovery_operation']['opcommand_hst'] = [];
1595				}
1596
1597				$hosts = API::Host()->get([
1598					'hostids' => zbx_objectValues($data['new_recovery_operation']['opcommand_hst'], 'hostid'),
1599					'output' => ['hostid', 'name'],
1600					'preservekeys' => true,
1601					'editable' => true
1602				]);
1603
1604				$data['new_recovery_operation']['opcommand_hst'] = array_values(
1605					$data['new_recovery_operation']['opcommand_hst']
1606				);
1607
1608				foreach ($data['new_recovery_operation']['opcommand_hst'] as $ohnum => $cmd) {
1609					$data['new_recovery_operation']['opcommand_hst'][$ohnum]['name'] = ($cmd['hostid'] > 0)
1610						? $hosts[$cmd['hostid']]['name']
1611						: '';
1612				}
1613				order_result($data['new_recovery_operation']['opcommand_hst'], 'name');
1614
1615				$groups = API::HostGroup()->get([
1616					'groupids' => zbx_objectValues($data['new_recovery_operation']['opcommand_grp'], 'groupid'),
1617					'output' => ['groupid', 'name'],
1618					'preservekeys' => true,
1619					'editable' => true
1620				]);
1621
1622				$data['new_recovery_operation']['opcommand_grp'] = array_values(
1623					$data['new_recovery_operation']['opcommand_grp']
1624				);
1625
1626				foreach ($data['new_recovery_operation']['opcommand_grp'] as $ognum => $cmd) {
1627					$data['new_recovery_operation']['opcommand_grp'][$ognum]['name'] = $groups[$cmd['groupid']]['name'];
1628				}
1629				order_result($data['new_recovery_operation']['opcommand_grp'], 'name');
1630
1631				// js add commands
1632				$host_values = zbx_jsvalue([
1633					'object' => 'hostid',
1634					'values' => $data['new_recovery_operation']['opcommand_hst'],
1635					'parentId' => 'recOpCmdListFooter'
1636				]);
1637
1638				$js_insert = 'addPopupValues('.$host_values.');';
1639
1640				$group_values = zbx_jsvalue([
1641					'object' => 'groupid',
1642					'values' => $data['new_recovery_operation']['opcommand_grp'],
1643					'parentId' => 'recOpCmdListFooter'
1644				]);
1645
1646				$js_insert .= 'addPopupValues('.$group_values.');';
1647				zbx_add_post_js($js_insert);
1648
1649				// target list
1650				$new_operation_formlist->addRow(
1651					(new CLabel(_('Target list'), 'recOpCmdList'))->setAsteriskMark(),
1652					(new CDiv(
1653						(new CTable())
1654							->setAttribute('style', 'width: 100%;')
1655							->setHeader([_('Target'), _('Action')])
1656							->addRow(
1657								(new CRow(
1658									(new CCol(
1659										(new CButton('add', _('New')))
1660											->onClick('javascript: showOpCmdForm(0, '.ACTION_RECOVERY_OPERATION.');')
1661											->addClass(ZBX_STYLE_BTN_LINK)
1662									))->setColSpan(3)
1663								))->setId('recOpCmdListFooter')
1664							)
1665					))
1666						->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
1667						->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
1668						->setId('recOpCmdList')
1669				);
1670
1671				// type
1672				$typeComboBox = (new CComboBox('new_recovery_operation[opcommand][type]',
1673					$data['new_recovery_operation']['opcommand']['type'],
1674					'showOpTypeForm('.ACTION_RECOVERY_OPERATION.')', [
1675						ZBX_SCRIPT_TYPE_IPMI => _('IPMI'),
1676						ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT => _('Custom script'),
1677						ZBX_SCRIPT_TYPE_SSH => _('SSH'),
1678						ZBX_SCRIPT_TYPE_TELNET => _('Telnet'),
1679						ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT => _('Global script')
1680					]
1681				));
1682
1683				$userScript = [
1684					new CVar('new_recovery_operation[opcommand][scriptid]',
1685						$data['new_recovery_operation']['opcommand']['scriptid']
1686					),
1687					(new CTextBox('new_recovery_operation[opcommand][script]',
1688						$data['new_recovery_operation']['opcommand']['script'], true
1689					))
1690						->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1691						->setAriaRequired(),
1692					(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
1693					(new CButton('select_recovery_operation_opcommand_script', _('Select')))
1694						->addClass(ZBX_STYLE_BTN_GREY)
1695				];
1696
1697				$new_operation_formlist->addRow((new CLabel(_('Type'), 'new_recovery_operation[opcommand][type]')),
1698					$typeComboBox
1699				);
1700				$new_operation_formlist->addRow(
1701					(new CLabel(_('Script name'), 'new_recovery_operation[opcommand][script]'))->setAsteriskMark(),
1702					(new CDiv($userScript))->addClass(ZBX_STYLE_NOWRAP)
1703				);
1704
1705				// script
1706				$new_operation_formlist->addRow(
1707					(new CLabel(_('Execute on'), 'new_recovery_operation[opcommand][execute_on]')),
1708					(new CRadioButtonList('new_recovery_operation[opcommand][execute_on]',
1709						(int) $data['new_recovery_operation']['opcommand']['execute_on']
1710					))
1711						->addValue(_('Zabbix agent'), ZBX_SCRIPT_EXECUTE_ON_AGENT)
1712						->addValue(_('Zabbix server (proxy)'), ZBX_SCRIPT_EXECUTE_ON_PROXY)
1713						->addValue(_('Zabbix server'), ZBX_SCRIPT_EXECUTE_ON_SERVER)
1714						->setModern(true)
1715				);
1716
1717				// ssh
1718				$authTypeComboBox = new CComboBox('new_recovery_operation[opcommand][authtype]',
1719					$data['new_recovery_operation']['opcommand']['authtype'],
1720					'showOpTypeAuth('.ACTION_RECOVERY_OPERATION.')', [
1721						ITEM_AUTHTYPE_PASSWORD => _('Password'),
1722						ITEM_AUTHTYPE_PUBLICKEY => _('Public key')
1723					]
1724				);
1725
1726				$new_operation_formlist->addRow(_('Authentication method'), $authTypeComboBox);
1727				$new_operation_formlist->addRow(
1728					(new CLabel(_('User name'), 'new_recovery_operation[opcommand][username]'))->setAsteriskMark(),
1729					(new CTextBox('new_recovery_operation[opcommand][username]',
1730						$data['new_recovery_operation']['opcommand']['username']
1731					))
1732						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
1733						->setAriaRequired()
1734						->disableAutocomplete()
1735				);
1736				$new_operation_formlist->addRow(
1737					(new CLabel(_('Public key file'), 'new_recovery_operation[opcommand][publickey]'))
1738						->setAsteriskMark(),
1739					(new CTextBox('new_recovery_operation[opcommand][publickey]',
1740						$data['new_recovery_operation']['opcommand']['publickey']
1741					))
1742						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
1743						->setAriaRequired()
1744				);
1745				$new_operation_formlist->addRow(
1746					(new CLabel(_('Private key file'), 'new_recovery_operation[opcommand][privatekey]'))
1747						->setAsteriskMark(),
1748					(new CTextBox('new_recovery_operation[opcommand][privatekey]',
1749						$data['new_recovery_operation']['opcommand']['privatekey']
1750					))
1751						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
1752						->setAriaRequired()
1753				);
1754				$new_operation_formlist->addRow(_('Password'),
1755					(new CTextBox('new_recovery_operation[opcommand][password]',
1756						$data['new_recovery_operation']['opcommand']['password']
1757					))
1758						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
1759						->disableAutocomplete()
1760				);
1761
1762				// set custom id because otherwise they are set based on name (sick!) and produce duplicate ids
1763				$passphraseCB = (new CTextBox('new_recovery_operation[opcommand][password]',
1764					$data['new_recovery_operation']['opcommand']['password']
1765				))
1766					->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
1767					->setId('new_recovery_operation_opcommand_passphrase')
1768					->disableAutocomplete();
1769				$new_operation_formlist->addRow(_('Key passphrase'), $passphraseCB);
1770
1771				// ssh && telnet
1772				$new_operation_formlist->addRow(_('Port'),
1773					(new CTextBox('new_recovery_operation[opcommand][port]',
1774						$data['new_recovery_operation']['opcommand']['port']
1775					))->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
1776				);
1777
1778				// command
1779				$new_operation_formlist->addRow(
1780					(new CLabel(_('Commands'), 'new_recovery_operation[opcommand][command]'))->setAsteriskMark(),
1781					(new CTextArea('new_recovery_operation[opcommand][command]',
1782						$data['new_recovery_operation']['opcommand']['command']
1783					))
1784						->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1785						->setAriaRequired()
1786				);
1787				$new_operation_formlist->addRow(
1788					(new CLabel(_('Commands'), 'new_recovery_operation_opcommand_command_ipmi'))->setAsteriskMark(),
1789					(new CTextBox('new_recovery_operation[opcommand][command]',
1790						$data['new_recovery_operation']['opcommand']['command']
1791					))
1792						->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1793						->setId('new_recovery_operation_opcommand_command_ipmi')
1794						->setAriaRequired()
1795				);
1796				break;
1797
1798			case OPERATION_TYPE_RECOVERY_MESSAGE:
1799				if (!array_key_exists('opmessage', $data['new_recovery_operation'])) {
1800					$data['new_recovery_operation']['opmessage_usr'] = [];
1801					$data['new_recovery_operation']['opmessage'] = ['default_msg' => 1];
1802
1803					if ($data['eventsource'] == EVENT_SOURCE_TRIGGERS) {
1804						$data['new_recovery_operation']['opmessage']['subject'] = ACTION_DEFAULT_SUBJ_RECOVERY;
1805						$data['new_recovery_operation']['opmessage']['message'] = ACTION_DEFAULT_MSG_RECOVERY;
1806					}
1807					else {
1808						$data['new_recovery_operation']['opmessage']['subject'] = '';
1809						$data['new_recovery_operation']['opmessage']['message'] = '';
1810					}
1811				}
1812
1813				if (!array_key_exists('default_msg', $data['new_recovery_operation']['opmessage'])) {
1814					$data['new_recovery_operation']['opmessage']['default_msg'] = 0;
1815				}
1816
1817				$new_operation_formlist
1818					->addRow(_('Default message'),
1819						(new CCheckBox('new_recovery_operation[opmessage][default_msg]'))
1820							->setChecked($data['new_recovery_operation']['opmessage']['default_msg'] == 1)
1821					)
1822					->addRow(_('Subject'),
1823						(new CTextBox('new_recovery_operation[opmessage][subject]',
1824								$data['new_recovery_operation']['opmessage']['subject']
1825						))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1826					)
1827					->addRow(_('Message'),
1828						(new CTextArea('new_recovery_operation[opmessage][message]',
1829							$data['new_recovery_operation']['opmessage']['message']
1830						))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1831					);
1832				break;
1833		}
1834
1835		$recovery_tab->addRow(_('Operation details'),
1836			(new CDiv([
1837				$new_recovery_operation_vars,
1838				$new_operation_formlist,
1839				new CHorList([
1840					(new CSimpleButton((isset($data['new_recovery_operation']['id'])) ? _('Update') : _('Add')))
1841						->onClick('javascript: submitFormWithParam('.
1842							'"'.$actionForm->getName().'", "add_recovery_operation", "1"'.
1843						');')
1844						->addClass(ZBX_STYLE_BTN_LINK),
1845					(new CSimpleButton(_('Cancel')))
1846						->onClick('javascript: submitFormWithParam('.
1847							'"'.$actionForm->getName().'", "cancel_new_recovery_operation", "1"'.
1848						');')
1849						->addClass(ZBX_STYLE_BTN_LINK)
1850				])
1851			]))
1852				->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
1853				->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
1854		);
1855	}
1856
1857	$action_tabs->addTab('recoveryOperationTab', _('Recovery operations'), $recovery_tab);
1858}
1859
1860// Acknowledge operations
1861if ($data['eventsource'] == EVENT_SOURCE_TRIGGERS) {
1862	$bottom_note = _('At least one operation, recovery operation or update operation must exist.');
1863	$action_formname = $actionForm->getName();
1864
1865	$acknowledge_tab = (new CFormList())
1866		->addRow(_('Default subject'),
1867			(new CTextBox('ack_shortdata', $data['action']['ack_shortdata']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1868		)
1869		->addRow(_('Default message'),
1870			(new CTextArea('ack_longdata', $data['action']['ack_longdata']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
1871		);
1872
1873	$operations_table = (new CTable())->setAttribute('style', 'width: 100%;');
1874	$operations_table->setHeader([_('Details'), _('Action')]);
1875
1876	if ($data['action']['ack_operations']) {
1877		$operation_descriptions = getActionOperationDescriptions([$data['action']], ACTION_ACKNOWLEDGE_OPERATION);
1878
1879		$default_message = [
1880			'subject' => $data['action']['ack_shortdata'],
1881			'message' => $data['action']['ack_longdata']
1882		];
1883
1884		$operation_hints = getActionOperationHints($data['action']['ack_operations'], $default_message);
1885
1886		foreach ($data['action']['ack_operations'] as $operationid => $operation) {
1887			if (!str_in_array($operation['operationtype'], $data['allowedOperations'][ACTION_ACKNOWLEDGE_OPERATION])) {
1888				continue;
1889			}
1890			$operation += [
1891				'opconditions'	=> [],
1892				'mediatypeid'	=> 0
1893			];
1894
1895			$details = new CSpan($operation_descriptions[0][$operationid]);
1896
1897			if (array_key_exists($operationid, $operation_hints) && $operation_hints[$operationid]) {
1898				$details->setHint($operation_hints[$operationid]);
1899			}
1900
1901			$operations_table->addRow([
1902				$details,
1903				(new CCol(
1904					new CHorList([
1905						(new CSimpleButton(_('Edit')))
1906							->onClick('javascript: submitFormWithParam('.
1907								'"'.$action_formname.'", "edit_ack_operationid['.$operationid.']", "1");'
1908							)
1909							->addClass(ZBX_STYLE_BTN_LINK),
1910						[
1911							(new CButton('remove', _('Remove')))
1912								->onClick('javascript: removeOperation('.$operationid.', '.ACTION_ACKNOWLEDGE_OPERATION.
1913									');'
1914								)
1915								->addClass(ZBX_STYLE_BTN_LINK)
1916								->removeId(),
1917							new CVar('ack_operations['.$operationid.']', $operation)
1918						]
1919					])
1920				))->addClass(ZBX_STYLE_NOWRAP)
1921			], null, 'ack_operations_'.$operationid);
1922
1923			$convert_to_hash = [
1924				'opmessage_grp' => 'usrgrpid',
1925				'opmessage_usr' => 'userid',
1926				'opcommand_grp' => 'groupid',
1927				'opcommand_hst' => 'hostid'
1928			];
1929
1930			foreach ($convert_to_hash as $operation_key => $hash_key) {
1931				$operation[$operation_key] = array_key_exists($operation_key, $operation)
1932					? zbx_toHash($operation[$operation_key], $hash_key)
1933					: null;
1934			}
1935		}
1936	}
1937
1938	if ($data['new_ack_operation']) {
1939		$new_operation_formlist = (new CFormList())->addStyle('width: 100%;');
1940		$new_ack_operation_vars = [];
1941
1942		foreach (['id', 'operationid', 'actionid'] as $field) {
1943			if (array_key_exists($field, $data['new_ack_operation'])) {
1944				$new_ack_operation_vars[] = new CVar('new_ack_operation['.$field.']',
1945					$data['new_ack_operation'][$field]
1946				);
1947			}
1948		}
1949
1950		$operationtype = new CComboBox('new_ack_operation[operationtype]', $data['new_ack_operation']['operationtype'],
1951			'submit()'
1952		);
1953
1954		foreach ($data['allowedOperations'][ACTION_ACKNOWLEDGE_OPERATION] as $operation) {
1955			$operationtype->addItem($operation, operation_type2str($operation));
1956		}
1957
1958		$new_operation_formlist->addRow((new CLabel(_('Operation type'), 'new_ack_operation[operationtype]')),
1959			$operationtype
1960		);
1961
1962		$usrgrp_list = null;
1963		$user_list = null;
1964
1965		if ($data['new_ack_operation']['operationtype'] == OPERATION_TYPE_MESSAGE) {
1966			$usrgrp_list = (new CTable())
1967				->addStyle('width: 100%;')
1968				->setHeader([_('User group'), _('Action')])
1969				->addRow(
1970					(new CRow(
1971						(new CCol(
1972							(new CButton(null, _('Add')))
1973								->onClick('return PopUp("popup.generic",'.
1974									CJs::encodeJson([
1975										'srctbl' => 'usrgrp',
1976										'srcfld1' => 'usrgrpid',
1977										'srcfld2' => 'name',
1978										'dstfrm' => $actionForm->getName(),
1979										'dstfld1' => 'ackOpmsgUsrgrpListFooter',
1980										'multiselect' => '1'
1981									]).', null, this);'
1982								)
1983								->addClass(ZBX_STYLE_BTN_LINK)
1984						))->setColSpan(2)
1985					))->setId('ackOpmsgUsrgrpListFooter')
1986				);
1987
1988			$user_list = (new CTable())
1989				->addStyle('width: 100%;')
1990				->setHeader([_('User'), _('Action')])
1991				->addRow(
1992					(new CRow(
1993						(new CCol(
1994							(new CButton(null, _('Add')))
1995								->onClick('return PopUp("popup.generic",'.
1996									CJs::encodeJson([
1997										'srctbl' => 'users',
1998										'srcfld1' => 'userid',
1999										'srcfld2' => 'fullname',
2000										'dstfrm' => $actionForm->getName(),
2001										'dstfld1' => 'ackOpmsgUserListFooter',
2002										'multiselect' => '1'
2003									]).', null, this);'
2004								)
2005								->addClass(ZBX_STYLE_BTN_LINK)
2006						))->setColSpan(2)
2007					))->setId('ackOpmsgUserListFooter')
2008				);
2009
2010			$usrgrpids = array_key_exists('opmessage_grp', $data['new_ack_operation'])
2011				? zbx_objectValues($data['new_ack_operation']['opmessage_grp'], 'usrgrpid')
2012				: [];
2013
2014			$userids = array_key_exists('opmessage_usr', $data['new_ack_operation'])
2015				? zbx_objectValues($data['new_ack_operation']['opmessage_usr'], 'userid')
2016				: [];
2017
2018			$usrgrps = API::UserGroup()->get([
2019				'output' => ['name'],
2020				'usrgrpids' => $usrgrpids
2021			]);
2022			order_result($usrgrps, 'name');
2023
2024			$users = API::User()->get([
2025				'output' => ['userid', 'alias', 'name', 'surname'],
2026				'userids' => $userids
2027			]);
2028			order_result($users, 'alias');
2029
2030			foreach ($users as &$user) {
2031				$user['id'] = $user['userid'];
2032				$user['name'] = getUserFullname($user);
2033			}
2034			unset($user);
2035
2036			$js_insert = 'addPopupValues('.zbx_jsvalue(['object' => 'usrgrpid', 'values' => $usrgrps,
2037				'parentId' => 'ackOpmsgUsrgrpListFooter']).
2038			');';
2039			$js_insert .= 'addPopupValues('.zbx_jsvalue(['object' => 'userid', 'values' => $users,
2040				'parentId' => 'ackOpmsgUserListFooter']).
2041			');';
2042			zbx_add_post_js($js_insert);
2043		}
2044		elseif ($data['new_ack_operation']['operationtype'] == OPERATION_TYPE_COMMAND) {
2045			if (!array_key_exists('opcommand', $data['new_ack_operation'])) {
2046				$data['new_ack_operation']['opcommand'] = [];
2047			}
2048
2049			$data['new_ack_operation'] += [
2050				'opcommand_grp'	=> [],
2051				'opcommand_hst' => []
2052			];
2053			$data['new_ack_operation']['opcommand'] += [
2054				'type'			=> ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT,
2055				'scriptid'		=> '',
2056				'execute_on'	=> ZBX_SCRIPT_EXECUTE_ON_AGENT,
2057				'publickey'		=> '',
2058				'privatekey'	=> '',
2059				'authtype'		=> ITEM_AUTHTYPE_PASSWORD,
2060				'username'		=> '',
2061				'password'		=> '',
2062				'port'			=> '',
2063				'command'		=> ''
2064			];
2065			$script_name = '';
2066
2067			if ($data['new_ack_operation']['opcommand']['scriptid']) {
2068				$user_scripts = API::Script()->get([
2069					'output' => ['name'],
2070					'scriptids' => $data['new_ack_operation']['opcommand']['scriptid']
2071				]);
2072
2073				if ($user_scripts) {
2074					$script_name = $user_scripts[0]['name'];
2075				}
2076			}
2077			$data['new_ack_operation']['opcommand']['script'] = $script_name;
2078
2079			$hosts = API::Host()->get([
2080				'output' => ['hostid', 'name'],
2081				'hostids' => zbx_objectValues($data['new_ack_operation']['opcommand_hst'], 'hostid'),
2082				'preservekeys' => true,
2083				'editable' => true
2084			]);
2085
2086			$data['new_ack_operation']['opcommand_hst'] = array_values($data['new_ack_operation']['opcommand_hst']);
2087
2088			foreach ($data['new_ack_operation']['opcommand_hst'] as $ohnum => $cmd) {
2089				$data['new_ack_operation']['opcommand_hst'][$ohnum]['name'] = ($cmd['hostid'] > 0)
2090					? $hosts[$cmd['hostid']]['name']
2091					: '';
2092			}
2093			order_result($data['new_ack_operation']['opcommand_hst'], 'name');
2094
2095			$groups = API::HostGroup()->get([
2096				'output' => ['groupid', 'name'],
2097				'groupids' => zbx_objectValues($data['new_ack_operation']['opcommand_grp'], 'groupid'),
2098				'preservekeys' => true,
2099				'editable' => true
2100			]);
2101
2102			$data['new_ack_operation']['opcommand_grp'] = array_values(
2103				$data['new_ack_operation']['opcommand_grp']
2104			);
2105
2106			foreach ($data['new_ack_operation']['opcommand_grp'] as $ognum => $cmd) {
2107				$data['new_ack_operation']['opcommand_grp'][$ognum]['name'] = $groups[$cmd['groupid']]['name'];
2108			}
2109			order_result($data['new_ack_operation']['opcommand_grp'], 'name');
2110
2111			// js add commands
2112			$host_values = zbx_jsvalue([
2113				'object' => 'hostid',
2114				'values' => $data['new_ack_operation']['opcommand_hst'],
2115				'parentId' => 'ackOpCmdListFooter'
2116			]);
2117
2118			$js_insert = 'addPopupValues('.$host_values.');';
2119
2120			$group_values = zbx_jsvalue([
2121				'object' => 'groupid',
2122				'values' => $data['new_ack_operation']['opcommand_grp'],
2123				'parentId' => 'ackOpCmdListFooter'
2124			]);
2125
2126			$js_insert .= 'addPopupValues('.$group_values.');';
2127			zbx_add_post_js($js_insert);
2128
2129			$new_operation_formlist->addRow(
2130					(new CLabel(_('Target list'), 'ackOpCmdList'))->setAsteriskMark(),
2131					(new CDiv(
2132						(new CTable())
2133							->addStyle('width: 100%;')
2134							->setHeader([_('Target'), _('Action')])
2135							->addRow(
2136								(new CRow(
2137									(new CCol(
2138										(new CButton('add', _('New')))
2139											->onClick('javascript: showOpCmdForm(0, '.ACTION_ACKNOWLEDGE_OPERATION.');')
2140											->addClass(ZBX_STYLE_BTN_LINK)
2141									))->setColSpan(3)
2142								))->setId('ackOpCmdListFooter')
2143							)
2144					))
2145					->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
2146					->addStyle('min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
2147					->setId('ackOpCmdList')
2148				)
2149				->addRow(
2150					(new CLabel(_('Type'), 'new_ack_operation[opcommand][type]')),
2151					(new CComboBox('new_ack_operation[opcommand][type]',
2152						$data['new_ack_operation']['opcommand']['type'],
2153						'showOpTypeForm('.ACTION_ACKNOWLEDGE_OPERATION.')', [
2154							ZBX_SCRIPT_TYPE_IPMI => _('IPMI'),
2155							ZBX_SCRIPT_TYPE_CUSTOM_SCRIPT => _('Custom script'),
2156							ZBX_SCRIPT_TYPE_SSH => _('SSH'),
2157							ZBX_SCRIPT_TYPE_TELNET => _('Telnet'),
2158							ZBX_SCRIPT_TYPE_GLOBAL_SCRIPT => _('Global script')
2159					]))
2160				)
2161				->addRow(
2162					(new CLabel(_('Script name'), 'new_ack_operation[opcommand][script]'))->setAsteriskMark(),
2163					(new CDiv([
2164						new CVar('new_ack_operation[opcommand][scriptid]',
2165							$data['new_ack_operation']['opcommand']['scriptid']
2166						),
2167						(new CTextBox('new_ack_operation[opcommand][script]',
2168							$data['new_ack_operation']['opcommand']['script'], true
2169						))
2170							->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
2171							->setAriaRequired(),
2172						(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
2173						(new CButton('select_ack_operation_opcommand_script', _('Select')))
2174							->addClass(ZBX_STYLE_BTN_GREY)
2175					]))->addClass(ZBX_STYLE_NOWRAP)
2176				)
2177				->addRow(
2178					(new CLabel(_('Execute on'), 'new_ack_operation[opcommand][execute_on]')),
2179					(new CRadioButtonList('new_ack_operation[opcommand][execute_on]',
2180						(int) $data['new_ack_operation']['opcommand']['execute_on']
2181					))
2182						->addValue(_('Zabbix agent'), ZBX_SCRIPT_EXECUTE_ON_AGENT)
2183						->addValue(_('Zabbix server (proxy)'), ZBX_SCRIPT_EXECUTE_ON_PROXY)
2184						->addValue(_('Zabbix server'), ZBX_SCRIPT_EXECUTE_ON_SERVER)
2185						->setModern(true)
2186				)
2187				->addRow(_('Authentication method'),
2188					new CComboBox('new_ack_operation[opcommand][authtype]',
2189						$data['new_ack_operation']['opcommand']['authtype'],
2190						'showOpTypeAuth('.ACTION_ACKNOWLEDGE_OPERATION.')', [
2191							ITEM_AUTHTYPE_PASSWORD => _('Password'),
2192							ITEM_AUTHTYPE_PUBLICKEY => _('Public key')
2193					])
2194				)
2195				->addRow((new CLabel(_('User name'), 'new_ack_operation[opcommand][username]'))->setAsteriskMark(),
2196					(new CTextBox('new_ack_operation[opcommand][username]',
2197						$data['new_ack_operation']['opcommand']['username']
2198					))
2199						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
2200						->setAriaRequired()
2201						->disableAutocomplete()
2202				)
2203				->addRow(
2204					(new CLabel(_('Public key file'), 'new_ack_operation[opcommand][publickey]'))->setAsteriskMark(),
2205					(new CTextBox('new_ack_operation[opcommand][publickey]',
2206						$data['new_ack_operation']['opcommand']['publickey']
2207					))
2208						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
2209						->setAriaRequired()
2210				)
2211				->addRow(
2212					(new CLabel(_('Private key file'), 'new_ack_operation[opcommand][privatekey]'))->setAsteriskMark(),
2213					(new CTextBox('new_ack_operation[opcommand][privatekey]',
2214						$data['new_ack_operation']['opcommand']['privatekey']
2215					))
2216						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
2217						->setAriaRequired()
2218				)
2219				->addRow(_('Password'),
2220					(new CTextBox('new_ack_operation[opcommand][password]',
2221						$data['new_ack_operation']['opcommand']['password']
2222					))
2223						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
2224						->disableAutocomplete()
2225				)
2226				->addRow(_('Key passphrase'),
2227					(new CTextBox('new_ack_operation[opcommand][password]',
2228						$data['new_ack_operation']['opcommand']['password']
2229					))
2230						->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
2231						->setId('new_ack_operation_opcommand_passphrase')
2232						->disableAutocomplete()
2233				)
2234				->addRow(_('Port'),
2235					(new CTextBox('new_ack_operation[opcommand][port]',
2236						$data['new_ack_operation']['opcommand']['port']
2237					))->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
2238				)
2239				->addRow(
2240					(new CLabel(_('Commands'), 'new_ack_operation[opcommand][command]'))->setAsteriskMark(),
2241					(new CTextArea('new_ack_operation[opcommand][command]',
2242						$data['new_ack_operation']['opcommand']['command']
2243					))
2244						->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
2245						->setAriaRequired()
2246				)
2247				->addRow(
2248					(new CLabel(_('Commands'), 'new_ack_operation[opcommand][command]'))->setAsteriskMark(),
2249					(new CTextBox('new_ack_operation[opcommand][command]',
2250						$data['new_ack_operation']['opcommand']['command']
2251					))
2252						->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
2253						->setId('new_ack_operation_opcommand_command_ipmi')
2254						->setAriaRequired()
2255				);
2256		}
2257
2258		if ($usrgrp_list || $user_list) {
2259			$new_operation_formlist->addRow('',
2260				(new CLabel(_('At least one user or user group must be selected.')))
2261					->setAsteriskMark()
2262			);
2263		}
2264
2265		if ($usrgrp_list) {
2266			$new_operation_formlist->addRow(_('Send to User groups'),
2267				(new CDiv($usrgrp_list))
2268					->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
2269					->addStyle('min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
2270			);
2271		}
2272
2273		if ($user_list) {
2274			$new_operation_formlist->addRow(_('Send to Users'),
2275				(new CDiv($user_list))
2276					->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
2277					->addStyle('min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
2278			);
2279		}
2280
2281		if (array_key_exists('opmessage', $data['new_ack_operation'])
2282				&& $data['new_ack_operation']['operationtype'] != OPERATION_TYPE_COMMAND) {
2283			$media_type_combobox = new CComboBox('new_ack_operation[opmessage][mediatypeid]',
2284				$data['new_ack_operation']['opmessage']['mediatypeid']
2285			);
2286			$media_type_combobox->addItem(0, '- '._('All').' -');
2287			foreach ($data['available_mediatypes'] as $value) {
2288				$media_type_combobox->addItem($value['mediatypeid'], $value['description'], null, true,
2289					($value['status'] == MEDIA_TYPE_STATUS_DISABLED) ? ZBX_STYLE_RED : null
2290				);
2291			}
2292
2293			$label = ($data['new_ack_operation']['operationtype'] == OPERATION_TYPE_ACK_MESSAGE)
2294				? _('Default media type')
2295				: _('Send only to');
2296
2297			$new_operation_formlist->addRow($label, $media_type_combobox);
2298
2299			$is_default_msg = (array_key_exists('default_msg', $data['new_ack_operation']['opmessage'])
2300				&& $data['new_ack_operation']['opmessage']['default_msg'] == 1);
2301
2302			$new_operation_formlist
2303				->addRow(_('Default message'),
2304					(new CCheckBox('new_ack_operation[opmessage][default_msg]'))
2305						->setChecked($is_default_msg)
2306				)
2307				->addRow(_('Subject'),
2308					(new CTextBox('new_ack_operation[opmessage][subject]',
2309						$data['new_ack_operation']['opmessage']['subject']
2310					))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
2311				)
2312				->addRow(_('Message'),
2313					(new CTextArea('new_ack_operation[opmessage][message]',
2314						$data['new_ack_operation']['opmessage']['message']
2315					))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
2316				);
2317		}
2318
2319		$acknowledge_tab->addRow(_('Operations'),
2320			(new CDiv([$new_ack_operation_vars, $operations_table]))
2321				->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
2322				->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
2323		);
2324
2325		$acknowledge_tab->addRow(_('Operation details'),
2326			(new CDiv([$new_operation_formlist,
2327				new CHorList([
2328					(new CSimpleButton(array_key_exists('id', $data['new_ack_operation']) ? _('Update') : _('Add')))
2329						->onClick('javascript: submitFormWithParam("'.$action_formname.'", "add_ack_operation", "1");')
2330						->addClass(ZBX_STYLE_BTN_LINK),
2331					(new CSimpleButton(_('Cancel')))
2332						->onClick('javascript: submitFormWithParam("'.$action_formname.'", "cancel_new_ack_operation", "1");')
2333						->addClass(ZBX_STYLE_BTN_LINK)
2334				])
2335			]))
2336				->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
2337				->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
2338		);
2339	}
2340	else {
2341		$acknowledge_tab->addRow(_('Operations'),
2342			(new CDiv([$operations_table,
2343				(new CSimpleButton(_('New')))
2344					->onClick('javascript: submitFormWithParam("'.$action_formname.'", "new_ack_operation", "1");')
2345					->addClass(ZBX_STYLE_BTN_LINK)
2346			]))
2347				->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
2348				->addStyle('min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
2349		);
2350	}
2351
2352	$action_tabs->addTab('acknowledgeTab', _('Update operations'), $acknowledge_tab);
2353}
2354
2355if (!hasRequest('form_refresh')) {
2356	$action_tabs->setSelected(0);
2357}
2358
2359// Append buttons to form.
2360$others = [];
2361if ($data['actionid']) {
2362	$form_buttons = [
2363		new CSubmit('update', _('Update')), [
2364			new CButton('clone', _('Clone')),
2365			new CButtonDelete(
2366				_('Delete current action?'),
2367				url_param('form').url_param('eventsource').url_param('actionid')
2368			),
2369			new CButtonCancel(url_param('actiontype'))
2370		]
2371	];
2372}
2373else {
2374	$form_buttons = [
2375		new CSubmit('add', _('Add')),
2376		[new CButtonCancel(url_param('actiontype'))]
2377	];
2378}
2379
2380$action_tabs->setFooter([
2381	(new CList())
2382		->addClass(ZBX_STYLE_TABLE_FORMS)
2383		->addItem([
2384			new CDiv(''),
2385			(new CDiv((new CLabel($bottom_note))->setAsteriskMark()))
2386				->addClass(ZBX_STYLE_TABLE_FORMS_TD_RIGHT)
2387		]),
2388	makeFormFooter($form_buttons[0], $form_buttons[1])
2389]);
2390$actionForm->addItem($action_tabs);
2391
2392// Append form to widget.
2393$widget->addItem($actionForm);
2394
2395return $widget;
2396