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

PHPStan: Fix more errors

This commit is contained in:
Jakub Vrana
2025-03-27 18:27:51 +01:00
parent e2deed9a02
commit b23bf6c055
11 changed files with 54 additions and 43 deletions

View File

@@ -783,17 +783,18 @@ if (!defined('Adminer\DRIVER')) {
/** Run commands to alter indexes
* @param string escaped table name
* @param array{string, string, 'DROP'|list<string>} of ["index type", "name", ["column definition", ...]] or ["index type", "name", "DROP"]
* @param list<array{string, string, 'DROP'|list<string>}> of ["index type", "name", ["column definition", ...]] or ["index type", "name", "DROP"]
* @return Result|bool
*/
function alter_indexes($table, $alter) {
foreach ($alter as $key => $val) {
$alter[$key] = ($val[2] == "DROP"
$changes = array();
foreach ($alter as $val) {
$changes[] = ($val[2] == "DROP"
? "\nDROP INDEX " . idf_escape($val[1])
: "\nADD $val[0] " . ($val[0] == "PRIMARY" ? "KEY " : "") . ($val[1] != "" ? idf_escape($val[1]) . " " : "") . "(" . implode(", ", $val[2]) . ")"
);
}
return queries("ALTER TABLE " . table($table) . implode(",", $alter));
return queries("ALTER TABLE " . table($table) . implode(",", $changes));
}
/** Run commands to truncate tables
@@ -925,7 +926,7 @@ if (!defined('Adminer\DRIVER')) {
/** Get information about stored routine
* @param string
* @param string "FUNCTION" or "PROCEDURE"
* @param 'FUNCTION'|'PROCEDURE'
* @return Routine
*/
function routine($name, $type) {

View File

@@ -844,7 +844,7 @@ AND typelem = 0"
foreach ($fields as $field) {
$part = idf_escape($field['field']) . ' ' . $field['full_type']
. default_value($field)
. ($field['attnotnull'] ? " NOT NULL" : "");
. ($field['null'] ? "" : " NOT NULL");
$return_parts[] = $part;
// sequences for fields

View File

@@ -521,23 +521,24 @@ if (isset($_GET["sqlite"])) {
}
queries("BEGIN");
}
foreach ($fields as $key => $field) {
$changes = array();
foreach ($fields as $field) {
if (preg_match('~GENERATED~', $field[3])) {
unset($originals[array_search($field[0], $originals)]);
}
$fields[$key] = " " . implode($field);
$changes[] = " " . implode($field);
}
$fields = array_merge($fields, array_filter($foreign));
$changes = array_merge($changes, array_filter($foreign));
foreach ($driver->checkConstraints($table) as $check) {
if ($check != $drop_check) {
$fields[] = " CHECK ($check)";
$changes[] = " CHECK ($check)";
}
}
if ($add_check) {
$fields[] = " CHECK ($add_check)";
$changes[] = " CHECK ($add_check)";
}
$temp_name = ($table == $name ? "adminer_$name" : $name);
if (!queries("CREATE TABLE " . table($temp_name) . " (\n" . implode(",\n", $fields) . "\n)")) {
if (!queries("CREATE TABLE " . table($temp_name) . " (\n" . implode(",\n", $changes) . "\n)")) {
// implicit ROLLBACK to not overwrite $connection->error
return false;
}

View File

@@ -52,7 +52,7 @@ if ($_SERVER["HTTP_X_FORWARDED_PREFIX"]) {
}
$HTTPS = ($_SERVER["HTTPS"] && strcasecmp($_SERVER["HTTPS"], "off")) || ini_bool("session.cookie_secure"); // session.cookie_secure could be set on HTTP if we are behind a reverse proxy
@ini_set("session.use_trans_sid", false); // protect links in export, @ - may be disabled
@ini_set("session.use_trans_sid", '0'); // protect links in export, @ - may be disabled
if (!defined("SID")) {
session_cache_limiter(""); // to allow restarting session
session_name("adminer_sid"); // use specific session name to get own namespace
@@ -66,7 +66,7 @@ if (function_exists("get_magic_quotes_runtime") && get_magic_quotes_runtime()) {
set_magic_quotes_runtime(false);
}
@set_time_limit(0); // @ - can be disabled
@ini_set("precision", 15); // @ - can be disabled, 15 - internal PHP precision
@ini_set("precision", '15'); // @ - can be disabled, 15 - internal PHP precision
include "../adminer/include/lang.inc.php";
include "../adminer/lang/$LANG.inc.php";

View File

@@ -102,7 +102,7 @@ function select($result, $connection2 = null, $orgtables = array(), $limit = 0)
/** Get referencable tables with single column primary key except self
* @param string
* @return Field[] [$table_name => $field]
* @return array<string, Field> [$table_name => $field]
*/
function referencable_primary($self) {
$return = array(); // table_name => field
@@ -180,7 +180,7 @@ function json_row($key, $val = null) {
* @param string
* @param Field
* @param list<string>
* @param Field[] returned by referencable_primary()
* @param string[]
* @param list<string> extra types to prepend
* @return void
*/
@@ -246,7 +246,7 @@ function process_length($length) {
}
/** Create SQL string from field type
* @param Field
* @param FieldType
* @param string
* @return string
*/
@@ -317,10 +317,10 @@ function type_class($type) {
}
/** Print table interior for fields editing
* @param Field[]
* @param (Field|RoutineField)[]
* @param list<string>
* @param string TABLE or PROCEDURE
* @param Field[] returned by referencable_primary()
* @param 'TABLE'|'PROCEDURE'
* @param string[]
* @return void
*/
function edit_fields($fields, $collations, $type = "TABLE", $foreign_keys = array()) {
@@ -502,7 +502,7 @@ function create_trigger($on, $row) {
}
/** Generate SQL query for creating routine
* @param string "PROCEDURE" or "FUNCTION"
* @param 'PROCEDURE'|'FUNCTION'
* @param Routine result of routine()
* @return string
*/

View File

@@ -354,7 +354,7 @@ function where_link($i, $column, $value, $operator = "=") {
}
/** Get select clause for convertible fields
* @param string[]
* @param mixed[] only keys are used
* @param Field[]
* @param list<string>
* @return string
@@ -436,7 +436,7 @@ function stop_session($force = false) {
$use_cookies = ini_bool("session.use_cookies");
if (!$use_cookies || $force) {
session_write_close(); // improves concurrency if a user opens several pages at once, may be restarted later
if ($use_cookies && @ini_set("session.use_cookies", false) === false) { // @ - may be disabled
if ($use_cookies && @ini_set("session.use_cookies", '0') === false) { // @ - may be disabled
session_start();
}
}
@@ -999,9 +999,12 @@ function slow_query($query) {
$timeout = $adminer->queryTimeout();
$slow_query = $driver->slowQuery($query, $timeout);
$connection2 = null;
if (!$slow_query && support("kill") && is_object($connection2 = connect($adminer->credentials())) && ($db == "" || $connection2->select_db($db))) {
$kill = $connection2->result(connection_id()); // MySQL and MySQLi can use thread_id but it's not in PDO_MySQL
echo script("const timeout = setTimeout(() => { ajax('" . js_escape(ME) . "script=kill', function () {}, 'kill=$kill&token=$token'); }, 1000 * $timeout);");
if (!$slow_query && support("kill")) {
$connection2 = connect($adminer->credentials());
if (is_object($connection2) && ($db == "" || $connection2->select_db($db))) {
$kill = $connection2->result(connection_id()); // MySQL and MySQLi can use thread_id but it's not in PDO_MySQL
echo script("const timeout = setTimeout(() => { ajax('" . js_escape(ME) . "script=kill', function () {}, 'kill=$kill&token=$token'); }, 1000 * $timeout);");
}
}
ob_flush();
flush();

View File

@@ -247,7 +247,7 @@ function enum_input($type, $attrs, $field, $value, $empty = null) {
}
/** Print edit input field
* @param Field one field from fields()
* @param Field|RoutineField one field from fields()
* @param mixed
* @param string
* @param bool
@@ -343,7 +343,7 @@ function input($field, $value, $function, $autofocus = false) {
}
/** Process edit input field
* @param Field one field from fields()
* @param Field|RoutineField one field from fields()
* @return mixed false to leave the original value
*/
function process_input($field) {

View File

@@ -59,11 +59,13 @@ if (extension_loaded('pdo')) {
}
function next_result() {
if (!is_object($this->multi)) {
/** @var PdoResult|bool */
$result = $this->multi;
if (!is_object($result)) {
return false;
}
$this->multi->_offset = 0;
return @$this->multi->nextRowset(); // @ - PDO_PgSQL doesn't support it
$result->_offset = 0;
return @$result->nextRowset(); // @ - PDO_PgSQL doesn't support it
}
}

View File

@@ -127,7 +127,10 @@ if ($_POST && !$error) {
: $driver->update($TABLE, $set, $where_check)
)
);
$affected = $connection->affected_rows + (is_object($result) ? $result->num_rows : 0); // PostgreSQL with RETURNING fills num_rows
$affected = $connection->affected_rows;
if (is_object($result)) { // PostgreSQL with RETURNING fills num_rows
$affected += $result->num_rows;
}
} else {
foreach ((array) $_POST["check"] as $val) {
// where is not unique so OR can't be used

View File

@@ -37,7 +37,7 @@ if (!$error && $_POST) {
if (is_string($query)) { // get_file() returns error as number, fread() as false
if (function_exists('memory_get_usage') && ($memory_limit = ini_bytes("memory_limit")) != "-1") {
@ini_set("memory_limit", max($memory_limit, 2 * strlen($query) + memory_get_usage() + 8e6)); // @ - may be disabled, 2 - substr and trim, 8e6 - other variables
@ini_set("memory_limit", max($memory_limit, strval(2 * strlen($query) + memory_get_usage() + 8e6))); // @ - may be disabled, 2 - substr and trim, 8e6 - other variables
}
if ($query != "" && strlen($query) < 1e6) { // don't add big queries
@@ -182,7 +182,7 @@ if (!$error && $_POST) {
stop_session();
}
if (!$_POST["only_errors"]) {
echo "<p class='message' title='" . h(isset($connection->info) ? $connection->info : "") . "'>" . lang('Query executed OK, %d row(s) affected.', $affected) . "$time\n";
echo "<p class='message' title='" . h($connection->info) . "'>" . lang('Query executed OK, %d row(s) affected.', $affected) . "$time\n";
}
}
echo ($warnings ? "<div id='$warnings_id' class='hidden'>\n$warnings</div>\n" : "");

View File

@@ -6,18 +6,14 @@ parameters:
# need to fix
- "~^Function Adminer\\\\fields_from_edit\\(\\) should return~" # Mongo and SimpleDB
- "~Adminer\\\\Result.*mysqli_result~" # mysqli_result
- "~expects array~" # different shape of array
# not real problems
- identifier: include.fileNotFound # relative includes
- identifier: include.fileNotFound # includes in include/ relative from index.php
- identifier: includeOnce.fileNotFound # ./adminer-plugins.php
- "~^Function (set_magic_quotes_runtime|mysql_)~" # PHP < 7 functions
- "~an unknown class OCI-?Lob~" # this looks like PHPStan bug
- "~^Variable \\$(adminer|connection|driver|drivers|error|HTTPS|LANG|langs|permanent|has_token|token|translations|VERSION) might not be defined~" # declared in bootstrap.inc.php
- "~^Method Adminer\\\\Plugins::\\w+\\(\\) with return type void~" # we use the same pattern for all methods
- "~Call to function is_object\\(\\) with Adminer\\\\Db\\|string will always evaluate to false~" # is_object(Db) is true
- "~^Comparison operation \"==\" between \\(array\\|float\\|int\\) and 1~" # it thinks that $affected could be an array
- "~^Parameter #2 \\$newvalue of function ini_set expects string~" # it expects string|int|float|bool|null since PHP 8.1
- "~expects int, float given~" # this will work
- "~expects bool~" # truthy values
- "~fread expects int<1, max>, 100000~" # 1e6
@@ -28,6 +24,10 @@ parameters:
paths:
- adminer/include/pdo.inc.php
- adminer/drivers/*
-
message: "~ to an undefined ~" # PostgreSQL has this in its version of Db
path: adminer/drivers/pgsql.inc.php
# it probably doesn't like $ar[$key] instead of isset($ar[$key]) and thinks that $ar[$key] is always set
- identifier: identical.alwaysFalse
@@ -64,10 +64,11 @@ parameters:
typeAliases:
TableStatus: "array{Name:string, Engine?:?string, Comment?:string, Oid?:numeric-string, Rows?:?numeric-string, Collation?:string, Auto_increment?:?numeric-string, Data_length?:numeric-string, Index_length?:numeric-string, Data_free?:numeric-string, Create_options?:string, nspname?:string}"
Field: "array{field:?string, full_type:string, type:string, length:numeric-string, unsigned:string, default:?string, null:bool, auto_increment:bool, collation:string, privileges:int[], comment:string, primary:bool, generated:string, orig?:string, on_update:?string, on_delete?:string, inout?:string}"
Field: "array{field?:string, full_type:string, type:string, length:numeric-string, unsigned:string, default?:string, null:bool, auto_increment:bool, collation:string, privileges:int[], comment:string, primary:bool, generated:string, orig?:string, on_update?:string, on_delete?:string, default_constraint?: string}"
FieldType: "array{type:string, length:numeric-string, unsigned:string, collation:string}" # subset of RoutineField and Field
RoutineField: "array{field:string, type:string, length:numeric-string, unsigned:string, null:bool, full_type:string, collation:string, inout?:string}"
Index: "array{type:string, columns:list<string>, lengths:list<numeric-string>, descs:list<?bool>}"
ForeignKey: "array{db:string, ns?:string, table:string, source:list<string>, target:list<string>, on_delete:string, on_update:string}"
ForeignKey: "array{db?:string, ns?:string, table:string, source:list<string>, target:list<?string>, on_delete:string, on_update?:string, definition?:string, deferrable?:string}"
Trigger: "array{Trigger?:string, Timing?:string, Event?:string, Of?:string, Type?:string, Statement?:string}"
RoutineField: "array{field:string, type:string, length:?string, unsigned:string, null:bool, full_type:string, inout:string, collation:string}"
Routine: "array{name?:string, fields:list<RoutineField>, comment:string, returns?:array{type:string, length:string, unsigned:string, collation:string}, definition:string, language?:string}"
Routine: "array{name?:string, fields:list<RoutineField>, comment:string, returns?:FieldType, definition:string, language?:string}"
BackwardKey: "array{name:string, keys:string[][]}"