]> git.joonet.de Git - adminer.git/commitdiff
PHPStan: Fix more errors
authorJakub Vrana <jakub@vrana.cz>
Thu, 27 Mar 2025 17:27:51 +0000 (18:27 +0100)
committerJakub Vrana <jakub@vrana.cz>
Thu, 27 Mar 2025 17:39:48 +0000 (18:39 +0100)
adminer/drivers/mysql.inc.php
adminer/drivers/pgsql.inc.php
adminer/drivers/sqlite.inc.php
adminer/include/bootstrap.inc.php
adminer/include/editing.inc.php
adminer/include/functions.inc.php
adminer/include/html.inc.php
adminer/include/pdo.inc.php
adminer/select.inc.php
adminer/sql.inc.php
phpstan.neon

index 26bd220e0e191adc6a79425772d9dfe3fbeb83ef..3047d68e399b2283d79c032560f478a5bd69413f 100644 (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) {
index 253d60ca237ea194f5b3ce6a35e4851fc9f8439f..5b931e8069df0422ef16f534af6c1f74915364f1 100644 (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
index c0f52c8f9b333db9c5c9e30c7973fdce9f093669..7826a52a2f96967b276bcd2e50a50bc5c6584f57 100644 (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;
                }
index 848d487cb678e619b879d6f8d1db374426ddb1da..3fdf2266d3c2552c1c03bbbf570f0d132b58ea74 100644 (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";
index c0ad3ab372fcd9500e1a613b32327b2714195648..8603d0338315e45ce5cf1694dc31948969695707 100644 (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
 */
index 1890290b806d30aa05e707bb0e39663b74928687..790df98d990ff8efe358428f0b120b998881d064 100644 (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();
index dcaa345ab27c03e0a46f6b8cd1dd7b08b467bc69..ea548e9c6cddd30d5bc4f375cf76925d8449013d 100644 (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) {
index 2c71ca95691347f998d10607c7e67df7f073e315..1447a1e39a8042a89ed092918fc0acad5a617ca5 100644 (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
                }
        }
 
index 0a56766f288bd91615dfefd50f34d44ae6af303f..b6f7f03a203383d1b7ed8767a0718aed9fbca4b0 100644 (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
index 67ded6331e0d813fed5e2566a4bcf9f68877da49..fe034a32636056a48ae4ed19cf1ee3501ba798f1 100644 (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" : "");
index d6a2399ab0e8ebd474f4eacd5cbecd9a771f3f5c..99bc9d14cb21ad4d7e2995cc5e825ca03ee551cb 100644 (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[][]}"