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.triggers.edit.js.php';
23
24$widget = (new CWidget())->setTitle(_('Triggers'));
25
26// append host summary to widget header
27if (!empty($data['hostid'])) {
28	$widget->addItem(get_header_host_table('triggers', $data['hostid']));
29}
30
31// Create form.
32$triggersForm = (new CForm())
33	->setName('triggersForm')
34	->setAttribute('aria-labeledby', ZBX_STYLE_PAGE_TITLE)
35	->addVar('form', $data['form'])
36	->addVar('hostid', $data['hostid'])
37	->addVar('expression_constructor', $data['expression_constructor'])
38	->addVar('recovery_expression_constructor', $data['recovery_expression_constructor'])
39	->addVar('toggle_expression_constructor', '')
40	->addVar('toggle_recovery_expression_constructor', '')
41	->addVar('remove_expression', '')
42	->addVar('remove_recovery_expression', '');
43
44$discovered_trigger = false;
45
46if ($data['triggerid'] !== null) {
47	$triggersForm->addVar('triggerid', $data['triggerid']);
48
49	if ($data['flags'] == ZBX_FLAG_DISCOVERY_CREATED) {
50		$discovered_trigger = true;
51	}
52}
53
54$readonly = ($data['limited'] || $discovered_trigger);
55
56if ($readonly) {
57	$triggersForm
58		->addVar('recovery_mode', $data['recovery_mode'])
59		->addVar('type', $data['type'])
60		->addVar('correlation_mode', $data['correlation_mode'])
61		->addVar('manual_close', $data['manual_close']);
62}
63
64// Create form list.
65$triggersFormList = new CFormList('triggersFormList');
66if (!empty($data['templates'])) {
67	$triggersFormList->addRow(_('Parent triggers'), $data['templates']);
68}
69
70if ($discovered_trigger) {
71	$triggersFormList->addRow(_('Discovered by'), new CLink($data['discoveryRule']['name'],
72		'trigger_prototypes.php?parent_discoveryid='.$data['discoveryRule']['itemid']
73	));
74}
75
76$triggersFormList->addRow(
77	(new CLabel(_('Name'), 'description'))->setAsteriskMark(),
78	(new CTextBox('description', $data['description'], $readonly))
79		->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
80		->setAriaRequired()
81		->setAttribute('autofocus', 'autofocus')
82);
83
84if ($discovered_trigger) {
85	$triggersFormList->addVar('priority', (int) $data['priority']);
86	$severity = new CSeverity(['name' => 'priority_names', 'value' => (int) $data['priority']], false);
87}
88else {
89	$severity = new CSeverity(['name' => 'priority', 'value' => (int) $data['priority']]);
90}
91
92$triggersFormList->addRow(_('Severity'), $severity);
93
94// Append expression to form list.
95if ($data['expression_field_readonly']) {
96	$triggersForm->addVar('expression', $data['expression']);
97}
98
99if ($data['recovery_expression_field_readonly']) {
100	$triggersForm->addVar('recovery_expression', $data['recovery_expression']);
101}
102
103$popup_options = [
104	'srctbl' => $data['expression_field_name'],
105	'srcfld1' => $data['expression_field_name'],
106	'dstfrm' => $triggersForm->getName(),
107	'dstfld1' => $data['expression_field_name']
108];
109
110if ($data['groupid'] && $data['hostid']) {
111	$popup_options['groupid'] = $data['groupid'];
112	$popup_options['hostid'] = $data['hostid'];
113}
114
115$expression_row = [
116	(new CTextArea(
117		$data['expression_field_name'],
118		$data['expression_field_value'],
119		['readonly' => $data['expression_field_readonly']]
120	))
121		->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
122		->setAriaRequired(),
123	(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
124	(new CButton('insert', ($data['expression_constructor'] == IM_TREE) ? _('Edit') : _('Add')))
125		->addClass(ZBX_STYLE_BTN_GREY)
126		->onClick('return PopUp("popup.triggerexpr",jQuery.extend('.CJs::encodeJson($popup_options).
127			',{expression: jQuery(\'[name="'.$data['expression_field_name'].'"]\').val()}), null, this);'
128		)
129		->setEnabled(!$readonly)
130		->removeId()
131];
132
133if ($data['expression_constructor'] == IM_TREE) {
134	// Append "Insert expression" button.
135	$expression_row[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
136	$expression_row[] = (new CButton('insert_macro', _('Insert expression')))
137		->addClass(ZBX_STYLE_BTN_GREY)
138		->setMenuPopup(CMenuPopupHelper::getTriggerMacro())
139		->setEnabled(!$readonly);
140	$expression_row[] = BR();
141
142	if ($data['expression_formula'] === '') {
143		// Append "Add" button.
144		$expression_row[] = (new CSimpleButton(_('Add')))
145			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "add_expression", "1");')
146			->addClass(ZBX_STYLE_BTN_GREY)
147			->setEnabled(!$readonly);
148	}
149	else {
150		// Append "And" button.
151		$expression_row[] = (new CSimpleButton(_('And')))
152			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "and_expression", "1");')
153			->addClass(ZBX_STYLE_BTN_GREY)
154			->setEnabled(!$readonly);
155
156		// Append "Or" button.
157		$expression_row[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
158		$expression_row[] = (new CSimpleButton(_('Or')))
159			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "or_expression", "1");')
160			->addClass(ZBX_STYLE_BTN_GREY)
161			->setEnabled(!$readonly);
162
163		// Append "Replace" button.
164		$expression_row[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
165		$expression_row[] = (new CSimpleButton(_('Replace')))
166			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "replace_expression", "1");')
167			->addClass(ZBX_STYLE_BTN_GREY)
168			->setEnabled(!$readonly);
169	}
170}
171elseif ($data['expression_constructor'] != IM_FORCED) {
172	$input_method_toggle = (new CSimpleButton(_('Expression constructor')))
173		->addClass(ZBX_STYLE_BTN_LINK)
174		->onClick('javascript: '.
175			'document.getElementById("toggle_expression_constructor").value=1;'.
176			'document.getElementById("expression_constructor").value='.
177				(($data['expression_constructor'] == IM_TREE) ? IM_ESTABLISHED : IM_TREE).';'.
178			'document.forms["'.$triggersForm->getName().'"].submit();');
179	$expression_row[] = [BR(), $input_method_toggle];
180}
181
182$triggersFormList->addRow(
183	(new CLabel(_('Expression'), $data['expression_field_name']))->setAsteriskMark(),
184	$expression_row,
185	'expression_row'
186);
187
188// Append expression table to form list.
189if ($data['expression_constructor'] == IM_TREE) {
190	$expressionTable = (new CTable())
191		->setAttribute('style', 'width: 100%;')
192		->setHeader([
193			$readonly ? null : _('Target'),
194			_('Expression'),
195			$readonly ? null : _('Action'),
196			_('Info')
197		]);
198
199	$allowed_testing = true;
200	if ($data['expression_tree']) {
201		foreach ($data['expression_tree'] as $i => $e) {
202			$info_icons = [];
203			if (isset($e['expression']['levelErrors'])) {
204				$allowed_testing = false;
205				$errors = [];
206
207				if (is_array($e['expression']['levelErrors'])) {
208					foreach ($e['expression']['levelErrors'] as $expVal => $errTxt) {
209						if ($errors) {
210							$errors[] = BR();
211						}
212						$errors[] = $expVal.':'.$errTxt;
213					}
214				}
215
216				$info_icons[] = makeErrorIcon($errors);
217			}
218
219			// Templated or discovered trigger.
220			if ($readonly) {
221				// Make all links inside inactive.
222				foreach ($e['list'] as &$obj) {
223					if ($obj instanceof CLinkAction && $obj->getAttribute('class') == ZBX_STYLE_LINK_ACTION) {
224						$obj = new CSpan($obj->items);
225					}
226				}
227				unset($obj);
228			}
229
230			$expressionTable->addRow(
231				new CRow([
232					!$readonly
233						? (new CCheckBox('expr_target_single', $e['id']))
234							->setChecked($i == 0)
235							->onClick('check_target(this, '.TRIGGER_EXPRESSION.');')
236							->removeId()
237						: null,
238					$e['list'],
239					!$readonly
240						? (new CCol(
241							(new CSimpleButton(_('Remove')))
242								->addClass(ZBX_STYLE_BTN_LINK)
243								->onClick('javascript:'.
244									' if (confirm('.CJs::encodeJson(_('Delete expression?')).')) {'.
245										' delete_expression("'.$e['id'] .'", '.TRIGGER_EXPRESSION.');'.
246										' document.forms["'.$triggersForm->getName().'"].submit();'.
247									' }'
248								)
249						))->addClass(ZBX_STYLE_NOWRAP)
250						: null,
251					makeInformationList($info_icons)
252				])
253			);
254		}
255	}
256	else {
257		$allowed_testing = false;
258		$data['expression_formula'] = '';
259	}
260
261	$testButton = (new CButton('test_expression', _('Test')))
262		->onClick('return PopUp("popup.testtriggerexpr",{expression: this.form.elements["expression"].value}, null,'.
263					'this);')
264		->addClass(ZBX_STYLE_BTN_LINK)
265		->removeId();
266
267	if (!$allowed_testing) {
268		$testButton->setEnabled(false);
269	}
270
271	if ($data['expression_formula'] === '') {
272		$testButton->setEnabled(false);
273	}
274
275	$wrapOutline = new CSpan([$data['expression_formula']]);
276	$triggersFormList->addRow(null, [
277		$wrapOutline,
278		BR(),
279		BR(),
280		(new CDiv([$expressionTable, $testButton]))
281			->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
282			->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
283	]);
284
285	$input_method_toggle = (new CSimpleButton(_('Close expression constructor')))
286		->addClass(ZBX_STYLE_BTN_LINK)
287		->onClick('javascript: '.
288			'document.getElementById("toggle_expression_constructor").value=1;'.
289			'document.getElementById("expression_constructor").value='.IM_ESTABLISHED.';'.
290			'document.forms["'.$triggersForm->getName().'"].submit();');
291	$triggersFormList->addRow(null, [$input_method_toggle, BR()]);
292}
293
294$triggersFormList->addRow(_('OK event generation'),
295	(new CRadioButtonList('recovery_mode', (int) $data['recovery_mode']))
296		->addValue(_('Expression'), ZBX_RECOVERY_MODE_EXPRESSION)
297		->addValue(_('Recovery expression'), ZBX_RECOVERY_MODE_RECOVERY_EXPRESSION)
298		->addValue(_('None'), ZBX_RECOVERY_MODE_NONE)
299		->setModern(true)
300		->setEnabled(!$readonly)
301);
302
303$popup_options = [
304	'srctbl' => $data['recovery_expression_field_name'],
305	'srcfld1' => $data['recovery_expression_field_name'],
306	'dstfrm' => $triggersForm->getName(),
307	'dstfld1' => $data['recovery_expression_field_name']
308];
309if ($data['groupid'] && $data['hostid']) {
310	$popup_options['groupid'] = $data['groupid'];
311	$popup_options['hostid'] = $data['hostid'];
312}
313
314$recovery_expression_row = [
315	(new CTextArea(
316		$data['recovery_expression_field_name'],
317		$data['recovery_expression_field_value'],
318		['readonly' => $data['recovery_expression_field_readonly']]
319	))
320		->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
321		->setAriaRequired(),
322	(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
323	(new CButton('insert', ($data['recovery_expression_constructor'] == IM_TREE) ? _('Edit') : _('Add')))
324		->addClass(ZBX_STYLE_BTN_GREY)
325		->onClick('return PopUp("popup.triggerexpr",jQuery.extend('.
326			CJs::encodeJson($popup_options).
327				',{expression: jQuery(\'[name="'.$data['recovery_expression_field_name'].'"]\').val()}), null, this);'
328		)
329		->setEnabled(!$readonly)
330		->removeId()
331];
332
333if ($data['recovery_expression_constructor'] == IM_TREE) {
334	$recovery_expression_row[] = BR();
335
336	if ($data['recovery_expression_formula'] === '') {
337		// Append "Add" button.
338		$recovery_expression_row[] = (new CSimpleButton(_('Add')))
339			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "add_recovery_expression", "1");')
340			->addClass(ZBX_STYLE_BTN_GREY)
341			->setEnabled(!$readonly);
342	}
343	else {
344		// Append "And" button.
345		$recovery_expression_row[] = (new CSimpleButton(_('And')))
346			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "and_recovery_expression", "1");')
347			->addClass(ZBX_STYLE_BTN_GREY)
348			->setEnabled(!$readonly);
349
350		// Append "Or" button.
351		$recovery_expression_row[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
352		$recovery_expression_row[] = (new CSimpleButton(_('Or')))
353			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "or_recovery_expression", "1");')
354			->addClass(ZBX_STYLE_BTN_GREY)
355			->setEnabled(!$readonly);
356
357		// Append "Replace" button.
358		$recovery_expression_row[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
359		$recovery_expression_row[] = (new CSimpleButton(_('Replace')))
360			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "replace_recovery_expression", "1");')
361			->addClass(ZBX_STYLE_BTN_GREY)
362			->setEnabled(!$readonly);
363	}
364}
365elseif ($data['recovery_expression_constructor'] != IM_FORCED) {
366	$input_method_toggle = (new CSimpleButton(_('Expression constructor')))
367		->addClass(ZBX_STYLE_BTN_LINK)
368		->onClick('javascript: '.
369			'document.getElementById("toggle_recovery_expression_constructor").value=1;'.
370			'document.getElementById("recovery_expression_constructor").value='.
371				(($data['recovery_expression_constructor'] == IM_TREE) ? IM_ESTABLISHED : IM_TREE).';'.
372			'document.forms["'.$triggersForm->getName().'"].submit();'
373		);
374	$recovery_expression_row[] = [BR(), $input_method_toggle];
375}
376
377$triggersFormList->addRow(
378	(new CLabel(_('Recovery expression'), $data['recovery_expression_field_name']))->setAsteriskMark(),
379	$recovery_expression_row,
380	null,
381	'recovery_expression_constructor_row'
382);
383
384// Append expression table to form list.
385if ($data['recovery_expression_constructor'] == IM_TREE) {
386	$recovery_expression_table = (new CTable())
387		->setAttribute('style', 'width: 100%;')
388		->setHeader([
389			$readonly ? null : _('Target'),
390			_('Expression'),
391			$readonly ? null : _('Action'),
392			_('Info')
393		]);
394
395	$allowed_testing = true;
396
397	if ($data['recovery_expression_tree']) {
398		foreach ($data['recovery_expression_tree'] as $i => $e) {
399			$info_icons = [];
400			if (isset($e['expression']['levelErrors'])) {
401				$allowed_testing = false;
402				$errors = [];
403
404				if (is_array($e['expression']['levelErrors'])) {
405					foreach ($e['expression']['levelErrors'] as $expVal => $errTxt) {
406						if ($errors) {
407							$errors[] = BR();
408						}
409						$errors[] = $expVal.':'.$errTxt;
410					}
411				}
412
413				$info_icons[] = makeErrorIcon($errors);
414			}
415
416			// Templated or discovered trigger.
417			if ($readonly) {
418				// Make all links inside inactive.
419				foreach ($e['list'] as &$obj) {
420					if ($obj instanceof CLinkAction && $obj->getAttribute('class') == ZBX_STYLE_LINK_ACTION) {
421						$obj = new CSpan($obj->items);
422					}
423				}
424				unset($obj);
425			}
426
427			$recovery_expression_table->addRow(
428				new CRow([
429					!$readonly
430						? (new CCheckBox('recovery_expr_target_single', $e['id']))
431							->setChecked($i == 0)
432							->onClick('check_target(this, '.TRIGGER_RECOVERY_EXPRESSION.');')
433							->removeId()
434						: null,
435					$e['list'],
436					!$readonly
437						? (new CCol(
438							(new CSimpleButton(_('Remove')))
439								->addClass(ZBX_STYLE_BTN_LINK)
440								->onClick('javascript:'.
441									' if (confirm('.CJs::encodeJson(_('Delete expression?')).')) {'.
442										' delete_expression("'.$e['id'] .'", '.TRIGGER_RECOVERY_EXPRESSION.');'.
443										' document.forms["'.$triggersForm->getName().'"].submit();'.
444									' }'
445								)
446						))->addClass(ZBX_STYLE_NOWRAP)
447						: null,
448					makeInformationList($info_icons)
449				])
450			);
451		}
452	}
453	else {
454		$allowed_testing = false;
455		$data['recovery_expression_formula'] = '';
456	}
457
458	$testButton = (new CButton('test_expression', _('Test')))
459		->onClick('return PopUp("popup.testtriggerexpr",'.
460			'{expression: this.form.elements["recovery_expression"].value}, null, this);')
461		->addClass(ZBX_STYLE_BTN_LINK)
462		->removeId();
463
464	if (!$allowed_testing) {
465		$testButton->setAttribute('disabled', 'disabled');
466	}
467
468	if ($data['recovery_expression_formula'] === '') {
469		$testButton->setAttribute('disabled', 'disabled');
470	}
471
472	$wrapOutline = new CSpan([$data['recovery_expression_formula']]);
473	$triggersFormList->addRow(null, [
474		$wrapOutline,
475		BR(),
476		BR(),
477		(new CDiv([$recovery_expression_table, $testButton]))
478			->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
479			->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
480	], null, 'recovery_expression_constructor_row');
481
482	$input_method_toggle = (new CSimpleButton(_('Close expression constructor')))
483		->addClass(ZBX_STYLE_BTN_LINK)
484		->onClick('javascript: '.
485			'document.getElementById("toggle_recovery_expression_constructor").value=1;'.
486			'document.getElementById("recovery_expression_constructor").value='.IM_ESTABLISHED.';'.
487			'document.forms["'.$triggersForm->getName().'"].submit();'
488		);
489	$triggersFormList->addRow(null, [$input_method_toggle, BR()], null, 'recovery_expression_constructor_row');
490}
491
492$triggersFormList
493	->addRow(_('PROBLEM event generation mode'),
494		(new CRadioButtonList('type', (int) $data['type']))
495			->addValue(_('Single'), TRIGGER_MULT_EVENT_DISABLED)
496			->addValue(_('Multiple'), TRIGGER_MULT_EVENT_ENABLED)
497			->setModern(true)
498			->setEnabled(!$readonly)
499	)
500	->addRow(_('OK event closes'),
501		(new CRadioButtonList('correlation_mode', (int) $data['correlation_mode']))
502			->addValue(_('All problems'), ZBX_TRIGGER_CORRELATION_NONE)
503			->addValue(_('All problems if tag values match'), ZBX_TRIGGER_CORRELATION_TAG)
504			->setModern(true)
505			->setEnabled(!$readonly),
506		'correlation_mode_row'
507	)
508	->addRow(
509		(new CLabel(_('Tag for matching'), 'correlation_tag'))->setAsteriskMark(),
510		(new CTextBox('correlation_tag', $data['correlation_tag'], $readonly))
511			->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
512			->setAriaRequired(),
513		'correlation_tag_row'
514	);
515
516// Append tags to form list.
517$tags_table = (new CTable())->setId('tbl_tags');
518
519foreach ($data['tags'] as $tag_key => $tag) {
520	$tags = [
521		(new CTextBox('tags['.$tag_key.'][tag]', $tag['tag'], $discovered_trigger, 255))
522			->setWidth(ZBX_TEXTAREA_TAG_WIDTH)
523			->setAttribute('placeholder', _('tag')),
524		(new CTextBox('tags['.$tag_key.'][value]', $tag['value'], $discovered_trigger, 255))
525			->setWidth(ZBX_TEXTAREA_TAG_WIDTH)
526			->setAttribute('placeholder', _('value'))
527	];
528
529	if (!$discovered_trigger) {
530		$tags[] = (new CCol(
531			(new CButton('tags['.$tag_key.'][remove]', _('Remove')))
532				->addClass(ZBX_STYLE_BTN_LINK)
533				->addClass('element-table-remove')
534		))->addClass(ZBX_STYLE_NOWRAP);
535	}
536
537	$tags_table->addRow($tags, 'form_row');
538}
539
540if (!$discovered_trigger) {
541	$tags_table->setFooter(new CCol(
542		(new CButton('tag_add', _('Add')))
543			->addClass(ZBX_STYLE_BTN_LINK)
544			->addClass('element-table-add')
545	));
546}
547
548$triggersFormList->addRow(_('Tags'),
549	(new CDiv($tags_table))
550		->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
551		->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
552);
553
554$triggersFormList->addRow(_('Allow manual close'),
555	(new CCheckBox('manual_close'))
556		->setChecked($data['manual_close'] == ZBX_TRIGGER_MANUAL_CLOSE_ALLOWED)
557		->setEnabled(!$readonly)
558);
559
560// Append status to form list.
561if (empty($data['triggerid']) && empty($data['form_refresh'])) {
562	$status = true;
563}
564else {
565	$status = ($data['status'] == TRIGGER_STATUS_ENABLED);
566}
567
568$triggersFormList
569	->addRow(_('URL'), (new CTextBox('url', $data['url'], $discovered_trigger))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH))
570	->addRow(_('Description'),
571		(new CTextArea('comments', $data['comments']))
572			->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
573			->setReadonly($discovered_trigger)
574	)
575	->addRow(_('Enabled'), (new CCheckBox('status'))->setChecked($status));
576
577// Append tabs to form.
578$triggersTab = new CTabView();
579if (!$data['form_refresh']) {
580	$triggersTab->setSelected(0);
581}
582$triggersTab->addTab('triggersTab', _('Trigger'), $triggersFormList);
583
584/*
585 * Dependencies tab
586 */
587$dependenciesFormList = new CFormList('dependenciesFormList');
588$dependenciesTable = (new CTable())
589	->setAttribute('style', 'width: 100%;')
590	->setHeader([_('Name'), $discovered_trigger ? null : _('Action')]);
591
592foreach ($data['db_dependencies'] as $dependency) {
593	$triggersForm->addVar('dependencies[]', $dependency['triggerid'], 'dependencies_'.$dependency['triggerid']);
594
595	$dep_trigger_description = CHtml::encode(
596		implode(', ', zbx_objectValues($dependency['hosts'], 'name')).NAME_DELIMITER.$dependency['description']
597	);
598
599	$dependenciesTable->addRow(
600		(new CRow([
601			(new CLink($dep_trigger_description, 'triggers.php?form=update&triggerid='.$dependency['triggerid']))
602				->setAttribute('target', '_blank'),
603			(new CCol(
604				$discovered_trigger
605					? null
606					: (new CButton('remove', _('Remove')))
607						->onClick('javascript: removeDependency("'.$dependency['triggerid'].'");')
608						->addClass(ZBX_STYLE_BTN_LINK)
609						->removeId()
610			))->addClass(ZBX_STYLE_NOWRAP)
611		]))->setId('dependency_'.$dependency['triggerid'])
612	);
613}
614
615$dependenciesFormList->addRow(_('Dependencies'),
616	(new CDiv([
617		$dependenciesTable,
618		$discovered_trigger
619			? null
620			: (new CButton('bnt1', _('Add')))
621				->onClick('return PopUp("popup.generic",'.
622					CJs::encodeJson([
623						'srctbl' => 'triggers',
624						'srcfld1' => 'triggerid',
625						'reference' => 'deptrigger',
626						'hostid' => $data['hostid'],
627						'groupid' => $data['groupid'],
628						'multiselect' => '1',
629						'with_triggers' => '1',
630						'noempty' => '1'
631					]).', null, this);'
632				)
633				->addClass(ZBX_STYLE_BTN_LINK)
634	]))
635		->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
636		->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
637);
638$triggersTab->addTab('dependenciesTab', _('Dependencies'), $dependenciesFormList);
639
640// Append buttons to form list.
641if (!empty($data['triggerid'])) {
642	$triggersTab->setFooter(makeFormFooter(
643		new CSubmit('update', _('Update')), [
644			new CSubmit('clone', _('Clone')),
645			(new CButtonDelete(_('Delete trigger?'), url_params(['form', 'hostid', 'triggerid'])))
646				->setEnabled(!$data['limited']),
647			new CButtonCancel(url_param('hostid'))
648		]
649	));
650}
651else {
652	$triggersTab->setFooter(makeFormFooter(
653		new CSubmit('add', _('Add')),
654		[new CButtonCancel(url_param('hostid'))]
655	));
656}
657
658// Append tabs to form.
659$triggersForm->addItem($triggersTab);
660
661$widget->addItem($triggersForm);
662
663return $widget;
664