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: + + +
+
$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 = ''; + if (count($this->tables)) { + foreach ($this->tables as $table) { + $html .= ''; + } + } else { + $html .= ''; + } + return $html; + } + + /** + * Return HTML select. + * + * @return string + */ + public function getHtmlSelect() + { + $html = ''; + $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 {