commit
f3ae7357d7
|
@ -25,9 +25,9 @@ class PreferenceController extends BasePreferenceController
|
|||
public static function createProvidedTabs()
|
||||
{
|
||||
return array(
|
||||
'general' => new Tab(
|
||||
'preferences' => new Tab(
|
||||
array(
|
||||
'title' => 'General settings',
|
||||
'title' => t('Preferences'),
|
||||
'url' => Url::fromPath('/preference')
|
||||
)
|
||||
)
|
||||
|
@ -51,6 +51,6 @@ class PreferenceController extends BasePreferenceController
|
|||
$form->handleRequest();
|
||||
|
||||
$this->view->form = $form;
|
||||
$this->getTabs()->activate('general');
|
||||
$this->getTabs()->activate('preferences');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,44 +29,6 @@ class ApplicationConfigForm extends Form
|
|||
*/
|
||||
public function createElements(array $formData)
|
||||
{
|
||||
$languages = array();
|
||||
foreach (Translator::getAvailableLocaleCodes() as $language) {
|
||||
$languages[$language] = $language;
|
||||
}
|
||||
|
||||
$this->addElement(
|
||||
'select',
|
||||
'global_language',
|
||||
array(
|
||||
'label' => t('Default Language'),
|
||||
'required' => true,
|
||||
'multiOptions' => $languages,
|
||||
'description' => t(
|
||||
'Select the language to use by default. Can be overwritten by a user in his preferences.'
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$tzList = array();
|
||||
foreach (DateTimeZone::listIdentifiers() as $tz) {
|
||||
$tzList[$tz] = $tz;
|
||||
}
|
||||
|
||||
$this->addElement(
|
||||
'select',
|
||||
'global_timezone',
|
||||
array(
|
||||
'label' => t('Default Application Timezone'),
|
||||
'required' => true,
|
||||
'multiOptions' => $tzList,
|
||||
'description' => t(
|
||||
'Select the timezone to be used as the default. User\'s can set their own timezone if'
|
||||
. ' they like to, but this is the timezone to be used as the default setting .'
|
||||
),
|
||||
'value' => date_default_timezone_get()
|
||||
)
|
||||
);
|
||||
|
||||
$this->addElement(
|
||||
'text',
|
||||
'global_modulePath',
|
||||
|
|
|
@ -7,10 +7,12 @@ namespace Icinga\Form;
|
|||
use Exception;
|
||||
use DateTimeZone;
|
||||
use Icinga\Application\Logger;
|
||||
use Icinga\Authentication\Manager;
|
||||
use Icinga\User\Preferences;
|
||||
use Icinga\User\Preferences\PreferencesStore;
|
||||
use Icinga\Util\TimezoneDetect;
|
||||
use Icinga\Util\Translator;
|
||||
use Icinga\Web\Controller\ControllerTabCollector;
|
||||
use Icinga\Web\Form;
|
||||
use Icinga\Web\Notification;
|
||||
use Icinga\Web\Request;
|
||||
|
@ -41,7 +43,6 @@ class PreferenceForm extends Form
|
|||
public function init()
|
||||
{
|
||||
$this->setName('form_config_preferences');
|
||||
$this->setSubmitLabel(t('Save Changes'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -76,7 +77,6 @@ class PreferenceForm extends Form
|
|||
*/
|
||||
public function save()
|
||||
{
|
||||
$this->store->load(); // Necessary for patching existing preferences
|
||||
$this->store->save($this->preferences);
|
||||
return $this;
|
||||
}
|
||||
|
@ -88,9 +88,11 @@ class PreferenceForm extends Form
|
|||
*/
|
||||
public function onSuccess(Request $request)
|
||||
{
|
||||
$this->preferences = new Preferences($this->store->load());
|
||||
|
||||
$webPreferences = $this->preferences->get('icingaweb', array());
|
||||
foreach ($this->getValues() as $key => $value) {
|
||||
if ($value === null) {
|
||||
if ($value === null || $value === 'autodetect') {
|
||||
if (isset($webPreferences[$key])) {
|
||||
unset($webPreferences[$key]);
|
||||
}
|
||||
|
@ -103,8 +105,12 @@ class PreferenceForm extends Form
|
|||
Session::getSession()->user->setPreferences($this->preferences);
|
||||
|
||||
try {
|
||||
$this->save();
|
||||
Notification::success(t('Preferences successfully saved'));
|
||||
if ($this->getElement('btn_submit_preferences')->isChecked()) {
|
||||
$this->save();
|
||||
Notification::success(t('Preferences successfully saved'));
|
||||
} else {
|
||||
Notification::success(t('Preferences successfully saved for the current session'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Logger::error($e);
|
||||
Notification::error($e->getMessage());
|
||||
|
@ -118,9 +124,17 @@ class PreferenceForm extends Form
|
|||
*/
|
||||
public function onRequest(Request $request)
|
||||
{
|
||||
$values = $this->preferences->get('icingaweb', array());
|
||||
$values['browser_language'] = false === isset($values['language']);
|
||||
$values['local_timezone'] = false === isset($values['timezone']);
|
||||
$auth = Manager::getInstance();
|
||||
$values = $auth->getUser()->getPreferences()->get('icingaweb');
|
||||
|
||||
if (! isset($values['language'])) {
|
||||
$values['language'] = 'autodetect';
|
||||
}
|
||||
|
||||
if (! isset($values['timezone'])) {
|
||||
$values['timezone'] = 'autodetect';
|
||||
}
|
||||
|
||||
$this->populate($values);
|
||||
}
|
||||
|
||||
|
@ -130,72 +144,40 @@ class PreferenceForm extends Form
|
|||
public function createElements(array $formData)
|
||||
{
|
||||
$languages = array();
|
||||
$languages['autodetect'] = sprintf(t('Browser (%s)', 'preferences.form'), $this->getLocale());
|
||||
foreach (Translator::getAvailableLocaleCodes() as $language) {
|
||||
$languages[$language] = $language;
|
||||
}
|
||||
|
||||
$tzList = array();
|
||||
$tzList['autodetect'] = sprintf(t('Browser (%s)', 'preferences.form'), $this->getDefaultTimezone());
|
||||
foreach (DateTimeZone::listIdentifiers() as $tz) {
|
||||
$tzList[$tz] = $tz;
|
||||
}
|
||||
|
||||
$this->addElement(
|
||||
'checkbox',
|
||||
'browser_language',
|
||||
array(
|
||||
'ignore' => true,
|
||||
'required' => true,
|
||||
'autosubmit' => true,
|
||||
'value' => true,
|
||||
'label' => t('Use your browser\'s language suggestions')
|
||||
)
|
||||
);
|
||||
|
||||
$useBrowserLanguage = isset($formData['browser_language']) ? $formData['browser_language'] == 1 : true;
|
||||
$languageSelection = $this->createElement(
|
||||
'select',
|
||||
'language',
|
||||
array(
|
||||
'required' => false === $useBrowserLanguage,
|
||||
'required' => true,
|
||||
'label' => t('Your Current Language'),
|
||||
'description' => t('Use the following language to display texts and messages'),
|
||||
'multiOptions' => $languages,
|
||||
'value' => substr(setlocale(LC_ALL, 0), 0, 5)
|
||||
)
|
||||
);
|
||||
if ($useBrowserLanguage) {
|
||||
$languageSelection->setAttrib('disabled', 'disabled');
|
||||
}
|
||||
$this->addElement($languageSelection);
|
||||
|
||||
$this->addElement(
|
||||
'checkbox',
|
||||
'local_timezone',
|
||||
array(
|
||||
'ignore' => true,
|
||||
'required' => true,
|
||||
'autosubmit' => true,
|
||||
'value' => true,
|
||||
'label' => t('Use your local timezone')
|
||||
)
|
||||
);
|
||||
|
||||
$useLocalTimezone = isset($formData['local_timezone']) ? $formData['local_timezone'] == 1 : true;
|
||||
$timezoneSelection = $this->createElement(
|
||||
'select',
|
||||
'timezone',
|
||||
array(
|
||||
'required' => false === $useLocalTimezone,
|
||||
'required' => true,
|
||||
'label' => t('Your Current Timezone'),
|
||||
'description' => t('Use the following timezone for dates and times'),
|
||||
'multiOptions' => $tzList,
|
||||
'value' => $this->getDefaultTimezone()
|
||||
)
|
||||
);
|
||||
if ($useLocalTimezone) {
|
||||
$timezoneSelection->setAttrib('disabled', 'disabled');
|
||||
}
|
||||
$this->addElement($timezoneSelection);
|
||||
|
||||
$this->addElement(
|
||||
'checkbox',
|
||||
|
@ -205,6 +187,43 @@ class PreferenceForm extends Form
|
|||
'label' => t('Use benchmark')
|
||||
)
|
||||
);
|
||||
|
||||
$this->addElement(
|
||||
'submit',
|
||||
'btn_submit_preferences',
|
||||
array(
|
||||
'ignore' => true,
|
||||
'label' => t('Save to the Preferences'),
|
||||
'decorators' => array(
|
||||
'ViewHelper',
|
||||
array('HtmlTag', array('tag' => 'div'))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->addElement(
|
||||
'submit',
|
||||
'btn_submit_session',
|
||||
array(
|
||||
'ignore' => true,
|
||||
'label' => t('Save for the current Session'),
|
||||
'decorators' => array(
|
||||
'ViewHelper',
|
||||
array('HtmlTag', array('tag' => 'div'))
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
$this->addDisplayGroup(
|
||||
array('btn_submit_preferences', 'btn_submit_session'),
|
||||
'submit_buttons',
|
||||
array(
|
||||
'decorators' => array(
|
||||
'FormElements',
|
||||
array('HtmlTag', array('tag' => 'div', 'class' => 'control-group'))
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -221,4 +240,15 @@ class PreferenceForm extends Form
|
|||
return date_default_timezone_get();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the preferred locale based on the given HTTP header and the available translations
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getLocale()
|
||||
{
|
||||
$locale = Translator::getPreferredLocaleCode($_SERVER['HTTP_ACCEPT_LANGUAGE']);
|
||||
return $locale;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,10 @@ CREATE TABLE `icingaweb_user`(
|
|||
|
||||
CREATE TABLE `icingaweb_user_preference`(
|
||||
`username` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
|
||||
`section` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
|
||||
`name` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
|
||||
`value` varchar(255) NOT NULL,
|
||||
`ctime` timestamp NULL DEFAULT NULL,
|
||||
`mtime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`username`,`name`)
|
||||
PRIMARY KEY (`username`,`section`,`name`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
|
|
@ -13,7 +13,7 @@ use Icinga\Exception\NotReadableError;
|
|||
use Icinga\Application\Logger;
|
||||
use Icinga\Util\DateTimeFactory;
|
||||
use Icinga\Util\Translator;
|
||||
use Icinga\File\Ini\IniWriter;
|
||||
use Icinga\Util\TimezoneDetect;
|
||||
use Icinga\Exception\IcingaException;
|
||||
|
||||
/**
|
||||
|
@ -478,42 +478,62 @@ abstract class ApplicationBootstrap
|
|||
}
|
||||
|
||||
/**
|
||||
* Setup default timezone
|
||||
* Detect the timezone
|
||||
*
|
||||
* @return self
|
||||
* @throws ConfigurationError if the timezone in config.ini isn't valid
|
||||
* @return null|string
|
||||
*/
|
||||
protected function setupTimezone()
|
||||
protected function detectTimezone()
|
||||
{
|
||||
$default = @date_default_timezone_get();
|
||||
if (! $default) {
|
||||
$default = 'UTC';
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the timezone
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected final function setupTimezone()
|
||||
{
|
||||
$timezone = $this->detectTimeZone();
|
||||
if ($timezone === null || @date_default_timezone_set($timezone) === false) {
|
||||
$timezone = @date_default_timezone_get();
|
||||
if ($timezone === false) {
|
||||
$timezone = 'UTC';
|
||||
date_default_timezone_set($timezone);
|
||||
}
|
||||
}
|
||||
$timeZoneString = $this->config->fromSection('global', 'timezone', $default);
|
||||
date_default_timezone_set($timeZoneString);
|
||||
DateTimeFactory::setConfig(array('timezone' => $timeZoneString));
|
||||
DateTimeFactory::setConfig(array('timezone' => $timezone));
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup internationalization using gettext
|
||||
* Detect the locale
|
||||
*
|
||||
* Uses the preferred language sent by the browser or the default one
|
||||
*
|
||||
* @return self
|
||||
* @return null|string
|
||||
*/
|
||||
protected function setupInternationalization()
|
||||
protected function detectLocale()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up internationalization using gettext
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
protected final function setupInternationalization()
|
||||
{
|
||||
if ($this->hasLocales()) {
|
||||
Translator::registerDomain(Translator::DEFAULT_DOMAIN, $this->getLocaleDir());
|
||||
}
|
||||
|
||||
$locale = $this->detectLocale();
|
||||
if ($locale === null) {
|
||||
$locale = Translator::DEFAULT_LOCALE;
|
||||
}
|
||||
|
||||
try {
|
||||
Translator::setupLocale(
|
||||
isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])
|
||||
? Translator::getPreferredLocaleCode($_SERVER['HTTP_ACCEPT_LANGUAGE'])
|
||||
: Translator::DEFAULT_LOCALE
|
||||
);
|
||||
Translator::setupLocale($locale);
|
||||
} catch (Exception $error) {
|
||||
Logger::error($error);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace Icinga\Application;
|
|||
require_once __DIR__ . '/ApplicationBootstrap.php';
|
||||
|
||||
use Icinga\Authentication\Manager as AuthenticationManager;
|
||||
use Icinga\Authentication\Manager;
|
||||
use Icinga\Exception\ConfigurationError;
|
||||
use Icinga\Exception\NotReadableError;
|
||||
use Icinga\Application\Logger;
|
||||
|
@ -14,6 +15,8 @@ use Icinga\Util\TimezoneDetect;
|
|||
use Icinga\Web\Request;
|
||||
use Icinga\Web\Response;
|
||||
use Icinga\Web\View;
|
||||
use Icinga\Web\Session\Session as BaseSession;
|
||||
use Icinga\Web\Session;
|
||||
use Icinga\User;
|
||||
use Icinga\Util\Translator;
|
||||
use Icinga\Util\DateTimeFactory;
|
||||
|
@ -58,6 +61,13 @@ class Web extends ApplicationBootstrap
|
|||
*/
|
||||
private $request;
|
||||
|
||||
/**
|
||||
* Session object
|
||||
*
|
||||
* @var BaseSession
|
||||
*/
|
||||
private $session;
|
||||
|
||||
/**
|
||||
* User object
|
||||
*
|
||||
|
@ -84,6 +94,7 @@ class Web extends ApplicationBootstrap
|
|||
->setupErrorHandling()
|
||||
->loadConfig()
|
||||
->setupResourceFactory()
|
||||
->setupSession()
|
||||
->setupUser()
|
||||
->setupTimezone()
|
||||
->setupLogger()
|
||||
|
@ -164,6 +175,7 @@ class Web extends ApplicationBootstrap
|
|||
|
||||
$this->setupFrontController();
|
||||
$this->setupViewRenderer();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
@ -183,6 +195,17 @@ class Web extends ApplicationBootstrap
|
|||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a session provider
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
private function setupSession()
|
||||
{
|
||||
$this->session = Session::create();
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject dependencies into request
|
||||
*
|
||||
|
@ -268,29 +291,19 @@ class Web extends ApplicationBootstrap
|
|||
}
|
||||
|
||||
/**
|
||||
* Setup user timezone if set and valid, otherwise global default timezone
|
||||
*
|
||||
* @return self
|
||||
* @see ApplicationBootstrap::setupTimezone
|
||||
* (non-PHPDoc)
|
||||
* @see ApplicationBootstrap::detectTimezone() For the method documentation.
|
||||
*/
|
||||
protected function setupTimezone()
|
||||
protected function detectTimezone()
|
||||
{
|
||||
$userTimezone = null;
|
||||
|
||||
if ($this->user !== null && $this->user->getPreferences() !== null) {
|
||||
$auth = Manager::getInstance();
|
||||
if (! $auth->isAuthenticated()
|
||||
|| ($timezone = $auth->getUser()->getPreferences()->getValue('icingaweb', 'timezone')) === null
|
||||
) {
|
||||
$detect = new TimezoneDetect();
|
||||
$userTimezone = $this->user->getPreferences()
|
||||
->getValue('icingaweb', 'timezone', $detect->getTimezoneName());
|
||||
$timezone = $detect->getTimezoneName();
|
||||
}
|
||||
|
||||
try {
|
||||
DateTimeFactory::setConfig(array('timezone' => $userTimezone));
|
||||
date_default_timezone_set($userTimezone);
|
||||
} catch (ConfigurationError $e) {
|
||||
return parent::setupTimezone();
|
||||
}
|
||||
|
||||
return $this;
|
||||
return $timezone;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -300,22 +313,16 @@ class Web extends ApplicationBootstrap
|
|||
*
|
||||
* @return self
|
||||
*/
|
||||
protected function setupInternationalization()
|
||||
protected function detectLocale()
|
||||
{
|
||||
parent::setupInternationalization();
|
||||
if ($this->user !== null && $this->user->getPreferences() !== null
|
||||
&& (($locale = $this->user->getPreferences()->getValue('icingaweb', 'language')) !== null)
|
||||
$auth = Manager::getInstance();
|
||||
if (! $auth->isAuthenticated()
|
||||
|| ($locale = $auth->getUser()->getPreferences()->getValue('icingaweb', 'language')) === null
|
||||
&& isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])
|
||||
) {
|
||||
try {
|
||||
Translator::setupLocale($locale);
|
||||
} catch (Exception $error) {
|
||||
Logger::warning(
|
||||
'Cannot set locale "' . $locale . '" configured in ' .
|
||||
'preferences of user "' . $this->user->getUsername() . '"'
|
||||
);
|
||||
}
|
||||
$locale = Translator::getPreferredLocaleCode($_SERVER['HTTP_ACCEPT_LANGUAGE']);
|
||||
}
|
||||
return $this;
|
||||
return $locale;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,3 +339,4 @@ class Web extends ApplicationBootstrap
|
|||
return $this;
|
||||
}
|
||||
}
|
||||
// @codeCoverageIgnoreEnd
|
||||
|
|
|
@ -9,6 +9,7 @@ use Icinga\Exception\NotReadableError;
|
|||
use Icinga\Exception\NotWritableError;
|
||||
use Icinga\User\Preferences;
|
||||
use Icinga\User\Preferences\PreferencesStore;
|
||||
use Zend_Db_Expr;
|
||||
|
||||
/**
|
||||
* Load and save user preferences by using a database
|
||||
|
@ -20,22 +21,37 @@ class DbStore extends PreferencesStore
|
|||
*/
|
||||
const COLUMN_USERNAME = 'username';
|
||||
|
||||
/**
|
||||
* Column name for section
|
||||
*/
|
||||
const COLUMN_SECTION = 'section';
|
||||
|
||||
/**
|
||||
* Column name for preference
|
||||
*/
|
||||
const COLUMN_PREFERENCE = 'key';
|
||||
const COLUMN_PREFERENCE = 'name';
|
||||
|
||||
/**
|
||||
* Column name for value
|
||||
*/
|
||||
const COLUMN_VALUE = 'value';
|
||||
|
||||
/**
|
||||
* Column name for created time
|
||||
*/
|
||||
const COLUMN_CREATED_TIME = 'ctime';
|
||||
|
||||
/**
|
||||
* Column name for modified time
|
||||
*/
|
||||
const COLUMN_MODIFIED_TIME = 'mtime';
|
||||
|
||||
/**
|
||||
* Table name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $table = 'preference';
|
||||
protected $table = 'icingaweb_user_preference';
|
||||
|
||||
/**
|
||||
* Stored preferences
|
||||
|
@ -74,7 +90,7 @@ class DbStore extends PreferencesStore
|
|||
try {
|
||||
$select = $this->getStoreConfig()->connection->getDbAdapter()->select();
|
||||
$result = $select
|
||||
->from($this->table, array(self::COLUMN_PREFERENCE, self::COLUMN_VALUE))
|
||||
->from($this->table, array(self::COLUMN_SECTION, self::COLUMN_PREFERENCE, self::COLUMN_VALUE))
|
||||
->where(self::COLUMN_USERNAME . ' = ?', $this->getUser()->getUsername())
|
||||
->query()
|
||||
->fetchAll();
|
||||
|
@ -89,7 +105,7 @@ class DbStore extends PreferencesStore
|
|||
if ($result !== false) {
|
||||
$values = array();
|
||||
foreach ($result as $row) {
|
||||
$values[$row->{self::COLUMN_PREFERENCE}] = $row->{self::COLUMN_VALUE};
|
||||
$values[$row->{self::COLUMN_SECTION}][$row->{self::COLUMN_PREFERENCE}] = $row->{self::COLUMN_VALUE};
|
||||
}
|
||||
$this->preferences = $values;
|
||||
}
|
||||
|
@ -106,22 +122,32 @@ class DbStore extends PreferencesStore
|
|||
{
|
||||
$preferences = $preferences->toArray();
|
||||
|
||||
$toBeInserted = array_diff_key($preferences, $this->preferences);
|
||||
if (!empty($toBeInserted)) {
|
||||
$this->insert($toBeInserted);
|
||||
}
|
||||
$sections = array_keys($preferences);
|
||||
|
||||
$toBeUpdated = array_intersect_key(
|
||||
array_diff_assoc($preferences, $this->preferences),
|
||||
array_diff_assoc($this->preferences, $preferences)
|
||||
);
|
||||
if (!empty($toBeUpdated)) {
|
||||
$this->update($toBeUpdated);
|
||||
}
|
||||
foreach ($sections as $section) {
|
||||
if (! array_key_exists($section, $this->preferences)) {
|
||||
$this->preferences[$section] = array();
|
||||
}
|
||||
if (! array_key_exists($section, $preferences)) {
|
||||
$preferences[$section] = array();
|
||||
}
|
||||
$toBeInserted = array_diff_key($preferences[$section], $this->preferences[$section]);
|
||||
if (!empty($toBeInserted)) {
|
||||
$this->insert($toBeInserted, $section);
|
||||
}
|
||||
|
||||
$toBeDeleted = array_keys(array_diff_key($this->preferences, $preferences));
|
||||
if (!empty($toBeDeleted)) {
|
||||
$this->delete($toBeDeleted);
|
||||
$toBeUpdated = array_intersect_key(
|
||||
array_diff_assoc($preferences[$section], $this->preferences[$section]),
|
||||
array_diff_assoc($this->preferences[$section], $preferences[$section])
|
||||
);
|
||||
if (!empty($toBeUpdated)) {
|
||||
$this->update($toBeUpdated, $section);
|
||||
}
|
||||
|
||||
$toBeDeleted = array_keys(array_diff_key($this->preferences[$section], $preferences[$section]));
|
||||
if (!empty($toBeDeleted)) {
|
||||
$this->delete($toBeDeleted, $section);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,11 +155,13 @@ class DbStore extends PreferencesStore
|
|||
* Insert the given preferences into the database
|
||||
*
|
||||
* @param array $preferences The preferences to insert
|
||||
* @param string $section The preferences in section to update
|
||||
*
|
||||
* @throws NotWritableError In case the database operation failed
|
||||
*/
|
||||
protected function insert(array $preferences)
|
||||
protected function insert(array $preferences, $section)
|
||||
{
|
||||
/** @var \Zend_Db_Adapter_Abstract $db */
|
||||
$db = $this->getStoreConfig()->connection->getDbAdapter();
|
||||
|
||||
try {
|
||||
|
@ -142,8 +170,11 @@ class DbStore extends PreferencesStore
|
|||
$this->table,
|
||||
array(
|
||||
self::COLUMN_USERNAME => $this->getUser()->getUsername(),
|
||||
$db->quoteIdentifier(self::COLUMN_SECTION) => $section,
|
||||
$db->quoteIdentifier(self::COLUMN_PREFERENCE) => $key,
|
||||
self::COLUMN_VALUE => $value
|
||||
self::COLUMN_VALUE => $value,
|
||||
self::COLUMN_CREATED_TIME => new Zend_Db_Expr('NOW()'),
|
||||
self::COLUMN_MODIFIED_TIME => new Zend_Db_Expr('NOW()')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -160,11 +191,13 @@ class DbStore extends PreferencesStore
|
|||
* Update the given preferences in the database
|
||||
*
|
||||
* @param array $preferences The preferences to update
|
||||
* @param string $section The preferences in section to update
|
||||
*
|
||||
* @throws NotWritableError In case the database operation failed
|
||||
*/
|
||||
protected function update(array $preferences)
|
||||
protected function update(array $preferences, $section)
|
||||
{
|
||||
/** @var \Zend_Db_Adapter_Abstract $db */
|
||||
$db = $this->getStoreConfig()->connection->getDbAdapter();
|
||||
|
||||
try {
|
||||
|
@ -174,7 +207,9 @@ class DbStore extends PreferencesStore
|
|||
array(self::COLUMN_VALUE => $value),
|
||||
array(
|
||||
self::COLUMN_USERNAME . '=?' => $this->getUser()->getUsername(),
|
||||
$db->quoteIdentifier(self::COLUMN_PREFERENCE) . '=?' => $key
|
||||
$db->quoteIdentifier(self::COLUMN_SECTION) . '=?' => $section,
|
||||
$db->quoteIdentifier(self::COLUMN_PREFERENCE) . '=?' => $key,
|
||||
self::COLUMN_MODIFIED_TIME => new Zend_Db_Expr('NOW()')
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -191,11 +226,13 @@ class DbStore extends PreferencesStore
|
|||
* Delete the given preference names from the database
|
||||
*
|
||||
* @param array $preferenceKeys The preference names to delete
|
||||
* @param string $section The preferences in section to update
|
||||
*
|
||||
* @throws NotWritableError In case the database operation failed
|
||||
*/
|
||||
protected function delete(array $preferenceKeys)
|
||||
protected function delete(array $preferenceKeys, $section)
|
||||
{
|
||||
/** @var \Zend_Db_Adapter_Abstract $db */
|
||||
$db = $this->getStoreConfig()->connection->getDbAdapter();
|
||||
|
||||
try {
|
||||
|
@ -203,6 +240,7 @@ class DbStore extends PreferencesStore
|
|||
$this->table,
|
||||
array(
|
||||
self::COLUMN_USERNAME . '=?' => $this->getUser()->getUsername(),
|
||||
$db->quoteIdentifier(self::COLUMN_SECTION) . '=?' => $section,
|
||||
$db->quoteIdentifier(self::COLUMN_PREFERENCE) . ' IN (?)' => $preferenceKeys
|
||||
)
|
||||
);
|
||||
|
|
|
@ -67,7 +67,7 @@ class IniStore extends PreferencesStore
|
|||
$this->getUser()->getUsername()
|
||||
);
|
||||
} else {
|
||||
$this->preferences = parse_ini_file($this->preferencesFile);
|
||||
$this->preferences = parse_ini_file($this->preferencesFile, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,9 +81,13 @@ class IniStore extends PreferencesStore
|
|||
*/
|
||||
public function save(Preferences $preferences)
|
||||
{
|
||||
$preferences = $preferences->toArray();
|
||||
$this->update(array_diff_assoc($preferences, $this->preferences));
|
||||
$this->delete(array_keys(array_diff_key($this->preferences, $preferences)));
|
||||
$this->preferences = $preferences->toArray();
|
||||
|
||||
// TODO: Elaborate whether we need to patch the contents
|
||||
// $preferences = $preferences->toArray();
|
||||
// $this->update(array_diff_assoc($preferences, $this->preferences));
|
||||
// $this->delete(array_keys(array_diff_key($this->preferences, $preferences)));
|
||||
|
||||
$this->write();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
namespace Icinga\Web;
|
||||
|
||||
use Icinga\Authentication\Manager;
|
||||
use Icinga\Web\Menu\MenuItemRenderer;
|
||||
use RecursiveIterator;
|
||||
use Icinga\Application\Config;
|
||||
|
@ -200,41 +201,50 @@ class Menu implements RecursiveIterator
|
|||
*/
|
||||
protected function addMainMenuItems()
|
||||
{
|
||||
$this->add(t('Dashboard'), array(
|
||||
'url' => 'dashboard',
|
||||
'icon' => 'img/icons/dashboard.png',
|
||||
'priority' => 10
|
||||
));
|
||||
$auth = Manager::getInstance();
|
||||
|
||||
$section = $this->add(t('System'), array(
|
||||
'icon' => 'img/icons/configuration.png',
|
||||
'priority' => 200
|
||||
));
|
||||
$section->add(t('Preferences'), array(
|
||||
'url' => 'preference',
|
||||
'priority' => 200
|
||||
));
|
||||
$section->add(t('Configuration'), array(
|
||||
'url' => 'config',
|
||||
'priority' => 300
|
||||
));
|
||||
$section->add(t('Modules'), array(
|
||||
'url' => 'config/modules',
|
||||
'priority' => 400
|
||||
));
|
||||
if ($auth->isAuthenticated()) {
|
||||
|
||||
if (Logger::writesToFile()) {
|
||||
$section->add(t('Application Log'), array(
|
||||
'url' => 'list/applicationlog',
|
||||
'priority' => 500
|
||||
$this->add(t('Dashboard'), array(
|
||||
'url' => 'dashboard',
|
||||
'icon' => 'img/icons/dashboard.png',
|
||||
'priority' => 10
|
||||
));
|
||||
|
||||
$section = $this->add(t('System'), array(
|
||||
'icon' => 'img/icons/configuration.png',
|
||||
'priority' => 200
|
||||
));
|
||||
$section->add(t('Configuration'), array(
|
||||
'url' => 'config',
|
||||
'priority' => 300
|
||||
));
|
||||
$section->add(t('Modules'), array(
|
||||
'url' => 'config/modules',
|
||||
'priority' => 400
|
||||
));
|
||||
|
||||
if (Logger::writesToFile()) {
|
||||
$section->add(t('Application Log'), array(
|
||||
'url' => 'list/applicationlog',
|
||||
'priority' => 500
|
||||
));
|
||||
}
|
||||
|
||||
$section = $this->add($auth->getUser()->getUsername(), array(
|
||||
'icon' => 'img/icons/user.png',
|
||||
'priority' => 600
|
||||
));
|
||||
$section->add(t('Preferences'), array(
|
||||
'url' => 'preference',
|
||||
'priority' => 601
|
||||
));
|
||||
|
||||
$section->add(t('Logout'), array(
|
||||
'url' => 'authentication/logout',
|
||||
'priority' => 700
|
||||
));
|
||||
}
|
||||
|
||||
$this->add(t('Logout'), array(
|
||||
'url' => 'authentication/logout',
|
||||
'icon' => 'img/icons/logout.png',
|
||||
'priority' => 300
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
namespace Tests\Icinga\User\Preferences\Store;
|
||||
|
||||
use Mockery;
|
||||
use Exception;
|
||||
use Icinga\Test\BaseTestCase;
|
||||
use Icinga\Application\Config;
|
||||
use Icinga\Exception\NotWritableError;
|
||||
use Icinga\Test\BaseTestCase;
|
||||
use Icinga\User\Preferences\Store\DbStore;
|
||||
|
||||
class DatabaseMock
|
||||
|
@ -44,17 +44,17 @@ class FaultyDatabaseMock extends DatabaseMock
|
|||
{
|
||||
public function insert($table, $row)
|
||||
{
|
||||
throw new Exception();
|
||||
throw new NotWritableError();
|
||||
}
|
||||
|
||||
public function update($table, $columns, $where)
|
||||
{
|
||||
throw new Exception();
|
||||
throw new NotWritableError();
|
||||
}
|
||||
|
||||
public function delete($table, $where)
|
||||
{
|
||||
throw new Exception();
|
||||
throw new NotWritableError();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -75,7 +75,7 @@ class DbStoreTest extends BaseTestCase
|
|||
$store->save(
|
||||
Mockery::mock(
|
||||
'Icinga\User\Preferences',
|
||||
array('toArray' => array('key' => 'value'))
|
||||
array('toArray' => array('testsection' => array('key' => 'value')))
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -85,7 +85,7 @@ class DbStoreTest extends BaseTestCase
|
|||
}
|
||||
|
||||
/**
|
||||
* @expectedException Icinga\Exception\NotWritableError
|
||||
* @expectedException \Icinga\Exception\NotWritableError
|
||||
*/
|
||||
public function testWhetherPreferenceInsertionThrowsNotWritableError()
|
||||
{
|
||||
|
@ -93,7 +93,7 @@ class DbStoreTest extends BaseTestCase
|
|||
$store->save(
|
||||
Mockery::mock(
|
||||
'Icinga\User\Preferences',
|
||||
array('toArray' => array('key' => 'value'))
|
||||
array('toArray' => array('testsection' => array('key' => 'value')))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -102,11 +102,11 @@ class DbStoreTest extends BaseTestCase
|
|||
{
|
||||
$dbMock = new DatabaseMock();
|
||||
$store = $this->getStore($dbMock);
|
||||
$store->setPreferences(array('key' => 'value'));
|
||||
$store->setPreferences(array('testsection' => array('key' => 'value')));
|
||||
$store->save(
|
||||
Mockery::mock(
|
||||
'Icinga\User\Preferences',
|
||||
array('toArray' => array('key' => 'eulav'))
|
||||
array('toArray' => array('testsection' => array('key' => 'eulav')))
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -116,16 +116,16 @@ class DbStoreTest extends BaseTestCase
|
|||
}
|
||||
|
||||
/**
|
||||
* @expectedException Icinga\Exception\NotWritableError
|
||||
* @expectedException \Icinga\Exception\NotWritableError
|
||||
*/
|
||||
public function testWhetherPreferenceUpdatesThrowNotWritableError()
|
||||
{
|
||||
$store = $this->getStore(new FaultyDatabaseMock());
|
||||
$store->setPreferences(array('key' => 'value'));
|
||||
$store->setPreferences(array('testsection' => array('key' => 'value')));
|
||||
$store->save(
|
||||
Mockery::mock(
|
||||
'Icinga\User\Preferences',
|
||||
array('toArray' => array('key' => 'eulav'))
|
||||
array('toArray' => array('testsection' => array('key' => 'eulav')))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -134,11 +134,11 @@ class DbStoreTest extends BaseTestCase
|
|||
{
|
||||
$dbMock = new DatabaseMock();
|
||||
$store = $this->getStore($dbMock);
|
||||
$store->setPreferences(array('key' => 'value'));
|
||||
$store->setPreferences(array('testsection' => array('key' => 'value')));
|
||||
$store->save(
|
||||
Mockery::mock(
|
||||
'Icinga\User\Preferences',
|
||||
array('toArray' => array())
|
||||
array('toArray' => array('testsection' => array()))
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -148,16 +148,16 @@ class DbStoreTest extends BaseTestCase
|
|||
}
|
||||
|
||||
/**
|
||||
* @expectedException Icinga\Exception\NotWritableError
|
||||
* @expectedException \Icinga\Exception\NotWritableError
|
||||
*/
|
||||
public function testWhetherPreferenceDeletionThrowsNotWritableError()
|
||||
{
|
||||
$store = $this->getStore(new FaultyDatabaseMock());
|
||||
$store->setPreferences(array('key' => 'value'));
|
||||
$store->setPreferences(array('testsection' => array('key' => 'value')));
|
||||
$store->save(
|
||||
Mockery::mock(
|
||||
'Icinga\User\Preferences',
|
||||
array('toArray' => array())
|
||||
array('toArray' => array('testsection' => array('key' => 'foo')))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -32,13 +32,15 @@ class IniStoreTest extends BaseTestCase
|
|||
public function testWhetherPreferenceChangesAreApplied()
|
||||
{
|
||||
$store = $this->getStore();
|
||||
$store->setPreferences(array('key1' => '1'));
|
||||
$store->setPreferences(array('testsection' => array('key1' => '1')));
|
||||
|
||||
$store->save(
|
||||
Mockery::mock('Icinga\User\Preferences', array('toArray' => array('key1' => '11', 'key2' => '2')))
|
||||
Mockery::mock('Icinga\User\Preferences', array(
|
||||
'toArray' => array('testsection' => array('key1' => '11', 'key2' => '2'))
|
||||
))
|
||||
);
|
||||
$this->assertEquals(
|
||||
array('key1' => '11', 'key2' => '2'),
|
||||
array('testsection' => array('key1' => '11', 'key2' => '2')),
|
||||
$store->getPreferences(),
|
||||
'IniStore::save does not properly apply changed preferences'
|
||||
);
|
||||
|
@ -47,10 +49,13 @@ class IniStoreTest extends BaseTestCase
|
|||
public function testWhetherPreferenceDeletionsAreApplied()
|
||||
{
|
||||
$store = $this->getStore();
|
||||
$store->setPreferences(array('key' => 'value'));
|
||||
$store->setPreferences(array('testsection' => array('key' => 'value')));
|
||||
|
||||
$store->save(Mockery::mock('Icinga\User\Preferences', array('toArray' => array())));
|
||||
$this->assertEmpty($store->getPreferences(), 'IniStore::save does not delete removed preferences');
|
||||
$store->save(Mockery::mock('Icinga\User\Preferences', array('toArray' => array('testsection' => array()))));
|
||||
|
||||
$result = $store->getPreferences();
|
||||
|
||||
$this->assertEmpty($result['testsection'], 'IniStore::save does not delete removed preferences');
|
||||
}
|
||||
|
||||
protected function getStore()
|
||||
|
|
Loading…
Reference in New Issue