"Fossies" - the Fresh Open Source Software Archive

Member "phpMyAdmin-5.1.0-english/libraries/classes/Bookmark.php" (24 Feb 2021, 10944 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 "Bookmark.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  * Handles bookmarking SQL queries
    4  */
    5 
    6 declare(strict_types=1);
    7 
    8 namespace PhpMyAdmin;
    9 
   10 use const PREG_SET_ORDER;
   11 use function count;
   12 use function is_array;
   13 use function preg_match_all;
   14 use function preg_replace;
   15 use function str_replace;
   16 use function strlen;
   17 
   18 /**
   19  * Handles bookmarking SQL queries
   20  */
   21 class Bookmark
   22 {
   23     /**
   24      * ID of the bookmark
   25      *
   26      * @var int
   27      */
   28     private $id;
   29     /**
   30      * Database the bookmark belongs to
   31      *
   32      * @var string
   33      */
   34     private $database;
   35     /**
   36      * The user to whom the bookmark belongs, empty for public bookmarks
   37      *
   38      * @var string
   39      */
   40     private $currentUser;
   41     /**
   42      * Label of the bookmark
   43      *
   44      * @var string
   45      */
   46     private $label;
   47     /**
   48      * SQL query that is bookmarked
   49      *
   50      * @var string
   51      */
   52     private $query;
   53 
   54     /** @var DatabaseInterface */
   55     private $dbi;
   56 
   57     /**
   58      * Current user
   59      *
   60      * @var string
   61      */
   62     private $user;
   63 
   64     /**
   65      * @param DatabaseInterface $dbi  DatabaseInterface object
   66      * @param string            $user Current user
   67      */
   68     public function __construct(DatabaseInterface $dbi, string $user)
   69     {
   70         $this->dbi = $dbi;
   71         $this->user = $user;
   72     }
   73 
   74     /**
   75      * Returns the ID of the bookmark
   76      */
   77     public function getId(): int
   78     {
   79         return (int) $this->id;
   80     }
   81 
   82     /**
   83      * Returns the database of the bookmark
   84      */
   85     public function getDatabase(): string
   86     {
   87         return $this->database;
   88     }
   89 
   90     /**
   91      * Returns the user whom the bookmark belongs to
   92      */
   93     public function getUser(): string
   94     {
   95         return $this->currentUser;
   96     }
   97 
   98     /**
   99      * Returns the label of the bookmark
  100      */
  101     public function getLabel(): string
  102     {
  103         return $this->label;
  104     }
  105 
  106     /**
  107      * Returns the query
  108      */
  109     public function getQuery(): string
  110     {
  111         return $this->query;
  112     }
  113 
  114     /**
  115      * Adds a bookmark
  116      *
  117      * @return bool whether the INSERT succeeds or not
  118      *
  119      * @access public
  120      */
  121     public function save(): bool
  122     {
  123         $cfgBookmark = self::getParams($this->user);
  124         if (! is_array($cfgBookmark)) {
  125             return false;
  126         }
  127 
  128         $query = 'INSERT INTO ' . Util::backquote($cfgBookmark['db'])
  129             . '.' . Util::backquote($cfgBookmark['table'])
  130             . ' (id, dbase, user, query, label) VALUES (NULL, '
  131             . "'" . $this->dbi->escapeString($this->database) . "', "
  132             . "'" . $this->dbi->escapeString($this->currentUser) . "', "
  133             . "'" . $this->dbi->escapeString($this->query) . "', "
  134             . "'" . $this->dbi->escapeString($this->label) . "')";
  135 
  136         return $this->dbi->query($query, DatabaseInterface::CONNECT_CONTROL);
  137     }
  138 
  139     /**
  140      * Deletes a bookmark
  141      *
  142      * @return bool true if successful
  143      *
  144      * @access public
  145      */
  146     public function delete(): bool
  147     {
  148         $cfgBookmark = self::getParams($this->user);
  149         if (! is_array($cfgBookmark)) {
  150             return false;
  151         }
  152 
  153         $query  = 'DELETE FROM ' . Util::backquote($cfgBookmark['db'])
  154             . '.' . Util::backquote($cfgBookmark['table'])
  155             . ' WHERE id = ' . $this->id;
  156 
  157         return $this->dbi->tryQuery($query, DatabaseInterface::CONNECT_CONTROL);
  158     }
  159 
  160     /**
  161      * Returns the number of variables in a bookmark
  162      *
  163      * @return int number of variables
  164      */
  165     public function getVariableCount(): int
  166     {
  167         $matches = [];
  168         preg_match_all('/\[VARIABLE[0-9]*\]/', $this->query, $matches, PREG_SET_ORDER);
  169 
  170         return count($matches);
  171     }
  172 
  173     /**
  174      * Replace the placeholders in the bookmark query with variables
  175      *
  176      * @param array $variables array of variables
  177      *
  178      * @return string query with variables applied
  179      */
  180     public function applyVariables(array $variables): string
  181     {
  182         // remove comments that encloses a variable placeholder
  183         $query = (string) preg_replace(
  184             '|/\*(.*\[VARIABLE[0-9]*\].*)\*/|imsU',
  185             '${1}',
  186             $this->query
  187         );
  188         // replace variable placeholders with values
  189         $number_of_variables = $this->getVariableCount();
  190         for ($i = 1; $i <= $number_of_variables; $i++) {
  191             $var = '';
  192             if (! empty($variables[$i])) {
  193                 $var = $this->dbi->escapeString($variables[$i]);
  194             }
  195             $query = str_replace('[VARIABLE' . $i . ']', $var, $query);
  196             // backward compatibility
  197             if ($i != 1) {
  198                 continue;
  199             }
  200 
  201             $query = str_replace('[VARIABLE]', $var, $query);
  202         }
  203 
  204         return $query;
  205     }
  206 
  207     /**
  208      * Defines the bookmark parameters for the current user
  209      *
  210      * @param string $user Current user
  211      *
  212      * @return array|bool the bookmark parameters for the current user
  213      *
  214      * @access public
  215      */
  216     public static function getParams(string $user)
  217     {
  218         global $dbi;
  219 
  220         static $cfgBookmark = null;
  221 
  222         if ($cfgBookmark !== null) {
  223             return $cfgBookmark;
  224         }
  225 
  226         $relation = new Relation($dbi);
  227         $cfgRelation = $relation->getRelationsParam();
  228         if ($cfgRelation['bookmarkwork']) {
  229             $cfgBookmark = [
  230                 'user'  => $user,
  231                 'db'    => $cfgRelation['db'],
  232                 'table' => $cfgRelation['bookmark'],
  233             ];
  234         } else {
  235             $cfgBookmark = false;
  236         }
  237 
  238         return $cfgBookmark;
  239     }
  240 
  241     /**
  242      * Creates a Bookmark object from the parameters
  243      *
  244      * @param DatabaseInterface $dbi        DatabaseInterface object
  245      * @param string            $user       Current user
  246      * @param array             $bkm_fields the properties of the bookmark to add; here,
  247      *                                      $bkm_fields['bkm_sql_query'] is urlencoded
  248      * @param bool              $all_users  whether to make the bookmark
  249      *                                      available for all users
  250      *
  251      * @return Bookmark|false
  252      */
  253     public static function createBookmark(
  254         DatabaseInterface $dbi,
  255         string $user,
  256         array $bkm_fields,
  257         bool $all_users = false
  258     ) {
  259         if (! (isset($bkm_fields['bkm_sql_query'], $bkm_fields['bkm_label'])
  260             && strlen($bkm_fields['bkm_sql_query']) > 0
  261             && strlen($bkm_fields['bkm_label']) > 0)
  262         ) {
  263             return false;
  264         }
  265 
  266         $bookmark = new Bookmark($dbi, $user);
  267         $bookmark->database = $bkm_fields['bkm_database'];
  268         $bookmark->label = $bkm_fields['bkm_label'];
  269         $bookmark->query = $bkm_fields['bkm_sql_query'];
  270         $bookmark->currentUser = $all_users ? '' : $bkm_fields['bkm_user'];
  271 
  272         return $bookmark;
  273     }
  274 
  275     /**
  276      * @param DatabaseInterface $dbi  DatabaseInterface object
  277      * @param string            $user Current user
  278      * @param array             $row  Resource used to build the bookmark
  279      */
  280     protected static function createFromRow(
  281         DatabaseInterface $dbi,
  282         string $user,
  283         $row
  284     ): Bookmark {
  285         $bookmark = new Bookmark($dbi, $user);
  286         $bookmark->id = $row['id'];
  287         $bookmark->database = $row['dbase'];
  288         $bookmark->currentUser = $row['user'];
  289         $bookmark->label = $row['label'];
  290         $bookmark->query = $row['query'];
  291 
  292         return $bookmark;
  293     }
  294 
  295     /**
  296      * Gets the list of bookmarks defined for the current database
  297      *
  298      * @param DatabaseInterface $dbi  DatabaseInterface object
  299      * @param string            $user Current user
  300      * @param string|false      $db   the current database name or false
  301      *
  302      * @return Bookmark[] the bookmarks list
  303      *
  304      * @access public
  305      */
  306     public static function getList(
  307         DatabaseInterface $dbi,
  308         string $user,
  309         $db = false
  310     ): array {
  311         $cfgBookmark = self::getParams($user);
  312         if (! is_array($cfgBookmark)) {
  313             return [];
  314         }
  315 
  316         $query = 'SELECT * FROM ' . Util::backquote($cfgBookmark['db'])
  317             . '.' . Util::backquote($cfgBookmark['table'])
  318             . " WHERE ( `user` = ''"
  319             . " OR `user` = '" . $dbi->escapeString($cfgBookmark['user']) . "' )";
  320         if ($db !== false) {
  321             $query .= " AND dbase = '" . $dbi->escapeString($db) . "'";
  322         }
  323         $query .= ' ORDER BY label ASC';
  324 
  325         $result = $dbi->fetchResult(
  326             $query,
  327             null,
  328             null,
  329             DatabaseInterface::CONNECT_CONTROL,
  330             DatabaseInterface::QUERY_STORE
  331         );
  332 
  333         if (! empty($result)) {
  334             $bookmarks = [];
  335             foreach ($result as $row) {
  336                 $bookmarks[] = self::createFromRow($dbi, $user, $row);
  337             }
  338 
  339             return $bookmarks;
  340         }
  341 
  342         return [];
  343     }
  344 
  345     /**
  346      * Retrieve a specific bookmark
  347      *
  348      * @param DatabaseInterface $dbi                 DatabaseInterface object
  349      * @param string            $user                Current user
  350      * @param string            $db                  the current database name
  351      * @param int|string        $id                  an identifier of the bookmark to get
  352      * @param string            $id_field            which field to look up the identifier
  353      * @param bool              $action_bookmark_all true: get all bookmarks regardless
  354      *                                               of the owning user
  355      * @param bool              $exact_user_match    whether to ignore bookmarks with no user
  356      *
  357      * @return Bookmark|null the bookmark
  358      *
  359      * @access public
  360      */
  361     public static function get(
  362         DatabaseInterface $dbi,
  363         string $user,
  364         string $db,
  365         $id,
  366         string $id_field = 'id',
  367         bool $action_bookmark_all = false,
  368         bool $exact_user_match = false
  369     ): ?self {
  370         $cfgBookmark = self::getParams($user);
  371         if (! is_array($cfgBookmark)) {
  372             return null;
  373         }
  374 
  375         $query = 'SELECT * FROM ' . Util::backquote($cfgBookmark['db'])
  376             . '.' . Util::backquote($cfgBookmark['table'])
  377             . " WHERE dbase = '" . $dbi->escapeString($db) . "'";
  378         if (! $action_bookmark_all) {
  379             $query .= " AND (user = '"
  380                 . $dbi->escapeString($cfgBookmark['user']) . "'";
  381             if (! $exact_user_match) {
  382                 $query .= " OR user = ''";
  383             }
  384             $query .= ')';
  385         }
  386         $query .= ' AND ' . Util::backquote($id_field)
  387             . " = '" . $dbi->escapeString((string) $id) . "' LIMIT 1";
  388 
  389         $result = $dbi->fetchSingleRow($query, 'ASSOC', DatabaseInterface::CONNECT_CONTROL);
  390         if (! empty($result)) {
  391             return self::createFromRow($dbi, $user, $result);
  392         }
  393 
  394         return null;
  395     }
  396 }