2 /* vim: set expandtab sw=4 ts=4 sts=4: */
4 * Recent and Favorite table list handling
8 declare(strict_types
=1);
13 * Handles the recently used and favorite tables.
15 * @TODO Change the release version in table pma_recent
16 * (#recent in documentation)
20 class RecentFavoriteTable
23 * Reference to session variable containing recently used or favorite tables.
31 * Defines type of action, Favorite or Recent table.
39 * RecentFavoriteTable instances.
44 private static $_instances = [];
52 * Creates a new instance of RecentFavoriteTable
54 * @param string $type the table type
58 private function __construct($type)
60 $this->relation
= new Relation($GLOBALS['dbi']);
61 $this->_tableType
= $type;
62 $server_id = $GLOBALS['server'];
63 if (! isset($_SESSION['tmpval'][$this->_tableType
. 'Tables'][$server_id])
65 $_SESSION['tmpval'][$this->_tableType
. 'Tables'][$server_id]
66 = $this->_getPmaTable() ?
$this->getFromDb() : [];
69 =& $_SESSION['tmpval'][$this->_tableType
. 'Tables'][$server_id];
73 * Returns class instance.
75 * @param string $type the table type
77 * @return RecentFavoriteTable
79 public static function getInstance($type)
81 if (! array_key_exists($type, self
::$_instances)) {
82 self
::$_instances[$type] = new RecentFavoriteTable($type);
84 return self
::$_instances[$type];
88 * Returns the recent/favorite tables array
92 public function getTables()
94 return $this->_tables
;
98 * Returns recently used tables or favorite from phpMyAdmin database.
102 public function getFromDb()
104 // Read from phpMyAdmin database, if recent tables is not in session
106 = " SELECT `tables` FROM " . $this->_getPmaTable() .
107 " WHERE `username` = '" . $GLOBALS['dbi']->escapeString($GLOBALS['cfg']['Server']['user']) . "'";
110 $result = $this->relation
->queryAsControlUser($sql_query, false);
112 $row = $GLOBALS['dbi']->fetchArray($result);
113 if (isset($row[0])) {
114 $return = json_decode($row[0], true);
121 * Save recent/favorite tables into phpMyAdmin database.
123 * @return true|Message
125 public function saveToDb()
127 $username = $GLOBALS['cfg']['Server']['user'];
129 = " REPLACE INTO " . $this->_getPmaTable() . " (`username`, `tables`)" .
130 " VALUES ('" . $GLOBALS['dbi']->escapeString($username) . "', '"
131 . $GLOBALS['dbi']->escapeString(
132 json_encode($this->_tables
)
135 $success = $GLOBALS['dbi']->tryQuery($sql_query, DatabaseInterface
::CONNECT_CONTROL
);
139 switch ($this->_tableType
) {
141 $error_msg = __('Could not save recent table!');
145 $error_msg = __('Could not save favorite table!');
148 $message = Message
::error($error_msg);
149 $message->addMessage(
151 $GLOBALS['dbi']->getError(DatabaseInterface
::CONNECT_CONTROL
)
161 * Trim recent.favorite table according to the
162 * NumRecentTables/NumFavoriteTables configuration.
164 * @return boolean True if trimming occurred
166 public function trim()
169 $GLOBALS['cfg']['Num' . ucfirst($this->_tableType
) . 'Tables'],
172 $trimming_occurred = count($this->_tables
) > $max;
173 while (count($this->_tables
) > $max) {
174 array_pop($this->_tables
);
176 return $trimming_occurred;
184 public function getHtmlList()
187 if (count($this->_tables
)) {
188 if ($this->_tableType
== 'recent') {
189 foreach ($this->_tables
as $table) {
190 $html .= '<li class="warp_link">';
192 'db' => $table['db'],
193 'table' => $table['table'],
195 $recent_url = 'tbl_recent_favorite.php'
196 . Url
::getCommon($recent_params);
197 $html .= '<a href="' . $recent_url . '">`'
198 . htmlspecialchars($table['db']) . '`.`'
199 . htmlspecialchars($table['table']) . '`</a>';
203 foreach ($this->_tables
as $table) {
204 $html .= '<li class="warp_link">';
206 $html .= '<a class="ajax favorite_table_anchor" ';
207 $fav_rm_url = Url
::getFromRoute('/database/structure', [
208 'db' => $table['db'],
209 'ajax_request' => true,
210 'favorite_table' => $table['table'],
211 'remove_favorite' => true,
213 $html .= 'href="' . $fav_rm_url
214 . '" title="' . __("Remove from Favorites")
215 . '" data-favtargetn="'
216 . md5($table['db'] . "." . $table['table'])
218 . Util
::getIcon('b_favorite')
222 'db' => $table['db'],
223 'table' => $table['table'],
225 $table_url = 'tbl_recent_favorite.php'
226 . Url
::getCommon($fav_params);
227 $html .= '<a href="' . $table_url . '">`'
228 . htmlspecialchars($table['db']) . '`.`'
229 . htmlspecialchars($table['table']) . '`</a>';
234 $html .= '<li class="warp_link">'
235 . ($this->_tableType
== 'recent'
236 ?
__('There are no recent tables.')
237 : __('There are no favorite tables.'))
248 public function getHtml()
250 $html = '<div class="drop_list">';
251 if ($this->_tableType
== 'recent') {
252 $html .= '<button title="' . __('Recent tables')
253 . '" class="drop_button btn">'
254 . __('Recent') . '</button><ul id="pma_recent_list">';
256 $html .= '<button title="' . __('Favorite tables')
257 . '" class="drop_button btn">'
258 . __('Favorites') . '</button><ul id="pma_favorite_list">';
260 $html .= $this->getHtmlList();
261 $html .= '</ul></div>';
266 * Add recently used or favorite tables.
268 * @param string $db database name where the table is located
269 * @param string $table table name
271 * @return true|Message True if success, Message if not
273 public function add($db, $table)
275 // If table does not exist, do not add._getPmaTable()
276 if (! $GLOBALS['dbi']->getColumns($db, $table)) {
281 $table_arr['db'] = $db;
282 $table_arr['table'] = $table;
284 // add only if this is new table
285 if (! isset($this->_tables
[0]) ||
$this->_tables
[0] != $table_arr) {
286 array_unshift($this->_tables
, $table_arr);
287 $this->_tables
= array_merge(array_unique($this->_tables
, SORT_REGULAR
));
289 if ($this->_getPmaTable()) {
290 return $this->saveToDb();
297 * Removes recent/favorite tables that don't exist.
299 * @param string $db database
300 * @param string $table table
302 * @return boolean|Message True if invalid and removed, False if not invalid,
303 * Message if error while removing
305 public function removeIfInvalid($db, $table)
307 foreach ($this->_tables
as $tbl) {
308 if ($tbl['db'] == $db && $tbl['table'] == $table) {
309 // TODO Figure out a better way to find the existence of a table
310 if (! $GLOBALS['dbi']->getColumns($tbl['db'], $tbl['table'])) {
311 return $this->remove($tbl['db'], $tbl['table']);
319 * Remove favorite tables.
321 * @param string $db database name where the table is located
322 * @param string $table table name
324 * @return true|Message True if success, Message if not
326 public function remove($db, $table)
328 foreach ($this->_tables
as $key => $value) {
329 if ($value['db'] == $db && $value['table'] == $table) {
330 unset($this->_tables
[$key]);
333 if ($this->_getPmaTable()) {
334 return $this->saveToDb();
340 * Generate Html for sync Favorite tables anchor. (from localStorage to pmadb)
344 public function getHtmlSyncFavoriteTables()
347 $server_id = $GLOBALS['server'];
348 if ($server_id == 0) {
351 $cfgRelation = $this->relation
->getRelationsParam();
352 // Not to show this once list is synchronized.
353 if ($cfgRelation['favoritework'] && ! isset($_SESSION['tmpval']['favorites_synced'][$server_id])) {
354 $url = Url
::getFromRoute('/database/structure', [
355 'ajax_request' => true,
356 'favorite_table' => true,
357 'sync_favorite_tables' => true,
359 $retval = '<a class="hide" id="sync_favorite_tables"';
360 $retval .= ' href="' . $url . '"></a>';
366 * Generate Html to update recent tables.
368 * @return string html
370 public static function getHtmlUpdateRecentTables()
373 'ajax_request' => true,
374 'recent_table' => true,
376 $url = 'index.php' . Url
::getCommon($params);
377 $retval = '<a class="hide" id="update_recent_tables"';
378 $retval .= ' href="' . $url . '"></a>';
383 * Return the name of the configuration storage table
385 * @return string|null pma table name
387 private function _getPmaTable(): ?
string
389 $cfgRelation = $this->relation
->getRelationsParam();
390 if (! empty($cfgRelation['db'])
391 && ! empty($cfgRelation[$this->_tableType
])
393 return Util
::backquote($cfgRelation['db']) . "."
394 . Util
::backquote($cfgRelation[$this->_tableType
]);