Address PHPStan findings as of 2.0.1

This commit is contained in:
wn_
2024-11-12 03:15:53 +00:00
parent e4c57769e0
commit a784305cc7
17 changed files with 106 additions and 118 deletions

View File

@@ -235,7 +235,7 @@ class API extends Handler {
}
function updateArticle(): bool {
$article_ids = explode(",", clean($_REQUEST["article_ids"]));
$article_ids = array_filter(explode(",", clean($_REQUEST["article_ids"] ?? "")));
$mode = (int) clean($_REQUEST["mode"]);
$data = clean($_REQUEST["data"] ?? "");
$field_raw = (int)clean($_REQUEST["field"]);
@@ -550,26 +550,22 @@ class API extends Handler {
/* Virtual feeds */
$vfeeds = PluginHost::getInstance()->get_feeds(Feeds::CATEGORY_SPECIAL);
foreach (PluginHost::getInstance()->get_feeds(Feeds::CATEGORY_SPECIAL) as $feed) {
if (!implements_interface($feed['sender'], 'IVirtualFeed'))
continue;
if (is_array($vfeeds)) {
foreach ($vfeeds as $feed) {
if (!implements_interface($feed['sender'], 'IVirtualFeed'))
continue;
/** @var IVirtualFeed $feed['sender'] */
$unread = $feed['sender']->get_unread($feed['id']);
/** @var IVirtualFeed $feed['sender'] */
$unread = $feed['sender']->get_unread($feed['id']);
if ($unread || !$unread_only) {
$row = [
'id' => PluginHost::pfeed_to_feed_id($feed['id']),
'title' => $feed['title'],
'unread' => $unread,
'cat_id' => Feeds::CATEGORY_SPECIAL,
];
if ($unread || !$unread_only) {
$row = [
'id' => PluginHost::pfeed_to_feed_id($feed['id']),
'title' => $feed['title'],
'unread' => $unread,
'cat_id' => Feeds::CATEGORY_SPECIAL,
];
array_push($feeds, $row);
}
array_push($feeds, $row);
}
}
@@ -696,10 +692,11 @@ class API extends Handler {
if (!$is_cat && is_numeric($feed_id) && $feed_id < PLUGIN_FEED_BASE_INDEX && $feed_id > LABEL_BASE_INDEX) {
$pfeed_id = PluginHost::feed_to_pfeed_id($feed_id);
/** @var IVirtualFeed|false $handler */
$handler = PluginHost::getInstance()->get_feed_handler($pfeed_id);
if ($handler) {
if ($handler && implements_interface($handler, 'IVirtualFeed')) {
/** @var Plugin&IVirtualFeed $handler */
$params = array(
"feed" => $feed_id,
"limit" => $limit,
@@ -858,7 +855,7 @@ class API extends Handler {
array_push($headlines, $headline_row);
}
} else if (is_numeric($result) && $result == -1) {
} else if ($result == -1) {
$headlines_header['first_id_changed'] = true;
}

View File

@@ -264,25 +264,21 @@ class Counters {
array_push($ret, $cv);
}
$feeds = PluginHost::getInstance()->get_feeds(Feeds::CATEGORY_SPECIAL);
foreach (PluginHost::getInstance()->get_feeds(Feeds::CATEGORY_SPECIAL) as $feed) {
/** @var IVirtualFeed $feed['sender'] */
if (is_array($feeds)) {
foreach ($feeds as $feed) {
/** @var IVirtualFeed $feed['sender'] */
if (!implements_interface($feed['sender'], 'IVirtualFeed'))
continue;
if (!implements_interface($feed['sender'], 'IVirtualFeed'))
continue;
$cv = [
"id" => PluginHost::pfeed_to_feed_id($feed['id']),
"counter" => $feed['sender']->get_unread($feed['id'])
];
$cv = [
"id" => PluginHost::pfeed_to_feed_id($feed['id']),
"counter" => $feed['sender']->get_unread($feed['id'])
];
if (method_exists($feed['sender'], 'get_total'))
$cv["auxcounter"] = $feed['sender']->get_total($feed['id']);
if (method_exists($feed['sender'], 'get_total'))
$cv["auxcounter"] = $feed['sender']->get_total($feed['id']);
array_push($ret, $cv);
}
array_push($ret, $cv);
}
return $ret;

View File

@@ -163,7 +163,7 @@ class Digest
$article_labels = Article::_get_labels($line["ref_id"], $user_id);
$article_labels_formatted = "";
if (is_array($article_labels) && count($article_labels) > 0) {
if (count($article_labels) > 0) {
$article_labels_formatted = implode(", ", array_map(fn($a) => $a[1], $article_labels));
}

View File

@@ -34,7 +34,7 @@ class FeedItem_RSS extends FeedItem_Common {
$links = $this->xpath->query("atom:link", $this->elem);
foreach ($links as $link) {
if ($link && $link->hasAttribute("href") &&
if ($link->hasAttribute("href") &&
(!$link->hasAttribute("rel")
|| $link->getAttribute("rel") == "alternate"
|| $link->getAttribute("rel") == "standout")) {

View File

@@ -103,12 +103,12 @@ class Feeds extends Handler_Protected {
$qfh_ret = [];
if (!$cat_view && is_numeric($feed) && $feed < PLUGIN_FEED_BASE_INDEX && $feed > LABEL_BASE_INDEX) {
/** @var IVirtualFeed|false $handler */
$handler = PluginHost::getInstance()->get_feed_handler(
PluginHost::feed_to_pfeed_id($feed));
if ($handler) {
if ($handler && implements_interface($handler, 'IVirtualFeed')) {
/** @var Plugin&IVirtualFeed $handler */
$options = array(
"limit" => $limit,
"view_mode" => $view_mode,
@@ -246,7 +246,7 @@ class Feeds extends Handler_Protected {
$label_cache = json_decode($label_cache, true);
if ($label_cache) {
if ($label_cache["no-labels"] ?? 0 == 1)
if (($label_cache["no-labels"] ?? 0) == 1)
$labels = [];
else
$labels = $label_cache;
@@ -940,7 +940,7 @@ class Feeds extends Handler_Protected {
$feed_id = PluginHost::feed_to_pfeed_id($feed);
$handler = PluginHost::getInstance()->get_feed_handler($feed_id);
if (implements_interface($handler, 'IVirtualFeed')) {
/** @var IVirtualFeed $handler */
/** @var Plugin&IVirtualFeed $handler */
return $handler->get_unread($feed_id);
} else {
return 0;

View File

@@ -76,7 +76,7 @@ abstract class Plugin {
*
* @return string */
function __($msgid) {
/** @var Plugin $this -- this is a strictly template-related hack */
// this is a strictly template-related hack
return _dgettext(PluginHost::object_to_domain($this), $msgid);
}
@@ -87,7 +87,7 @@ abstract class Plugin {
*
* @return string */
function _ngettext($singular, $plural, $number) {
/** @var Plugin $this -- this is a strictly template-related hack */
// this is a strictly template-related hack
return _dngettext(PluginHost::object_to_domain($this), $singular, $plural, $number);
}

View File

@@ -386,6 +386,7 @@ class PluginHost {
* @param PluginHost::HOOK_* $type
*/
function del_hook(string $type, Plugin $sender): void {
/** @phpstan-ignore function.alreadyNarrowedType ($type might not exist) */
if (is_array($this->hooks[$type])) {
foreach (array_keys($this->hooks[$type]) as $prio) {
$key = array_search($sender, $this->hooks[$type][$prio]);
@@ -589,7 +590,7 @@ class PluginHost {
}
}
/** @return array<string, array{'description': string, 'suffix': string, 'arghelp': string, 'class': Plugin}>> command type -> details array */
/** @return array<string, array{'description': string, 'suffix': string, 'arghelp': string, 'class': Plugin}> command type -> details array */
function get_commands() {
return $this->commands;
}

View File

@@ -240,8 +240,7 @@ class Pref_Feeds extends Handler_Protected {
/**
* Uncategorized is a special case.
*
* Define a minimal array shape to help PHPStan with the type of $cat['items']
* @var array{items: array<int, array<string, mixed>>} $cat
* @var array{id: string, bare_id: int, auxcounter: int, name: string, items: array<int, array<string, mixed>>, type: 'category', checkbox: bool, unread: int, child_unread: int}
*/
$cat = [
'id' => 'CAT:0',

View File

@@ -714,7 +714,6 @@ class Pref_Filters extends Handler_Protected {
}
function editrule(): void {
/** @var array<int, int|string> */
$feed_ids = explode(",", clean($_REQUEST["ids"]));
print json_encode([

View File

@@ -177,7 +177,7 @@ class Pref_Prefs extends Handler_Protected {
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
if (implements_interface($authenticator, "IAuthModule2")) {
/** @var IAuthModule2 $authenticator */
/** @var Plugin&IAuthModule2 $authenticator */
print format_notice($authenticator->change_password($_SESSION["uid"], $old_pw, $new_pw));
} else {
print "ERROR: ".format_error("Function not supported by authentication module.");
@@ -976,7 +976,7 @@ class Pref_Prefs extends Handler_Protected {
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
/** @var Auth_Internal|false $authenticator -- this is only here to make check_password() visible to static analyzer */
/** @var Auth_Internal|null $authenticator -- this is only here to make check_password() visible to static analyzer */
if ($authenticator->check_password($_SESSION["uid"], $password)) {
if (UserHelper::enable_otp($_SESSION["uid"], $otp_check)) {
print "OK";
@@ -991,7 +991,7 @@ class Pref_Prefs extends Handler_Protected {
function otpdisable(): void {
$password = clean($_REQUEST["password"]);
/** @var Auth_Internal|false $authenticator -- this is only here to make check_password() visible to static analyzer */
/** @var Auth_Internal|null $authenticator -- this is only here to make check_password() visible to static analyzer */
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
if ($authenticator->check_password($_SESSION["uid"], $password)) {
@@ -1316,14 +1316,8 @@ class Pref_Prefs extends Handler_Protected {
function updateLocalPlugins(): void {
if ($_SESSION["access_level"] >= UserHelper::ACCESS_LEVEL_ADMIN) {
$plugins = explode(",", $_REQUEST["plugins"] ?? "");
if ($plugins !== false) {
$plugins = array_filter($plugins, 'strlen');
}
$plugins = array_filter(explode(",", $_REQUEST["plugins"] ?? ""), "strlen");
$root_dir = Config::get_self_dir();
$rv = [];
if ($plugins) {

View File

@@ -503,7 +503,6 @@ class UserHelper {
return $authenticator->check_password($owner_uid, $password);
} else {
/** @var Auth_Internal|false $authenticator -- this is only here to make check_password() visible to static analyzer */
$authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]);
if ($authenticator &&

View File

@@ -2,40 +2,38 @@
/**
* @param array<int, array<string, mixed>> $trace
*/
function format_backtrace($trace): string {
function format_backtrace(array $trace): string {
$rv = "";
$idx = 1;
if (is_array($trace)) {
foreach ($trace as $e) {
if (isset($e["file"]) && isset($e["line"])) {
$fmt_args = [];
foreach ($trace as $e) {
if (isset($e["file"]) && isset($e["line"])) {
$fmt_args = [];
if (is_array($e["args"] ?? false)) {
foreach ($e["args"] as $a) {
if (is_object($a)) {
array_push($fmt_args, "{" . get_class($a) . "}");
} else if (is_array($a)) {
array_push($fmt_args, "[" . truncate_string(json_encode($a), 256, "...")) . "]";
} else if (is_resource($a)) {
array_push($fmt_args, truncate_string(get_resource_type($a), 256, "..."));
} else if (is_string($a)) {
array_push($fmt_args, truncate_string($a, 256, "..."));
}
if (is_array($e["args"] ?? false)) {
foreach ($e["args"] as $a) {
if (is_object($a)) {
array_push($fmt_args, "{" . get_class($a) . "}");
} else if (is_array($a)) {
array_push($fmt_args, "[" . truncate_string(json_encode($a), 256, "...")) . "]";
} else if (is_resource($a)) {
array_push($fmt_args, truncate_string(get_resource_type($a), 256, "..."));
} else if (is_string($a)) {
array_push($fmt_args, truncate_string($a, 256, "..."));
}
}
$filename = str_replace(dirname(__DIR__) . "/", "", $e["file"]);
$rv .= sprintf("%d. %s(%s): %s(%s)\n",
$idx,
$filename,
$e["line"],
$e["function"],
implode(", ", $fmt_args));
$idx++;
}
$filename = str_replace(dirname(__DIR__) . "/", "", $e["file"]);
$rv .= sprintf("%d. %s(%s): %s(%s)\n",
$idx,
$filename,
$e["line"],
$e["function"],
implode(", ", $fmt_args));
$idx++;
}
}

View File

@@ -123,6 +123,7 @@
// create a list like "en" => 0.8
$langs = array_combine($lang_parse[1], $lang_parse[4]);
/** @phpstan-ignore function.alreadyNarrowedType (PHP 7.4 will return false if array_value has an issue) */
if (is_array($langs)) {
// set default to 1 for any without q factor
foreach ($langs as $lang => $val) {

View File

@@ -39,16 +39,14 @@
<?php
foreach (PluginHost::getInstance()->get_plugins() as $n => $p) {
if (method_exists($p, "get_login_js")) {
$script = $p->get_login_js();
$script = $p->get_login_js();
if ($script) {
echo "try {
$script
} catch (e) {
console.warn('failed to initialize plugin JS: $n', e);
}";
}
if ($script) {
echo "try {
$script
} catch (e) {
console.warn('failed to initialize plugin JS: $n', e);
}";
}
}
?>

View File

@@ -36,8 +36,9 @@
<style type="text/css">
<?php
foreach (PluginHost::getInstance()->get_plugins() as $p) {
if (method_exists($p, "get_css")) {
echo $p->get_css();
$css = $p->get_css();
if ($css) {
echo $css;
}
}
?>
@@ -73,16 +74,14 @@
<script type="text/javascript">
<?php
foreach (PluginHost::getInstance()->get_plugins() as $n => $p) {
if (method_exists($p, "get_js")) {
$script = $p->get_js();
$script = $p->get_js();
if ($script) {
echo "try {
$script
} catch (e) {
console.warn('failed to initialize plugin JS: $n', e);
}";
}
if ($script) {
echo "try {
$script
} catch (e) {
console.warn('failed to initialize plugin JS: $n', e);
}";
}
}
?>

View File

@@ -5,8 +5,17 @@ parameters:
maximumNumberOfProcesses: 4
reportUnmatchedIgnoredErrors: false
ignoreErrors:
- '#Constant.*\b(SUBSTRING_FOR_DATE|SCHEMA_VERSION|SELF_USER_AGENT|LABEL_BASE_INDEX|PLUGIN_FEED_BASE_INDEX)\b.*not found#'
- '#Comparison operation ">" between int<1, max> and 0 is always true.#'
# set_include_path detection issue
- identifier: requireOnce.fileNotFound
# undetected as DOMElement
- '#Call to an undefined method DOMNode::#'
- '#Access to an undefined property DOMNode::#'
- '#expects DOMElement, DOMNode given#'
# allow passing a 'strlen' string, etc. as the array_filter callback
- "/Parameter #2 \\$callback of function array_filter expects .+ '.+' given/"
- message: '##'
paths:
- lib/*

View File

@@ -64,16 +64,14 @@
<script type="text/javascript">
<?php
foreach (PluginHost::getInstance()->get_plugins() as $n => $p) {
if (method_exists($p, "get_prefs_js")) {
$script = $p->get_prefs_js();
$script = $p->get_prefs_js();
if ($script) {
echo "try {
$script
} catch (e) {
console.warn('failed to initialize plugin JS: $n', e);
}";
}
if ($script) {
echo "try {
$script
} catch (e) {
console.warn('failed to initialize plugin JS: $n', e);
}";
}
}
?>