diff --git a/adminer/drivers/mssql.inc.php b/adminer/drivers/mssql.inc.php index c9302cf3..061547aa 100644 --- a/adminer/drivers/mssql.inc.php +++ b/adminer/drivers/mssql.inc.php @@ -385,7 +385,7 @@ WHERE c.object_id = " . q($table_id)) as $row ) { $type = $row["type"]; $length = (preg_match("~char|binary~", $type) - ? $row["max_length"] / ($type[0] == 'n' ? 2 : 1) + ? intval($row["max_length"]) / ($type[0] == 'n' ? 2 : 1) : ($type == "decimal" ? "$row[precision],$row[scale]" : "") ); $return[$row["name"]] = array( diff --git a/adminer/drivers/mysql.inc.php b/adminer/drivers/mysql.inc.php index 423b0a4e..177d178b 100644 --- a/adminer/drivers/mysql.inc.php +++ b/adminer/drivers/mysql.inc.php @@ -550,7 +550,6 @@ if (!defined('Adminer\DRIVER')) { * @param string * @param bool return only "Name", "Engine" and "Comment" fields * @return TableStatus[] - * @phpstan-type TableStatus array{Name:string, Engine:string, Comment:string, Oid:int, Rows:int, Collation:string, Auto_increment:int, Data_length:int, Index_length:int, Data_free:int} */ function table_status($name = "", $fast = false) { $return = array(); @@ -596,7 +595,6 @@ if (!defined('Adminer\DRIVER')) { /** Get information about fields * @param string * @return Field[] - * @phpstan-type Field array{field:string, full_type:string, type:string, length:int, unsigned:string, default:string, null:bool, auto_increment:bool, on_update:string, collation:string, privileges:int[], comment:string, primary:bool, generated:string} */ function fields($table) { global $connection; @@ -653,7 +651,6 @@ if (!defined('Adminer\DRIVER')) { * @param string * @param string Db to use * @return Index[] - * @phpstan-type Index array{type:string, columns:list, lengths:list, descs:list} */ function indexes($table, $connection2 = null) { $return = array(); @@ -670,7 +667,6 @@ if (!defined('Adminer\DRIVER')) { /** Get foreign keys in table * @param string * @return ForeignKey[] - * @phpstan-type ForeignKey array{db:string, ns:string, table:string, source:list, target:list, on_delete:string, on_update:string} */ function foreign_keys($table) { global $driver; @@ -963,7 +959,6 @@ if (!defined('Adminer\DRIVER')) { * @param string trigger name * @param string * @return Trigger - * @phpstan-type Trigger array{Trigger:string, Timing:string, Event:string, Of:string, Type:string, Statement:string} */ function trigger($name, $table) { if ($name == "") { @@ -1000,7 +995,6 @@ if (!defined('Adminer\DRIVER')) { * @param string * @param string "FUNCTION" or "PROCEDURE" * @return Routine - * @phpstan-type Routine array{fields:list, comment:string, returns:array, definition:string, language:string} */ function routine($name, $type) { global $driver; @@ -1185,7 +1179,7 @@ if (!defined('Adminer\DRIVER')) { /** Convert field in select and edit * @param Field one element from fields() - * @return ?string + * @return string|void */ function convert_field($field) { if (preg_match("~binary~", $field["type"])) { diff --git a/adminer/drivers/oracle.inc.php b/adminer/drivers/oracle.inc.php index 21edace3..b7eff953 100644 --- a/adminer/drivers/oracle.inc.php +++ b/adminer/drivers/oracle.inc.php @@ -89,7 +89,7 @@ if (isset($_GET["oracle"])) { private function convert($row) { foreach ((array) $row as $key => $val) { - if (is_a($val, 'OCI-Lob')) { + if (is_a($val, 'OCILob') || is_a($val, 'OCI-Lob')) { $row[$key] = $val->load(); } } diff --git a/adminer/drivers/pgsql.inc.php b/adminer/drivers/pgsql.inc.php index a699126e..be4293af 100644 --- a/adminer/drivers/pgsql.inc.php +++ b/adminer/drivers/pgsql.inc.php @@ -499,7 +499,7 @@ ORDER BY indisprimary DESC, indisunique DESC", $connection2) as $row $return[$relname]["columns"][] = $columns[$indkey]; } foreach (explode(" ", $row["indoption"]) as $indoption) { - $return[$relname]["descs"][] = ($indoption & 1 ? '1' : null); // 1 - INDOPTION_DESC + $return[$relname]["descs"][] = (intval($indoption) & 1 ? '1' : null); // 1 - INDOPTION_DESC } } $return[$relname]["lengths"] = array(); diff --git a/adminer/include/adminer.inc.php b/adminer/include/adminer.inc.php index b4ccb81a..869533e7 100644 --- a/adminer/include/adminer.inc.php +++ b/adminer/include/adminer.inc.php @@ -5,7 +5,7 @@ namespace Adminer; class Adminer { public $operators; ///< @var list operators used in select, null for all operators - public $error = ''; ///< @var protected(set) string HTML + public $error = ''; ///< @var string @visibility protected(set) string HTML /** Name in title and navigation * @return string HTML code @@ -22,7 +22,7 @@ class Adminer { } /** Get SSL connection options - * @return ?string[] + * @return string[]|void */ function connectSsl() { } @@ -221,7 +221,6 @@ class Adminer { * @param string * @param string * @return BackwardKey[] - * @phpstan-type BackwardKey array{name:string, keys:string[][]} */ function backwardKeys($table, $tableName) { return array(); @@ -289,7 +288,7 @@ class Adminer { /** Get a link to use in select table * @param string raw value of the field * @param Field single field returned from fields() - * @return ?string null to create the default link + * @return string|void null to create the default link */ function selectLink($val, $field) { } diff --git a/adminer/include/driver.inc.php b/adminer/include/driver.inc.php index a9af6ab0..2ae93d96 100644 --- a/adminer/include/driver.inc.php +++ b/adminer/include/driver.inc.php @@ -61,14 +61,14 @@ abstract class SqlDriver { /** Get enum values * @param Field - * @return ?string + * @return string|void */ function enumLength($field) { } /** Function used to convert the value inputted by user * @param Field - * @return ?string + * @return string|void */ function unconvertFunction($field) { } @@ -187,7 +187,7 @@ abstract class SqlDriver { /** Return query with a timeout * @param string * @param int seconds - * @return ?string null if the driver doesn't support query timeouts + * @return string|void null if the driver doesn't support query timeouts */ function slowQuery($query, $timeout) { } @@ -231,7 +231,7 @@ abstract class SqlDriver { } /** Get warnings about the last command - * @return ?string HTML + * @return string|void HTML */ function warnings() { } @@ -239,7 +239,7 @@ abstract class SqlDriver { /** Get help link for table * @param string * @param bool - * @return ?string relative URL + * @return string|void relative URL */ function tableHelp($name, $is_view = false) { } diff --git a/adminer/include/editing.inc.php b/adminer/include/editing.inc.php index ebb5f89b..78bed1de 100644 --- a/adminer/include/editing.inc.php +++ b/adminer/include/editing.inc.php @@ -299,7 +299,7 @@ function default_value($field) { /** Get type class to use in CSS * @param string -* @return ?string class='' +* @return string|void class='' */ function type_class($type) { foreach ( diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index 1d457bbc..db3ca128 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -274,7 +274,7 @@ function get_rows($query, $connection2 = null, $error = "

") { /** Find unique identifier of a row * @param string[] * @param Index[] result of indexes() -* @return ?string[] null if there is no unique identifier +* @return string[]|void null if there is no unique identifier */ function unique_array($row, $indexes) { foreach ($indexes as $index) { diff --git a/adminer/include/html.inc.php b/adminer/include/html.inc.php index dc0f2f72..a265a18f 100644 --- a/adminer/include/html.inc.php +++ b/adminer/include/html.inc.php @@ -343,7 +343,7 @@ function input($field, $value, $function, $autofocus = false) { } /** Process edit input field -* @param one field from fields() +* @param Field one field from fields() * @return string or false to leave the original value */ function process_input($field) { @@ -417,7 +417,7 @@ function search_tables() { /** Return events to display help on mouse over * @param string JS expression -* @param bool JS expression +* @param int JS expression * @return string */ function on_help($command, $side = 0) { diff --git a/adminer/include/plugins.inc.php b/adminer/include/plugins.inc.php index da222c55..294c6135 100644 --- a/adminer/include/plugins.inc.php +++ b/adminer/include/plugins.inc.php @@ -2,7 +2,7 @@ namespace Adminer; class Plugins extends Adminer { - public $plugins; ///< @var protected(set) array + public $plugins; ///< @var list @visibility protected(set) /** Register plugins * @param list object instances or null to autoload plugins from adminer-plugins/ diff --git a/adminer/include/tmpfile.inc.php b/adminer/include/tmpfile.inc.php index b75f478f..a9c87d29 100644 --- a/adminer/include/tmpfile.inc.php +++ b/adminer/include/tmpfile.inc.php @@ -2,7 +2,8 @@ namespace Adminer; class TmpFile { - private $handler, $size; + private $handler; + public $size; ///< @visibility protected(set) function __construct() { $this->handler = tmpfile(); diff --git a/adminer/schema.inc.php b/adminer/schema.inc.php index b2284d19..b3ab4e41 100644 --- a/adminer/schema.inc.php +++ b/adminer/schema.inc.php @@ -3,6 +3,7 @@ namespace Adminer; page_header(lang('Database schema'), "", array(), h(DB . ($_GET["ns"] ? ".$_GET[ns]" : ""))); +/** @var array{float, float}[] */ $table_pos = array(); $table_pos_js = array(); $SCHEMA = ($_GET["schema"] ?: $_COOKIE["adminer_schema-" . str_replace(".", "_", DB)]); // $_COOKIE["adminer_schema"] was used before 3.2.0 //! ':' in table name @@ -14,6 +15,7 @@ foreach ($matches as $i => $match) { $top = 0; $base_left = -1; +/** @var array{fields:Field[], pos:array{float, float}, references:string[][][]}[] */ $schema = array(); // table => array("fields" => array(name => field), "pos" => array(top, left), "references" => array(table => array(left => array(source, target)))) $referenced = array(); // target_table => array(table => array(left => target_column)) $lefts = array(); // float => bool diff --git a/adminer/select.inc.php b/adminer/select.inc.php index d0dba925..cb0db3c5 100644 --- a/adminer/select.inc.php +++ b/adminer/select.inc.php @@ -270,7 +270,7 @@ if (!$columns && support("table")) { $page = $_GET["page"]; if ($page == "last") { $found_rows = get_val(count_rows($TABLE, $where, $is_group, $group)); - $page = floor(max(0, $found_rows - 1) / $limit); + $page = floor(max(0, intval($found_rows) - 1) / $limit); } $select2 = $select; diff --git a/editor/include/editing.inc.php b/editor/include/editing.inc.php index 529a0be6..6dacd510 100644 --- a/editor/include/editing.inc.php +++ b/editor/include/editing.inc.php @@ -15,7 +15,7 @@ function email_header($header) { * @param string * @param string * @param string -* @param array{error:list, type:list, name:list} +* @param array{error?:list, type?:list, name?:list} * @return bool */ function send_mail($email, $subject, $message, $from = "", $files = array()) { diff --git a/phpstan.neon b/phpstan.neon index df336bbd..ad5a02d7 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,14 +1,25 @@ parameters: - level: 1 + level: 2 ignoreErrors: - identifier: include.fileNotFound # relative includes - identifier: includeOnce.fileNotFound # ./adminer-plugins.php - "~^Function (set_magic_quotes_runtime|mysql_)~" # PHP < 7 functions - "~^Instantiated class Adminer\\w~" # no support for classes defined inside function - "~^Variable \\$(adminer|connection|driver|drivers|error|HTTPS|LANG|langs|permanent|has_token|token|translations|VERSION) might not be defined~" # declared in bootstrap.inc.php + - "~^Comparison operation \"==\" between \\(array\\|float\\|int\\) and 1~" # false positive + - "~OCI-?Lob~" # maybe include stub? + - "~Adminer\\\\Db::~" # diagnose! paths: - . phpVersion: min: 70100 max: 80499 checkMissingCallableSignature: true + typeAliases: + TableStatus: "array{Name:string, Engine:string, Comment:string, Oid:int, Rows:int, Collation:string, Auto_increment:int, Data_length:int, Index_length:int, Data_free:int}" + Field: "array{field:string, full_type:string, type:string, length:int, unsigned:string, default:string, null:bool, auto_increment:bool, on_update:string, collation:string, privileges:int[], comment:string, primary:bool, generated:string}" + Index: "array{type:string, columns:list, lengths:list, descs:list}" + ForeignKey: "array{db:string, ns:string, table:string, source:list, target:list, on_delete:string, on_update:string}" + Trigger: "array{Trigger:string, Timing:string, Event:string, Of:string, Type:string, Statement:string}" + Routine: "array{fields:list, comment:string, returns:array, definition:string, language:string}" + BackwardKey: "array{name:string, keys:string[][]}" diff --git a/plugins/drivers/mongo.php b/plugins/drivers/mongo.php index bbe925df..f36f6adc 100644 --- a/plugins/drivers/mongo.php +++ b/plugins/drivers/mongo.php @@ -9,7 +9,7 @@ if (isset($_GET["mongo"])) { if (class_exists('MongoDB\Driver\Manager')) { class Db { public $extension = "MongoDB", $flavor = '', $server_info = MONGODB_VERSION, $affected_rows, $error, $last_id; - /** @var MongoDB\Driver\Manager */ + /** @var \MongoDB\Driver\Manager */ public $_link; public $_db, $_db_name;