"Fossies" - the Fresh Open Source Software Archive

Member "phpMyAdmin-5.1.0-english/libraries/classes/RecentFavoriteTable.php" (24 Feb 2021, 12297 Bytes) of package /linux/www/phpMyAdmin-5.1.0-english.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "RecentFavoriteTable.php" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.0.4-english_vs_5.1.0-english.

    1 <?php
    2 /**
    3  * Recent and Favorite table list handling
    4  */
    5 
    6 declare(strict_types=1);
    7 
    8 namespace PhpMyAdmin;
    9 
   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;
   24 
   25 /**
   26  * Handles the recently used and favorite tables.
   27  *
   28  * @TODO Change the release version in table pma_recent
   29  * (#recent in documentation)
   30  */
   31 class RecentFavoriteTable
   32 {
   33     /**
   34      * Reference to session variable containing recently used or favorite tables.
   35      *
   36      * @access private
   37      * @var array
   38      */
   39     private $tables;
   40 
   41     /**
   42      * Defines type of action, Favorite or Recent table.
   43      *
   44      * @access private
   45      * @var string
   46      */
   47     private $tableType;
   48 
   49     /**
   50      * RecentFavoriteTable instances.
   51      *
   52      * @access private
   53      * @var array
   54      */
   55     private static $instances = [];
   56 
   57     /** @var Relation */
   58     private $relation;
   59 
   60     /**
   61      * Creates a new instance of RecentFavoriteTable
   62      *
   63      * @param string $type the table type
   64      *
   65      * @access private
   66      */
   67     private function __construct($type)
   68     {
   69         global $dbi;
   70 
   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() : [];
   78         }
   79         $this->tables
   80             =& $_SESSION['tmpval'][$this->tableType . 'Tables'][$server_id];
   81     }
   82 
   83     /**
   84      * Returns class instance.
   85      *
   86      * @param string $type the table type
   87      *
   88      * @return RecentFavoriteTable
   89      */
   90     public static function getInstance($type)
   91     {
   92         if (! array_key_exists($type, self::$instances)) {
   93             self::$instances[$type] = new RecentFavoriteTable($type);
   94         }
   95 
   96         return self::$instances[$type];
   97     }
   98 
   99     /**
  100      * Returns the recent/favorite tables array
  101      *
  102      * @return array
  103      */
  104     public function getTables()
  105     {
  106         return $this->tables;
  107     }
  108 
  109     /**
  110      * Returns recently used tables or favorite from phpMyAdmin database.
  111      *
  112      * @return array
  113      */
  114     public function getFromDb()
  115     {
  116         global $dbi;
  117 
  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']) . "'";
  122 
  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);
  129             }
  130         }
  131 
  132         return $return;
  133     }
  134 
  135     /**
  136      * Save recent/favorite tables into phpMyAdmin database.
  137      *
  138      * @return true|Message
  139      */
  140     public function saveToDb()
  141     {
  142         global $dbi;
  143 
  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                 ) . "')";
  151 
  152         $success = $dbi->tryQuery($sql_query, DatabaseInterface::CONNECT_CONTROL);
  153 
  154         if (! $success) {
  155             $error_msg = '';
  156             switch ($this->tableType) {
  157                 case 'recent':
  158                     $error_msg = __('Could not save recent table!');
  159                     break;
  160 
  161                 case 'favorite':
  162                     $error_msg = __('Could not save favorite table!');
  163                     break;
  164             }
  165             $message = Message::error($error_msg);
  166             $message->addMessage(
  167                 Message::rawError(
  168                     $dbi->getError(DatabaseInterface::CONNECT_CONTROL)
  169                 ),
  170                 '<br><br>'
  171             );
  172 
  173             return $message;
  174         }
  175 
  176         return true;
  177     }
  178 
  179     /**
  180      * Trim recent.favorite table according to the
  181      * NumRecentTables/NumFavoriteTables configuration.
  182      *
  183      * @return bool True if trimming occurred
  184      */
  185     public function trim()
  186     {
  187         $max = max(
  188             $GLOBALS['cfg']['Num' . ucfirst($this->tableType) . 'Tables'],
  189             0
  190         );
  191         $trimming_occurred = count($this->tables) > $max;
  192         while (count($this->tables) > $max) {
  193             array_pop($this->tables);
  194         }
  195 
  196         return $trimming_occurred;
  197     }
  198 
  199     /**
  200      * Return HTML ul.
  201      *
  202      * @return string
  203      */
  204     public function getHtmlList()
  205     {
  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'],
  214                     ]);
  215                     $html .= '<a href="' . $recent_url . '">`'
  216                           . htmlspecialchars($table['db']) . '`.`'
  217                           . htmlspecialchars($table['table']) . '`</a>';
  218                     $html .= '</li>';
  219                 }
  220             } else {
  221                 foreach ($this->tables as $table) {
  222                     $html .= '<li class="warp_link">';
  223 
  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,
  230                     ]);
  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>';
  238 
  239                     $table_url = Url::getFromRoute('/table/recent-favorite', [
  240                         'db' => $table['db'],
  241                         'table' => $table['table'],
  242                     ]);
  243                     $html .= '<a href="' . $table_url . '">`'
  244                         . htmlspecialchars($table['db']) . '`.`'
  245                         . htmlspecialchars($table['table']) . '`</a>';
  246                     $html .= '</li>';
  247                 }
  248             }
  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>';
  255         }
  256 
  257         return $html;
  258     }
  259 
  260     /**
  261      * Return HTML.
  262      *
  263      * @return string
  264      */
  265     public function getHtml()
  266     {
  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">';
  276         }
  277         $html .= $this->getHtmlList();
  278         $html .= '</ul></div>';
  279 
  280         return $html;
  281     }
  282 
  283     /**
  284      * Add recently used or favorite tables.
  285      *
  286      * @param string $db    database name where the table is located
  287      * @param string $table table name
  288      *
  289      * @return true|Message True if success, Message if not
  290      */
  291     public function add($db, $table)
  292     {
  293         global $dbi;
  294 
  295         // If table does not exist, do not add._getPmaTable()
  296         if (! $dbi->getColumns($db, $table)) {
  297             return true;
  298         }
  299 
  300         $table_arr = [];
  301         $table_arr['db'] = $db;
  302         $table_arr['table'] = $table;
  303 
  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();
  311             }
  312         }
  313 
  314         return true;
  315     }
  316 
  317     /**
  318      * Removes recent/favorite tables that don't exist.
  319      *
  320      * @param string $db    database
  321      * @param string $table table
  322      *
  323      * @return bool|Message True if invalid and removed, False if not invalid,
  324      * Message if error while removing
  325      */
  326     public function removeIfInvalid($db, $table)
  327     {
  328         global $dbi;
  329 
  330         foreach ($this->tables as $tbl) {
  331             if ($tbl['db'] != $db || $tbl['table'] != $table) {
  332                 continue;
  333             }
  334 
  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']);
  338             }
  339         }
  340 
  341         return false;
  342     }
  343 
  344     /**
  345      * Remove favorite tables.
  346      *
  347      * @param string $db    database name where the table is located
  348      * @param string $table table name
  349      *
  350      * @return true|Message True if success, Message if not
  351      */
  352     public function remove($db, $table)
  353     {
  354         foreach ($this->tables as $key => $value) {
  355             if ($value['db'] != $db || $value['table'] != $table) {
  356                 continue;
  357             }
  358 
  359             unset($this->tables[$key]);
  360         }
  361         if ($this->getPmaTable()) {
  362             return $this->saveToDb();
  363         }
  364 
  365         return true;
  366     }
  367 
  368     /**
  369      * Generate Html for sync Favorite tables anchor. (from localStorage to pmadb)
  370      *
  371      * @return string
  372      */
  373     public function getHtmlSyncFavoriteTables()
  374     {
  375         $retval = '';
  376         $server_id = $GLOBALS['server'];
  377         if ($server_id == 0) {
  378             return '';
  379         }
  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,
  387             ]);
  388             $retval  = '<a class="hide" id="sync_favorite_tables"';
  389             $retval .= ' href="' . $url . '"></a>';
  390         }
  391 
  392         return $retval;
  393     }
  394 
  395     /**
  396      * Generate Html to update recent tables.
  397      *
  398      * @return string html
  399      */
  400     public static function getHtmlUpdateRecentTables()
  401     {
  402         $retval = '<a class="hide" id="update_recent_tables" href="';
  403         $retval .= Url::getFromRoute('/recent-table', [
  404             'ajax_request' => true,
  405             'recent_table' => true,
  406         ]);
  407         $retval .= '"></a>';
  408 
  409         return $retval;
  410     }
  411 
  412     /**
  413      * Return the name of the configuration storage table
  414      *
  415      * @return string|null pma table name
  416      */
  417     private function getPmaTable(): ?string
  418     {
  419         $cfgRelation = $this->relation->getRelationsParam();
  420         if (! $cfgRelation['recentwork']) {
  421             return null;
  422         }
  423 
  424         if (! empty($cfgRelation['db'])
  425             && ! empty($cfgRelation[$this->tableType])
  426         ) {
  427             return Util::backquote($cfgRelation['db']) . '.'
  428                 . Util::backquote($cfgRelation[$this->tableType]);
  429         }
  430 
  431         return null;
  432     }
  433 }