diff --git a/adminer/call.inc.php b/adminer/call.inc.php index c409fd7e..b9ffbaa5 100644 --- a/adminer/call.inc.php +++ b/adminer/call.inc.php @@ -26,7 +26,7 @@ if (!$error && $_POST) { $val = "''"; } if (isset($out[$key])) { - $connection->query("SET @" . idf_escape($field["field"]) . " = $val"); + connection()->query("SET @" . idf_escape($field["field"]) . " = $val"); } } $call[] = (isset($out[$key]) ? "@" . idf_escape($field["field"]) : $val); @@ -34,8 +34,8 @@ if (!$error && $_POST) { $query = (isset($_GET["callf"]) ? "SELECT" : "CALL") . " " . table($PROCEDURE) . "(" . implode(", ", $call) . ")"; $start = microtime(true); - $result = $connection->multi_query($query); - $affected = $connection->affected_rows; // getting warnings overwrites this + $result = connection()->multi_query($query); + $affected = connection()->affected_rows; // getting warnings overwrites this echo adminer()->selectQuery($query, $start, !$result); if (!$result) { @@ -47,7 +47,7 @@ if (!$error && $_POST) { } do { - $result = $connection->store_result(); + $result = connection()->store_result(); if (is_object($result)) { print_select_result($result, $connection2); } else { @@ -55,10 +55,10 @@ if (!$error && $_POST) { . " " . @date("H:i:s") . "\n" // @ - time zone may be not set ; } - } while ($connection->next_result()); + } while (connection()->next_result()); if ($out) { - print_select_result($connection->query("SELECT " . implode(", ", $out))); + print_select_result(connection()->query("SELECT " . implode(", ", $out))); } } } diff --git a/adminer/drivers/mssql.inc.php b/adminer/drivers/mssql.inc.php index 90a4778d..db305a9c 100644 --- a/adminer/drivers/mssql.inc.php +++ b/adminer/drivers/mssql.inc.php @@ -170,8 +170,7 @@ if (isset($_GET["mssql"])) { } function last_id($result) { - global $connection; - return $connection->lastInsertId(); + return connection()->lastInsertId(); } function explain($connection, $query) { @@ -323,10 +322,9 @@ if (isset($_GET["mssql"])) { } function count_tables($databases) { - global $connection; $return = array(); foreach ($databases as $db) { - $connection->select_db($db); + connection()->select_db($db); $return[$db] = get_val("SELECT COUNT(*) FROM INFORMATION_SCHEMA.TABLES"); } return $return; @@ -428,8 +426,7 @@ WHERE OBJECT_NAME(i.object_id) = " . q($table), $connection2) as $row } function error() { - global $connection; - return nl_br(h(preg_replace('~^(\[[^]]*])+~m', '', $connection->error))); + return nl_br(h(preg_replace('~^(\[[^]]*])+~m', '', connection()->error))); } function create_database($db, $collation) { diff --git a/adminer/drivers/mysql.inc.php b/adminer/drivers/mysql.inc.php index 7c0a69c2..4540abbf 100644 --- a/adminer/drivers/mysql.inc.php +++ b/adminer/drivers/mysql.inc.php @@ -8,6 +8,7 @@ if (!defined('Adminer\DRIVER')) { // MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable if (extension_loaded("mysqli") && $_GET["ext"] != "pdo") { class Db extends \MySQLi { + /** @var Db|string */ static $instance = ''; public string $extension = "MySQLi", $flavor = ''; function __construct() { @@ -487,8 +488,7 @@ if (!defined('Adminer\DRIVER')) { * @return Field[] */ function fields(string $table): array { - global $connection; - $maria = ($connection->flavor == 'maria'); + $maria = (connection()->flavor == 'maria'); $return = array(); foreach (get_rows("SELECT * FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = " . q($table) . " ORDER BY ORDINAL_POSITION") as $row) { $field = $row["COLUMN_NAME"]; @@ -616,8 +616,7 @@ if (!defined('Adminer\DRIVER')) { /** Get escaped error message */ function error(): string { - global $connection; - return h(preg_replace('~^You have an error.*syntax to use~U', "Syntax error", $connection->error)); + return h(preg_replace('~^You have an error.*syntax to use~U', "Syntax error", connection()->error)); } /** Create database @@ -685,14 +684,13 @@ if (!defined('Adminer\DRIVER')) { * @return Result|bool */ function alter_table(string $table, string $name, array $fields, array $foreign, ?string $comment, string $engine, string $collation, string $auto_increment, string $partitioning) { - global $connection; $alter = array(); foreach ($fields as $field) { if ($field[1]) { $default = $field[1][3]; if (preg_match('~ GENERATED~', $default)) { // swap default and null - $field[1][3] = ($connection->flavor == 'maria' ? "" : $field[1][2]); // MariaDB doesn't support NULL on virtual columns + $field[1][3] = (connection()->flavor == 'maria' ? "" : $field[1][2]); // MariaDB doesn't support NULL on virtual columns $field[1][2] = $default; } $alter[] = ($table != "" ? ($field[0] != "" ? "CHANGE " . idf_escape($field[0]) : "ADD") : " ") . " " . implode($field[1]) . ($table != "" ? $field[2] : ""); @@ -762,7 +760,6 @@ if (!defined('Adminer\DRIVER')) { * @param list $views */ function move_tables(array $tables, array $views, string $target): bool { - global $connection; $rename = array(); foreach ($tables as $table) { $rename[] = table($table) . " TO " . idf_escape($target) . "." . table($table); @@ -772,7 +769,7 @@ if (!defined('Adminer\DRIVER')) { foreach ($views as $table) { $definitions[table($table)] = view($table); } - $connection->select_db($target); + connection()->select_db($target); $db = idf_escape(DB); foreach ($definitions as $name => $view) { if (!queries("CREATE VIEW $name AS " . str_replace(" $db.", " ", $view["select"])) || !queries("DROP VIEW $db.$name")) { diff --git a/adminer/drivers/oracle.inc.php b/adminer/drivers/oracle.inc.php index ccc413d9..78700d00 100644 --- a/adminer/drivers/oracle.inc.php +++ b/adminer/drivers/oracle.inc.php @@ -154,7 +154,6 @@ if (isset($_GET["oracle"])) { } function insertUpdate(string $table, array $rows, array $primary) { - global $connection; foreach ($rows as $set) { $update = array(); $where = array(); @@ -165,7 +164,7 @@ if (isset($_GET["oracle"])) { } } if ( - !(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $connection->affected_rows) + !(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && connection()->affected_rows) || queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")")) ) { return false; @@ -224,9 +223,8 @@ ORDER BY 1" } function get_current_db() { - global $connection; - $db = $connection->_current_db ?: DB; - unset($connection->_current_db); + $db = connection()->_current_db ?: DB; + unset(connection()->_current_db); return $db; } @@ -347,8 +345,7 @@ ORDER BY ac.constraint_type, aic.column_position", $connection2) as $row } function error() { - global $connection; - return h($connection->error); //! highlight sqltext from offset + return h(connection()->error); //! highlight sqltext from offset } function explain($connection, $query) { @@ -474,9 +471,8 @@ AND c_src.TABLE_NAME = " . q($table); } function set_schema($scheme, $connection2 = null) { - global $connection; if (!$connection2) { - $connection2 = $connection; + $connection2 = connection(); } return $connection2->query("ALTER SESSION SET CURRENT_SCHEMA = " . idf_escape($scheme)); } diff --git a/adminer/drivers/pgsql.inc.php b/adminer/drivers/pgsql.inc.php index 0795ecf7..21ec1b35 100644 --- a/adminer/drivers/pgsql.inc.php +++ b/adminer/drivers/pgsql.inc.php @@ -218,7 +218,6 @@ if (isset($_GET["pgsql"])) { } function insertUpdate(string $table, array $rows, array $primary) { - global $connection; foreach ($rows as $set) { $update = array(); $where = array(); @@ -229,7 +228,7 @@ if (isset($_GET["pgsql"])) { } } if ( - !(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && $connection->affected_rows) + !(($where && queries("UPDATE " . table($table) . " SET " . implode(", ", $update) . " WHERE " . implode(" AND ", $where)) && connection()->affected_rows) || queries("INSERT INTO " . table($table) . " (" . implode(", ", array_keys($set)) . ") VALUES (" . implode(", ", $set) . ")")) ) { return false; @@ -354,10 +353,9 @@ ORDER BY 1"; } function count_tables($databases) { - global $connection; $return = array(); foreach ($databases as $db) { - if ($connection->select_db($db)) { + if (connection()->select_db($db)) { $return[$db] = count(tables_list()); } } @@ -453,9 +451,8 @@ ORDER BY a.attnum") as $row } function indexes($table, $connection2 = null) { - global $connection; if (!is_object($connection2)) { - $connection2 = $connection; + $connection2 = connection(); } $return = array(); $table_oid = get_val("SELECT oid FROM pg_class WHERE relnamespace = (SELECT oid FROM pg_namespace WHERE nspname = current_schema()) AND relname = " . q($table), 0, $connection2); @@ -521,8 +518,7 @@ ORDER BY conkey, conname") as $row } function error() { - global $connection; - $return = h($connection->error); + $return = h(connection()->error); if (preg_match('~^(.*\n)?([^\n]*)\n( *)\^(\n.*)?$~s', $return, $match)) { $return = $match[1] . preg_replace('~((?:[^&]|&[^;]*;){' . strlen($match[3]) . '})(.*)~', '\1\2', $match[2]) . $match[4]; } @@ -534,14 +530,12 @@ ORDER BY conkey, conname") as $row } function drop_databases($databases) { - global $connection; - $connection->close(); + connection()->close(); return apply_queries("DROP DATABASE", $databases, 'Adminer\idf_escape'); } function rename_database($name, $collation) { - global $connection; - $connection->close(); + connection()->close(); return queries("ALTER DATABASE " . idf_escape(DB) . " RENAME TO " . idf_escape($name)); } @@ -792,9 +786,8 @@ AND typelem = 0" } function set_schema($schema, $connection2 = null) { - global $connection; if (!$connection2) { - $connection2 = $connection; + $connection2 = connection(); } $return = $connection2->query("SET search_path TO " . idf_escape($schema)); driver()->setUserTypes(types()); //! get types from current_schemas('t') @@ -929,9 +922,8 @@ AND typelem = 0" } function support($feature) { - global $connection; return preg_match('~^(check|database|table|columns|sql|indexes|descidx|comment|view|' . (min_version(9.3) ? 'materializedview|' : '') . 'scheme|' . (min_version(11) ? 'procedure|' : '') . 'routine|sequence|trigger|type|variables|drop_col' - . ($connection->flavor == 'cockroach' ? '' : '|processlist') // https://github.com/cockroachdb/cockroach/issues/24745 + . (connection()->flavor == 'cockroach' ? '' : '|processlist') // https://github.com/cockroachdb/cockroach/issues/24745 . '|kill|dump)$~', $feature) ; } diff --git a/adminer/drivers/sqlite.inc.php b/adminer/drivers/sqlite.inc.php index 27891dec..79e600d6 100644 --- a/adminer/drivers/sqlite.inc.php +++ b/adminer/drivers/sqlite.inc.php @@ -270,9 +270,8 @@ if (isset($_GET["sqlite"])) { } function indexes($table, $connection2 = null) { - global $connection; if (!is_object($connection2)) { - $connection2 = $connection; + $connection2 = connection(); } $return = array(); $sql = get_val("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = " . q($table), 0, $connection2); @@ -342,25 +341,22 @@ if (isset($_GET["sqlite"])) { } function error() { - global $connection; - return h($connection->error); + return h(connection()->error); } function check_sqlite_name($name) { // avoid creating PHP files on unsecured servers - global $connection; $extensions = "db|sdb|sqlite"; if (!preg_match("~^[^\\0]*\\.($extensions)\$~", $name)) { - $connection->error = lang('Please use one of the extensions %s.', str_replace("|", ", ", $extensions)); + connection()->error = lang('Please use one of the extensions %s.', str_replace("|", ", ", $extensions)); return false; } return true; } function create_database($db, $collation) { - global $connection; if (file_exists($db)) { - $connection->error = lang('File exists.'); + connection()->error = lang('File exists.'); return false; } if (!check_sqlite_name($db)) { @@ -370,7 +366,7 @@ if (isset($_GET["sqlite"])) { $link = new Db(); $link->attach($db, '', ''); } catch (\Exception $ex) { - $connection->error = $ex->getMessage(); + connection()->error = $ex->getMessage(); return false; } $link->query('PRAGMA encoding = "UTF-8"'); @@ -380,11 +376,10 @@ if (isset($_GET["sqlite"])) { } function drop_databases($databases) { - global $connection; - $connection->attach(":memory:", '', ''); // to unlock file, doesn't work in PDO on Windows + connection()->attach(":memory:", '', ''); // to unlock file, doesn't work in PDO on Windows foreach ($databases as $db) { if (!@unlink($db)) { - $connection->error = lang('File exists.'); + connection()->error = lang('File exists.'); return false; } } @@ -392,12 +387,11 @@ if (isset($_GET["sqlite"])) { } function rename_database($name, $collation) { - global $connection; if (!check_sqlite_name($name)) { return false; } - $connection->attach(":memory:", '', ''); - $connection->error = lang('File exists.'); + connection()->attach(":memory:", '', ''); + connection()->error = lang('File exists.'); return @rename(DB, $name); } @@ -406,7 +400,6 @@ if (isset($_GET["sqlite"])) { } function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) { - global $connection; $use_all_fields = ($table == "" || $foreign); foreach ($fields as $field) { if ($field[0] != "" || !$field[1] || $field[2]) { @@ -439,7 +432,7 @@ if (isset($_GET["sqlite"])) { if ($auto_increment) { queries("BEGIN"); queries("UPDATE sqlite_sequence SET seq = $auto_increment WHERE name = " . q($name)); // ignores error - if (!$connection->affected_rows) { + if (!connection()->affected_rows) { queries("INSERT INTO sqlite_sequence (name, seq) VALUES (" . q($name) . ", $auto_increment)"); } queries("COMMIT"); @@ -533,7 +526,7 @@ if (isset($_GET["sqlite"])) { } $temp_name = ($table == $name ? "adminer_$name" : $name); if (!queries("CREATE TABLE " . table($temp_name) . " (\n" . implode(",\n", $changes) . "\n)")) { - // implicit ROLLBACK to not overwrite $connection->error + // implicit ROLLBACK to not overwrite connection()->error return false; } if ($table != "") { diff --git a/adminer/dump.inc.php b/adminer/dump.inc.php index 09a8eea3..500d66ff 100644 --- a/adminer/dump.inc.php +++ b/adminer/dump.inc.php @@ -16,7 +16,7 @@ if ($_POST && !$error) { $is_sql = preg_match('~sql~', $_POST["format"]); if ($is_sql) { - echo "-- Adminer " . VERSION . " " . get_driver(DRIVER) . " " . str_replace("\n", " ", $connection->server_info) . " dump\n\n"; + echo "-- Adminer " . VERSION . " " . get_driver(DRIVER) . " " . str_replace("\n", " ", connection()->server_info) . " dump\n\n"; if (JUSH == "sql") { echo "SET NAMES utf8; SET time_zone = '+00:00'; @@ -24,8 +24,8 @@ SET foreign_key_checks = 0; " . ($_POST["data_style"] ? "SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; " : "") . " "; - $connection->query("SET time_zone = '+00:00'"); - $connection->query("SET sql_mode = ''"); + connection()->query("SET time_zone = '+00:00'"); + connection()->query("SET sql_mode = ''"); } } @@ -40,7 +40,7 @@ SET foreign_key_checks = 0; foreach ((array) $databases as $db) { adminer()->dumpDatabase($db); - if ($connection->select_db($db)) { + if (connection()->select_db($db)) { if ($is_sql && preg_match('~CREATE~', $style) && ($create = get_val("SHOW CREATE DATABASE " . idf_escape($db), 1))) { set_utf8mb4($create); if ($style == "DROP+CREATE") { diff --git a/adminer/foreign.inc.php b/adminer/foreign.inc.php index 792c12e6..6d4aecc9 100644 --- a/adminer/foreign.inc.php +++ b/adminer/foreign.inc.php @@ -58,7 +58,7 @@ if ($_POST) { select_db($row["db"]); + connection()->select_db($row["db"]); } if ($row["ns"] != "") { $orig_schema = get_schema(); diff --git a/adminer/include/adminer.inc.php b/adminer/include/adminer.inc.php index 0162a627..7878f5ef 100644 --- a/adminer/include/adminer.inc.php +++ b/adminer/include/adminer.inc.php @@ -521,7 +521,6 @@ class Adminer { * @return list expressions to join by AND */ function selectSearchProcess(array $fields, array $indexes): array { - global $connection; $return = array(); foreach ($indexes as $i => $index) { if ($index["type"] == "FULLTEXT" && $_GET["fulltext"][$i] != "") { @@ -793,7 +792,6 @@ class Adminer { * @return void prints data */ function dumpData(string $table, string $style, string $query): void { - global $connection; if ($style) { $max_packet = (JUSH == "sqlite" ? 0 : 1048576); // default, minimum is 1024 $fields = array(); @@ -813,7 +811,7 @@ class Adminer { } } } - $result = $connection->query($query, 1); // 1 - MYSQLI_USE_RESULT //! enum and set as numbers + $result = connection()->query($query, 1); // 1 - MYSQLI_USE_RESULT //! enum and set as numbers if ($result) { $insert = ""; $buffer = ""; @@ -872,7 +870,7 @@ class Adminer { echo $buffer . $suffix; } } elseif ($_POST["format"] == "sql") { - echo "-- " . str_replace("\n", " ", $connection->error) . "\n"; + echo "-- " . str_replace("\n", " ", connection()->error) . "\n"; } if ($identity_insert) { echo "SET IDENTITY_INSERT " . table($table) . " OFF;\n"; @@ -938,7 +936,6 @@ class Adminer { * @param string $missing can be "auth" if there is no database connection, "db" if there is no database selected, "ns" with invalid schema */ function navigation(string $missing): void { - global $connection; echo "

" . adminer()->name() . " " . VERSION; $new_version = $_COOKIE["adminer_version"]; echo " " . (version_compare(VERSION, $new_version) < 0 ? h($new_version) : "") . ""; @@ -966,7 +963,7 @@ class Adminer { } else { $tables = array(); if ($_GET["ns"] !== "" && !$missing && DB != "") { - $connection->select_db(DB); + connection()->select_db(DB); $tables = table_status('', true); } adminer()->syntaxHighlighting($tables); @@ -998,7 +995,6 @@ class Adminer { * @param TableStatus[] $tables */ function syntaxHighlighting(array $tables): void { - global $connection; // this is matched by compile.php echo script_src("../externals/jush/modules/jush.js"); echo script_src("../externals/jush/modules/jush-textarea.js"); @@ -1019,14 +1015,13 @@ class Adminer { } echo "\n"; } - echo script("syntaxHighlighting('" . (is_object($connection) ? preg_replace('~^(\d\.?\d).*~s', '\1', $connection->server_info) : "") . "'" - . ($connection->flavor == 'maria' ? ", 'maria'" : ($connection->flavor == 'cockroach' ? ", 'cockroach'" : "")) . ");" + echo script("syntaxHighlighting('" . (is_object(connection()) ? preg_replace('~^(\d\.?\d).*~s', '\1', connection()->server_info) : "") . "'" + . (connection()->flavor == 'maria' ? ", 'maria'" : (connection()->flavor == 'cockroach' ? ", 'cockroach'" : "")) . ");" ); } /** Print databases list in menu */ function databasesPrint(string $missing): void { - global $connection; $databases = adminer()->databases(); if (DB && $databases && !in_array(DB, $databases)) { array_unshift($databases, DB); @@ -1040,7 +1035,7 @@ class Adminer { ); echo "\n"; if (support("scheme")) { - if ($missing != "db" && DB != "" && $connection->select_db(DB)) { + if ($missing != "db" && DB != "" && connection()->select_db(DB)) { echo "
" . lang('Schema') . ": " . html_select("ns", array("" => "") + adminer()->schemas(), $_GET["ns"]) . $db_events; if ($_GET["ns"] != "") { set_schema($_GET["ns"]); diff --git a/adminer/include/auth.inc.php b/adminer/include/auth.inc.php index 5b1e510b..d9a75a15 100644 --- a/adminer/include/auth.inc.php +++ b/adminer/include/auth.inc.php @@ -1,8 +1,6 @@ credentials()); - if (is_object($connection)) { - Driver::$instance = new Driver($connection); - if ($connection->flavor) { + Db::$instance = connect(adminer()->credentials()); + if (is_object(Db::$instance)) { + Driver::$instance = new Driver(Db::$instance); + if (Db::$instance->flavor) { save_settings(array("vendor-" . DRIVER . "-" . SERVER => get_driver(DRIVER))); } } } $login = null; -if (!is_object($connection) || ($login = adminer()->login($_GET["username"], get_password())) !== true) { - $error = (is_string($connection) ? nl_br(h($connection)) : (is_string($login) ? $login : lang('Invalid credentials.'))); +if (!is_object(connection()) || ($login = adminer()->login($_GET["username"], get_password())) !== true) { + $error = (is_string(connection()) ? nl_br(h(connection())) : (is_string($login) ? $login : lang('Invalid credentials.'))); auth_error( $error . (preg_match('~^ | $~', get_password()) ? '
' . lang('There is a space in the input password which might be the cause.') : ''), $permanent diff --git a/adminer/include/bootstrap.inc.php b/adminer/include/bootstrap.inc.php index aae9e23c..71a70b4d 100644 --- a/adminer/include/bootstrap.inc.php +++ b/adminer/include/bootstrap.inc.php @@ -39,7 +39,7 @@ if ($_GET["script"] == "version") { exit; } -global $connection, $translations; // allows including Adminer inside a function +global $translations; // allows including Adminer inside a function if (!$_SERVER["REQUEST_URI"]) { // IIS 5 compatibility $_SERVER["REQUEST_URI"] = $_SERVER["ORIG_PATH_INFO"]; diff --git a/adminer/include/connect.inc.php b/adminer/include/connect.inc.php index 99221189..ef0173fc 100644 --- a/adminer/include/connect.inc.php +++ b/adminer/include/connect.inc.php @@ -10,7 +10,7 @@ if (isset($_GET["import"])) { if ( !(DB != "" - ? $connection->select_db(DB) + ? connection()->select_db(DB) : isset($_GET["sql"]) || isset($_GET["dump"]) || isset($_GET["database"]) || isset($_GET["processlist"]) || isset($_GET["privileges"]) || isset($_GET["user"]) || isset($_GET["variables"]) || $_GET["script"] == "connect" || $_GET["script"] == "kill" ) @@ -42,7 +42,7 @@ if ( echo "$val\n"; } } - echo "

" . lang('%s version: %s through PHP extension %s', get_driver(DRIVER), "" . h($connection->server_info) . "", "$connection->extension") . "\n"; + echo "

" . lang('%s version: %s through PHP extension %s', get_driver(DRIVER), "" . h(connection()->server_info) . "", "" . connection()->extension . "") . "\n"; echo "

" . lang('Logged as: %s', "" . h(logged_user()) . "") . "\n"; if (isset(adminer()->plugins) && is_array(adminer()->plugins)) { echo "

" . lang('Loaded plugins') . ":\n

    \n"; diff --git a/adminer/include/db.inc.php b/adminer/include/db.inc.php index 76832c0d..2477231f 100644 --- a/adminer/include/db.inc.php +++ b/adminer/include/db.inc.php @@ -4,6 +4,8 @@ namespace Adminer; // this could be interface when "Db extends \mysqli" can have compatible type declarations (PHP 7) // interfaces can include properties only since PHP 8.4 abstract class SqlDb { + /** @var Db|string */ static $instance = ''; // string means error + public string $extension; // extension name public string $flavor = ''; // different vendor with the same API, e.g. MariaDB; usually stays empty public string $server_info; // server version diff --git a/adminer/include/editing.inc.php b/adminer/include/editing.inc.php index 92be3b1e..eb70db95 100644 --- a/adminer/include/editing.inc.php +++ b/adminer/include/editing.inc.php @@ -206,9 +206,8 @@ function edit_type(string $key, array $field, array $collations, array $foreign_ * @return array{partition_by:string, partition:string, partitions:string, partition_names:list, partition_values:list} */ function get_partitions_info(string $table): array { - global $connection; $from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($table); - $result = $connection->query("SELECT PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_ORDINAL_POSITION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1"); + $result = connection()->query("SELECT PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_ORDINAL_POSITION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1"); $return = array(); list($return["partition_by"], $return["partition"], $return["partitions"]) = $result->fetch_row(); $partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION"); @@ -543,17 +542,16 @@ function ini_bytes(string $ini): int { * @return string HTML code */ function doc_link(array $paths, string $text = "?"): string { - global $connection; - $server_info = $connection->server_info; + $server_info = connection()->server_info; $version = preg_replace('~^(\d\.?\d).*~s', '\1', $server_info); // two most significant digits $urls = array( 'sql' => "https://dev.mysql.com/doc/refman/$version/en/", 'sqlite' => "https://www.sqlite.org/", - 'pgsql' => "https://www.postgresql.org/docs/" . ($connection->flavor == 'cockroach' ? "current" : $version) . "/", + 'pgsql' => "https://www.postgresql.org/docs/" . (connection()->flavor == 'cockroach' ? "current" : $version) . "/", 'mssql' => "https://learn.microsoft.com/en-us/sql/", 'oracle' => "https://www.oracle.com/pls/topic/lookup?ctx=db" . preg_replace('~^.* (\d+)\.(\d+)\.\d+\.\d+\.\d+.*~s', '\1\2', $server_info) . "&id=", ); - if ($connection->flavor == 'maria') { + if (connection()->flavor == 'maria') { $urls['sql'] = "https://mariadb.com/kb/en/"; $paths['sql'] = (isset($paths['mariadb']) ? $paths['mariadb'] : str_replace(".html", "/", $paths['sql'])); } @@ -564,8 +562,7 @@ function doc_link(array $paths, string $text = "?"): string { * @return string formatted */ function db_size(string $db): string { - global $connection; - if (!$connection->select_db($db)) { + if (!connection()->select_db($db)) { return "?"; } $return = 0; @@ -577,10 +574,9 @@ function db_size(string $db): string { /** Print SET NAMES if utf8mb4 might be needed */ function set_utf8mb4(string $create): void { - global $connection; static $set = false; if (!$set && preg_match('~\butf8mb4~i', $create)) { // possible false positive $set = true; - echo "SET NAMES " . charset($connection) . ";\n\n"; + echo "SET NAMES " . charset(connection()) . ";\n\n"; } } diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index 593bea19..7b8e38c3 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -3,11 +3,12 @@ namespace Adminer; // This file is used both in Adminer and Adminer Editor. -/** Get database connection */ -function connection(): Db { - // can be used in customization, $connection is minified - global $connection; - return $connection; +/** Get database connection +* @return Db|string string means error +*/ +function connection() { + // can be used in customization, Db::$instance is minified + return Db::$instance; } /** Get Adminer object @@ -33,10 +34,9 @@ function idf_unescape(string $idf): string { return str_replace($last . $last, $last, substr($idf, 1, -1)); } -/** Shortcut for $connection->quote($string) */ +/** Shortcut for connection()->quote($string) */ function q(string $string): string { - global $connection; - return $connection->quote($string); + return connection()->quote($string); } /** Escape string to use inside '' */ @@ -96,12 +96,11 @@ function bracket_escape(string $idf, bool $back = false): string { /** Check if connection has at least the given version * @param string|float $version required version * @param string|float $maria_db required MariaDB version -* @param Db $connection2 defaults to $connection +* @param Db $connection2 defaults to connection() */ function min_version($version, $maria_db = "", Db $connection2 = null): bool { - global $connection; if (!$connection2) { - $connection2 = $connection; + $connection2 = connection(); } $server_info = $connection2->server_info; if ($maria_db && preg_match('~([\d.]+)-MariaDB~', $server_info, $match)) { @@ -157,8 +156,7 @@ function get_password() { * @return string|false false if error */ function get_val(string $query, int $field = 0, ?Db $conn = null) { - global $connection; - $conn = (is_object($conn) ? $conn : $connection); + $conn = (is_object($conn) ? $conn : connection()); $result = $conn->query($query); if (!is_object($result)) { return false; @@ -172,9 +170,8 @@ function get_val(string $query, int $field = 0, ?Db $conn = null) { * @return list */ function get_vals(string $query, $column = 0): array { - global $connection; $return = array(); - $result = $connection->query($query); + $result = connection()->query($query); if (is_object($result)) { while ($row = $result->fetch_row()) { $return[] = $row[$column]; @@ -187,9 +184,8 @@ function get_vals(string $query, $column = 0): array { * @return string[] */ function get_key_vals(string $query, Db $connection2 = null, bool $set_keys = true): array { - global $connection; if (!is_object($connection2)) { - $connection2 = $connection; + $connection2 = connection(); } $return = array(); $result = $connection2->query($query); @@ -209,8 +205,7 @@ function get_key_vals(string $query, Db $connection2 = null, bool $set_keys = tr * @return list of associative arrays */ function get_rows(string $query, Db $connection2 = null, string $error = "

    "): array { - global $connection; - $conn = (is_object($connection2) ? $connection2 : $connection); + $conn = (is_object($connection2) ? $connection2 : connection()); $return = array(); $result = $conn->query($query); if (is_object($result)) { // can return true @@ -256,7 +251,6 @@ function escape_key(string $key): string { * @param Field[] $fields */ function where(array $where, array $fields = array()): string { - global $connection; $return = array(); foreach ((array) $where["where"] as $key => $val) { $key = bracket_escape($key, true); // true - back @@ -270,7 +264,7 @@ function where(array $where, array $fields = array()): string { : " = " . unconvert_field($field, q($val))))) ; //! enum and set if (JUSH == "sql" && preg_match('~char|text~', $field_type) && preg_match("~[^ -@]~", $val)) { // not just [a-z] to catch non-ASCII characters - $return[] = "$column = " . q($val) . " COLLATE " . charset($connection) . "_bin"; + $return[] = "$column = " . q($val) . " COLLATE " . charset(connection()) . "_bin"; } } foreach ((array) $where["null"] as $key) { @@ -430,10 +424,9 @@ function redirect(?string $location, string $message = null): void { * @param bool $redirect */ function query_redirect(string $query, ?string $location, string $message, $redirect = true, bool $execute = true, bool $failed = false, string $time = ""): bool { - global $connection; if ($execute) { $start = microtime(true); - $failed = !$connection->query($query); + $failed = !connection()->query($query); $time = format_time($start); } $sql = ($query ? adminer()->messageQuery($query, $time, $failed) : ""); @@ -457,12 +450,11 @@ class Queries { * @return Result|bool */ function queries(string $query) { - global $connection; if (!Queries::$start) { Queries::$start = microtime(true); } Queries::$queries[] = (preg_match('~;$~', $query) ? "DELIMITER ;;\n$query;\nDELIMITER " : $query) . ";"; - return $connection->query($query); + return connection()->query($query); } /** Apply command to all array items diff --git a/adminer/include/html.inc.php b/adminer/include/html.inc.php index 7f744151..04469ad7 100644 --- a/adminer/include/html.inc.php +++ b/adminer/include/html.inc.php @@ -331,13 +331,12 @@ function process_input(array $field) { * @uses $_POST["tables"] */ function search_tables(): void { - global $connection; $_GET["where"][0]["val"] = $_POST["query"]; $sep = "

      \n"; foreach (table_status('', true) as $table => $table_status) { $name = adminer()->tableName($table_status); if (isset($table_status["Engine"]) && $name != "" && (!$_POST["tables"] || in_array($table, $_POST["tables"]))) { - $result = $connection->query("SELECT" . limit("1 FROM " . table($table), " WHERE " . implode(" AND ", adminer()->selectSearchProcess(fields($table), array())), 1)); + $result = connection()->query("SELECT" . limit("1 FROM " . table($table), " WHERE " . implode(" AND ", adminer()->selectSearchProcess(fields($table), array())), 1)); if (!$result || $result->fetch_row()) { $print = "$name"; echo "$sep
    • " . ($result ? $print : "

      $print: " . error()) . "\n"; diff --git a/adminer/privileges.inc.php b/adminer/privileges.inc.php index 975548ad..3e6fc26d 100644 --- a/adminer/privileges.inc.php +++ b/adminer/privileges.inc.php @@ -5,11 +5,11 @@ page_header(lang('Privileges')); echo '

      \n"; diff --git a/adminer/script.inc.php b/adminer/script.inc.php index 35b981c6..5e1f0d7a 100644 --- a/adminer/script.inc.php +++ b/adminer/script.inc.php @@ -36,7 +36,7 @@ if ($_GET["script"] == "db") { json_row(""); } elseif ($_GET["script"] == "kill") { - $connection->query("KILL " . number($_POST["kill"])); + connection()->query("KILL " . number($_POST["kill"])); } else { // connect foreach (count_tables(adminer()->databases()) as $db => $val) { diff --git a/adminer/select.inc.php b/adminer/select.inc.php index 04ac30f2..b920cd7f 100644 --- a/adminer/select.inc.php +++ b/adminer/select.inc.php @@ -127,7 +127,7 @@ if ($_POST && !$error) { : driver()->update($TABLE, $set, $where_check) ) ); - $affected = $connection->affected_rows; + $affected = connection()->affected_rows; if (is_object($result)) { // PostgreSQL with RETURNING fills num_rows $affected += $result->num_rows; } @@ -145,7 +145,7 @@ if ($_POST && !$error) { if (!$result) { break; } - $affected += $connection->affected_rows; + $affected += connection()->affected_rows; } } } @@ -186,7 +186,7 @@ if ($_POST && !$error) { if (!$result) { break; } - $affected += $connection->affected_rows; + $affected += connection()->affected_rows; } queries_redirect(remove_from_uri(), lang('%d item(s) have been affected.', $affected), $result); } diff --git a/adminer/sql.inc.php b/adminer/sql.inc.php index e0a84dd6..4860c5fb 100644 --- a/adminer/sql.inc.php +++ b/adminer/sql.inc.php @@ -126,16 +126,16 @@ if (!$error && $_POST) { } $start = microtime(true); //! don't allow changing of character_set_results, convert encoding of displayed query - if ($connection->multi_query($q) && is_object($connection2) && preg_match("~^$space*+USE\\b~i", $q)) { + if (connection()->multi_query($q) && is_object($connection2) && preg_match("~^$space*+USE\\b~i", $q)) { $connection2->query($q); } do { - $result = $connection->store_result(); + $result = connection()->store_result(); - if ($connection->error) { + if (connection()->error) { echo ($_POST["only_errors"] ? $print : ""); - echo "

      " . lang('Error in query') . ($connection->errno ? " ($connection->errno)" : "") . ": " . error() . "\n"; + echo "

      " . lang('Error in query') . (connection()->errno ? " (" . connection()->errno . ")" : "") . ": " . error() . "\n"; $errors[] = " $commands"; if ($_POST["error_stops"]) { break 2; @@ -145,7 +145,7 @@ if (!$error && $_POST) { $time = " (" . format_time($start) . ")" . (strlen($q) < 1000 ? " " . lang('Edit') . "" : "") // 1000 - maximum length of encoded URL in IE is 2083 characters ; - $affected = $connection->affected_rows; // getting warnings overwrites this + $affected = connection()->affected_rows; // getting warnings overwrites this $warnings = ($_POST["only_errors"] ? "" : driver()->warnings()); $warnings_id = "warnings-$commands"; if ($warnings) { @@ -182,7 +182,7 @@ if (!$error && $_POST) { stop_session(); } if (!$_POST["only_errors"]) { - echo "

      " . lang('Query executed OK, %d row(s) affected.', $affected) . "$time\n"; + echo "

      " . lang('Query executed OK, %d row(s) affected.', $affected) . "$time\n"; } } echo ($warnings ? "

      \n" : ""); @@ -194,7 +194,7 @@ if (!$error && $_POST) { } $start = microtime(true); - } while ($connection->next_result()); + } while (connection()->next_result()); } $query = substr($query, $offset); diff --git a/adminer/user.inc.php b/adminer/user.inc.php index a74b2431..9f9c5e39 100644 --- a/adminer/user.inc.php +++ b/adminer/user.inc.php @@ -29,7 +29,7 @@ if ($_POST) { $grants = array(); $old_pass = ""; -if (isset($_GET["host"]) && ($result = $connection->query("SHOW GRANTS FOR " . q($USER) . "@" . q($_GET["host"])))) { //! use information_schema for MySQL 5 - column names in column privileges are not escaped +if (isset($_GET["host"]) && ($result = connection()->query("SHOW GRANTS FOR " . q($USER) . "@" . q($_GET["host"])))) { //! use information_schema for MySQL 5 - column names in column privileges are not escaped while ($row = $result->fetch_row()) { if (preg_match('~GRANT (.*) ON (.*) TO ~', $row[0], $match) && preg_match_all('~ *([^(,]*[^ ,(])( *\([^)]+\))?~', $match[1], $matches, PREG_SET_ORDER)) { //! escape the part between ON and TO foreach ($matches as $val) { @@ -113,7 +113,7 @@ if ($_POST && !$error) { if ($created) { // delete new user in case of an error - $connection->query("DROP USER $new_user"); + connection()->query("DROP USER $new_user"); } } } diff --git a/compile.php b/compile.php index cfa606f8..e248013e 100755 --- a/compile.php +++ b/compile.php @@ -278,7 +278,7 @@ if ($_SERVER["argv"][1]) { include __DIR__ . "/adminer/include/db.inc.php"; include __DIR__ . "/adminer/include/pdo.inc.php"; include __DIR__ . "/adminer/include/driver.inc.php"; -$connection = (object) array('flavor' => '', 'server_info' => '99'); // used in support() +Adminer\SqlDb::$instance = (object) array('flavor' => '', 'server_info' => '99'); // used in support() $features = array("check", "call" => "routine", "dump", "event", "privileges", "procedure" => "routine", "processlist", "routine", "scheme", "sequence", "sql", "status", "trigger", "type", "user" => "privileges", "variables", "view"); $lang_ids = array(); // global variable simplifies usage in a callback function $file = file_get_contents(__DIR__ . "/$project/index.php"); diff --git a/editor/include/adminer.inc.php b/editor/include/adminer.inc.php index ac3ef4fb..0373809b 100644 --- a/editor/include/adminer.inc.php +++ b/editor/include/adminer.inc.php @@ -31,8 +31,7 @@ class Adminer { } function database() { - global $connection; - if ($connection) { + if (connection()) { $databases = adminer()->databases(false); return (!$databases ? get_val("SELECT SUBSTRING_INDEX(CURRENT_USER, '@', 1)") // username without the database list @@ -558,8 +557,7 @@ ORDER BY ORDINAL_POSITION", null, "") as $row } function dumpData($table, $style, $query) { - global $connection; - $result = $connection->query($query, 1); // 1 - MYSQLI_USE_RESULT + $result = connection()->query($query, 1); // 1 - MYSQLI_USE_RESULT if ($result) { while ($row = $result->fetch_assoc()) { if ($style == "table") { diff --git a/editor/include/connect.inc.php b/editor/include/connect.inc.php index d9752a07..fe584c18 100644 --- a/editor/include/connect.inc.php +++ b/editor/include/connect.inc.php @@ -1,4 +1,4 @@ select_db(adminer()->database()); +connection()->select_db(adminer()->database()); diff --git a/editor/script.inc.php b/editor/script.inc.php index 77acd532..a24553ed 100644 --- a/editor/script.inc.php +++ b/editor/script.inc.php @@ -2,11 +2,11 @@ namespace Adminer; if ($_GET["script"] == "kill") { - $connection->query("KILL " . number($_POST["kill"])); + connection()->query("KILL " . number($_POST["kill"])); } elseif (list($table, $id, $name) = adminer()->_foreignColumn(column_foreign_keys($_GET["source"]), $_GET["field"])) { // complete $limit = 11; - $result = $connection->query("SELECT $id, $name FROM " . table($table) . " WHERE " . (preg_match('~^[0-9]+$~', $_GET["value"]) ? "$id = $_GET[value] OR " : "") . "$name LIKE " . q("$_GET[value]%") . " ORDER BY 2 LIMIT $limit"); + $result = connection()->query("SELECT $id, $name FROM " . table($table) . " WHERE " . (preg_match('~^[0-9]+$~', $_GET["value"]) ? "$id = $_GET[value] OR " : "") . "$name LIKE " . q("$_GET[value]%") . " ORDER BY 2 LIMIT $limit"); for ($i=1; ($row = $result->fetch_row()) && $i < $limit; $i++) { echo "" . h($row[1]) . "
      \n"; } diff --git a/plugins/codemirror.php b/plugins/codemirror.php index db62affe..dfb2455c 100644 --- a/plugins/codemirror.php +++ b/plugins/codemirror.php @@ -15,7 +15,6 @@ class AdminerCodemirror { } function syntaxHighlighting($tableStatuses) { - $connection = Adminer\connection(); ?>