diff --git a/config.sample.inc.php b/config.sample.inc.php
index 2b3024d12d..0e57bc50d2 100644
--- a/config.sample.inc.php
+++ b/config.sample.inc.php
@@ -57,6 +57,7 @@ $cfg['Servers'][$i]['AllowNoPassword'] = false;
// $cfg['Servers'][$i]['designer_coords'] = 'pma__designer_coords';
// $cfg['Servers'][$i]['userconfig'] = 'pma__userconfig';
// $cfg['Servers'][$i]['recent'] = 'pma__recent';
+// $cfg['Servers'][$i]['favorite'] = 'pma__favorite';
// $cfg['Servers'][$i]['users'] = 'pma__users';
// $cfg['Servers'][$i]['usergroups'] = 'pma__usergroups';
// $cfg['Servers'][$i]['navigationhiding'] = 'pma__navigationhiding';
diff --git a/db_structure.php b/db_structure.php
index e848ad641e..63e36fc9c0 100644
--- a/db_structure.php
+++ b/db_structure.php
@@ -41,6 +41,7 @@ if ((!empty($_POST['submit_mult']) && isset($_POST['selected_tbl']))
$_POST['message'] = PMA_Message::success();
}
}
+
require 'libraries/db_common.inc.php';
$url_query .= '&goto=db_structure.php';
@@ -132,12 +133,14 @@ $overhead_size = (double) 0;
$hidden_fields = array();
$odd_row = true;
$sum_row_count_pre = '';
-
+// Instance of PMA_FavoriteTable class.
+$fav_instance = PMA_FavoriteTable::getInstance();
foreach ($tables as $keyname => $current_table) {
// Get valid statistics whatever is the table type
$drop_query = '';
$drop_message = '';
+ $already_favorite = false;
$overhead = '';
$table_is_view = false;
@@ -251,6 +254,24 @@ foreach ($tables as $keyname => $current_table) {
list($do, $ignored) = PMA_getServerSlaveStatus(
$server_slave_status, $truename
);
+ // Handle favorite table list. ----START----
+ $already_favorite = PMA_checkFavoriteTable($db, $current_table['TABLE_NAME']);
+
+ if (isset($_REQUEST['remove_favorite'])) {
+ if ($already_favorite) {
+ // If already in favorite list, remove it.
+ $favorite_table = $_REQUEST['favorite_table'];
+ $fav_instance->remove($db, $favorite_table);
+ }
+ }
+
+ if (isset($_REQUEST['add_favorite'])) {
+ if (!$already_favorite) {
+ // Otherwise add to favorite list.
+ $favorite_table = $_REQUEST['favorite_table'];
+ $fav_instance->add($db, $favorite_table);
+ }
+ } // Handle favorite table list. ----ENDS----
list($html_output, $odd_row) = PMA_getHtmlForStructureTableRow(
$i, $odd_row, $table_is_view, $current_table,
diff --git a/examples/create_tables.sql b/examples/create_tables.sql
index 8ffbf5ef84..953a4b6bbc 100644
--- a/examples/create_tables.sql
+++ b/examples/create_tables.sql
@@ -119,6 +119,20 @@ CREATE TABLE IF NOT EXISTS `pma__recent` (
-- --------------------------------------------------------
+--
+-- Table structure for table `pma__favorite`
+--
+
+CREATE TABLE IF NOT EXISTS `pma__favorite` (
+ `username` varchar(64) NOT NULL,
+ `tables` text NOT NULL,
+ PRIMARY KEY (`username`)
+)
+ COMMENT='Favorite tables'
+ DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
+
+-- --------------------------------------------------------
+
--
-- Table structure for table `pma__table_uiprefs`
--
diff --git a/js/db_structure.js b/js/db_structure.js
index 63d6f43ee6..25161811fb 100644
--- a/js/db_structure.js
+++ b/js/db_structure.js
@@ -382,4 +382,18 @@ AJAX.registerOnload('db_structure.js', function () {
return false;
}); //end Calculate Real End for InnoDB
+ PMA_tooltip(
+ $("select[name*='funcs']"),
+ 'select',
+ PMA_messages.strFunctionHint
+ );
+ // Add tooltip to favorite icons.
+ $(".favorite_table_anchor").each(function () {
+ PMA_tooltip(
+ $(this),
+ 'a',
+ $(this).attr("title")
+ );
+ });
+
}); // end $()
diff --git a/js/navigation.js b/js/navigation.js
index 07f2874add..5d7d99fd01 100644
--- a/js/navigation.js
+++ b/js/navigation.js
@@ -107,6 +107,20 @@ $(function () {
}
});
+ /**
+ * Jump to favorite table
+ */
+ $('#favoriteTable').live('change', function () {
+ if (this.value !== '') {
+ var arr = jQuery.parseJSON(this.value);
+ var $form = $(this).closest('form');
+ $form.find('input[name=db]').val(arr.db);
+ $form.find('input[name=table]').val(arr.table);
+ $form.submit();
+ $(this).prop('selectedIndex', 0);
+ }
+ });
+
/** Create a Routine, Trigger or Event */
$('li.new_procedure a.ajax, li.new_function a.ajax').live('click', function (event) {
event.preventDefault();
diff --git a/libraries/FavoriteTable.class.php b/libraries/FavoriteTable.class.php
new file mode 100644
index 0000000000..4e445e8240
--- /dev/null
+++ b/libraries/FavoriteTable.class.php
@@ -0,0 +1,271 @@
+_pmaTable
+ = PMA_Util::backquote($GLOBALS['cfg']['Server']['pmadb']) . "."
+ . PMA_Util::backquote($GLOBALS['cfg']['Server']['favorite']);
+ }
+ $server_id = $GLOBALS['server'];
+ if (! isset($_SESSION['tmpval']['favorite_tables'][$server_id])) {
+ $_SESSION['tmpval']['favorite_tables'][$server_id]
+ = isset($this->_pmaTable) ? $this->getFromDb() : array();
+ }
+ $this->tables =& $_SESSION['tmpval']['favorite_tables'][$server_id];
+ }
+
+ /**
+ * Returns class instance.
+ *
+ * @return PMA_FavoriteTable
+ */
+ public static function getInstance()
+ {
+ if (is_null(self::$_instance)) {
+ self::$_instance = new PMA_FavoriteTable();
+ }
+ return self::$_instance;
+ }
+
+ /**
+ * Returns favorite tables from phpMyAdmin database.
+ *
+ * @return array
+ */
+ public function getFromDb()
+ {
+ // Read from phpMyAdmin database, if favorite tables are not in session
+ $sql_query
+ = " SELECT `tables` FROM " . $this->_pmaTable .
+ " WHERE `username` = '" . $GLOBALS['cfg']['Server']['user'] . "'";
+
+ $return = array();
+ $result = PMA_queryAsControlUser($sql_query, false);
+ if ($result) {
+ $row = $GLOBALS['dbi']->fetchArray($result);
+ if (isset($row[0])) {
+ $return = json_decode($row[0], true);
+ }
+ }
+ return $return;
+ }
+
+ /**
+ * Save favorite tables into phpMyAdmin database.
+ *
+ * @return true|PMA_Message
+ */
+ public function saveToDb()
+ {
+ $username = $GLOBALS['cfg']['Server']['user'];
+ $sql_query
+ = " REPLACE INTO " . $this->_pmaTable . " (`username`, `tables`)" .
+ " VALUES ('" . $username . "', '"
+ . PMA_Util::sqlAddSlashes(
+ json_encode($this->tables)
+ ) . "')";
+
+ $success = $GLOBALS['dbi']->tryQuery($sql_query, $GLOBALS['controllink']);
+
+ if (! $success) {
+ $message = PMA_Message::error(__('Could not save favorite table!'));
+ $message->addMessage('
');
+ $message->addMessage(
+ PMA_Message::rawError(
+ $GLOBALS['dbi']->getError($GLOBALS['controllink'])
+ )
+ );
+ return $message;
+ }
+ return true;
+ }
+
+ /**
+ * Remove favorite tables from phpMyAdmin database.
+ *
+ * @return true|PMA_Message
+ */
+ public function removeFromDb()
+ {
+ $username = $GLOBALS['cfg']['Server']['user'];
+ $sql_query
+ = " REPLACE INTO " . $this->_pmaTable . " (`username`, `tables`)" .
+ " VALUES ('" . $username . "', '"
+ . PMA_Util::sqlAddSlashes(
+ json_encode($this->tables)
+ ) . "')";
+
+ $success = $GLOBALS['dbi']->tryQuery($sql_query, $GLOBALS['controllink']);
+
+ if (! $success) {
+ $message = PMA_Message::error(__('Could not remove favorite table!'));
+ $message->addMessage('
');
+ $message->addMessage(
+ PMA_Message::rawError(
+ $GLOBALS['dbi']->getError($GLOBALS['controllink'])
+ )
+ );
+ return $message;
+ }
+ return true;
+ }
+
+ /**
+ * Trim favorite table according to the NumFavoriteTables configuration.
+ *
+ * @return boolean True if trimming occurred
+ */
+ public function trim()
+ {
+ $max = max($GLOBALS['cfg']['NumFavoriteTables'], 0);
+ $trimming_occurred = count($this->tables) > $max;
+ while (count($this->tables) > $max) {
+ array_pop($this->tables);
+ }
+ return $trimming_occurred;
+ }
+
+ /**
+ * 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->_pmaTable)) {
+ $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 = '';
+
+ return $html;
+ }
+
+ /**
+ * Add favorite 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_arr = array();
+ $table_arr['db'] = $db;
+ $table_arr['table'] = $table;
+
+ // add only if this is new table
+ if (! isset($this->tables[0]) || $this->tables[0] != $table_arr) {
+ array_unshift($this->tables, $table_arr);
+ $this->tables = array_merge(array_unique($this->tables, SORT_REGULAR));
+ $this->trim();
+ if (isset($this->_pmaTable)) {
+ return $this->saveToDb();
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Remove favorite 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 remove($db, $table)
+ {
+ $table_arr = array();
+ $table_arr['db'] = $db;
+ $table_arr['table'] = $table;
+ foreach ($this->tables as $key => $value) {
+ if ($value['db'] == $db && $value['table'] == $table) {
+ unset($this->tables[$key]);
+ }
+ }
+ if (isset($this->_pmaTable)) {
+ return $this->removeFromDb();
+ }
+ return true;
+ }
+}
+?>
diff --git a/libraries/Header.class.php b/libraries/Header.class.php
index 798cfadbd5..14ae45dc24 100644
--- a/libraries/Header.class.php
+++ b/libraries/Header.class.php
@@ -11,6 +11,7 @@ if (! defined('PHPMYADMIN')) {
require_once 'libraries/Scripts.class.php';
require_once 'libraries/RecentTable.class.php';
+require_once 'libraries/FavoriteTable.class.php';
require_once 'libraries/Menu.class.php';
require_once 'libraries/navigation/Navigation.class.php';
require_once 'libraries/url_generating.lib.php';
diff --git a/libraries/Util.class.php b/libraries/Util.class.php
index 59f2d20530..e98930825b 100644
--- a/libraries/Util.class.php
+++ b/libraries/Util.class.php
@@ -3418,6 +3418,8 @@ class PMA_Util
$titles['NoExport'] = self::getIcon('bd_export.png', __('Export'));
$titles['Execute'] = self::getIcon('b_nextpage.png', __('Execute'));
$titles['NoExecute'] = self::getIcon('bd_nextpage.png', __('Execute'));
+ $titles['Favorite'] = self::getIcon('b_favorite.png', __(''));
+ $titles['NoFavorite']= self::getIcon('b_no_favorite.png', __(''));
return $titles;
}
diff --git a/libraries/config.default.php b/libraries/config.default.php
index 68ee0fd0e8..b5d1a815f0 100644
--- a/libraries/config.default.php
+++ b/libraries/config.default.php
@@ -413,6 +413,13 @@ $cfg['Servers'][$i]['designer_coords'] = '';
*/
$cfg['Servers'][$i]['recent'] = '';
+/**
+ * table to store favorite tables
+ * - leave blank for no favorite tables
+ * SUGGESTED: 'pma__favorite'
+ */
+$cfg['Servers'][$i]['favorite'] = '';
+
/**
* table to store UI preferences for tables
* - leave blank for no "persistent" UI preferences
@@ -906,6 +913,13 @@ $cfg['NavigationLogoLinkWindow'] = 'main';
*/
$cfg['NumRecentTables'] = 10;
+/**
+ * number of favorite tables displayed in the navigation panel
+ *
+ * @global integer $cfg['NumFavoriteTables']
+ */
+$cfg['NumFavoriteTables'] = 10;
+
/**
* display a JavaScript table filter in the navigation panel
* when more then x tables are present
diff --git a/libraries/config.values.php b/libraries/config.values.php
index 33285614b9..d5b63ad45e 100644
--- a/libraries/config.values.php
+++ b/libraries/config.values.php
@@ -221,6 +221,7 @@ $cfg_db['_validators'] = array(
'Import/skip_queries' => 'validateNonNegativeNumber',
'InsertRows' => 'validatePositiveNumber',
'NumRecentTables' => 'validateNonNegativeNumber',
+ 'NumFavoriteTables' => 'validateNonNegativeNumber',
'LimitChars' => 'validatePositiveNumber',
'LoginCookieValidity' => 'validatePositiveNumber',
'LoginCookieStore' => 'validateNonNegativeNumber',
diff --git a/libraries/config/messages.inc.php b/libraries/config/messages.inc.php
index bcfafdf4f5..f0032047c3 100644
--- a/libraries/config/messages.inc.php
+++ b/libraries/config/messages.inc.php
@@ -471,6 +471,8 @@ $strConfigNavigationTreeDisableDatabaseExpansion_name
= __('Disable database expansion');
$strConfigNumRecentTables_desc
= __('Maximum number of recently used tables; set 0 to disable.');
+$strConfigNumFavoriteTables_desc
+ = __('Maximum number of favorite tables; set 0 to disable.');
$strConfigNumRecentTables_name = __('Recently used tables');
$strConfigRowActionLinks_desc = __('These are Edit, Copy and Delete links.');
$strConfigRowActionLinks_name = __('Where to show the table row links');
diff --git a/libraries/config/setup.forms.php b/libraries/config/setup.forms.php
index 9ba96c752b..d87b63a7d2 100644
--- a/libraries/config/setup.forms.php
+++ b/libraries/config/setup.forms.php
@@ -131,6 +131,7 @@ $forms['Features']['Other_core_settings'] = array(
'MaxDbList',
'MaxTableList',
'NumRecentTables',
+ 'NumFavoriteTables',
'ShowHint',
'OBGzip',
'PersistentConnections',
diff --git a/libraries/config/user_preferences.forms.php b/libraries/config/user_preferences.forms.php
index 6c0e77ece8..98313de90a 100644
--- a/libraries/config/user_preferences.forms.php
+++ b/libraries/config/user_preferences.forms.php
@@ -33,6 +33,7 @@ $forms['Features']['General'] = array(
'MaxDbList',
'MaxTableList',
'NumRecentTables',
+ 'NumFavoriteTables',
'ShowHint',
'SendErrorReports');
$forms['Features']['Text_fields'] = array(
diff --git a/libraries/navigation/NavigationHeader.class.php b/libraries/navigation/NavigationHeader.class.php
index 41d34ed2ca..7577209b60 100644
--- a/libraries/navigation/NavigationHeader.class.php
+++ b/libraries/navigation/NavigationHeader.class.php
@@ -303,11 +303,27 @@ class PMA_NavigationHeader
)
);
$retval .= PMA_RecentTable::getInstance()->getHtmlSelect();
+ $retval .= $this->_favorite();
$retval .= '';
$retval .= '';
$retval .= '';
}
return $retval;
}
+
+ /**
+ * Displays a drop-down choice of favorite tables
+ *
+ * @return string HTML code for the Favorite tables
+ */
+ private function _favorite()
+ {
+ $retval = '';
+ // display favorite tables
+ if ($GLOBALS['cfg']['NumFavoriteTables'] > 0) {
+ $retval .= PMA_FavoriteTable::getInstance()->getHtmlSelect();
+ }
+ return $retval;
+ }
}
?>
diff --git a/libraries/structure.lib.php b/libraries/structure.lib.php
index 981e480d3e..69909f56d5 100644
--- a/libraries/structure.lib.php
+++ b/libraries/structure.lib.php
@@ -181,7 +181,7 @@ function PMA_getHtmlBodyForTableSummary($num_tables, $server_slave_status,
if ($server_slave_status) {
$html_output .= '