aboutsummaryrefslogtreecommitdiff
path: root/srcs/phpmyadmin/libraries/classes/Database/Search.php
diff options
context:
space:
mode:
authorCharles <sircharlesaze@gmail.com>2020-01-09 10:55:03 +0100
committerCharles <sircharlesaze@gmail.com>2020-01-09 13:09:38 +0100
commit04d6d5ca99ebfd1cebb8ce06618fb3811fc1a8aa (patch)
tree5c691241355c943a3c68ddb06b8cf8c60aa11319 /srcs/phpmyadmin/libraries/classes/Database/Search.php
parent7e0d85db834d6351ed85d01e5126ac31dc510b86 (diff)
downloadft_server-04d6d5ca99ebfd1cebb8ce06618fb3811fc1a8aa.tar.gz
ft_server-04d6d5ca99ebfd1cebb8ce06618fb3811fc1a8aa.tar.bz2
ft_server-04d6d5ca99ebfd1cebb8ce06618fb3811fc1a8aa.zip
phpmyadmin working
Diffstat (limited to 'srcs/phpmyadmin/libraries/classes/Database/Search.php')
-rw-r--r--srcs/phpmyadmin/libraries/classes/Database/Search.php347
1 files changed, 347 insertions, 0 deletions
diff --git a/srcs/phpmyadmin/libraries/classes/Database/Search.php b/srcs/phpmyadmin/libraries/classes/Database/Search.php
new file mode 100644
index 0000000..3f1b250
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/Database/Search.php
@@ -0,0 +1,347 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Handles Database Search
+ *
+ * @package PhpMyAdmin
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin\Database;
+
+use PhpMyAdmin\DatabaseInterface;
+use PhpMyAdmin\Template;
+use PhpMyAdmin\Util;
+
+/**
+ * Class to handle database search
+ *
+ * @package PhpMyAdmin
+ */
+class Search
+{
+ /**
+ * Database name
+ *
+ * @access private
+ * @var string
+ */
+ private $db;
+
+ /**
+ * Table Names
+ *
+ * @access private
+ * @var array
+ */
+ private $tablesNamesOnly;
+
+ /**
+ * Type of search
+ *
+ * @access private
+ * @var array
+ */
+ private $searchTypes;
+
+ /**
+ * Already set search type
+ *
+ * @access private
+ * @var integer
+ */
+ private $criteriaSearchType;
+
+ /**
+ * Already set search type's description
+ *
+ * @access private
+ * @var string
+ */
+ private $searchTypeDescription;
+
+ /**
+ * Search string/regexp
+ *
+ * @access private
+ * @var string
+ */
+ private $criteriaSearchString;
+
+ /**
+ * Criteria Tables to search in
+ *
+ * @access private
+ * @var array
+ */
+ private $criteriaTables;
+
+ /**
+ * Restrict the search to this column
+ *
+ * @access private
+ * @var string
+ */
+ private $criteriaColumnName;
+
+ /**
+ * @var DatabaseInterface
+ */
+ private $dbi;
+
+ /**
+ * @var Template
+ */
+ public $template;
+
+ /**
+ * Public Constructor
+ *
+ * @param DatabaseInterface $dbi DatabaseInterface object
+ * @param string $db Database name
+ * @param Template $template Template object
+ */
+ public function __construct(DatabaseInterface $dbi, $db, Template $template)
+ {
+ $this->db = $db;
+ $this->dbi = $dbi;
+ $this->searchTypes = [
+ '1' => __('at least one of the words'),
+ '2' => __('all of the words'),
+ '3' => __('the exact phrase as substring'),
+ '4' => __('the exact phrase as whole field'),
+ '5' => __('as regular expression'),
+ ];
+ $this->template = $template;
+ // Sets criteria parameters
+ $this->setSearchParams();
+ }
+
+ /**
+ * Sets search parameters
+ *
+ * @return void
+ */
+ private function setSearchParams()
+ {
+ $this->tablesNamesOnly = $this->dbi->getTables($this->db);
+
+ if (empty($_POST['criteriaSearchType'])
+ || ! is_string($_POST['criteriaSearchType'])
+ || ! array_key_exists(
+ $_POST['criteriaSearchType'],
+ $this->searchTypes
+ )
+ ) {
+ $this->criteriaSearchType = 1;
+ unset($_POST['submit_search']);
+ } else {
+ $this->criteriaSearchType = (int) $_POST['criteriaSearchType'];
+ $this->searchTypeDescription
+ = $this->searchTypes[$_POST['criteriaSearchType']];
+ }
+
+ if (empty($_POST['criteriaSearchString'])
+ || ! is_string($_POST['criteriaSearchString'])
+ ) {
+ $this->criteriaSearchString = '';
+ unset($_POST['submit_search']);
+ } else {
+ $this->criteriaSearchString = $_POST['criteriaSearchString'];
+ }
+
+ $this->criteriaTables = [];
+ if (empty($_POST['criteriaTables'])
+ || ! is_array($_POST['criteriaTables'])
+ ) {
+ unset($_POST['submit_search']);
+ } else {
+ $this->criteriaTables = array_intersect(
+ $_POST['criteriaTables'],
+ $this->tablesNamesOnly
+ );
+ }
+
+ if (empty($_POST['criteriaColumnName'])
+ || ! is_string($_POST['criteriaColumnName'])
+ ) {
+ unset($this->criteriaColumnName);
+ } else {
+ $this->criteriaColumnName = $this->dbi->escapeString(
+ $_POST['criteriaColumnName']
+ );
+ }
+ }
+
+ /**
+ * Builds the SQL search query
+ *
+ * @param string $table The table name
+ *
+ * @return array 3 SQL queries (for count, display and delete results)
+ *
+ * @todo can we make use of fulltextsearch IN BOOLEAN MODE for this?
+ * PMA_backquote
+ * DatabaseInterface::freeResult
+ * DatabaseInterface::fetchAssoc
+ * $GLOBALS['db']
+ * explode
+ * count
+ * strlen
+ */
+ private function getSearchSqls($table)
+ {
+ // Statement types
+ $sqlstr_select = 'SELECT';
+ $sqlstr_delete = 'DELETE';
+ // Table to use
+ $sqlstr_from = ' FROM '
+ . Util::backquote($GLOBALS['db']) . '.'
+ . Util::backquote($table);
+ // Gets where clause for the query
+ $where_clause = $this->getWhereClause($table);
+ // Builds complete queries
+ $sql = [];
+ $sql['select_columns'] = $sqlstr_select . ' * ' . $sqlstr_from
+ . $where_clause;
+ // here, I think we need to still use the COUNT clause, even for
+ // VIEWs, anyway we have a WHERE clause that should limit results
+ $sql['select_count'] = $sqlstr_select . ' COUNT(*) AS `count`'
+ . $sqlstr_from . $where_clause;
+ $sql['delete'] = $sqlstr_delete . $sqlstr_from . $where_clause;
+
+ return $sql;
+ }
+
+ /**
+ * Provides where clause for building SQL query
+ *
+ * @param string $table The table name
+ *
+ * @return string The generated where clause
+ */
+ private function getWhereClause($table)
+ {
+ // Columns to select
+ $allColumns = $this->dbi->getColumns($GLOBALS['db'], $table);
+ $likeClauses = [];
+ // Based on search type, decide like/regex & '%'/''
+ $like_or_regex = (($this->criteriaSearchType == 5) ? 'REGEXP' : 'LIKE');
+ $automatic_wildcard = (($this->criteriaSearchType < 4) ? '%' : '');
+ // For "as regular expression" (search option 5), LIKE won't be used
+ // Usage example: If user is searching for a literal $ in a regexp search,
+ // he should enter \$ as the value.
+ $criteriaSearchStringEscaped = $this->dbi->escapeString(
+ $this->criteriaSearchString
+ );
+ // Extract search words or pattern
+ $search_words = (($this->criteriaSearchType > 2)
+ ? [$criteriaSearchStringEscaped]
+ : explode(' ', $criteriaSearchStringEscaped));
+
+ foreach ($search_words as $search_word) {
+ // Eliminates empty values
+ if (strlen($search_word) === 0) {
+ continue;
+ }
+ $likeClausesPerColumn = [];
+ // for each column in the table
+ foreach ($allColumns as $column) {
+ if (! isset($this->criteriaColumnName)
+ || strlen($this->criteriaColumnName) === 0
+ || $column['Field'] == $this->criteriaColumnName
+ ) {
+ $column = 'CONVERT(' . Util::backquote($column['Field'])
+ . ' USING utf8)';
+ $likeClausesPerColumn[] = $column . ' ' . $like_or_regex . ' '
+ . "'"
+ . $automatic_wildcard . $search_word . $automatic_wildcard
+ . "'";
+ }
+ } // end for
+ if (count($likeClausesPerColumn) > 0) {
+ $likeClauses[] = implode(' OR ', $likeClausesPerColumn);
+ }
+ } // end for
+ // Use 'OR' if 'at least one word' is to be searched, else use 'AND'
+ $implode_str = ($this->criteriaSearchType == 1 ? ' OR ' : ' AND ');
+ if (empty($likeClauses)) {
+ // this could happen when the "inside column" does not exist
+ // in any selected tables
+ $where_clause = ' WHERE FALSE';
+ } else {
+ $where_clause = ' WHERE ('
+ . implode(') ' . $implode_str . ' (', $likeClauses)
+ . ')';
+ }
+ return $where_clause;
+ }
+
+ /**
+ * Displays database search results
+ *
+ * @return string HTML for search results
+ */
+ public function getSearchResults()
+ {
+ $resultTotal = 0;
+ $rows = [];
+ // For each table selected as search criteria
+ foreach ($this->criteriaTables as $eachTable) {
+ // Gets the SQL statements
+ $newSearchSqls = $this->getSearchSqls($eachTable);
+ // Executes the "COUNT" statement
+ $resultCount = intval($this->dbi->fetchValue(
+ $newSearchSqls['select_count']
+ ));
+ $resultTotal += $resultCount;
+ // Gets the result row's HTML for a table
+ $rows[] = [
+ 'table' => htmlspecialchars($eachTable),
+ 'new_search_sqls' => $newSearchSqls,
+ 'result_count' => $resultCount,
+ ];
+ }
+
+ return $this->template->render('database/search/results', [
+ 'db' => $this->db,
+ 'rows' => $rows,
+ 'result_total' => $resultTotal,
+ 'criteria_tables' => $this->criteriaTables,
+ 'criteria_search_string' => htmlspecialchars($this->criteriaSearchString),
+ 'search_type_description' => $this->searchTypeDescription,
+ ]);
+ }
+
+ /**
+ * Provides the main search form's html
+ *
+ * @return string HTML for selection form
+ */
+ public function getMainHtml()
+ {
+ $choices = [
+ '1' => $this->searchTypes[1] . ' '
+ . Util::showHint(
+ __('Words are separated by a space character (" ").')
+ ),
+ '2' => $this->searchTypes[2] . ' '
+ . Util::showHint(
+ __('Words are separated by a space character (" ").')
+ ),
+ '3' => $this->searchTypes[3],
+ '4' => $this->searchTypes[4],
+ '5' => $this->searchTypes[5] . ' ' . Util::showMySQLDocu('Regexp'),
+ ];
+ return $this->template->render('database/search/main', [
+ 'db' => $this->db,
+ 'choices' => $choices,
+ 'criteria_search_string' => $this->criteriaSearchString,
+ 'criteria_search_type' => $this->criteriaSearchType,
+ 'criteria_tables' => $this->criteriaTables,
+ 'tables_names_only' => $this->tablesNamesOnly,
+ 'criteria_column_name' => isset($this->criteriaColumnName)
+ ? $this->criteriaColumnName : null,
+ ]);
+ }
+}