user preferences saving and integration

This commit is contained in:
Crack
2010-06-20 21:34:13 +02:00
parent f920e44af4
commit 9f44d864b6
17 changed files with 291 additions and 170 deletions

View File

@@ -1,112 +0,0 @@
Features
General
DefaultLang (just persist main page settings?)
DefaultConnectionCollation (just persist main page settings?)
ThemeDefault (if ThemeManager == true)
NaturalOrder [s-]
InitialSlidersState [s-]
ErrorIconic [s-]
ReplaceHelpImg [s-]
Text fields
CharEditing [s]
CharTextareaCols [s]
CharTextareaRows [s]
TextareaCols [s-]
TextareaRows [s-]
LongtextDoubleTextarea [s-]
SQL Queries
ShowSQL [s]
Confirm [s]
IgnoreMultiSubmitErrors [s]
VerboseMultiSubmit [s]
MaxCharactersInDisplayedSQL [s-]
SQLQuery/Edit [s-]
SQLQuery/Explain [s-]
SQLQuery/ShowAsPHP [s-]
SQLQuery/Validate [false or no override]
SQLQuery/Refresh [s-]
EditInWindow [s-]
QueryWindowWidth [s-]
QueryWindowHeight [s-]
QueryWindowDefTab [s-]
Page titles
TitleTable [s-]
TitleDatabase[s-]
TitleServer [s-]
TitleDefault [s-]
LEFT FRAME
Navigation frame
LeftFrameLight [s]
LeftDisplayLogo [s]
LeftLogoLink [s]
LeftLogoLinkWindow [s]
LeftPointerEnable [s]
Servers
LeftDisplayServers [s]
DisplayServersList [s]
Databases
DisplayDatabasesList [s]
LeftFrameDBTree [s]
LeftFrameDBSeparator [s]
LeftFrameTableLevel [s]
ShowTooltipAliasDB [s]
Tables
LeftDefaultTabTable [s]
LeftFrameTableSeparator [s]
LeftFrameTableLevel [s]
ShowTooltip [s]
ShowTooltipAliasTB [s]
MAIN FRAME
AT STARTUP
MainPageIconic [s]
-ShowStats [false or no override]
-ShowPhpInfo [false or no override]
-ShowServerInfo [false or no override]
-ShowChgPassword [false or no override]
-ShowCreateDb [false or no override]
SuggestDBName [s]
In browse mode...
NavigationBarIconic [s]
ShowAll [s]
MaxRows [s]
Order [s]
DisplayBinaryAsHex [s]
BrowsePointerEnable [s]
BrowseMarkerEnable [s]
RepeatCells [s-]
LimitChars [s-]
ModifyDeleteAtLeft [s-]
ModifyDeleteAtRight [s-]
DefaultDisplay [s-]
In edit mode...
ProtectBinary [s]
ShowFunctionFields [s]
ShowFieldTypesInDataEditView [s-]
InsertRows [s]
ForeignKeyDropdownOrder [s, ? custom text value]
ForeignKeyMaxLimit [s]
CtrlArrowsMoving [s]
DefaultPropDisplay [s-]
Tabs display settings
LightTabs [s]
PropertiesIconic [s]
DefaultTabServer [s]
DefaultTabDatabase [s]
DefaultTabTable [s]
SQL Query Box
Edit [s]
Explain [s]
ShowAsPHP [s]
Validate (false or no override)
Refresh [s]
Export
PDFDefaultPageSize [s-]
WYSIWYG-PDF [s-]
all export defaults [s:some]
Import
all import defaults [s:some]

1
.gsoc/todo.txt Normal file
View File

@@ -0,0 +1 @@
restore cache'ing in phpmyadmin.css.php

View File

