diff --git a/Documentation.html b/Documentation.html
index 5b3da22006..3bbb832dd4 100644
--- a/Documentation.html
+++ b/Documentation.html
@@ -1054,6 +1054,29 @@ ALTER TABLE `pma_column_comments`
+
+ $cfg['Servers'][$i]['recent'] string
+
+
+ Since release 3.5.0 you can show recently used tables in the left navigation frame.
+ It helps you to jump across table directly, without the need to select the database,
+ and then select the table. Using
+ $cfg['LeftRecentTable']
+ you can configure the maximum number of recent tables shown. When you select a table
+ from the list, it will jump to the page specified in
+ $cfg['LeftDefaultTabTable'] .
+
+ Without configuring the storage, you can still access the recently used tables,
+ but it will disappear after you logout.
+
+ To allow the usage of this functionality:
+
+
+ set up pmadb and the phpMyAdmin configuration storage
+ put the table name in $cfg['Servers'][$i]['recent'] (e.g. 'pma_recent')
+
+
+
$cfg['Servers'][$i]['tracking'] string
@@ -1469,6 +1492,10 @@ CREATE DATABASE,ALTER DATABASE,DROP DATABASE
Defines how many sublevels should be displayed when splitting
up tables by the above separator.
+ $cfg['LeftRecentTable'] integer
+ The maximum number of recently used tables shown in the left navigation
+ frame. Set this to 0 (zero) to disable the listing of recent tables.
+
$cfg['ShowTooltip'] boolean
Defines whether to display table comment as tool-tip in left frame or
not.
diff --git a/config.sample.inc.php b/config.sample.inc.php
index 0ea16d5f76..95d3a1a911 100644
--- a/config.sample.inc.php
+++ b/config.sample.inc.php
@@ -52,6 +52,7 @@ $cfg['Servers'][$i]['AllowNoPassword'] = false;
// $cfg['Servers'][$i]['pdf_pages'] = 'pma_pdf_pages';
// $cfg['Servers'][$i]['column_info'] = 'pma_column_info';
// $cfg['Servers'][$i]['history'] = 'pma_history';
+// $cfg['Servers'][$i]['recent'] = 'pma_recent';
// $cfg['Servers'][$i]['tracking'] = 'pma_tracking';
// $cfg['Servers'][$i]['designer_coords'] = 'pma_designer_coords';
// $cfg['Servers'][$i]['userconfig'] = 'pma_userconfig';
diff --git a/js/functions.js b/js/functions.js
index a5118df9a2..f745e8c106 100644
--- a/js/functions.js
+++ b/js/functions.js
@@ -2287,6 +2287,10 @@ $(document).ready(function() {
}
});
+ $('#update_recent_tables').ready(function() {
+ window.parent.frame_navigation.PMA_reloadRecentTable();
+ });
+
}) // end of $(document).ready()
/**
diff --git a/js/navigation.js b/js/navigation.js
index 505284895a..52d13cfd4d 100644
--- a/js/navigation.js
+++ b/js/navigation.js
@@ -167,6 +167,19 @@ function clear_fast_filter() {
elm.focus();
}
+/**
+ * Reloads the recent tables list.
+ */
+function PMA_reloadRecentTable() {
+ $.get('navigation.php',
+ { 'token' : window.parent.token, 'ajax_request' : true, 'recent_table' : true },
+ function (data) {
+ if (data.success == true) {
+ $('#recentTable').html(data.options);
+ }
+ });
+}
+
/* Performed on load */
$(document).ready(function(){
/* Display filter */
@@ -179,4 +192,14 @@ $(document).ready(function(){
$('#clear_fast_filter').click(clear_fast_filter);
$('#fast_filter').focus(function (evt) {evt.target.select();});
$('#fast_filter').keyup(function (evt) {fast_filter(evt.target.value);});
+
+ /* Jump to recent table */
+ $('#recentTable').change(function() {
+ if (this.value != '') {
+ var arr = this.value.split('.');
+ window.parent.setDb(arr[0]);
+ window.parent.setTable(arr[1]);
+ window.parent.refreshMain($('#LeftDefaultTabTable')[0].value);
+ }
+ });
});
diff --git a/libraries/RecentTable.class.php b/libraries/RecentTable.class.php
new file mode 100644
index 0000000000..ebe93f5fd7
--- /dev/null
+++ b/libraries/RecentTable.class.php
@@ -0,0 +1,200 @@
+pma_table = PMA_backquote($GLOBALS['cfg']['Server']['pmadb']) .".".
+ PMA_backquote($GLOBALS['cfg']['Server']['recent']);
+ }
+ if (! isset($_SESSION['tmp_user_values']['recent_tables'])) {
+ $_SESSION['tmp_user_values']['recent_tables'] =
+ isset($this->pma_table) ? $this->getFromDb() : array();
+ }
+ $this->tables =& $_SESSION['tmp_user_values']['recent_tables'];
+ }
+
+ /**
+ * Returns class instance.
+ *
+ * @return RecentTable
+ */
+ public static function getInstance()
+ {
+ if (is_null(self::$_instance)) {
+ self::$_instance = new RecentTable();
+ }
+ return self::$_instance;
+ }
+
+ /**
+ * Returns recently used tables from phpMyAdmin database.
+ *
+ * @uses $pma_table
+ * @uses PMA_query_as_controluser()
+ * @uses PMA_DBI_fetch_array()
+ * @uses json_decode()
+ *
+ * @return array
+ */
+ public function getFromDb()
+ {
+ // Read from phpMyAdmin database, if recent tables is not in session
+ $sql_query =
+ " SELECT `tables` FROM " . $this->pma_table .
+ " WHERE `username` = '" . $GLOBALS['cfg']['Server']['user'] . "'";
+
+ $row = PMA_DBI_fetch_array(PMA_query_as_controluser($sql_query));
+ if (isset($row[0])) {
+ return json_decode($row[0]);
+ } else {
+ return array();
+ }
+ }
+
+ /**
+ * Save recent tables into phpMyAdmin database.
+ *
+ * @uses PMA_DBI_try_query()
+ * @uses json_decode()
+ * @uses PMA_Message
+ *
+ * @return true|PMA_Message
+ */
+ public function saveToDb()
+ {
+ $username = $GLOBALS['cfg']['Server']['user'];
+ $sql_query =
+ " REPLACE INTO " . $this->pma_table . " (`username`, `tables`)" .
+ " VALUES ('" . $username . "', '" . PMA_sqlAddslashes(json_encode($this->tables)) . "')";
+
+ $success = PMA_DBI_try_query($sql_query, $GLOBALS['controllink']);
+
+ if (!$success) {
+ $message = PMA_Message::error(__('Could not save recent table'));
+ $message->addMessage(' ');
+ $message->addMessage(PMA_Message::rawError(PMA_DBI_getError($GLOBALS['controllink'])));
+ return $message;
+ }
+ return true;
+ }
+
+ /**
+ * Trim recent table according to the LeftRecentTable configuration.
+ *
+ * @return boolean True if trimming occurred
+ */
+ public function trim()
+ {
+ $max = max($GLOBALS['cfg']['LeftRecentTable'], 0);
+ $trimming_occured = count($this->tables) > $max;
+ while (count($this->tables) > $max) {
+ array_pop($this->tables);
+ }
+ return $trimming_occured;
+ }
+
+ /**
+ * Return options for HTML select.
+ *
+ * @return string
+ */
+ public function getHtmlSelectOption()
+ {
+ // trim and save, in case where the configuration is changed
+ if ($this->trim() && isset($this->pma_table)) {
+ $this->saveToDb();
+ }
+
+ $html = '(' . __('Recent tables') . ') ... ';
+ if (count($this->tables)) {
+ foreach ($this->tables as $table) {
+ $html .= '' . $table . ' ';
+ }
+ } else {
+ $html .= '' . __('There are no recent tables') . ' ';
+ }
+ return $html;
+ }
+
+ /**
+ * Return HTML select.
+ *
+ * @return string
+ */
+ public function getHtmlSelect()
+ {
+ $html = ' ';
+ $html .= '';
+ $html .= $this->getHtmlSelectOption();
+ $html .= ' ';
+
+ return $html;
+ }
+
+ /**
+ * Add recently used tables.
+ *
+ * @param string $db Database name where the table is located
+ * @param string $table Table name
+ *
+ * @return true|PMA_Message True if success, PMA_Message if not
+ */
+ public function add($db, $table)
+ {
+ $table_str = $db . '.' . $table;
+
+ // add only if this is new table
+ if (! isset($this->tables[0]) || $this->tables[0] != $table_str) {
+ array_unshift($this->tables, $table_str);
+ $this->tables = array_merge(array_unique($this->tables));
+ $this->trim();
+ if (isset($this->pma_table)) {
+ return $this->saveToDb();
+ }
+ }
+ return true;
+ }
+
+}
+?>
diff --git a/libraries/config.default.php b/libraries/config.default.php
index 4ca31e78f5..5c0b1b2d14 100644
--- a/libraries/config.default.php
+++ b/libraries/config.default.php
@@ -338,6 +338,13 @@ $cfg['Servers'][$i]['history'] = '';
*/
$cfg['Servers'][$i]['designer_coords'] = '';
+/**
+ * table to store recently used tables
+ * - leave blank for no "persistent" recently used tables
+ * SUGGESTED: 'pma_recent'
+ */
+$cfg['Servers'][$i]['recent'] = '';
+
/**
* table to store SQL tracking
* - leave blank for no SQL tracking
@@ -794,6 +801,13 @@ $cfg['LeftLogoLink'] = 'main.php';
*/
$cfg['LeftLogoLinkWindow'] = 'main';
+/**
+ * number of recently used tables displayed in the navigation frame
+ *
+ * @global integer $cfg['LeftRecentTable']
+ */
+$cfg['LeftRecentTable'] = 10;
+
/**
* display a JavaScript table filter in the left frame
* when more then x tables are present
diff --git a/libraries/config.values.php b/libraries/config.values.php
index b5190370a4..d884e59a01 100644
--- a/libraries/config.values.php
+++ b/libraries/config.values.php
@@ -159,6 +159,7 @@ $cfg_db['_validators'] = array(
'Import/skip_queries' => 'validate_non_negative_number',
'InsertRows' => 'validate_positive_number',
'LeftFrameTableLevel' => 'validate_positive_number',
+ 'LeftRecentTable' => 'validate_non_negative_number',
'LimitChars' => 'validate_positive_number',
'LoginCookieValidity' => 'validate_positive_number',
'LoginCookieStore' => 'validate_non_negative_number',
diff --git a/libraries/config/messages.inc.php b/libraries/config/messages.inc.php
index 8ea3cefe20..e8ce0df96b 100644
--- a/libraries/config/messages.inc.php
+++ b/libraries/config/messages.inc.php
@@ -283,6 +283,8 @@ $strConfigLeftLogoLinkWindow_desc = __('Open the linked page in the main window
$strConfigLeftLogoLinkWindow_name = __('Logo link target');
$strConfigLeftPointerEnable_desc = __('Highlight server under the mouse cursor');
$strConfigLeftPointerEnable_name = __('Enable highlighting');
+$strConfigLeftRecentTable_desc = __('Maximum number of recently used tables; set 0 to disable');
+$strConfigLeftRecentTable_name = __('Recently used tables');
$strConfigLightTabs_desc = __('Use less graphically intense tabs');
$strConfigLightTabs_name = __('Light tabs');
$strConfigLimitChars_desc = __('Maximum number of characters shown in any non-numeric column on browse view');
@@ -401,6 +403,8 @@ $strConfigServers_pmadb_desc = __('Database used for relations, bookmarks, and P
$strConfigServers_pmadb_name = __('Database name');
$strConfigServers_port_desc = __('Port on which MySQL server is listening, leave empty for default');
$strConfigServers_port_name = __('Server port');
+$strConfigServers_recent_desc = __('Leave blank for no "persistent" recently used tables across sessions, suggested: [kbd]pma_recent[/kbd]');
+$strConfigServers_recent_name = __('Recently used table');
$strConfigServers_relation_desc = __('Leave blank for no [a@http://wiki.phpmyadmin.net/pma/relation]relation-links[/a] support, suggested: [kbd]pma_relation[/kbd]');
$strConfigServers_relation_name = __('Relation table');
$strConfigServers_ShowDatabasesCommand_desc = __('SQL command to fetch available databases');
diff --git a/libraries/config/setup.forms.php b/libraries/config/setup.forms.php
index 5287aade93..7269823d2d 100644
--- a/libraries/config/setup.forms.php
+++ b/libraries/config/setup.forms.php
@@ -73,6 +73,7 @@ $forms['Servers']['Server_pmadb'] = array('Servers' => array(1 => array(
'table_info' => 'pma_table_info',
'column_info' => 'pma_column_info',
'history' => 'pma_history',
+ 'recent' => 'pma_recent',
'tracking' => 'pma_tracking',
'table_coords' => 'pma_table_coords',
'pdf_pages' => 'pma_pdf_pages',
@@ -162,7 +163,8 @@ $forms['Left_frame']['Left_frame'] = array(
'LeftDisplayLogo',
'LeftLogoLink',
'LeftLogoLinkWindow',
- 'LeftPointerEnable');
+ 'LeftPointerEnable',
+ 'LeftRecentTable');
$forms['Left_frame']['Left_servers'] = array(
'LeftDisplayServers',
'DisplayServersList');
diff --git a/libraries/config/user_preferences.forms.php b/libraries/config/user_preferences.forms.php
index d23eddafef..ffe036632f 100644
--- a/libraries/config/user_preferences.forms.php
+++ b/libraries/config/user_preferences.forms.php
@@ -77,7 +77,8 @@ $forms['Left_frame']['Left_frame'] = array(
'LeftDisplayLogo',
'LeftLogoLink',
'LeftLogoLinkWindow',
- 'LeftPointerEnable');
+ 'LeftPointerEnable',
+ 'LeftRecentTable');
$forms['Left_frame']['Left_databases'] = array(
'DisplayDatabasesList',
'LeftFrameDBTree',
diff --git a/libraries/header.inc.php b/libraries/header.inc.php
index f6c3dcd14c..4036f862ea 100644
--- a/libraries/header.inc.php
+++ b/libraries/header.inc.php
@@ -8,12 +8,26 @@ if (! defined('PHPMYADMIN')) {
exit;
}
-/**
- *
- */
require_once './libraries/common.inc.php';
+require_once './libraries/RecentTable.class.php';
+/**
+ * Add recently used table and reload the navigation.
+ *
+ * @param string $db Database name where the table is located.
+ * @param string $table The table name
+ */
+function PMA_addRecentTable($db, $table) {
+ $tmp_result = RecentTable::getInstance()->add($db, $table);
+ if ($tmp_result === true) {
+ echo ' ';
+ } else {
+ $error = $tmp_result;
+ $error->display();
+ }
+}
+
/**
* This is not an Ajax request so we need to generate all this output.
*/
@@ -151,6 +165,11 @@ if (isset($GLOBALS['is_ajax_request']) && !$GLOBALS['is_ajax_request']) {
.'"' . htmlspecialchars($show_comment)
.'"' . "\n";
} // end if
+
+ // add recently used table and reload the navigation
+ if ($GLOBALS['cfg']['LeftRecentTable'] > 0) {
+ PMA_addRecentTable($GLOBALS['db'], $GLOBALS['table']);
+ }
} else {
// no table selected, display database comment if present
/**
diff --git a/libraries/relation.lib.php b/libraries/relation.lib.php
index 338f833a91..87521a9131 100644
--- a/libraries/relation.lib.php
+++ b/libraries/relation.lib.php
@@ -138,6 +138,10 @@ function PMA_printRelationsParamDiagnostic($cfgRelation)
PMA_printDiagMessageForFeature(__('Designer'), 'designerwork', $messages);
+ PMA_printDiagMessageForParameter('recent', isset($cfgRelation['recent']), $messages, 'recent');
+
+ PMA_printDiagMessageForFeature(__('Persistent recently used tables'), 'recentwork', $messages);
+
PMA_printDiagMessageForParameter('tracking', isset($cfgRelation['tracking']), $messages, 'tracking');
PMA_printDiagMessageForFeature(__('Tracking'), 'trackingwork', $messages);
@@ -220,6 +224,7 @@ function PMA__getRelationsParam()
$cfgRelation['commwork'] = false;
$cfgRelation['mimework'] = false;
$cfgRelation['historywork'] = false;
+ $cfgRelation['recentwork'] = false;
$cfgRelation['trackingwork'] = false;
$cfgRelation['designerwork'] = false;
$cfgRelation['userconfigwork'] = false;
@@ -271,6 +276,8 @@ function PMA__getRelationsParam()
$cfgRelation['pdf_pages'] = $curr_table[0];
} elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['history']) {
$cfgRelation['history'] = $curr_table[0];
+ } elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['recent']) {
+ $cfgRelation['recent'] = $curr_table[0];
} elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['tracking']) {
$cfgRelation['tracking'] = $curr_table[0];
} elseif ($curr_table[0] == $GLOBALS['cfg']['Server']['userconfig']) {
@@ -325,6 +332,10 @@ function PMA__getRelationsParam()
$cfgRelation['historywork'] = true;
}
+ if (isset($cfgRelation['recent'])) {
+ $cfgRelation['recentwork'] = true;
+ }
+
if (isset($cfgRelation['tracking'])) {
$cfgRelation['trackingwork'] = true;
}
@@ -346,8 +357,9 @@ function PMA__getRelationsParam()
if ($cfgRelation['relwork'] && $cfgRelation['displaywork']
&& $cfgRelation['pdfwork'] && $cfgRelation['commwork']
&& $cfgRelation['mimework'] && $cfgRelation['historywork']
- && $cfgRelation['trackingwork'] && $cfgRelation['userconfigwork']
- && $cfgRelation['bookmarkwork'] && $cfgRelation['designerwork']) {
+ && $cfgRelation['recentwork'] && $cfgRelation['trackingwork']
+ && $cfgRelation['userconfigwork'] && $cfgRelation['bookmarkwork']
+ && $cfgRelation['designerwork']) {
$cfgRelation['allworks'] = true;
}
diff --git a/navigation.php b/navigation.php
index a07a5166ec..ac128070d5 100644
--- a/navigation.php
+++ b/navigation.php
@@ -53,6 +53,16 @@ function PMA_exitNavigationFrame()
exit;
}
+require_once './libraries/common.lib.php';
+require_once './libraries/RecentTable.class.php';
+
+/**
+ * Check if it is an ajax request to reload the recent tables list.
+ */
+if ($GLOBALS['is_ajax_request'] && $_REQUEST['recent_table']) {
+ PMA_ajaxResponse('', true, array('options' => RecentTable::getInstance()->getHtmlSelectOption()) );
+}
+
// keep the offset of the db list in session before closing it
if (! isset($_SESSION['tmp_user_values']['navi_limit_offset'])) {
$_SESSION['tmp_user_values']['navi_limit_offset'] = 0;
@@ -179,6 +189,14 @@ require_once './libraries/header_http.inc.php';
0) {
+ echo '';
+ echo RecentTable::getInstance()->getHtmlSelect();
+ echo '
';
+}
+
if (! $GLOBALS['server']) {
// no server selected
PMA_exitNavigationFrame();
diff --git a/scripts/create_tables.sql b/scripts/create_tables.sql
index 1efdaadfde..2d6cb56886 100644
--- a/scripts/create_tables.sql
+++ b/scripts/create_tables.sql
@@ -105,6 +105,18 @@ CREATE TABLE IF NOT EXISTS `pma_pdf_pages` (
-- --------------------------------------------------------
+--
+-- Table structure for table `pma_recent`
+--
+
+CREATE TABLE IF NOT EXISTS `pma_recent` (
+ `username` varchar(64) COLLATE utf8_bin NOT NULL,
+ `tables` blob NOT NULL,
+ PRIMARY KEY (`username`)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
+
+-- --------------------------------------------------------
+
--
-- Table structure for table `pma_relation`
--
diff --git a/themes/original/css/theme_left.css.php b/themes/original/css/theme_left.css.php
index 50ffc3984e..f21bca27f0 100644
--- a/themes/original/css/theme_left.css.php
+++ b/themes/original/css/theme_left.css.php
@@ -83,6 +83,16 @@ div#pmalogo {
background-color: ;
padding:.3em;
}
+
+div#recentTableList {
+ text-align: center;
+ margin-bottom: 0.5em;
+}
+
+div#recentTableList select {
+ width: 100%;
+}
+
div#pmalogo,
div#leftframelinks,
div#databaseList {
diff --git a/themes/pmahomme/css/theme_left.css.php b/themes/pmahomme/css/theme_left.css.php
index 467e70a255..e0a6393c5e 100644
--- a/themes/pmahomme/css/theme_left.css.php
+++ b/themes/pmahomme/css/theme_left.css.php
@@ -94,11 +94,21 @@ button {
div#pmalogo {
}
+
+div#recentTableList {
+ text-align: center;
+ margin: 20px 10px 0px 10px;
+}
+
+div#recentTableList select {
+ width: 100%;
+}
+
div#pmalogo,
div#leftframelinks,
div#databaseList {
text-align: center;
- margin: 20px 10px 0px 10px;
+ margin: 5px 10px 0px 10px;
}
ul#databaseList {