diff --git a/.gsoc/options.txt b/.gsoc/options.txt
deleted file mode 100644
index e4bb56b94..000000000
--- a/.gsoc/options.txt
+++ /dev/null
@@ -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]
diff --git a/.gsoc/todo.txt b/.gsoc/todo.txt
new file mode 100644
index 000000000..4dd9492f8
--- /dev/null
+++ b/.gsoc/todo.txt
@@ -0,0 +1 @@
+restore cache'ing in phpmyadmin.css.php
diff --git a/libraries/Config.class.php b/libraries/Config.class.php
index c0090aa7f..7b72240ca 100644
--- a/libraries/Config.class.php
+++ b/libraries/Config.class.php
@@ -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
diff --git a/libraries/common.inc.php b/libraries/common.inc.php
index 710ecdfc4..8dfb7e7d3 100644
--- a/libraries/common.inc.php
+++ b/libraries/common.inc.php
@@ -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)
diff --git a/libraries/config/ConfigFile.class.php b/libraries/config/ConfigFile.class.php
index bcb1e8ac2..ffbcea1ad 100644
--- a/libraries/config/ConfigFile.class.php
+++ b/libraries/config/ConfigFile.class.php
@@ -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 = '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;
}
diff --git a/libraries/config/FormDisplay.class.php b/libraries/config/FormDisplay.class.php
index 7d812fbe2..55a02952d 100644
--- a/libraries/config/FormDisplay.class.php
+++ b/libraries/config/FormDisplay.class.php
@@ -28,7 +28,7 @@ class FormDisplay
{
/**
* Form list
- * @var array
+ * @var Form[]
*/
private $forms = array();
diff --git a/libraries/config/FormDisplay.tpl.php b/libraries/config/FormDisplay.tpl.php
index e22d3a9b5..1fced4a60 100644
--- a/libraries/config/FormDisplay.tpl.php
+++ b/libraries/config/FormDisplay.tpl.php
@@ -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;
diff --git a/libraries/config/setup.forms.php b/libraries/config/setup.forms.php
index 795ca91f1..2f78f6732 100644
--- a/libraries/config/setup.forms.php
+++ b/libraries/config/setup.forms.php
@@ -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',
diff --git a/libraries/config/user_preferences.forms.php b/libraries/config/user_preferences.forms.php
index bf6ed7540..dbc1ef691 100644
--- a/libraries/config/user_preferences.forms.php
+++ b/libraries/config/user_preferences.forms.php
@@ -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',
diff --git a/libraries/user_preferences.lib.php b/libraries/user_preferences.lib.php
index e28ec7208..74ed13dd5 100644
--- a/libraries/user_preferences.lib.php
+++ b/libraries/user_preferences.lib.php
@@ -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('
');
+ $message->addMessage(PMA_Message::rawError(PMA_DBI_getError($GLOBALS['controllink'])));
+ return $message;
+ }
+ return true;
+}
?>
\ No newline at end of file
diff --git a/setup/config.php b/setup/config.php
index d6c6d4075..555a8ab84 100644
--- a/setup/config.php
+++ b/setup/config.php
@@ -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;
diff --git a/setup/frames/form.inc.php b/setup/frames/form.inc.php
index 5ede9d483..604189ea7 100644
--- a/setup/frames/form.inc.php
+++ b/setup/frames/form.inc.php
@@ -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(
diff --git a/setup/frames/index.inc.php b/setup/frames/index.inc.php
index 970114483..b82801201 100644
--- a/setup/frames/index.inc.php
+++ b/setup/frames/index.inc.php
@@ -116,7 +116,7 @@ display_form_top('index.php', 'get', array(