@@ -409,6 +409,40 @@ class PMA_Config
return true;
}
/**
* loads user preferences and merges them with current config
* must be called after control connection has been estabilished
*
* @uses PMA_array_merge_recursive
* @uses PMA_backquote()
* @uses PMA_DBI_fetch_value
* @uses PMA_getRelationsParam()
* @uses PMA_sqlAddslashes()
* @uses $GLOBALS['cfg']
* @uses $GLOBALS['controllink']
* @return boolean
*/
function loadUserPreferences()
{
$cfgRelation = PMA_getRelationsParam();
if (!$cfgRelation['userconfigwork']) {
return false;
}
$query_table = PMA_backquote($cfgRelation['db']) . '.' . PMA_backquote($cfgRelation['userconfig']);
$query = '
SELECT `config_data`
FROM ' . $query_table . '
WHERE `username` = \'' . PMA_sqlAddslashes($cfgRelation['user']) . '\'';
$config_data = PMA_DBI_fetch_value($query, 0, 0, $GLOBALS['controllink']);
if (!$config_data) {
return false;
}
$config_data = unserialize($config_data);
$this->settings = PMA_array_merge_recursive($this->settings, $config_data);
$GLOBALS['cfg'] = PMA_array_merge_recursive($GLOBALS['cfg'], $config_data);
$this->set('user_preferences_loaded', true);
}
/**
* set source
* @param string $source

View File

@@ -954,6 +954,9 @@ if (! defined('PMA_MINIMUM_COMMON')) {
} // end server connecting
// load user preferences
$GLOBALS['PMA_Config']->loadUserPreferences();
/**
* check if profiling was requested and remember it
* (note: when $cfg['ServerDefault'] = 0, constant is not defined)

View File

@@ -29,7 +29,25 @@ class ConfigFile
* Keys which will be always written to config file
* @var array
*/
private $persistKeys;
private $persistKeys = array();
/**
* Key filter for {@link set()}
* @var array|null
*/
private $setFilter;
/**
* Instance id (key in $_SESSION array, separate for each server - ConfigFile{server id})
* @var string
*/
private $id;
/**
* Result for {@link _flattenArray()}
* @var array
*/
private $_flattenArrayResult;
/**
* ConfigFile instance
@@ -56,6 +74,11 @@ class ConfigFile
PMA_array_write($path, $cfg, $value);
}
}
$this->id = 'ConfigFile' . $GLOBALS['server'];
if (!isset($_SESSION[$this->id])) {
$_SESSION[$this->id] = array();
}
}
/**
@@ -83,6 +106,40 @@ class ConfigFile
$this->persistKeys = array_flip($keys);
}
/**
* By default ConfigFile allows setting of all configuration keys, use this method
* to set up a filter on {@link set()} method
*
* @param array|null $keys array of allowed keys or null to remove filter
*/
public function setAllowedKeys($keys)
{
if ($keys === null) {
$this->setFilter = null;
return;
}
// checking key presence is much faster than searching so move values to keys
$this->setFilter = array_flip($keys);
}
/**
* Resets configuration data
*/
public function resetConfigData()
{
$_SESSION[$this->id] = array();
}
/**
* Sets configuration data (overrides old data)
*
* @param array $cfg
*/
public function setConfigData(array $cfg)
{
$_SESSION[$this->id] = $cfg;
}
/**
* Sets config value
*
@@ -95,13 +152,57 @@ class ConfigFile
if ($canonical_path === null) {
$canonical_path = $this->getCanonicalPath($path);
}
// apply key whitelist
if ($this->setFilter !== null && !isset($this->setFilter[$canonical_path])) {
return;
}
// remove if the path isn't protected and it's empty or has a default value
$default_value = $this->getDefault($canonical_path);
if (!isset($this->persistKeys[$canonical_path])
&& (($value == $default_value) || (empty($value) && empty($default_value)))) {
PMA_array_remove($path, $_SESSION['ConfigFile']);
&& (($value == $default_value) || (empty($value) && empty($default_value)))) {
PMA_array_remove($path, $_SESSION[$this->id]);
} else {
PMA_array_write($path, $_SESSION['ConfigFile'], $value);
PMA_array_write($path, $_SESSION[$this->id], $value);
}
}
/**
* Flattens multidimensional array, changes indices to paths (eg. 'key/subkey')
*
* @param mixed $value
* @param mixed $key
* @param mixed $prefix
*/
private function _flattenArray($value, $key, $prefix)
{
// no recursion for numeric arrays
if (is_array($value) && !isset($value[0])) {
//$prefix .= (empty($prefix) ? '' : '/') . $key;
$prefix .= $key . '/';
array_walk($value, array($this, '_flattenArray'), $prefix);
} else {
//$this->_flattenArrayResult[$prefix . '/' . $key] = $value;
$this->_flattenArrayResult[$prefix . $key] = $value;
}
}
/**
* Updates config with values read from PMA_Config class
* (config will contain differences to defaults from config.defaults.php).
*
* @param PMA_Config $PMA_Config
*/
public function updateWithGlobalConfig(PMA_Config $PMA_Config)
{
// load config array and flatten it
$this->_flattenArrayResult = array();
array_walk($PMA_Config->settings, array($this, '_flattenArray'), '');
$flat_cfg = $this->_flattenArrayResult;
$this->_flattenArrayResult = null;
// save values
foreach ($flat_cfg as $path => $value) {
$this->set($path, $value, $path);
}
}
@@ -114,7 +215,7 @@ class ConfigFile
*/
public function get($path, $default = null)
{
return PMA_array_read($path, $_SESSION['ConfigFile'], $default);
return PMA_array_read($path, $_SESSION[$this->id], $default);
}
/**
@@ -141,7 +242,7 @@ class ConfigFile
*/
public function getValue($path, $default = null)
{
$v = PMA_array_read($path, $_SESSION['ConfigFile'], null);
$v = PMA_array_read($path, $_SESSION[$this->id], null);
if ($v !== null) {
return $v;
}
@@ -178,11 +279,23 @@ class ConfigFile
*/
public function getServerCount()
{
return isset($_SESSION['ConfigFile']['Servers'])
? count($_SESSION['ConfigFile']['Servers'])
return isset($_SESSION[$this->id]['Servers'])
? count($_SESSION[$this->id]['Servers'])
: 0;
}
/**
* Returns server list
*
* @return array|null
*/
public function getServers()
{
return isset($_SESSION[$this->id]['Servers'])
? $_SESSION[$this->id]['Servers']
: null;
}
/**
* Returns DSN of given server
*
@@ -191,7 +304,7 @@ class ConfigFile
*/
function getServerDSN($server)
{
if (!isset($_SESSION['ConfigFile']['Servers'][$server])) {
if (!isset($_SESSION[$this->id]['Servers'][$server])) {
return '';
}
@@ -224,7 +337,7 @@ class ConfigFile
*/
public function getServerName($id)
{
if (!isset($_SESSION['ConfigFile']['Servers'][$id])) {
if (!isset($_SESSION[$this->id]['Servers'][$id])) {
return '';
}
$verbose = $this->get("Servers/$id/verbose");
@@ -242,19 +355,19 @@ class ConfigFile
*/
public function removeServer($server)
{
if (!isset($_SESSION['ConfigFile']['Servers'][$server])) {
if (!isset($_SESSION[$this->id]['Servers'][$server])) {
return;
}
$last_server = $this->getServerCount();
for ($i = $server; $i < $last_server; $i++) {
$_SESSION['ConfigFile']['Servers'][$i] = $_SESSION['ConfigFile']['Servers'][$i+1];
$_SESSION[$this->id]['Servers'][$i] = $_SESSION[$this->id]['Servers'][$i+1];
}
unset($_SESSION['ConfigFile']['Servers'][$last_server]);
unset($_SESSION[$this->id]['Servers'][$last_server]);
if (isset($_SESSION['ConfigFile']['ServerDefault'])
&& $_SESSION['ConfigFile']['ServerDefault'] >= 0) {
unset($_SESSION['ConfigFile']['ServerDefault']);
if (isset($_SESSION[$this->id]['ServerDefault'])
&& $_SESSION[$this->id]['ServerDefault'] >= 0) {
unset($_SESSION[$this->id]['ServerDefault']);
}
}
@@ -273,6 +386,23 @@ class ConfigFile
return SETUP_CONFIG_FILE;
}
/**
* Returns configuration array
*
* @return array
*/
public function getConfigArray()
{
$c = $_SESSION[$this->id];
$persistKeys = array_diff(array_keys($this->persistKeys), array_keys($c));
foreach ($persistKeys as $k) {
if (strpos($k, '/') === false) {
$c[$k] = $this->getDefault($k);
}
}
return $c;
}
/**
* Creates config file
*
@@ -281,7 +411,7 @@ class ConfigFile
public function getConfigFile()
{
$crlf = (isset($_SESSION['eol']) && $_SESSION['eol'] == 'win') ? "\r\n" : "\n";
$c = $_SESSION['ConfigFile'];
$c = $_SESSION[$this->id];
// header
$ret = '<?php' . $crlf

View File

@@ -93,7 +93,7 @@ class Form
/**
* array_walk callback function, reads path of form fields from
* array (see file comment in forms.inc.php)
* array (see file comment in setup.forms.php or user_preferences.forms.inc)
*
* @param mixed $value
* @param mixed $key
@@ -102,14 +102,14 @@ class Form
private function _readFormPathsCallback($value, $key, $prefix)
{
if (is_array($value)) {
$prefix .= (empty($prefix) ? '' : '/') . $key;
$prefix .= $key . '/';
array_walk($value, array($this, '_readFormPathsCallback'), $prefix);
} else {
if (!is_int($key)) {
$this->default[$prefix . '/' . $key] = $value;
$this->default[$prefix . $key] = $value;
$value = $key;
}
$this->fields[] = $prefix . '/' . $value;
$this->fields[] = $prefix . $value;
}
}
@@ -129,7 +129,6 @@ class Form
$paths = $this->fields;
$this->fields = array();
foreach ($paths as $path) {
$path = ltrim($path, '/');
$key = ltrim(substr($path, strrpos($path, '/')), '/');
$this->fields[$key] = $path;
}

View File

@@ -28,7 +28,7 @@ class FormDisplay
{
/**
* Form list
* @var array
* @var Form[]
*/
private $forms = array();

View File

@@ -116,6 +116,7 @@ function display_input($path, $name, $description = '', $type, $value, $value_is
$field_class = $value_is_default ? '' : ' class="custom"';
$name_id = 'name="' . $path . '" id="' . $path . '"';
$base_dir = defined('PMA_SETUP') ? '../' : '';
//todo use PMA_showDocu(), create and use PMA_showWiki()
$img_path = defined('PMA_SETUP')
? '../' . ltrim($GLOBALS['cfg']['ThemePath'], './') . '/original/img/'
: $_SESSION['PMA_Theme']->img_path;
@@ -152,7 +153,7 @@ function display_input($path, $name, $description = '', $type, $value, $value_is
foreach ($opts['values'] as $opt_value => $opt_name) {
// set names for boolean values
if (is_bool($opt_name)) {
$opt_name = $GLOBALS['strSetup' . ($opt_value ? __('Yes') : __('No'))];
$opt_name = strtolower($opt_value ? __('Yes') : __('No'));
}
// cast boolean values to integers
$display_value = is_bool($opt_value) ? (int) $opt_value : $opt_value;

View File

@@ -103,8 +103,8 @@ $forms['Sql_queries'] = array(
'VerboseMultiSubmit',
'MaxCharactersInDisplayedSQL',
'EditInWindow',
'QueryWindowWidth',
'QueryWindowHeight',
//'QueryWindowWidth', // overridden in theme
//'QueryWindowHeight',
'QueryWindowDefTab');
$forms['Page_titles'] = array(
'TitleDefault',
@@ -112,6 +112,10 @@ $forms['Page_titles'] = array(
'TitleDatabase',
'TitleServer');
$forms['Other_core_settings'] = array(
'NaturalOrder',
'InitialSlidersState',
'ErrorIconic',
'ReplaceHelpImg',
'MaxDbList',
'MaxTableList',
'MaxCharactersInDisplayedSQL',

View File

@@ -3,10 +3,8 @@
* List of avaible forms, each form is described as an array of fields to display.
* Fields MUST have their counterparts in the $cfg array.
*
* There are two possible notations:
* $forms['Form name'] = array('Servers' => array(1 => array('host')));
* can be written as
* $forms['Form name'] = array('Servers/1/host');
* To define form field, use the notatnion below:
* $forms['Form group']['Form name'] = array('Servers/1/host');
*
* You can assign default values set by special button ("set value: ..."), eg.:
* $forms['Server_pmadb'] = array('Servers' => array(1 => array(
@@ -35,8 +33,8 @@ $forms['Sql_queries']['Sql_queries'] = array(
'VerboseMultiSubmit',
'MaxCharactersInDisplayedSQL',
'EditInWindow',
'QueryWindowWidth',
'QueryWindowHeight',
//'QueryWindowWidth', // overridden in theme
//'QueryWindowHeight',
'QueryWindowDefTab');
$forms['Sql_queries']['Sql_box'] = array(
'SQLQuery/Edit',

View File

@@ -6,5 +6,43 @@
* @package phpMyAdmin
*/
/**
* Saves user preferences
*
* @uses PMA_getRelationsParam()
* @return true|PMA_Message
*/
function PMA_save_userprefs()
{
$cfgRelation = PMA_getRelationsParam();
$cf = ConfigFile::getInstance();
$config_data = serialize($cf->getConfigArray());
$query_table = PMA_backquote($cfgRelation['db']) . '.' . PMA_backquote($cfgRelation['userconfig']);
$query = '
SELECT `username`
FROM ' . $query_table . '
WHERE `username` = \'' . PMA_sqlAddslashes($cfgRelation['user']) . '\'';
$has_config = PMA_DBI_fetch_value($query, 0, 0, $GLOBALS['controllink']);
if ($has_config) {
$query = '
UPDATE ' . $query_table . '
SET `config_data` = \'' . PMA_sqlAddslashes($config_data) . '\'
WHERE `username` = \'' . PMA_sqlAddslashes($cfgRelation['user']) . '\'';
} else {
$query = '
INSERT INTO ' . $query_table . ' (`username`, `config_data`)
VALUES (\'' . PMA_sqlAddslashes($cfgRelation['user']) . '\',
\'' . PMA_sqlAddslashes($config_data) . '\')';
}
if (!PMA_DBI_try_query($query, $GLOBALS['controllink'])) {
$message = PMA_Message::error(__('Could not save configuration'));
$message->addMessage('<br /><br />');
$message->addMessage(PMA_Message::rawError(PMA_DBI_getError($GLOBALS['controllink'])));
return $message;
}
return true;
}
?>

View File

@@ -29,7 +29,7 @@ if (PMA_ifSetOr($_POST['submit_clear'], '')) {
//
// Clear current config and return to main page
//
$_SESSION['ConfigFile'] = array();
ConfigFile::getInstance()->resetConfigData();
// drop post data
header('HTTP/1.1 303 See Other');
header('Location: index.php');
@@ -56,7 +56,7 @@ if (PMA_ifSetOr($_POST['submit_clear'], '')) {
//
$cfg = array();
require_once $config_file_path;
$_SESSION['ConfigFile'] = $cfg;
ConfigFile::getInstance()->setConfigData($cfg);
header('HTTP/1.1 303 See Other');
header('Location: index.php');
exit;

View File

@@ -18,7 +18,7 @@ require_once './libraries/config/Form.class.php';
require_once './libraries/config/FormDisplay.class.php';
require_once './setup/lib/form_processing.lib.php';
require './setup/lib/forms.inc.php';
require './libraries/config/setup.forms.php';
$formsets = array(
'features' => array(

View File

@@ -116,7 +116,7 @@ display_form_top('index.php', 'get', array(
<th><?php echo __('Authentication type') ?></th>
<th colspan="2">DSN</th>
</tr>
<?php foreach ($_SESSION['ConfigFile']['Servers'] as $id => $server): ?>
<?php foreach ($cf->getServers() as $id => $server): ?>
<tr>
<td><?php echo $id ?></td>
<td><?php echo $cf->getServerName($id) ?></td>
@@ -189,7 +189,7 @@ if ($cf->getServerCount() > 0) {
}
$opts['values_disabled'][] = '-';
foreach ($_SESSION['ConfigFile']['Servers'] as $id => $server) {
foreach ($cf->getServers() as $id => $server) {
$opts['values'][(string)$id] = $cf->getServerName($id) . " [$id]";
}
} else {

View File

@@ -18,7 +18,7 @@ require_once './libraries/config/Form.class.php';
require_once './libraries/config/FormDisplay.class.php';
require_once './setup/lib/form_processing.lib.php';
require './setup/lib/forms.inc.php';
require './libraries/config/setup.forms.php';
$mode = filter_input(INPUT_GET, 'mode');
$id = filter_input(INPUT_GET, 'id', FILTER_VALIDATE_INT);

View File

@@ -30,9 +30,6 @@ restore_error_handler();
// Save current language in a cookie, required since we use PMA_MINIMUM_COMMON
$GLOBALS['PMA_Config']->setCookie('pma_lang', $GLOBALS['lang']);
if (!isset($_SESSION['ConfigFile'])) {
$_SESSION['ConfigFile'] = array();
}
ConfigFile::getInstance()->setPersistKeys(array(
'DefaultLang',
'ServerDefault',

View File

@@ -16,34 +16,52 @@ require_once './libraries/config/messages.inc.php';
require_once './libraries/config/ConfigFile.class.php';
require_once './libraries/config/Form.class.php';
require_once './libraries/config/FormDisplay.class.php';
require_once './libraries/config/user_preferences.forms.php';
require './libraries/config/user_preferences.forms.php';
$GLOBALS['js_include'][] = 'config.js';
require_once './libraries/header.inc.php';
// Any message to display?
if (! empty($message)) {
PMA_showMessage($message);
unset($message);
}
// build tabs
$tabs = array();
$form_param = filter_input(INPUT_GET, 'form');
if (!isset($forms[$form_param])) {
$form_param = array_shift(array_keys($forms));
$forms_keys = array_keys($forms);
$form_param = array_shift($forms_keys);
}
foreach (array_keys($forms) as $form) {
foreach (array_keys($forms) as $formset) {
$tabs[] = array(
'link' => 'user_preferences.php',
'text' => PMA_ifSetOr($GLOBALS['strSetupForm_' . $form], $form), // TODO: remove ifSetOr
'active' => $form == $form_param,
'url_params' => array('form' => $form)
'text' => PMA_ifSetOr($GLOBALS['strSetupForm_' . $formset], $formset), // TODO: remove ifSetOr
'active' => $formset == $form_param,
'url_params' => array('form' => $formset)
);
}
echo PMA_generate_html_tabs($tabs, array());
// handle form display and processing
$forms_all_keys = array();
foreach ($forms as $formset) {
foreach ($formset as $form) {
$forms_all_keys = array_merge($forms_all_keys, $form);
}
}
$cf = ConfigFile::getInstance();
$cf->setAllowedKeys($forms_all_keys);
$cf->updateWithGlobalConfig($GLOBALS['PMA_Config']);
// todo: debug - remove
$arr = $cf->getConfigArray();
$arr2 = array();
foreach ($arr as $k => $v) {
$arr2[] = "<b>$k</b> " . var_export($v, true);
}
$arr2 = implode(', ', $arr2);
$msg = !empty($arr2) ? PMA_Message::notice('Debug: ' . $arr2) : PMA_Message::notice('no settings');
$msg->display();
$form_display = new FormDisplay();
foreach ($forms[$form_param] as $form_name => $form) {
$form_display->registerForm($form_name, $form);
@@ -78,13 +96,23 @@ if (!$form_display->process(false)) {
<a class="btn" href="?form=<?php echo $form_param ?>&amp;mode=edit"><?php echo PMA_lang('ShowForm') ?></a>
<?php
} else {
// redirect
$url_params = array('form' => $form_param);
PMA_sendHeaderLocation($cfg['PmaAbsoluteUri'] . 'user_preferences.php'
. PMA_generate_common_url($url_params, '&'));
exit;
// save settings
$result = PMA_save_userprefs();
if ($result === true) {
$message = PMA_Message::rawSuccess(__('Configuration has been saved'));
$message->display();
// redirect
//$url_params = array('form' => $form_param);
//PMA_sendHeaderLocation($cfg['PmaAbsoluteUri'] . 'user_preferences.php'
// . PMA_generate_common_url($url_params, '&'));
//exit;
} else {
$result->display();
}
$form_display->display(true, true);
}
}
$GLOBALS['error_handler']->dispAllErrors();
/**
* Displays the footer