diff --git a/adminer/call.inc.php b/adminer/call.inc.php index cc4666a7..509f9f97 100644 --- a/adminer/call.inc.php +++ b/adminer/call.inc.php @@ -57,7 +57,7 @@ if ($in) { if (strlen($value) && ($field["type"] == "enum" || $field["type"] == "set")) { $value = intval($value); } - input($key, $field, $value, (string) $_POST["function"][$name]); // param name can be empty + input($field, $value, (string) $_POST["function"][$name]); // param name can be empty echo "\n"; } echo "\n"; diff --git a/adminer/edit.inc.php b/adminer/edit.inc.php index 802f8f48..157d5c5c 100644 --- a/adminer/edit.inc.php +++ b/adminer/edit.inc.php @@ -79,7 +79,7 @@ if ($fields) { : ($_POST["clone"] && $field["auto_increment"] ? "" : (isset($_GET["select"]) ? false : $field["default"])) ); $function = ($_POST["save"] ? (string) $_POST["function"][$name] : ($where && $field["on_update"] == "CURRENT_TIMESTAMP" ? "now" : ($value === false ? null : (isset($value) ? '' : 'NULL')))); - input($name, $field, $value, $function); + input($field, $value, $function); if (isset($_GET["default"]) && $field["type"] == "timestamp") { if (!isset($create) && !$_POST) { //! disable sql_mode NO_FIELD_OPTIONS diff --git a/adminer/include/adminer.inc.php b/adminer/include/adminer.inc.php index 25965c53..d5814d44 100644 --- a/adminer/include/adminer.inc.php +++ b/adminer/include/adminer.inc.php @@ -90,9 +90,17 @@ function adminer_select_query($query) { return call_adminer('select_query', "

" . htmlspecialchars($query) . " " . lang('Edit') . "\n", $query); } -/** Descriptions of selected data +/** Description of a row in a table +* @param string +* @return string SQL expression, empty string for no description +*/ +function adminer_row_description($table) { + return call_adminer('row_description', "", $table); +} + +/** Get descriptions of selected data * @param array all data to print -* @param array foreign keys +* @param array * @return array */ function adminer_row_descriptions($rows, $foreign_keys) { @@ -147,7 +155,16 @@ function adminer_edit_functions($field) { if ($field["null"] || isset($_GET["default"])) { array_unshift($return, "NULL"); } - return call_adminer('edit_functions', $return, $field); + return call_adminer('edit_functions', (isset($_GET["select"]) ? array("orig" => lang('original')) : array()) + $return, $field); +} + +/** Get options to display edit field +* @param string table name +* @param array single field from fields() +* @return array options for +*/ +function adminer_edit_input($table, $field) { + return call_adminer('edit_input', false, $table, $field); } /** Prints navigation after Adminer title diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index ec2b46e2..72b1d661 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -13,14 +13,14 @@ function bracket_escape($idf, $back = false) { return strtr($idf, ($back ? array_flip($trans) : $trans)); } -function optionlist($options, $selected = null) { +function optionlist($options, $selected = null, $use_keys = false) { $return = ""; foreach ($options as $k => $v) { if (is_array($v)) { $return .= ''; } foreach ((is_array($v) ? $v : array($k => $v)) as $key => $val) { - $return .= '' . htmlspecialchars($val); + $return .= '' . htmlspecialchars($val); } if (is_array($v)) { $return .= ''; @@ -265,9 +265,19 @@ function hidden_fields($process, $ignore = array()) { } } -function input($name, $field, $value, $function) { +function column_foreign_keys($table) { + $return = array(); + foreach (foreign_keys($table) as $foreign_key) { + foreach ($foreign_key["source"] as $val) { + $return[$val][] = $foreign_key; + } + } + return $return; +} + +function input($field, $value, $function) { global $types; - $name = htmlspecialchars(bracket_escape($name)); + $name = htmlspecialchars(bracket_escape($field["field"])); echo ""; if ($field["type"] == "enum") { echo " " . (isset($_GET["select"]) ? ' ' : ""); @@ -284,11 +294,14 @@ function input($name, $field, $value, $function) { echo ' '; } } else { - $first = ($field["null"] || isset($_GET["default"])) + isset($_GET["select"]); + $functions = adminer_edit_functions($field); + $first = array_search("", $functions); $onchange = ($first ? ' onchange="var f = this.form[\'function[' . addcslashes($name, "\r\n'\\") . ']\']; if (' . $first . ' > f.selectedIndex) f.selectedIndex = ' . $first . ';"' : ''); - $options = adminer_edit_functions($field); - echo (count($options) > 1 || isset($_GET["select"]) ? '' : " ") . ''; - if ($field["type"] == "set") { //! 64 bits + echo (count($functions) > 1 ? '' : " ") . ''; + $options = adminer_edit_input($_GET["edit"], $field); // usage in call is without a table + if (is_array($options)) { + echo ''; + } elseif ($field["type"] == "set") { //! 64 bits preg_match_all("~'((?:[^']+|'')*)'~", $field["length"], $matches); foreach ($matches[1] as $i => $val) { $val = stripcslashes(str_replace("''", "'", $val)); @@ -302,7 +315,7 @@ function input($name, $field, $value, $function) { } else { // int(3) is only a display hint $maxlength = (!ereg('int', $field["type"]) && preg_match('~^([0-9]+)(,([0-9]+))?$~', $field["length"], $match) ? ($match[1] + ($match[3] ? 1 : 0) + ($match[2] && !$field["unsigned"] ? 1 : 0)) : ($types[$field["type"]] ? $types[$field["type"]] + ($field["unsigned"] ? 0 : 1) : 0)); - echo ''; + echo '"; } } } diff --git a/adminer/select.inc.php b/adminer/select.inc.php index 2f2987f0..745f7009 100644 --- a/adminer/select.inc.php +++ b/adminer/select.inc.php @@ -20,7 +20,7 @@ unset($text_length); foreach ($fields as $key => $field) { $name = adminer_field_name($fields, $key); if (isset($field["privileges"]["select"]) && strlen($name)) { - $columns[$key] = html_entity_decode(strip_tags($name)); //! numeric $key is problematic in optionlist() + $columns[$key] = html_entity_decode(strip_tags($name)); if (ereg('text|blob', $field["type"])) { $text_length = (isset($_GET["text_length"]) ? $_GET["text_length"] : "100"); } @@ -196,11 +196,11 @@ if (!$columns) { foreach ($select as $key => $val) { $val = $_GET["columns"][$key]; echo "

"; - echo "
\n"; + echo "\n"; $i++; } echo "
"; - echo "
\n"; + echo "\n"; echo "\n"; echo '
' . lang('Search') . "
\n"; @@ -230,12 +230,12 @@ if (!$columns) { $i = 0; foreach ((array) $_GET["order"] as $key => $val) { if (isset($columns[$val])) { - echo "
"; + echo "
"; echo "
\n"; $i++; } } - echo "
"; + echo "
"; echo "
\n"; echo "
\n"; @@ -277,12 +277,7 @@ if (!$columns) { : count($rows) ); - $foreign_keys = array(); - foreach (foreign_keys($_GET["select"]) as $foreign_key) { - foreach ($foreign_key["source"] as $val) { - $foreign_keys[$val][] = $foreign_key; - } - } + $foreign_keys = column_foreign_keys($_GET["select"]); $descriptions = adminer_row_descriptions($rows, $foreign_keys); $backward_keys = adminer_backward_keys($_GET["select"]); diff --git a/changes.txt b/changes.txt index 13420ba6..cb735980 100644 --- a/changes.txt +++ b/changes.txt @@ -2,7 +2,7 @@ Adminer 2.0.0: Editor: User friendly data editor Customization: Adminer class E-mail sending -Table relations +Table relations (Editor) Create single column foreign key in table structure Separate types to groups in table creation Show type in field name title (thanks to Jakub Sochor) diff --git a/editor/include/adminer.inc.php b/editor/include/adminer.inc.php index 88d61132..3e33d18c 100644 --- a/editor/include/adminer.inc.php +++ b/editor/include/adminer.inc.php @@ -62,6 +62,18 @@ function adminer_select_query($query) { return call_adminer('select_query', "\n", $query); } +function adminer_row_description($table) { + $return = ""; + // first varchar column + foreach (fields($table) as $field) { + if ($field["type"] == "varchar") { + $return = idf_escape($field["field"]); + break; + } + } + return call_adminer('row_description', $return, $table); +} + function adminer_row_descriptions($rows, $foreign_keys) { global $dbh; $return = $rows; @@ -69,31 +81,26 @@ function adminer_row_descriptions($rows, $foreign_keys) { foreach ((array) $foreign_keys[$key] as $foreign_key) { if (count($foreign_key["source"]) == 1) { $id = idf_escape($foreign_key["target"][0]); - // find out the description column - first varchar - $name = $id; - foreach (fields($foreign_key["table"]) as $field) { - if ($field["type"] == "varchar") { - $name = idf_escape($field["field"]); - break; + $name = adminer_row_description($foreign_key["table"]); + if (strlen($name)) { + // find all used ids + $ids = array(); + foreach ($rows as $row) { + $ids[$row[$key]] = $dbh->quote($row[$key]); } + // uses constant number of queries to get the descriptions, join would be complex, multiple queries would be slow + $descriptions = array(); + $result = $dbh->query("SELECT $id, $name FROM " . idf_escape($foreign_key["table"]) . " WHERE $id IN (" . implode(", ", $ids) . ")"); + while ($row = $result->fetch_row()) { + $descriptions[$row[0]] = $row[1]; + } + $result->free(); + // use the descriptions + foreach ($rows as $n => $row) { + $return[$n][$key] = $descriptions[$row[$key]]; + } + break; } - // find all used ids - $ids = array(); - foreach ($rows as $row) { - $ids[$row[$key]] = $dbh->quote($row[$key]); - } - // uses constant number of queries to get the descriptions, join would be complex, multiple queries would be slow - $descriptions = array(); - $result = $dbh->query("SELECT $id, $name FROM " . idf_escape($foreign_key["table"]) . " WHERE $id IN (" . implode(", ", $ids) . ")"); - while ($row = $result->fetch_row()) { - $descriptions[$row[0]] = $row[1]; - } - $result->free(); - // use the descriptions - foreach ($rows as $n => $row) { - $return[$n][$key] = $descriptions[$row[$key]]; - } - break; } } } @@ -108,11 +115,35 @@ function adminer_select_val($val, $link) { } function adminer_message_query($query) { - return call_adminer('message_query', "", $query); + return call_adminer('message_query', "", $query); } function adminer_edit_functions($field) { - return call_adminer('edit_functions', array(""), $field); + return call_adminer('edit_functions', (isset($_GET["select"]) ? array("orig" => lang('original')) : array()) + array(""), $field); +} + +function adminer_edit_input($table, $field) { + global $dbh; + $return = null; + $foreign_keys = column_foreign_keys($table); + foreach ((array) $foreign_keys[$field["field"]] as $foreign_key) { + if (count($foreign_key["source"]) == 1) { + $id = idf_escape($foreign_key["target"][0]); + $name = adminer_row_description($foreign_key["table"]); + if (strlen($name) && $dbh->result($dbh->query("SELECT COUNT(*) FROM " . idf_escape($foreign_key["table"]))) <= 1000) { // optionlist with more than 1000 options would be too big + if ($field["null"]) { + $return[""] = ""; + } + $result = $dbh->query("SELECT $id, $name FROM " . idf_escape($foreign_key["table"]) . " ORDER BY 2"); + while ($row = $result->fetch_row()) { + $return[$row[0]] = $row[1]; + } + $result->free(); + break; + } + } + } + return call_adminer('edit_input', $return, $table, $field); } function adminer_navigation($missing) {