setName('form_config_preferences'); $this->setSubmitLabel($this->translate('Save to the Preferences')); } /** * Set preferences to work with * * @param Preferences $preferences The preferences to work with * * @return $this */ public function setPreferences(Preferences $preferences) { $this->preferences = $preferences; return $this; } /** * Set the preference store to use * * @param PreferencesStore $store The preference store to use * * @return $this */ public function setStore(PreferencesStore $store) { $this->store = $store; return $this; } /** * Persist preferences * * @return $this */ public function save() { $this->store->save($this->preferences); return $this; } /** * Adjust preferences and persist them * * @see Form::onSuccess() */ public function onSuccess() { $currentPreferences = $this->Auth()->getUser()->getPreferences(); $oldTheme = $currentPreferences->getValue('icingaweb', 'theme'); $oldMode = $currentPreferences->getValue('icingaweb', 'theme_mode'); $oldLocale = $currentPreferences->getValue('icingaweb', 'language'); $defaultTheme = Config::app()->get('themes', 'default', StyleSheet::DEFAULT_THEME); $this->preferences = new Preferences($this->store ? $this->store->load() : array()); $webPreferences = $this->preferences->get('icingaweb'); foreach ($this->getValues() as $key => $value) { if ($value === '' || $value === null || $value === 'autodetect' || ($key === 'theme' && $value === $defaultTheme) ) { if (isset($webPreferences[$key])) { unset($webPreferences[$key]); } } else { $webPreferences[$key] = $value; } } $this->preferences->icingaweb = $webPreferences; Session::getSession()->user->setPreferences($this->preferences); if ((($theme = $this->getElement('theme')) !== null && ($theme = $theme->getValue()) !== $oldTheme && ($theme !== $defaultTheme || $oldTheme !== null)) || (($mode = $this->getElement('theme_mode')) !== null && ($mode->getValue()) !== $oldMode) ) { $this->getResponse()->setReloadCss(true); } if (($locale = $this->getElement('language')) !== null && $locale->getValue() !== 'autodetect' && $locale->getValue() !== $oldLocale ) { $this->getResponse()->setHeader('X-Icinga-Redirect-Http', 'yes'); } try { if ($this->store && $this->getElement('btn_submit')->isChecked()) { $this->save(); Notification::success($this->translate('Preferences successfully saved')); } else { Notification::success($this->translate('Preferences successfully saved for the current session')); } } catch (Exception $e) { Logger::error($e); Notification::error($e->getMessage()); } } /** * Populate preferences * * @see Form::onRequest() */ public function onRequest() { $auth = Auth::getInstance(); $values = $auth->getUser()->getPreferences()->get('icingaweb'); if (! isset($values['language'])) { $values['language'] = 'autodetect'; } if (! isset($values['timezone'])) { $values['timezone'] = 'autodetect'; } if (! isset($values['auto_refresh'])) { $values['auto_refresh'] = '1'; } $this->populate($values); } /** * @see Form::createElements() */ public function createElements(array $formData) { if (setlocale(LC_ALL, 0) === 'C') { $this->warning( $this->translate( 'Your language setting is not applied because your platform is missing the corresponding locale.' . ' Make sure to install the correct language pack and restart your web server afterwards.' ), false ); } $themeFile = StyleSheet::getThemeFile(Config::app()->get('themes', 'default')); if (! (bool) Config::app()->get('themes', 'disabled', false)) { $themes = Icinga::app()->getThemes(); if (count($themes) > 1) { $defaultTheme = Config::app()->get('themes', 'default', StyleSheet::DEFAULT_THEME); if (isset($themes[$defaultTheme])) { $themes[$defaultTheme] .= ' (' . $this->translate('default') . ')'; } $this->addElement( 'select', 'theme', array( 'label' => $this->translate('Theme', 'Form element label'), 'multiOptions' => $themes, 'autosubmit' => true, 'value' => $this->preferences->getValue( 'icingaweb', 'theme', $defaultTheme ) ) ); } } if (isset($formData['theme'])) { $themeFile = StyleSheet::getThemeFile($formData['theme']); } $disabled = []; if ($themeFile !== null) { $file = @file_get_contents($themeFile); if ($file && strpos($file, StyleSheet::LIGHT_MODE_IDENTIFIER) === false) { $disabled = ['', 'light', 'system']; } } $this->addElement( 'radio', 'theme_mode', [ 'class' => 'theme-mode-input', 'label' => $this->translate('Theme Mode'), 'multiOptions' => [ '' => HtmlElement::create( 'img', ['src' => $this->getView()->href('img/theme-mode-thumbnail-dark.svg')] ) . HtmlElement::create('span', [], $this->translate('Dark')), 'light' => HtmlElement::create( 'img', ['src' => $this->getView()->href('img/theme-mode-thumbnail-light.svg')] ) . HtmlElement::create('span', [], $this->translate('Light')), 'system' => HtmlElement::create( 'img', ['src' => $this->getView()->href('img/theme-mode-thumbnail-system.svg')] ) . HtmlElement::create('span', [], $this->translate('System')) ], 'disable' => $disabled, 'escape' => false, 'decorators' => array_merge( array_slice(self::$defaultElementDecorators, 0, -1), [['HtmlTag', ['tag' => 'div', 'class' => 'control-group theme-mode']]] ) ] ); /** @var GettextTranslator $translator */ $translator = StaticTranslator::$instance; $languages = array(); $availableLocales = $translator->listLocales(); $locale = $this->getLocale($availableLocales); if ($locale !== null) { $languages['autodetect'] = sprintf($this->translate('Browser (%s)', 'preferences.form'), $locale); } $availableLocales[] = $translator->getDefaultLocale(); foreach ($availableLocales as $language) { $languages[$language] = $language; } $tzList = array(); $tzList['autodetect'] = sprintf( $this->translate('Browser (%s)', 'preferences.form'), $this->getDefaultTimezone() ); foreach (DateTimeZone::listIdentifiers() as $tz) { $tzList[$tz] = $tz; } $this->addElement( 'select', 'language', array( 'required' => true, 'label' => $this->translate('Your Current Language'), 'description' => $this->translate('Use the following language to display texts and messages'), 'multiOptions' => $languages, 'value' => substr(setlocale(LC_ALL, 0), 0, 5) ) ); $this->addElement( 'select', 'timezone', array( 'required' => true, 'label' => $this->translate('Your Current Timezone'), 'description' => $this->translate('Use the following timezone for dates and times'), 'multiOptions' => $tzList, 'value' => $this->getDefaultTimezone() ) ); $this->addElement( 'select', 'show_application_state_messages', array( 'required' => true, 'label' => $this->translate('Show application state messages'), 'description' => $this->translate('Whether to show application state messages.'), 'multiOptions' => [ 'system' => (bool) Config::app()->get('global', 'show_application_state_messages', true) ? $this->translate('System (Yes)') : $this->translate('System (No)'), 1 => $this->translate('Yes'), 0 => $this->translate('No')], 'value' => 'system' ) ); if (Auth::getInstance()->hasPermission('user/application/stacktraces')) { $this->addElement( 'checkbox', 'show_stacktraces', array( 'value' => $this->getDefaultShowStacktraces(), 'label' => $this->translate('Show Stacktraces'), 'description' => $this->translate('Set whether to show an exception\'s stacktrace.') ) ); } $this->addElement( 'checkbox', 'show_benchmark', array( 'label' => $this->translate('Use benchmark') ) ); $this->addElement( 'checkbox', 'auto_refresh', array( 'required' => false, 'autosubmit' => true, 'label' => $this->translate('Enable auto refresh'), 'description' => $this->translate( 'This option allows you to enable or to disable the global page content auto refresh' ), 'value' => 1 ) ); if (isset($formData['auto_refresh']) && $formData['auto_refresh']) { $this->addElement( 'select', 'auto_refresh_speed', [ 'required' => false, 'label' => $this->translate('Auto refresh speed'), 'description' => $this->translate( 'This option allows you to speed up or to slow down the global page content auto refresh' ), 'multiOptions' => [ '0.5' => $this->translate('Fast', 'refresh_speed'), '' => $this->translate('Default', 'refresh_speed'), '2' => $this->translate('Moderate', 'refresh_speed'), '4' => $this->translate('Slow', 'refresh_speed') ], 'value' => '' ] ); } $this->addElement( 'number', 'default_page_size', array( 'label' => $this->translate('Default page size'), 'description' => $this->translate('Default number of items per page for list views'), 'placeholder' => 25, 'min' => 25, 'step' => 1 ) ); if ($this->store) { $this->addElement( 'submit', 'btn_submit', array( 'ignore' => true, 'label' => $this->translate('Save to the Preferences'), 'decorators' => array('ViewHelper'), 'class' => 'btn-primary' ) ); } $this->addElement( 'submit', 'btn_submit_session', array( 'ignore' => true, 'label' => $this->translate('Save for the current Session'), 'decorators' => array('ViewHelper') ) ); $this->setAttrib('data-progress-element', 'preferences-progress'); $this->addElement( 'note', 'preferences-progress', array( 'decorators' => array( 'ViewHelper', array('Spinner', array('id' => 'preferences-progress')) ) ) ); $this->addDisplayGroup( array('btn_submit', 'btn_submit_session', 'preferences-progress'), 'submit_buttons', array( 'decorators' => array( 'FormElements', array('HtmlTag', array('tag' => 'div', 'class' => 'control-group form-controls')) ) ) ); } public function addSubmitButton() { return $this; } public function isSubmitted() { if (parent::isSubmitted()) { return true; } return $this->getElement('btn_submit_session')->isChecked(); } /** * Return the current default timezone * * @return string */ protected function getDefaultTimezone() { $detect = new TimezoneDetect(); if ($detect->success()) { return $detect->getTimezoneName(); } else { return @date_default_timezone_get(); } } /** * Return the preferred locale based on the given HTTP header and the available translations * * @return string|null */ protected function getLocale($availableLocales) { return isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? (new Locale())->getPreferred($_SERVER['HTTP_ACCEPT_LANGUAGE'], $availableLocales) : null; } /** * Return the default global setting for show_stacktraces * * @return bool */ protected function getDefaultShowStacktraces() { return Config::app()->get('global', 'show_stacktraces', true); } }