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
26$this->includeJsFile('administration.user.edit.common.js.php');
27$this->includeJsFile(($data['action'] === 'user.edit')
28	? 'administration.user.edit.js.php'
29	: 'administration.userprofile.edit.js.php'
30);
31$this->addJsFile('multiselect.js');
32$this->addJsFile('class.tab-indicators.js');
33
34$widget = new CWidget();
35
36if ($data['action'] === 'user.edit') {
37	$widget_name = _('Users');
38}
39else {
40	$widget_name = _('User profile').NAME_DELIMITER;
41	$widget_name .= ($data['name'] !== '' || $data['surname'] !== '')
42		? $data['name'].' '.$data['surname']
43		: $data['username'];
44	$widget->setTitleSubmenu(getUserSettingsSubmenu());
45}
46
47$widget->setTitle($widget_name);
48$tabs = new CTabView();
49
50if ($data['form_refresh'] == 0) {
51	$tabs->setSelected(0);
52}
53
54// Create form.
55$user_form = (new CForm())
56	->setId('user-form')
57	->setName('user_form')
58	->setAttribute('aria-labeledby', ZBX_STYLE_PAGE_TITLE)
59	->addVar('action', $data['action'])
60	->addVar('userid', $data['userid']);
61
62// Create form list and user tab.
63$user_form_list = new CFormList('user_form_list');
64
65if ($data['action'] === 'user.edit') {
66	$user_form_list
67		->addRow((new CLabel(_('Username'), 'username'))->setAsteriskMark(),
68			(new CTextBox('username', $data['username']))
69				->setReadonly($data['db_user']['username'] === ZBX_GUEST_USER)
70				->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
71				->setAriaRequired()
72				->setAttribute('autofocus', 'autofocus')
73				->setAttribute('maxlength', DB::getFieldLength('users', 'username'))
74		)
75		->addRow(_x('Name', 'user first name'),
76			(new CTextBox('name', $data['name']))
77				->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
78				->setAttribute('maxlength', DB::getFieldLength('users', 'name'))
79		)
80		->addRow(_('Surname'),
81			(new CTextBox('surname', $data['surname']))
82				->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
83				->setAttribute('maxlength', DB::getFieldLength('users', 'surname'))
84		)
85		->addRow(
86			(new CLabel(_('Groups'), 'user_groups__ms'))->setAsteriskMark(),
87			(new CMultiSelect([
88				'name' => 'user_groups[]',
89				'object_name' => 'usersGroups',
90				'data' => $data['groups'],
91				'popup' => [
92					'parameters' => [
93						'srctbl' => 'usrgrp',
94						'srcfld1' => 'usrgrpid',
95						'dstfrm' => $user_form->getName(),
96						'dstfld1' => 'user_groups_'
97					]
98				]
99			]))
100				->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
101				->setAriaRequired()
102		);
103}
104
105if ($data['change_password']) {
106	$user_form->disablePasswordAutofill();
107
108	$password1 = (new CPassBox('password1', $data['password1']))
109		->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
110		->setAriaRequired();
111
112	if ($data['action'] !== 'user.edit') {
113		$password1->setAttribute('autofocus', 'autofocus');
114	}
115
116	$user_form_list
117		->addRow((new CLabel(_('Password'), 'password1'))->setAsteriskMark(), [
118			// Hidden dummy login field for protection against chrome error when password autocomplete.
119			(new CInput('text', null, null))
120				->setAttribute('tabindex', '-1')
121				->addStyle('position: absolute; left: -100vw;'),
122			$password1
123		])
124		->addRow((new CLabel(_('Password (once again)'), 'password2'))->setAsteriskMark(),
125			(new CPassBox('password2', $data['password2']))
126				->setWidth(ZBX_TEXTAREA_SMALL_WIDTH)
127				->setAriaRequired()
128		)
129		->addRow('', _('Password is not mandatory for non internal authentication type.'));
130}
131else {
132	$user_form_list->addRow(_('Password'),
133		(new CSimpleButton(_('Change password')))
134			->setEnabled($data['action'] === 'userprofile.edit' || $data['db_user']['username'] !== ZBX_GUEST_USER)
135			->setAttribute('autofocus', 'autofocus')
136			->onClick('javascript: submitFormWithParam("'.$user_form->getName().'", "change_password", "1");')
137			->addClass(ZBX_STYLE_BTN_GREY)
138	);
139}
140
141// Append languages, timezones & themes to form list.
142$lang_select = (new CSelect('lang'))
143	->setFocusableElementId('label-lang')
144	->setValue($data['lang'])
145	->addOption(new CSelectOption(LANG_DEFAULT, _('System default')));
146
147$timezone_select = (new CSelect('timezone'))->setFocusableElementId('label-timezone');
148$theme_select = (new CSelect('theme'))
149	->setFocusableElementId('label-theme')
150	->setValue($data['theme'])
151	->addOption(new CSelectOption(THEME_DEFAULT, _('System default')));
152
153$language_error = null;
154if ($data['action'] === 'user.edit' && $data['db_user']['username'] === ZBX_GUEST_USER) {
155	$lang_select
156		->setName(null)
157		->setReadonly();
158	$theme_select
159		->setName(null)
160		->setReadonly();
161	$timezone_select
162		->addOption(new CSelectOption(TIMEZONE_DEFAULT, $data['timezones'][TIMEZONE_DEFAULT]))
163		->setValue(TIMEZONE_DEFAULT)
164		->setReadonly();
165}
166else {
167	$has_unavailable_locale = false;
168
169	foreach (getLocales() as $localeid => $locale) {
170		if (!$locale['display']) {
171			continue;
172		}
173
174		/*
175		 * Checking if this locale exists in the system. The only way of doing it is to try and set one
176		 * trying to set only the LC_MONETARY locale to avoid changing LC_NUMERIC.
177		 */
178		$locale_available = setlocale(LC_MONETARY, zbx_locale_variants($localeid));
179
180		$lang_select->addOption((new CSelectOption($localeid, $locale['name']))->setDisabled(!$locale_available));
181
182		$has_unavailable_locale |= !$locale_available;
183	}
184
185	// Restoring original locale.
186	setlocale(LC_MONETARY, zbx_locale_variants(CWebUser::$data['lang']));
187
188	if (!function_exists('bindtextdomain')) {
189		$language_error = 'Translations are unavailable because the PHP gettext module is missing.';
190		$lang_select->setReadonly();
191	}
192	elseif ($has_unavailable_locale) {
193		$language_error = _('You are not able to choose some of the languages, because locales for them are not installed on the web server.');
194	}
195
196	if ($language_error) {
197		$language_error = (makeErrorIcon($language_error))->addStyle('margin-left: 5px;');
198	}
199
200	$timezone_select
201		->addOptions(CSelect::createOptionsFromArray($data['timezones']))
202		->setValue($data['timezone']);
203	$theme_select->addOptions(CSelect::createOptionsFromArray(APP::getThemes()));
204}
205
206$user_form_list
207	->addRow(new CLabel(_('Language'), $lang_select->getFocusableElementId()), [$lang_select, $language_error])
208	->addRow(new CLabel(_('Time zone'), $timezone_select->getFocusableElementId()), $timezone_select)
209	->addRow(new CLabel(_('Theme'), $theme_select->getFocusableElementId()), $theme_select);
210
211// Append auto-login & auto-logout to form list.
212if ($data['action'] === 'userprofile.edit' || $data['db_user']['username'] !== ZBX_GUEST_USER) {
213	$autologout = ($data['autologout'] !== '0') ? $data['autologout'] : DB::getDefault('users', 'autologout');
214
215	$user_form_list->addRow(_('Auto-login'),
216		(new CCheckBox('autologin'))
217			->setUncheckedValue('0')
218			->setChecked($data['autologin'])
219	);
220	$user_form_list->addRow(_('Auto-logout'), [
221		(new CCheckBox(null))
222			->setId('autologout_visible')
223			->setChecked($data['autologout'] !== '0'),
224		(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
225		(new CTextBox('autologout', $autologout))->setWidth(ZBX_TEXTAREA_TINY_WIDTH)
226	]);
227}
228
229$user_form_list
230	->addRow((new CLabel(_('Refresh'), 'refresh'))->setAsteriskMark(),
231		(new CTextBox('refresh', $data['refresh']))
232			->setWidth(ZBX_TEXTAREA_TINY_WIDTH)
233			->setAriaRequired()
234	)
235	->addRow((new CLabel(_('Rows per page'), 'rows_per_page'))->setAsteriskMark(),
236		(new CNumericBox('rows_per_page', $data['rows_per_page'], 6))
237			->setWidth(ZBX_TEXTAREA_NUMERIC_STANDARD_WIDTH)
238			->setAriaRequired()
239	)
240	->addRow(_('URL (after login)'),
241		(new CTextBox('url', $data['url']))->setWidth(ZBX_TEXTAREA_STANDARD_WIDTH)
242	);
243
244$tabs->addTab('userTab', _('User'), $user_form_list);
245
246// Media tab.
247if ($data['action'] === 'user.edit' || CWebUser::$data['type'] > USER_TYPE_ZABBIX_USER) {
248	$media_form_list = new CFormList('userMediaFormList');
249	$user_form->addVar('medias', $data['medias']);
250
251	$media_table_info = (new CTable())
252		->setId('media-table')
253		->setAttribute('style', 'width: 100%;')
254		->setHeader([_('Type'), _('Send to'), _('When active'), _('Use if severity'), _('Status'), _('Action')]);
255
256	foreach ($data['medias'] as $index => $media) {
257		if ($media['active'] == MEDIA_STATUS_ACTIVE) {
258			$status = (new CLink(_('Enabled'), '#'))
259				->onClick('return create_var("'.$user_form->getName().'","disable_media",'.$index.', true);')
260				->addClass(ZBX_STYLE_LINK_ACTION)
261				->addClass(ZBX_STYLE_GREEN);
262		}
263		else {
264			$status = (new CLink(_('Disabled'), '#'))
265				->onClick('return create_var("'.$user_form->getName().'","enable_media",'.$index.', true);')
266				->addClass(ZBX_STYLE_LINK_ACTION)
267				->addClass(ZBX_STYLE_RED);
268		}
269
270		$popup_options = [
271			'dstfrm' => $user_form->getName(),
272			'media' => $index,
273			'mediatypeid' => $media['mediatypeid'],
274			($media['mediatype'] == MEDIA_TYPE_EMAIL) ? 'sendto_emails' : 'sendto' => $media['sendto'],
275			'period' => $media['period'],
276			'severity' => $media['severity'],
277			'active' => $media['active']
278		];
279
280
281		$media_severity = [];
282
283		for ($severity = TRIGGER_SEVERITY_NOT_CLASSIFIED; $severity < TRIGGER_SEVERITY_COUNT; $severity++) {
284			$severity_name = getSeverityName($severity);
285
286			$media_active = ($media['severity'] & (1 << $severity));
287
288			$media_severity[$severity] = (new CSpan(mb_substr($severity_name, 0, 1)))
289				->setHint($severity_name.' ('.($media_active ? _('on') : _('off')).')', '', false)
290				->addClass($media_active ? getSeverityStatusStyle($severity) : ZBX_STYLE_STATUS_DISABLED_BG);
291		}
292
293		if ($media['mediatype'] == MEDIA_TYPE_EMAIL) {
294			$media['sendto'] = implode(', ', $media['sendto']);
295		}
296
297		if (mb_strlen($media['sendto']) > 50) {
298			$media['sendto'] = (new CSpan(mb_substr($media['sendto'], 0, 50).'...'))->setHint($media['sendto']);
299		}
300
301		$media_table_info->addRow(
302			(new CRow([
303				$media['name'],
304				$media['sendto'],
305				(new CDiv($media['period']))
306					->setAttribute('style', 'max-width: '.ZBX_TEXTAREA_STANDARD_WIDTH.'px;')
307					->addClass(ZBX_STYLE_OVERFLOW_ELLIPSIS),
308				(new CDiv($media_severity))->addClass(ZBX_STYLE_STATUS_CONTAINER),
309				$status,
310				(new CCol(
311					new CHorList([
312						(new CButton(null, _('Edit')))
313							->addClass(ZBX_STYLE_BTN_LINK)
314							->onClick('return PopUp("popup.media",'.json_encode($popup_options).', null, this);'),
315						(new CButton(null, _('Remove')))
316							->addClass(ZBX_STYLE_BTN_LINK)
317							->onClick('javascript: removeMedia('.$index.');')
318					])
319				))->addClass(ZBX_STYLE_NOWRAP)
320			]))->setId('medias_'.$index)
321		);
322	}
323
324	$media_form_list->addRow(_('Media'),
325		(new CDiv([
326			$media_table_info,
327			(new CButton(null, _('Add')))
328				->onClick('return PopUp("popup.media",'.
329					json_encode([
330						'dstfrm' => $user_form->getName()
331					]).', null, this);'
332				)
333				->addClass(ZBX_STYLE_BTN_LINK)
334		]))
335			->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
336			->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
337	);
338
339	$tabs->addTab('mediaTab', _('Media'), $media_form_list, TAB_INDICATOR_MEDIA);
340}
341
342// Permissions tab.
343if ($data['action'] === 'user.edit') {
344	$permissions_form_list = new CFormList('permissionsFormList');
345
346	$role_multiselect = (new CMultiSelect([
347		'name' => 'roleid',
348		'object_name' => 'roles',
349		'data' => $data['role'],
350		'multiple' => false,
351		'disabled' => $data['userid'] != 0 && bccomp(CWebUser::$data['userid'], $data['userid']) == 0,
352		'popup' => [
353			'parameters' => [
354				'srctbl' => 'roles',
355				'srcfld1' => 'roleid',
356				'dstfrm' => 'user_form',
357				'dstfld1' => 'roleid'
358			]
359		]
360	]))->setWidth(ZBX_TEXTAREA_MEDIUM_WIDTH);
361
362	if ($data['userid'] != 0 && bccomp(CWebUser::$data['userid'], $data['userid']) == 0) {
363		$permissions_form_list->addRow((new CLabel(_('Role')))->setAsteriskMark(),
364			(new CDiv([
365				$role_multiselect,
366				new CDiv(_('User cannot change own role.'))
367			]))
368				->setWidth(ZBX_TEXTAREA_BIG_WIDTH)
369				->addClass('multiselect-description-container')
370		);
371	}
372	else {
373		$permissions_form_list->addRow((new CLabel(_('Role')))->setAsteriskMark(), $role_multiselect);
374	}
375
376	if ($data['roleid']) {
377		$permissions_form_list->addRow(_('User type'),
378			new CTextBox('user_type', user_type2str($data['user_type']), true)
379		);
380
381		$permissions_table = (new CTable())
382			->setAttribute('style', 'width: 100%;')
383			->setHeader([_('Host group'), _('Permissions')]);
384
385		if ($data['user_type'] == USER_TYPE_SUPER_ADMIN) {
386			$permissions_table->addRow([italic(_('All groups')), permissionText(PERM_READ_WRITE)]);
387		}
388		else {
389			foreach ($data['groups_rights'] as $groupid => $group_rights) {
390				if (array_key_exists('grouped', $group_rights) && $group_rights['grouped']) {
391					$group_name = ($groupid == 0)
392						? italic(_('All groups'))
393						: [$group_rights['name'], SPACE, italic('('._('including subgroups').')')];
394				}
395				else {
396					$group_name = $group_rights['name'];
397				}
398				$permissions_table->addRow([$group_name, permissionText($group_rights['permission'])]);
399			}
400		}
401
402		$permissions_form_list
403			->addRow(_('Permissions'),
404				(new CDiv($permissions_table))
405					->addClass(ZBX_STYLE_TABLE_FORMS_SEPARATOR)
406					->setAttribute('style', 'min-width: '.ZBX_TEXTAREA_BIG_WIDTH.'px;')
407			)
408			->addInfo(_('Permissions can be assigned for user groups only.'));
409
410		$permissions_form_list
411			->addRow((new CTag('h4', true, _('Access to UI elements')))->addClass('input-section-header'));
412
413		foreach (CRoleHelper::getUiSectionsLabels($data['user_type']) as $section_name => $section_label) {
414			$elements = [];
415
416			foreach (CRoleHelper::getUiSectionRulesLabels($section_name, $data['user_type']) as $rule_name => $rule_label) {
417				$elements[] = (new CSpan($rule_label))->addClass(
418					CRoleHelper::checkAccess($rule_name, $data['roleid']) ? ZBX_STYLE_STATUS_GREEN : ZBX_STYLE_STATUS_GREY
419				);
420			}
421
422			if ($elements) {
423				$permissions_form_list->addRow($section_label, (new CDiv($elements))
424					->setWidth(ZBX_TEXTAREA_BIG_WIDTH)
425					->addClass('rules-status-container')
426				);
427			}
428		}
429
430		$permissions_form_list->addRow((new CTag('h4', true, _('Access to modules')))->addClass('input-section-header'));
431
432		if (!$data['modules']) {
433			$permissions_form_list->addRow(italic(_('No enabled modules found.')));
434		}
435		else {
436			$elements = [];
437
438			foreach ($data['modules'] as $moduleid => $module) {
439				$elements[] = (new CSpan($module['id']))->addClass(
440					CRoleHelper::checkAccess(CRoleHelper::MODULES_MODULE.$moduleid, $data['roleid'])
441						? ZBX_STYLE_STATUS_GREEN
442						: ZBX_STYLE_STATUS_GREY
443				);
444			}
445
446			if ($elements) {
447				$permissions_form_list->addRow((new CDiv($elements))
448					->setWidth(ZBX_TEXTAREA_BIG_WIDTH)
449					->addClass('rules-status-container')
450				);
451			}
452		}
453
454		$api_access_enabled = CRoleHelper::checkAccess(CRoleHelper::API_ACCESS, $data['roleid']);
455		$permissions_form_list
456			->addRow((new CTag('h4', true, _('Access to API')))->addClass('input-section-header'))
457			->addRow((new CDiv((new CSpan($api_access_enabled ? _('Enabled') : _('Disabled')))->addClass(
458					$api_access_enabled ? ZBX_STYLE_STATUS_GREEN : ZBX_STYLE_STATUS_GREY
459				)))
460				->setWidth(ZBX_TEXTAREA_BIG_WIDTH)
461				->addClass('rules-status-container')
462			);
463
464		$api_methods = CRoleHelper::getRoleApiMethods($data['roleid']);
465
466		if ($api_methods) {
467			$api_access_mode_allowed = CRoleHelper::checkAccess(CRoleHelper::API_MODE, $data['roleid']);
468			$elements = [];
469
470			foreach ($api_methods as $api_method) {
471				$elements[] = (new CSpan($api_method))->addClass(
472					$api_access_mode_allowed ? ZBX_STYLE_STATUS_GREEN : ZBX_STYLE_STATUS_GREY
473				);
474			}
475
476			$permissions_form_list->addRow($api_access_mode_allowed ? _('Allowed methods') : _('Denied methods'),
477				(new CDiv($elements))
478					->setWidth(ZBX_TEXTAREA_BIG_WIDTH)
479					->addClass('rules-status-container')
480			);
481		}
482
483		$permissions_form_list->addRow((new CTag('h4', true, _('Access to actions')))->addClass('input-section-header'));
484		$elements = [];
485
486		foreach (CRoleHelper::getActionsLabels($data['user_type']) as $rule_name => $rule_label) {
487			$elements[] = (new CSpan($rule_label))
488				->addClass(CRoleHelper::checkAccess($rule_name, $data['roleid'])
489					? ZBX_STYLE_STATUS_GREEN
490					: ZBX_STYLE_STATUS_GREY
491				);
492		}
493
494		$permissions_form_list->addRow((new CDiv($elements))
495			->setWidth(ZBX_TEXTAREA_BIG_WIDTH)
496			->addClass('rules-status-container')
497		);
498	}
499
500	$tabs->addTab('permissionsTab', _('Permissions'), $permissions_form_list);
501}
502
503// Messaging tab.
504if ($data['action'] !== 'user.edit') {
505	$messaging_form_list = (new CFormList())
506		->addRow(_('Frontend messaging'),
507			(new CCheckBox('messages[enabled]'))
508				->setChecked($data['messages']['enabled'] == 1)
509				->setUncheckedValue(0)
510		)
511		->addRow(_('Message timeout'),
512			(new CTextBox('messages[timeout]', $data['messages']['timeout']))->setWidth(ZBX_TEXTAREA_TINY_WIDTH),
513			'timeout_row'
514		)
515		->addRow(new CLabel(_('Play sound'), 'label-sounds'),
516			(new CSelect('messages[sounds.repeat]'))
517				->setId('messages_sounds.repeat')
518				->setFocusableElementId('label-sounds')
519				->setValue($data['messages']['sounds.repeat'])
520				->addOptions(CSelect::createOptionsFromArray([
521					1 => _('Once'),
522					10 => _n('%1$s second', '%1$s seconds', 10),
523					-1 => _('Message timeout')
524				])),
525			'repeat_row'
526		);
527
528	$zbx_sounds = array_flip(getSounds());
529
530	$triggers_table = (new CTable())
531		->addRow([
532			(new CCheckBox('messages[triggers.recovery]'))
533				->setLabel(_('Recovery'))
534				->setChecked($data['messages']['triggers.recovery'] == 1)
535				->setUncheckedValue(0),
536			[
537				(new CSelect('messages[sounds.recovery]'))
538					->setId('messages_sounds.recovery')
539					->setValue($data['messages']['sounds.recovery'])
540					->addOptions(CSelect::createOptionsFromArray($zbx_sounds)),
541				(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
542				(new CButton('start', _('Play')))
543					->addClass(ZBX_STYLE_BTN_GREY)
544					->onClick("javascript: testUserSound('messages_sounds.recovery');")
545					->removeId(),
546				(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
547				(new CButton('stop', _('Stop')))
548					->addClass(ZBX_STYLE_BTN_GREY)
549					->onClick('javascript: AudioControl.stop();')
550					->removeId()
551			]
552		]);
553
554	$msg_visibility = ['1' => [
555		'messages[timeout]',
556		'messages[sounds.repeat]',
557		'messages[sounds.recovery]',
558		'messages[triggers.recovery]',
559		'timeout_row',
560		'repeat_row',
561		'triggers_row'
562	]];
563
564	// trigger sounds
565	for ($severity = TRIGGER_SEVERITY_NOT_CLASSIFIED; $severity < TRIGGER_SEVERITY_COUNT; $severity++) {
566		$triggers_table->addRow([
567			(new CCheckBox('messages[triggers.severities]['.$severity.']'))
568				->setLabel(getSeverityName($severity))
569				->setChecked(array_key_exists($severity, $data['messages']['triggers.severities']))
570				->setUncheckedValue(0),
571			[
572				(new CSelect('messages[sounds.'.$severity.']'))
573					->setId('messages_sounds.'.$severity)
574					->setValue($data['messages']['sounds.'.$severity])
575					->addOptions(CSelect::createOptionsFromArray($zbx_sounds)),
576				(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
577				(new CButton('start', _('Play')))
578					->addClass(ZBX_STYLE_BTN_GREY)
579					->onClick("javascript: testUserSound('messages_sounds.".$severity."');")
580					->removeId(),
581				(new CDiv())->addClass(ZBX_STYLE_FORM_INPUT_MARGIN),
582				(new CButton('stop', _('Stop')))
583					->addClass(ZBX_STYLE_BTN_GREY)
584					->onClick('javascript: AudioControl.stop();')
585					->removeId()
586			]
587		]);
588
589		zbx_subarray_push($msg_visibility, 1, 'messages[triggers.severities]['.$severity.']');
590		zbx_subarray_push($msg_visibility, 1, 'messages[sounds.'.$severity.']');
591	}
592
593	$messaging_form_list
594		->addRow(_('Trigger severity'), $triggers_table, 'triggers_row')
595		->addRow(_('Show suppressed problems'),
596			(new CCheckBox('messages[show_suppressed]'))
597				->setChecked($data['messages']['show_suppressed'] == ZBX_PROBLEM_SUPPRESSED_TRUE)
598				->setUncheckedValue(ZBX_PROBLEM_SUPPRESSED_FALSE)
599		);
600
601	$tabs->addTab('messagingTab', _('Messaging'), $messaging_form_list, TAB_INDICATOR_FRONTEND_MESSAGE);
602}
603
604// Append buttons to form.
605if ($data['action'] === 'user.edit') {
606	$cancel_button = (new CRedirectButton(_('Cancel'), (new CUrl('zabbix.php'))
607		->setArgument('action', 'user.list')
608		->setArgument('page', CPagerHelper::loadPage('user.list', null))
609	))->setId('cancel');
610
611	if ($data['userid'] != 0) {
612		$tabs->setFooter(makeFormFooter(
613			(new CSubmitButton(_('Update'), 'action', 'user.update'))->setId('update'),
614			[
615				(new CRedirectButton(_('Delete'),
616					'zabbix.php?action=user.delete&sid='.$data['sid'].'&userids[]='.$data['userid'],
617					_('Delete selected user?')
618				))
619					->setEnabled(bccomp(CWebUser::$data['userid'], $data['userid']) != 0)
620					->setId('delete'),
621				$cancel_button
622			]
623		));
624	}
625	else {
626		$tabs->setFooter(makeFormFooter(
627			(new CSubmitButton(_('Add'), 'action', 'user.create'))->setId('add'),
628			[
629				$cancel_button
630			]
631		));
632	}
633}
634else {
635	$tabs->setFooter(makeFormFooter(
636		(new CSubmitButton(_('Update'), 'action', 'userprofile.update'))->setId('update'),
637		[(new CRedirectButton(_('Cancel'), CMenuHelper::getFirstUrl()))->setId('cancel')]
638	));
639}
640
641// Append tab to form.
642$user_form->addItem($tabs);
643$widget
644	->addItem($user_form)
645	->show();
646