/** * Displays the headers of the results table * * @param array which elements to display * @param array the list of fields properties * @param integer the total number of fields returned by the sql query * @param array the analyzed query * * @return boolean always true * * @global string $db the database name * @global string $table the table name * @global string $goto the url to go back in case of errors * @global boolean $dontlimitchars whether to limit the number of displayed * characters of text type fields or not * @global string $sql_query the sql query * @global integer $num_rows the total number of rows returned by the * sql query * @global integer $pos the current position in results * @global integer $session_max_rows the maximum number of rows per page * @global array $vertical_display informations used with vertical display * mode * @global string $disp_direction the display mode * (horizontal/vertical/horizontalflipped) * @global integer $repeat_cellsthe number of row to display between two * table headers * * @access private * * @see PMA_displayTable() */ function PMA_displayTableHeaders(&$is_display, &$fields_meta, $fields_cnt = 0, $analyzed_sql = '') { global $db, $table, $goto, $dontlimitchars; global $sql_query, $num_rows, $pos, $session_max_rows; global $vertical_display, $disp_direction, $repeat_cells, $highlight_columns; if ($analyzed_sql == '') { $analyzed_sql = array(); } // can the result be sorted? if ($is_display['sort_lnk'] == '1') { // Just as fallback $unsorted_sql_query = $sql_query; if (isset($analyzed_sql[0]['unsorted_query'])) { $unsorted_sql_query = $analyzed_sql[0]['unsorted_query']; } // we need $sort_expression and $sort_expression_nodir // even if there are many table references $sort_expression = trim(str_replace(' ', ' ', $analyzed_sql[0]['order_by_clause'])); // Get rid of ASC|DESC (TODO: analyzer) preg_match('@(.*)([[:space:]]*(ASC|DESC))@si', $sort_expression, $matches); $sort_expression_nodir = isset($matches[1]) ? trim($matches[1]) : $sort_expression; // sorting by indexes, only if it makes sense (only one table ref) if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['querytype']) && $analyzed_sql[0]['querytype'] == 'SELECT' && isset($analyzed_sql[0]['table_ref']) && count($analyzed_sql[0]['table_ref']) == 1) { // grab indexes data: PMA_DBI_select_db($db); if (!defined('PMA_IDX_INCLUDED')) { $ret_keys = PMA_get_indexes($table); } $prev_index = ''; foreach ($ret_keys as $row) { if ($row['Key_name'] != $prev_index) { $indexes[] = $row['Key_name']; $prev_index = $row['Key_name']; } $indexes_info[$row['Key_name']]['Sequences'][] = $row['Seq_in_index']; $indexes_info[$row['Key_name']]['Non_unique'] = $row['Non_unique']; if (isset($row['Cardinality'])) { $indexes_info[$row['Key_name']]['Cardinality'] = $row['Cardinality']; } // I don't know what does the following column mean.... // $indexes_info[$row['Key_name']]['Packed'] = $row['Packed']; $indexes_info[$row['Key_name']]['Comment'] = isset($row['Comment']) ? $row['Comment'] : ''; $indexes_info[$row['Key_name']]['Index_type'] = isset($row['Index_type']) ? $row['Index_type'] : ''; $indexes_data[$row['Key_name']][$row['Seq_in_index']]['Column_name'] = $row['Column_name']; if (isset($row['Sub_part'])) { $indexes_data[$row['Key_name']][$row['Seq_in_index']]['Sub_part'] = $row['Sub_part']; } } // end while // do we have any index? if (isset($indexes_data)) { if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { $span = $fields_cnt; if ($is_display['edit_lnk'] != 'nn') { $span++; } if ($is_display['del_lnk'] != 'nn') { $span++; } if ($is_display['del_lnk'] != 'kp' && $is_display['del_lnk'] != 'nn') { $span++; } } else { $span = $num_rows + floor($num_rows / $repeat_cells) + 1; } echo '<form action="sql.php" method="post">' . "\n"; echo PMA_generate_common_hidden_inputs($db, $table, 5); echo '<input type="hidden" name="pos" value="' . $pos . '" />' . "\n"; echo '<input type="hidden" name="session_max_rows" value="' . $session_max_rows . '" />' . "\n"; echo '<input type="hidden" name="disp_direction" value="' . $disp_direction . '" />' . "\n"; echo '<input type="hidden" name="repeat_cells" value="' . $repeat_cells . '" />' . "\n"; echo '<input type="hidden" name="dontlimitchars" value="' . $dontlimitchars . '" />' . "\n"; echo $GLOBALS['strSortByKey'] . ': <select name="sql_query">' . "\n"; $used_index = false; $local_order = isset($sort_expression) ? $sort_expression : ''; foreach ($indexes_data as $key => $val) { $asc_sort = ''; $desc_sort = ''; foreach ($val as $key2 => $val2) { $asc_sort .= PMA_backquote($val2['Column_name']) . ' ASC , '; $desc_sort .= PMA_backquote($val2['Column_name']) . ' DESC , '; } $asc_sort = substr($asc_sort, 0, -3); $desc_sort = substr($desc_sort, 0, -3); $used_index = $used_index || $local_order == $asc_sort || $local_order == $desc_sort; echo '<option value="' . htmlspecialchars($unsorted_sql_query . ' ORDER BY ' . $asc_sort) . '"' . ($local_order == $asc_sort ? ' selected="selected"' : '') . '>' . htmlspecialchars($key) . ' (' . $GLOBALS['strAscending'] . ')</option>'; echo "\n"; echo '<option value="' . htmlspecialchars($unsorted_sql_query . ' ORDER BY ' . $desc_sort) . '"' . ($local_order == $desc_sort ? ' selected="selected"' : '') . '>' . htmlspecialchars($key) . ' (' . $GLOBALS['strDescending'] . ')</option>'; echo "\n"; } echo '<option value="' . htmlspecialchars($unsorted_sql_query) . '"' . ($used_index ? '' : ' selected="selected"') . '>' . $GLOBALS['strNone'] . '</option>'; echo "\n"; echo '</select>' . "\n"; echo '<input type="submit" value="' . $GLOBALS['strGo'] . '" />'; echo "\n"; echo '</form>' . "\n"; } } } $vertical_display['emptypre'] = 0; $vertical_display['emptyafter'] = 0; $vertical_display['textbtn'] = ''; // Start of form for multi-rows delete if ($is_display['del_lnk'] == 'dr' || $is_display['del_lnk'] == 'kp') { echo '<form method="post" action="tbl_row_action.php" name="rowsDeleteForm" id="rowsDeleteForm">' . "\n"; echo PMA_generate_common_hidden_inputs($db, $table, 1); echo '<input type="hidden" name="disp_direction" value="' . $disp_direction . '" />' . "\n"; echo '<input type="hidden" name="repeat_cells" value="' . $repeat_cells . '" />' . "\n"; echo '<input type="hidden" name="dontlimitchars" value="' . $dontlimitchars . '" />' . "\n"; echo '<input type="hidden" name="pos" value="' . $pos . '" />' . "\n"; echo '<input type="hidden" name="session_max_rows" value="' . $session_max_rows . '" />' . "\n"; echo '<input type="hidden" name="goto" value="sql.php" />' . "\n"; } echo '<table id="table_results" class="data">' . "\n"; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo '<thead><tr>' . "\n"; } // 1. Displays the full/partial text button (part 1)... if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { $colspan = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? ' colspan="3"' : ''; } else { $rowspan = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? ' rowspan="3"' : ''; } $text_url = 'sql.php?' . PMA_generate_common_url($db, $table) . '&sql_query=' . urlencode($sql_query) . '&session_max_rows=' . $session_max_rows . '&pos=' . $pos . '&disp_direction=' . $disp_direction . '&repeat_cells=' . $repeat_cells . '&goto=' . $goto . '&dontlimitchars=' . ($dontlimitchars ? 0 : 1); $text_message = '<img class="fulltext" src="' . $GLOBALS['pmaThemeImage'] . 's_' . ($dontlimitchars ? 'partialtext' : 'fulltext') . '.png" width="50" height="20" alt="' . ($dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']) . '" title="' . ($dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']) . '" />'; $text_link = PMA_linkOrButton($text_url, $text_message, array(), false); // ... before the result table if ($is_display['edit_lnk'] == 'nn' && $is_display['del_lnk'] == 'nn' && $is_display['text_btn'] == '1') { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 0; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { ?> <th colspan="<?php echo $fields_cnt; ?> "><?php echo $text_link; ?> </th> </tr> <tr> <?php } else { ?> <tr> <th colspan="<?php echo $num_rows + floor($num_rows / $repeat_cells) + 1; ?> "> <?php echo $text_link; ?> </th> </tr> <?php } // end vertical mode } elseif ($GLOBALS['cfg']['ModifyDeleteAtLeft'] && $is_display['text_btn'] == '1') { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 0; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { ?> <th <?php echo $colspan; ?> ><?php echo $text_link; ?> </th> <?php } else { $vertical_display['textbtn'] = ' <th ' . $rowspan . ' valign="middle">' . "\n" . ' ' . $text_link . "\n" . ' </th>' . "\n"; } // end vertical mode } elseif ($GLOBALS['cfg']['ModifyDeleteAtLeft'] && ($is_display['edit_lnk'] != 'nn' || $is_display['del_lnk'] != 'nn')) { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 0; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { ?> <td<?php echo $colspan; ?> ></td> <?php } else { $vertical_display['textbtn'] = ' <td' . $rowspan . '></td>' . "\n"; } // end vertical mode } // 2. Displays the fields' name // 2.0 If sorting links should be used, checks if the query is a "JOIN" // statement (see 2.1.3) // 2.0.1 Prepare Display column comments if enabled ($GLOBALS['cfg']['ShowBrowseComments']). // Do not show comments, if using horizontalflipped mode, because of space usage if ($GLOBALS['cfg']['ShowBrowseComments'] && ($GLOBALS['cfgRelation']['commwork'] || PMA_MYSQL_INT_VERSION >= 40100) && $disp_direction != 'horizontalflipped') { $comments_map = array(); if (isset($analyzed_sql[0]) && is_array($analyzed_sql[0])) { foreach ($analyzed_sql[0]['table_ref'] as $tbl) { $tb = $tbl['table_true_name']; $comments_map[$tb] = PMA_getComments($db, $tb); unset($tb); } } } if ($GLOBALS['cfgRelation']['commwork'] && $GLOBALS['cfgRelation']['mimework'] && $GLOBALS['cfg']['BrowseMIME']) { require_once './libraries/transformations.lib.php'; $GLOBALS['mime_map'] = PMA_getMIME($db, $table); } if ($is_display['sort_lnk'] == '1') { //$is_join = preg_match('@(.*)[[:space:]]+FROM[[:space:]]+.*[[:space:]]+JOIN@im', $sql_query, $select_stt); $is_join = isset($analyzed_sql[0]['queryflags']['join']) ? true : false; $select_expr = $analyzed_sql[0]['select_expr_clause']; } else { $is_join = false; } // garvin: See if we have to highlight any header fields of a WHERE query. // Uses SQL-Parser results. $highlight_columns = array(); if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['where_clause_identifiers'])) { $wi = 0; if (isset($analyzed_sql[0]['where_clause_identifiers']) && is_array($analyzed_sql[0]['where_clause_identifiers'])) { foreach ($analyzed_sql[0]['where_clause_identifiers'] as $wci_nr => $wci) { $highlight_columns[$wci] = 'true'; } } } for ($i = 0; $i < $fields_cnt; $i++) { // garvin: See if this column should get highlight because it's used in the // where-query. if (isset($highlight_columns[$fields_meta[$i]->name]) || isset($highlight_columns[PMA_backquote($fields_meta[$i]->name)])) { $condition_field = true; } else { $condition_field = false; } // 2.0 Prepare comment-HTML-wrappers for each row, if defined/enabled. if (isset($comments_map) && isset($comments_map[$fields_meta[$i]->table]) && isset($comments_map[$fields_meta[$i]->table][$fields_meta[$i]->name])) { $comments = '<span class="tblcomment">' . htmlspecialchars($comments_map[$fields_meta[$i]->table][$fields_meta[$i]->name]) . '</span>'; } else { $comments = ''; } // 2.1 Results can be sorted if ($is_display['sort_lnk'] == '1') { // 2.1.1 Checks if the table name is required; it's the case // for a query with a "JOIN" statement and if the column // isn't aliased, or in queries like // SELECT `1`.`master_field` , `2`.`master_field` // FROM `PMA_relation` AS `1` , `PMA_relation` AS `2` /** * we prefer always using table if existing * and second this code does not correctly check $fields_meta[$i]->table if (($is_join && !preg_match('~([^[:space:],]|`[^`]`)[[:space:]]+(as[[:space:]]+)?' . strtr($fields_meta[$i]->name, array('[' => '\\[', '~' => '\\~', '\\' => '\\\\')) . '~i', $select_expr, $parts)) || (isset($analyzed_sql[0]['select_expr'][$i]['expr']) && isset($analyzed_sql[0]['select_expr'][$i]['column']) && $analyzed_sql[0]['select_expr'][$i]['expr'] != $analyzed_sql[0]['select_expr'][$i]['column'] && isset($fields_meta[$i]->table) && strlen($fields_meta[$i]->table))) { */ if (isset($fields_meta[$i]->table) && strlen($fields_meta[$i]->table)) { $sort_tbl = PMA_backquote($fields_meta[$i]->table) . '.'; } else { $sort_tbl = ''; } // 2.1.2 Checks if the current column is used to sort the // results if (empty($sort_expression)) { $is_in_sort = false; } else { // field name may be preceded by a space, or any number // of characters followed by a dot (tablename.fieldname) // so do a direct comparison // for the sort expression (avoids problems with queries // like "SELECT id, count(id)..." and clicking to sort // on id or on count(id)) $is_in_sort = $sort_tbl . PMA_backquote($fields_meta[$i]->name) == $sort_expression_nodir ? true : false; } // 2.1.3 Check the field name for backquotes. // If it contains some, it's probably a function column // like 'COUNT(`field`)' if (strpos($fields_meta[$i]->name, '`') !== false) { $sort_order = ' ORDER BY ' . PMA_backquote($fields_meta[$i]->name) . ' '; } else { $sort_order = ' ORDER BY ' . $sort_tbl . PMA_backquote($fields_meta[$i]->name) . ' '; } // 2.1.4 Do define the sorting url if (!$is_in_sort) { // loic1: patch #455484 ("Smart" order) $GLOBALS['cfg']['Order'] = strtoupper($GLOBALS['cfg']['Order']); if ($GLOBALS['cfg']['Order'] == 'SMART') { $GLOBALS['cfg']['Order'] = preg_match('@time|date@i', $fields_meta[$i]->type) ? 'DESC' : 'ASC'; } $sort_order .= $GLOBALS['cfg']['Order']; $order_img = ''; } elseif (preg_match('@[[:space:]]ASC$@i', $sort_expression)) { $sort_order .= ' DESC'; $order_img = ' <img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 's_asc.png" width="11" height="9" alt="' . $GLOBALS['strAscending'] . '" title="' . $GLOBALS['strAscending'] . '" id="soimg' . $i . '" />'; } elseif (preg_match('@[[:space:]]DESC$@i', $sort_expression)) { $sort_order .= ' ASC'; $order_img = ' <img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 's_desc.png" width="11" height="9" alt="' . $GLOBALS['strDescending'] . '" title="' . $GLOBALS['strDescending'] . '" id="soimg' . $i . '" />'; } else { $sort_order .= ' DESC'; $order_img = ' <img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 's_asc.png" width="11" height="9" alt="' . $GLOBALS['strAscending'] . '" title="' . $GLOBALS['strAscending'] . '" id="soimg' . $i . '" />'; } if (preg_match('@(.*)([[:space:]](LIMIT (.*)|PROCEDURE (.*)|FOR UPDATE|LOCK IN SHARE MODE))@i', $unsorted_sql_query, $regs3)) { $sorted_sql_query = $regs3[1] . $sort_order . $regs3[2]; } else { $sorted_sql_query = $unsorted_sql_query . $sort_order; } $url_query = PMA_generate_common_url($db, $table) . '&pos=' . $pos . '&session_max_rows=' . $session_max_rows . '&disp_direction=' . $disp_direction . '&repeat_cells=' . $repeat_cells . '&dontlimitchars=' . $dontlimitchars . '&sql_query=' . urlencode($sorted_sql_query); $order_url = 'sql.php?' . $url_query; // 2.1.5 Displays the sorting url // added 20004-06-09: Michael Keck <*****@*****.**> // enable sord order swapping for image $order_link_params = array(); if (isset($order_img) && $order_img != '') { if (strstr($order_img, 'asc')) { $order_link_params['onmouseover'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_desc.png\'; }'; $order_link_params['onmouseout'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_asc.png\'; }'; } elseif (strstr($order_img, 'desc')) { $order_link_params['onmouseover'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_asc.png\'; }'; $order_link_params['onmouseout'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_desc.png\'; }'; } } if ($disp_direction == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'css') { $order_link_params['style'] = 'direction: ltr; writing-mode: tb-rl;'; } $order_link_params['title'] = $GLOBALS['strSort']; $order_link_content = $disp_direction == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'fake' ? PMA_flipstring(htmlspecialchars($fields_meta[$i]->name), "<br />\n") : htmlspecialchars($fields_meta[$i]->name); $order_link = PMA_linkOrButton($order_url, $order_link_content . $order_img, $order_link_params, false, true); if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo '<th'; if ($condition_field) { echo ' class="condition"'; } if ($disp_direction == 'horizontalflipped') { echo ' valign="bottom"'; } echo '>' . $order_link . $comments . '</th>'; } $vertical_display['desc'][] = ' <th ' . ($condition_field ? ' class="condition"' : '') . '>' . "\n" . $order_link . $comments . ' </th>' . "\n"; } else { if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo '<th'; if ($condition_field) { echo ' class="condition"'; } if ($disp_direction == 'horizontalflipped') { echo ' valign="bottom"'; } if ($disp_direction == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'css') { echo ' style="direction: ltr; writing-mode: tb-rl;"'; } echo '>'; if ($disp_direction == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'fake') { echo PMA_flipstring(htmlspecialchars($fields_meta[$i]->name), '<br />'); } else { echo htmlspecialchars($fields_meta[$i]->name); } echo "\n" . $comments . '</th>'; } $vertical_display['desc'][] = ' <th ' . ($condition_field ? ' class="condition"' : '') . '>' . "\n" . ' ' . htmlspecialchars($fields_meta[$i]->name) . "\n" . $comments . ' </th>'; } // end else (2.2) } // end for // 3. Displays the full/partial text button (part 2) at the right // column of the result table header if possible and required... if ($GLOBALS['cfg']['ModifyDeleteAtRight'] && ($is_display['edit_lnk'] != 'nn' || $is_display['del_lnk'] != 'nn') && $is_display['text_btn'] == '1') { $vertical_display['emptyafter'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 1; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo "\n"; ?> <th <?php echo $colspan; ?> > <?php echo $text_link; ?> </th> <?php } else { $vertical_display['textbtn'] = ' <th ' . $rowspan . ' valign="middle">' . "\n" . ' ' . $text_link . "\n" . ' </th>' . "\n"; } // end vertical mode } elseif ($GLOBALS['cfg']['ModifyDeleteAtRight'] && ($is_display['edit_lnk'] == 'nn' && $is_display['del_lnk'] == 'nn') && !$GLOBALS['is_header_sent']) { $vertical_display['emptyafter'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 1; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo "\n"; ?> <td<?php echo $colspan; ?> ></td> <?php } else { $vertical_display['textbtn'] = ' <td' . $rowspan . '></td>' . "\n"; } // end vertical mode } if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { ?> </tr> </thead> <?php } return true; }
/** * Displays the headers of the results table * * @uses $_SESSION['tmp_user_values']['disp_direction'] * @uses $_SESSION['tmp_user_values']['repeat_cells'] * @uses $_SESSION['tmp_user_values']['max_rows'] * @uses $_SESSION['tmp_user_values']['display_text'] * @uses $_SESSION['tmp_user_values']['display_binary'] * @uses $_SESSION['tmp_user_values']['display_binary_as_hex'] * @param array which elements to display * @param array the list of fields properties * @param integer the total number of fields returned by the SQL query * @param array the analyzed query * * @return boolean $clause_is_unique * * @global string $db the database name * @global string $table the table name * @global string $goto the URL to go back in case of errors * @global string $sql_query the SQL query * @global integer $num_rows the total number of rows returned by the * SQL query * @global array $vertical_display informations used with vertical display * mode * * @access private * * @see PMA_displayTable() */ function PMA_displayTableHeaders(&$is_display, &$fields_meta, $fields_cnt = 0, $analyzed_sql = '', $sort_expression, $sort_expression_nodirection, $sort_direction) { global $db, $table, $goto; global $sql_query, $num_rows; global $vertical_display, $highlight_columns; if ($analyzed_sql == '') { $analyzed_sql = array(); } // can the result be sorted? if ($is_display['sort_lnk'] == '1') { // Just as fallback $unsorted_sql_query = $sql_query; if (isset($analyzed_sql[0]['unsorted_query'])) { $unsorted_sql_query = $analyzed_sql[0]['unsorted_query']; } // Handles the case of multiple clicks on a column's header // which would add many spaces before "ORDER BY" in the // generated query. $unsorted_sql_query = trim($unsorted_sql_query); // sorting by indexes, only if it makes sense (only one table ref) if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['querytype']) && $analyzed_sql[0]['querytype'] == 'SELECT' && isset($analyzed_sql[0]['table_ref']) && count($analyzed_sql[0]['table_ref']) == 1) { // grab indexes data: $indexes = PMA_Index::getFromTable($table, $db); // do we have any index? if ($indexes) { if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { $span = $fields_cnt; if ($is_display['edit_lnk'] != 'nn') { $span++; } if ($is_display['del_lnk'] != 'nn') { $span++; } if ($is_display['del_lnk'] != 'kp' && $is_display['del_lnk'] != 'nn') { $span++; } } else { $span = $num_rows + floor($num_rows / $_SESSION['tmp_user_values']['repeat_cells']) + 1; } echo '<form action="sql.php" method="post">' . "\n"; echo PMA_generate_common_hidden_inputs($db, $table); echo $GLOBALS['strSortByKey'] . ': <select name="sql_query" onchange="this.form.submit();">' . "\n"; $used_index = false; $local_order = isset($sort_expression) ? $sort_expression : ''; foreach ($indexes as $index) { $asc_sort = '`' . implode('` ASC, `', array_keys($index->getColumns())) . '` ASC'; $desc_sort = '`' . implode('` DESC, `', array_keys($index->getColumns())) . '` DESC'; $used_index = $used_index || $local_order == $asc_sort || $local_order == $desc_sort; echo '<option value="' . htmlspecialchars($unsorted_sql_query . ' ORDER BY ' . $asc_sort) . '"' . ($local_order == $asc_sort ? ' selected="selected"' : '') . '>' . htmlspecialchars($index->getName()) . ' (' . $GLOBALS['strAscending'] . ')</option>'; echo '<option value="' . htmlspecialchars($unsorted_sql_query . ' ORDER BY ' . $desc_sort) . '"' . ($local_order == $desc_sort ? ' selected="selected"' : '') . '>' . htmlspecialchars($index->getName()) . ' (' . $GLOBALS['strDescending'] . ')</option>'; } echo '<option value="' . htmlspecialchars($unsorted_sql_query) . '"' . ($used_index ? '' : ' selected="selected"') . '>' . $GLOBALS['strNone'] . '</option>'; echo '</select>' . "\n"; echo '<noscript><input type="submit" value="' . $GLOBALS['strGo'] . '" /></noscript>'; echo '</form>' . "\n"; } } } $vertical_display['emptypre'] = 0; $vertical_display['emptyafter'] = 0; $vertical_display['textbtn'] = ''; // Display options (if we are not in print view) if (!(isset($GLOBALS['printview']) && $GLOBALS['printview'] == '1')) { echo '<form method="post" action="sql.php" name="displayOptionsForm" id="displayOptionsForm">'; $url_params = array('db' => $db, 'table' => $table, 'sql_query' => $sql_query, 'goto' => $goto, 'display_options_form' => 1); echo PMA_generate_common_hidden_inputs($url_params); echo '<br />'; PMA_generate_slider_effect('displayoptions', $GLOBALS['strOptions']); echo '<fieldset>'; echo '<div class="formelement">'; $choices = array('P' => $GLOBALS['strPartialText'], 'F' => $GLOBALS['strFullText']); PMA_display_html_radio('display_text', $choices, $_SESSION['tmp_user_values']['display_text']); echo '</div>'; // prepare full/partial text button or link if ($_SESSION['tmp_user_values']['display_text'] == 'F') { // currently in fulltext mode so show the opposite link $tmp_image_file = $GLOBALS['pmaThemeImage'] . 's_partialtext.png'; $tmp_txt = $GLOBALS['strPartialText']; $url_params['display_text'] = 'P'; } else { $tmp_image_file = $GLOBALS['pmaThemeImage'] . 's_fulltext.png'; $tmp_txt = $GLOBALS['strFullText']; $url_params['display_text'] = 'F'; } $tmp_image = '<img class="fulltext" width="50" height="20" src="' . $tmp_image_file . '" alt="' . $tmp_txt . '" title="' . $tmp_txt . '" />'; $tmp_url = 'sql.php' . PMA_generate_common_url($url_params); $full_or_partial_text_link = PMA_linkOrButton($tmp_url, $tmp_image, array(), false); unset($tmp_image_file, $tmp_txt, $tmp_url, $tmp_image); if ($GLOBALS['cfgRelation']['relwork'] && $GLOBALS['cfgRelation']['displaywork']) { echo '<div class="formelement">'; $choices = array('K' => $GLOBALS['strRelationalKey'], 'D' => $GLOBALS['strRelationalDisplayField']); PMA_display_html_radio('relational_display', $choices, $_SESSION['tmp_user_values']['relational_display']); echo '</div>'; } echo '<div class="formelement">'; PMA_display_html_checkbox('display_binary', $GLOBALS['strShowBinaryContents'], !empty($_SESSION['tmp_user_values']['display_binary']), false); echo '<br />'; PMA_display_html_checkbox('display_blob', $GLOBALS['strShowBLOBContents'], !empty($_SESSION['tmp_user_values']['display_blob']), false); echo '<br />'; PMA_display_html_checkbox('display_binary_as_hex', $GLOBALS['strShowBinaryContentsAsHex'], !empty($_SESSION['tmp_user_values']['display_binary_as_hex']), false); echo '</div>'; // I would have preferred to name this "display_transformation". // This is the only way I found to be able to keep this setting sticky // per SQL query, and at the same time have a default that displays // the transformations. echo '<div class="formelement">'; PMA_display_html_checkbox('hide_transformation', $GLOBALS['strHide'] . ' ' . $GLOBALS['strMIME_transformation'], !empty($_SESSION['tmp_user_values']['hide_transformation']), false); echo '</div>'; echo '<div class="clearfloat"></div>'; echo '</fieldset>'; echo '<fieldset class="tblFooters">'; echo '<input type="submit" value="' . $GLOBALS['strGo'] . '" />'; echo '</fieldset>'; echo '</div>'; echo '</form>'; } // Start of form for multi-rows edit/delete/export if ($is_display['del_lnk'] == 'dr' || $is_display['del_lnk'] == 'kp') { echo '<form method="post" action="tbl_row_action.php" name="rowsDeleteForm" id="rowsDeleteForm">' . "\n"; echo PMA_generate_common_hidden_inputs($db, $table, 1); echo '<input type="hidden" name="goto" value="sql.php" />' . "\n"; } echo '<table id="table_results" class="data">' . "\n"; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo '<thead><tr>' . "\n"; } // 1. Displays the full/partial text button (part 1)... if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { $colspan = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? ' colspan="3"' : ''; } else { $rowspan = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? ' rowspan="3"' : ''; } // ... before the result table if ($is_display['edit_lnk'] == 'nn' && $is_display['del_lnk'] == 'nn' && $is_display['text_btn'] == '1') { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 0; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { ?> <th colspan="<?php echo $fields_cnt; ?> "></th> </tr> <tr> <?php } else { ?> <tr> <th colspan="<?php echo $num_rows + floor($num_rows / $_SESSION['tmp_user_values']['repeat_cells']) + 1; ?> "></th> </tr> <?php } // end vertical mode } elseif ($GLOBALS['cfg']['ModifyDeleteAtLeft'] && $is_display['text_btn'] == '1') { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 0; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { ?> <th <?php echo $colspan; ?> ><?php echo $full_or_partial_text_link; ?> </th> <?php } else { $vertical_display['textbtn'] = ' <th ' . $rowspan . ' valign="middle">' . "\n" . ' ' . "\n" . ' </th>' . "\n"; } // end vertical mode } elseif ($GLOBALS['cfg']['ModifyDeleteAtLeft'] && ($is_display['edit_lnk'] != 'nn' || $is_display['del_lnk'] != 'nn')) { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 0; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { ?> <td<?php echo $colspan; ?> ></td> <?php } else { $vertical_display['textbtn'] = ' <td' . $rowspan . '></td>' . "\n"; } // end vertical mode } // 2. Displays the fields' name // 2.0 If sorting links should be used, checks if the query is a "JOIN" // statement (see 2.1.3) // 2.0.1 Prepare Display column comments if enabled ($GLOBALS['cfg']['ShowBrowseComments']). // Do not show comments, if using horizontalflipped mode, because of space usage if ($GLOBALS['cfg']['ShowBrowseComments'] && $_SESSION['tmp_user_values']['disp_direction'] != 'horizontalflipped') { $comments_map = array(); if (isset($analyzed_sql[0]) && is_array($analyzed_sql[0])) { foreach ($analyzed_sql[0]['table_ref'] as $tbl) { $tb = $tbl['table_true_name']; $comments_map[$tb] = PMA_getComments($db, $tb); unset($tb); } } } if ($GLOBALS['cfgRelation']['commwork'] && $GLOBALS['cfgRelation']['mimework'] && $GLOBALS['cfg']['BrowseMIME'] && !$_SESSION['tmp_user_values']['hide_transformation']) { require_once './libraries/transformations.lib.php'; $GLOBALS['mime_map'] = PMA_getMIME($db, $table); } if ($is_display['sort_lnk'] == '1') { $select_expr = $analyzed_sql[0]['select_expr_clause']; } // garvin: See if we have to highlight any header fields of a WHERE query. // Uses SQL-Parser results. $highlight_columns = array(); if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['where_clause_identifiers'])) { $wi = 0; if (isset($analyzed_sql[0]['where_clause_identifiers']) && is_array($analyzed_sql[0]['where_clause_identifiers'])) { foreach ($analyzed_sql[0]['where_clause_identifiers'] as $wci_nr => $wci) { $highlight_columns[$wci] = 'true'; } } } for ($i = 0; $i < $fields_cnt; $i++) { // garvin: See if this column should get highlight because it's used in the // where-query. if (isset($highlight_columns[$fields_meta[$i]->name]) || isset($highlight_columns[PMA_backquote($fields_meta[$i]->name)])) { $condition_field = true; } else { $condition_field = false; } // 2.0 Prepare comment-HTML-wrappers for each row, if defined/enabled. if (isset($comments_map) && isset($comments_map[$fields_meta[$i]->table]) && isset($comments_map[$fields_meta[$i]->table][$fields_meta[$i]->name])) { $comments = '<span class="tblcomment">' . htmlspecialchars($comments_map[$fields_meta[$i]->table][$fields_meta[$i]->name]) . '</span>'; } else { $comments = ''; } // 2.1 Results can be sorted if ($is_display['sort_lnk'] == '1') { // 2.1.1 Checks if the table name is required; it's the case // for a query with a "JOIN" statement and if the column // isn't aliased, or in queries like // SELECT `1`.`master_field` , `2`.`master_field` // FROM `PMA_relation` AS `1` , `PMA_relation` AS `2` if (isset($fields_meta[$i]->table) && strlen($fields_meta[$i]->table)) { $sort_tbl = PMA_backquote($fields_meta[$i]->table) . '.'; } else { $sort_tbl = ''; } // 2.1.2 Checks if the current column is used to sort the // results // the orgname member does not exist for all MySQL versions // but if found, it's the one on which to sort $name_to_use_in_sort = $fields_meta[$i]->name; if (isset($fields_meta[$i]->orgname) && strlen($fields_meta[$i]->orgname)) { $name_to_use_in_sort = $fields_meta[$i]->orgname; } // $name_to_use_in_sort might contain a space due to // formatting of function expressions like "COUNT(name )" // so we remove the space in this situation $name_to_use_in_sort = str_replace(' )', ')', $name_to_use_in_sort); if (empty($sort_expression)) { $is_in_sort = false; } else { // Field name may be preceded by a space, or any number // of characters followed by a dot (tablename.fieldname) // so do a direct comparison for the sort expression; // this avoids problems with queries like // "SELECT id, count(id)..." and clicking to sort // on id or on count(id). // Another query to test this: // SELECT p.*, FROM_UNIXTIME(p.temps) FROM mytable AS p // (and try clicking on each column's header twice) if (!empty($sort_tbl) && strpos($sort_expression_nodirection, $sort_tbl) === false && strpos($sort_expression_nodirection, '(') === false) { $sort_expression_nodirection = $sort_tbl . $sort_expression_nodirection; } $is_in_sort = str_replace('`', '', $sort_tbl) . $name_to_use_in_sort == str_replace('`', '', $sort_expression_nodirection) ? true : false; } // 2.1.3 Check the field name for a bracket. // If it contains one, it's probably a function column // like 'COUNT(`field`)' if (strpos($name_to_use_in_sort, '(') !== false) { $sort_order = ' ORDER BY ' . $name_to_use_in_sort . ' '; } else { $sort_order = ' ORDER BY ' . $sort_tbl . PMA_backquote($name_to_use_in_sort) . ' '; } unset($name_to_use_in_sort); // 2.1.4 Do define the sorting URL if (!$is_in_sort) { // loic1: patch #455484 ("Smart" order) $GLOBALS['cfg']['Order'] = strtoupper($GLOBALS['cfg']['Order']); if ($GLOBALS['cfg']['Order'] === 'SMART') { $sort_order .= preg_match('@time|date@i', $fields_meta[$i]->type) ? 'DESC' : 'ASC'; } else { $sort_order .= $GLOBALS['cfg']['Order']; } $order_img = ''; } elseif ('DESC' == $sort_direction) { $sort_order .= ' ASC'; $order_img = ' <img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 's_desc.png" width="11" height="9" alt="' . $GLOBALS['strDescending'] . '" title="' . $GLOBALS['strDescending'] . '" id="soimg' . $i . '" />'; } else { $sort_order .= ' DESC'; $order_img = ' <img class="icon" src="' . $GLOBALS['pmaThemeImage'] . 's_asc.png" width="11" height="9" alt="' . $GLOBALS['strAscending'] . '" title="' . $GLOBALS['strAscending'] . '" id="soimg' . $i . '" />'; } if (preg_match('@(.*)([[:space:]](LIMIT (.*)|PROCEDURE (.*)|FOR UPDATE|LOCK IN SHARE MODE))@i', $unsorted_sql_query, $regs3)) { $sorted_sql_query = $regs3[1] . $sort_order . $regs3[2]; } else { $sorted_sql_query = $unsorted_sql_query . $sort_order; } $_url_params = array('db' => $db, 'table' => $table, 'sql_query' => $sorted_sql_query); $order_url = 'sql.php' . PMA_generate_common_url($_url_params); // 2.1.5 Displays the sorting URL // added 20004-06-09: Michael Keck <*****@*****.**> // enable sort order swapping for image $order_link_params = array(); if (isset($order_img) && $order_img != '') { if (strstr($order_img, 'asc')) { $order_link_params['onmouseover'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_desc.png\'; }'; $order_link_params['onmouseout'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_asc.png\'; }'; } elseif (strstr($order_img, 'desc')) { $order_link_params['onmouseover'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_asc.png\'; }'; $order_link_params['onmouseout'] = 'if(document.getElementById(\'soimg' . $i . '\')){ document.getElementById(\'soimg' . $i . '\').src=\'' . $GLOBALS['pmaThemeImage'] . 's_desc.png\'; }'; } } if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'css') { $order_link_params['style'] = 'direction: ltr; writing-mode: tb-rl;'; } $order_link_params['title'] = $GLOBALS['strSort']; $order_link_content = $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'fake' ? PMA_flipstring(htmlspecialchars($fields_meta[$i]->name), "<br />\n") : htmlspecialchars($fields_meta[$i]->name); $order_link = PMA_linkOrButton($order_url, $order_link_content . $order_img, $order_link_params, false, true); if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo '<th'; if ($condition_field) { echo ' class="condition"'; } if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo ' valign="bottom"'; } echo '>' . $order_link . $comments . '</th>'; } $vertical_display['desc'][] = ' <th ' . ($condition_field ? ' class="condition"' : '') . '>' . "\n" . $order_link . $comments . ' </th>' . "\n"; } else { if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo '<th'; if ($condition_field) { echo ' class="condition"'; } if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo ' valign="bottom"'; } if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'css') { echo ' style="direction: ltr; writing-mode: tb-rl;"'; } echo '>'; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'fake') { echo PMA_flipstring(htmlspecialchars($fields_meta[$i]->name), '<br />'); } else { echo htmlspecialchars($fields_meta[$i]->name); } echo "\n" . $comments . '</th>'; } $vertical_display['desc'][] = ' <th ' . ($condition_field ? ' class="condition"' : '') . '>' . "\n" . ' ' . htmlspecialchars($fields_meta[$i]->name) . "\n" . $comments . ' </th>'; } // end else (2.2) } // end for // 3. Displays the needed checkboxes at the right // column of the result table header if possible and required... if ($GLOBALS['cfg']['ModifyDeleteAtRight'] && ($is_display['edit_lnk'] != 'nn' || $is_display['del_lnk'] != 'nn') && $is_display['text_btn'] == '1') { $vertical_display['emptyafter'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 1; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo "\n"; ?> <th <?php echo $colspan; ?> ><?php echo $full_or_partial_text_link; ?> </th> <?php } else { $vertical_display['textbtn'] = ' <th ' . $rowspan . ' valign="middle">' . "\n" . ' ' . "\n" . ' </th>' . "\n"; } // end vertical mode } elseif ($GLOBALS['cfg']['ModifyDeleteAtRight'] && ($is_display['edit_lnk'] == 'nn' && $is_display['del_lnk'] == 'nn') && !$GLOBALS['is_header_sent']) { $vertical_display['emptyafter'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 1; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo "\n"; ?> <td<?php echo $colspan; ?> ></td> <?php } else { $vertical_display['textbtn'] = ' <td' . $rowspan . '></td>' . "\n"; } // end vertical mode } if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { ?> </tr> </thead> <?php } return true; }
/** * Displays the headers of the results table * * @param array &$is_display which elements to display * @param array &$fields_meta the list of fields properties * @param integer $fields_cnt the total number of fields returned by the SQL query * @param array $analyzed_sql the analyzed query * @param string $sort_expression sort expression * @param string $sort_expression_nodirection sort expression without direction * @param string $sort_direction sort direction * * @return boolean $clause_is_unique * * @global string $db the database name * @global string $table the table name * @global string $goto the URL to go back in case of errors * @global string $sql_query the SQL query * @global integer $num_rows the total number of rows returned by the * SQL query * @global array $vertical_display informations used with vertical display * mode * * @access private * * @see PMA_displayTable() */ function PMA_displayTableHeaders(&$is_display, &$fields_meta, $fields_cnt = 0, $analyzed_sql = '', $sort_expression, $sort_expression_nodirection, $sort_direction) { global $db, $table, $goto; global $sql_query, $num_rows; global $vertical_display, $highlight_columns; // required to generate sort links that will remember whether the // "Show all" button has been clicked $sql_md5 = md5($GLOBALS['sql_query']); $session_max_rows = $_SESSION['tmp_user_values']['query'][$sql_md5]['max_rows']; if ($analyzed_sql == '') { $analyzed_sql = array(); } // can the result be sorted? if ($is_display['sort_lnk'] == '1') { // Just as fallback $unsorted_sql_query = $sql_query; if (isset($analyzed_sql[0]['unsorted_query'])) { $unsorted_sql_query = $analyzed_sql[0]['unsorted_query']; } // Handles the case of multiple clicks on a column's header // which would add many spaces before "ORDER BY" in the // generated query. $unsorted_sql_query = trim($unsorted_sql_query); // sorting by indexes, only if it makes sense (only one table ref) if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['querytype']) && $analyzed_sql[0]['querytype'] == 'SELECT' && isset($analyzed_sql[0]['table_ref']) && count($analyzed_sql[0]['table_ref']) == 1) { // grab indexes data: $indexes = PMA_Index::getFromTable($table, $db); // do we have any index? if ($indexes) { if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { $span = $fields_cnt; if ($is_display['edit_lnk'] != 'nn') { $span++; } if ($is_display['del_lnk'] != 'nn') { $span++; } if ($is_display['del_lnk'] != 'kp' && $is_display['del_lnk'] != 'nn') { $span++; } } else { $span = $num_rows + floor($num_rows / $_SESSION['tmp_user_values']['repeat_cells']) + 1; } echo '<form action="sql.php" method="post">' . "\n"; echo PMA_generate_common_hidden_inputs($db, $table); echo __('Sort by key') . ': <select name="sql_query" class="autosubmit">' . "\n"; $used_index = false; $local_order = isset($sort_expression) ? $sort_expression : ''; foreach ($indexes as $index) { $asc_sort = '`' . implode('` ASC, `', array_keys($index->getColumns())) . '` ASC'; $desc_sort = '`' . implode('` DESC, `', array_keys($index->getColumns())) . '` DESC'; $used_index = $used_index || $local_order == $asc_sort || $local_order == $desc_sort; if (preg_match('@(.*)([[:space:]](LIMIT (.*)|PROCEDURE (.*)|FOR UPDATE|LOCK IN SHARE MODE))@is', $unsorted_sql_query, $my_reg)) { $unsorted_sql_query_first_part = $my_reg[1]; $unsorted_sql_query_second_part = $my_reg[2]; } else { $unsorted_sql_query_first_part = $unsorted_sql_query; $unsorted_sql_query_second_part = ''; } echo '<option value="' . htmlspecialchars($unsorted_sql_query_first_part . "\n" . ' ORDER BY ' . $asc_sort . $unsorted_sql_query_second_part) . '"' . ($local_order == $asc_sort ? ' selected="selected"' : '') . '>' . htmlspecialchars($index->getName()) . ' (' . __('Ascending') . ')</option>'; echo '<option value="' . htmlspecialchars($unsorted_sql_query_first_part . "\n" . ' ORDER BY ' . $desc_sort . $unsorted_sql_query_second_part) . '"' . ($local_order == $desc_sort ? ' selected="selected"' : '') . '>' . htmlspecialchars($index->getName()) . ' (' . __('Descending') . ')</option>'; } echo '<option value="' . htmlspecialchars($unsorted_sql_query) . '"' . ($used_index ? '' : ' selected="selected"') . '>' . __('None') . '</option>'; echo '</select>' . "\n"; echo '<noscript><input type="submit" value="' . __('Go') . '" /></noscript>'; echo '</form>' . "\n"; } } } // Output data needed for grid editing echo '<input id="save_cells_at_once" type="hidden" value="' . $GLOBALS['cfg']['SaveCellsAtOnce'] . '" />'; echo '<div class="common_hidden_inputs">'; echo PMA_generate_common_hidden_inputs($db, $table); echo '</div>'; // Output data needed for column reordering and show/hide column if (PMA_isSelect()) { // generate the column order, if it is set $pmatable = new PMA_Table($GLOBALS['table'], $GLOBALS['db']); $col_order = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_ORDER); if ($col_order) { echo '<input id="col_order" type="hidden" value="' . implode(',', $col_order) . '" />'; } $col_visib = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_VISIB); if ($col_visib) { echo '<input id="col_visib" type="hidden" value="' . implode(',', $col_visib) . '" />'; } // generate table create time if (!PMA_Table::isView($GLOBALS['table'], $GLOBALS['db'])) { echo '<input id="table_create_time" type="hidden" value="' . PMA_Table::sGetStatusInfo($GLOBALS['db'], $GLOBALS['table'], 'Create_time') . '" />'; } } $vertical_display['emptypre'] = 0; $vertical_display['emptyafter'] = 0; $vertical_display['textbtn'] = ''; // Display options (if we are not in print view) if (!(isset($GLOBALS['printview']) && $GLOBALS['printview'] == '1')) { echo '<form method="post" action="sql.php" name="displayOptionsForm" id="displayOptionsForm"'; if ($GLOBALS['cfg']['AjaxEnable']) { echo ' class="ajax" '; } echo '>'; $url_params = array('db' => $db, 'table' => $table, 'sql_query' => $sql_query, 'goto' => $goto, 'display_options_form' => 1); echo PMA_generate_common_hidden_inputs($url_params); echo '<br />'; PMA_generate_slider_effect('displayoptions', __('Options')); echo '<fieldset>'; echo '<div class="formelement">'; $choices = array('P' => __('Partial texts'), 'F' => __('Full texts')); PMA_display_html_radio('display_text', $choices, $_SESSION['tmp_user_values']['display_text']); echo '</div>'; // prepare full/partial text button or link $url_params_full_text = array('db' => $db, 'table' => $table, 'sql_query' => $sql_query, 'goto' => $goto, 'full_text_button' => 1); if ($_SESSION['tmp_user_values']['display_text'] == 'F') { // currently in fulltext mode so show the opposite link $tmp_image_file = $GLOBALS['pmaThemeImage'] . 's_partialtext.png'; $tmp_txt = __('Partial texts'); $url_params_full_text['display_text'] = 'P'; } else { $tmp_image_file = $GLOBALS['pmaThemeImage'] . 's_fulltext.png'; $tmp_txt = __('Full texts'); $url_params_full_text['display_text'] = 'F'; } $tmp_image = '<img class="fulltext" src="' . $tmp_image_file . '" alt="' . $tmp_txt . '" title="' . $tmp_txt . '" />'; $tmp_url = 'sql.php' . PMA_generate_common_url($url_params_full_text); $full_or_partial_text_link = PMA_linkOrButton($tmp_url, $tmp_image, array(), false); unset($tmp_image_file, $tmp_txt, $tmp_url, $tmp_image); if ($GLOBALS['cfgRelation']['relwork'] && $GLOBALS['cfgRelation']['displaywork']) { echo '<div class="formelement">'; $choices = array('K' => __('Relational key'), 'D' => __('Relational display column')); PMA_display_html_radio('relational_display', $choices, $_SESSION['tmp_user_values']['relational_display']); echo '</div>'; } echo '<div class="formelement">'; PMA_display_html_checkbox('display_binary', __('Show binary contents'), !empty($_SESSION['tmp_user_values']['display_binary']), false); echo '<br />'; PMA_display_html_checkbox('display_blob', __('Show BLOB contents'), !empty($_SESSION['tmp_user_values']['display_blob']), false); echo '<br />'; PMA_display_html_checkbox('display_binary_as_hex', __('Show binary contents as HEX'), !empty($_SESSION['tmp_user_values']['display_binary_as_hex']), false); echo '</div>'; // I would have preferred to name this "display_transformation". // This is the only way I found to be able to keep this setting sticky // per SQL query, and at the same time have a default that displays // the transformations. echo '<div class="formelement">'; PMA_display_html_checkbox('hide_transformation', __('Hide browser transformation'), !empty($_SESSION['tmp_user_values']['hide_transformation']), false); echo '</div>'; if (!PMA_DRIZZLE) { echo '<div class="formelement">'; $choices = array('GEOM' => __('Geometry'), 'WKT' => __('Well Known Text'), 'WKB' => __('Well Known Binary')); PMA_display_html_radio('geometry_display', $choices, $_SESSION['tmp_user_values']['geometry_display']); echo '</div>'; } echo '<div class="clearfloat"></div>'; echo '</fieldset>'; echo '<fieldset class="tblFooters">'; echo '<input type="submit" value="' . __('Go') . '" />'; echo '</fieldset>'; echo '</div>'; echo '</form>'; } // Start of form for multi-rows edit/delete/export if ($is_display['del_lnk'] == 'dr' || $is_display['del_lnk'] == 'kp') { echo '<form method="post" action="tbl_row_action.php" name="resultsForm" id="resultsForm"'; if ($GLOBALS['cfg']['AjaxEnable']) { echo ' class="ajax" '; } echo '>' . "\n"; echo PMA_generate_common_hidden_inputs($db, $table, 1); echo '<input type="hidden" name="goto" value="sql.php" />' . "\n"; } echo '<table id="table_results" class="data'; if ($GLOBALS['cfg']['AjaxEnable']) { echo ' ajax'; } echo '">' . "\n"; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo '<thead><tr>' . "\n"; } // 1. Displays the full/partial text button (part 1)... if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { $colspan = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? ' colspan="4"' : ''; } else { $rowspan = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? ' rowspan="4"' : ''; } // ... before the result table if ($is_display['edit_lnk'] == 'nn' && $is_display['del_lnk'] == 'nn' && $is_display['text_btn'] == '1') { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 4 : 0; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { ?> <th colspan="<?php echo $fields_cnt; ?> "></th> </tr> <tr> <?php // end horizontal/horizontalflipped mode } else { ?> <tr> <th colspan="<?php echo $num_rows + floor($num_rows / $_SESSION['tmp_user_values']['repeat_cells']) + 1; ?> "></th> </tr> <?php } // end vertical mode } elseif (($GLOBALS['cfg']['RowActionLinks'] == 'left' || $GLOBALS['cfg']['RowActionLinks'] == 'both') && $is_display['text_btn'] == '1') { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 4 : 0; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { ?> <th <?php echo $colspan; ?> ><?php echo $full_or_partial_text_link; ?> </th> <?php // end horizontal/horizontalflipped mode } else { $vertical_display['textbtn'] = ' <th ' . $rowspan . ' valign="middle">' . "\n" . ' ' . "\n" . ' </th>' . "\n"; } // end vertical mode } elseif (($GLOBALS['cfg']['RowActionLinks'] == 'left' || $GLOBALS['cfg']['RowActionLinks'] == 'both') && ($is_display['edit_lnk'] != 'nn' || $is_display['del_lnk'] != 'nn')) { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 4 : 0; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { ?> <td<?php echo $colspan; ?> ></td> <?php // end horizontal/horizontalfipped mode } else { $vertical_display['textbtn'] = ' <td' . $rowspan . '></td>' . "\n"; } // end vertical mode } elseif ($GLOBALS['cfg']['RowActionLinks'] == 'none' && ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped')) { echo '<th></th>'; } // 2. Displays the fields' name // 2.0 If sorting links should be used, checks if the query is a "JOIN" // statement (see 2.1.3) // 2.0.1 Prepare Display column comments if enabled ($GLOBALS['cfg']['ShowBrowseComments']). // Do not show comments, if using horizontalflipped mode, because of space usage if ($GLOBALS['cfg']['ShowBrowseComments'] && $_SESSION['tmp_user_values']['disp_direction'] != 'horizontalflipped') { $comments_map = array(); if (isset($analyzed_sql[0]) && is_array($analyzed_sql[0])) { foreach ($analyzed_sql[0]['table_ref'] as $tbl) { $tb = $tbl['table_true_name']; $comments_map[$tb] = PMA_getComments($db, $tb); unset($tb); } } } if ($GLOBALS['cfgRelation']['commwork'] && $GLOBALS['cfgRelation']['mimework'] && $GLOBALS['cfg']['BrowseMIME'] && !$_SESSION['tmp_user_values']['hide_transformation']) { include_once './libraries/transformations.lib.php'; $GLOBALS['mime_map'] = PMA_getMIME($db, $table); } // See if we have to highlight any header fields of a WHERE query. // Uses SQL-Parser results. $highlight_columns = array(); if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['where_clause_identifiers'])) { $wi = 0; if (isset($analyzed_sql[0]['where_clause_identifiers']) && is_array($analyzed_sql[0]['where_clause_identifiers'])) { foreach ($analyzed_sql[0]['where_clause_identifiers'] as $wci_nr => $wci) { $highlight_columns[$wci] = 'true'; } } } if (PMA_isSelect()) { // prepare to get the column order, if available $pmatable = new PMA_Table($GLOBALS['table'], $GLOBALS['db']); $col_order = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_ORDER); $col_visib = $pmatable->getUiProp(PMA_Table::PROP_COLUMN_VISIB); } else { $col_order = false; $col_visib = false; } for ($j = 0; $j < $fields_cnt; $j++) { // assign $i with appropriate column order $i = $col_order ? $col_order[$j] : $j; // See if this column should get highlight because it's used in the // where-query. if (isset($highlight_columns[$fields_meta[$i]->name]) || isset($highlight_columns[PMA_backquote($fields_meta[$i]->name)])) { $condition_field = true; } else { $condition_field = false; } // 2.0 Prepare comment-HTML-wrappers for each row, if defined/enabled. if (isset($comments_map) && isset($comments_map[$fields_meta[$i]->table]) && isset($comments_map[$fields_meta[$i]->table][$fields_meta[$i]->name])) { $comments = '<span class="tblcomment">' . htmlspecialchars($comments_map[$fields_meta[$i]->table][$fields_meta[$i]->name]) . '</span>'; } else { $comments = ''; } // 2.1 Results can be sorted if ($is_display['sort_lnk'] == '1') { // 2.1.1 Checks if the table name is required; it's the case // for a query with a "JOIN" statement and if the column // isn't aliased, or in queries like // SELECT `1`.`master_field` , `2`.`master_field` // FROM `PMA_relation` AS `1` , `PMA_relation` AS `2` if (isset($fields_meta[$i]->table) && strlen($fields_meta[$i]->table)) { $sort_tbl = PMA_backquote($fields_meta[$i]->table) . '.'; } else { $sort_tbl = ''; } // 2.1.2 Checks if the current column is used to sort the // results // the orgname member does not exist for all MySQL versions // but if found, it's the one on which to sort $name_to_use_in_sort = $fields_meta[$i]->name; $is_orgname = false; if (isset($fields_meta[$i]->orgname) && strlen($fields_meta[$i]->orgname)) { $name_to_use_in_sort = $fields_meta[$i]->orgname; $is_orgname = true; } // $name_to_use_in_sort might contain a space due to // formatting of function expressions like "COUNT(name )" // so we remove the space in this situation $name_to_use_in_sort = str_replace(' )', ')', $name_to_use_in_sort); if (empty($sort_expression)) { $is_in_sort = false; } else { // Field name may be preceded by a space, or any number // of characters followed by a dot (tablename.fieldname) // so do a direct comparison for the sort expression; // this avoids problems with queries like // "SELECT id, count(id)..." and clicking to sort // on id or on count(id). // Another query to test this: // SELECT p.*, FROM_UNIXTIME(p.temps) FROM mytable AS p // (and try clicking on each column's header twice) if (!empty($sort_tbl) && strpos($sort_expression_nodirection, $sort_tbl) === false && strpos($sort_expression_nodirection, '(') === false) { $sort_expression_nodirection = $sort_tbl . $sort_expression_nodirection; } $is_in_sort = str_replace('`', '', $sort_tbl) . $name_to_use_in_sort == str_replace('`', '', $sort_expression_nodirection) ? true : false; } // 2.1.3 Check the field name for a bracket. // If it contains one, it's probably a function column // like 'COUNT(`field`)' // It still might be a column name of a view. See bug #3383711 // Check is_orgname. if (strpos($name_to_use_in_sort, '(') !== false && !$is_orgname) { $sort_order = "\n" . 'ORDER BY ' . $name_to_use_in_sort . ' '; } else { $sort_order = "\n" . 'ORDER BY ' . $sort_tbl . PMA_backquote($name_to_use_in_sort) . ' '; } unset($name_to_use_in_sort); unset($is_orgname); // 2.1.4 Do define the sorting URL if (!$is_in_sort) { // patch #455484 ("Smart" order) $GLOBALS['cfg']['Order'] = strtoupper($GLOBALS['cfg']['Order']); if ($GLOBALS['cfg']['Order'] === 'SMART') { $sort_order .= preg_match('@time|date@i', $fields_meta[$i]->type) ? 'DESC' : 'ASC'; } else { $sort_order .= $GLOBALS['cfg']['Order']; } $order_img = ''; } elseif ('DESC' == $sort_direction) { $sort_order .= ' ASC'; $order_img = ' ' . PMA_getImage('s_desc.png', __('Descending'), array('class' => "soimg{$i}", 'title' => '')); $order_img .= ' ' . PMA_getImage('s_asc.png', __('Ascending'), array('class' => "soimg{$i} hide", 'title' => '')); } else { $sort_order .= ' DESC'; $order_img = ' ' . PMA_getImage('s_asc.png', __('Ascending'), array('class' => "soimg{$i}", 'title' => '')); $order_img .= ' ' . PMA_getImage('s_desc.png', __('Descending'), array('class' => "soimg{$i} hide", 'title' => '')); } if (preg_match('@(.*)([[:space:]](LIMIT (.*)|PROCEDURE (.*)|FOR UPDATE|LOCK IN SHARE MODE))@is', $unsorted_sql_query, $regs3)) { $sorted_sql_query = $regs3[1] . $sort_order . $regs3[2]; } else { $sorted_sql_query = $unsorted_sql_query . $sort_order; } $_url_params = array('db' => $db, 'table' => $table, 'sql_query' => $sorted_sql_query, 'session_max_rows' => $session_max_rows); $order_url = 'sql.php' . PMA_generate_common_url($_url_params); // 2.1.5 Displays the sorting URL // enable sort order swapping for image $order_link_params = array(); if (isset($order_img) && $order_img != '') { if (strstr($order_img, 'asc')) { $order_link_params['onmouseover'] = "\$('.soimg{$i}').toggle()"; $order_link_params['onmouseout'] = "\$('.soimg{$i}').toggle()"; } elseif (strstr($order_img, 'desc')) { $order_link_params['onmouseover'] = "\$('.soimg{$i}').toggle()"; $order_link_params['onmouseout'] = "\$('.soimg{$i}').toggle()"; } } if ($GLOBALS['cfg']['HeaderFlipType'] == 'auto') { if (PMA_USR_BROWSER_AGENT == 'IE') { $GLOBALS['cfg']['HeaderFlipType'] = 'css'; } else { $GLOBALS['cfg']['HeaderFlipType'] = 'fake'; } } if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'css') { $order_link_params['style'] = 'direction: ltr; writing-mode: tb-rl;'; } $order_link_params['title'] = __('Sort'); $order_link_content = $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'fake' ? PMA_flipstring(htmlspecialchars($fields_meta[$i]->name), "<br />\n") : htmlspecialchars($fields_meta[$i]->name); $order_link = PMA_linkOrButton($order_url, $order_link_content . $order_img, $order_link_params, false, true); if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo '<th'; $th_class = array(); $th_class[] = 'draggable'; if ($col_visib && !$col_visib[$j]) { $th_class[] = 'hide'; } if ($condition_field) { $th_class[] = 'condition'; } $th_class[] = 'column_heading'; if ($GLOBALS['cfg']['BrowsePointerEnable'] == true) { $th_class[] = 'pointer'; } if ($GLOBALS['cfg']['BrowseMarkerEnable'] == true) { $th_class[] = 'marker'; } echo ' class="' . implode(' ', $th_class) . '"'; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo ' valign="bottom"'; } echo '>' . $order_link . $comments . '</th>'; } $vertical_display['desc'][] = ' <th ' . 'class="draggable' . ($condition_field ? ' condition' : '') . '">' . "\n" . $order_link . $comments . ' </th>' . "\n"; } else { if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo '<th'; $th_class = array(); $th_class[] = 'draggable'; if ($col_visib && !$col_visib[$j]) { $th_class[] = 'hide'; } if ($condition_field) { $th_class[] = 'condition'; } echo ' class="' . implode(' ', $th_class) . '"'; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo ' valign="bottom"'; } if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'css') { echo ' style="direction: ltr; writing-mode: tb-rl;"'; } echo '>'; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'fake') { echo PMA_flipstring(htmlspecialchars($fields_meta[$i]->name), '<br />'); } else { echo htmlspecialchars($fields_meta[$i]->name); } echo "\n" . $comments . '</th>'; } $vertical_display['desc'][] = ' <th ' . 'class="draggable' . ($condition_field ? ' condition"' : '') . '">' . "\n" . ' ' . htmlspecialchars($fields_meta[$i]->name) . "\n" . $comments . ' </th>'; } // end else (2.2) } // end for // 3. Displays the needed checkboxes at the right // column of the result table header if possible and required... if (($GLOBALS['cfg']['RowActionLinks'] == 'right' || $GLOBALS['cfg']['RowActionLinks'] == 'both') && ($is_display['edit_lnk'] != 'nn' || $is_display['del_lnk'] != 'nn') && $is_display['text_btn'] == '1') { $vertical_display['emptyafter'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 4 : 1; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo "\n"; ?> <th <?php echo $colspan; ?> ><?php echo $full_or_partial_text_link; ?> </th> <?php // end horizontal/horizontalflipped mode } else { $vertical_display['textbtn'] = ' <th ' . $rowspan . ' valign="middle">' . "\n" . ' ' . "\n" . ' </th>' . "\n"; } // end vertical mode } elseif (($GLOBALS['cfg']['RowActionLinks'] == 'left' || $GLOBALS['cfg']['RowActionLinks'] == 'both') && ($is_display['edit_lnk'] == 'nn' && $is_display['del_lnk'] == 'nn') && !$GLOBALS['is_header_sent']) { $vertical_display['emptyafter'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 4 : 1; if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { echo "\n"; ?> <td<?php echo $colspan; ?> ></td> <?php // end horizontal/horizontalflipped mode } else { $vertical_display['textbtn'] = ' <td' . $rowspan . '></td>' . "\n"; } // end vertical mode } if ($_SESSION['tmp_user_values']['disp_direction'] == 'horizontal' || $_SESSION['tmp_user_values']['disp_direction'] == 'horizontalflipped') { ?> </tr> </thead> <?php } return true; }
/** * Displays the headers of the results table * * @param array which elements to display * @param array the list of fields properties * @param integer the total number of fields returned by the sql query * @param array the analyzed query * * @return boolean always true * * @global string the current language * @global string the current charset for MySQL * @global integer the server to use (refers to the number in the * configuration file) * @global string the database name * @global string the table name * @global string the sql query * @global string the url to go back in case of errors * @global integer the total number of rows returned by the sql query * @global integer the current position in results * @global integer the maximum number of rows per page * @global array informations used with vertical display mode * @global string the display mode (horizontal/vertical/horizontalflipped) * @global integer the number of row to display between two table headers * @global boolean whether to limit the number of displayed characters of * text type fields or not * * @access private * * @see PMA_displayTable() */ function PMA_displayTableHeaders(&$is_display, &$fields_meta, $fields_cnt = 0, $analyzed_sql = '') { global $lang, $convcharset, $server, $db, $table; global $goto; global $sql_query, $num_rows, $pos, $session_max_rows; global $vertical_display, $disp_direction, $repeat_cells, $highlight_columns; global $dontlimitchars; if ($analyzed_sql == '') { $analyzed_sql = array(); } // can be result sorted? if ($is_display['sort_lnk'] == '1') { // Defines the url used to append/modify a sorting order // Nijel: This was originally done inside loop below, but I see // no reason to do this for each column. if (preg_match('@(.*)([[:space:]]ORDER[[:space:]]*BY[[:space:]](.*))@si', $sql_query, $regs1)) { if (preg_match('@((.*)([[:space:]]ASC|[[:space:]]DESC)([[:space:]]|$))(.*)@si', $regs1[2], $regs2)) { $unsorted_sql_query = trim($regs1[1] . ' ' . $regs2[5]); $sql_order = trim($regs2[1]); preg_match('@(ORDER[[:space:]]*BY[[:space:]]*)(.*)([[:space:]]*ASC|[[:space:]]*DESC)@si', $sql_order, $after_order); $sort_expression = trim($after_order[2]); } else { if (preg_match('@((.*))[[:space:]]+(LIMIT (.*)|PROCEDURE (.*)|FOR UPDATE|LOCK IN SHARE MODE)@si', $regs1[2], $regs3)) { $unsorted_sql_query = trim($regs1[1] . ' ' . $regs3[3]); $sql_order = trim($regs3[1]) . ' ASC'; preg_match('@(ORDER[[:space:]]*BY[[:space:]]*)(.*)([[:space:]]*ASC|[[:space:]]*DESC)@si', $sql_order, $after_order); $sort_expression = trim($after_order[2]); } else { $unsorted_sql_query = trim($regs1[1]); $sql_order = trim($regs1[2]) . ' ASC'; preg_match('@(ORDER[[:space:]]*BY[[:space:]]*)(.*)([[:space:]]*ASC|[[:space:]]*DESC)@si', $sql_order, $after_order); $sort_expression = trim($after_order[2]); } } } else { $unsorted_sql_query = $sql_query; } // sorting by indexes, only if it makes sense if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['querytype']) && $analyzed_sql[0]['querytype'] == 'SELECT' && isset($analyzed_sql[0]['table_ref']) && count($analyzed_sql[0]['table_ref']) == 1) { // grab indexes data: $local_query = 'SHOW KEYS FROM ' . PMA_backquote($table); $result = PMA_mysql_query($local_query) or PMA_mysqlDie('', $local_query, '', $err_url_0); $idx_cnt = mysql_num_rows($result); $prev_index = ''; for ($i = 0; $i < $idx_cnt; $i++) { $row = defined('PMA_IDX_INCLUDED') ? $ret_keys[$i] : PMA_mysql_fetch_array($result); if ($row['Key_name'] != $prev_index) { $indexes[] = $row['Key_name']; $prev_index = $row['Key_name']; } $indexes_info[$row['Key_name']]['Sequences'][] = $row['Seq_in_index']; $indexes_info[$row['Key_name']]['Non_unique'] = $row['Non_unique']; if (isset($row['Cardinality'])) { $indexes_info[$row['Key_name']]['Cardinality'] = $row['Cardinality']; } // I don't know what does following column mean.... // $indexes_info[$row['Key_name']]['Packed'] = $row['Packed']; $indexes_info[$row['Key_name']]['Comment'] = isset($row['Comment']) ? $row['Comment'] : ''; $indexes_info[$row['Key_name']]['Index_type'] = isset($row['Index_type']) ? $row['Index_type'] : ''; $indexes_data[$row['Key_name']][$row['Seq_in_index']]['Column_name'] = $row['Column_name']; if (isset($row['Sub_part'])) { $indexes_data[$row['Key_name']][$row['Seq_in_index']]['Sub_part'] = $row['Sub_part']; } } // end while // do we have any index? if (isset($indexes_data)) { if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { $span = $fields_cnt; } else { $span = $num_rows + floor($num_rows / $repeat_cells) + 1; } if ($is_display['edit_lnk'] != 'nn') { $span++; } if ($is_display['del_lnk'] != 'nn') { $span++; } ?> <tr> <td colspan="<?php echo $span; ?> " align="center"> <?php echo '<form action="sql.php" method="POST">' . "\n"; echo PMA_generate_common_hidden_inputs($db, $table, 5); echo '<input type="hidden" name="pos" value="' . $pos . '" />' . "\n"; echo '<input type="hidden" name="session_max_rows" value="' . $session_max_rows . '" />' . "\n"; echo '<input type="hidden" name="disp_direction" value="' . $disp_direction . '" />' . "\n"; echo '<input type="hidden" name="repeat_cells" value="' . $repeat_cells . '" />' . "\n"; echo '<input type="hidden" name="dontlimitchars" value="' . $dontlimitchars . '" />' . "\n"; echo $GLOBALS['strSortByKey'] . ': <select name="sql_query"> '; $used_index = false; $local_order = isset($sql_order) ? str_replace(' ', ' ', $sql_order) : ''; foreach ($indexes_data as $key => $val) { $asc_sort = 'ORDER BY '; $desc_sort = 'ORDER BY '; foreach ($val as $key2 => $val2) { $asc_sort .= PMA_backquote($val2['Column_name']) . ' ASC , '; $desc_sort .= PMA_backquote($val2['Column_name']) . ' DESC , '; } $asc_sort = substr($asc_sort, 0, -3); $desc_sort = substr($desc_sort, 0, -3); $used_index = $used_index || $local_order == $asc_sort || $local_order == $desc_sort; echo '<option value="' . htmlspecialchars($unsorted_sql_query . ' ' . $asc_sort) . '"' . ($local_order == $asc_sort ? ' selected="selected"' : '') . '>' . htmlspecialchars($key) . ' (' . $GLOBALS['strAscending'] . ')</option>'; echo "\n"; echo '<option value="' . htmlspecialchars($unsorted_sql_query . ' ' . $desc_sort) . '"' . ($local_order == $desc_sort ? ' selected="selected"' : '') . '>' . htmlspecialchars($key) . ' (' . $GLOBALS['strDescending'] . ')</option>'; echo "\n"; } echo '<option value="' . htmlspecialchars($unsorted_sql_query) . '"' . ($used_index ? '' : ' selected="selected"') . '>' . $GLOBALS['strNone'] . '</option>'; echo "\n"; echo '</select> '; echo "\n"; echo '<input type="submit" value="' . $GLOBALS['strGo'] . '" />'; echo "\n"; echo '</form>'; echo "\n"; ?> </td> </tr> <?php } } } if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { ?> <!-- Results table headers --> <tr> <?php echo "\n"; } $vertical_display['emptypre'] = 0; $vertical_display['emptyafter'] = 0; $vertical_display['textbtn'] = ''; // Start of form for multi-rows delete if ($is_display['del_lnk'] == 'dr' || $is_display['del_lnk'] == 'kp') { echo '<form method="post" action="tbl_row_delete.php" name="rowsDeleteForm">' . "\n"; echo PMA_generate_common_hidden_inputs($db, $table, 1); echo '<input type="hidden" name="disp_direction" value="' . $disp_direction . '" />' . "\n"; echo '<input type="hidden" name="repeat_cells" value="' . $repeat_cells . '" />' . "\n"; echo '<input type="hidden" name="goto" value="' . $goto . '" />' . "\n"; echo '<input type="hidden" name="dontlimitchars" value="' . $dontlimitchars . '" />' . "\n"; } // 1. Displays the full/partial text button (part 1)... if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { $colspan = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? ' colspan="3"' : ''; } else { $rowspan = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? ' rowspan="3"' : ''; } $text_url = 'sql.php?' . PMA_generate_common_url($db, $table) . '&sql_query=' . urlencode($sql_query) . '&pos=' . $pos . '&session_max_rows=' . $session_max_rows . '&pos=' . $pos . '&disp_direction=' . $disp_direction . '&repeat_cells=' . $repeat_cells . '&goto=' . $goto . '&dontlimitchars=' . ($dontlimitchars ? 0 : 1); // ... before the result table if ($is_display['edit_lnk'] == 'nn' && $is_display['del_lnk'] == 'nn' && $is_display['text_btn'] == '1') { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 0; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { ?> <td colspan="<?php echo $fields_cnt; ?> " align="center"> <a href="<?php echo $text_url; ?> "> <img src="./images/<?php echo $dontlimitchars ? 'partialtext' : 'fulltext'; ?> .png" border="0" width="50" height="20" alt="<?php echo $dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']; ?> " title="<?php echo $dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']; ?> " /></a> </td> </tr> <tr> <?php } else { echo "\n"; ?> <tr> <td colspan="<?php echo $num_rows + floor($num_rows / $repeat_cells) + 1; ?> " align="center"> <a href="<?php echo $text_url; ?> "> <img src="./images/<?php echo $dontlimitchars ? 'partialtext' : 'fulltext'; ?> .png" border="0" width="50" height="20" alt="<?php echo $dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']; ?> " title="<?php echo $dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']; ?> " /></a> </td> </tr> <?php } // end vertical mode } else { if ($GLOBALS['cfg']['ModifyDeleteAtLeft'] && $is_display['text_btn'] == '1') { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 0; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo "\n"; ?> <td<?php echo $colspan; ?> align="center"> <a href="<?php echo $text_url; ?> "> <img src="./images/<?php echo $dontlimitchars ? 'partialtext' : 'fulltext'; ?> .png" border="0" width="50" height="20" alt="<?php echo $dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']; ?> " title="<?php echo $dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']; ?> " /></a> </td> <?php } else { $vertical_display['textbtn'] = ' <td' . $rowspan . ' align="center" valign="middle">' . "\n" . ' <a href="' . $text_url . '">' . "\n" . ' <img src="./images/' . ($dontlimitchars ? 'partialtext' : 'fulltext') . '.png" border="0" width="50" height="20" alt="' . ($dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']) . '" title="' . ($dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']) . '" /></a>' . "\n" . ' </td>' . "\n"; } // end vertical mode } else { if ($GLOBALS['cfg']['ModifyDeleteAtLeft'] && ($is_display['edit_lnk'] != 'nn' || $is_display['del_lnk'] != 'nn')) { $vertical_display['emptypre'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 0; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo "\n"; ?> <td<?php echo $colspan; ?> ></td> <?php echo "\n"; } else { $vertical_display['textbtn'] = ' <td' . $rowspan . '></td>' . "\n"; } // end vertical mode } } } // 2. Displays the fields' name // 2.0 If sorting links should be used, checks if the query is a "JOIN" // statement (see 2.1.3) // 2.0.1 Prepare Display column comments if enabled ($cfg['ShowBrowseComments']). // Do not show comments, if using horizontalflipped mode, because of space usage if ($GLOBALS['cfg']['ShowBrowseComments'] && $GLOBALS['cfgRelation']['commwork'] && $disp_direction != 'horizontalflipped') { $comments_map = PMA_getComments($db, $table); } else { $comments_map = array(); } if ($GLOBALS['cfgRelation']['commwork'] && $GLOBALS['cfgRelation']['mimework'] && $GLOBALS['cfg']['BrowseMIME']) { require_once './libraries/transformations.lib.php'; $GLOBALS['mime_map'] = PMA_getMIME($db, $table); } if ($is_display['sort_lnk'] == '1') { $is_join = preg_match('@(.*)[[:space:]]+FROM[[:space:]]+.*[[:space:]]+JOIN@i', $sql_query, $select_stt); } else { $is_join = FALSE; } // garvin: See if we have to highlight any header fields of a WHERE query. // Uses SQL-Parser results. $highlight_columns = array(); if (isset($analyzed_sql) && isset($analyzed_sql[0]) && isset($analyzed_sql[0]['where_clause_identifiers'])) { $wi = 0; if (isset($analyzed_sql[0]['where_clause_identifiers']) && is_array($analyzed_sql[0]['where_clause_identifiers'])) { foreach ($analyzed_sql[0]['where_clause_identifiers'] as $wci_nr => $wci) { $highlight_columns[$wci] = 'true'; } } } for ($i = 0; $i < $fields_cnt; $i++) { // garvin: See if this column should get highlight because it's used in the // where-query. if (isset($highlight_columns[$fields_meta[$i]->name]) || isset($highlight_columns[PMA_backquote($fields_meta[$i]->name)])) { $column_style = 'style="border: 1px solid ' . $GLOBALS['cfg']['BrowseMarkerColor'] . '"'; } else { $column_style = ''; } // 2.0 Prepare comment-HTML-wrappers for each row, if defined/enabled. if (isset($comments_map[$fields_meta[$i]->name])) { $comments_table_wrap_pre = '<table border="0" cellpadding="0" cellspacing="0" width="100%"><tr><th>'; $comments_table_wrap_post = '</th></tr><tr><th style="font-size: 8pt; font-weight: normal">' . htmlspecialchars($comments_map[$fields_meta[$i]->name]) . '</td></tr></table>'; } else { $comments_table_wrap_pre = ''; $comments_table_wrap_post = ''; } // 2.1 Results can be sorted if ($is_display['sort_lnk'] == '1') { // 2.1.1 Checks if the table name is required; it's the case // for a query with a "JOIN" statement and if the column // isn't aliased, or in queries like // SELECT `1`.`master_field` , `2`.`master_field` // FROM `PMA_relation` AS `1` , `PMA_relation` AS `2` if ($is_join && !preg_match('~([^[:space:],]|`[^`]`)[[:space:]]+(as[[:space:]]+)?' . $fields_meta[$i]->name . '~i', $select_stt[1], $parts) || isset($analyzed_sql[0]['select_expr'][$i]['expr']) && isset($analyzed_sql[0]['select_expr'][$i]['column']) && $analyzed_sql[0]['select_expr'][$i]['expr'] != $analyzed_sql[0]['select_expr'][$i]['column'] && !empty($fields_meta[$i]->table)) { $sort_tbl = PMA_backquote($fields_meta[$i]->table) . '.'; } else { $sort_tbl = ''; } // 2.1.2 Checks if the current column is used to sort the // results if (empty($sql_order)) { $is_in_sort = FALSE; } else { // field name may be preceded by a space, or any number // of characters followed by a dot (tablename.fieldname) // so do a direct comparison // for the sort expression (avoids problems with queries // like "SELECT id, count(id)..." and clicking to sort // on id or on count(id) ) $is_in_sort = $sort_tbl . PMA_backquote($fields_meta[$i]->name) == $sort_expression ? TRUE : FALSE; } // 2.1.3 Check the field name for backquotes. // If it contains some, it's probably a function column // like 'COUNT(`field`)' if (strpos(' ' . $fields_meta[$i]->name, '`') > 0) { $sort_order = ' ORDER BY \'' . $fields_meta[$i]->name . '\' '; } else { $sort_order = ' ORDER BY ' . $sort_tbl . PMA_backquote($fields_meta[$i]->name) . ' '; } // 2.1.4 Do define the sorting url if (!$is_in_sort) { // loic1: patch #455484 ("Smart" order) $cfg['Order'] = strtoupper($GLOBALS['cfg']['Order']); if ($cfg['Order'] == 'SMART') { $cfg['Order'] = preg_match('@time|date@i', $fields_meta[$i]->type) ? 'DESC' : 'ASC'; } $sort_order .= $cfg['Order']; $order_img = ''; } else { if (preg_match('@[[:space:]]ASC$@i', $sql_order)) { $sort_order .= ' DESC'; $order_img = ' <img src="./images/asc_order.png" border="0" width="7" height="7" alt="' . $GLOBALS['strAscending'] . '" title="' . $GLOBALS['strAscending'] . '" />'; } else { if (preg_match('@[[:space:]]DESC$@i', $sql_order)) { $sort_order .= ' ASC'; $order_img = ' <img src="./images/desc_order.png" border="0" width="7" height="7" alt="' . $GLOBALS['strDescending'] . '" title="' . $GLOBALS['strDescending'] . '" />'; } } } if (preg_match('@(.*)([[:space:]](LIMIT (.*)|PROCEDURE (.*)|FOR UPDATE|LOCK IN SHARE MODE))@i', $unsorted_sql_query, $regs3)) { $sorted_sql_query = $regs3[1] . $sort_order . $regs3[2]; } else { $sorted_sql_query = $unsorted_sql_query . $sort_order; } $url_query = PMA_generate_common_url($db, $table) . '&pos=' . $pos . '&session_max_rows=' . $session_max_rows . '&disp_direction=' . $disp_direction . '&repeat_cells=' . $repeat_cells . '&dontlimitchars=' . $dontlimitchars . '&sql_query=' . urlencode($sorted_sql_query); // 2.1.5 Displays the sorting url if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo "\n"; ?> <th <?php echo $column_style; ?> <?php if ($disp_direction == 'horizontalflipped') { echo 'valign="bottom"'; } ?> > <?php echo $comments_table_wrap_pre; ?> <a href="sql.php?<?php echo $url_query; ?> " <?php echo (($disp_direction == 'horizontalflipped' and $GLOBALS['cfg']['HeaderFlipType'] == 'css') ? 'style="direction: ltr; writing-mode: tb-rl;"' : '') . ' title="' . $GLOBALS['strSort'] . '"'; ?> > <?php echo $disp_direction == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'fake' ? PMA_flipstring(htmlspecialchars($fields_meta[$i]->name), "<br />\n") : htmlspecialchars($fields_meta[$i]->name); ?> </a><?php echo $order_img . "\n"; ?> <?php echo $comments_table_wrap_post; ?> </th> <?php } $vertical_display['desc'][] = ' <th ' . $column_style . '>' . "\n" . $comments_table_wrap_pre . ' <a href="sql.php?' . $url_query . '">' . "\n" . ' ' . htmlspecialchars($fields_meta[$i]->name) . '</a>' . $order_img . "\n" . $comments_table_wrap_post . ' </th>' . "\n"; } else { if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo "\n"; ?> <th <?php echo $column_style; ?> <?php if ($disp_direction == 'horizontalflipped') { echo 'valign="bottom"'; } ?> <?php echo $disp_direction == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'css' ? 'style="direction: ltr; writing-mode: tb-rl;"' : ''; ?> > <?php echo $comments_table_wrap_pre; ?> <?php echo ($disp_direction == 'horizontalflipped' && $GLOBALS['cfg']['HeaderFlipType'] == 'fake' ? PMA_flipstring(htmlspecialchars($fields_meta[$i]->name), "<br />\n") : htmlspecialchars($fields_meta[$i]->name)) . "\n"; ?> <?php echo $comments_table_wrap_post; ?> </th> <?php } $vertical_display['desc'][] = ' <th ' . $column_style . '>' . "\n" . $comments_table_wrap_pre . ' ' . htmlspecialchars($fields_meta[$i]->name) . "\n" . $comments_table_wrap_post . ' </th>'; } // end else (2.2) } // end for // 3. Displays the full/partial text button (part 2) at the right // column of the result table header if possible and required... if ($GLOBALS['cfg']['ModifyDeleteAtRight'] && ($is_display['edit_lnk'] != 'nn' || $is_display['del_lnk'] != 'nn') && $is_display['text_btn'] == '1') { $vertical_display['emptyafter'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 1; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo "\n"; ?> <td<?php echo $colspan; ?> align="center"> <a href="<?php echo $text_url; ?> "> <img src="./images/<?php echo $dontlimitchars ? 'partialtext' : 'fulltext'; ?> .png" border="0" width="50" height="20" alt="<?php echo $dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']; ?> " title="<?php echo $dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']; ?> " /></a> </td> <?php } else { $vertical_display['textbtn'] = ' <td' . $rowspan . ' align="center" valign="middle">' . "\n" . ' <a href="' . $text_url . '">' . "\n" . ' <img src="./images/' . ($dontlimitchars ? 'partialtext' : 'fulltext') . '.png" border="0" width="50" height="20" alt="' . ($dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']) . '" title="' . ($dontlimitchars ? $GLOBALS['strPartialText'] : $GLOBALS['strFullText']) . '" /></a>' . "\n" . ' </td>' . "\n"; } // end vertical mode } else { if ($GLOBALS['cfg']['ModifyDeleteAtRight'] && ($is_display['edit_lnk'] == 'nn' && $is_display['del_lnk'] == 'nn') && !$GLOBALS['is_header_sent']) { $vertical_display['emptyafter'] = $is_display['edit_lnk'] != 'nn' && $is_display['del_lnk'] != 'nn' ? 3 : 1; if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo "\n"; ?> <td<?php echo $colspan; ?> ></td> <?php } else { $vertical_display['textbtn'] = ' <td' . $rowspan . '></td>' . "\n"; } // end vertical mode } } if ($disp_direction == 'horizontal' || $disp_direction == 'horizontalflipped') { echo "\n"; ?> </tr> <?php } echo "\n"; return TRUE; }
/** * test of changing string from horizontal to vertical orientation * @dataProvider flipStringDataProvider */ public function testFlipString($a, $e) { $this->assertEquals($e, PMA_flipstring($a)); }