1<?php
2/*
3** Zabbix
4** Copyright (C) 2001-2021 Zabbix SIA
5**
6** This program is free software; you can redistribute it and/or modify
7** it under the terms of the GNU General Public License as published by
8** the Free Software Foundation; either version 2 of the License, or
9** (at your option) any later version.
10**
11** This program is distributed in the hope that it will be useful,
12** but WITHOUT ANY WARRANTY; without even the implied warranty of
13** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14** GNU General Public License for more details.
15**
16** You should have received a copy of the GNU General Public License
17** along with this program; if not, write to the Free Software
18** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19**/
20
21
22/**
23 * @var CView $this
24 */
25
26require_once dirname(__FILE__).'/js/configuration.triggers.edit.js.php';
27
28$triggersWidget = (new CWidget())
29	->setTitle(_('Trigger prototypes'))
30	->setNavigation(getHostNavigation('triggers', $data['hostid'], $data['parent_discoveryid']));
31
32$url = (new CUrl('trigger_prototypes.php'))
33	->setArgument('context', $data['context'])
34	->getUrl();
35
36// create form
37$triggersForm = (new CForm('post', $url))
38	->setId('triggers-prototype-form')
39	->setName('triggersForm')
40	->setAttribute('aria-labeledby', ZBX_STYLE_PAGE_TITLE)
41	->addVar('form', $data['form'])
42	->addItem((new CVar('parent_discoveryid', $data['parent_discoveryid']))->removeId())
43	->addVar('expression_constructor', $data['expression_constructor'])
44	->addVar('recovery_expression_constructor', $data['recovery_expression_constructor'])
45	->addVar('toggle_expression_constructor', '')
46	->addVar('toggle_recovery_expression_constructor', '')
47	->addVar('remove_expression', '')
48	->addVar('remove_recovery_expression', '');
49
50if ($data['triggerid'] !== null) {
51	$triggersForm->addVar('triggerid', $data['triggerid']);
52}
53
54if ($data['limited']) {
55	$triggersForm
56		->addItem((new CVar('opdata', $data['opdata']))->removeId())
57		->addItem((new CVar('recovery_mode', $data['recovery_mode']))->removeId())
58		->addItem((new CVar('type', $data['type']))->removeId())
59		->addItem((new CVar('correlation_mode', $data['correlation_mode']))->removeId())
60		->addItem((new CVar('manual_close', $data['manual_close']))->removeId());
61}
62
63// create form list
64$triggersFormList = new CFormList('triggersFormList');
65if (!empty($data['templates'])) {
66	$triggersFormList->addRow(_('Parent triggers'), $data['templates']);
67}
68$triggersFormList
69	->addRow(
70		(new CLabel(_('Name'), 'description'))->setAsteriskMark(),
71		(new CTextBox('description', $data['description'], $data['limited']))
72			->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
73			->setAriaRequired()
74			->setAttribute('autofocus', 'autofocus')
75	)
76	->addRow(
77		(new CLabel(_('Event name'), 'event_name')),
78		(new CTextAreaFlexible('event_name', $data['event_name']))
79			->setReadonly($data['limited'])
80			->setMaxlength(DB::getFieldLength('triggers', 'event_name'))
81			->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
82	)
83	->addRow(
84		new CLabel(_('Operational data'), 'opdata'),
85		(new CTextBox('opdata', $data['opdata'], $data['limited']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
86	)
87	->addRow(
88		_('Severity'),
89		new CSeverity(['name' => 'priority', 'value' => (int) $data['priority']])
90	);
91
92// append expression to form list
93if ($data['expression_field_readonly']) {
94	$triggersForm->addItem((new CVar('expression', $data['expression']))->removeId());
95}
96
97if ($data['recovery_expression_field_readonly']) {
98	$triggersForm->addItem((new CVar('recovery_expression', $data['recovery_expression']))->removeId());
99}
100
101$popup_options = [
102	'srctbl' => 'expression',
103	'srcfld1' => 'expression',
104	'dstfrm' => $triggersForm->getName(),
105	'dstfld1' => $data['expression_field_name'],
106	'parent_discoveryid' => $data['parent_discoveryid']
107];
108if ($data['hostid']) {
109	$popup_options['hostid'] = $data['hostid'];
110}
111$add_expression_button = (new CButton('insert', ($data['expression_constructor'] == IM_TREE) ? _('Edit') : _('Add')))
112	->addClass(ZBX_STYLE_BTN_GREY)
113	->onClick('return PopUp("popup.triggerexpr",jQuery.extend('.
114		json_encode($popup_options).
115			',{expression: jQuery(\'[name="'.$data['expression_field_name'].'"]\').val()}), null, this);'
116	)
117	->removeId();
118if ($data['limited']) {
119	$add_expression_button->setAttribute('disabled', 'disabled');
120}
121$expression_row = [
122	(new CTextArea(
123		$data['expression_field_name'],
124		$data['expression_field_value'],
125		['readonly' => $data['expression_field_readonly']]
126	))
127		->addClass(ZBX_STYLE_MONOSPACE_FONT)
128		->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
129		->setAriaRequired(),
130	(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
131	$add_expression_button
132];
133
134if ($data['expression_constructor'] == IM_TREE) {
135	// insert macro button
136	$insertMacroButton = (new CButton('insert_macro', _('Insert expression')))
137		->addClass(ZBX_STYLE_BTN_GREY)
138		->setMenuPopup(CMenuPopupHelper::getTriggerMacro());
139	if ($data['limited']) {
140		$insertMacroButton->setAttribute('disabled', 'disabled');
141	}
142	$expression_row[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
143	$expression_row[] = $insertMacroButton;
144	$expression_row[] = BR();
145
146	if ($data['expression_formula'] === '') {
147		// Append "Add" button.
148		$expression_row[] = (new CSimpleButton(_('Add')))
149			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "add_expression", "1");')
150			->addClass(ZBX_STYLE_BTN_GREY)
151			->setEnabled(!$data['limited']);
152	}
153	else {
154		// Append "And" button.
155		$expression_row[] = (new CSimpleButton(_('And')))
156			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "and_expression", "1");')
157			->addClass(ZBX_STYLE_BTN_GREY)
158			->setEnabled(!$data['limited']);
159
160		// Append "Or" button.
161		$expression_row[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
162		$expression_row[] = (new CSimpleButton(_('Or')))
163			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "or_expression", "1");')
164			->addClass(ZBX_STYLE_BTN_GREY)
165			->setEnabled(!$data['limited']);
166
167		// Append "Replace" button.
168		$expression_row[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
169		$expression_row[] = (new CSimpleButton(_('Replace')))
170			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "replace_expression", "1");')
171			->addClass(ZBX_STYLE_BTN_GREY)
172			->setEnabled(!$data['limited']);
173	}
174}
175elseif ($data['expression_constructor'] != IM_FORCED) {
176	$input_method_toggle = (new CSimpleButton(_('Expression constructor')))
177		->addClass(ZBX_STYLE_BTN_LINK)
178		->onClick('javascript: '.
179			'document.getElementById("toggle_expression_constructor").value=1;'.
180			'document.getElementById("expression_constructor").value='.
181				(($data['expression_constructor'] == IM_TREE) ? IM_ESTABLISHED : IM_TREE).';'.
182			'document.forms["'.$triggersForm->getName().'"].submit();');
183	$expression_row[] = [BR(), $input_method_toggle];
184}
185
186$triggersFormList->addRow(
187	(new CLabel(_('Expression'), $data['expression_field_name']))->setAsteriskMark(),
188	$expression_row,
189	'expression_row'
190);
191
192// Append expression table to form list.
193if ($data['expression_constructor'] == IM_TREE) {
194	$expressionTable = (new CTable())
195		->setAttribute('style', 'width: 100%;')
196		->setHeader([
197			$data['limited'] ? null : _('Target'),
198			_('Expression'),
199			$data['limited'] ? null : _('Action'),
200			_('Info')
201		]);
202
203	$allowed_testing = true;
204	if ($data['expression_tree']) {
205		foreach ($data['expression_tree'] as $i => $e) {
206			$info_icons = [];
207			if (isset($e['expression']['levelErrors'])) {
208				$allowed_testing = false;
209				$errors = [];
210
211				if (is_array($e['expression']['levelErrors'])) {
212					foreach ($e['expression']['levelErrors'] as $expVal => $errTxt) {
213						if ($errors) {
214							$errors[] = BR();
215						}
216						$errors[] = $expVal.':'.$errTxt;
217					}
218				}
219
220				$info_icons[] = makeErrorIcon($errors);
221			}
222
223			// templated trigger
224			if ($data['limited']) {
225				// make all links inside inactive
226				foreach ($e['list'] as &$obj) {
227					if ($obj instanceof CLinkAction && $obj->getAttribute('class') == ZBX_STYLE_LINK_ACTION) {
228						$obj = new CSpan($obj->items);
229					}
230				}
231				unset($obj);
232			}
233
234			$expressionTable->addRow(
235				new CRow([
236					!$data['limited']
237						? (new CCheckBox('expr_target_single', $e['id']))
238							->setChecked($i == 0)
239							->onClick('check_target(this, '.TRIGGER_EXPRESSION.');')
240						: null,
241					(new CDiv($e['list']))->addClass(ZBX_STYLE_WORDWRAP),
242					!$data['limited']
243						? (new CCol(
244							(new CSimpleButton(_('Remove')))
245								->addClass(ZBX_STYLE_BTN_LINK)
246								->onClick('javascript:'.
247									' if (confirm('.json_encode(_('Delete expression?')).')) {'.
248										' delete_expression("'.$e['id'] .'", '.TRIGGER_EXPRESSION.');'.
249										' document.forms["'.$triggersForm->getName().'"].submit();'.
250									' }'
251								)
252						))->addClass(ZBX_STYLE_NOWRAP)
253						: null,
254					makeInformationList($info_icons)
255				])
256			);
257		}
258	}
259	else {
260		$allowed_testing = false;
261		$data['expression_formula'] = '';
262	}
263
264	$testButton = (new CButton('test_expression', _('Test')))
265		->onClick('return PopUp("popup.testtriggerexpr",{expression: this.form.elements["expression"].value}, null,'.
266					'this);')
267		->addClass(ZBX_STYLE_BTN_LINK)
268		->removeId();
269	if (!$allowed_testing) {
270		$testButton->setAttribute('disabled', 'disabled');
271	}
272	if ($data['expression_formula'] === '') {
273		$testButton->setAttribute('disabled', 'disabled');
274	}
275
276	$wrapOutline = new CSpan([$data['expression_formula']]);
277	$triggersFormList->addRow(null, [
278		$wrapOutline,
279		BR(),
280		BR(),
281		(new CDiv([$expressionTable, $testButton]))
282			->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
283			->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
284	]);
285
286	$input_method_toggle = (new CSimpleButton(_('Close expression constructor')))
287		->addClass(ZBX_STYLE_BTN_LINK)
288		->onClick('javascript: '.
289			'document.getElementById("toggle_expression_constructor").value=1;'.
290			'document.getElementById("expression_constructor").value='.IM_ESTABLISHED.';'.
291			'document.forms["'.$triggersForm->getName().'"].submit();');
292	$triggersFormList->addRow(null, [$input_method_toggle, BR()]);
293}
294
295$triggersFormList->addRow(_('OK event generation'),
296	(new CRadioButtonList('recovery_mode', (int) $data['recovery_mode']))
297		->addValue(_('Expression'), ZBX_RECOVERY_MODE_EXPRESSION)
298		->addValue(_('Recovery expression'), ZBX_RECOVERY_MODE_RECOVERY_EXPRESSION)
299		->addValue(_('None'), ZBX_RECOVERY_MODE_NONE)
300		->setModern(true)
301		->setEnabled(!$data['limited'])
302);
303
304$add_recovery_expression_button = (new CButton('insert',
305		($data['recovery_expression_constructor'] == IM_TREE) ? _('Edit') : _('Add'))
306	)
307	->addClass(ZBX_STYLE_BTN_GREY)
308	->onClick('return PopUp("popup.triggerexpr",jQuery.extend('.
309		json_encode([
310			'srctbl' => $data['recovery_expression_field_name'],
311			'srcfld1' => $data['recovery_expression_field_name'],
312			'dstfrm' => $triggersForm->getName(),
313			'dstfld1' => $data['recovery_expression_field_name'],
314			'parent_discoveryid' => $data['parent_discoveryid']
315		]).
316			',{expression: jQuery(\'[name="'.$data['recovery_expression_field_name'].'"]\').val()}), null, this);'
317	);
318
319if ($data['limited']) {
320	$add_recovery_expression_button->setAttribute('disabled', 'disabled');
321}
322
323$recovery_expression_row = [
324	(new CTextArea(
325		$data['recovery_expression_field_name'],
326		$data['recovery_expression_field_value'],
327		['readonly' => $data['recovery_expression_field_readonly']]
328	))
329		->addClass(ZBX_STYLE_MONOSPACE_FONT)
330		->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
331		->setAriaRequired(),
332	(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
333	$add_recovery_expression_button
334];
335
336if ($data['recovery_expression_constructor'] == IM_TREE) {
337	$recovery_expression_row[] = BR();
338
339	if ($data['recovery_expression_formula'] === '') {
340		// Append "Add" button.
341		$recovery_expression_row[] = (new CSimpleButton(_('Add')))
342			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "add_recovery_expression", "1");')
343			->addClass(ZBX_STYLE_BTN_GREY)
344			->setEnabled(!$data['limited']);
345	}
346	else {
347		// Append "And" button.
348		$recovery_expression_row[] = (new CSimpleButton(_('And')))
349			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "and_recovery_expression", "1");')
350			->addClass(ZBX_STYLE_BTN_GREY)
351			->setEnabled(!$data['limited']);
352
353		// Append "Or" button.
354		$recovery_expression_row[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
355		$recovery_expression_row[] = (new CSimpleButton(_('Or')))
356			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "or_recovery_expression", "1");')
357			->addClass(ZBX_STYLE_BTN_GREY)
358			->setEnabled(!$data['limited']);
359
360		// Append "Replace" button.
361		$recovery_expression_row[] = (new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN);
362		$recovery_expression_row[] = (new CSimpleButton(_('Replace')))
363			->onClick('javascript: submitFormWithParam("'.$triggersForm->getName().'", "replace_recovery_expression", "1");')
364			->addClass(ZBX_STYLE_BTN_GREY)
365			->setEnabled(!$data['limited']);
366	}
367}
368elseif ($data['recovery_expression_constructor'] != IM_FORCED) {
369	$input_method_toggle = (new CSimpleButton(_('Expression constructor')))
370		->addClass(ZBX_STYLE_BTN_LINK)
371		->onClick('javascript: '.
372			'document.getElementById("toggle_recovery_expression_constructor").value=1;'.
373			'document.getElementById("recovery_expression_constructor").value='.
374				(($data['recovery_expression_constructor'] == IM_TREE) ? IM_ESTABLISHED : IM_TREE).';'.
375			'document.forms["'.$triggersForm->getName().'"].submit();'
376		);
377	$recovery_expression_row[] = [BR(), $input_method_toggle];
378}
379
380$triggersFormList->addRow(
381	(new CLabel(_('Recovery expression'), $data['recovery_expression_field_name']))->setAsteriskMark(),
382	$recovery_expression_row,
383	null,
384	'recovery_expression_constructor_row'
385);
386
387// Append expression table to form list.
388if ($data['recovery_expression_constructor'] == IM_TREE) {
389	$recovery_expression_table = (new CTable())
390		->setAttribute('style', 'width: 100%;')
391		->setHeader([
392			$data['limited'] ? null : _('Target'),
393			_('Expression'),
394			$data['limited'] ? null : _('Action'),
395			_('Info')
396		]);
397
398	$allowed_testing = true;
399
400	if ($data['recovery_expression_tree']) {
401		foreach ($data['recovery_expression_tree'] as $i => $e) {
402			$info_icons = [];
403			if (isset($e['expression']['levelErrors'])) {
404				$allowed_testing = false;
405				$errors = [];
406
407				if (is_array($e['expression']['levelErrors'])) {
408					foreach ($e['expression']['levelErrors'] as $expVal => $errTxt) {
409						if ($errors) {
410							$errors[] = BR();
411						}
412						$errors[] = $expVal.':'.$errTxt;
413					}
414				}
415
416				$info_icons[] = makeErrorIcon($errors);
417			}
418
419			// templated trigger
420			if ($data['limited']) {
421				// make all links inside inactive
422				foreach ($e['list'] as &$obj) {
423					if ($obj instanceof CLinkAction && $obj->getAttribute('class') == ZBX_STYLE_LINK_ACTION) {
424						$obj = new CSpan($obj->items);
425					}
426				}
427				unset($obj);
428			}
429
430			$recovery_expression_table->addRow(
431				new CRow([
432					!$data['limited']
433						? (new CCheckBox('recovery_expr_target_single', $e['id']))
434							->setChecked($i == 0)
435							->onClick('check_target(this, '.TRIGGER_RECOVERY_EXPRESSION.');')
436						: null,
437					$e['list'],
438					!$data['limited']
439						? (new CCol(
440							(new CSimpleButton(_('Remove')))
441								->addClass(ZBX_STYLE_BTN_LINK)
442								->onClick('javascript:'.
443									' if (confirm('.json_encode(_('Delete expression?')).')) {'.
444										' delete_expression("'.$e['id'] .'", '.TRIGGER_RECOVERY_EXPRESSION.');'.
445										' document.forms["'.$triggersForm->getName().'"].submit();'.
446									' }'
447								)
448						))->addClass(ZBX_STYLE_NOWRAP)
449						: null,
450					makeInformationList($info_icons)
451				])
452			);
453		}
454	}
455	else {
456		$allowed_testing = false;
457		$data['recovery_expression_formula'] = '';
458	}
459
460	$testButton = (new CButton('test_expression', _('Test')))
461		->onClick('return PopUp("popup.testtriggerexpr",'.
462			'{expression: this.form.elements["recovery_expression"].value}, null, this);')
463		->addClass(ZBX_STYLE_BTN_LINK)
464		->removeId();
465	if (!$allowed_testing) {
466		$testButton->setAttribute('disabled', 'disabled');
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(!$data['limited'])
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(!$data['limited']),
506		'correlation_mode_row'
507	)
508	->addRow(
509		(new CLabel(_('Tag for matching'), 'correlation_tag'))->setAsteriskMark(),
510		(new CTextBox('correlation_tag', $data['correlation_tag'], $data['limited']))
511			->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
512			->setAriaRequired(),
513		'correlation_tag_row'
514	)
515	->addRow(_('Allow manual close'),
516		(new CCheckBox('manual_close'))
517			->setChecked($data['manual_close'] == ZBX_TRIGGER_MANUAL_CLOSE_ALLOWED)
518			->setEnabled(!$data['limited'])
519	);
520
521// append status to form list
522if (empty($data['triggerid']) && empty($data['form_refresh'])) {
523	$status = true;
524}
525else {
526	$status = ($data['status'] == TRIGGER_STATUS_ENABLED);
527}
528
529$triggersFormList
530	->addRow(_('URL'), (new CTextBox('url', $data['url']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH))
531	->addRow(_('Description'),
532		(new CTextArea('comments', $data['comments']))
533			->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
534			->setMaxlength(DB::getFieldLength('triggers', 'comments'))
535	)
536	->addRow(_('Create enabled'), (new CCheckBox('status'))->setChecked($status))
537	->addRow(_('Discover'),
538		(new CCheckBox('discover', ZBX_PROTOTYPE_DISCOVER))
539			->setChecked($data['discover'] == ZBX_PROTOTYPE_DISCOVER)
540			->setUncheckedValue(ZBX_PROTOTYPE_NO_DISCOVER)
541	);
542
543// append tabs to form
544$triggersTab = new CTabView();
545if (!$data['form_refresh']) {
546	$triggersTab->setSelected(0);
547}
548$triggersTab->addTab('triggersTab',	_('Trigger prototype'), $triggersFormList);
549
550// tags
551$triggersTab->addTab('tags-tab', _('Tags'), new CPartial('configuration.tags.tab', [
552		'source' => 'trigger_prototype',
553		'tags' => $data['tags'],
554		'show_inherited_tags' => $data['show_inherited_tags'],
555		'readonly' => false
556	]), TAB_INDICATOR_TAGS
557);
558
559/*
560 * Dependencies tab
561 */
562$dependenciesFormList = new CFormList('dependenciesFormList');
563$dependenciesTable = (new CTable())
564	->setId('dependency-table')
565	->setAttribute('style', 'width: 100%;')
566	->setHeader([_('Name'), _('Action')]);
567
568foreach ($data['db_dependencies'] as $dependency) {
569	$triggersForm->addVar('dependencies[]', $dependency['triggerid'], 'dependencies_'.$dependency['triggerid']);
570
571	$depTriggerDescription = CHtml::encode(
572		implode(', ', zbx_objectValues($dependency['hosts'], 'name')).NAME_DELIMITER.$dependency['description']
573	);
574
575	if ($dependency['flags'] == ZBX_FLAG_DISCOVERY_PROTOTYPE) {
576		$description = (new CLink($depTriggerDescription,
577			(new CUrl('trigger_prototypes.php'))
578				->setArgument('form', 'update')
579				->setArgument('parent_discoveryid', $data['parent_discoveryid'])
580				->setArgument('triggerid', $dependency['triggerid'])
581				->setArgument('context', $data['context'])
582		))->setTarget('_blank');
583	}
584	elseif ($dependency['flags'] == ZBX_FLAG_DISCOVERY_NORMAL) {
585		$description = (new CLink($depTriggerDescription,
586			(new CUrl('triggers.php'))
587				->setArgument('form', 'update')
588				->setArgument('triggerid', $dependency['triggerid'])
589				->setArgument('context', $data['context'])
590		))->setTarget('_blank');
591	}
592
593	$row = new CRow([$description,
594		(new CCol(
595			(new CButton('remove', _('Remove')))
596				->onClick('javascript: removeDependency("'.$dependency['triggerid'].'");')
597				->addClass(ZBX_STYLE_BTN_LINK)
598				->removeId()
599		))->addClass(ZBX_STYLE_NOWRAP)
600	]);
601
602	$row->setId('dependency_'.$dependency['triggerid']);
603	$dependenciesTable->addRow($row);
604}
605
606$dependenciesFormList->addRow(_('Dependencies'),
607	(new CDiv([
608		$dependenciesTable,
609		new CHorList([
610			(new CButton('add_dep_trigger', _('Add')))
611				->onClick('return PopUp("popup.generic",'.
612					json_encode([
613						'srctbl' => 'triggers',
614						'srcfld1' => 'triggerid',
615						'reference' => 'deptrigger',
616						'multiselect' => '1',
617						'with_triggers' => '1',
618						'normal_only' => '1',
619						'noempty' => '1',
620						'hostid' => $data['hostid']
621					]).', null, this);'
622				)
623				->addClass(ZBX_STYLE_BTN_LINK),
624			(new CButton('add_dep_trigger_prototype', _('Add prototype')))
625				->onClick('return PopUp("popup.generic",'.
626					json_encode([
627						'srctbl' => 'trigger_prototypes',
628						'srcfld1' => 'triggerid',
629						'reference' => 'deptrigger',
630						'multiselect' => '1',
631						'parent_discoveryid' => $data['parent_discoveryid']
632					]).', null, this);'
633				)
634				->addClass(ZBX_STYLE_BTN_LINK)
635		])
636	]))
637		->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
638		->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
639);
640$triggersTab->addTab('dependenciesTab', _('Dependencies'), $dependenciesFormList, TAB_INDICATOR_DEPENDENCY);
641
642// append buttons to form
643if (!empty($data['triggerid'])) {
644	$deleteButton = new CButtonDelete(_('Delete trigger prototype?'),
645		url_params(['form', 'triggerid', 'parent_discoveryid', 'context']), 'context'
646	);
647
648	if ($data['limited']) {
649		$deleteButton->setAttribute('disabled', 'disabled');
650	}
651
652	$triggersTab->setFooter(makeFormFooter(
653		new CSubmit('update', _('Update')), [
654			new CSubmit('clone', _('Clone')),
655			$deleteButton,
656			new CButtonCancel(url_params(['parent_discoveryid', 'context']))
657		]
658	));
659}
660else {
661	$triggersTab->setFooter(makeFormFooter(
662		new CSubmit('add', _('Add')),
663		[new CButtonCancel(url_params(['parent_discoveryid', 'context']))]
664	));
665}
666
667// append tabs to form
668$triggersForm->addItem($triggersTab);
669
670$triggersWidget->addItem($triggersForm);
671
672$triggersWidget->show();
673