From bf2bb875ab09c1cb51b7ac0a7bb29a79770e435f Mon Sep 17 00:00:00 2001 From: wn_ Date: Thu, 11 Nov 2021 15:57:03 +0000 Subject: Address PHPStan warnings in 'include/sessions.php'. --- include/sessions.php | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) (limited to 'include') diff --git a/include/sessions.php b/include/sessions.php index 26f4e0bca..48afd0a8b 100644 --- a/include/sessions.php +++ b/include/sessions.php @@ -1,9 +1,9 @@ prepare("SELECT data FROM ttrss_sessions WHERE id=?"); @@ -84,7 +84,7 @@ require_once "autoload.php"; } - function ttrss_write ($id, $data) { + function ttrss_write(string $id, string $data): bool { global $session_expire; $data = base64_encode($data); @@ -105,18 +105,18 @@ require_once "autoload.php"; return true; } - function ttrss_close () { + function ttrss_close(): bool { return true; } - function ttrss_destroy($id) { + function ttrss_destroy(string $id): bool { $sth = \Db::pdo()->prepare("DELETE FROM ttrss_sessions WHERE id = ?"); $sth->execute([$id]); return true; } - function ttrss_gc ($expire) { + function ttrss_gc(int $lifetime): bool { \Db::pdo()->query("DELETE FROM ttrss_sessions WHERE expire < " . time()); return true; @@ -126,7 +126,10 @@ require_once "autoload.php"; session_set_save_handler('\Sessions\ttrss_open', '\Sessions\ttrss_close', '\Sessions\ttrss_read', '\Sessions\ttrss_write', '\Sessions\ttrss_destroy', - '\Sessions\ttrss_gc'); + '\Sessions\ttrss_gc'); // @phpstan-ignore-line + // PHPStan complains about '\Sessions\ttrss_gc' if its $lifetime param isn't marked as string, + // but the docs say it's an int. If it is actually a string it'll get coerced to an int. + register_shutdown_function('session_write_close'); if (!defined('NO_SESSION_AUTOSTART')) { -- cgit v1.2.3-54-g00ecf From 03495c11ed69f6311e9c7596cc53c5b15ce82bf6 Mon Sep 17 00:00:00 2001 From: wn_ Date: Thu, 11 Nov 2021 19:59:25 +0000 Subject: Address PHPStan warnings in 'classes/sanitizer.php'. This also includes some minor tweaks to things that call 'Sanitizer::sanitize()'. --- classes/api.php | 4 ++-- classes/feeds.php | 2 +- classes/handler/public.php | 4 ++-- classes/sanitizer.php | 19 ++++++++++++++----- include/functions.php | 10 ++++++++-- plugins/share/init.php | 2 +- 6 files changed, 28 insertions(+), 13 deletions(-) (limited to 'include') diff --git a/classes/api.php b/classes/api.php index 033aa8654..7d6ac174c 100755 --- a/classes/api.php +++ b/classes/api.php @@ -351,7 +351,7 @@ class API extends Handler { $article['content'] = Sanitizer::sanitize( $entry->content, self::_param_to_bool($entry->hide_images), - false, $entry->site_url, false, $entry->id); + null, $entry->site_url, null, $entry->id); } else { $article['content'] = $entry->content; } @@ -746,7 +746,7 @@ class API extends Handler { $headline_row["content"] = Sanitizer::sanitize( $line["content"], self::_param_to_bool($line['hide_images']), - false, $line["site_url"], false, $line["id"]); + null, $line["site_url"], null, $line["id"]); } else { $headline_row["content"] = $line["content"]; } diff --git a/classes/feeds.php b/classes/feeds.php index cd2633ffb..20aa9c05d 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -271,7 +271,7 @@ class Feeds extends Handler_Protected { $this->_mark_timestamp(" pre-sanitize"); $line["content"] = Sanitizer::sanitize($line["content"], - $line['hide_images'], false, $line["site_url"], $highlight_words, $line["id"]); + $line['hide_images'], null, $line["site_url"], $highlight_words, $line["id"]); $this->_mark_timestamp(" sanitize"); diff --git a/classes/handler/public.php b/classes/handler/public.php index 14474d0bb..9a9f7b892 100755 --- a/classes/handler/public.php +++ b/classes/handler/public.php @@ -109,7 +109,7 @@ class Handler_Public extends Handler { $tpl->setVariable('ARTICLE_EXCERPT', $line["content_preview"], true); $content = Sanitizer::sanitize($line["content"], false, $owner_uid, - $feed_site_url, false, $line["id"]); + $feed_site_url, null, $line["id"]); $content = DiskCache::rewrite_urls($content); @@ -207,7 +207,7 @@ class Handler_Public extends Handler { $article['link'] = $line['link']; $article['title'] = $line['title']; $article['excerpt'] = $line["content_preview"]; - $article['content'] = Sanitizer::sanitize($line["content"], false, $owner_uid, $feed_site_url, false, $line["id"]); + $article['content'] = Sanitizer::sanitize($line["content"], false, $owner_uid, $feed_site_url, null, $line["id"]); $article['updated'] = date('c', strtotime($line["updated"])); if (!empty($line['note'])) $article['note'] = $line['note']; diff --git a/classes/sanitizer.php b/classes/sanitizer.php index 3f6e9504e..2770aece2 100644 --- a/classes/sanitizer.php +++ b/classes/sanitizer.php @@ -1,6 +1,10 @@ $allowed_elements + * @param array $disallowed_attributes + */ + private static function strip_harmful_tags(DOMDocument $doc, array $allowed_elements, $disallowed_attributes): DOMDocument { $xpath = new DOMXPath($doc); $entries = $xpath->query('//*'); @@ -40,7 +44,7 @@ class Sanitizer { return $doc; } - public static function iframe_whitelisted($entry) { + public static function iframe_whitelisted(DOMNode $entry): bool { $src = parse_url($entry->getAttribute("src"), PHP_URL_HOST); if (!empty($src)) @@ -49,11 +53,16 @@ class Sanitizer { return false; } - private static function is_prefix_https() { + private static function is_prefix_https(): bool { return parse_url(Config::get(Config::SELF_URL_PATH), PHP_URL_SCHEME) == 'https'; } - public static function sanitize($str, $force_remove_images = false, $owner = false, $site_url = false, $highlight_words = false, $article_id = false) { + /** + * @param array|null $highlight_words Words to highlight in the HTML output. + * + * @return false|string The HTML, or false if an error occurred. + */ + public static function sanitize(string $str, bool $force_remove_images = false, int $owner = null, string $site_url = null, array $highlight_words = null, int $article_id = null) { if (!$owner && isset($_SESSION["uid"])) $owner = $_SESSION["uid"]; @@ -183,7 +192,7 @@ class Sanitizer { $div->appendChild($entry); } - if ($highlight_words && is_array($highlight_words)) { + if (is_array($highlight_words)) { foreach ($highlight_words as $word) { // http://stackoverflow.com/questions/4081372/highlight-keywords-in-a-paragraph diff --git a/include/functions.php b/include/functions.php index 36519fd44..238cbe7f5 100644 --- a/include/functions.php +++ b/include/functions.php @@ -181,8 +181,14 @@ return Feeds::_get_counters($feed, $is_cat, true, $_SESSION["uid"]); } - /** function is @deprecated by Sanitizer::sanitize() */ - function sanitize($str, $force_remove_images = false, $owner = false, $site_url = false, $highlight_words = false, $article_id = false) { + /** + * @deprecated by Sanitizer::sanitize() + * + * @param array|null $highlight_words Words to highlight in the HTML output. + * + * @return false|string The HTML, or false if an error occurred. + */ + function sanitize(string $str, bool $force_remove_images = false, int $owner = null, string $site_url = null, array $highlight_words = null, int $article_id = null) { return Sanitizer::sanitize($str, $force_remove_images, $owner, $site_url, $highlight_words, $article_id); } diff --git a/plugins/share/init.php b/plugins/share/init.php index 359d86802..8da417e52 100644 --- a/plugins/share/init.php +++ b/plugins/share/init.php @@ -133,7 +133,7 @@ class Share extends Plugin { $line["content"] = Sanitizer::sanitize($line["content"], $line['hide_images'], - $owner_uid, $line["site_url"], false, $line["id"]); + $owner_uid, $line["site_url"], null, $line["id"]); PluginHost::getInstance()->chain_hooks_callback(PluginHost::HOOK_RENDER_ARTICLE, function ($result) use (&$line) { -- cgit v1.2.3-54-g00ecf From f704d25ab15c5ffd988403d36b90fe76fb72916e Mon Sep 17 00:00:00 2001 From: wn_ Date: Thu, 11 Nov 2021 20:12:47 +0000 Subject: Address PHPStan warnings in 'classes/timehelper.php'. --- classes/feeds.php | 2 +- classes/timehelper.php | 8 ++++---- include/functions.php | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'include') diff --git a/classes/feeds.php b/classes/feeds.php index 20aa9c05d..529a8e403 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -299,7 +299,7 @@ class Feeds extends Handler_Protected { $this->_mark_timestamp(" enclosures"); $line["updated_long"] = TimeHelper::make_local_datetime($line["updated"],true); - $line["updated"] = TimeHelper::make_local_datetime($line["updated"], false, false, false, true); + $line["updated"] = TimeHelper::make_local_datetime($line["updated"], false, null, false, true); $line['imported'] = T_sprintf("Imported at %s", TimeHelper::make_local_datetime($line["date_entered"], false)); diff --git a/classes/timehelper.php b/classes/timehelper.php index 4317f343f..e66f82f90 100644 --- a/classes/timehelper.php +++ b/classes/timehelper.php @@ -1,7 +1,7 @@ Date: Thu, 11 Nov 2021 20:36:37 +0000 Subject: Address PHPStan warnings in 'include/controls.php'. --- include/controls.php | 70 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 15 deletions(-) (limited to 'include') diff --git a/include/controls.php b/include/controls.php index a1a1bc59b..46bcf56a0 100755 --- a/include/controls.php +++ b/include/controls.php @@ -1,7 +1,10 @@ $attributes + */ + function attributes_to_string(array $attributes): string { $rv = []; foreach ($attributes as $k => $v) { @@ -21,21 +24,27 @@ return hidden_tag("op", strtolower(get_class($plugin) . \PluginHost::PUBLIC_METHOD_DELIMITER . $method)); } */ - function public_method_tags(\Plugin $plugin, string $method) { + function public_method_tags(\Plugin $plugin, string $method): string { return hidden_tag("op", strtolower(get_class($plugin) . \PluginHost::PUBLIC_METHOD_DELIMITER . $method)); } - function pluginhandler_tags(\Plugin $plugin, string $method) { + function pluginhandler_tags(\Plugin $plugin, string $method): string { return hidden_tag("op", "pluginhandler") . hidden_tag("plugin", strtolower(get_class($plugin))) . hidden_tag("method", $method); } - function button_tag(string $value, string $type, array $attributes = []) { + /** + * @param array $attributes + */ + function button_tag(string $value, string $type, array $attributes = []): string { return ""; } - function input_tag(string $name, string $value, string $type = "text", array $attributes = [], string $id = "") { + /** + * @param array $attributes + */ + function input_tag(string $name, string $value, string $type = "text", array $attributes = [], string $id = ""): string { $attributes_str = attributes_to_string($attributes); $dojo_type = strpos($attributes_str, "dojoType") === false ? "dojoType='dijit.form.TextBox'" : ""; @@ -43,23 +52,40 @@ type=\"$type\" value=\"".htmlspecialchars($value)."\">"; } - function number_spinner_tag(string $name, string $value, array $attributes = [], string $id = "") { + /** + * @param array $attributes + */ + function number_spinner_tag(string $name, string $value, array $attributes = [], string $id = ""): string { return input_tag($name, $value, "text", array_merge(["dojoType" => "dijit.form.NumberSpinner"], $attributes), $id); } - function submit_tag(string $value, array $attributes = []) { + /** + * @param array $attributes + */ + function submit_tag(string $value, array $attributes = []): string { return button_tag($value, "submit", array_merge(["class" => "alt-primary"], $attributes)); } - function cancel_dialog_tag(string $value, array $attributes = []) { + /** + * @param array $attributes + */ + function cancel_dialog_tag(string $value, array $attributes = []): string { return button_tag($value, "", array_merge(["onclick" => "App.dialogOf(this).hide()"], $attributes)); } - function icon(string $icon, array $attributes = []) { + /** + * @param array $attributes + */ + function icon(string $icon, array $attributes = []): string { return "$icon"; } - function select_tag(string $name, $value, array $values, array $attributes = [], string $id = "") { + /** + * @param mixed $value + * @param array $values + * @param array $attributes + */ + function select_tag(string $name, $value, array $values, array $attributes = [], string $id = ""): string { $attributes_str = attributes_to_string($attributes); $dojo_type = strpos($attributes_str, "dojoType") === false ? "dojoType='fox.form.Select'" : ""; @@ -83,7 +109,12 @@ return select_tag($name, $value, $values, $attributes, $id); }*/ - function select_hash(string $name, $value, array $values, array $attributes = [], string $id = "") { + /** + * @param mixed $value + * @param array $values + * @param array $attributes + */ + function select_hash(string $name, $value, array $values, array $attributes = [], string $id = ""): string { $attributes_str = attributes_to_string($attributes); $dojo_type = strpos($attributes_str, "dojoType") === false ? "dojoType='fox.form.Select'" : ""; @@ -93,7 +124,7 @@ foreach ($values as $k => $v) { $is_sel = ($k == $value) ? "selected=\"selected\"" : ""; - $rv .= ""; + $rv .= ""; } $rv .= ""; @@ -101,13 +132,19 @@ return $rv; } - function hidden_tag(string $name, string $value, array $attributes = []) { + /** + * @param array $attributes + */ + function hidden_tag(string $name, string $value, array $attributes = []): string { return ""; } - function checkbox_tag(string $name, bool $checked = false, string $value = "", array $attributes = [], string $id = "") { + /** + * @param array $attributes + */ + function checkbox_tag(string $name, bool $checked = false, string $value = "", array $attributes = [], string $id = ""): string { $is_checked = $checked ? "checked" : ""; $value_str = $value ? "value=\"".htmlspecialchars($value)."\"" : ""; @@ -115,8 +152,11 @@ $value_str $is_checked ".attributes_to_string($attributes)." id=\"".htmlspecialchars($id)."\">"; } + /** + * @param array $attributes + */ function select_feeds_cats(string $name, int $default_id = null, array $attributes = [], - bool $include_all_cats = true, string $root_id = null, int $nest_level = 0, string $id = "") { + bool $include_all_cats = true, string $root_id = null, int $nest_level = 0, string $id = ""): string { $ret = ""; -- cgit v1.2.3-54-g00ecf From e4b8e2d0631825ff0d3fa7bd5eb6e88414facd92 Mon Sep 17 00:00:00 2001 From: wn_ Date: Thu, 11 Nov 2021 20:40:30 +0000 Subject: Address PHPStan warnings in 'include/controls_compat.php'. --- include/controls_compat.php | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'include') diff --git a/include/controls_compat.php b/include/controls_compat.php index d1c2c12b5..5a2a9f2ba 100644 --- a/include/controls_compat.php +++ b/include/controls_compat.php @@ -1,7 +1,9 @@ $attributes + */ +function stylesheet_tag(string $filename, array $attributes = []): string { $attributes_str = \Controls\attributes_to_string( array_merge( @@ -16,7 +18,10 @@ function stylesheet_tag($filename, $attributes = []) { return "\n"; } -function javascript_tag($filename, $attributes = []) { +/** + * @param array $attributes + */ +function javascript_tag(string $filename, array $attributes = []): string { $attributes_str = \Controls\attributes_to_string( array_merge( [ @@ -29,26 +34,26 @@ function javascript_tag($filename, $attributes = []) { return "\n"; } -function format_warning($msg, $id = "") { +function format_warning(string $msg, string $id = ""): string { return "
$msg
"; } -function format_notice($msg, $id = "") { +function format_notice(string $msg, string $id = ""): string { return "
$msg
"; } -function format_error($msg, $id = "") { +function format_error(string $msg, string $id = ""): string { return "
$msg
"; } -function print_notice($msg) { +function print_notice(string $msg): string { return print format_notice($msg); } -function print_warning($msg) { +function print_warning(string $msg): string { return print format_warning($msg); } -function print_error($msg) { +function print_error(string $msg): string { return print format_error($msg); } -- cgit v1.2.3-54-g00ecf From 00b86bac39f63bc8d23bba470c8f53d5b7c97e6a Mon Sep 17 00:00:00 2001 From: wn_ Date: Thu, 11 Nov 2021 20:46:42 +0000 Subject: Address PHPStan warnings in 'include/errorhandler.php'. --- include/errorhandler.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/errorhandler.php b/include/errorhandler.php index 3211599ba..09d6bd7bc 100644 --- a/include/errorhandler.php +++ b/include/errorhandler.php @@ -1,5 +1,8 @@ > $trace + */ +function format_backtrace($trace): string { $rv = ""; $idx = 1; @@ -39,7 +42,7 @@ function format_backtrace($trace) { return $rv; } -function ttrss_error_handler($errno, $errstr, $file, $line) { +function ttrss_error_handler(int $errno, string $errstr, string $file, int $line): bool { /*if (version_compare(PHP_VERSION, '8.0.0', '<')) { if (error_reporting() == 0 || !$errno) return false; } else { @@ -59,7 +62,7 @@ function ttrss_error_handler($errno, $errstr, $file, $line) { return false; } -function ttrss_fatal_handler() { +function ttrss_fatal_handler(): bool { $error = error_get_last(); if ($error !== NULL) { -- cgit v1.2.3-54-g00ecf From cc220058e075602ed689eb77b402ad4c9a623c79 Mon Sep 17 00:00:00 2001 From: wn_ Date: Thu, 11 Nov 2021 21:37:34 +0000 Subject: Address PHPStan warnings in 'include/functions.php'. --- include/functions.php | 134 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 38 deletions(-) (limited to 'include') diff --git a/include/functions.php b/include/functions.php index 8b112e3fb..af4819f00 100644 --- a/include/functions.php +++ b/include/functions.php @@ -36,15 +36,24 @@ define('SUBSTRING_FOR_DATE', 'SUBSTRING'); } + /** + * @return bool|int|null|string + */ function get_pref(string $pref_name, int $owner_uid = null) { return Prefs::get($pref_name, $owner_uid ? $owner_uid : $_SESSION["uid"], $_SESSION["profile"] ?? null); } - function set_pref(string $pref_name, $value, int $owner_uid = null, bool $strip_tags = true) { + /** + * @param bool|int|string $value + */ + function set_pref(string $pref_name, $value, int $owner_uid = null, bool $strip_tags = true): bool { return Prefs::set($pref_name, $value, $owner_uid ? $owner_uid : $_SESSION["uid"], $_SESSION["profile"] ?? null, $strip_tags); } - function get_translations() { + /** + * @return array + */ + function get_translations(): array { $t = array( "auto" => __("Detect automatically"), "ar_SA" => "العربيّة (Arabic)", @@ -81,7 +90,7 @@ require_once "lib/gettext/gettext.inc.php"; - function startup_gettext() { + function startup_gettext(): void { $selected_locale = ""; @@ -161,23 +170,27 @@ /* compat shims */ - /** function is @deprecated by Config::get_version() */ + /** + * @deprecated by Config::get_version() + * + * @return array|string + */ function get_version() { return Config::get_version(); } /** function is @deprecated by Config::get_schema_version() */ - function get_schema_version() { + function get_schema_version(): int { return Config::get_schema_version(); } /** function is @deprecated by Debug::log() */ - function _debug($msg) { - Debug::log($msg); + function _debug(string $msg): void { + Debug::log($msg); } /** function is @deprecated */ - function getFeedUnread($feed, $is_cat = false) { + function getFeedUnread(int $feed, bool $is_cat = false): int { return Feeds::_get_counters($feed, $is_cat, true, $_SESSION["uid"]); } @@ -192,23 +205,42 @@ return Sanitizer::sanitize($str, $force_remove_images, $owner, $site_url, $highlight_words, $article_id); } - /** function is @deprecated by UrlHelper::fetch() */ + /** + * @deprecated by UrlHelper::fetch() + * + * @param array|string $params + * @return bool|string false if something went wrong, otherwise string contents + */ function fetch_file_contents($params) { return UrlHelper::fetch($params); } - /** function is @deprecated by UrlHelper::rewrite_relative() */ + /** + * @deprecated by UrlHelper::rewrite_relative() + * + * Converts a (possibly) relative URL to a absolute one, using provided base URL. + * Provides some exceptions for additional schemes like data: if called with owning element/attribute. + * + * @param string $base_url Base URL (i.e. from where the document is) + * @param string $rel_url Possibly relative URL in the document + * + * @return string Absolute URL + */ function rewrite_relative_url($base_url, $rel_url) { return UrlHelper::rewrite_relative($base_url, $rel_url); } - /** function is @deprecated by UrlHelper::validate() */ - function validate_url($url) { + /** + * @deprecated by UrlHelper::validate() + * + * @return bool|string false if something went wrong, otherwise the URL string + */ + function validate_url(string $url) { return UrlHelper::validate($url); } /** function is @deprecated by UserHelper::authenticate() */ - function authenticate_user($login, $password, $check_only = false, $service = false) { + function authenticate_user(string $login = null, string $password = null, bool $check_only = false, string $service = null): bool { return UserHelper::authenticate($login, $password, $check_only, $service); } @@ -224,13 +256,19 @@ // this returns Config::SELF_URL_PATH sans ending slash /** function is @deprecated by Config::get_self_url() */ - function get_self_url_prefix() { + function get_self_url_prefix(): string { return Config::get_self_url(); } /* end compat shims */ - // this is used for user http parameters unless HTML code is actually needed + /** + * This is used for user http parameters unless HTML code is actually needed. + * + * @param mixed $param + * + * @return mixed + */ function clean($param) { if (is_array($param)) { return array_map("trim", array_map("strip_tags", $param)); @@ -249,7 +287,7 @@ } } - function make_password($length = 12) { + function make_password(int $length = 12): string { $password = ""; $possible = "0123456789abcdfghjkmnpqrstvwxyzABCDFGHJKMNPQRSTVWXYZ*%+^"; @@ -274,11 +312,11 @@ return $password; } - function validate_csrf($csrf_token) { + function validate_csrf(?string $csrf_token): bool { return isset($csrf_token) && hash_equals($_SESSION['csrf_token'] ?? "", $csrf_token); } - function truncate_string($str, $max_len, $suffix = '…') { + function truncate_string(string $str, int $max_len, string $suffix = '…'): string { if (mb_strlen($str, "utf-8") > $max_len) { return mb_substr($str, 0, $max_len, "utf-8") . $suffix; } else { @@ -286,7 +324,7 @@ } } - function mb_substr_replace($original, $replacement, $position, $length) { + function mb_substr_replace(string $original, string $replacement, int $position, int $length): string { $startString = mb_substr($original, 0, $position, "UTF-8"); $endString = mb_substr($original, $position + $length, mb_strlen($original), "UTF-8"); @@ -295,7 +333,7 @@ return $out; } - function truncate_middle($str, $max_len, $suffix = '…') { + function truncate_middle(string $str, int $max_len, string $suffix = '…'): string { if (mb_strlen($str) > $max_len) { return mb_substr_replace($str, $suffix, $max_len / 2, mb_strlen($str) - $max_len); } else { @@ -303,15 +341,15 @@ } } - function sql_bool_to_bool($s) { + function sql_bool_to_bool(string $s): bool { return $s && ($s !== "f" && $s !== "false"); //no-op for PDO, backwards compat for legacy layer } - function bool_to_sql_bool($s) { + function bool_to_sql_bool(bool $s): int { return $s ? 1 : 0; } - function file_is_locked($filename) { + function file_is_locked(string $filename): bool { if (file_exists(Config::get(Config::LOCK_DIRECTORY) . "/$filename")) { if (function_exists('flock')) { $fp = @fopen(Config::get(Config::LOCK_DIRECTORY) . "/$filename", "r"); @@ -333,7 +371,10 @@ } } - function make_lockfile($filename) { + /** + * @return resource|false A file pointer resource on success, or false on error. + */ + function make_lockfile(string $filename) { $fp = fopen(Config::get(Config::LOCK_DIRECTORY) . "/$filename", "w"); if ($fp && flock($fp, LOCK_EX | LOCK_NB)) { @@ -357,38 +398,44 @@ } } - function checkbox_to_sql_bool($val) { + /** + * @param mixed $val + */ + function checkbox_to_sql_bool($val): int { return ($val == "on") ? 1 : 0; } - function uniqid_short() { + function uniqid_short(): string { return uniqid(base_convert((string)rand(), 10, 36)); } - function T_sprintf() { + function T_sprintf(): string { $args = func_get_args(); return vsprintf(__(array_shift($args)), $args); } - function T_nsprintf() { + function T_nsprintf(): string { $args = func_get_args(); return vsprintf(_ngettext(array_shift($args), array_shift($args), array_shift($args)), $args); } - function init_plugins() { + function init_plugins(): bool { PluginHost::getInstance()->load(Config::get(Config::PLUGINS), PluginHost::KIND_ALL); return true; } if (!function_exists('gzdecode')) { - function gzdecode($string) { // no support for 2nd argument + /** + * @return false|string The decoded string or false if an error occurred. + */ + function gzdecode(string $string) { // no support for 2nd argument return file_get_contents('compress.zlib://data:who/cares;base64,'. base64_encode($string)); } } - function get_random_bytes($length) { + function get_random_bytes(int $length): string { if (function_exists('random_bytes')) { return random_bytes($length); } else if (function_exists('openssl_random_pseudo_bytes')) { @@ -403,7 +450,7 @@ } } - function read_stdin() { + function read_stdin(): ?string { $fp = fopen("php://stdin", "r"); if ($fp) { @@ -415,11 +462,19 @@ return null; } - function implements_interface($class, $interface) { - return in_array($interface, class_implements($class)); + /** + * @param object|string $class + */ + function implements_interface($class, string $interface): bool { + $class_implemented_interfaces = class_implements($class); + + if ($class_implemented_interfaces) { + return in_array($interface, $class_implemented_interfaces); + } + return false; } - function get_theme_path($theme) { + function get_theme_path(string $theme): string { $check = "themes/$theme"; if (file_exists($check)) return $check; @@ -429,15 +484,18 @@ return ""; } - function theme_exists($theme) { + function theme_exists(string $theme): bool { return file_exists("themes/$theme") || file_exists("themes.local/$theme"); } - function arr_qmarks($arr) { + /** + * @param array $arr + */ + function arr_qmarks(array $arr): string { return str_repeat('?,', count($arr) - 1) . '?'; } - function get_scripts_timestamp() { + function get_scripts_timestamp(): int { $files = glob("js/*.js"); $ts = 0; -- cgit v1.2.3-54-g00ecf From abab2a94e8443f205719e9a66c66e3f00a371195 Mon Sep 17 00:00:00 2001 From: wn_ Date: Sun, 14 Nov 2021 20:12:37 +0000 Subject: Address PHPStan warning in 'classes/pref/prefs.php'. Also update 'select_hash' and 'select_tag' values param, which can have int or string keys. --- classes/pref/prefs.php | 237 ++++++++++++++++++++++++++++--------------------- include/controls.php | 6 +- 2 files changed, 141 insertions(+), 102 deletions(-) (limited to 'include') diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php index 025d8fda2..d3a5a1370 100644 --- a/classes/pref/prefs.php +++ b/classes/pref/prefs.php @@ -2,12 +2,21 @@ use chillerlan\QRCode; class Pref_Prefs extends Handler_Protected { - + // TODO: class properties can be switched to PHP typing if/when the minimum PHP_VERSION is raised to 7.4.0+ + /** @var array> */ private $pref_help = []; + + /** @var array> pref items are Prefs::*|Pref_Prefs::BLOCK_SEPARATOR (PHPStan was complaining) */ private $pref_item_map = []; + + /** @var array */ private $pref_help_bottom = []; + + /** @var array */ private $pref_blacklist = []; + private const BLOCK_SEPARATOR = 'BLOCK_SEPARATOR'; + const PI_RES_ALREADY_INSTALLED = "PI_RES_ALREADY_INSTALLED"; const PI_RES_SUCCESS = "PI_RES_SUCCESS"; const PI_ERR_NO_CLASS = "PI_ERR_NO_CLASS"; @@ -17,6 +26,7 @@ class Pref_Prefs extends Handler_Protected { const PI_ERR_PLUGIN_NOT_FOUND = "PI_ERR_PLUGIN_NOT_FOUND"; const PI_ERR_NO_WORKDIR = "PI_ERR_NO_WORKDIR"; + /** @param string $method */ function csrf_ignore($method) : bool { $csrf_ignored = array("index", "updateself", "otpqrcode"); @@ -30,35 +40,35 @@ class Pref_Prefs extends Handler_Protected { __('General') => [ Prefs::USER_LANGUAGE, Prefs::USER_TIMEZONE, - 'BLOCK_SEPARATOR', + self::BLOCK_SEPARATOR, Prefs::USER_CSS_THEME, - 'BLOCK_SEPARATOR', + self::BLOCK_SEPARATOR, Prefs::ENABLE_API_ACCESS, ], __('Feeds') => [ Prefs::DEFAULT_UPDATE_INTERVAL, Prefs::FRESH_ARTICLE_MAX_AGE, Prefs::DEFAULT_SEARCH_LANGUAGE, - 'BLOCK_SEPARATOR', + self::BLOCK_SEPARATOR, Prefs::ENABLE_FEED_CATS, - 'BLOCK_SEPARATOR', + self::BLOCK_SEPARATOR, Prefs::CONFIRM_FEED_CATCHUP, Prefs::ON_CATCHUP_SHOW_NEXT_FEED, - 'BLOCK_SEPARATOR', + self::BLOCK_SEPARATOR, Prefs::HIDE_READ_FEEDS, Prefs::HIDE_READ_SHOWS_SPECIAL, ], __('Articles') => [ Prefs::PURGE_OLD_DAYS, Prefs::PURGE_UNREAD_ARTICLES, - 'BLOCK_SEPARATOR', + self::BLOCK_SEPARATOR, Prefs::COMBINED_DISPLAY_MODE, Prefs::CDM_EXPANDED, Prefs::CDM_ENABLE_GRID, - 'BLOCK_SEPARATOR', + self::BLOCK_SEPARATOR, Prefs::CDM_AUTO_CATCHUP, Prefs::VFEED_GROUP_BY_FEED, - 'BLOCK_SEPARATOR', + self::BLOCK_SEPARATOR, Prefs::SHOW_CONTENT_PREVIEW, Prefs::STRIP_IMAGES, ], @@ -69,12 +79,12 @@ class Pref_Prefs extends Handler_Protected { ], __('Advanced') => [ Prefs::BLACKLISTED_TAGS, - 'BLOCK_SEPARATOR', + self::BLOCK_SEPARATOR, Prefs::LONG_DATE_FORMAT, Prefs::SHORT_DATE_FORMAT, - 'BLOCK_SEPARATOR', + self::BLOCK_SEPARATOR, Prefs::SSL_CERT_SERIAL, - 'BLOCK_SEPARATOR', + self::BLOCK_SEPARATOR, Prefs::DISABLE_CONDITIONAL_COUNTERS, Prefs::HEADLINES_NO_DISTINCT, ], @@ -127,7 +137,7 @@ class Pref_Prefs extends Handler_Protected { ]; } - function changepassword() { + function changepassword(): void { if (Config::get(Config::FORBID_PASSWORD_CHANGES)) { print "ERROR: ".format_error("Access forbidden."); @@ -173,7 +183,7 @@ class Pref_Prefs extends Handler_Protected { } } - function saveconfig() { + function saveconfig(): void { $boolean_prefs = explode(",", clean($_POST["boolean_prefs"])); foreach ($boolean_prefs as $pref) { @@ -223,7 +233,7 @@ class Pref_Prefs extends Handler_Protected { } } - function changePersonalData() { + function changePersonalData(): void { $user = ORM::for_table('ttrss_users')->find_one($_SESSION['uid']); $new_email = clean($_POST['email']); @@ -264,13 +274,13 @@ class Pref_Prefs extends Handler_Protected { print __("Your personal data has been saved."); } - function resetconfig() { + function resetconfig(): void { Prefs::reset($_SESSION["uid"], $_SESSION["profile"]); print "PREFS_NEED_RELOAD"; } - private function index_auth_personal() { + private function index_auth_personal(): void { $user = ORM::for_table('ttrss_users')->find_one($_SESSION['uid']); @@ -310,7 +320,7 @@ class Pref_Prefs extends Handler_Protected { get_plugin($_SESSION["auth_module"]); } else { @@ -385,7 +395,7 @@ class Pref_Prefs extends Handler_Protected { } } - private function index_auth_app_passwords() { + private function index_auth_app_passwords(): void { print_notice("Separate passwords used for API clients. Required if you enable OTP."); ?> @@ -409,7 +419,7 @@ class Pref_Prefs extends Handler_Protected {
@@ -534,35 +544,38 @@ class Pref_Prefs extends Handler_Protected { */ $prefs_available = []; + + /** @var array */ $listed_boolean_prefs = []; - foreach (Prefs::get_all($_SESSION["uid"], $profile) as $line) { + foreach (Prefs::get_all($_SESSION["uid"], $profile) as $pref) { - if (in_array($line["pref_name"], $this->pref_blacklist)) { + if (in_array($pref["pref_name"], $this->pref_blacklist)) { continue; } - if ($profile && in_array($line["pref_name"], Prefs::_PROFILE_BLACKLIST)) { + if ($profile && in_array($pref["pref_name"], Prefs::_PROFILE_BLACKLIST)) { continue; } - $pref_name = $line["pref_name"]; + $pref_name = $pref["pref_name"]; $short_desc = $this->_get_short_desc($pref_name); if (!$short_desc) continue; $prefs_available[$pref_name] = [ - 'type_hint' => $line['type_hint'], - 'value' => $line['value'], + 'type_hint' => $pref['type_hint'], + 'value' => $pref['value'], 'help_text' => $this->_get_help_text($pref_name), 'short_desc' => $short_desc ]; @@ -574,12 +587,12 @@ class Pref_Prefs extends Handler_Protected { foreach ($this->pref_item_map[$section] as $pref_name) { - if ($pref_name == 'BLOCK_SEPARATOR' && !$profile) { + if ($pref_name == self::BLOCK_SEPARATOR && !$profile) { print "
"; continue; } - if ($pref_name == "DEFAULT_SEARCH_LANGUAGE" && Config::get(Config::DB_TYPE) != "pgsql") { + if ($pref_name == Prefs::DEFAULT_SEARCH_LANGUAGE && Config::get(Config::DB_TYPE) != "pgsql") { continue; } @@ -596,17 +609,17 @@ class Pref_Prefs extends Handler_Protected { $value = $item['value']; $type_hint = $item['type_hint']; - if ($pref_name == "USER_LANGUAGE") { + if ($pref_name == Prefs::USER_LANGUAGE) { print \Controls\select_hash($pref_name, $value, get_translations(), ["style" => 'width : 220px; margin : 0px']); - } else if ($pref_name == "USER_TIMEZONE") { + } else if ($pref_name == Prefs::USER_TIMEZONE) { $timezones = explode("\n", file_get_contents("lib/timezones.txt")); print \Controls\select_tag($pref_name, $value, $timezones, ["dojoType" => "dijit.form.FilteringSelect"]); - } else if ($pref_name == "BLACKLISTED_TAGS") { # TODO: other possible