aboutsummaryrefslogtreecommitdiff
path: root/srcs/phpmyadmin/libraries/classes/Database/Qbe.php
diff options
context:
space:
mode:
Diffstat (limited to 'srcs/phpmyadmin/libraries/classes/Database/Qbe.php')
-rw-r--r--srcs/phpmyadmin/libraries/classes/Database/Qbe.php1963
1 files changed, 1963 insertions, 0 deletions
diff --git a/srcs/phpmyadmin/libraries/classes/Database/Qbe.php b/srcs/phpmyadmin/libraries/classes/Database/Qbe.php
new file mode 100644
index 0000000..27116d0
--- /dev/null
+++ b/srcs/phpmyadmin/libraries/classes/Database/Qbe.php
@@ -0,0 +1,1963 @@
+<?php
+/* vim: set expandtab sw=4 ts=4 sts=4: */
+/**
+ * Handles DB QBE search
+ *
+ * @package PhpMyAdmin
+ */
+declare(strict_types=1);
+
+namespace PhpMyAdmin\Database;
+
+use PhpMyAdmin\Core;
+use PhpMyAdmin\DatabaseInterface;
+use PhpMyAdmin\Message;
+use PhpMyAdmin\Relation;
+use PhpMyAdmin\SavedSearches;
+use PhpMyAdmin\Table;
+use PhpMyAdmin\Template;
+use PhpMyAdmin\Url;
+use PhpMyAdmin\Util;
+
+/**
+ * Class to handle database QBE search
+ *
+ * @package PhpMyAdmin
+ */
+class Qbe
+{
+ /**
+ * Database name
+ *
+ * @access private
+ * @var string
+ */
+ private $_db;
+ /**
+ * Table Names (selected/non-selected)
+ *
+ * @access private
+ * @var array
+ */
+ private $_criteriaTables;
+ /**
+ * Column Names
+ *
+ * @access private
+ * @var array
+ */
+ private $_columnNames;
+ /**
+ * Number of columns
+ *
+ * @access private
+ * @var integer
+ */
+ private $_criteria_column_count;
+ /**
+ * Number of Rows
+ *
+ * @access private
+ * @var integer
+ */
+ private $_criteria_row_count;
+ /**
+ * Whether to insert a new column
+ *
+ * @access private
+ * @var array
+ */
+ private $_criteriaColumnInsert;
+ /**
+ * Whether to delete a column
+ *
+ * @access private
+ * @var array
+ */
+ private $_criteriaColumnDelete;
+ /**
+ * Whether to insert a new row
+ *
+ * @access private
+ * @var array
+ */
+ private $_criteriaRowInsert;
+ /**
+ * Whether to delete a row
+ *
+ * @access private
+ * @var array
+ */
+ private $_criteriaRowDelete;
+ /**
+ * Already set criteria values
+ *
+ * @access private
+ * @var array
+ */
+ private $_criteria;
+ /**
+ * Previously set criteria values
+ *
+ * @access private
+ * @var array
+ */
+ private $_prev_criteria;
+ /**
+ * AND/OR relation b/w criteria columns
+ *
+ * @access private
+ * @var array
+ */
+ private $_criteriaAndOrColumn;
+ /**
+ * AND/OR relation b/w criteria rows
+ *
+ * @access private
+ * @var array
+ */
+ private $_criteriaAndOrRow;
+ /**
+ * Large width of a column
+ *
+ * @access private
+ * @var string
+ */
+ private $_realwidth;
+ /**
+ * Minimum width of a column
+ *
+ * @access private
+ * @var int
+ */
+ private $_form_column_width;
+ /**
+ * Selected columns in the form
+ *
+ * @access private
+ * @var array
+ */
+ private $_formColumns;
+ /**
+ * Entered aliases in the form
+ *
+ * @access private
+ * @var array
+ */
+ private $_formAliases;
+ /**
+ * Chosen sort options in the form
+ *
+ * @access private
+ * @var array
+ */
+ private $_formSorts;
+ /**
+ * Chosen sort orders in the form
+ *
+ * @access private
+ * @var array
+ */
+ private $_formSortOrders;
+ /**
+ * Show checkboxes in the form
+ *
+ * @access private
+ * @var array
+ */
+ private $_formShows;
+ /**
+ * Entered criteria values in the form
+ *
+ * @access private
+ * @var array
+ */
+ private $_formCriterions;
+ /**
+ * AND/OR column radio buttons in the form
+ *
+ * @access private
+ * @var array
+ */
+ private $_formAndOrCols;
+ /**
+ * AND/OR row radio buttons in the form
+ *
+ * @access private
+ * @var array
+ */
+ private $_formAndOrRows;
+ /**
+ * New column count in case of add/delete
+ *
+ * @access private
+ * @var integer
+ */
+ private $_new_column_count;
+ /**
+ * New row count in case of add/delete
+ *
+ * @access private
+ * @var integer
+ */
+ private $_new_row_count;
+ /**
+ * List of saved searches
+ *
+ * @access private
+ * @var array
+ */
+ private $_savedSearchList = null;
+ /**
+ * Current search
+ *
+ * @access private
+ * @var SavedSearches
+ */
+ private $_currentSearch = null;
+
+ /**
+ * @var Relation
+ */
+ private $relation;
+
+ /**
+ * @var DatabaseInterface
+ */
+ public $dbi;
+
+ /**
+ * @var Template
+ */
+ public $template;
+
+ /**
+ * Public Constructor
+ *
+ * @param Relation $relation Relation object
+ * @param Template $template Template object
+ * @param DatabaseInterface $dbi DatabaseInterface object
+ * @param string $dbname Database name
+ * @param array $savedSearchList List of saved searches
+ * @param SavedSearches $currentSearch Current search id
+ */
+ public function __construct(
+ Relation $relation,
+ Template $template,
+ $dbi,
+ $dbname,
+ array $savedSearchList = [],
+ $currentSearch = null
+ ) {
+ $this->_db = $dbname;
+ $this->_savedSearchList = $savedSearchList;
+ $this->_currentSearch = $currentSearch;
+ $this->dbi = $dbi;
+ $this->relation = $relation;
+ $this->template = $template;
+
+ $this->_loadCriterias();
+ // Sets criteria parameters
+ $this->_setSearchParams();
+ $this->_setCriteriaTablesAndColumns();
+ }
+
+ /**
+ * Initialize criterias
+ *
+ * @return static
+ */
+ private function _loadCriterias()
+ {
+ if (null === $this->_currentSearch
+ || null === $this->_currentSearch->getCriterias()
+ ) {
+ return $this;
+ }
+
+ $criterias = $this->_currentSearch->getCriterias();
+ $_POST = $criterias + $_POST;
+
+ return $this;
+ }
+
+ /**
+ * Getter for current search
+ *
+ * @return SavedSearches
+ */
+ private function _getCurrentSearch()
+ {
+ return $this->_currentSearch;
+ }
+
+ /**
+ * Sets search parameters
+ *
+ * @return void
+ */
+ private function _setSearchParams()
+ {
+ $criteriaColumnCount = $this->_initializeCriteriasCount();
+
+ $this->_criteriaColumnInsert = Core::ifSetOr(
+ $_POST['criteriaColumnInsert'],
+ null,
+ 'array'
+ );
+ $this->_criteriaColumnDelete = Core::ifSetOr(
+ $_POST['criteriaColumnDelete'],
+ null,
+ 'array'
+ );
+
+ $this->_prev_criteria = isset($_POST['prev_criteria'])
+ ? $_POST['prev_criteria']
+ : [];
+ $this->_criteria = isset($_POST['criteria'])
+ ? $_POST['criteria']
+ : array_fill(0, $criteriaColumnCount, '');
+
+ $this->_criteriaRowInsert = isset($_POST['criteriaRowInsert'])
+ ? $_POST['criteriaRowInsert']
+ : array_fill(0, $criteriaColumnCount, '');
+ $this->_criteriaRowDelete = isset($_POST['criteriaRowDelete'])
+ ? $_POST['criteriaRowDelete']
+ : array_fill(0, $criteriaColumnCount, '');
+ $this->_criteriaAndOrRow = isset($_POST['criteriaAndOrRow'])
+ ? $_POST['criteriaAndOrRow']
+ : array_fill(0, $criteriaColumnCount, '');
+ $this->_criteriaAndOrColumn = isset($_POST['criteriaAndOrColumn'])
+ ? $_POST['criteriaAndOrColumn']
+ : array_fill(0, $criteriaColumnCount, '');
+ // sets minimum width
+ $this->_form_column_width = 12;
+ $this->_formColumns = [];
+ $this->_formSorts = [];
+ $this->_formShows = [];
+ $this->_formCriterions = [];
+ $this->_formAndOrRows = [];
+ $this->_formAndOrCols = [];
+ }
+
+ /**
+ * Sets criteria tables and columns
+ *
+ * @return void
+ */
+ private function _setCriteriaTablesAndColumns()
+ {
+ // The tables list sent by a previously submitted form
+ if (Core::isValid($_POST['TableList'], 'array')) {
+ foreach ($_POST['TableList'] as $each_table) {
+ $this->_criteriaTables[$each_table] = ' selected="selected"';
+ }
+ } // end if
+ $all_tables = $this->dbi->query(
+ 'SHOW TABLES FROM ' . Util::backquote($this->_db) . ';',
+ DatabaseInterface::CONNECT_USER,
+ DatabaseInterface::QUERY_STORE
+ );
+ $all_tables_count = $this->dbi->numRows($all_tables);
+ if (0 == $all_tables_count) {
+ Message::error(__('No tables found in database.'))->display();
+ exit;
+ }
+ // The tables list gets from MySQL
+ while (list($table) = $this->dbi->fetchRow($all_tables)) {
+ $columns = $this->dbi->getColumns($this->_db, $table);
+
+ if (empty($this->_criteriaTables[$table])
+ && ! empty($_POST['TableList'])
+ ) {
+ $this->_criteriaTables[$table] = '';
+ } else {
+ $this->_criteriaTables[$table] = ' selected="selected"';
+ } // end if
+
+ // The fields list per selected tables
+ if ($this->_criteriaTables[$table] == ' selected="selected"') {
+ $each_table = Util::backquote($table);
+ $this->_columnNames[] = $each_table . '.*';
+ foreach ($columns as $each_column) {
+ $each_column = $each_table . '.'
+ . Util::backquote($each_column['Field']);
+ $this->_columnNames[] = $each_column;
+ // increase the width if necessary
+ $this->_form_column_width = max(
+ mb_strlen($each_column),
+ $this->_form_column_width
+ );
+ } // end foreach
+ } // end if
+ } // end while
+ $this->dbi->freeResult($all_tables);
+
+ // sets the largest width found
+ $this->_realwidth = $this->_form_column_width . 'ex';
+ }
+ /**
+ * Provides select options list containing column names
+ *
+ * @param integer $column_number Column Number (0,1,2) or more
+ * @param string $selected Selected criteria column name
+ *
+ * @return string HTML for select options
+ */
+ private function _showColumnSelectCell($column_number, $selected = '')
+ {
+ return $this->template->render('database/qbe/column_select_cell', [
+ 'column_number' => $column_number,
+ 'column_names' => $this->_columnNames,
+ 'selected' => $selected,
+ ]);
+ }
+
+ /**
+ * Provides select options list containing sort options (ASC/DESC)
+ *
+ * @param integer $columnNumber Column Number (0,1,2) or more
+ * @param string $selected Selected criteria 'ASC' or 'DESC'
+ *
+ * @return string HTML for select options
+ */
+ private function _getSortSelectCell(
+ $columnNumber,
+ $selected = ''
+ ) {
+ return $this->template->render('database/qbe/sort_select_cell', [
+ 'real_width' => $this->_realwidth,
+ 'column_number' => $columnNumber,
+ 'selected' => $selected,
+ ]);
+ }
+
+ /**
+ * Provides select options list containing sort order
+ *
+ * @param integer $columnNumber Column Number (0,1,2) or more
+ * @param integer $sortOrder Sort order
+ *
+ * @return string HTML for select options
+ */
+ private function _getSortOrderSelectCell($columnNumber, $sortOrder)
+ {
+ $totalColumnCount = $this->_getNewColumnCount();
+ return $this->template->render('database/qbe/sort_order_select_cell', [
+ 'total_column_count' => $totalColumnCount,
+ 'column_number' => $columnNumber,
+ 'sort_order' => $sortOrder,
+ ]);
+ }
+
+ /**
+ * Returns the new column count after adding and removing columns as instructed
+ *
+ * @return int new column count
+ */
+ private function _getNewColumnCount()
+ {
+ $totalColumnCount = $this->_criteria_column_count;
+ if (! empty($this->_criteriaColumnInsert)) {
+ $totalColumnCount += count($this->_criteriaColumnInsert);
+ }
+ if (! empty($this->_criteriaColumnDelete)) {
+ $totalColumnCount -= count($this->_criteriaColumnDelete);
+ }
+ return $totalColumnCount;
+ }
+
+ /**
+ * Provides search form's row containing column select options
+ *
+ * @return string HTML for search table's row
+ */
+ private function _getColumnNamesRow()
+ {
+ $html_output = '<tr class="noclick">';
+ $html_output .= '<th>' . __('Column:') . '</th>';
+ $new_column_count = 0;
+ for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
+ if (isset($this->_criteriaColumnInsert[$column_index])
+ && $this->_criteriaColumnInsert[$column_index] == 'on'
+ ) {
+ $html_output .= $this->_showColumnSelectCell(
+ $new_column_count
+ );
+ $new_column_count++;
+ }
+ if (! empty($this->_criteriaColumnDelete)
+ && isset($this->_criteriaColumnDelete[$column_index])
+ && $this->_criteriaColumnDelete[$column_index] == 'on'
+ ) {
+ continue;
+ }
+ $selected = '';
+ if (isset($_POST['criteriaColumn'][$column_index])) {
+ $selected = $_POST['criteriaColumn'][$column_index];
+ $this->_formColumns[$new_column_count]
+ = $_POST['criteriaColumn'][$column_index];
+ }
+ $html_output .= $this->_showColumnSelectCell(
+ $new_column_count,
+ $selected
+ );
+ $new_column_count++;
+ } // end for
+ $this->_new_column_count = $new_column_count;
+ $html_output .= '</tr>';
+ return $html_output;
+ }
+
+ /**
+ * Provides search form's row containing column aliases
+ *
+ * @return string HTML for search table's row
+ */
+ private function _getColumnAliasRow()
+ {
+ $html_output = '<tr class="noclick">';
+ $html_output .= '<th>' . __('Alias:') . '</th>';
+ $new_column_count = 0;
+
+ for ($colInd = 0; $colInd < $this->_criteria_column_count; $colInd++) {
+ if (! empty($this->_criteriaColumnInsert)
+ && isset($this->_criteriaColumnInsert[$colInd])
+ && $this->_criteriaColumnInsert[$colInd] == 'on'
+ ) {
+ $html_output .= '<td class="center">';
+ $html_output .= '<input type="text"'
+ . ' name="criteriaAlias[' . $new_column_count . ']">';
+ $html_output .= '</td>';
+ $new_column_count++;
+ } // end if
+
+ if (! empty($this->_criteriaColumnDelete)
+ && isset($this->_criteriaColumnDelete[$colInd])
+ && $this->_criteriaColumnDelete[$colInd] == 'on'
+ ) {
+ continue;
+ }
+
+ $tmp_alias = '';
+ if (! empty($_POST['criteriaAlias'][$colInd])) {
+ $tmp_alias
+ = $this->_formAliases[$new_column_count]
+ = $_POST['criteriaAlias'][$colInd];
+ }// end if
+
+ $html_output .= '<td class="center">';
+ $html_output .= '<input type="text"'
+ . ' name="criteriaAlias[' . $new_column_count . ']"'
+ . ' value="' . htmlspecialchars($tmp_alias) . '">';
+ $html_output .= '</td>';
+ $new_column_count++;
+ } // end for
+ $html_output .= '</tr>';
+ return $html_output;
+ }
+
+ /**
+ * Provides search form's row containing sort(ASC/DESC) select options
+ *
+ * @return string HTML for search table's row
+ */
+ private function _getSortRow()
+ {
+ $html_output = '<tr class="noclick">';
+ $html_output .= '<th>' . __('Sort:') . '</th>';
+ $new_column_count = 0;
+
+ for ($colInd = 0; $colInd < $this->_criteria_column_count; $colInd++) {
+ if (! empty($this->_criteriaColumnInsert)
+ && isset($this->_criteriaColumnInsert[$colInd])
+ && $this->_criteriaColumnInsert[$colInd] == 'on'
+ ) {
+ $html_output .= $this->_getSortSelectCell($new_column_count);
+ $new_column_count++;
+ } // end if
+
+ if (! empty($this->_criteriaColumnDelete)
+ && isset($this->_criteriaColumnDelete[$colInd])
+ && $this->_criteriaColumnDelete[$colInd] == 'on'
+ ) {
+ continue;
+ }
+ // If they have chosen all fields using the * selector,
+ // then sorting is not available, Fix for Bug #570698
+ if (isset($_POST['criteriaSort'][$colInd])
+ && isset($_POST['criteriaColumn'][$colInd])
+ && mb_substr($_POST['criteriaColumn'][$colInd], -2) == '.*'
+ ) {
+ $_POST['criteriaSort'][$colInd] = '';
+ } //end if
+
+ $selected = '';
+ if (isset($_POST['criteriaSort'][$colInd])) {
+ $this->_formSorts[$new_column_count]
+ = $_POST['criteriaSort'][$colInd];
+
+ if ($_POST['criteriaSort'][$colInd] == 'ASC') {
+ $selected = 'ASC';
+ } elseif ($_POST['criteriaSort'][$colInd] == 'DESC') {
+ $selected = 'DESC';
+ }
+ } else {
+ $this->_formSorts[$new_column_count] = '';
+ }
+
+ $html_output .= $this->_getSortSelectCell(
+ $new_column_count,
+ $selected
+ );
+ $new_column_count++;
+ } // end for
+ $html_output .= '</tr>';
+ return $html_output;
+ }
+
+ /**
+ * Provides search form's row containing sort order
+ *
+ * @return string HTML for search table's row
+ */
+ private function _getSortOrder()
+ {
+ $html_output = '<tr class="noclick">';
+ $html_output .= '<th>' . __('Sort order:') . '</th>';
+ $new_column_count = 0;
+
+ for ($colInd = 0; $colInd < $this->_criteria_column_count; $colInd++) {
+ if (! empty($this->_criteriaColumnInsert)
+ && isset($this->_criteriaColumnInsert[$colInd])
+ && $this->_criteriaColumnInsert[$colInd] == 'on'
+ ) {
+ $html_output .= $this->_getSortOrderSelectCell(
+ $new_column_count,
+ null
+ );
+ $new_column_count++;
+ } // end if
+
+ if (! empty($this->_criteriaColumnDelete)
+ && isset($this->_criteriaColumnDelete[$colInd])
+ && $this->_criteriaColumnDelete[$colInd] == 'on'
+ ) {
+ continue;
+ }
+
+ $sortOrder = null;
+ if (! empty($_POST['criteriaSortOrder'][$colInd])) {
+ $sortOrder
+ = $this->_formSortOrders[$new_column_count]
+ = $_POST['criteriaSortOrder'][$colInd];
+ }
+
+ $html_output .= $this->_getSortOrderSelectCell(
+ $new_column_count,
+ $sortOrder
+ );
+ $new_column_count++;
+ } // end for
+ $html_output .= '</tr>';
+ return $html_output;
+ }
+
+ /**
+ * Provides search form's row containing SHOW checkboxes
+ *
+ * @return string HTML for search table's row
+ */
+ private function _getShowRow()
+ {
+ $html_output = '<tr class="noclick">';
+ $html_output .= '<th>' . __('Show:') . '</th>';
+ $new_column_count = 0;
+ for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
+ if (! empty($this->_criteriaColumnInsert)
+ && isset($this->_criteriaColumnInsert[$column_index])
+ && $this->_criteriaColumnInsert[$column_index] == 'on'
+ ) {
+ $html_output .= '<td class="center">';
+ $html_output .= '<input type="checkbox"'
+ . ' name="criteriaShow[' . $new_column_count . ']">';
+ $html_output .= '</td>';
+ $new_column_count++;
+ } // end if
+ if (! empty($this->_criteriaColumnDelete)
+ && isset($this->_criteriaColumnDelete[$column_index])
+ && $this->_criteriaColumnDelete[$column_index] == 'on'
+ ) {
+ continue;
+ }
+ if (isset($_POST['criteriaShow'][$column_index])) {
+ $checked_options = ' checked="checked"';
+ $this->_formShows[$new_column_count]
+ = $_POST['criteriaShow'][$column_index];
+ } else {
+ $checked_options = '';
+ }
+ $html_output .= '<td class="center">';
+ $html_output .= '<input type="checkbox"'
+ . ' name="criteriaShow[' . $new_column_count . ']"'
+ . $checked_options . '>';
+ $html_output .= '</td>';
+ $new_column_count++;
+ } // end for
+ $html_output .= '</tr>';
+ return $html_output;
+ }
+
+ /**
+ * Provides search form's row containing criteria Inputboxes
+ *
+ * @return string HTML for search table's row
+ */
+ private function _getCriteriaInputboxRow()
+ {
+ $html_output = '<tr class="noclick">';
+ $html_output .= '<th>' . __('Criteria:') . '</th>';
+ $new_column_count = 0;
+ for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
+ if (! empty($this->_criteriaColumnInsert)
+ && isset($this->_criteriaColumnInsert[$column_index])
+ && $this->_criteriaColumnInsert[$column_index] == 'on'
+ ) {
+ $html_output .= '<td class="center">';
+ $html_output .= '<input type="text"'
+ . ' name="criteria[' . $new_column_count . ']"'
+ . ' class="textfield"'
+ . ' style="width: ' . $this->_realwidth . '"'
+ . ' size="20">';
+ $html_output .= '</td>';
+ $new_column_count++;
+ } // end if
+ if (! empty($this->_criteriaColumnDelete)
+ && isset($this->_criteriaColumnDelete[$column_index])
+ && $this->_criteriaColumnDelete[$column_index] == 'on'
+ ) {
+ continue;
+ }
+ $tmp_criteria = '';
+ if (isset($this->_criteria[$column_index])) {
+ $tmp_criteria = $this->_criteria[$column_index];
+ }
+ if ((empty($this->_prev_criteria)
+ || ! isset($this->_prev_criteria[$column_index]))
+ || $this->_prev_criteria[$column_index] != htmlspecialchars($tmp_criteria)
+ ) {
+ $this->_formCriterions[$new_column_count] = $tmp_criteria;
+ } else {
+ $this->_formCriterions[$new_column_count]
+ = $this->_prev_criteria[$column_index];
+ }
+ $html_output .= '<td class="center">';
+ $html_output .= '<input type="hidden"'
+ . ' name="prev_criteria[' . $new_column_count . ']"'
+ . ' value="'
+ . htmlspecialchars($this->_formCriterions[$new_column_count])
+ . '">';
+ $html_output .= '<input type="text"'
+ . ' name="criteria[' . $new_column_count . ']"'
+ . ' value="' . htmlspecialchars($tmp_criteria) . '"'
+ . ' class="textfield"'
+ . ' style="width: ' . $this->_realwidth . '"'
+ . ' size="20">';
+ $html_output .= '</td>';
+ $new_column_count++;
+ } // end for
+ $html_output .= '</tr>';
+ return $html_output;
+ }
+
+ /**
+ * Provides footer options for adding/deleting row/columns
+ *
+ * @param string $type Whether row or column
+ *
+ * @return string HTML for footer options
+ */
+ private function _getFootersOptions($type)
+ {
+ return $this->template->render('database/qbe/footer_options', [
+ 'type' => $type,
+ ]);
+ }
+
+ /**
+ * Provides search form table's footer options
+ *
+ * @return string HTML for table footer
+ */
+ private function _getTableFooters()
+ {
+ $html_output = '<fieldset class="tblFooters">';
+ $html_output .= $this->_getFootersOptions("row");
+ $html_output .= $this->_getFootersOptions("column");
+ $html_output .= '<div class="floatleft">';
+ $html_output .= '<input class="btn btn-secondary" type="submit" name="modify"'
+ . ' value="' . __('Update Query') . '">';
+ $html_output .= '</div>';
+ $html_output .= '</fieldset>';
+ return $html_output;
+ }
+
+ /**
+ * Provides a select list of database tables
+ *
+ * @return string HTML for table select list
+ */
+ private function _getTablesList()
+ {
+ $html_output = '<div class="floatleft width100">';
+ $html_output .= '<fieldset>';
+ $html_output .= '<legend>' . __('Use Tables') . '</legend>';
+ // Build the options list for each table name
+ $options = '';
+ $numTableListOptions = 0;
+ foreach ($this->_criteriaTables as $key => $val) {
+ $options .= '<option value="' . htmlspecialchars($key) . '"' . $val . '>'
+ . str_replace(' ', '&nbsp;', htmlspecialchars($key)) . '</option>';
+ $numTableListOptions++;
+ }
+ $html_output .= '<select name="TableList[]"'
+ . ' multiple="multiple" id="listTable"'
+ . ' size="' . ($numTableListOptions > 30 ? '15' : '7') . '">';
+ $html_output .= $options;
+ $html_output .= '</select>';
+ $html_output .= '</fieldset>';
+ $html_output .= '<fieldset class="tblFooters">';
+ $html_output .= '<input class="btn btn-secondary" type="submit" name="modify" value="'
+ . __('Update Query') . '">';
+ $html_output .= '</fieldset>';
+ $html_output .= '</div>';
+ return $html_output;
+ }
+
+ /**
+ * Provides And/Or modification cell along with Insert/Delete options
+ * (For modifying search form's table columns)
+ *
+ * @param integer $column_number Column Number (0,1,2) or more
+ * @param array|null $selected Selected criteria column name
+ * @param bool $last_column Whether this is the last column
+ *
+ * @return string HTML for modification cell
+ */
+ private function _getAndOrColCell(
+ $column_number,
+ $selected = null,
+ $last_column = false
+ ) {
+ $html_output = '<td class="center">';
+ if (! $last_column) {
+ $html_output .= '<strong>' . __('Or:') . '</strong>';
+ $html_output .= '<input type="radio"'
+ . ' name="criteriaAndOrColumn[' . $column_number . ']"'
+ . ' value="or"' . ($selected['or'] ?? '') . '>';
+ $html_output .= '&nbsp;&nbsp;<strong>' . __('And:') . '</strong>';
+ $html_output .= '<input type="radio"'
+ . ' name="criteriaAndOrColumn[' . $column_number . ']"'
+ . ' value="and"' . ($selected['and'] ?? '') . '>';
+ }
+ $html_output .= '<br>' . __('Ins');
+ $html_output .= '<input type="checkbox"'
+ . ' name="criteriaColumnInsert[' . $column_number . ']">';
+ $html_output .= '&nbsp;&nbsp;' . __('Del');
+ $html_output .= '<input type="checkbox"'
+ . ' name="criteriaColumnDelete[' . $column_number . ']">';
+ $html_output .= '</td>';
+ return $html_output;
+ }
+
+ /**
+ * Provides search form's row containing column modifications options
+ * (For modifying search form's table columns)
+ *
+ * @return string HTML for search table's row
+ */
+ private function _getModifyColumnsRow()
+ {
+ $html_output = '<tr class="noclick">';
+ $html_output .= '<th>' . __('Modify:') . '</th>';
+ $new_column_count = 0;
+ for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
+ if (! empty($this->_criteriaColumnInsert)
+ && isset($this->_criteriaColumnInsert[$column_index])
+ && $this->_criteriaColumnInsert[$column_index] == 'on'
+ ) {
+ $html_output .= $this->_getAndOrColCell($new_column_count);
+ $new_column_count++;
+ } // end if
+
+ if (! empty($this->_criteriaColumnDelete)
+ && isset($this->_criteriaColumnDelete[$column_index])
+ && $this->_criteriaColumnDelete[$column_index] == 'on'
+ ) {
+ continue;
+ }
+
+ if (isset($this->_criteriaAndOrColumn[$column_index])) {
+ $this->_formAndOrCols[$new_column_count]
+ = $this->_criteriaAndOrColumn[$column_index];
+ }
+ $checked_options = [];
+ if (isset($this->_criteriaAndOrColumn[$column_index])
+ && $this->_criteriaAndOrColumn[$column_index] == 'or'
+ ) {
+ $checked_options['or'] = ' checked="checked"';
+ $checked_options['and'] = '';
+ } else {
+ $checked_options['and'] = ' checked="checked"';
+ $checked_options['or'] = '';
+ }
+ $html_output .= $this->_getAndOrColCell(
+ $new_column_count,
+ $checked_options,
+ $column_index + 1 == $this->_criteria_column_count
+ );
+ $new_column_count++;
+ } // end for
+ $html_output .= '</tr>';
+ return $html_output;
+ }
+
+ /**
+ * Provides Insert/Delete options for criteria inputbox
+ * with AND/OR relationship modification options
+ *
+ * @param integer $row_index Number of criteria row
+ * @param array $checked_options If checked
+ *
+ * @return string HTML
+ */
+ private function _getInsDelAndOrCell($row_index, array $checked_options)
+ {
+ $html_output = '<td class="value nowrap">';
+ $html_output .= '<!-- Row controls -->';
+ $html_output .= '<table class="nospacing nopadding">';
+ $html_output .= '<tr>';
+ $html_output .= '<td class="value nowrap">';
+ $html_output .= '<small>' . __('Ins:') . '</small>';
+ $html_output .= '<input type="checkbox"'
+ . ' name="criteriaRowInsert[' . $row_index . ']">';
+ $html_output .= '</td>';
+ $html_output .= '<td class="value">';
+ $html_output .= '<strong>' . __('And:') . '</strong>';
+ $html_output .= '</td>';
+ $html_output .= '<td>';
+ $html_output .= '<input type="radio"'
+ . ' name="criteriaAndOrRow[' . $row_index . ']" value="and"'
+ . $checked_options['and'] . '>';
+ $html_output .= '</td>';
+ $html_output .= '</tr>';
+ $html_output .= '<tr>';
+ $html_output .= '<td class="value nowrap">';
+ $html_output .= '<small>' . __('Del:') . '</small>';
+ $html_output .= '<input type="checkbox"'
+ . ' name="criteriaRowDelete[' . $row_index . ']">';
+ $html_output .= '</td>';
+ $html_output .= '<td class="value">';
+ $html_output .= '<strong>' . __('Or:') . '</strong>';
+ $html_output .= '</td>';
+ $html_output .= '<td>';
+ $html_output .= '<input type="radio"'
+ . ' name="criteriaAndOrRow[' . $row_index . ']"'
+ . ' value="or"' . $checked_options['or'] . '>';
+ $html_output .= '</td>';
+ $html_output .= '</tr>';
+ $html_output .= '</table>';
+ $html_output .= '</td>';
+ return $html_output;
+ }
+
+ /**
+ * Provides rows for criteria inputbox Insert/Delete options
+ * with AND/OR relationship modification options
+ *
+ * @param integer $new_row_index New row index if rows are added/deleted
+ *
+ * @return string HTML table rows
+ */
+ private function _getInputboxRow($new_row_index)
+ {
+ $html_output = '';
+ $new_column_count = 0;
+ for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) {
+ if (! empty($this->_criteriaColumnInsert)
+ && isset($this->_criteriaColumnInsert[$column_index])
+ && $this->_criteriaColumnInsert[$column_index] == 'on'
+ ) {
+ $orFieldName = 'Or' . $new_row_index . '[' . $new_column_count . ']';
+ $html_output .= '<td class="center">';
+ $html_output .= '<input type="text"'
+ . ' name="Or' . $orFieldName . '" class="textfield"'
+ . ' style="width: ' . $this->_realwidth . '" size="20">';
+ $html_output .= '</td>';
+ $new_column_count++;
+ } // end if
+ if (! empty($this->_criteriaColumnDelete)
+ && isset($this->_criteriaColumnDelete[$column_index])
+ && $this->_criteriaColumnDelete[$column_index] == 'on'
+ ) {
+ continue;
+ }
+ $or = 'Or' . $new_row_index;
+ if (! empty($_POST[$or]) && isset($_POST[$or][$column_index])) {
+ $tmp_or = $_POST[$or][$column_index];
+ } else {
+ $tmp_or = '';
+ }
+ $html_output .= '<td class="center">';
+ $html_output .= '<input type="text"'
+ . ' name="Or' . $new_row_index . '[' . $new_column_count . ']"'
+ . ' value="' . htmlspecialchars($tmp_or) . '" class="textfield"'
+ . ' style="width: ' . $this->_realwidth . '" size="20">';
+