Upgraded phpmyadmin to 4.0.4 (All Languages) - No modifications yet
[openemr.git] / phpmyadmin / libraries / TableSearch.class.php
blobd9bb83079b9fde83096a58f7fb9a71651cf78580
1 <?php
2 /* vim: set expandtab sw=4 ts=4 sts=4: */
3 /**
4 * Handles Table search and Zoom search
6 * @package PhpMyAdmin
7 */
8 if (! defined('PHPMYADMIN')) {
9 exit;
12 /**
13 * Class to handle normal-search
14 * and zoom-search in a table
16 * @package PhpMyAdmin
18 class PMA_TableSearch
20 /**
21 * Database name
23 * @access private
24 * @var string
26 private $_db;
27 /**
28 * Table name
30 * @access private
31 * @var string
33 private $_table;
34 /**
35 * Normal search or Zoom search
37 * @access private
38 * @var string
40 private $_searchType;
41 /**
42 * Names of columns
44 * @access private
45 * @var array
47 private $_columnNames;
48 /**
49 * Types of columns
51 * @access private
52 * @var array
54 private $_columnTypes;
55 /**
56 * Collations of columns
58 * @access private
59 * @var array
61 private $_columnCollations;
62 /**
63 * Null Flags of columns
65 * @access private
66 * @var array
68 private $_columnNullFlags;
69 /**
70 * Whether a geometry column is present
72 * @access private
73 * @var boolean
75 private $_geomColumnFlag;
76 /**
77 * Foreign Keys
79 * @access private
80 * @var array
82 private $_foreigners;
85 /**
86 * Public Constructor
88 * @param string $db Database name
89 * @param string $table Table name
90 * @param string $searchType Whether normal or zoom search
92 public function __construct($db, $table, $searchType)
94 $this->_db = $db;
95 $this->_table = $table;
96 $this->_searchType = $searchType;
97 $this->_columnNames = array();
98 $this->_columnNullFlags = array();
99 $this->_columnTypes = array();
100 $this->_columnCollations = array();
101 $this->_geomColumnFlag = false;
102 $this->_foreigners = array();
103 // Loads table's information
104 $this->_loadTableInfo();
108 * Returns Column names array
110 * @return array column names
112 public function getColumnNames()
114 return $this->_columnNames;
118 * Gets all the columns of a table along with their types, collations
119 * and whether null or not.
121 * @return void
123 private function _loadTableInfo()
125 // Gets the list and number of columns
126 $columns = PMA_DBI_get_columns($this->_db, $this->_table, null, true);
127 // Get details about the geometry fucntions
128 $geom_types = PMA_Util::getGISDatatypes();
130 foreach ($columns as $row) {
131 // set column name
132 $this->_columnNames[] = $row['Field'];
134 $type = $row['Type'];
135 // check whether table contains geometric columns
136 if (in_array($type, $geom_types)) {
137 $this->_geomColumnFlag = true;
139 // reformat mysql query output
140 if (strncasecmp($type, 'set', 3) == 0
141 || strncasecmp($type, 'enum', 4) == 0
143 $type = str_replace(',', ', ', $type);
144 } else {
145 // strip the "BINARY" attribute, except if we find "BINARY(" because
146 // this would be a BINARY or VARBINARY column type
147 if (! preg_match('@BINARY[\(]@i', $type)) {
148 $type = preg_replace('@BINARY@i', '', $type);
150 $type = preg_replace('@ZEROFILL@i', '', $type);
151 $type = preg_replace('@UNSIGNED@i', '', $type);
152 $type = strtolower($type);
154 if (empty($type)) {
155 $type = '&nbsp;';
157 $this->_columnTypes[] = $type;
158 $this->_columnNullFlags[] = $row['Null'];
159 $this->_columnCollations[]
160 = ! empty($row['Collation']) && $row['Collation'] != 'NULL'
161 ? $row['Collation']
162 : '';
163 } // end for
165 // Retrieve foreign keys
166 $this->_foreigners = PMA_getForeigners($this->_db, $this->_table);
170 * Sets the table header for displaying a table in query-by-example format.
172 * @return HTML content, the tags and content for table header
174 private function _getTableHeader()
176 // Display the Function column only if there is at least one geometry column
177 $func = '';
178 if ($this->_geomColumnFlag) {
179 $func = '<th>' . __('Function') . '</th>';
182 return '<thead>
183 <tr>' . $func . '<th>' . __('Column') . '</th>
184 <th>' . __('Type') . '</th>
185 <th>' . __('Collation') . '</th>
186 <th>' . __('Operator') . '</th>
187 <th>' . __('Value') . '</th>
188 </tr>
189 </thead>';
193 * Returns an array with necessary configrations to create
194 * sub-tabs(Table Search and Zoom Search) in the table_select page.
196 * @return array Array containing configuration (icon, text, link, id, args)
197 * of sub-tabs for Table Search and Zoom search
199 private function _getSubTabs()
201 $subtabs = array();
202 $subtabs['search']['icon'] = 'b_search.png';
203 $subtabs['search']['text'] = __('Table Search');
204 $subtabs['search']['link'] = 'tbl_select.php';
205 $subtabs['search']['id'] = 'tbl_search_id';
206 $subtabs['search']['args']['pos'] = 0;
208 $subtabs['zoom']['icon'] = 'b_props.png';
209 $subtabs['zoom']['link'] = 'tbl_zoom_select.php';
210 $subtabs['zoom']['text'] = __('Zoom Search');
211 $subtabs['zoom']['id'] = 'zoom_search_id';
213 return $subtabs;
217 * Provides html elements for search criteria inputbox
218 * in case the column's type is geometrical
220 * @param int $column_index Column's index
221 * @param bool $in_fbs Whether we are in 'function based search'
223 * @return HTML elements.
225 private function _getGeometricalInputBox($column_index, $in_fbs)
227 $html_output = '<input type="text" name="criteriaValues[' . $column_index . ']"'
228 . ' size="40" class="textfield" id="field_' . $column_index . '" />';
230 if ($in_fbs) {
231 $edit_url = 'gis_data_editor.php?' . PMA_generate_common_url();
232 $edit_str = PMA_Util::getIcon('b_edit.png', __('Edit/Insert'));
233 $html_output .= '<span class="open_search_gis_editor">';
234 $html_output .= PMA_Util::linkOrButton(
235 $edit_url, $edit_str, array(), false, false, '_blank'
237 $html_output .= '</span>';
239 return $html_output;
243 * Provides html elements for search criteria inputbox
244 * in case the column is a Foreign Key
246 * @param array $foreignData Foreign keys data
247 * @param string $column_name Column name
248 * @param int $column_index Column index
249 * @param array $titles Selected title
250 * @param int $foreignMaxLimit Max limit of displaying foreign elements
251 * @param array $criteriaValues Array of search criteria inputs
252 * @param string $column_id Column's inputbox's id
253 * @param bool $in_zoom_search_edit Whether we are in zoom search edit
255 * @return HTML elements.
257 private function _getForeignKeyInputBox($foreignData, $column_name,
258 $column_index, $titles, $foreignMaxLimit, $criteriaValues, $column_id,
259 $in_zoom_search_edit = false
261 $html_output = '';
262 if (is_array($foreignData['disp_row'])) {
263 $html_output .= '<select name="criteriaValues[' . $column_index . ']"'
264 . ' id="' . $column_id . $column_index .'">';
265 $html_output .= PMA_foreignDropdown(
266 $foreignData['disp_row'], $foreignData['foreign_field'],
267 $foreignData['foreign_display'], '', $foreignMaxLimit
269 $html_output .= '</select>';
271 } elseif ($foreignData['foreign_link'] == true) {
272 $html_output .= '<input type="text" id="' . $column_id . $column_index . '"'
273 . ' name="criteriaValues[' . $column_index . ']" id="field_'
274 . md5($column_name) . '[' . $column_index .']" class="textfield"'
275 . (isset($criteriaValues[$column_index])
276 && is_string($criteriaValues[$column_index])
277 ? (' value="' . $criteriaValues[$column_index] . '"')
278 : '')
279 . ' />';
281 $html_output .= <<<EOT
282 <a target="_blank" onclick="window.open(this.href, 'foreigners', 'width=640,height=240,scrollbars=yes'); return false" href="browse_foreigners.php?
283 EOT;
284 $html_output .= '' . PMA_generate_common_url($this->_db, $this->_table)
285 . '&amp;field=' . urlencode($column_name) . '&amp;fieldkey='
286 . $column_index . '"';
287 if ($in_zoom_search_edit) {
288 $html_output .= ' class="browse_foreign"';
290 $html_output .= '>' . str_replace("'", "\'", $titles['Browse']) . '</a>';
292 return $html_output;
296 * Provides html elements for search criteria inputbox
297 * in case the column is of ENUM or SET type
299 * @param int $column_index Column index
300 * @param array $criteriaValues Array of search criteria inputs
301 * @param string $column_type Column type
302 * @param string $column_id Column's inputbox's id
303 * @param bool $in_zoom_search_edit Whether we are in zoom search edit
305 * @return HTML elements.
307 private function _getEnumSetInputBox($column_index, $criteriaValues,
308 $column_type, $column_id, $in_zoom_search_edit = false
310 $html_output = '';
311 $value = explode(
312 ', ',
313 str_replace("'", '', substr($column_type, 5, -1))
315 $cnt_value = count($value);
318 * Enum in edit mode --> dropdown
319 * Enum in search mode --> multiselect
320 * Set in edit mode --> multiselect
321 * Set in search mode --> input (skipped here, so the 'else'
322 * section would handle it)
324 if ((strncasecmp($column_type, 'enum', 4) && ! $in_zoom_search_edit)
325 || (strncasecmp($column_type, 'set', 3) && $in_zoom_search_edit)
327 $html_output .= '<select name="criteriaValues[' . ($column_index)
328 . ']" id="' . $column_id . $column_index .'">';
329 } else {
330 $html_output .= '<select name="criteriaValues[' . $column_index . ']"'
331 . ' id="' . $column_id . $column_index . '" multiple="multiple"'
332 . ' size="' . min(3, $cnt_value) . '">';
335 //Add select options
336 for ($j = 0; $j < $cnt_value; $j++) {
337 if (isset($criteriaValues[$column_index])
338 && is_array($criteriaValues[$column_index])
339 && in_array($value[$j], $criteriaValues[$column_index])
341 $html_output .= '<option value="' . $value[$j] . '" Selected>'
342 . $value[$j] . '</option>';
343 } else {
344 $html_output .= '<option value="' . $value[$j] . '">'
345 . $value[$j] . '</option>';
347 } // end for
348 $html_output .= '</select>';
349 return $html_output;
353 * Creates the HTML content for:
354 * 1) Browsing foreign data for a column.
355 * 2) Creating elements for search criteria input on columns.
357 * @param array $foreignData Foreign keys data
358 * @param string $column_name Column name
359 * @param string $column_type Column type
360 * @param int $column_index Column index
361 * @param array $titles Selected title
362 * @param int $foreignMaxLimit Max limit of displaying foreign elements
363 * @param array $criteriaValues Array of search criteria inputs
364 * @param bool $in_fbs Whether we are in 'function based search'
365 * @param bool $in_zoom_search_edit Whether we are in zoom search edit
367 * @return string HTML content for viewing foreign data and elements
368 * for search criteria input.
370 private function _getInputbox($foreignData, $column_name, $column_type,
371 $column_index, $titles, $foreignMaxLimit, $criteriaValues, $in_fbs = false,
372 $in_zoom_search_edit = false
374 $str = '';
375 $column_type = (string)$column_type;
376 $column_id = ($in_zoom_search_edit) ? 'edit_fieldID_' : 'fieldID_';
378 // Get inputbox based on different column types
379 // (Foreign key, geometrical, enum)
380 if ($this->_foreigners && isset($this->_foreigners[$column_name])) {
381 $str .= $this->_getForeignKeyInputBox(
382 $foreignData, $column_name, $column_index, $titles,
383 $foreignMaxLimit, $criteriaValues, $column_id
386 } elseif (in_array($column_type, PMA_Util::getGISDatatypes())) {
387 $str .= $this->_getGeometricalInputBox($column_index, $in_fbs);
389 } elseif (strncasecmp($column_type, 'enum', 4) == 0
390 || (strncasecmp($column_type, 'set', 3) == 0 && $in_zoom_search_edit)
392 $str .= $this->_getEnumSetInputBox(
393 $column_index, $criteriaValues, $column_type, $column_id,
394 $in_zoom_search_edit = false
397 } else {
398 // other cases
399 $the_class = 'textfield';
401 if ($column_type == 'date') {
402 $the_class .= ' datefield';
403 } elseif ($column_type == 'datetime'
404 || substr($column_type, 0, 9) == 'timestamp'
406 $the_class .= ' datetimefield';
407 } elseif (substr($column_type, 0, 3) == 'bit') {
408 $the_class .= ' bit';
411 $str .= '<input type="text" name="criteriaValues[' . $column_index . ']"'
412 .' size="40" class="' . $the_class . '" id="'
413 . $column_id . $column_index . '"'
414 . (isset($criteriaValues[$column_index])
415 && is_string($criteriaValues[$column_index])
416 ? (' value="' . $criteriaValues[$column_index] . '"')
417 : '')
418 . ' />';
420 return $str;
424 * Return the where clause in case column's type is ENUM.
426 * @param mixed $criteriaValues Search criteria input
427 * @param string $func_type Search function/operator
429 * @return string part of where clause.
431 private function _getEnumWhereClause($criteriaValues, $func_type)
433 if (! is_array($criteriaValues)) {
434 $criteriaValues = explode(',', $criteriaValues);
436 $enum_selected_count = count($criteriaValues);
437 if ($func_type == '=' && $enum_selected_count > 1) {
438 $func_type = 'IN';
439 $parens_open = '(';
440 $parens_close = ')';
442 } elseif ($func_type == '!=' && $enum_selected_count > 1) {
443 $func_type = 'NOT IN';
444 $parens_open = '(';
445 $parens_close = ')';
447 } else {
448 $parens_open = '';
449 $parens_close = '';
451 $enum_where = '\''
452 . PMA_Util::sqlAddSlashes($criteriaValues[0]) . '\'';
453 for ($e = 1; $e < $enum_selected_count; $e++) {
454 $enum_where .= ', \''
455 . PMA_Util::sqlAddSlashes($criteriaValues[$e]) . '\'';
458 return ' ' . $func_type . ' ' . $parens_open
459 . $enum_where . $parens_close;
463 * Return the where clause for a geometrical column.
465 * @param mixed $criteriaValues Search criteria input
466 * @param string $names Name of the column on which search is submitted
467 * @param string $func_type Search function/operator
468 * @param string $types Type of the field
469 * @param bool $geom_func Whether geometry functions should be applied
471 * @return string part of where clause.
473 private function _getGeomWhereClause($criteriaValues, $names,
474 $func_type, $types, $geom_func = null
476 $geom_unary_functions = array(
477 'IsEmpty' => 1,
478 'IsSimple' => 1,
479 'IsRing' => 1,
480 'IsClosed' => 1,
482 $where = '';
484 // Get details about the geometry functions
485 $geom_funcs = PMA_Util::getGISFunctions($types, true, false);
486 // New output type is the output type of the function being applied
487 $types = $geom_funcs[$geom_func]['type'];
489 // If the function takes a single parameter
490 if ($geom_funcs[$geom_func]['params'] == 1) {
491 $backquoted_name = $geom_func . '(' . PMA_Util::backquote($names) . ')';
492 } else {
493 // If the function takes two parameters
494 // create gis data from the criteria input
495 $gis_data = PMA_Util::createGISData($criteriaValues);
496 $where = $geom_func . '(' . PMA_Util::backquote($names) . ',' . $gis_data . ')';
497 return $where;
500 // If the where clause is something like 'IsEmpty(`spatial_col_name`)'
501 if (isset($geom_unary_functions[$geom_func])
502 && trim($criteriaValues) == ''
504 $where = $backquoted_name;
506 } elseif (in_array($types, PMA_Util::getGISDatatypes())
507 && ! empty($criteriaValues)
509 // create gis data from the criteria input
510 $gis_data = PMA_Util::createGISData($criteriaValues);
511 $where = $backquoted_name . ' ' . $func_type . ' ' . $gis_data;
513 return $where;
517 * Return the where clause for query generation based on the inputs provided.
519 * @param mixed $criteriaValues Search criteria input
520 * @param string $names Name of the column on which search is submitted
521 * @param string $types Type of the field
522 * @param string $collations Field collation
523 * @param string $func_type Search function/operator
524 * @param bool $unaryFlag Whether operator unary or not
525 * @param bool $geom_func Whether geometry functions should be applied
527 * @return string generated where clause.
529 private function _getWhereClause($criteriaValues, $names, $types, $collations,
530 $func_type, $unaryFlag, $geom_func = null
532 // If geometry function is set
533 if ($geom_func != null && trim($geom_func) != '') {
534 return $this->_getGeomWhereClause(
535 $criteriaValues, $names, $func_type, $types, $geom_func
539 $backquoted_name = PMA_Util::backquote($names);
540 $where = '';
541 if ($unaryFlag) {
542 $criteriaValues = '';
543 $where = $backquoted_name . ' ' . $func_type;
545 } elseif (strncasecmp($types, 'enum', 4) == 0 && ! empty($criteriaValues)) {
546 $where = $backquoted_name;
547 $where .= $this->_getEnumWhereClause($criteriaValues, $func_type);
549 } elseif ($criteriaValues != '') {
550 // For these types we quote the value. Even if it's another type
551 // (like INT), for a LIKE we always quote the value. MySQL converts
552 // strings to numbers and numbers to strings as necessary
553 // during the comparison
554 if (preg_match('@char|binary|blob|text|set|date|time|year@i', $types)
555 || strpos(' ' . $func_type, 'LIKE')
557 $quot = '\'';
558 } else {
559 $quot = '';
562 // LIKE %...%
563 if ($func_type == 'LIKE %...%') {
564 $func_type = 'LIKE';
565 $criteriaValues = '%' . $criteriaValues . '%';
567 if ($func_type == 'REGEXP ^...$') {
568 $func_type = 'REGEXP';
569 $criteriaValues = '^' . $criteriaValues . '$';
572 if ($func_type == 'IN (...)'
573 || $func_type == 'NOT IN (...)'
574 || $func_type == 'BETWEEN'
575 || $func_type == 'NOT BETWEEN'
577 $func_type = str_replace(' (...)', '', $func_type);
579 // quote values one by one
580 $values = explode(',', $criteriaValues);
581 foreach ($values as &$value) {
582 $value = $quot . PMA_Util::sqlAddSlashes(trim($value))
583 . $quot;
586 if ($func_type == 'BETWEEN' || $func_type == 'NOT BETWEEN') {
587 $where = $backquoted_name . ' ' . $func_type . ' '
588 . (isset($values[0]) ? $values[0] : '')
589 . ' AND ' . (isset($values[1]) ? $values[1] : '');
590 } else {
591 $where = $backquoted_name . ' ' . $func_type
592 . ' (' . implode(',', $values) . ')';
594 } else {
595 if ($func_type == 'LIKE %...%' || $func_type == 'LIKE') {
596 $where = $backquoted_name . ' ' . $func_type . ' ' . $quot
597 . PMA_Util::sqlAddSlashes($criteriaValues, true) . $quot;
598 } else {
599 $where = $backquoted_name . ' ' . $func_type . ' ' . $quot
600 . PMA_Util::sqlAddSlashes($criteriaValues) . $quot;
603 } // end if
605 return $where;
609 * Builds the sql search query from the post parameters
611 * @return string the generated SQL query
613 public function buildSqlQuery()
615 $sql_query = 'SELECT ';
617 // If only distinct values are needed
618 $is_distinct = (isset($_POST['distinct'])) ? 'true' : 'false';
619 if ($is_distinct == 'true') {
620 $sql_query .= 'DISTINCT ';
623 // if all column names were selected to display, we do a 'SELECT *'
624 // (more efficient and this helps prevent a problem in IE
625 // if one of the rows is edited and we come back to the Select results)
626 if (isset($_POST['zoom_submit']) || ! empty($_POST['displayAllColumns'])) {
627 $sql_query .= '* ';
628 } else {
629 $sql_query .= implode(
630 ', ',
631 PMA_Util::backquote($_POST['columnsToDisplay'])
633 } // end if
635 $sql_query .= ' FROM '
636 . PMA_Util::backquote($_POST['table']);
637 $whereClause = $this->_generateWhereClause();
638 $sql_query .= $whereClause;
640 // if the search results are to be ordered
641 if (isset($_POST['orderByColumn']) && $_POST['orderByColumn'] != '--nil--') {
642 $sql_query .= ' ORDER BY '
643 . PMA_Util::backquote($_POST['orderByColumn'])
644 . ' ' . $_POST['order'];
645 } // end if
646 return $sql_query;
650 * Generates the where clause for the SQL search query to be executed
652 * @return string the generated where clause
654 private function _generateWhereClause()
656 if (isset($_POST['customWhereClause'])
657 && trim($_POST['customWhereClause']) != ''
659 return ' WHERE ' . $_POST['customWhereClause'];
662 // If there are no search criteria set or no unary criteria operators, return
663 if (! isset($_POST['criteriaValues'])
664 && ! isset($_POST['criteriaColumnOperators'])
666 return '';
669 // else continue to form the where clause from column criteria values
670 $fullWhereClause = $charsets = array();
671 reset($_POST['criteriaColumnOperators']);
672 while (list($column_index, $operator) = each($_POST['criteriaColumnOperators'])) {
673 list($charsets[$column_index]) = explode(
674 '_', $_POST['criteriaColumnCollations'][$column_index]
676 $unaryFlag = $GLOBALS['PMA_Types']->isUnaryOperator($operator);
677 $tmp_geom_func = isset($geom_func[$column_index])
678 ? $geom_func[$column_index] : null;
680 $whereClause = $this->_getWhereClause(
681 $_POST['criteriaValues'][$column_index],
682 $_POST['criteriaColumnNames'][$column_index],
683 $_POST['criteriaColumnTypes'][$column_index],
684 $_POST['criteriaColumnCollations'][$column_index],
685 $operator,
686 $unaryFlag,
687 $tmp_geom_func
690 if ($whereClause) {
691 $fullWhereClause[] = $whereClause;
693 } // end while
695 if ($fullWhereClause) {
696 return ' WHERE ' . implode(' AND ', $fullWhereClause);
698 return '';
702 * Generates HTML for a geometrical function column to be displayed in table
703 * search selection form
705 * @param integer $column_index index of current column in $columnTypes array
707 * @return string the generated HTML
709 private function _getGeomFuncHtml($column_index)
711 $html_output = '';
712 // return if geometrical column is not present
713 if (! $this->_geomColumnFlag) {
714 return $html_output;
718 * Displays 'Function' column if it is present
720 $html_output .= '<td>';
721 $geom_types = PMA_Util::getGISDatatypes();
722 // if a geometry column is present
723 if (in_array($this->_columnTypes[$column_index], $geom_types)) {
724 $html_output .= '<select class="geom_func" name="geom_func['
725 . $column_index . ']">';
726 // get the relevant list of GIS functions
727 $funcs = PMA_Util::getGISFunctions($this->_columnTypes[$column_index], true, true);
729 * For each function in the list of functions,
730 * add an option to select list
732 foreach ($funcs as $func_name => $func) {
733 $name = isset($func['display']) ? $func['display'] : $func_name;
734 $html_output .= '<option value="' . htmlspecialchars($name) . '">'
735 . htmlspecialchars($name) . '</option>';
737 $html_output .= '</select>';
738 } else {
739 $html_output .= '&nbsp;';
741 $html_output .= '</td>';
742 return $html_output;
746 * Generates formatted HTML for extra search options in table search form
748 * @return string the generated HTML
750 private function _getOptions()
752 $html_output = '';
753 $html_output .= PMA_Util::getDivForSliderEffect(
754 'searchoptions', __('Options')
758 * Displays columns select list for selecting distinct columns in the search
760 $html_output .= '<fieldset id="fieldset_select_fields">'
761 . '<legend>' . __('Select columns (at least one):') . '</legend>'
762 . '<select name="columnsToDisplay[]"'
763 . ' size="' . min(count($this->_columnNames), 10) . '"'
764 . ' multiple="multiple">';
765 // Displays the list of the fields
766 foreach ($this->_columnNames as $each_field) {
767 $html_output .= ' '
768 . '<option value="' . htmlspecialchars($each_field) . '"'
769 . ' selected="selected">' . htmlspecialchars($each_field)
770 . '</option>' . "\n";
771 } // end for
772 $html_output .= '</select>'
773 . '<input type="checkbox" name="distinct" value="DISTINCT" id="oDistinct" />'
774 . '<label for="oDistinct">DISTINCT</label></fieldset>';
777 * Displays input box for custom 'Where' clause to be used in the search
779 $html_output .= '<fieldset id="fieldset_search_conditions">'
780 . '<legend>' . '<em>' . __('Or') . '</em> '
781 . __('Add search conditions (body of the "where" clause):') . '</legend>';
782 $html_output .= PMA_Util::showMySQLDocu(
783 'SQL-Syntax', 'Functions'
785 $html_output .= '<input type="text" name="customWhereClause"'
786 . ' class="textfield" size="64" />';
787 $html_output .= '</fieldset>';
790 * Displays option of changing default number of rows displayed per page
792 $html_output .= '<fieldset id="fieldset_limit_rows">'
793 . '<legend>' . __('Number of rows per page') . '</legend>'
794 . '<input type="text" size="4" name="session_max_rows" '
795 . 'value="' . $GLOBALS['cfg']['MaxRows'] . '" class="textfield" />'
796 . '</fieldset>';
799 * Displays option for ordering search results
800 * by a column value (Asc or Desc)
802 $html_output .= '<fieldset id="fieldset_display_order">'
803 . '<legend>' . __('Display order:') . '</legend>'
804 . '<select name="orderByColumn"><option value="--nil--"></option>';
805 foreach ($this->_columnNames as $each_field) {
806 $html_output .= ' '
807 . '<option value="' . htmlspecialchars($each_field) . '">'
808 . htmlspecialchars($each_field) . '</option>' . "\n";
809 } // end for
810 $html_output .= '</select>';
811 $choices = array(
812 'ASC' => __('Ascending'),
813 'DESC' => __('Descending')
815 $html_output .= PMA_Util::getRadioFields(
816 'order', $choices, 'ASC', false, true, "formelement"
818 unset($choices);
820 $html_output .= '</fieldset><br style="clear: both;"/></div>';
821 return $html_output;
825 * Other search criteria like data label
826 * (for tbl_zoom_select.php)
828 * @param array $dataLabel Label for points in zoom plot
830 * @return string the generated html
832 private function _getOptionsZoom($dataLabel)
834 $html_output = '';
835 $html_output .= '<table class="data">';
836 //Select options for datalabel
837 $html_output .= '<tr>';
838 $html_output .= '<td><label for="dataLabel">'
839 . __("Use this column to label each point") . '</label></td>';
840 $html_output .= '<td><select name="dataLabel" id="dataLabel" >'
841 . '<option value = "">' . __('None') . '</option>';
842 for ($j = 0; $j < count($this->_columnNames); $j++) {
843 if (isset($dataLabel)
844 && $dataLabel == htmlspecialchars($this->_columnNames[$j])
846 $html_output .= '<option value="'
847 . htmlspecialchars($this->_columnNames[$j]) . '" selected="selected">'
848 . htmlspecialchars($this->_columnNames[$j]) . '</option>';
849 } else {
850 $html_output .= '<option value="'
851 . htmlspecialchars($this->_columnNames[$j]) . '" >'
852 . htmlspecialchars($this->_columnNames[$j]) . '</option>';
855 $html_output .= '</select></td>';
856 $html_output .= '</tr>';
857 //Inputbox for changing default maximum rows to plot
858 $html_output .= '<tr>';
859 $html_output .= '<td><label for="maxRowPlotLimit">'
860 . __("Maximum rows to plot") . '</label></td>';
861 $html_output .= '<td>';
862 $html_output .= '<input type="text" name="maxPlotLimit"'
863 . ' id="maxRowPlotLimit"'
864 . ' value="' . ((! empty($_POST['maxPlotLimit']))
865 ? htmlspecialchars($_POST['maxPlotLimit'])
866 : $GLOBALS['cfg']['maxRowPlotLimit'])
867 . '" />';
868 $html_output .= '</td></tr>';
869 $html_output .= '</table>';
870 return $html_output;
874 * Provides a column's type, collation, operators list, and crietria value
875 * to display in table search form
877 * @param integer $search_index Row number in table search form
878 * @param integer $column_index Column index in ColumnNames array
880 * @return array Array contaning column's properties
882 public function getColumnProperties($search_index, $column_index)
884 $selected_operator = (isset($_POST['criteriaColumnOperators'])
885 ? $_POST['criteriaColumnOperators'][$search_index] : '');
886 $entered_value = (isset($_POST['criteriaValues'])
887 ? $_POST['criteriaValues'] : '');
888 $titles['Browse'] = PMA_Util::getIcon('b_browse.png', __('Browse foreign values'));
889 //Gets column's type and collation
890 $type = $this->_columnTypes[$column_index];
891 $collation = $this->_columnCollations[$column_index];
892 //Gets column's comparison operators depending on column type
893 $func = '<select name="criteriaColumnOperators[' . $search_index . ']">';
894 $func .= $GLOBALS['PMA_Types']->getTypeOperatorsHtml(
895 preg_replace('@\(.*@s', '', $this->_columnTypes[$column_index]),
896 $this->_columnNullFlags[$column_index], $selected_operator
898 $func .= '</select>';
899 //Gets link to browse foreign data(if any) and criteria inputbox
900 $foreignData = PMA_getForeignData(
901 $this->_foreigners, $this->_columnNames[$column_index], false, '', ''
903 $value = $this->_getInputbox(
904 $foreignData, $this->_columnNames[$column_index], $type, $search_index,
905 $titles, $GLOBALS['cfg']['ForeignKeyMaxLimit'], $entered_value
907 return array(
908 'type' => $type,
909 'collation' => $collation,
910 'func' => $func,
911 'value' => $value
916 * Provides the search form's table row in case of Normal Search
917 * (for tbl_select.php)
919 * @return string the generated table row
921 private function _getRowsNormal()
923 $odd_row = true;
924 $html_output = '';
925 // for every column present in table
926 for ($column_index = 0; $column_index < count($this->_columnNames); $column_index++) {
927 $html_output .= '<tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">';
928 $odd_row = !$odd_row;
929 //If 'Function' column is present
930 $html_output .= $this->_getGeomFuncHtml($column_index);
931 //Displays column's name, type, collation and value
932 $html_output .= '<th>'
933 . htmlspecialchars($this->_columnNames[$column_index]) . '</th>';
934 $properties = $this->getColumnProperties($column_index, $column_index);
935 $html_output .= '<td>' . $properties['type'] . '</td>';
936 $html_output .= '<td>' . $properties['collation'] . '</td>';
937 $html_output .= '<td>' . $properties['func'] . '</td>';
938 $html_output .= '<td>' . $properties['value'] . '</td>';
939 $html_output .= '</tr>';
940 //Displays hidden fields
941 $html_output .= '<tr><td>';
942 $html_output .= '<input type="hidden"'
943 . ' name="criteriaColumnNames[' . $column_index . ']"'
944 . ' value="' . htmlspecialchars($this->_columnNames[$column_index])
945 . '" />';
946 $html_output .= '<input type="hidden"'
947 . ' name="criteriaColumnTypes[' . $column_index . ']"'
948 . ' value="' . $this->_columnTypes[$column_index] . '" />';
949 $html_output .= '<input type="hidden"'
950 . ' name="criteriaColumnCollations[' . $column_index . ']"'
951 . ' value="' . $this->_columnCollations[$column_index] . '" />';
952 $html_output .= '</td></tr>';
953 } // end for
955 return $html_output;
959 * Provides the search form's table row in case of Zoom Search
960 * (for tbl_zoom_select.php)
962 * @return string the generated table row
964 private function _getRowsZoom()
966 $odd_row = true;
967 $html_output = '';
969 * Get already set search criteria (if any)
972 //Displays column rows for search criteria input
973 for ($i = 0; $i < 4; $i++) {
974 //After X-Axis and Y-Axis column rows, display additional criteria option
975 if ($i == 2) {
976 $html_output .= '<tr><td>';
977 $html_output .= __("Additional search criteria");
978 $html_output .= '</td></tr>';
980 $html_output .= '<tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">';
981 $odd_row = ! $odd_row;
982 //Select options for column names
983 $html_output .= '<th><select name="criteriaColumnNames[]" id="'
984 . 'tableid_' . $i . '" >';
985 $html_output .= '<option value="' . 'pma_null' . '">' . __('None')
986 . '</option>';
987 for ($j = 0 ; $j < count($this->_columnNames); $j++) {
988 if (isset($_POST['criteriaColumnNames'][$i])
989 && $_POST['criteriaColumnNames'][$i] == htmlspecialchars($this->_columnNames[$j])
991 $html_output .= '<option value="'
992 . htmlspecialchars($this->_columnNames[$j]) . '" selected="selected">'
993 . htmlspecialchars($this->_columnNames[$j]) . '</option>';
994 } else {
995 $html_output .= '<option value="'
996 . htmlspecialchars($this->_columnNames[$j]) . '">'
997 . htmlspecialchars($this->_columnNames[$j]) . '</option>';
1000 $html_output .= '</select></th>';
1001 if (isset($_POST['criteriaColumnNames'])
1002 && $_POST['criteriaColumnNames'][$i] != 'pma_null'
1004 $key = array_search(
1005 $_POST['criteriaColumnNames'][$i],
1006 $this->_columnNames
1008 $properties = $this->getColumnProperties($i, $key);
1009 $type[$i] = $properties['type'];
1010 $collation[$i] = $properties['collation'];
1011 $func[$i] = $properties['func'];
1012 $value[$i] = $properties['value'];
1014 //Column type
1015 $html_output .= '<td>' . (isset($type[$i]) ? $type[$i] : '') . '</td>';
1016 //Column Collation
1017 $html_output .= '<td>' . (isset($collation[$i]) ? $collation[$i] : '')
1018 . '</td>';
1019 //Select options for column operators
1020 $html_output .= '<td>' . (isset($func[$i]) ? $func[$i] : '') . '</td>';
1021 //Inputbox for search criteria value
1022 $html_output .= '<td>' . (isset($value[$i]) ? $value[$i] : '') . '</td>';
1023 $html_output .= '</tr>';
1024 //Displays hidden fields
1025 $html_output .= '<tr><td>';
1026 $html_output .= '<input type="hidden" name="criteriaColumnTypes[' . $i . ']"'
1027 . ' id="types_' . $i . '" ';
1028 if (isset($_POST['criteriaColumnTypes'][$i])) {
1029 $html_output .= 'value="' . $_POST['criteriaColumnTypes'][$i] . '" ';
1031 $html_output .= '/>';
1032 $html_output .= '<input type="hidden" name="criteriaColumnCollations['
1033 . $i . ']" id="collations_' . $i . '" />';
1034 $html_output .= '</td></tr>';
1035 }//end for
1036 return $html_output;
1040 * Generates HTML for displaying fields table in search form
1042 * @return string the generated HTML
1044 private function _getFieldsTableHtml()
1046 $html_output = '';
1047 $html_output .= '<table class="data"'
1048 . ($this->_searchType == 'zoom' ? ' id="tableFieldsId"' : '') . '>';
1049 $html_output .= $this->_getTableHeader();
1050 $html_output .= '<tbody>';
1052 if ($this->_searchType == 'zoom') {
1053 $html_output .= $this->_getRowsZoom();
1054 } else {
1055 $html_output .= $this->_getRowsNormal();
1058 $html_output .= '</tbody></table>';
1059 return $html_output;
1063 * Provides the form tag for table search form
1064 * (normal search or zoom search)
1066 * @param string $goto Goto URL
1068 * @return string the HTML for form tag
1070 private function _getFormTag($goto)
1072 $html_output = '';
1073 $scriptName = ($this->_searchType == 'zoom' ? 'tbl_zoom_select.php' : 'tbl_select.php');
1074 $formId = ($this->_searchType == 'zoom' ? 'zoom_search_form' : 'tbl_search_form');
1076 $html_output .= '<form method="post" action="' . $scriptName . '" '
1077 . 'name="insertForm" id="' . $formId . '" '
1078 . 'class="ajax"' . '>';
1080 $html_output .= PMA_generate_common_hidden_inputs($this->_db, $this->_table);
1081 $html_output .= '<input type="hidden" name="goto" value="' . $goto . '" />';
1082 $html_output .= '<input type="hidden" name="back" value="' . $scriptName
1083 . '" />';
1085 return $html_output;
1089 * Generates the table search form under table search tab
1091 * @param string $goto Goto URL
1092 * @param string $dataLabel Label for points in zoom plot
1094 * @return string the generated HTML for table search form
1096 public function getSelectionForm($goto, $dataLabel = null)
1098 $url_params = array();
1099 $url_params['db'] = $this->_db;
1100 $url_params['table'] = $this->_table;
1102 $html_output = '<ul id="topmenu2">';
1103 foreach ($this->_getSubTabs() as $tab) {
1104 $html_output .= PMA_Util::getHtmlTab($tab, $url_params);
1106 $html_output .= '</ul>';
1107 $html_output .= '<div class="clearfloat"></div>';
1109 $html_output .= $this->_getFormTag($goto);
1111 if ($this->_searchType == 'zoom') {
1112 $html_output .= '<fieldset id="fieldset_zoom_search">';
1113 $html_output .= '<fieldset id="inputSection">';
1114 $html_output .= '<legend>'
1115 . __('Do a "query by example" (wildcard: "%") for two different columns')
1116 . '</legend>';
1117 $html_output .= $this->_getFieldsTableHtml();
1118 $html_output .= $this->_getOptionsZoom($dataLabel);
1119 $html_output .= '</fieldset>';
1120 $html_output .= '</fieldset>';
1121 } else {
1122 $html_output .= '<fieldset id="fieldset_table_search">';
1123 $html_output .= '<fieldset id="fieldset_table_qbe">';
1124 $html_output .= '<legend>'
1125 . __('Do a "query by example" (wildcard: "%")')
1126 . '</legend>';
1127 $html_output .= $this->_getFieldsTableHtml();
1128 $html_output .= '<div id="gis_editor"></div>';
1129 $html_output .= '<div id="popup_background"></div>';
1130 $html_output .= '</fieldset>';
1131 $html_output .= $this->_getOptions();
1132 $html_output .= '</fieldset>';
1136 * Displays selection form's footer elements
1138 $html_output .= '<fieldset class="tblFooters">';
1139 $html_output .= '<input type="submit" name="'
1140 . ($this->_searchType == 'zoom' ? 'zoom_submit' : 'submit')
1141 . ($this->_searchType == 'zoom' ? '" id="inputFormSubmitId"' : '" ')
1142 . 'value="' . __('Go') . '" />';
1143 $html_output .= '</fieldset></form>';
1144 $html_output .= '<div id="sqlqueryresults"></div>';
1145 return $html_output;
1149 * Provides form for displaying point data and also the scatter plot
1150 * (for tbl_zoom_select.php)
1152 * @param string $goto Goto URL
1153 * @param array $data Array containing SQL query data
1155 * @return string form's html
1157 public function getZoomResultsForm($goto, $data)
1159 $html_output = '';
1160 $titles['Browse'] = PMA_Util::getIcon('b_browse.png', __('Browse foreign values'));
1161 $html_output .= '<form method="post" action="tbl_zoom_select.php"'
1162 . ' name="displayResultForm" id="zoom_display_form"'
1163 . ' class="ajax"' . '>';
1164 $html_output .= PMA_generate_common_hidden_inputs($this->_db, $this->_table);
1165 $html_output .= '<input type="hidden" name="goto" value="' . $goto . '" />';
1166 $html_output .= '<input type="hidden" name="back" value="tbl_zoom_select.php" />';
1168 $html_output .= '<fieldset id="displaySection">';
1169 $html_output .= '<legend>' . __('Browse/Edit the points') . '</legend>';
1171 //JSON encode the data(query result)
1172 $html_output .= '<center>';
1173 if (isset($_POST['zoom_submit']) && ! empty($data)) {
1174 $html_output .= '<div id="resizer">';
1175 $html_output .= '<center><a href="#" onclick="displayHelp();">'
1176 . __('How to use') . '</a></center>';
1177 $html_output .= '<div id="querydata" style="display:none">'
1178 . json_encode($data) . '</div>';
1179 $html_output .= '<div id="querychart"></div>';
1180 $html_output .= '<button class="button-reset">'
1181 . __('Reset zoom') . '</button>';
1182 $html_output .= '</div>';
1184 $html_output .= '</center>';
1186 //Displays rows in point edit form
1187 $html_output .= '<div id="dataDisplay" style="display:none">';
1188 $html_output .= '<table><thead>';
1189 $html_output .= '<tr>';
1190 $html_output .= '<th>' . __('Column') . '</th>'
1191 . '<th>' . __('Null') . '</th>'
1192 . '<th>' . __('Value') . '</th>';
1193 $html_output .= '</tr>';
1194 $html_output .= '</thead>';
1196 $html_output .= '<tbody>';
1197 $odd_row = true;
1198 for ($column_index = 0; $column_index < count($this->_columnNames); $column_index++) {
1199 $fieldpopup = $this->_columnNames[$column_index];
1200 $foreignData = PMA_getForeignData($this->_foreigners, $fieldpopup, false, '', '');
1201 $html_output .= '<tr class="noclick ' . ($odd_row ? 'odd' : 'even') . '">';
1202 $odd_row = ! $odd_row;
1203 //Display column Names
1204 $html_output .= '<th>' . htmlspecialchars($this->_columnNames[$column_index])
1205 . '</th>';
1206 //Null checkbox if column can be null
1207 $html_output .= '<th>' . (($this->_columnNullFlags[$column_index] == 'YES')
1208 ? '<input type="checkbox" class="checkbox_null"'
1209 . ' name="criteriaColumnNullFlags[' . $column_index . ']"'
1210 . ' id="edit_fields_null_id_' . $column_index . '" />'
1211 : '');
1212 $html_output .= '</th>';
1213 //Column's Input box
1214 $html_output .= '<th>';
1215 $html_output .= $this->_getInputbox(
1216 $foreignData, $fieldpopup, $this->_columnTypes[$column_index],
1217 $column_index, $titles, $GLOBALS['cfg']['ForeignKeyMaxLimit'],
1218 '', false, true
1220 $html_output .= '</th></tr>';
1222 $html_output .= '</tbody></table>';
1223 $html_output .= '</div>';
1224 $html_output .= '<input type="hidden" id="queryID" name="sql_query" />';
1225 $html_output .= '</form>';
1226 return $html_output;