Translated using Weblate (Slovenian)
[phpmyadmin.git] / libraries / classes / RecentFavoriteTable.php
blobced49f1918e62862e42f469f68b6ec56cc7b783e
1 <?php
2 /**
3 * Recent and Favorite table list handling
4 */
6 declare(strict_types=1);
8 namespace PhpMyAdmin;
10 use PhpMyAdmin\Html\Generator;
11 use const SORT_REGULAR;
12 use function array_key_exists;
13 use function array_merge;
14 use function array_pop;
15 use function array_unique;
16 use function array_unshift;
17 use function count;
18 use function htmlspecialchars;
19 use function json_decode;
20 use function json_encode;
21 use function max;
22 use function md5;
23 use function ucfirst;
25 /**
26 * Handles the recently used and favorite tables.
28 * @TODO Change the release version in table pma_recent
29 * (#recent in documentation)
31 class RecentFavoriteTable
33 /**
34 * Reference to session variable containing recently used or favorite tables.
36 * @access private
37 * @var array
39 private $tables;
41 /**
42 * Defines type of action, Favorite or Recent table.
44 * @access private
45 * @var string
47 private $tableType;
49 /**
50 * RecentFavoriteTable instances.
52 * @access private
53 * @var array
55 private static $instances = [];
57 /** @var Relation */
58 private $relation;
60 /**
61 * Creates a new instance of RecentFavoriteTable
63 * @param string $type the table type
65 * @access private
67 private function __construct($type)
69 global $dbi;
71 $this->relation = new Relation($dbi);
72 $this->tableType = $type;
73 $server_id = $GLOBALS['server'];
74 if (! isset($_SESSION['tmpval'][$this->tableType . 'Tables'][$server_id])
75 ) {
76 $_SESSION['tmpval'][$this->tableType . 'Tables'][$server_id]
77 = $this->getPmaTable() ? $this->getFromDb() : [];
79 $this->tables
80 =& $_SESSION['tmpval'][$this->tableType . 'Tables'][$server_id];
83 /**
84 * Returns class instance.
86 * @param string $type the table type
88 * @return RecentFavoriteTable
90 public static function getInstance($type)
92 if (! array_key_exists($type, self::$instances)) {
93 self::$instances[$type] = new RecentFavoriteTable($type);
96 return self::$instances[$type];
99 /**
100 * Returns the recent/favorite tables array
102 * @return array
104 public function getTables()
106 return $this->tables;
110 * Returns recently used tables or favorite from phpMyAdmin database.
112 * @return array
114 public function getFromDb()
116 global $dbi;
118 // Read from phpMyAdmin database, if recent tables is not in session
119 $sql_query
120 = ' SELECT `tables` FROM ' . $this->getPmaTable() .
121 " WHERE `username` = '" . $dbi->escapeString($GLOBALS['cfg']['Server']['user']) . "'";
123 $return = [];
124 $result = $this->relation->queryAsControlUser($sql_query, false);
125 if ($result) {
126 $row = $dbi->fetchArray($result);
127 if (isset($row[0])) {
128 $return = json_decode($row[0], true);
132 return $return;
136 * Save recent/favorite tables into phpMyAdmin database.
138 * @return true|Message
140 public function saveToDb()
142 global $dbi;
144 $username = $GLOBALS['cfg']['Server']['user'];
145 $sql_query
146 = ' REPLACE INTO ' . $this->getPmaTable() . ' (`username`, `tables`)' .
147 " VALUES ('" . $dbi->escapeString($username) . "', '"
148 . $dbi->escapeString(
149 json_encode($this->tables)
150 ) . "')";
152 $success = $dbi->tryQuery($sql_query, DatabaseInterface::CONNECT_CONTROL);
154 if (! $success) {
155 $error_msg = '';
156 switch ($this->tableType) {
157 case 'recent':
158 $error_msg = __('Could not save recent table!');
159 break;
161 case 'favorite':
162 $error_msg = __('Could not save favorite table!');
163 break;
165 $message = Message::error($error_msg);
166 $message->addMessage(
167 Message::rawError(
168 $dbi->getError(DatabaseInterface::CONNECT_CONTROL)
170 '<br><br>'
173 return $message;
176 return true;
180 * Trim recent.favorite table according to the
181 * NumRecentTables/NumFavoriteTables configuration.
183 * @return bool True if trimming occurred
185 public function trim()
187 $max = max(
188 $GLOBALS['cfg']['Num' . ucfirst($this->tableType) . 'Tables'],
191 $trimming_occurred = count($this->tables) > $max;
192 while (count($this->tables) > $max) {
193 array_pop($this->tables);
196 return $trimming_occurred;
200 * Return HTML ul.
202 * @return string
204 public function getHtmlList()
206 $html = '';
207 if (count($this->tables)) {
208 if ($this->tableType === 'recent') {
209 foreach ($this->tables as $table) {
210 $html .= '<li class="warp_link">';
211 $recent_url = Url::getFromRoute('/table/recent-favorite', [
212 'db' => $table['db'],
213 'table' => $table['table'],
215 $html .= '<a href="' . $recent_url . '">`'
216 . htmlspecialchars($table['db']) . '`.`'
217 . htmlspecialchars($table['table']) . '`</a>';
218 $html .= '</li>';
220 } else {
221 foreach ($this->tables as $table) {
222 $html .= '<li class="warp_link">';
224 $html .= '<a class="ajax favorite_table_anchor" ';
225 $fav_rm_url = Url::getFromRoute('/database/structure/favorite-table', [
226 'db' => $table['db'],
227 'ajax_request' => true,
228 'favorite_table' => $table['table'],
229 'remove_favorite' => true,
231 $html .= 'href="' . $fav_rm_url
232 . '" title="' . __('Remove from Favorites')
233 . '" data-favtargetn="'
234 . md5($table['db'] . '.' . $table['table'])
235 . '" >'
236 . Generator::getIcon('b_favorite')
237 . '</a>';
239 $table_url = Url::getFromRoute('/table/recent-favorite', [
240 'db' => $table['db'],
241 'table' => $table['table'],
243 $html .= '<a href="' . $table_url . '">`'
244 . htmlspecialchars($table['db']) . '`.`'
245 . htmlspecialchars($table['table']) . '`</a>';
246 $html .= '</li>';
249 } else {
250 $html .= '<li class="warp_link">'
251 . ($this->tableType === 'recent'
252 ? __('There are no recent tables.')
253 : __('There are no favorite tables.'))
254 . '</li>';
257 return $html;
261 * Return HTML.
263 * @return string
265 public function getHtml()
267 $html = '<div class="drop_list">';
268 if ($this->tableType === 'recent') {
269 $html .= '<button title="' . __('Recent tables')
270 . '" class="drop_button btn">'
271 . __('Recent') . '</button><ul id="pma_recent_list">';
272 } else {
273 $html .= '<button title="' . __('Favorite tables')
274 . '" class="drop_button btn">'
275 . __('Favorites') . '</button><ul id="pma_favorite_list">';
277 $html .= $this->getHtmlList();
278 $html .= '</ul></div>';
280 return $html;
284 * Add recently used or favorite tables.
286 * @param string $db database name where the table is located
287 * @param string $table table name
289 * @return true|Message True if success, Message if not
291 public function add($db, $table)
293 global $dbi;
295 // If table does not exist, do not add._getPmaTable()
296 if (! $dbi->getColumns($db, $table)) {
297 return true;
300 $table_arr = [];
301 $table_arr['db'] = $db;
302 $table_arr['table'] = $table;
304 // add only if this is new table
305 if (! isset($this->tables[0]) || $this->tables[0] != $table_arr) {
306 array_unshift($this->tables, $table_arr);
307 $this->tables = array_merge(array_unique($this->tables, SORT_REGULAR));
308 $this->trim();
309 if ($this->getPmaTable()) {
310 return $this->saveToDb();
314 return true;
318 * Removes recent/favorite tables that don't exist.
320 * @param string $db database
321 * @param string $table table
323 * @return bool|Message True if invalid and removed, False if not invalid,
324 * Message if error while removing
326 public function removeIfInvalid($db, $table)
328 global $dbi;
330 foreach ($this->tables as $tbl) {
331 if ($tbl['db'] != $db || $tbl['table'] != $table) {
332 continue;
335 // TODO Figure out a better way to find the existence of a table
336 if (! $dbi->getColumns($tbl['db'], $tbl['table'])) {
337 return $this->remove($tbl['db'], $tbl['table']);
341 return false;
345 * Remove favorite tables.
347 * @param string $db database name where the table is located
348 * @param string $table table name
350 * @return true|Message True if success, Message if not
352 public function remove($db, $table)
354 foreach ($this->tables as $key => $value) {
355 if ($value['db'] != $db || $value['table'] != $table) {
356 continue;
359 unset($this->tables[$key]);
361 if ($this->getPmaTable()) {
362 return $this->saveToDb();
365 return true;
369 * Generate Html for sync Favorite tables anchor. (from localStorage to pmadb)
371 * @return string
373 public function getHtmlSyncFavoriteTables()
375 $retval = '';
376 $server_id = $GLOBALS['server'];
377 if ($server_id == 0) {
378 return '';
380 $cfgRelation = $this->relation->getRelationsParam();
381 // Not to show this once list is synchronized.
382 if ($cfgRelation['favoritework'] && ! isset($_SESSION['tmpval']['favorites_synced'][$server_id])) {
383 $url = Url::getFromRoute('/database/structure/favorite-table', [
384 'ajax_request' => true,
385 'favorite_table' => true,
386 'sync_favorite_tables' => true,
388 $retval = '<a class="hide" id="sync_favorite_tables"';
389 $retval .= ' href="' . $url . '"></a>';
392 return $retval;
396 * Generate Html to update recent tables.
398 * @return string html
400 public static function getHtmlUpdateRecentTables()
402 $retval = '<a class="hide" id="update_recent_tables" href="';
403 $retval .= Url::getFromRoute('/recent-table', [
404 'ajax_request' => true,
405 'recent_table' => true,
407 $retval .= '"></a>';
409 return $retval;
413 * Return the name of the configuration storage table
415 * @return string|null pma table name
417 private function getPmaTable(): ?string
419 $cfgRelation = $this->relation->getRelationsParam();
420 if (! $cfgRelation['recentwork']) {
421 return null;
424 if (! empty($cfgRelation['db'])
425 && ! empty($cfgRelation[$this->tableType])
427 return Util::backquote($cfgRelation['db']) . '.'
428 . Util::backquote($cfgRelation[$this->tableType]);
431 return null;