1
0
mirror of https://github.com/vrana/adminer.git synced 2025-08-06 14:46:36 +02:00

Doc-comments: Move return types to declaration

This commit is contained in:
Jakub Vrana
2025-03-28 09:03:09 +01:00
parent 641ee4ff26
commit 45c045382a
21 changed files with 277 additions and 456 deletions

View File

@@ -94,7 +94,7 @@ if ($in) {
/** Format string as table row /** Format string as table row
* @return string HTML * @return string HTML
*/ */
function pre_tr(string $s) { function pre_tr(string $s): string {
return preg_replace('~^~m', '<tr>', preg_replace('~\|~', '<td>', preg_replace('~\|$~m', "", rtrim($s)))); return preg_replace('~^~m', '<tr>', preg_replace('~\|~', '<td>', preg_replace('~\|$~m', "", rtrim($s))));
} }

View File

@@ -84,9 +84,8 @@ if (!defined('Adminer\DRIVER')) {
} }
/** Set the client character set /** Set the client character set
* @return bool
*/ */
function set_charset(string $charset) { function set_charset(string $charset): bool {
if (function_exists('mysql_set_charset')) { if (function_exists('mysql_set_charset')) {
if (mysql_set_charset($charset, $this->link)) { if (mysql_set_charset($charset, $this->link)) {
return true; return true;
@@ -137,21 +136,21 @@ if (!defined('Adminer\DRIVER')) {
/** Fetch next row as associative array /** Fetch next row as associative array
* @return array<?string> * @return array<?string>
*/ */
function fetch_assoc() { function fetch_assoc(): array {
return mysql_fetch_assoc($this->result); return mysql_fetch_assoc($this->result);
} }
/** Fetch next row as numbered array /** Fetch next row as numbered array
* @return list<?string> * @return list<?string>
*/ */
function fetch_row() { function fetch_row(): array {
return mysql_fetch_row($this->result); return mysql_fetch_row($this->result);
} }
/** Fetch next field /** Fetch next field
* @return object properties: name, type (0 number, 15 varchar, 254 char), charsetnr (63 binary); optionally: table, orgtable, orgname * @return object properties: name, type (0 number, 15 varchar, 254 char), charsetnr (63 binary); optionally: table, orgtable, orgname
*/ */
function fetch_field() { function fetch_field(): object {
$return = mysql_fetch_field($this->result, $this->offset++); // offset required under certain conditions $return = mysql_fetch_field($this->result, $this->offset++); // offset required under certain conditions
$return->orgtable = $return->table; $return->orgtable = $return->table;
$return->charsetnr = ($return->blob ? 63 : 0); $return->charsetnr = ($return->blob ? 63 : 0);
@@ -357,16 +356,14 @@ if (!defined('Adminer\DRIVER')) {
/** Escape database identifier /** Escape database identifier
* @return string
*/ */
function idf_escape(string $idf) { function idf_escape(string $idf): string {
return "`" . str_replace("`", "``", $idf) . "`"; return "`" . str_replace("`", "``", $idf) . "`";
} }
/** Get escaped table name /** Get escaped table name
* @return string
*/ */
function table(string $idf) { function table(string $idf): string {
return idf_escape($idf); return idf_escape($idf);
} }
@@ -394,7 +391,7 @@ if (!defined('Adminer\DRIVER')) {
/** Get cached list of databases /** Get cached list of databases
* @return list<string> * @return list<string>
*/ */
function get_databases(bool $flush) { function get_databases(bool $flush): array {
// SHOW DATABASES can take a very long time so it is cached // SHOW DATABASES can take a very long time so it is cached
$return = get_session("dbs"); $return = get_session("dbs");
if ($return === null) { if ($return === null) {
@@ -410,25 +407,22 @@ if (!defined('Adminer\DRIVER')) {
/** Formulate SQL query with limit /** Formulate SQL query with limit
* @param string $query everything after SELECT * @param string $query everything after SELECT
* @param string $where including WHERE * @param string $where including WHERE
* @return string
*/ */
function limit(string $query, string $where, int $limit, int $offset = 0, string $separator = " ") { function limit(string $query, string $where, int $limit, int $offset = 0, string $separator = " "): string {
return " $query$where" . ($limit !== null ? $separator . "LIMIT $limit" . ($offset ? " OFFSET $offset" : "") : ""); return " $query$where" . ($limit !== null ? $separator . "LIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
} }
/** Formulate SQL modification query with limit 1 /** Formulate SQL modification query with limit 1
* @param string $query everything after UPDATE or DELETE * @param string $query everything after UPDATE or DELETE
* @return string
*/ */
function limit1(string $table, string $query, string $where, string $separator = "\n") { function limit1(string $table, string $query, string $where, string $separator = "\n"): string {
return limit($query, $where, 1, 0, $separator); return limit($query, $where, 1, 0, $separator);
} }
/** Get database collation /** Get database collation
* @param string[][] $collations result of collations() * @param string[][] $collations result of collations()
* @return string
*/ */
function db_collation(string $db, array $collations) { function db_collation(string $db, array $collations): string {
$return = null; $return = null;
$create = get_val("SHOW CREATE DATABASE " . idf_escape($db), 1); $create = get_val("SHOW CREATE DATABASE " . idf_escape($db), 1);
if (preg_match('~ COLLATE ([^ ]+)~', $create, $match)) { if (preg_match('~ COLLATE ([^ ]+)~', $create, $match)) {
@@ -441,16 +435,15 @@ if (!defined('Adminer\DRIVER')) {
} }
/** Get logged user /** Get logged user
* @return string
*/ */
function logged_user() { function logged_user(): string {
return get_val("SELECT USER()"); return get_val("SELECT USER()");
} }
/** Get tables list /** Get tables list
* @return string[] [$name => $type] * @return string[] [$name => $type]
*/ */
function tables_list() { function tables_list(): array {
return get_key_vals("SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME"); return get_key_vals("SELECT TABLE_NAME, TABLE_TYPE FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE() ORDER BY TABLE_NAME");
} }
@@ -458,7 +451,7 @@ if (!defined('Adminer\DRIVER')) {
* @param list<string> $databases * @param list<string> $databases
* @return int[] [$db => $tables] * @return int[] [$db => $tables]
*/ */
function count_tables(array $databases) { function count_tables(array $databases): array {
$return = array(); $return = array();
foreach ($databases as $db) { foreach ($databases as $db) {
$return[$db] = count(get_vals("SHOW TABLES IN " . idf_escape($db))); $return[$db] = count(get_vals("SHOW TABLES IN " . idf_escape($db)));
@@ -470,7 +463,7 @@ if (!defined('Adminer\DRIVER')) {
* @param bool $fast return only "Name", "Engine" and "Comment" fields * @param bool $fast return only "Name", "Engine" and "Comment" fields
* @return TableStatus[] * @return TableStatus[]
*/ */
function table_status(string $name = "", bool $fast = false) { function table_status(string $name = "", bool $fast = false): array {
$return = array(); $return = array();
foreach ( foreach (
get_rows( get_rows(
@@ -497,24 +490,22 @@ if (!defined('Adminer\DRIVER')) {
/** Find out whether the identifier is view /** Find out whether the identifier is view
* @param TableStatus $table_status * @param TableStatus $table_status
* @return bool
*/ */
function is_view(array $table_status) { function is_view(array $table_status): bool {
return $table_status["Engine"] === null; return $table_status["Engine"] === null;
} }
/** Check if table supports foreign keys /** Check if table supports foreign keys
* @param TableStatus $table_status result of table_status1() * @param TableStatus $table_status result of table_status1()
* @return bool
*/ */
function fk_support(array $table_status) { function fk_support(array $table_status): bool {
return preg_match('~InnoDB|IBMDB2I' . (min_version(5.6) ? '|NDB' : '') . '~i', $table_status["Engine"]); return preg_match('~InnoDB|IBMDB2I' . (min_version(5.6) ? '|NDB' : '') . '~i', $table_status["Engine"]);
} }
/** Get information about fields /** Get information about fields
* @return Field[] * @return Field[]
*/ */
function fields(string $table) { function fields(string $table): array {
global $connection; global $connection;
$maria = ($connection->flavor == 'maria'); $maria = ($connection->flavor == 'maria');
$return = array(); $return = array();
@@ -568,7 +559,7 @@ if (!defined('Adminer\DRIVER')) {
/** Get table indexes /** Get table indexes
* @return Index[] * @return Index[]
*/ */
function indexes(string $table, ?Db $connection2 = null) { function indexes(string $table, ?Db $connection2 = null): array {
$return = array(); $return = array();
foreach (get_rows("SHOW INDEX FROM " . table($table), $connection2) as $row) { foreach (get_rows("SHOW INDEX FROM " . table($table), $connection2) as $row) {
$name = $row["Key_name"]; $name = $row["Key_name"];
@@ -583,7 +574,7 @@ if (!defined('Adminer\DRIVER')) {
/** Get foreign keys in table /** Get foreign keys in table
* @return ForeignKey[] * @return ForeignKey[]
*/ */
function foreign_keys(string $table) { function foreign_keys(string $table): array {
global $driver; global $driver;
static $pattern = '(?:`(?:[^`]|``)+`|"(?:[^"]|"")+")'; static $pattern = '(?:`(?:[^`]|``)+`|"(?:[^"]|"")+")';
$return = array(); $return = array();
@@ -614,14 +605,14 @@ if (!defined('Adminer\DRIVER')) {
/** Get view SELECT /** Get view SELECT
* @return array{select:string} * @return array{select:string}
*/ */
function view(string $name) { function view(string $name): array {
return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)*\s+AS\s+~isU', '', get_val("SHOW CREATE VIEW " . table($name), 1))); return array("select" => preg_replace('~^(?:[^`]|`[^`]*`)*\s+AS\s+~isU', '', get_val("SHOW CREATE VIEW " . table($name), 1)));
} }
/** Get sorted grouped list of collations /** Get sorted grouped list of collations
* @return string[][] * @return string[][]
*/ */
function collations() { function collations(): array {
$return = array(); $return = array();
foreach (get_rows("SHOW COLLATION") as $row) { foreach (get_rows("SHOW COLLATION") as $row) {
if ($row["Default"]) { if ($row["Default"]) {
@@ -638,17 +629,15 @@ if (!defined('Adminer\DRIVER')) {
} }
/** Find out if database is information_schema /** Find out if database is information_schema
* @return bool
*/ */
function information_schema(string $db) { function information_schema(string $db): bool {
return ($db == "information_schema") return ($db == "information_schema")
|| (min_version(5.5) && $db == "performance_schema"); || (min_version(5.5) && $db == "performance_schema");
} }
/** Get escaped error message /** Get escaped error message
* @return string
*/ */
function error() { function error(): string {
global $connection; 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));
} }
@@ -662,9 +651,8 @@ if (!defined('Adminer\DRIVER')) {
/** Drop databases /** Drop databases
* @param list<string> $databases * @param list<string> $databases
* @return bool
*/ */
function drop_databases(array $databases) { function drop_databases(array $databases): bool {
$return = apply_queries("DROP DATABASE", $databases, 'Adminer\idf_escape'); $return = apply_queries("DROP DATABASE", $databases, 'Adminer\idf_escape');
restart_session(); restart_session();
set_session("dbs", null); set_session("dbs", null);
@@ -673,9 +661,8 @@ if (!defined('Adminer\DRIVER')) {
/** Rename database from DB /** Rename database from DB
* @param string $name new name * @param string $name new name
* @return bool
*/ */
function rename_database(string $name, string $collation) { function rename_database(string $name, string $collation): bool {
$return = false; $return = false;
if (create_database($name, $collation)) { if (create_database($name, $collation)) {
$tables = array(); $tables = array();
@@ -694,9 +681,8 @@ if (!defined('Adminer\DRIVER')) {
} }
/** Generate modifier for auto increment column /** Generate modifier for auto increment column
* @return string
*/ */
function auto_increment() { function auto_increment(): string {
$auto_increment_index = " PRIMARY KEY"; $auto_increment_index = " PRIMARY KEY";
// don't overwrite primary key by auto_increment // don't overwrite primary key by auto_increment
if ($_GET["create"] != "" && $_POST["auto_increment_col"]) { if ($_GET["create"] != "" && $_POST["auto_increment_col"]) {
@@ -773,9 +759,8 @@ if (!defined('Adminer\DRIVER')) {
/** Run commands to truncate tables /** Run commands to truncate tables
* @param list<string> $tables * @param list<string> $tables
* @return bool
*/ */
function truncate_tables(array $tables) { function truncate_tables(array $tables): bool {
return apply_queries("TRUNCATE TABLE", $tables); return apply_queries("TRUNCATE TABLE", $tables);
} }
@@ -798,9 +783,8 @@ if (!defined('Adminer\DRIVER')) {
/** Move tables to other schema /** Move tables to other schema
* @param list<string> $tables * @param list<string> $tables
* @param list<string> $views * @param list<string> $views
* @return bool
*/ */
function move_tables(array $tables, array $views, string $target) { function move_tables(array $tables, array $views, string $target): bool {
global $connection; global $connection;
$rename = array(); $rename = array();
foreach ($tables as $table) { foreach ($tables as $table) {
@@ -827,9 +811,8 @@ if (!defined('Adminer\DRIVER')) {
/** Copy tables to other schema /** Copy tables to other schema
* @param list<string> $tables * @param list<string> $tables
* @param list<string> $views * @param list<string> $views
* @return bool
*/ */
function copy_tables(array $tables, array $views, string $target) { function copy_tables(array $tables, array $views, string $target): bool {
queries("SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'"); queries("SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'");
foreach ($tables as $table) { foreach ($tables as $table) {
$name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table)); $name = ($target == DB ? table("copy_$table") : idf_escape($target) . "." . table($table));
@@ -864,7 +847,7 @@ if (!defined('Adminer\DRIVER')) {
* @param string $name trigger name * @param string $name trigger name
* @return Trigger * @return Trigger
*/ */
function trigger(string $name, string $table) { function trigger(string $name, string $table): array {
if ($name == "") { if ($name == "") {
return array(); return array();
} }
@@ -875,7 +858,7 @@ if (!defined('Adminer\DRIVER')) {
/** Get defined triggers /** Get defined triggers
* @return array{string, string}[] * @return array{string, string}[]
*/ */
function triggers(string $table) { function triggers(string $table): array {
$return = array(); $return = array();
foreach (get_rows("SHOW TRIGGERS LIKE " . q(addcslashes($table, "%_\\"))) as $row) { foreach (get_rows("SHOW TRIGGERS LIKE " . q(addcslashes($table, "%_\\"))) as $row) {
$return[$row["Trigger"]] = array($row["Timing"], $row["Event"]); $return[$row["Trigger"]] = array($row["Timing"], $row["Event"]);
@@ -886,7 +869,7 @@ if (!defined('Adminer\DRIVER')) {
/** Get trigger options /** Get trigger options
* @return array{Timing: list<string>, Event: list<string>, Type: list<string>} * @return array{Timing: list<string>, Event: list<string>, Type: list<string>}
*/ */
function trigger_options() { function trigger_options(): array {
return array( return array(
"Timing" => array("BEFORE", "AFTER"), "Timing" => array("BEFORE", "AFTER"),
"Event" => array("INSERT", "UPDATE", "DELETE"), "Event" => array("INSERT", "UPDATE", "DELETE"),
@@ -898,7 +881,7 @@ if (!defined('Adminer\DRIVER')) {
* @param 'FUNCTION'|'PROCEDURE' $type * @param 'FUNCTION'|'PROCEDURE' $type
* @return Routine * @return Routine
*/ */
function routine(string $name, $type) { function routine(string $name, $type): array {
global $driver; global $driver;
$aliases = array("bool", "boolean", "integer", "double precision", "real", "dec", "numeric", "fixed", "national char", "national varchar"); $aliases = array("bool", "boolean", "integer", "double precision", "real", "dec", "numeric", "fixed", "national char", "national varchar");
$space = "(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)"; $space = "(?:\\s|/\\*[\s\S]*?\\*/|(?:#|-- )[^\n]*\n?|--\r?\n)";
@@ -935,30 +918,28 @@ if (!defined('Adminer\DRIVER')) {
/** Get list of routines /** Get list of routines
* @return list<string[]> ["SPECIFIC_NAME" => , "ROUTINE_NAME" => , "ROUTINE_TYPE" => , "DTD_IDENTIFIER" => ] * @return list<string[]> ["SPECIFIC_NAME" => , "ROUTINE_NAME" => , "ROUTINE_TYPE" => , "DTD_IDENTIFIER" => ]
*/ */
function routines() { function routines(): array {
return get_rows("SELECT ROUTINE_NAME AS SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE()"); return get_rows("SELECT ROUTINE_NAME AS SPECIFIC_NAME, ROUTINE_NAME, ROUTINE_TYPE, DTD_IDENTIFIER FROM information_schema.ROUTINES WHERE ROUTINE_SCHEMA = DATABASE()");
} }
/** Get list of available routine languages /** Get list of available routine languages
* @return list<string> * @return list<string>
*/ */
function routine_languages() { function routine_languages(): array {
return array(); // "SQL" not required return array(); // "SQL" not required
} }
/** Get routine signature /** Get routine signature
* @param Routine $row result of routine() * @param Routine $row result of routine()
* @return string
*/ */
function routine_id(string $name, array $row) { function routine_id(string $name, array $row): string {
return idf_escape($name); return idf_escape($name);
} }
/** Get last auto increment ID /** Get last auto increment ID
* @param Result $result or true * @param Result $result or true
* @return string
*/ */
function last_id($result) { function last_id($result): string {
return get_val("SELECT LAST_INSERT_ID()"); // mysql_insert_id() truncates bigint return get_val("SELECT LAST_INSERT_ID()"); // mysql_insert_id() truncates bigint
} }
@@ -979,9 +960,8 @@ if (!defined('Adminer\DRIVER')) {
} }
/** Get SQL command to create table /** Get SQL command to create table
* @return string
*/ */
function create_sql(string $table, bool $auto_increment, string $style) { function create_sql(string $table, bool $auto_increment, string $style): string {
$return = get_val("SHOW CREATE TABLE " . table($table), 1); $return = get_val("SHOW CREATE TABLE " . table($table), 1);
if (!$auto_increment) { if (!$auto_increment) {
$return = preg_replace('~ AUTO_INCREMENT=\d+~', '', $return); //! skip comments $return = preg_replace('~ AUTO_INCREMENT=\d+~', '', $return); //! skip comments
@@ -990,23 +970,20 @@ if (!defined('Adminer\DRIVER')) {
} }
/** Get SQL command to truncate table /** Get SQL command to truncate table
* @return string
*/ */
function truncate_sql(string $table) { function truncate_sql(string $table): string {
return "TRUNCATE " . table($table); return "TRUNCATE " . table($table);
} }
/** Get SQL command to change database /** Get SQL command to change database
* @return string
*/ */
function use_sql(string $database) { function use_sql(string $database): string {
return "USE " . idf_escape($database); return "USE " . idf_escape($database);
} }
/** Get SQL commands to create triggers /** Get SQL commands to create triggers
* @return string
*/ */
function trigger_sql(string $table) { function trigger_sql(string $table): string {
$return = ""; $return = "";
foreach (get_rows("SHOW TRIGGERS LIKE " . q(addcslashes($table, "%_\\")), null, "-- ") as $row) { foreach (get_rows("SHOW TRIGGERS LIKE " . q(addcslashes($table, "%_\\")), null, "-- ") as $row) {
$return .= "\nCREATE TRIGGER " . idf_escape($row["Trigger"]) . " $row[Timing] $row[Event] ON " . table($row["Table"]) . " FOR EACH ROW\n$row[Statement];;\n"; $return .= "\nCREATE TRIGGER " . idf_escape($row["Trigger"]) . " $row[Timing] $row[Event] ON " . table($row["Table"]) . " FOR EACH ROW\n$row[Statement];;\n";
@@ -1017,21 +994,21 @@ if (!defined('Adminer\DRIVER')) {
/** Get server variables /** Get server variables
* @return list<string[]> [[$name, $value]] * @return list<string[]> [[$name, $value]]
*/ */
function show_variables() { function show_variables(): array {
return get_rows("SHOW VARIABLES"); return get_rows("SHOW VARIABLES");
} }
/** Get status variables /** Get status variables
* @return list<string[]> [[$name, $value]] * @return list<string[]> [[$name, $value]]
*/ */
function show_status() { function show_status(): array {
return get_rows("SHOW STATUS"); return get_rows("SHOW STATUS");
} }
/** Get process list /** Get process list
* @return list<string[]> [$row] * @return list<string[]> [$row]
*/ */
function process_list() { function process_list(): array {
return get_rows("SHOW FULL PROCESSLIST"); return get_rows("SHOW FULL PROCESSLIST");
} }
@@ -1054,9 +1031,8 @@ if (!defined('Adminer\DRIVER')) {
/** Convert value in edit after applying functions back /** Convert value in edit after applying functions back
* @param Field $field one element from fields() * @param Field $field one element from fields()
* @param string $return SQL expression * @param string $return SQL expression
* @return string
*/ */
function unconvert_field(array $field, string $return) { function unconvert_field(array $field, string $return): string {
if (preg_match("~binary~", $field["type"])) { if (preg_match("~binary~", $field["type"])) {
$return = "UNHEX($return)"; $return = "UNHEX($return)";
} }
@@ -1072,9 +1048,8 @@ if (!defined('Adminer\DRIVER')) {
/** Check whether a feature is supported /** Check whether a feature is supported
* @param literal-string $feature "check|comment|copy|database|descidx|drop_col|dump|event|indexes|kill|materializedview|partitioning|privileges|procedure|processlist|routine|scheme|sequence|status|table|trigger|type|variables|view|view_trigger" * @param literal-string $feature "check|comment|copy|database|descidx|drop_col|dump|event|indexes|kill|materializedview|partitioning|privileges|procedure|processlist|routine|scheme|sequence|status|table|trigger|type|variables|view|view_trigger"
* @return bool
*/ */
function support(string $feature) { function support(string $feature): bool {
return !preg_match("~scheme|sequence|type|view_trigger|materializedview" . (min_version(8) ? "" : "|descidx" . (min_version(5.1) ? "" : "|event|partitioning")) . (min_version('8.0.16', '10.2.1') ? "" : "|check") . "~", $feature); return !preg_match("~scheme|sequence|type|view_trigger|materializedview" . (min_version(8) ? "" : "|descidx" . (min_version(5.1) ? "" : "|event|partitioning")) . (min_version('8.0.16', '10.2.1') ? "" : "|check") . "~", $feature);
} }
@@ -1087,16 +1062,15 @@ if (!defined('Adminer\DRIVER')) {
} }
/** Return query to get connection ID /** Return query to get connection ID
* @return string
*/ */
function connection_id() { function connection_id(): string {
return "SELECT CONNECTION_ID()"; return "SELECT CONNECTION_ID()";
} }
/** Get maximum number of connections /** Get maximum number of connections
* @return numeric-string * @return numeric-string
*/ */
function max_connections() { function max_connections(): string {
return get_val("SELECT @@max_connections"); return get_val("SELECT @@max_connections");
} }
@@ -1105,35 +1079,32 @@ if (!defined('Adminer\DRIVER')) {
/** Get user defined types /** Get user defined types
* @return string[] [$id => $name] * @return string[] [$id => $name]
*/ */
function types() { function types(): array {
return array(); return array();
} }
/** Get values of user defined type /** Get values of user defined type
* @return string
*/ */
function type_values(int $id) { function type_values(int $id): string {
return ""; return "";
} }
/** Get existing schemas /** Get existing schemas
* @return list<string> * @return list<string>
*/ */
function schemas() { function schemas(): array {
return array(); return array();
} }
/** Get current schema /** Get current schema
* @return string
*/ */
function get_schema() { function get_schema(): string {
return ""; return "";
} }
/** Set current schema /** Set current schema
* @return bool
*/ */
function set_schema(string $schema, Db $connection2 = null) { function set_schema(string $schema, Db $connection2 = null): bool {
return true; return true;
} }
} }

View File

@@ -461,9 +461,8 @@ if (isset($_GET["sqlite"])) {
* @param list<array{string, string, list<string>|'DROP'}> $indexes [[$type, $name, $columns]], empty to preserve * @param list<array{string, string, list<string>|'DROP'}> $indexes [[$type, $name, $columns]], empty to preserve
* @param string $drop_check CHECK constraint to drop * @param string $drop_check CHECK constraint to drop
* @param string $add_check CHECK constraint to add * @param string $add_check CHECK constraint to add
* @return bool
*/ */
function recreate_table(string $table, string $name, array $fields, array $originals, array $foreign, int $auto_increment = 0, $indexes = array(), string $drop_check = "", string $add_check = "") { function recreate_table(string $table, string $name, array $fields, array $originals, array $foreign, int $auto_increment = 0, $indexes = array(), string $drop_check = "", string $add_check = ""): bool {
global $driver; global $driver;
if ($table != "") { if ($table != "") {
if (!$fields) { if (!$fields) {

View File

@@ -10,14 +10,14 @@ class Adminer {
/** Name in title and navigation /** Name in title and navigation
* @return string HTML code * @return string HTML code
*/ */
function name() { function name(): string {
return "<a href='https://www.adminer.org/'" . target_blank() . " id='h1'>Adminer</a>"; return "<a href='https://www.adminer.org/'" . target_blank() . " id='h1'>Adminer</a>";
} }
/** Connection parameters /** Connection parameters
* @return array{string, string, string} * @return array{string, string, string}
*/ */
function credentials() { function credentials(): array {
return array(SERVER, $_GET["username"], get_password()); return array(SERVER, $_GET["username"], get_password());
} }
@@ -30,28 +30,26 @@ class Adminer {
/** Get key used for permanent login /** Get key used for permanent login
* @return string cryptic string which gets combined with password or false in case of an error * @return string cryptic string which gets combined with password or false in case of an error
*/ */
function permanentLogin(bool $create = false) { function permanentLogin(bool $create = false): string {
return password_file($create); return password_file($create);
} }
/** Return key used to group brute force attacks; behind a reverse proxy, you want to return the last part of X-Forwarded-For /** Return key used to group brute force attacks; behind a reverse proxy, you want to return the last part of X-Forwarded-For
* @return string
*/ */
function bruteForceKey() { function bruteForceKey(): string {
return $_SERVER["REMOTE_ADDR"]; return $_SERVER["REMOTE_ADDR"];
} }
/** Get server name displayed in breadcrumbs /** Get server name displayed in breadcrumbs
* @return string HTML code or null * @return string HTML code or null
*/ */
function serverName(string $server) { function serverName(string $server): string {
return h($server); return h($server);
} }
/** Identifier of selected database /** Identifier of selected database
* @return string
*/ */
function database() { function database(): string {
// should be used everywhere instead of DB // should be used everywhere instead of DB
return DB; return DB;
} }
@@ -59,34 +57,33 @@ class Adminer {
/** Get cached list of databases /** Get cached list of databases
* @return list<string> * @return list<string>
*/ */
function databases(bool $flush = true) { function databases(bool $flush = true): array {
return get_databases($flush); return get_databases($flush);
} }
/** Get list of schemas /** Get list of schemas
* @return list<string> * @return list<string>
*/ */
function schemas() { function schemas(): array {
return schemas(); return schemas();
} }
/** Specify limit for waiting on some slow queries like DB list /** Specify limit for waiting on some slow queries like DB list
* @return float number of seconds * @return float number of seconds
*/ */
function queryTimeout() { function queryTimeout(): float {
return 2; return 2;
} }
/** Headers to send before HTML output /** Headers to send before HTML output
* @return void
*/ */
function headers() { function headers(): void {
} }
/** Get Content Security Policy headers /** Get Content Security Policy headers
* @return list<string[]> of arrays with directive name in key, allowed sources in value * @return list<string[]> of arrays with directive name in key, allowed sources in value
*/ */
function csp() { function csp(): array {
return csp(); return csp();
} }
@@ -94,7 +91,7 @@ class Adminer {
* @param bool $dark dark CSS: false to disable, true to force, null to base on user preferences * @param bool $dark dark CSS: false to disable, true to force, null to base on user preferences
* @return bool true to link favicon.ico * @return bool true to link favicon.ico
*/ */
function head(bool $dark = null) { function head(bool $dark = null): bool {
// this is matched by compile.php // this is matched by compile.php
echo "<link rel='stylesheet' href='../externals/jush/jush.css'>\n"; echo "<link rel='stylesheet' href='../externals/jush/jush.css'>\n";
echo ($dark !== false ? "<link rel='stylesheet'" . ($dark ? "" : " media='(prefers-color-scheme: dark)'") . " href='../externals/jush/jush-dark.css'>\n" : ""); echo ($dark !== false ? "<link rel='stylesheet'" . ($dark ? "" : " media='(prefers-color-scheme: dark)'") . " href='../externals/jush/jush-dark.css'>\n" : "");
@@ -104,7 +101,7 @@ class Adminer {
/** Get URLs of the CSS files /** Get URLs of the CSS files
* @return list<string> * @return list<string>
*/ */
function css() { function css(): array {
$return = array(); $return = array();
foreach (array("", "-dark") as $mode) { foreach (array("", "-dark") as $mode) {
$filename = "adminer$mode.css"; $filename = "adminer$mode.css";
@@ -116,9 +113,8 @@ class Adminer {
} }
/** Print login form /** Print login form
* @return void
*/ */
function loginForm() { function loginForm(): void {
global $drivers; global $drivers;
echo "<table class='layout'>\n"; echo "<table class='layout'>\n";
// this is matched by compile.php // this is matched by compile.php
@@ -136,9 +132,8 @@ class Adminer {
/** Get login form field /** Get login form field
* @param string $heading HTML * @param string $heading HTML
* @param string $value HTML * @param string $value HTML
* @return string
*/ */
function loginFormField(string $name, string $heading, string $value) { function loginFormField(string $name, string $heading, string $value): string {
return $heading . $value . "\n"; return $heading . $value . "\n";
} }
@@ -156,7 +151,7 @@ class Adminer {
* @param TableStatus $tableStatus result of table_status1() * @param TableStatus $tableStatus result of table_status1()
* @return string HTML code, "" to ignore table * @return string HTML code, "" to ignore table
*/ */
function tableName(array $tableStatus) { function tableName(array $tableStatus): string {
return h($tableStatus["Name"]); return h($tableStatus["Name"]);
} }
@@ -165,7 +160,7 @@ class Adminer {
* @param int $order order of column in select * @param int $order order of column in select
* @return string HTML code, "" to ignore field * @return string HTML code, "" to ignore field
*/ */
function fieldName(array $field, int $order = 0) { function fieldName(array $field, int $order = 0): string {
$type = $field["full_type"]; $type = $field["full_type"];
$comment = $field["comment"]; $comment = $field["comment"];
return '<span title="' . h($type . ($comment != "" ? ($type ? ": " : "") . $comment : '')) . '">' . h($field["field"]) . '</span>'; return '<span title="' . h($type . ($comment != "" ? ($type ? ": " : "") . $comment : '')) . '">' . h($field["field"]) . '</span>';
@@ -174,9 +169,8 @@ class Adminer {
/** Print links after select heading /** Print links after select heading
* @param TableStatus $tableStatus result of table_status1() * @param TableStatus $tableStatus result of table_status1()
* @param string $set new item options, NULL for no new item * @param string $set new item options, NULL for no new item
* @return void
*/ */
function selectLinks(array $tableStatus, string $set = "") { function selectLinks(array $tableStatus, string $set = ""): void {
global $driver; global $driver;
echo '<p class="links">'; echo '<p class="links">';
$links = array("select" => lang('Select data')); $links = array("select" => lang('Select data'));
@@ -206,31 +200,29 @@ class Adminer {
/** Get foreign keys for table /** Get foreign keys for table
* @return ForeignKey[] same format as foreign_keys() * @return ForeignKey[] same format as foreign_keys()
*/ */
function foreignKeys(string $table) { function foreignKeys(string $table): array {
return foreign_keys($table); return foreign_keys($table);
} }
/** Find backward keys for table /** Find backward keys for table
* @return BackwardKey[] * @return BackwardKey[]
*/ */
function backwardKeys(string $table, string $tableName) { function backwardKeys(string $table, string $tableName): array {
return array(); return array();
} }
/** Print backward keys for row /** Print backward keys for row
* @param BackwardKey[] $backwardKeys result of $this->backwardKeys() * @param BackwardKey[] $backwardKeys result of $this->backwardKeys()
* @param string[] $row * @param string[] $row
* @return void
*/ */
function backwardKeysPrint(array $backwardKeys, array $row) { function backwardKeysPrint(array $backwardKeys, array $row): void {
} }
/** Query printed in select before execution /** Query printed in select before execution
* @param string $query query to be executed * @param string $query query to be executed
* @param float $start start time of the query * @param float $start start time of the query
* @return string
*/ */
function selectQuery(string $query, float $start, bool $failed = false) { function selectQuery(string $query, float $start, bool $failed = false): string {
global $driver; global $driver;
$return = "</p>\n"; // required for IE9 inline edit $return = "</p>\n"; // required for IE9 inline edit
if (!$failed && ($warnings = $driver->warnings())) { if (!$failed && ($warnings = $driver->warnings())) {
@@ -249,20 +241,19 @@ class Adminer {
* @param string $query query to be executed * @param string $query query to be executed
* @return string escaped query to be printed * @return string escaped query to be printed
*/ */
function sqlCommandQuery(string $query) { function sqlCommandQuery(string $query): string {
return shorten_utf8(trim($query), 1000); return shorten_utf8(trim($query), 1000);
} }
/** Print HTML code just before the Execute button in SQL command /** Print HTML code just before the Execute button in SQL command
* @return void
*/ */
function sqlPrintAfter() { function sqlPrintAfter(): void {
} }
/** Description of a row in a table /** Description of a row in a table
* @return string SQL expression, empty string for no description * @return string SQL expression, empty string for no description
*/ */
function rowDescription(string $table) { function rowDescription(string $table): string {
return ""; return "";
} }
@@ -271,7 +262,7 @@ class Adminer {
* @param ForeignKey[] $foreignKeys * @param ForeignKey[] $foreignKeys
* @return list<string[]> * @return list<string[]>
*/ */
function rowDescriptions(array $rows, array $foreignKeys) { function rowDescriptions(array $rows, array $foreignKeys): array {
return $rows; return $rows;
} }
@@ -288,9 +279,8 @@ class Adminer {
* @param string $link link to foreign key * @param string $link link to foreign key
* @param Field $field single field returned from fields() * @param Field $field single field returned from fields()
* @param string $original original value before applying editVal() and escaping * @param string $original original value before applying editVal() and escaping
* @return string
*/ */
function selectVal(string $val, string $link, array $field, string $original) { function selectVal(string $val, string $link, array $field, string $original): string {
$return = ($val === null ? "<i>NULL</i>" $return = ($val === null ? "<i>NULL</i>"
: (preg_match("~char|binary|boolean~", $field["type"]) && !preg_match("~var~", $field["type"]) ? "<code>$val</code>" : (preg_match("~char|binary|boolean~", $field["type"]) && !preg_match("~var~", $field["type"]) ? "<code>$val</code>"
: (preg_match('~json~', $field["type"]) ? "<code class='jush-js'>$val</code>" : (preg_match('~json~', $field["type"]) ? "<code class='jush-js'>$val</code>"
@@ -304,18 +294,16 @@ class Adminer {
/** Value conversion used in select and edit /** Value conversion used in select and edit
* @param Field $field single field returned from fields() * @param Field $field single field returned from fields()
* @return string
*/ */
function editVal(string $val, array $field) { function editVal(string $val, array $field): string {
return $val; return $val;
} }
/** Print table structure in tabular format /** Print table structure in tabular format
* @param Field[] $fields data about individual fields * @param Field[] $fields data about individual fields
* @param TableStatus $tableStatus * @param TableStatus $tableStatus
* @return void
*/ */
function tableStructurePrint(array $fields, array $tableStatus = null) { function tableStructurePrint(array $fields, array $tableStatus = null): void {
global $driver; global $driver;
echo "<div class='scrollable'>\n"; echo "<div class='scrollable'>\n";
echo "<table class='nowrap odds'>\n"; echo "<table class='nowrap odds'>\n";
@@ -344,9 +332,8 @@ class Adminer {
/** Print list of indexes on table in tabular format /** Print list of indexes on table in tabular format
* @param Index[] $indexes data about all indexes on a table * @param Index[] $indexes data about all indexes on a table
* @return void
*/ */
function tableIndexesPrint(array $indexes) { function tableIndexesPrint(array $indexes): void {
echo "<table>\n"; echo "<table>\n";
foreach ($indexes as $name => $index) { foreach ($indexes as $name => $index) {
ksort($index["columns"]); // enforce correct columns order ksort($index["columns"]); // enforce correct columns order
@@ -365,9 +352,8 @@ class Adminer {
/** Print columns box in select /** Print columns box in select
* @param list<string> $select result of selectColumnsProcess()[0] * @param list<string> $select result of selectColumnsProcess()[0]
* @param string[] $columns selectable columns * @param string[] $columns selectable columns
* @return void
*/ */
function selectColumnsPrint(array $select, array $columns) { function selectColumnsPrint(array $select, array $columns): void {
global $driver; global $driver;
print_fieldset("select", lang('Select'), $select); print_fieldset("select", lang('Select'), $select);
$i = 0; $i = 0;
@@ -393,9 +379,8 @@ class Adminer {
* @param list<string> $where result of selectSearchProcess() * @param list<string> $where result of selectSearchProcess()
* @param string[] $columns selectable columns * @param string[] $columns selectable columns
* @param Index[] $indexes * @param Index[] $indexes
* @return void
*/ */
function selectSearchPrint(array $where, array $columns, array $indexes) { function selectSearchPrint(array $where, array $columns, array $indexes): void {
print_fieldset("search", lang('Search'), $where); print_fieldset("search", lang('Search'), $where);
foreach ($indexes as $i => $index) { foreach ($indexes as $i => $index) {
if ($index["type"] == "FULLTEXT") { if ($index["type"] == "FULLTEXT") {
@@ -429,9 +414,8 @@ class Adminer {
* @param list<string> $order result of selectOrderProcess() * @param list<string> $order result of selectOrderProcess()
* @param string[] $columns selectable columns * @param string[] $columns selectable columns
* @param Index[] $indexes * @param Index[] $indexes
* @return void
*/ */
function selectOrderPrint(array $order, array $columns, array $indexes) { function selectOrderPrint(array $order, array $columns, array $indexes): void {
print_fieldset("sort", lang('Sort'), $order); print_fieldset("sort", lang('Sort'), $order);
$i = 0; $i = 0;
foreach ((array) $_GET["order"] as $key => $val) { foreach ((array) $_GET["order"] as $key => $val) {
@@ -448,9 +432,8 @@ class Adminer {
/** Print limit box in select /** Print limit box in select
* @param string $limit result of selectLimitProcess() * @param string $limit result of selectLimitProcess()
* @return void
*/ */
function selectLimitPrint(string $limit) { function selectLimitPrint(string $limit): void {
echo "<fieldset><legend>" . lang('Limit') . "</legend><div>"; // <div> for easy styling echo "<fieldset><legend>" . lang('Limit') . "</legend><div>"; // <div> for easy styling
echo "<input type='number' name='limit' class='size' value='" . h($limit) . "'>"; echo "<input type='number' name='limit' class='size' value='" . h($limit) . "'>";
echo script("qsl('input').oninput = selectFieldChange;", ""); echo script("qsl('input').oninput = selectFieldChange;", "");
@@ -459,9 +442,8 @@ class Adminer {
/** Print text length box in select /** Print text length box in select
* @param string $text_length result of selectLengthProcess() * @param string $text_length result of selectLengthProcess()
* @return void
*/ */
function selectLengthPrint(string $text_length) { function selectLengthPrint(string $text_length): void {
if ($text_length !== null) { if ($text_length !== null) {
echo "<fieldset><legend>" . lang('Text length') . "</legend><div>"; echo "<fieldset><legend>" . lang('Text length') . "</legend><div>";
echo "<input type='number' name='text_length' class='size' value='" . h($text_length) . "'>"; echo "<input type='number' name='text_length' class='size' value='" . h($text_length) . "'>";
@@ -471,9 +453,8 @@ class Adminer {
/** Print action box in select /** Print action box in select
* @param Index[] $indexes * @param Index[] $indexes
* @return void
*/ */
function selectActionPrint(array $indexes) { function selectActionPrint(array $indexes): void {
echo "<fieldset><legend>" . lang('Action') . "</legend><div>"; echo "<fieldset><legend>" . lang('Action') . "</legend><div>";
echo "<input type='submit' value='" . lang('Select') . "'>"; echo "<input type='submit' value='" . lang('Select') . "'>";
echo " <span id='noindex' title='" . lang('Full table scan') . "'></span>"; echo " <span id='noindex' title='" . lang('Full table scan') . "'></span>";
@@ -499,23 +480,22 @@ class Adminer {
/** Print command box in select /** Print command box in select
* @return bool whether to print default commands * @return bool whether to print default commands
*/ */
function selectCommandPrint() { function selectCommandPrint(): bool {
return !information_schema(DB); return !information_schema(DB);
} }
/** Print import box in select /** Print import box in select
* @return bool whether to print default import * @return bool whether to print default import
*/ */
function selectImportPrint() { function selectImportPrint(): bool {
return !information_schema(DB); return !information_schema(DB);
} }
/** Print extra text in the end of a select form /** Print extra text in the end of a select form
* @param string[] $emailFields fields holding e-mails * @param string[] $emailFields fields holding e-mails
* @param string[] $columns selectable columns * @param string[] $columns selectable columns
* @return void
*/ */
function selectEmailPrint(array $emailFields, array $columns) { function selectEmailPrint(array $emailFields, array $columns): void {
} }
/** Process columns box in select /** Process columns box in select
@@ -523,7 +503,7 @@ class Adminer {
* @param Index[] $indexes * @param Index[] $indexes
* @return list<list<string>> [[select_expressions], [group_expressions]] * @return list<list<string>> [[select_expressions], [group_expressions]]
*/ */
function selectColumnsProcess(array $columns, array $indexes) { function selectColumnsProcess(array $columns, array $indexes): array {
global $driver; global $driver;
$select = array(); // select expressions, empty for * $select = array(); // select expressions, empty for *
$group = array(); // expressions without aggregation - will be used for GROUP BY if an aggregation function is used $group = array(); // expressions without aggregation - will be used for GROUP BY if an aggregation function is used
@@ -543,7 +523,7 @@ class Adminer {
* @param Index[] $indexes * @param Index[] $indexes
* @return list<string> expressions to join by AND * @return list<string> expressions to join by AND
*/ */
function selectSearchProcess(array $fields, array $indexes) { function selectSearchProcess(array $fields, array $indexes): array {
global $connection, $driver; global $connection, $driver;
$return = array(); $return = array();
foreach ($indexes as $i => $index) { foreach ($indexes as $i => $index) {
@@ -597,7 +577,7 @@ class Adminer {
* @param Index[] $indexes * @param Index[] $indexes
* @return list<string> expressions to join by comma * @return list<string> expressions to join by comma
*/ */
function selectOrderProcess(array $fields, array $indexes) { function selectOrderProcess(array $fields, array $indexes): array {
$return = array(); $return = array();
foreach ((array) $_GET["order"] as $key => $val) { foreach ((array) $_GET["order"] as $key => $val) {
if ($val != "") { if ($val != "") {
@@ -612,14 +592,14 @@ class Adminer {
/** Process limit box in select /** Process limit box in select
* @return string expression to use in LIMIT, will be escaped * @return string expression to use in LIMIT, will be escaped
*/ */
function selectLimitProcess() { function selectLimitProcess(): string {
return (isset($_GET["limit"]) ? $_GET["limit"] : "50"); return (isset($_GET["limit"]) ? $_GET["limit"] : "50");
} }
/** Process length box in select /** Process length box in select
* @return string number of characters to shorten texts, will be escaped * @return string number of characters to shorten texts, will be escaped
*/ */
function selectLengthProcess() { function selectLengthProcess(): string {
return (isset($_GET["text_length"]) ? $_GET["text_length"] : "100"); return (isset($_GET["text_length"]) ? $_GET["text_length"] : "100");
} }
@@ -628,7 +608,7 @@ class Adminer {
* @param ForeignKey[] $foreignKeys * @param ForeignKey[] $foreignKeys
* @return bool true if processed, false to process other parts of form * @return bool true if processed, false to process other parts of form
*/ */
function selectEmailProcess(array $where, array $foreignKeys) { function selectEmailProcess(array $where, array $foreignKeys): bool {
return false; return false;
} }
@@ -641,16 +621,15 @@ class Adminer {
* @param int $page index of page starting at zero * @param int $page index of page starting at zero
* @return string empty string to use default query * @return string empty string to use default query
*/ */
function selectQueryBuild(array $select, array $where, array $group, array $order, int $limit, int $page) { function selectQueryBuild(array $select, array $where, array $group, array $order, int $limit, int $page): string {
return ""; return "";
} }
/** Query printed after execution in the message /** Query printed after execution in the message
* @param string $query executed query * @param string $query executed query
* @param string $time elapsed time * @param string $time elapsed time
* @return string
*/ */
function messageQuery(string $query, string $time, bool $failed = false) { function messageQuery(string $query, string $time, bool $failed = false): string {
global $driver; global $driver;
restart_session(); restart_session();
$history = &get_session("queries"); $history = &get_session("queries");
@@ -678,16 +657,15 @@ class Adminer {
/** Print before edit form /** Print before edit form
* @param Field[] $fields * @param Field[] $fields
* @param mixed $row * @param mixed $row
* @return void
*/ */
function editRowPrint(string $table, array $fields, $row, bool $update) { function editRowPrint(string $table, array $fields, $row, bool $update): void {
} }
/** Functions displayed in edit form /** Functions displayed in edit form
* @param Field $field single field from fields() * @param Field $field single field from fields()
* @return list<string> * @return list<string>
*/ */
function editFunctions(array $field) { function editFunctions(array $field): array {
global $driver; global $driver;
$return = ($field["null"] ? "NULL/" : ""); $return = ($field["null"] ? "NULL/" : "");
$update = isset($_GET["select"]) || where($_GET); $update = isset($_GET["select"]) || where($_GET);
@@ -715,7 +693,7 @@ class Adminer {
* @param string $attrs attributes to use inside the tag * @param string $attrs attributes to use inside the tag
* @return string custom input field or empty string for default * @return string custom input field or empty string for default
*/ */
function editInput(string $table, array $field, string $attrs, string $value) { function editInput(string $table, array $field, string $attrs, string $value): string {
if ($field["type"] == "enum") { if ($field["type"] == "enum") {
return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "") return (isset($_GET["select"]) ? "<label><input type='radio'$attrs value='-1' checked><i>" . lang('original') . "</i></label> " : "")
. ($field["null"] ? "<label><input type='radio'$attrs value=''" . ($value !== null || isset($_GET["select"]) ? "" : " checked") . "><i>NULL</i></label> " : "") . ($field["null"] ? "<label><input type='radio'$attrs value=''" . ($value !== null || isset($_GET["select"]) ? "" : " checked") . "><i>NULL</i></label> " : "")
@@ -728,9 +706,8 @@ class Adminer {
/** Get hint for edit field /** Get hint for edit field
* @param string $table table name * @param string $table table name
* @param Field $field single field from fields() * @param Field $field single field from fields()
* @return string
*/ */
function editHint(string $table, array $field, string $value) { function editHint(string $table, array $field, string $value): string {
return ""; return "";
} }
@@ -738,7 +715,7 @@ class Adminer {
* @param Field $field single field from fields() * @param Field $field single field from fields()
* @return string expression to use in a query * @return string expression to use in a query
*/ */
function processInput(array $field, string $value, string $function = "") { function processInput(array $field, string $value, string $function = ""): string {
if ($function == "SQL") { if ($function == "SQL") {
return $value; // SQL injection return $value; // SQL injection
} }
@@ -763,7 +740,7 @@ class Adminer {
/** Return export output options /** Return export output options
* @return string[] * @return string[]
*/ */
function dumpOutput() { function dumpOutput(): array {
$return = array('text' => lang('open'), 'file' => lang('save')); $return = array('text' => lang('open'), 'file' => lang('save'));
if (function_exists('gzencode')) { if (function_exists('gzencode')) {
$return['gz'] = 'gzip'; $return['gz'] = 'gzip';
@@ -774,21 +751,21 @@ class Adminer {
/** Return export format options /** Return export format options
* @return string[] empty to disable export * @return string[] empty to disable export
*/ */
function dumpFormat() { function dumpFormat(): array {
return (support("dump") ? array('sql' => 'SQL') : array()) + array('csv' => 'CSV,', 'csv;' => 'CSV;', 'tsv' => 'TSV'); return (support("dump") ? array('sql' => 'SQL') : array()) + array('csv' => 'CSV,', 'csv;' => 'CSV;', 'tsv' => 'TSV');
} }
/** Export database structure /** Export database structure
* @return void prints data * @return void prints data
*/ */
function dumpDatabase(string $db) { function dumpDatabase(string $db): void {
} }
/** Export table structure /** Export table structure
* @param int $is_view 0 table, 1 view, 2 temporary view table * @param int $is_view 0 table, 1 view, 2 temporary view table
* @return void prints data * @return void prints data
*/ */
function dumpTable(string $table, string $style, int $is_view = 0) { function dumpTable(string $table, string $style, int $is_view = 0): void {
if ($_POST["format"] != "sql") { if ($_POST["format"] != "sql") {
echo "\xef\xbb\xbf"; // UTF-8 byte order mark echo "\xef\xbb\xbf"; // UTF-8 byte order mark
if ($style) { if ($style) {
@@ -820,7 +797,7 @@ class Adminer {
/** Export table data /** Export table data
* @return void prints data * @return void prints data
*/ */
function dumpData(string $table, string $style, string $query) { function dumpData(string $table, string $style, string $query): void {
global $connection; global $connection;
if ($style) { if ($style) {
$max_packet = (JUSH == "sqlite" ? 0 : 1048576); // default, minimum is 1024 $max_packet = (JUSH == "sqlite" ? 0 : 1048576); // default, minimum is 1024
@@ -911,14 +888,14 @@ class Adminer {
/** Set export filename /** Set export filename
* @return string filename without extension * @return string filename without extension
*/ */
function dumpFilename(string $identifier) { function dumpFilename(string $identifier): string {
return friendly_url($identifier != "" ? $identifier : (SERVER != "" ? SERVER : "localhost")); return friendly_url($identifier != "" ? $identifier : (SERVER != "" ? SERVER : "localhost"));
} }
/** Send headers for export /** Send headers for export
* @return string extension * @return string extension
*/ */
function dumpHeaders(string $identifier, bool $multi_table = false) { function dumpHeaders(string $identifier, bool $multi_table = false): string {
$output = $_POST["output"]; $output = $_POST["output"];
$ext = (preg_match('~sql~', $_POST["format"]) ? "sql" : ($multi_table ? "tar" : "csv")); // multiple CSV packed to TAR $ext = (preg_match('~sql~', $_POST["format"]) ? "sql" : ($multi_table ? "tar" : "csv")); // multiple CSV packed to TAR
header("Content-Type: " . header("Content-Type: " .
@@ -938,7 +915,7 @@ class Adminer {
/** Print text after export /** Print text after export
* @return void prints data * @return void prints data
*/ */
function dumpFooter() { function dumpFooter(): void {
if ($_POST["format"] == "sql") { if ($_POST["format"] == "sql") {
echo "-- " . gmdate("Y-m-d H:i:s e") . "\n"; echo "-- " . gmdate("Y-m-d H:i:s e") . "\n";
} }
@@ -947,14 +924,14 @@ class Adminer {
/** Set the path of the file for webserver load /** Set the path of the file for webserver load
* @return string path of the sql dump file * @return string path of the sql dump file
*/ */
function importServerPath() { function importServerPath(): string {
return "adminer.sql"; return "adminer.sql";
} }
/** Print homepage /** Print homepage
* @return bool whether to print default homepage * @return bool whether to print default homepage
*/ */
function homepage() { function homepage(): bool {
echo '<p class="links">' . ($_GET["ns"] == "" && support("database") ? '<a href="' . h(ME) . 'database=">' . lang('Alter database') . "</a>\n" : ""); echo '<p class="links">' . ($_GET["ns"] == "" && support("database") ? '<a href="' . h(ME) . 'database=">' . lang('Alter database') . "</a>\n" : "");
echo (support("scheme") ? "<a href='" . h(ME) . "scheme='>" . ($_GET["ns"] != "" ? lang('Alter schema') : lang('Create schema')) . "</a>\n" : ""); echo (support("scheme") ? "<a href='" . h(ME) . "scheme='>" . ($_GET["ns"] != "" ? lang('Alter schema') : lang('Create schema')) . "</a>\n" : "");
echo ($_GET["ns"] !== "" ? '<a href="' . h(ME) . 'schema=">' . lang('Database schema') . "</a>\n" : ""); echo ($_GET["ns"] !== "" ? '<a href="' . h(ME) . 'schema=">' . lang('Database schema') . "</a>\n" : "");
@@ -964,9 +941,8 @@ class Adminer {
/** Print navigation after Adminer title /** Print navigation after Adminer title
* @param string $missing can be "auth" if there is no database connection, "db" if there is no database selected, "ns" with invalid schema * @param string $missing can be "auth" if there is no database connection, "db" if there is no database selected, "ns" with invalid schema
* @return void
*/ */
function navigation(string $missing) { function navigation(string $missing): void {
global $VERSION, $drivers, $connection; global $VERSION, $drivers, $connection;
echo "<h1>" . $this->name() . " <span class='version'>$VERSION"; echo "<h1>" . $this->name() . " <span class='version'>$VERSION";
$new_version = $_COOKIE["adminer_version"]; $new_version = $_COOKIE["adminer_version"];
@@ -1025,9 +1001,8 @@ class Adminer {
/** Set up syntax highlight for code and <textarea> /** Set up syntax highlight for code and <textarea>
* @param TableStatus[] $tables result of table_status('', true) * @param TableStatus[] $tables result of table_status('', true)
* @return void
*/ */
function syntaxHighlighting(array $tables) { function syntaxHighlighting(array $tables): void {
global $connection; global $connection;
// this is matched by compile.php // this is matched by compile.php
echo script_src("../externals/jush/modules/jush.js"); echo script_src("../externals/jush/modules/jush.js");
@@ -1055,9 +1030,8 @@ class Adminer {
} }
/** Print databases list in menu /** Print databases list in menu
* @return void
*/ */
function databasesPrint(string $missing) { function databasesPrint(string $missing): void {
global $adminer, $connection; global $adminer, $connection;
$databases = $this->databases(); $databases = $this->databases();
if (DB && $databases && !in_array(DB, $databases)) { if (DB && $databases && !in_array(DB, $databases)) {
@@ -1090,9 +1064,8 @@ class Adminer {
/** Print table list in menu /** Print table list in menu
* @param TableStatus[] $tables result of table_status('', true) * @param TableStatus[] $tables result of table_status('', true)
* @return void
*/ */
function tablesPrint(array $tables) { function tablesPrint(array $tables): void {
echo "<ul id='tables'>" . script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});"); echo "<ul id='tables'>" . script("mixin(qs('#tables'), {onmouseover: menuOver, onmouseout: menuOut});");
foreach ($tables as $table => $status) { foreach ($tables as $table => $status) {
$name = $this->tableName($status); $name = $this->tableName($status);

View File

@@ -17,8 +17,7 @@ if ($_COOKIE["adminer_permanent"]) {
} }
} }
/** @return void */ function add_invalid_login(): void {
function add_invalid_login() {
global $adminer; global $adminer;
$base = get_temp_dir() . "/adminer.invalid"; $base = get_temp_dir() . "/adminer.invalid";
// adminer.invalid may not be writable by us, try the files with random suffixes // adminer.invalid may not be writable by us, try the files with random suffixes
@@ -51,8 +50,7 @@ function add_invalid_login() {
file_write_unlock($fp, serialize($invalids)); file_write_unlock($fp, serialize($invalids));
} }
/** @return void */ function check_invalid_login(): void {
function check_invalid_login() {
global $adminer; global $adminer;
$invalids = array(); $invalids = array();
foreach (glob(get_temp_dir() . "/adminer.invalid*") as $filename) { foreach (glob(get_temp_dir() . "/adminer.invalid*") as $filename) {
@@ -115,8 +113,7 @@ if ($auth) {
} }
} }
/** @return void */ function unset_permanent(): void {
function unset_permanent() {
global $permanent; global $permanent;
foreach ($permanent as $key => $val) { foreach ($permanent as $key => $val) {
list($vendor, $server, $username, $db) = array_map('base64_decode', explode("-", $key)); list($vendor, $server, $username, $db) = array_map('base64_decode', explode("-", $key));

View File

@@ -3,8 +3,7 @@ namespace Adminer;
// coverage is used in tests and removed in compilation // coverage is used in tests and removed in compilation
if (extension_loaded("xdebug") && file_exists(sys_get_temp_dir() . "/adminer.coverage")) { if (extension_loaded("xdebug") && file_exists(sys_get_temp_dir() . "/adminer.coverage")) {
/** @return void */ function save_coverage(): void {
function save_coverage() {
$coverage_filename = sys_get_temp_dir() . "/adminer.coverage"; $coverage_filename = sys_get_temp_dir() . "/adminer.coverage";
$coverage = unserialize(file_get_contents($coverage_filename)); $coverage = unserialize(file_get_contents($coverage_filename));
foreach (xdebug_get_code_coverage() as $filename => $lines) { foreach (xdebug_get_code_coverage() as $filename => $lines) {

View File

@@ -14,19 +14,17 @@ abstract class SqlDb {
/** @var Result|bool */ protected $multi; // used for multiquery /** @var Result|bool */ protected $multi; // used for multiquery
/** Connect to server /** Connect to server
* @return bool
*/ */
abstract function connect(string $server, string $username, string $password); abstract function connect(string $server, string $username, string $password): bool;
/** Quote string to use in SQL /** Quote string to use in SQL
* @return string escaped string enclosed in ' * @return string escaped string enclosed in '
*/ */
abstract function quote(string $string); abstract function quote(string $string): string;
/** Select database /** Select database
* @return bool
*/ */
abstract function select_db(string $database); abstract function select_db(string $database): bool;
/** Send query /** Send query
* @return Result|bool * @return Result|bool
@@ -48,9 +46,8 @@ abstract class SqlDb {
} }
/** Fetch next resultset /** Fetch next resultset
* @return bool
*/ */
function next_result() { function next_result(): bool {
return false; return false;
} }

View File

@@ -5,9 +5,8 @@ namespace Adminer;
* @param string $title used in title, breadcrumb and heading, should be HTML escaped * @param string $title used in title, breadcrumb and heading, should be HTML escaped
* @param mixed $breadcrumb ["key" => "link", "key2" => ["link", "desc"]], null for nothing, false for driver only, true for driver and server * @param mixed $breadcrumb ["key" => "link", "key2" => ["link", "desc"]], null for nothing, false for driver only, true for driver and server
* @param string $title2 used after colon in title and heading, should be HTML escaped * @param string $title2 used after colon in title and heading, should be HTML escaped
* @return void
*/ */
function page_header(string $title, string $error = "", $breadcrumb = array(), string $title2 = "") { function page_header(string $title, string $error = "", $breadcrumb = array(), string $title2 = ""): void {
global $LANG, $VERSION, $adminer, $drivers; global $LANG, $VERSION, $adminer, $drivers;
page_headers(); page_headers();
if (is_ajax() && $error) { if (is_ajax() && $error) {
@@ -127,9 +126,8 @@ const thousandsSeparator = '" . js_escape(lang(',')) . "';")
} }
/** Send HTTP headers /** Send HTTP headers
* @return void
*/ */
function page_headers() { function page_headers(): void {
global $adminer; global $adminer;
header("Content-Type: text/html; charset=utf-8"); header("Content-Type: text/html; charset=utf-8");
header("Cache-Control: no-cache"); header("Cache-Control: no-cache");
@@ -150,7 +148,7 @@ function page_headers() {
/** Get Content Security Policy headers /** Get Content Security Policy headers
* @return list<string[]> of arrays with directive name in key, allowed sources in value * @return list<string[]> of arrays with directive name in key, allowed sources in value
*/ */
function csp() { function csp(): array {
return array( return array(
array( array(
"script-src" => "'self' 'unsafe-inline' 'nonce-" . get_nonce() . "' 'strict-dynamic'", // 'self' is a fallback for browsers not supporting 'strict-dynamic', 'unsafe-inline' is a fallback for browsers not supporting 'nonce-' "script-src" => "'self' 'unsafe-inline' 'nonce-" . get_nonce() . "' 'strict-dynamic'", // 'self' is a fallback for browsers not supporting 'strict-dynamic', 'unsafe-inline' is a fallback for browsers not supporting 'nonce-'
@@ -166,7 +164,7 @@ function csp() {
/** Get a CSP nonce /** Get a CSP nonce
* @return string Base64 value * @return string Base64 value
*/ */
function get_nonce() { function get_nonce(): string {
static $nonce; static $nonce;
if (!$nonce) { if (!$nonce) {
$nonce = base64_encode(rand_string()); $nonce = base64_encode(rand_string());
@@ -175,9 +173,8 @@ function get_nonce() {
} }
/** Print flash and error messages /** Print flash and error messages
* @return void
*/ */
function page_messages(string $error) { function page_messages(string $error): void {
global $adminer; global $adminer;
$uri = preg_replace('~^[^?]*~', '', $_SERVER["REQUEST_URI"]); $uri = preg_replace('~^[^?]*~', '', $_SERVER["REQUEST_URI"]);
$messages = idx($_SESSION["messages"], $uri); $messages = idx($_SESSION["messages"], $uri);
@@ -195,9 +192,8 @@ function page_messages(string $error) {
/** Print HTML footer /** Print HTML footer
* @param string $missing "auth", "db", "ns" * @param string $missing "auth", "db", "ns"
* @return void
*/ */
function page_footer(string $missing = "") { function page_footer(string $missing = ""): void {
global $adminer; global $adminer;
echo "</div>\n\n<div id='menu'>\n"; echo "</div>\n\n<div id='menu'>\n";
$adminer->navigation($missing); $adminer->navigation($missing);

View File

@@ -4,17 +4,15 @@ namespace Adminer;
$drivers = array(); $drivers = array();
/** Add a driver /** Add a driver
* @return void
*/ */
function add_driver(string $id, string $name) { function add_driver(string $id, string $name): void {
global $drivers; global $drivers;
$drivers[$id] = $name; $drivers[$id] = $name;
} }
/** Get driver name /** Get driver name
* @return string
*/ */
function get_driver(string $id) { function get_driver(string $id): string {
global $drivers; global $drivers;
return $drivers[$id]; return $drivers[$id];
} }
@@ -44,7 +42,7 @@ abstract class SqlDriver {
/** Get all types /** Get all types
* @return int[] [$type => $maximum_unsigned_length, ...] * @return int[] [$type => $maximum_unsigned_length, ...]
*/ */
function types() { function types(): array {
return call_user_func_array('array_merge', array_values($this->types)); return call_user_func_array('array_merge', array_values($this->types));
} }
@@ -137,9 +135,8 @@ abstract class SqlDriver {
} }
/** Get RETURNING clause for INSERT queries (PostgreSQL specific) /** Get RETURNING clause for INSERT queries (PostgreSQL specific)
* @return string
*/ */
function insertReturning(string $table) { function insertReturning(string $table): string {
return ""; return "";
} }
@@ -184,24 +181,21 @@ abstract class SqlDriver {
* @param string $idf escaped column name * @param string $idf escaped column name
* @param array{op:string, val:string} $val * @param array{op:string, val:string} $val
* @param Field $field * @param Field $field
* @return string
*/ */
function convertSearch(string $idf, array $val, array $field) { function convertSearch(string $idf, array $val, array $field): string {
return $idf; return $idf;
} }
/** Convert operator so it can be used in search /** Convert operator so it can be used in search
* @return string
*/ */
function convertOperator(string $operator) { function convertOperator(string $operator): string {
return $operator; return $operator;
} }
/** Convert value returned by database to actual value /** Convert value returned by database to actual value
* @param Field $field * @param Field $field
* @return string
*/ */
function value(string $val, array $field) { function value(string $val, array $field): string {
return (method_exists($this->conn, 'value') return (method_exists($this->conn, 'value')
? $this->conn->value($val, $field) ? $this->conn->value($val, $field)
: (is_resource($val) ? stream_get_contents($val) : $val) : (is_resource($val) ? stream_get_contents($val) : $val)
@@ -209,9 +203,8 @@ abstract class SqlDriver {
} }
/** Quote binary string /** Quote binary string
* @return string
*/ */
function quoteBinary(string $s) { function quoteBinary(string $s): string {
return q($s); return q($s);
} }
@@ -228,31 +221,29 @@ abstract class SqlDriver {
} }
/** Check if C-style escapes are supported /** Check if C-style escapes are supported
* @return bool
*/ */
function hasCStyleEscapes() { function hasCStyleEscapes(): bool {
return false; return false;
} }
/** Get supported engines /** Get supported engines
* @return list<string> * @return list<string>
*/ */
function engines() { function engines(): array {
return array(); return array();
} }
/** Check whether table supports indexes /** Check whether table supports indexes
* @param TableStatus $table_status result of table_status1() * @param TableStatus $table_status result of table_status1()
* @return bool
*/ */
function supportsIndex(array $table_status) { function supportsIndex(array $table_status): bool {
return !is_view($table_status); return !is_view($table_status);
} }
/** Get defined check constraints /** Get defined check constraints
* @return string[] [$name => $clause] * @return string[] [$name => $clause]
*/ */
function checkConstraints(string $table) { function checkConstraints(string $table): array {
// MariaDB contains CHECK_CONSTRAINTS.TABLE_NAME, MySQL and PostrgreSQL not // MariaDB contains CHECK_CONSTRAINTS.TABLE_NAME, MySQL and PostrgreSQL not
return get_key_vals("SELECT c.CONSTRAINT_NAME, CHECK_CLAUSE return get_key_vals("SELECT c.CONSTRAINT_NAME, CHECK_CLAUSE
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS c FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS c

View File

@@ -9,7 +9,7 @@ namespace Adminer;
* @param string[] $orgtables * @param string[] $orgtables
* @return string[] $orgtables * @return string[] $orgtables
*/ */
function select($result, Db $connection2 = null, array $orgtables = array(), int $limit = 0) { function select($result, Db $connection2 = null, array $orgtables = array(), int $limit = 0): array {
$links = array(); // colno => orgtable - create links from these columns $links = array(); // colno => orgtable - create links from these columns
$indexes = array(); // orgtable => array(column => colno) - primary keys $indexes = array(); // orgtable => array(column => colno) - primary keys
$columns = array(); // orgtable => array(column => ) - not selected columns in primary key $columns = array(); // orgtable => array(column => ) - not selected columns in primary key
@@ -102,7 +102,7 @@ function select($result, Db $connection2 = null, array $orgtables = array(), int
/** Get referencable tables with single column primary key except self /** Get referencable tables with single column primary key except self
* @return array<string, Field> [$table_name => $field] * @return array<string, Field> [$table_name => $field]
*/ */
function referencable_primary(string $self) { function referencable_primary(string $self): array {
$return = array(); // table_name => field $return = array(); // table_name => field
foreach (table_status('', true) as $table_name => $table) { foreach (table_status('', true) as $table_name => $table) {
if ($table_name != $self && fk_support($table)) { if ($table_name != $self && fk_support($table)) {
@@ -122,9 +122,8 @@ function referencable_primary(string $self) {
/** Print SQL <textarea> tag /** Print SQL <textarea> tag
* @param string|list<array{string}> $value * @param string|list<array{string}> $value
* @return void
*/ */
function textarea(string $name, $value, int $rows = 10, int $cols = 80) { function textarea(string $name, $value, int $rows = 10, int $cols = 80): void {
echo "<textarea name='" . h($name) . "' rows='$rows' cols='$cols' class='sqlarea jush-" . JUSH . "' spellcheck='false' wrap='off'>"; echo "<textarea name='" . h($name) . "' rows='$rows' cols='$cols' class='sqlarea jush-" . JUSH . "' spellcheck='false' wrap='off'>";
if (is_array($value)) { if (is_array($value)) {
foreach ($value as $val) { // not implode() to save memory foreach ($value as $val) { // not implode() to save memory
@@ -138,9 +137,8 @@ function textarea(string $name, $value, int $rows = 10, int $cols = 80) {
/** Generate HTML <select> or <input> if $options are empty /** Generate HTML <select> or <input> if $options are empty
* @param string[] $options * @param string[] $options
* @return string
*/ */
function select_input(string $attrs, array $options, string $value = "", string $onchange = "", string $placeholder = "") { function select_input(string $attrs, array $options, string $value = "", string $onchange = "", string $placeholder = ""): string {
$tag = ($options ? "select" : "input"); $tag = ($options ? "select" : "input");
return "<$tag$attrs" . ($options return "<$tag$attrs" . ($options
? "><option value=''>$placeholder" . optionlist($options, $value, true) . "</select>" ? "><option value=''>$placeholder" . optionlist($options, $value, true) . "</select>"
@@ -151,9 +149,8 @@ function select_input(string $attrs, array $options, string $value = "", string
/** Print one row in JSON object /** Print one row in JSON object
* @param string $key or "" to close the object * @param string $key or "" to close the object
* @param string|int $val * @param string|int $val
* @return void
*/ */
function json_row(string $key, $val = null) { function json_row(string $key, $val = null): void {
static $first = true; static $first = true;
if ($first) { if ($first) {
echo "{"; echo "{";
@@ -172,9 +169,8 @@ function json_row(string $key, $val = null) {
* @param list<string> $collations * @param list<string> $collations
* @param string[] $foreign_keys * @param string[] $foreign_keys
* @param list<string> $extra_types extra types to prepend * @param list<string> $extra_types extra types to prepend
* @return void
*/ */
function edit_type(string $key, array $field, array $collations, array $foreign_keys = array(), array $extra_types = array()) { function edit_type(string $key, array $field, array $collations, array $foreign_keys = array(), array $extra_types = array()): void {
global $driver; global $driver;
$type = $field["type"]; $type = $field["type"];
echo "<td><select name='" . h($key) . "[type]' class='type' aria-labelledby='label-type'>"; echo "<td><select name='" . h($key) . "[type]' class='type' aria-labelledby='label-type'>";
@@ -209,7 +205,7 @@ function edit_type(string $key, array $field, array $collations, array $foreign_
/** Get partition info /** Get partition info
* @return array{partition_by:string, partition:string, partitions:string, partition_names:list<string>, partition_values:list<string>} * @return array{partition_by:string, partition:string, partitions:string, partition_names:list<string>, partition_values:list<string>}
*/ */
function get_partitions_info(string $table) { function get_partitions_info(string $table): array {
global $connection; global $connection;
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($table); $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");
@@ -222,9 +218,8 @@ function get_partitions_info(string $table) {
} }
/** Filter length value including enums /** Filter length value including enums
* @return string
*/ */
function process_length(string $length) { function process_length(string $length): string {
global $driver; global $driver;
$enum_length = $driver->enumLength; $enum_length = $driver->enumLength;
return (preg_match("~^\\s*\\(?\\s*$enum_length(?:\\s*,\\s*$enum_length)*+\\s*\\)?\\s*\$~", $length) && preg_match_all("~$enum_length~", $length, $matches) return (preg_match("~^\\s*\\(?\\s*$enum_length(?:\\s*,\\s*$enum_length)*+\\s*\\)?\\s*\$~", $length) && preg_match_all("~$enum_length~", $length, $matches)
@@ -235,9 +230,8 @@ function process_length(string $length) {
/** Create SQL string from field type /** Create SQL string from field type
* @param FieldType $field * @param FieldType $field
* @return string
*/ */
function process_type(array $field, string $collate = "COLLATE") { function process_type(array $field, string $collate = "COLLATE"): string {
global $driver; global $driver;
return " $field[type]" return " $field[type]"
. process_length($field["length"]) . process_length($field["length"])
@@ -251,7 +245,7 @@ function process_type(array $field, string $collate = "COLLATE") {
* @param Field $type_field information about field type * @param Field $type_field information about field type
* @return list<string> ["field", "type", "NULL", "DEFAULT", "ON UPDATE", "COMMENT", "AUTO_INCREMENT"] * @return list<string> ["field", "type", "NULL", "DEFAULT", "ON UPDATE", "COMMENT", "AUTO_INCREMENT"]
*/ */
function process_field(array $field, array $type_field) { function process_field(array $field, array $type_field): array {
// MariaDB exports CURRENT_TIMESTAMP as a function. // MariaDB exports CURRENT_TIMESTAMP as a function.
if ($field["on_update"]) { if ($field["on_update"]) {
$field["on_update"] = str_ireplace("current_timestamp()", "CURRENT_TIMESTAMP", $field["on_update"]); $field["on_update"] = str_ireplace("current_timestamp()", "CURRENT_TIMESTAMP", $field["on_update"]);
@@ -269,9 +263,8 @@ function process_field(array $field, array $type_field) {
/** Get default value clause /** Get default value clause
* @param Field $field * @param Field $field
* @return string
*/ */
function default_value(array $field) { function default_value(array $field): string {
global $driver; global $driver;
$default = $field["default"]; $default = $field["default"];
$generated = $field["generated"]; $generated = $field["generated"];
@@ -307,9 +300,8 @@ function type_class(string $type) {
* @param list<string> $collations * @param list<string> $collations
* @param 'TABLE'|'PROCEDURE' $type * @param 'TABLE'|'PROCEDURE' $type
* @param string[] $foreign_keys * @param string[] $foreign_keys
* @return void
*/ */
function edit_fields(array $fields, array $collations, $type = "TABLE", array $foreign_keys = array()) { function edit_fields(array $fields, array $collations, $type = "TABLE", array $foreign_keys = array()): void {
global $driver; global $driver;
$fields = array_values($fields); $fields = array_values($fields);
$default_class = (($_POST ? $_POST["defaults"] : get_setting("defaults")) ? "" : " class='hidden'"); $default_class = (($_POST ? $_POST["defaults"] : get_setting("defaults")) ? "" : " class='hidden'");
@@ -369,9 +361,8 @@ function edit_fields(array $fields, array $collations, $type = "TABLE", array $f
/** Move fields up and down or add field /** Move fields up and down or add field
* @param Field[] $fields * @param Field[] $fields
* @return bool
*/ */
function process_fields(&array $fields) { function process_fields(&array $fields): bool {
$offset = 0; $offset = 0;
if ($_POST["up"]) { if ($_POST["up"]) {
$last = 0; $last = 0;
@@ -410,9 +401,8 @@ function process_fields(&array $fields) {
/** Callback used in routine() /** Callback used in routine()
* @param list<string> $match * @param list<string> $match
* @return string
*/ */
function normalize_enum(array $match) { function normalize_enum(array $match): string {
$val = $match[0]; $val = $match[0];
return "'" . str_replace("'", "''", addcslashes(stripcslashes(str_replace($val[0] . $val[0], $val[0], substr($val, 1, -1))), '\\')) . "'"; return "'" . str_replace("'", "''", addcslashes(stripcslashes(str_replace($val[0] . $val[0], $val[0], substr($val, 1, -1))), '\\')) . "'";
} }
@@ -444,7 +434,7 @@ function grant(string $grant, array $privileges, string $columns, string $on) {
* @param string $drop_test drop test object query * @param string $drop_test drop test object query
* @return void redirect on success * @return void redirect on success
*/ */
function drop_create(string $drop, string $create, string $drop_created, string $test, string $drop_test, string $location, string $message_drop, string $message_alter, string $message_create, string $old_name, string $new_name) { function drop_create(string $drop, string $create, string $drop_created, string $test, string $drop_test, string $location, string $message_drop, string $message_alter, string $message_create, string $old_name, string $new_name): void {
if ($_POST["drop"]) { if ($_POST["drop"]) {
query_redirect($drop, $location, $message_drop); query_redirect($drop, $location, $message_drop);
} elseif ($old_name == "") { } elseif ($old_name == "") {
@@ -466,9 +456,8 @@ function drop_create(string $drop, string $create, string $drop_created, string
/** Generate SQL query for creating trigger /** Generate SQL query for creating trigger
* @param Trigger $row result of trigger() * @param Trigger $row result of trigger()
* @return string
*/ */
function create_trigger(string $on, array $row) { function create_trigger(string $on, array $row): string {
$timing_event = " $row[Timing] $row[Event]" . (preg_match('~ OF~', $row["Event"]) ? " $row[Of]" : ""); // SQL injection $timing_event = " $row[Timing] $row[Event]" . (preg_match('~ OF~', $row["Event"]) ? " $row[Of]" : ""); // SQL injection
return "CREATE TRIGGER " return "CREATE TRIGGER "
. idf_escape($row["Trigger"]) . idf_escape($row["Trigger"])
@@ -481,9 +470,8 @@ function create_trigger(string $on, array $row) {
/** Generate SQL query for creating routine /** Generate SQL query for creating routine
* @param 'PROCEDURE'|'FUNCTION' $routine * @param 'PROCEDURE'|'FUNCTION' $routine
* @param Routine $row result of routine() * @param Routine $row result of routine()
* @return string
*/ */
function create_routine($routine, array $row) { function create_routine($routine, array $row): string {
global $driver; global $driver;
$set = array(); $set = array();
$fields = (array) $row["fields"]; $fields = (array) $row["fields"];
@@ -504,17 +492,15 @@ function create_routine($routine, array $row) {
} }
/** Remove current user definer from SQL command /** Remove current user definer from SQL command
* @return string
*/ */
function remove_definer(string $query) { function remove_definer(string $query): string {
return preg_replace('~^([A-Z =]+) DEFINER=`' . preg_replace('~@(.*)~', '`@`(%|\1)', logged_user()) . '`~', '\1', $query); //! proper escaping of user return preg_replace('~^([A-Z =]+) DEFINER=`' . preg_replace('~@(.*)~', '`@`(%|\1)', logged_user()) . '`~', '\1', $query); //! proper escaping of user
} }
/** Format foreign key to use in SQL query /** Format foreign key to use in SQL query
* @param ForeignKey $foreign_key * @param ForeignKey $foreign_key
* @return string
*/ */
function format_foreign_key(array $foreign_key) { function format_foreign_key(array $foreign_key): string {
global $driver; global $driver;
$db = $foreign_key["db"]; $db = $foreign_key["db"];
$ns = $foreign_key["ns"]; $ns = $foreign_key["ns"];
@@ -532,7 +518,7 @@ function format_foreign_key(array $foreign_key) {
* @param TmpFile $tmp_file * @param TmpFile $tmp_file
* @return void prints the output * @return void prints the output
*/ */
function tar_file(string $filename, $tmp_file) { function tar_file(string $filename, $tmp_file): void {
$return = pack("a100a8a8a8a12a12", $filename, 644, 0, 0, decoct($tmp_file->size), decoct(time())); $return = pack("a100a8a8a8a12a12", $filename, 644, 0, 0, decoct($tmp_file->size), decoct(time()));
$checksum = 8*32; // space for checksum itself $checksum = 8*32; // space for checksum itself
for ($i=0; $i < strlen($return); $i++) { for ($i=0; $i < strlen($return); $i++) {
@@ -546,9 +532,8 @@ function tar_file(string $filename, $tmp_file) {
} }
/** Get INI bytes value /** Get INI bytes value
* @return int
*/ */
function ini_bytes(string $ini) { function ini_bytes(string $ini): int {
$val = ini_get($ini); $val = ini_get($ini);
switch (strtolower(substr($val, -1))) { switch (strtolower(substr($val, -1))) {
case 'g': case 'g':
@@ -566,7 +551,7 @@ function ini_bytes(string $ini) {
* @param string $text HTML code * @param string $text HTML code
* @return string HTML code * @return string HTML code
*/ */
function doc_link(array $paths, string $text = "<sup>?</sup>") { function doc_link(array $paths, string $text = "<sup>?</sup>"): string {
global $connection; 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 $version = preg_replace('~^(\d\.?\d).*~s', '\1', $server_info); // two most significant digits
@@ -587,7 +572,7 @@ function doc_link(array $paths, string $text = "<sup>?</sup>") {
/** Compute size of database /** Compute size of database
* @return string formatted * @return string formatted
*/ */
function db_size(string $db) { function db_size(string $db): string {
global $connection; global $connection;
if (!$connection->select_db($db)) { if (!$connection->select_db($db)) {
return "?"; return "?";
@@ -600,9 +585,8 @@ function db_size(string $db) {
} }
/** Print SET NAMES if utf8mb4 might be needed /** Print SET NAMES if utf8mb4 might be needed
* @return void
*/ */
function set_utf8mb4(string $create) { function set_utf8mb4(string $create): void {
global $connection; global $connection;
static $set = false; static $set = false;
if (!$set && preg_match('~\butf8mb4~i', $create)) { // possible false positive if (!$set && preg_match('~\butf8mb4~i', $create)) { // possible false positive

View File

@@ -4,9 +4,8 @@ namespace Adminer;
// This file is used both in Adminer and Adminer Editor. // This file is used both in Adminer and Adminer Editor.
/** Get database connection /** Get database connection
* @return Db
*/ */
function connection() { function connection(): Db {
// can be used in customization, $connection is minified // can be used in customization, $connection is minified
global $connection; global $connection;
return $connection; return $connection;
@@ -29,18 +28,16 @@ function driver() {
} }
/** Get Adminer version /** Get Adminer version
* @return string
*/ */
function version() { function version(): string {
global $VERSION; global $VERSION;
return $VERSION; return $VERSION;
} }
/** Unescape database identifier /** Unescape database identifier
* @param string $idf text inside `` * @param string $idf text inside ``
* @return string
*/ */
function idf_unescape(string $idf) { function idf_unescape(string $idf): string {
if (!preg_match('~^[`\'"[]~', $idf)) { if (!preg_match('~^[`\'"[]~', $idf)) {
return $idf; return $idf;
} }
@@ -49,17 +46,15 @@ function idf_unescape(string $idf) {
} }
/** Shortcut for $connection->quote($string) /** Shortcut for $connection->quote($string)
* @return string
*/ */
function q(string $string) { function q(string $string): string {
global $connection; global $connection;
return $connection->quote($string); return $connection->quote($string);
} }
/** Escape string to use inside '' /** Escape string to use inside ''
* @return string
*/ */
function escape_string(string $val) { function escape_string(string $val): string {
return substr(q($val), 1, -1); return substr(q($val), 1, -1);
} }
@@ -75,16 +70,14 @@ function idx(?array $array, $key, $default = null) {
} }
/** Remove non-digits from a string /** Remove non-digits from a string
* @return string
*/ */
function number(string $val) { function number(string $val): string {
return preg_replace('~[^0-9]+~', '', $val); return preg_replace('~[^0-9]+~', '', $val);
} }
/** Get regular expression to match numeric types /** Get regular expression to match numeric types
* @return string
*/ */
function number_type() { function number_type(): string {
return '((?<!o)int(?!er)|numeric|real|float|double|decimal|money)'; // not point, not interval return '((?<!o)int(?!er)|numeric|real|float|double|decimal|money)'; // not point, not interval
} }
@@ -93,7 +86,7 @@ function number_type() {
* @param bool $filter whether to leave values as is * @param bool $filter whether to leave values as is
* @return void modified in place * @return void modified in place
*/ */
function remove_slashes(array $process, bool $filter = false) { function remove_slashes(array $process, bool $filter = false): void {
if (function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) { if (function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) {
while (list($key, $val) = each($process)) { while (list($key, $val) = each($process)) {
foreach ($val as $k => $v) { foreach ($val as $k => $v) {
@@ -110,9 +103,8 @@ function remove_slashes(array $process, bool $filter = false) {
} }
/** Escape or unescape string to use inside form [] /** Escape or unescape string to use inside form []
* @return string
*/ */
function bracket_escape(string $idf, bool $back = false) { function bracket_escape(string $idf, bool $back = false): string {
// escape brackets inside name="x[]" // escape brackets inside name="x[]"
static $trans = array(':' => ':1', ']' => ':2', '[' => ':3', '"' => ':4'); static $trans = array(':' => ':1', ']' => ':2', '[' => ':3', '"' => ':4');
return strtr($idf, ($back ? array_flip($trans) : $trans)); return strtr($idf, ($back ? array_flip($trans) : $trans));
@@ -122,9 +114,8 @@ function bracket_escape(string $idf, bool $back = false) {
* @param string|float $version required version * @param string|float $version required version
* @param string|float $maria_db required MariaDB version * @param string|float $maria_db required MariaDB version
* @param Db $connection2 defaults to $connection * @param Db $connection2 defaults to $connection
* @return bool
*/ */
function min_version($version, $maria_db = "", Db $connection2 = null) { function min_version($version, $maria_db = "", Db $connection2 = null): bool {
global $connection; global $connection;
if (!$connection2) { if (!$connection2) {
$connection2 = $connection; $connection2 = $connection;
@@ -138,24 +129,21 @@ function min_version($version, $maria_db = "", Db $connection2 = null) {
} }
/** Get connection charset /** Get connection charset
* @return string
*/ */
function charset(Db $connection) { function charset(Db $connection): string {
return (min_version("5.5.3", 0, $connection) ? "utf8mb4" : "utf8"); // SHOW CHARSET would require an extra query return (min_version("5.5.3", 0, $connection) ? "utf8mb4" : "utf8"); // SHOW CHARSET would require an extra query
} }
/** Get INI boolean value /** Get INI boolean value
* @return bool
*/ */
function ini_bool(string $ini) { function ini_bool(string $ini): bool {
$val = ini_get($ini); $val = ini_get($ini);
return (preg_match('~^(on|true|yes)$~i', $val) || (int) $val); // boolean values set by php_value are strings return (preg_match('~^(on|true|yes)$~i', $val) || (int) $val); // boolean values set by php_value are strings
} }
/** Check if SID is necessary /** Check if SID is necessary
* @return bool
*/ */
function sid() { function sid(): bool {
static $return; static $return;
if ($return === null) { // restart_session() defines SID if ($return === null) { // restart_session() defines SID
$return = (SID && !($_COOKIE && ini_bool("session.use_cookies"))); // $_COOKIE - don't pass SID with permanent login $return = (SID && !($_COOKIE && ini_bool("session.use_cookies"))); // $_COOKIE - don't pass SID with permanent login
@@ -164,9 +152,8 @@ function sid() {
} }
/** Set password to session /** Set password to session
* @return void
*/ */
function set_password(string $vendor, string $server, string $username, ?string $password) { function set_password(string $vendor, string $server, string $username, ?string $password): void {
$_SESSION["pwds"][$vendor][$server][$username] = ($_COOKIE["adminer_key"] && is_string($password) $_SESSION["pwds"][$vendor][$server][$username] = ($_COOKIE["adminer_key"] && is_string($password)
? array(encrypt_string($password, $_COOKIE["adminer_key"])) ? array(encrypt_string($password, $_COOKIE["adminer_key"]))
: $password : $password
@@ -190,7 +177,7 @@ function get_password() {
/** Get single value from database /** Get single value from database
* @return string or false if error * @return string or false if error
*/ */
function get_val(string $query, int $field = 0) { function get_val(string $query, int $field = 0): string {
global $connection; global $connection;
return $connection->result($query, $field); return $connection->result($query, $field);
} }
@@ -199,7 +186,7 @@ function get_val(string $query, int $field = 0) {
* @param mixed $column * @param mixed $column
* @return list<string> * @return list<string>
*/ */
function get_vals(string $query, $column = 0) { function get_vals(string $query, $column = 0): array {
global $connection; global $connection;
$return = array(); $return = array();
$result = $connection->query($query); $result = $connection->query($query);
@@ -214,7 +201,7 @@ function get_vals(string $query, $column = 0) {
/** Get keys from first column and values from second /** Get keys from first column and values from second
* @return string[] * @return string[]
*/ */
function get_key_vals(string $query, Db $connection2 = null, bool $set_keys = true) { function get_key_vals(string $query, Db $connection2 = null, bool $set_keys = true): array {
global $connection; global $connection;
if (!is_object($connection2)) { if (!is_object($connection2)) {
$connection2 = $connection; $connection2 = $connection;
@@ -236,7 +223,7 @@ function get_key_vals(string $query, Db $connection2 = null, bool $set_keys = tr
/** Get all rows of result /** Get all rows of result
* @return list<string[]> of associative arrays * @return list<string[]> of associative arrays
*/ */
function get_rows(string $query, Db $connection2 = null, string $error = "<p class='error'>") { function get_rows(string $query, Db $connection2 = null, string $error = "<p class='error'>"): array {
global $connection; global $connection;
$conn = (is_object($connection2) ? $connection2 : $connection); $conn = (is_object($connection2) ? $connection2 : $connection);
$return = array(); $return = array();
@@ -272,9 +259,8 @@ function unique_array(array $row, array $indexes) {
} }
/** Escape column key used in where() /** Escape column key used in where()
* @return string
*/ */
function escape_key(string $key) { function escape_key(string $key): string {
if (preg_match('(^([\w(]+)(' . str_replace("_", ".*", preg_quote(idf_escape("_"))) . ')([ \w)]+)$)', $key, $match)) { //! columns looking like functions if (preg_match('(^([\w(]+)(' . str_replace("_", ".*", preg_quote(idf_escape("_"))) . ')([ \w)]+)$)', $key, $match)) { //! columns looking like functions
return $match[1] . idf_escape(idf_unescape($match[2])) . $match[3]; //! SQL injection return $match[1] . idf_escape(idf_unescape($match[2])) . $match[3]; //! SQL injection
} }
@@ -284,9 +270,8 @@ function escape_key(string $key) {
/** Create SQL condition from parsed query string /** Create SQL condition from parsed query string
* @param array{where:string[], null:list<string>} $where parsed query string * @param array{where:string[], null:list<string>} $where parsed query string
* @param Field[] $fields * @param Field[] $fields
* @return string
*/ */
function where(array $where, array $fields = array()) { function where(array $where, array $fields = array()): string {
global $connection; global $connection;
$return = array(); $return = array();
foreach ((array) $where["where"] as $key => $val) { foreach ((array) $where["where"] as $key => $val) {
@@ -312,9 +297,8 @@ function where(array $where, array $fields = array()) {
/** Create SQL condition from query string /** Create SQL condition from query string
* @param Field[] $fields * @param Field[] $fields
* @return string
*/ */
function where_check(string $val, array $fields = array()) { function where_check(string $val, array $fields = array()): string {
parse_str($val, $check); parse_str($val, $check);
remove_slashes(array(&$check)); remove_slashes(array(&$check));
return where($check, $fields); return where($check, $fields);
@@ -323,9 +307,8 @@ function where_check(string $val, array $fields = array()) {
/** Create query string where condition from value /** Create query string where condition from value
* @param int $i condition order * @param int $i condition order
* @param string $column column identifier * @param string $column column identifier
* @return string
*/ */
function where_link(int $i, string $column, string $value, string $operator = "=") { function where_link(int $i, string $column, string $value, string $operator = "="): string {
return "&where%5B$i%5D%5Bcol%5D=" . urlencode($column) . "&where%5B$i%5D%5Bop%5D=" . urlencode(($value !== null ? $operator : "IS NULL")) . "&where%5B$i%5D%5Bval%5D=" . urlencode($value); return "&where%5B$i%5D%5Bcol%5D=" . urlencode($column) . "&where%5B$i%5D%5Bop%5D=" . urlencode(($value !== null ? $operator : "IS NULL")) . "&where%5B$i%5D%5Bval%5D=" . urlencode($value);
} }
@@ -333,9 +316,8 @@ function where_link(int $i, string $column, string $value, string $operator = "=
* @param mixed[] $columns only keys are used * @param mixed[] $columns only keys are used
* @param Field[] $fields * @param Field[] $fields
* @param list<string> $select * @param list<string> $select
* @return string
*/ */
function convert_fields(array $columns, array $fields, array $select = array()) { function convert_fields(array $columns, array $fields, array $select = array()): string {
$return = ""; $return = "";
foreach ($columns as $key => $val) { foreach ($columns as $key => $val) {
if ($select && !in_array(idf_escape($key), $select)) { if ($select && !in_array(idf_escape($key), $select)) {
@@ -351,9 +333,8 @@ function convert_fields(array $columns, array $fields, array $select = array())
/** Set cookie valid on current path /** Set cookie valid on current path
* @param int $lifetime number of seconds, 0 for session cookie, 2592000 - 30 days * @param int $lifetime number of seconds, 0 for session cookie, 2592000 - 30 days
* @return void
*/ */
function cookie(string $name, string $value, int $lifetime = 2592000) { function cookie(string $name, string $value, int $lifetime = 2592000): void {
global $HTTPS; global $HTTPS;
header( header(
"Set-Cookie: $name=" . urlencode($value) "Set-Cookie: $name=" . urlencode($value)
@@ -368,7 +349,7 @@ function cookie(string $name, string $value, int $lifetime = 2592000) {
/** Get settings stored in a cookie /** Get settings stored in a cookie
* @return mixed[] * @return mixed[]
*/ */
function get_settings(string $cookie) { function get_settings(string $cookie): array {
parse_str($_COOKIE[$cookie], $settings); parse_str($_COOKIE[$cookie], $settings);
return $settings; return $settings;
} }
@@ -383,25 +364,22 @@ function get_setting(string $key, string $cookie = "adminer_settings") {
/** Store settings to a cookie /** Store settings to a cookie
* @param mixed[] $settings * @param mixed[] $settings
* @return void
*/ */
function save_settings(array $settings, string $cookie = "adminer_settings") { function save_settings(array $settings, string $cookie = "adminer_settings"): void {
cookie($cookie, http_build_query($settings + get_settings($cookie))); cookie($cookie, http_build_query($settings + get_settings($cookie)));
} }
/** Restart stopped session /** Restart stopped session
* @return void
*/ */
function restart_session() { function restart_session(): void {
if (!ini_bool("session.use_cookies") && (!function_exists('session_status') || session_status() == 1)) { // 1 - PHP_SESSION_NONE, session_status() available since PHP 5.4 if (!ini_bool("session.use_cookies") && (!function_exists('session_status') || session_status() == 1)) { // 1 - PHP_SESSION_NONE, session_status() available since PHP 5.4
session_start(); session_start();
} }
} }
/** Stop session if possible /** Stop session if possible
* @return void
*/ */
function stop_session(bool $force = false) { function stop_session(bool $force = false): void {
$use_cookies = ini_bool("session.use_cookies"); $use_cookies = ini_bool("session.use_cookies");
if (!$use_cookies || $force) { if (!$use_cookies || $force) {
session_write_close(); // improves concurrency if a user opens several pages at once, may be restarted later session_write_close(); // improves concurrency if a user opens several pages at once, may be restarted later
@@ -427,9 +405,8 @@ function set_session(string $key, $val) {
} }
/** Get authenticated URL /** Get authenticated URL
* @return string
*/ */
function auth_url(string $vendor, string $server, string $username, string $db = null) { function auth_url(string $vendor, string $server, string $username, string $db = null): string {
global $drivers; global $drivers;
$uri = remove_from_uri(implode("|", array_keys($drivers)) $uri = remove_from_uri(implode("|", array_keys($drivers))
. "|username|ext|" . "|username|ext|"
@@ -449,17 +426,15 @@ function auth_url(string $vendor, string $server, string $username, string $db =
} }
/** Find whether it is an AJAX request /** Find whether it is an AJAX request
* @return bool
*/ */
function is_ajax() { function is_ajax(): bool {
return ($_SERVER["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest"); return ($_SERVER["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest");
} }
/** Send Location header and exit /** Send Location header and exit
* @param string $location null to only set a message * @param string $location null to only set a message
* @return void
*/ */
function redirect(string $location, string $message = null) { function redirect(string $location, string $message = null): void {
if ($message !== null) { if ($message !== null) {
restart_session(); restart_session();
$_SESSION["messages"][preg_replace('~^[^?]*~', '', ($location !== null ? $location : $_SERVER["REQUEST_URI"]))][] = $message; $_SESSION["messages"][preg_replace('~^[^?]*~', '', ($location !== null ? $location : $_SERVER["REQUEST_URI"]))][] = $message;
@@ -474,9 +449,8 @@ function redirect(string $location, string $message = null) {
} }
/** Execute query and redirect if successful /** Execute query and redirect if successful
* @return bool
*/ */
function query_redirect(string $query, string $location, string $message, bool $redirect = true, bool $execute = true, bool $failed = false, string $time = "") { function query_redirect(string $query, string $location, string $message, bool $redirect = true, bool $execute = true, bool $failed = false, string $time = ""): bool {
global $connection, $error, $adminer; global $connection, $error, $adminer;
if ($execute) { if ($execute) {
$start = microtime(true); $start = microtime(true);
@@ -518,9 +492,8 @@ function queries(string $query) {
/** Apply command to all array items /** Apply command to all array items
* @param list<string> $tables * @param list<string> $tables
* @param callable(string):string $escape * @param callable(string):string $escape
* @return bool
*/ */
function apply_queries(string $query, array $tables, callable $escape = 'Adminer\table') { function apply_queries(string $query, array $tables, callable $escape = 'Adminer\table'): bool {
foreach ($tables as $table) { foreach ($tables as $table) {
if (!queries("$query " . $escape($table))) { if (!queries("$query " . $escape($table))) {
return false; return false;
@@ -530,9 +503,8 @@ function apply_queries(string $query, array $tables, callable $escape = 'Adminer
} }
/** Redirect by remembered queries /** Redirect by remembered queries
* @return bool
*/ */
function queries_redirect(string $location, string $message, bool $redirect) { function queries_redirect(string $location, string $message, bool $redirect): bool {
$queries = implode("\n", Queries::$queries); $queries = implode("\n", Queries::$queries);
$time = format_time(Queries::$start); $time = format_time(Queries::$start);
return query_redirect($queries, $location, $message, $redirect, false, !$redirect, $time); return query_redirect($queries, $location, $message, $redirect, false, !$redirect, $time);
@@ -542,21 +514,19 @@ function queries_redirect(string $location, string $message, bool $redirect) {
* @param float $start output of microtime(true) * @param float $start output of microtime(true)
* @return string HTML code * @return string HTML code
*/ */
function format_time(float $start) { function format_time(float $start): string {
return lang('%.3f s', max(0, microtime(true) - $start)); return lang('%.3f s', max(0, microtime(true) - $start));
} }
/** Get relative REQUEST_URI /** Get relative REQUEST_URI
* @return string
*/ */
function relative_uri() { function relative_uri(): string {
return str_replace(":", "%3a", preg_replace('~^[^?]*/([^?]*)~', '\1', $_SERVER["REQUEST_URI"])); return str_replace(":", "%3a", preg_replace('~^[^?]*/([^?]*)~', '\1', $_SERVER["REQUEST_URI"]));
} }
/** Remove parameter from query string /** Remove parameter from query string
* @return string
*/ */
function remove_from_uri(string $param = "") { function remove_from_uri(string $param = ""): string {
return substr(preg_replace("~(?<=[?&])($param" . (SID ? "" : "|" . session_name()) . ")=[^&]*&~", '', relative_uri() . "&"), 0, -1); return substr(preg_replace("~(?<=[?&])($param" . (SID ? "" : "|" . session_name()) . ")=[^&]*&~", '', relative_uri() . "&"), 0, -1);
} }
@@ -600,25 +570,22 @@ function get_file(string $key, bool $decompress = false, string $delimiter = "")
} }
/** Determine upload error /** Determine upload error
* @return string
*/ */
function upload_error(int $error) { function upload_error(int $error): string {
$max_size = ($error == UPLOAD_ERR_INI_SIZE ? ini_get("upload_max_filesize") : 0); // post_max_size is checked in index.php $max_size = ($error == UPLOAD_ERR_INI_SIZE ? ini_get("upload_max_filesize") : 0); // post_max_size is checked in index.php
return ($error ? lang('Unable to upload a file.') . ($max_size ? " " . lang('Maximum allowed file size is %sB.', $max_size) : "") : lang('File does not exist.')); return ($error ? lang('Unable to upload a file.') . ($max_size ? " " . lang('Maximum allowed file size is %sB.', $max_size) : "") : lang('File does not exist.'));
} }
/** Create repeat pattern for preg /** Create repeat pattern for preg
* @return string
*/ */
function repeat_pattern(string $pattern, int $length) { function repeat_pattern(string $pattern, int $length): string {
// fix for Compilation failed: number too big in {} quantifier // fix for Compilation failed: number too big in {} quantifier
return str_repeat("$pattern{0,65535}", $length / 65535) . "$pattern{0," . ($length % 65535) . "}"; // can create {0,0} which is OK return str_repeat("$pattern{0,65535}", $length / 65535) . "$pattern{0," . ($length % 65535) . "}"; // can create {0,0} which is OK
} }
/** Check whether the string is in UTF-8 /** Check whether the string is in UTF-8
* @return bool
*/ */
function is_utf8(string $val) { function is_utf8(string $val): bool {
// don't print control chars except \t\r\n // don't print control chars except \t\r\n
return (preg_match('~~u', $val) && !preg_match('~[\0-\x8\xB\xC\xE-\x1F]~', $val)); return (preg_match('~~u', $val) && !preg_match('~[\0-\x8\xB\xC\xE-\x1F]~', $val));
} }
@@ -626,7 +593,7 @@ function is_utf8(string $val) {
/** Shorten UTF-8 string /** Shorten UTF-8 string
* @return string escaped string with appended ... * @return string escaped string with appended ...
*/ */
function shorten_utf8(string $string, int $length = 80, string $suffix = "") { function shorten_utf8(string $string, int $length = 80, string $suffix = ""): string {
if (!preg_match("(^(" . repeat_pattern("[\t\r\n -\x{10FFFF}]", $length) . ")($)?)u", $string, $match)) { // ~s causes trash in $match[2] under some PHP versions, (.|\n) is slow if (!preg_match("(^(" . repeat_pattern("[\t\r\n -\x{10FFFF}]", $length) . ")($)?)u", $string, $match)) { // ~s causes trash in $match[2] under some PHP versions, (.|\n) is slow
preg_match("(^(" . repeat_pattern("[\t\r\n -~]", $length) . ")($)?)", $string, $match); preg_match("(^(" . repeat_pattern("[\t\r\n -~]", $length) . ")($)?)", $string, $match);
} }
@@ -635,16 +602,14 @@ function shorten_utf8(string $string, int $length = 80, string $suffix = "") {
/** Format decimal number /** Format decimal number
* @param float|numeric-string $val * @param float|numeric-string $val
* @return string
*/ */
function format_number($val) { function format_number($val): string {
return strtr(number_format($val, 0, ".", lang(',')), preg_split('~~u', lang('0123456789'), -1, PREG_SPLIT_NO_EMPTY)); return strtr(number_format($val, 0, ".", lang(',')), preg_split('~~u', lang('0123456789'), -1, PREG_SPLIT_NO_EMPTY));
} }
/** Generate friendly URL /** Generate friendly URL
* @return string
*/ */
function friendly_url(string $val) { function friendly_url(string $val): string {
// used for blobs and export // used for blobs and export
return preg_replace('~\W~i', '-', $val); return preg_replace('~\W~i', '-', $val);
} }
@@ -652,7 +617,7 @@ function friendly_url(string $val) {
/** Get status of a single table and fall back to name on error /** Get status of a single table and fall back to name on error
* @return TableStatus one element from table_status() * @return TableStatus one element from table_status()
*/ */
function table_status1(string $table, bool $fast = false) { function table_status1(string $table, bool $fast = false): array {
$return = table_status($table, $fast); $return = table_status($table, $fast);
return ($return ? reset($return) : array("Name" => $table)); return ($return ? reset($return) : array("Name" => $table));
} }
@@ -660,7 +625,7 @@ function table_status1(string $table, bool $fast = false) {
/** Find out foreign keys for each column /** Find out foreign keys for each column
* @return list<ForeignKey>[] [$col => []] * @return list<ForeignKey>[] [$col => []]
*/ */
function column_foreign_keys(string $table) { function column_foreign_keys(string $table): array {
global $adminer; global $adminer;
$return = array(); $return = array();
foreach ($adminer->foreignKeys($table) as $foreign_key) { foreach ($adminer->foreignKeys($table) as $foreign_key) {
@@ -674,7 +639,7 @@ function column_foreign_keys(string $table) {
/** Compute fields() from $_POST edit data /** Compute fields() from $_POST edit data
* @return Field[] same as fields() * @return Field[] same as fields()
*/ */
function fields_from_edit() { // used by Mongo and SimpleDB function fields_from_edit(): array { // used by Mongo and SimpleDB
global $driver; global $driver;
$return = array(); $return = array();
foreach ((array) $_POST["field_keys"] as $key => $val) { foreach ((array) $_POST["field_keys"] as $key => $val) {
@@ -699,7 +664,7 @@ function fields_from_edit() { // used by Mongo and SimpleDB
/** Send headers for export /** Send headers for export
* @return string extension * @return string extension
*/ */
function dump_headers(string $identifier, bool $multi_table = false) { function dump_headers(string $identifier, bool $multi_table = false): string {
global $adminer; global $adminer;
$return = $adminer->dumpHeaders($identifier, $multi_table); $return = $adminer->dumpHeaders($identifier, $multi_table);
$output = $_POST["output"]; $output = $_POST["output"];
@@ -717,9 +682,8 @@ function dump_headers(string $identifier, bool $multi_table = false) {
/** Print CSV row /** Print CSV row
* @param string[] $row * @param string[] $row
* @return void
*/ */
function dump_csv(array $row) { function dump_csv(array $row): void {
foreach ($row as $key => $val) { foreach ($row as $key => $val) {
if (preg_match('~["\n,;\t]|^0|\.\d*0$~', $val) || $val === "") { if (preg_match('~["\n,;\t]|^0|\.\d*0$~', $val) || $val === "") {
$row[$key] = '"' . str_replace('"', '""', $val) . '"'; $row[$key] = '"' . str_replace('"', '""', $val) . '"';
@@ -730,16 +694,14 @@ function dump_csv(array $row) {
/** Apply SQL function /** Apply SQL function
* @param string $column escaped column identifier * @param string $column escaped column identifier
* @return string
*/ */
function apply_sql_function(string $function, string $column) { function apply_sql_function(string $function, string $column): string {
return ($function ? ($function == "unixepoch" ? "DATETIME($column, '$function')" : ($function == "count distinct" ? "COUNT(DISTINCT " : strtoupper("$function(")) . "$column)") : $column); return ($function ? ($function == "unixepoch" ? "DATETIME($column, '$function')" : ($function == "count distinct" ? "COUNT(DISTINCT " : strtoupper("$function(")) . "$column)") : $column);
} }
/** Get path of the temporary directory /** Get path of the temporary directory
* @return string
*/ */
function get_temp_dir() { function get_temp_dir(): string {
$return = ini_get("upload_tmp_dir"); // session_save_path() may contain other storage path $return = ini_get("upload_tmp_dir"); // session_save_path() may contain other storage path
if (!$return) { if (!$return) {
if (function_exists('sys_get_temp_dir')) { if (function_exists('sys_get_temp_dir')) {
@@ -776,9 +738,8 @@ function file_open_lock(string $filename) {
} }
/** Write and unlock a file /** Write and unlock a file
* @return void
*/ */
function file_write_unlock(resource $fp, string $data) { function file_write_unlock(resource $fp, string $data): void {
rewind($fp); rewind($fp);
fwrite($fp, $data); fwrite($fp, $data);
ftruncate($fp, strlen($data)); ftruncate($fp, strlen($data));
@@ -786,9 +747,8 @@ function file_write_unlock(resource $fp, string $data) {
} }
/** Unlock and close a file /** Unlock and close a file
* @return void
*/ */
function file_unlock(resource $fp) { function file_unlock(resource $fp): void {
flock($fp, LOCK_UN); flock($fp, LOCK_UN);
fclose($fp); fclose($fp);
} }
@@ -827,7 +787,7 @@ function password_file(bool $create) {
/** Get a random string /** Get a random string
* @return string 32 hexadecimal characters * @return string 32 hexadecimal characters
*/ */
function rand_string() { function rand_string(): string {
return md5(uniqid(strval(mt_rand()), true)); return md5(uniqid(strval(mt_rand()), true));
} }
@@ -836,7 +796,7 @@ function rand_string() {
* @param Field $field * @param Field $field
* @return string HTML * @return string HTML
*/ */
function select_value($val, string $link, array $field, int $text_length) { function select_value($val, string $link, array $field, int $text_length): string {
global $adminer; global $adminer;
if (is_array($val)) { if (is_array($val)) {
$return = ""; $return = "";
@@ -873,9 +833,8 @@ function select_value($val, string $link, array $field, int $text_length) {
} }
/** Check whether the string is e-mail address /** Check whether the string is e-mail address
* @return bool
*/ */
function is_mail(?string $email) { function is_mail(?string $email): bool {
$atom = '[-a-z0-9!#$%&\'*+/=?^_`{|}~]'; // characters of local-name $atom = '[-a-z0-9!#$%&\'*+/=?^_`{|}~]'; // characters of local-name
$domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component $domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component
$pattern = "$atom+(\\.$atom+)*@($domain?\\.)+$domain"; $pattern = "$atom+(\\.$atom+)*@($domain?\\.)+$domain";
@@ -883,27 +842,24 @@ function is_mail(?string $email) {
} }
/** Check whether the string is URL address /** Check whether the string is URL address
* @return bool
*/ */
function is_url(string $string) { function is_url(string $string): bool {
$domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component //! IDN $domain = '[a-z0-9]([-a-z0-9]{0,61}[a-z0-9])'; // one domain component //! IDN
return preg_match("~^(https?)://($domain?\\.)+$domain(:\\d+)?(/.*)?(\\?.*)?(#.*)?\$~i", $string); //! restrict path, query and fragment characters return preg_match("~^(https?)://($domain?\\.)+$domain(:\\d+)?(/.*)?(\\?.*)?(#.*)?\$~i", $string); //! restrict path, query and fragment characters
} }
/** Check if field should be shortened /** Check if field should be shortened
* @param Field $field * @param Field $field
* @return bool
*/ */
function is_shortable(array $field) { function is_shortable(array $field): bool {
return preg_match('~char|text|json|lob|geometry|point|linestring|polygon|string|bytea~', $field["type"]); return preg_match('~char|text|json|lob|geometry|point|linestring|polygon|string|bytea~', $field["type"]);
} }
/** Get query to compute number of found rows /** Get query to compute number of found rows
* @param list<string> $where * @param list<string> $where
* @param list<string> $group * @param list<string> $group
* @return string
*/ */
function count_rows(string $table, array $where, bool $is_group, array $group) { function count_rows(string $table, array $where, bool $is_group, array $group): string {
$query = " FROM " . table($table) . ($where ? " WHERE " . implode(" AND ", $where) : ""); $query = " FROM " . table($table) . ($where ? " WHERE " . implode(" AND ", $where) : "");
return ($is_group && (JUSH == "sql" || count($group) == 1) return ($is_group && (JUSH == "sql" || count($group) == 1)
? "SELECT COUNT(DISTINCT " . implode(", ", $group) . ")$query" ? "SELECT COUNT(DISTINCT " . implode(", ", $group) . ")$query"
@@ -914,7 +870,7 @@ function count_rows(string $table, array $where, bool $is_group, array $group) {
/** Run query which can be killed by AJAX call after timing out /** Run query which can be killed by AJAX call after timing out
* @return string[] * @return string[]
*/ */
function slow_query(string $query) { function slow_query(string $query): array {
global $adminer, $token, $driver; global $adminer, $token, $driver;
$db = $adminer->database(); $db = $adminer->database();
$timeout = $adminer->queryTimeout(); $timeout = $adminer->queryTimeout();
@@ -939,26 +895,23 @@ function slow_query(string $query) {
} }
/** Generate BREACH resistant CSRF token /** Generate BREACH resistant CSRF token
* @return string
*/ */
function get_token() { function get_token(): string {
$rand = rand(1, 1e6); $rand = rand(1, 1e6);
return ($rand ^ $_SESSION["token"]) . ":$rand"; return ($rand ^ $_SESSION["token"]) . ":$rand";
} }
/** Verify if supplied CSRF token is valid /** Verify if supplied CSRF token is valid
* @return bool
*/ */
function verify_token() { function verify_token(): bool {
list($token, $rand) = explode(":", $_POST["token"]); list($token, $rand) = explode(":", $_POST["token"]);
return ($rand ^ $_SESSION["token"]) == $token; return ($rand ^ $_SESSION["token"]) == $token;
} }
// used in compiled version // used in compiled version
/** /**
* @return string
*/ */
function lzw_decompress(string $binary) { function lzw_decompress(string $binary): string {
// convert binary string to codes // convert binary string to codes
$dictionary_count = 256; $dictionary_count = 256;
$bits = 8; // ceil(log($dictionary_count, 2)) $bits = 8; // ceil(log($dictionary_count, 2))

View File

@@ -2,23 +2,20 @@
namespace Adminer; namespace Adminer;
/** Return <script> element /** Return <script> element
* @return string
*/ */
function script(string $source, string $trailing = "\n") { function script(string $source, string $trailing = "\n"): string {
return "<script" . nonce() . ">$source</script>$trailing"; return "<script" . nonce() . ">$source</script>$trailing";
} }
/** Return <script src> element /** Return <script src> element
* @return string
*/ */
function script_src(string $url) { function script_src(string $url): string {
return "<script src='" . h($url) . "'" . nonce() . "></script>\n"; return "<script src='" . h($url) . "'" . nonce() . "></script>\n";
} }
/** Get a nonce="" attribute with CSP nonce /** Get a nonce="" attribute with CSP nonce
* @return string
*/ */
function nonce() { function nonce(): string {
return ' nonce="' . get_nonce() . '"'; return ' nonce="' . get_nonce() . '"';
} }
@@ -26,7 +23,7 @@ function nonce() {
* @param string|int $value * @param string|int $value
* @return string HTML * @return string HTML
*/ */
function input_hidden(string $name, $value = "") { function input_hidden(string $name, $value = ""): string {
return "<input type='hidden' name='" . h($name) . "' value='" . h($value) . "'>\n"; return "<input type='hidden' name='" . h($name) . "' value='" . h($value) . "'>\n";
} }
@@ -34,37 +31,33 @@ function input_hidden(string $name, $value = "") {
* @param string $special token to use instead of global $token * @param string $special token to use instead of global $token
* @return string HTML * @return string HTML
*/ */
function input_token(string $special = "") { function input_token(string $special = ""): string {
global $token; global $token;
return input_hidden("token", ($special ?: $token)); return input_hidden("token", ($special ?: $token));
} }
/** Get a target="_blank" attribute /** Get a target="_blank" attribute
* @return string
*/ */
function target_blank() { function target_blank(): string {
return ' target="_blank" rel="noreferrer noopener"'; return ' target="_blank" rel="noreferrer noopener"';
} }
/** Escape for HTML /** Escape for HTML
* @return string
*/ */
function h(string $string) { function h(string $string): string {
return str_replace("\0", "&#0;", htmlspecialchars($string, ENT_QUOTES, 'utf-8')); return str_replace("\0", "&#0;", htmlspecialchars($string, ENT_QUOTES, 'utf-8'));
} }
/** Convert \n to <br> /** Convert \n to <br>
* @return string
*/ */
function nl_br(string $string) { function nl_br(string $string): string {
return str_replace("\n", "<br>", $string); // nl2br() uses XHTML before PHP 5.3 return str_replace("\n", "<br>", $string); // nl2br() uses XHTML before PHP 5.3
} }
/** Generate HTML checkbox /** Generate HTML checkbox
* @param string|int $value * @param string|int $value
* @return string
*/ */
function checkbox(string $name, $value, bool $checked, string $label = "", string $onclick = "", string $class = "", string $labelled_by = "") { function checkbox(string $name, $value, bool $checked, string $label = "", string $onclick = "", string $class = "", string $labelled_by = ""): string {
$return = "<input type='checkbox' name='$name' value='" . h($value) . "'" $return = "<input type='checkbox' name='$name' value='" . h($value) . "'"
. ($checked ? " checked" : "") . ($checked ? " checked" : "")
. ($labelled_by ? " aria-labelledby='$labelled_by'" : "") . ($labelled_by ? " aria-labelledby='$labelled_by'" : "")
@@ -78,9 +71,8 @@ function checkbox(string $name, $value, bool $checked, string $label = "", strin
* @param string[]|string[][] $options array of strings or arrays (creates optgroup) * @param string[]|string[][] $options array of strings or arrays (creates optgroup)
* @param mixed $selected * @param mixed $selected
* @param bool $use_keys always use array keys for value="", otherwise only string keys are used * @param bool $use_keys always use array keys for value="", otherwise only string keys are used
* @return string
*/ */
function optionlist($options, $selected = null, bool $use_keys = false) { function optionlist($options, $selected = null, bool $use_keys = false): string {
$return = ""; $return = "";
foreach ($options as $k => $v) { foreach ($options as $k => $v) {
$opts = array($k => $v); $opts = array($k => $v);
@@ -104,9 +96,8 @@ function optionlist($options, $selected = null, bool $use_keys = false) {
/** Generate HTML <select> /** Generate HTML <select>
* @param string[] $options * @param string[] $options
* @return string
*/ */
function html_select(string $name, array $options, string $value = "", string $onchange = "", string $labelled_by = "") { function html_select(string $name, array $options, string $value = "", string $onchange = "", string $labelled_by = ""): string {
return "<select name='" . h($name) . "'" return "<select name='" . h($name) . "'"
. ($labelled_by ? " aria-labelledby='$labelled_by'" : "") . ($labelled_by ? " aria-labelledby='$labelled_by'" : "")
. ">" . optionlist($options, $value) . "</select>" . ">" . optionlist($options, $value) . "</select>"
@@ -116,9 +107,8 @@ function html_select(string $name, array $options, string $value = "", string $o
/** Generate HTML radio list /** Generate HTML radio list
* @param string[] $options * @param string[] $options
* @return string
*/ */
function html_radios(string $name, array $options, string $value = "") { function html_radios(string $name, array $options, string $value = ""): string {
$return = ""; $return = "";
foreach ($options as $key => $val) { foreach ($options as $key => $val) {
$return .= "<label><input type='radio' name='" . h($name) . "' value='" . h($key) . "'" . ($key == $value ? " checked" : "") . ">" . h($val) . "</label>"; $return .= "<label><input type='radio' name='" . h($name) . "' value='" . h($key) . "'" . ($key == $value ? " checked" : "") . ">" . h($val) . "</label>";
@@ -127,16 +117,14 @@ function html_radios(string $name, array $options, string $value = "") {
} }
/** Get onclick confirmation /** Get onclick confirmation
* @return string
*/ */
function confirm(string $message = "", string $selector = "qsl('input')") { function confirm(string $message = "", string $selector = "qsl('input')"): string {
return script("$selector.onclick = () => confirm('" . ($message ? js_escape($message) : lang('Are you sure?')) . "');", ""); return script("$selector.onclick = () => confirm('" . ($message ? js_escape($message) : lang('Are you sure?')) . "');", "");
} }
/** Print header for hidden fieldset (close by </div></fieldset>) /** Print header for hidden fieldset (close by </div></fieldset>)
* @return void
*/ */
function print_fieldset(string $id, string $legend, bool $visible = false) { function print_fieldset(string $id, string $legend, bool $visible = false): void {
echo "<fieldset><legend>"; echo "<fieldset><legend>";
echo "<a href='#fieldset-$id'>$legend</a>"; echo "<a href='#fieldset-$id'>$legend</a>";
echo script("qsl('a').onclick = partial(toggle, 'fieldset-$id');", ""); echo script("qsl('a').onclick = partial(toggle, 'fieldset-$id');", "");
@@ -145,23 +133,20 @@ function print_fieldset(string $id, string $legend, bool $visible = false) {
} }
/** Return class='active' if $bold is true /** Return class='active' if $bold is true
* @return string
*/ */
function bold(bool $bold, string $class = "") { function bold(bool $bold, string $class = ""): string {
return ($bold ? " class='active $class'" : ($class ? " class='$class'" : "")); return ($bold ? " class='active $class'" : ($class ? " class='$class'" : ""));
} }
/** Escape string for JavaScript apostrophes /** Escape string for JavaScript apostrophes
* @return string
*/ */
function js_escape(string $string) { function js_escape(string $string): string {
return addcslashes($string, "\r\n'\\/"); // slash for <script> return addcslashes($string, "\r\n'\\/"); // slash for <script>
} }
/** Generate page number for pagination /** Generate page number for pagination
* @return string
*/ */
function pagination(int $page, int $current) { function pagination(int $page, int $current): string {
return " " . ($page == $current return " " . ($page == $current
? $page + 1 ? $page + 1
: '<a href="' . h(remove_from_uri("page") . ($page ? "&page=$page" . ($_GET["next"] ? "&next=" . urlencode($_GET["next"]) : "") : "")) . '">' . ($page + 1) . "</a>" : '<a href="' . h(remove_from_uri("page") . ($page ? "&page=$page" . ($_GET["next"] ? "&next=" . urlencode($_GET["next"]) : "") : "")) . '">' . ($page + 1) . "</a>"
@@ -171,9 +156,8 @@ function pagination(int $page, int $current) {
/** Print hidden fields /** Print hidden fields
* @param mixed[] $process * @param mixed[] $process
* @param list<string> $ignore * @param list<string> $ignore
* @return bool
*/ */
function hidden_fields(array $process, array $ignore = array(), string $prefix = '') { function hidden_fields(array $process, array $ignore = array(), string $prefix = ''): bool {
$return = false; $return = false;
foreach ($process as $key => $val) { foreach ($process as $key => $val) {
if (!in_array($key, $ignore)) { if (!in_array($key, $ignore)) {
@@ -189,9 +173,8 @@ function hidden_fields(array $process, array $ignore = array(), string $prefix =
} }
/** Print hidden fields for GET forms /** Print hidden fields for GET forms
* @return void
*/ */
function hidden_fields_get() { function hidden_fields_get(): void {
echo (sid() ? input_hidden(session_name(), session_id()) : ''); echo (sid() ? input_hidden(session_name(), session_id()) : '');
echo (SERVER !== null ? input_hidden(DRIVER, SERVER) : ""); echo (SERVER !== null ? input_hidden(DRIVER, SERVER) : "");
echo input_hidden("username", $_GET["username"]); echo input_hidden("username", $_GET["username"]);
@@ -201,9 +184,8 @@ function hidden_fields_get() {
* @param string $type "radio"|"checkbox" * @param string $type "radio"|"checkbox"
* @param Field $field * @param Field $field
* @param mixed $value string|array * @param mixed $value string|array
* @return string
*/ */
function enum_input(string $type, string $attrs, array $field, $value, string $empty = null) { function enum_input(string $type, string $attrs, array $field, $value, string $empty = null): string {
global $adminer; global $adminer;
preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches); preg_match_all("~'((?:[^']|'')*)'~", $field["length"], $matches);
$return = ($empty !== null ? "<label><input type='$type'$attrs value='$empty'" . ((is_array($value) ? in_array($empty, $value) : $value === $empty) ? " checked" : "") . "><i>" . lang('empty') . "</i></label>" : ""); $return = ($empty !== null ? "<label><input type='$type'$attrs value='$empty'" . ((is_array($value) ? in_array($empty, $value) : $value === $empty) ? " checked" : "") . "><i>" . lang('empty') . "</i></label>" : "");
@@ -218,9 +200,8 @@ function enum_input(string $type, string $attrs, array $field, $value, string $e
/** Print edit input field /** Print edit input field
* @param Field|RoutineField $field one field from fields() * @param Field|RoutineField $field one field from fields()
* @param mixed $value * @param mixed $value
* @return void
*/ */
function input(array $field, $value, string $function, bool $autofocus = false) { function input(array $field, $value, string $function, bool $autofocus = false): void {
global $driver, $adminer; global $driver, $adminer;
$name = h(bracket_escape($field["field"])); $name = h(bracket_escape($field["field"]));
echo "<td class='function'>"; echo "<td class='function'>";
@@ -362,9 +343,8 @@ function process_input(array $field) {
/** Print results of search in all tables /** Print results of search in all tables
* @uses $_GET["where"][0] * @uses $_GET["where"][0]
* @uses $_POST["tables"] * @uses $_POST["tables"]
* @return void
*/ */
function search_tables() { function search_tables(): void {
global $adminer, $connection; global $adminer, $connection;
$_GET["where"][0]["val"] = $_POST["query"]; $_GET["where"][0]["val"] = $_POST["query"];
$sep = "<ul>\n"; $sep = "<ul>\n";
@@ -385,18 +365,16 @@ function search_tables() {
/** Return events to display help on mouse over /** Return events to display help on mouse over
* @param string $command JS expression * @param string $command JS expression
* @param int $side JS expression * @param int $side JS expression
* @return string
*/ */
function on_help(string $command, int $side = 0) { function on_help(string $command, int $side = 0): string {
return script("mixin(qsl('select, input'), {onmouseover: function (event) { helpMouseover.call(this, event, $command, $side) }, onmouseout: helpMouseout});", ""); return script("mixin(qsl('select, input'), {onmouseover: function (event) { helpMouseover.call(this, event, $command, $side) }, onmouseout: helpMouseout});", "");
} }
/** Print edit data form /** Print edit data form
* @param Field[] $fields * @param Field[] $fields
* @param mixed $row * @param mixed $row
* @return void
*/ */
function edit_form(string $table, array $fields, $row, bool $update) { function edit_form(string $table, array $fields, $row, bool $update): void {
global $adminer, $error; global $adminer, $error;
$table_name = $adminer->tableName(table_status1($table, true)); $table_name = $adminer->tableName(table_status1($table, true));
page_header( page_header(
@@ -501,8 +479,7 @@ function edit_form(string $table, array $fields, $row, bool $update) {
} }
/** Get button with icon /** Get button with icon
* @return string
*/ */
function icon(string $icon, string $name, string $html, string $title) { function icon(string $icon, string $name, string $html, string $title): string {
return "<button type='submit' name='$name' title='" . h($title) . "' class='icon icon-$icon'><span>$html</span></button>"; return "<button type='submit' name='$name' title='" . h($title) . "' class='icon icon-$icon'><span>$html</span></button>";
} }

View File

@@ -52,9 +52,8 @@ $langs = array(
); );
/** Get current language /** Get current language
* @return string
*/ */
function get_lang() { function get_lang(): string {
global $LANG; global $LANG;
return $LANG; return $LANG;
} }
@@ -62,9 +61,8 @@ function get_lang() {
/** Translate string /** Translate string
* @param literal-string $idf * @param literal-string $idf
* @param float|string $number * @param float|string $number
* @return string
*/ */
function lang(string $idf, $number = null) { function lang(string $idf, $number = null): string {
// this is matched by compile.php // this is matched by compile.php
global $LANG, $translations; global $LANG, $translations;
$translation = ($translations[$idf] ?: $idf); $translation = ($translations[$idf] ?: $idf);
@@ -92,8 +90,7 @@ function lang(string $idf, $number = null) {
return vsprintf($format, $args); return vsprintf($format, $args);
} }
/** @return void */ function switch_lang(): void {
function switch_lang() {
global $LANG, $langs; global $LANG, $langs;
echo "<form action='' method='post'>\n<div id='lang'>"; echo "<form action='' method='post'>\n<div id='lang'>";
echo lang('Language') . ": " . html_select("lang", $langs, $LANG, "this.form.submit();"); echo lang('Language') . ": " . html_select("lang", $langs, $LANG, "this.form.submit();");

View File

@@ -8,9 +8,8 @@ if (extension_loaded('pdo')) {
/** Connect to server using DSN /** Connect to server using DSN
* @param mixed[] $options * @param mixed[] $options
* @return void
*/ */
function dsn(string $dsn, string $username, string $password, array $options = array()) { function dsn(string $dsn, string $username, string $password, array $options = array()): void {
$options[\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_SILENT; $options[\PDO::ATTR_ERRMODE] = \PDO::ERRMODE_SILENT;
$options[\PDO::ATTR_STATEMENT_CLASS] = array('Adminer\PdoResult'); $options[\PDO::ATTR_STATEMENT_CLASS] = array('Adminer\PdoResult');
try { try {

View File

@@ -10,15 +10,13 @@ class TmpFile {
} }
/** /**
* @return void
*/ */
function write(string $contents) { function write(string $contents): void {
$this->size += strlen($contents); $this->size += strlen($contents);
fwrite($this->handler, $contents); fwrite($this->handler, $contents);
} }
/** @return void */ function send(): void {
function send() {
fseek($this->handler, 0); fseek($this->handler, 0);
fpassthru($this->handler); fpassthru($this->handler);
fclose($this->handler); fclose($this->handler);

View File

@@ -7,9 +7,8 @@ namespace Adminer;
*/ */
/** /**
* @return int
*/ */
function int32(int $n) { function int32(int $n): int {
while ($n >= 2147483648) { while ($n >= 2147483648) {
$n -= 4294967296; $n -= 4294967296;
} }
@@ -21,9 +20,8 @@ function int32(int $n) {
/** /**
* @param int[] $v * @param int[] $v
* @return string
*/ */
function long2str(array $v, bool $w) { function long2str(array $v, bool $w): string {
$s = ''; $s = '';
foreach ($v as $val) { foreach ($v as $val) {
$s .= pack('V', $val); $s .= pack('V', $val);
@@ -37,7 +35,7 @@ function long2str(array $v, bool $w) {
/** /**
* @return int[] * @return int[]
*/ */
function str2long(string $s, bool $w) { function str2long(string $s, bool $w): array {
$v = array_values(unpack('V*', str_pad($s, 4 * ceil(strlen($s) / 4), "\0"))); $v = array_values(unpack('V*', str_pad($s, 4 * ceil(strlen($s) / 4), "\0")));
if ($w) { if ($w) {
$v[] = strlen($s); $v[] = strlen($s);
@@ -46,9 +44,8 @@ function str2long(string $s, bool $w) {
} }
/** /**
* @return int
*/ */
function xxtea_mx(int $z, int $y, int $sum, int $k) { function xxtea_mx(int $z, int $y, int $sum, int $k): int {
return int32((($z >> 5 & 0x7FFFFFF) ^ $y << 2) + (($y >> 3 & 0x1FFFFFFF) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k ^ $z)); return int32((($z >> 5 & 0x7FFFFFF) ^ $y << 2) + (($y >> 3 & 0x1FFFFFFF) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k ^ $z));
} }
@@ -56,7 +53,7 @@ function xxtea_mx(int $z, int $y, int $sum, int $k) {
* @param string $str plain-text password * @param string $str plain-text password
* @return string binary cipher * @return string binary cipher
*/ */
function encrypt_string(string $str, string $key) { function encrypt_string(string $str, string $key): string {
if ($str == "") { if ($str == "") {
return ""; return "";
} }

View File

@@ -87,7 +87,7 @@ function put_file($match) {
} }
if (basename($match[2]) != "lang.inc.php" || !$_SESSION["lang"]) { if (basename($match[2]) != "lang.inc.php" || !$_SESSION["lang"]) {
if (basename($match[2]) == "lang.inc.php") { if (basename($match[2]) == "lang.inc.php") {
$return = str_replace('function lang(string $idf, $number = null) {', 'function lang($idf, $number = null) { $return = str_replace('function lang(string $idf, $number = null): string {', 'function lang($idf, $number = null) {
if (is_string($idf)) { // compiled version uses numbers, string comes from a plugin if (is_string($idf)) { // compiled version uses numbers, string comes from a plugin
// English translation is closest to the original identifiers //! pluralized translations are not found // English translation is closest to the original identifiers //! pluralized translations are not found
$pos = array_search($idf, get_translations("en")); //! this should be cached $pos = array_search($idf, get_translations("en")); //! this should be cached

View File

@@ -2,18 +2,16 @@
namespace Adminer; namespace Adminer;
/** Encode e-mail header in UTF-8 /** Encode e-mail header in UTF-8
* @return string
*/ */
function email_header(string $header) { function email_header(string $header): string {
// iconv_mime_encode requires iconv, imap_8bit requires IMAP extension // iconv_mime_encode requires iconv, imap_8bit requires IMAP extension
return "=?UTF-8?B?" . base64_encode($header) . "?="; //! split long lines return "=?UTF-8?B?" . base64_encode($header) . "?="; //! split long lines
} }
/** Send e-mail in UTF-8 /** Send e-mail in UTF-8
* @param array{error?:list<int>, type?:list<string>, name?:list<string>, tmp_name?:list<string>} $files * @param array{error?:list<int>, type?:list<string>, name?:list<string>, tmp_name?:list<string>} $files
* @return bool
*/ */
function send_mail(string $email, string $subject, string $message, string $from = "", array $files = array()) { function send_mail(string $email, string $subject, string $message, string $from = "", array $files = array()): bool {
$eol = PHP_EOL; $eol = PHP_EOL;
$message = str_replace("\n", $eol, wordwrap(str_replace("\r", "", "$message\n"))); $message = str_replace("\n", $eol, wordwrap(str_replace("\r", "", "$message\n")));
$boundary = uniqid("boundary"); $boundary = uniqid("boundary");
@@ -43,8 +41,7 @@ function send_mail(string $email, string $subject, string $message, string $from
/** Check whether the column looks like boolean /** Check whether the column looks like boolean
* @param Field $field single field returned from fields() * @param Field $field single field returned from fields()
* @return bool
*/ */
function like_bool(array $field) { function like_bool(array $field): bool {
return preg_match("~bool|(tinyint|bit)\\(1\\)~", $field["full_type"]); return preg_match("~bool|(tinyint|bit)\\(1\\)~", $field["full_type"]);
} }

View File

@@ -66,9 +66,8 @@ if (isset($_GET["elastic"])) {
} }
/** /**
* @return bool
*/ */
function connect(string $server, string $username, string $password) { function connect(string $server, string $username, string $password): bool {
preg_match('~^(https?://)?(.*)~', $server, $match); preg_match('~^(https?://)?(.*)~', $server, $match);
$this->url = ($match[1] ?: "http://") . urlencode($username) . ":" . urlencode($password) . "@$match[2]"; $this->url = ($match[1] ?: "http://") . urlencode($username) . ":" . urlencode($password) . "@$match[2]";
$return = $this->query(''); $return = $this->query('');
@@ -543,9 +542,8 @@ if (isset($_GET["elastic"])) {
/** Drop types /** Drop types
* @param list<string> $tables * @param list<string> $tables
* @return bool
*/ */
function drop_tables(array $tables) { function drop_tables(array $tables): bool {
$return = true; $return = true;
foreach ($tables as $table) { //! convert to bulk api foreach ($tables as $table) { //! convert to bulk api
$return = $return && connection()->query(urlencode($table), null, 'DELETE'); $return = $return && connection()->query(urlencode($table), null, 'DELETE');

View File

@@ -10,9 +10,8 @@ class AdminerTableIndexesStructure {
/** Print table structure in tabular format /** Print table structure in tabular format
* @param Index[] $indexes data about all indexes on a table * @param Index[] $indexes data about all indexes on a table
* @return bool
*/ */
function tableIndexesPrint(array $indexes) { function tableIndexesPrint(array $indexes): bool {
echo "<table>\n"; echo "<table>\n";
echo "<thead><tr><th>" . Adminer\lang('Name') . "<th>" . Adminer\lang('Type') . "<th>" . Adminer\lang('Columns') . "</thead>\n"; echo "<thead><tr><th>" . Adminer\lang('Name') . "<th>" . Adminer\lang('Type') . "<th>" . Adminer\lang('Columns') . "</thead>\n";
foreach ($indexes as $name => $index) { foreach ($indexes as $name => $index) {

View File

@@ -10,9 +10,8 @@ class AdminerTableStructure {
/** Print table structure in tabular format /** Print table structure in tabular format
* @param Field[] $fields data about individual fields * @param Field[] $fields data about individual fields
* @return bool
*/ */
function tableStructurePrint(array $fields, $tableStatus = null) { function tableStructurePrint(array $fields, $tableStatus = null): bool {
echo "<div class='scrollable'>\n"; echo "<div class='scrollable'>\n";
echo "<table class='nowrap odds'>\n"; echo "<table class='nowrap odds'>\n";
echo "<thead><tr>" echo "<thead><tr>"