From 57bf56f7945b639d0e39f4c7ad9da161a4a18888 Mon Sep 17 00:00:00 2001 From: wn_ Date: Fri, 12 Nov 2021 01:50:40 +0000 Subject: Address PHPStan warnings in 'classes/article.php'. Also related changes in some other classes. --- classes/article.php | 92 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 30 deletions(-) (limited to 'classes/article.php') diff --git a/classes/article.php b/classes/article.php index 04855ac9d..4af36d1c0 100755 --- a/classes/article.php +++ b/classes/article.php @@ -4,7 +4,11 @@ class Article extends Handler_Protected { const ARTICLE_KIND_VIDEO = 2; const ARTICLE_KIND_YOUTUBE = 3; - function redirect() { + const CATCHUP_MODE_MARK_AS_READ = 0; + const CATCHUP_MODE_MARK_AS_UNREAD = 1; + const CATCHUP_MODE_TOGGLE = 2; + + function redirect(): void { $article = ORM::for_table('ttrss_entries') ->table_alias('e') ->join('ttrss_user_entries', [ 'ref_id', '=', 'e.id'], 'ue') @@ -24,8 +28,7 @@ class Article extends Handler_Protected { print "Article not found or has an empty URL."; } - static function _create_published_article($title, $url, $content, $labels_str, - $owner_uid) { + static function _create_published_article(string $title, string $url, string $content, string $labels_str, int $owner_uid): bool { $guid = 'SHA1:' . sha1("ttshared:" . $url . $owner_uid); // include owner_uid to prevent global GUID clash @@ -158,14 +161,14 @@ class Article extends Handler_Protected { return $rc; } - function printArticleTags() { + function printArticleTags(): void { $id = (int) clean($_REQUEST['id'] ?? 0); print json_encode(["id" => $id, "tags" => self::_get_tags($id)]); } - function setScore() { + function setScore(): void { $ids = array_map("intval", clean($_REQUEST['ids'] ?? [])); $score = (int)clean($_REQUEST['score']); @@ -179,7 +182,7 @@ class Article extends Handler_Protected { print json_encode(["id" => $ids, "score" => $score]); } - function setArticleTags() { + function setArticleTags(): void { $id = clean($_REQUEST["id"]); @@ -254,18 +257,18 @@ class Article extends Handler_Protected { print ""; }*/ - function assigntolabel() { - return $this->_label_ops(true); + function assigntolabel(): void { + $this->_label_ops(true); } - function removefromlabel() { - return $this->_label_ops(false); + function removefromlabel(): void { + $this->_label_ops(false); } - private function _label_ops($assign) { + private function _label_ops(bool $assign): void { $reply = array(); - $ids = explode(",", clean($_REQUEST["ids"])); + $ids = array_map("intval", explode(",", clean($_REQUEST["ids"] ?? []))); $label_id = clean($_REQUEST["lid"]); $label = Labels::find_caption($label_id, $_SESSION["uid"]); @@ -289,11 +292,10 @@ class Article extends Handler_Protected { print json_encode($reply); } - static function _format_enclosures($id, - $always_display_enclosures, - $article_content, - $hide_images = false) { - + /** + * @return array{'formatted': string, 'entries': array>} + */ + static function _format_enclosures(int $id, bool $always_display_enclosures, string $article_content, bool $hide_images = false): array { $enclosures = self::_get_enclosures($id); $enclosures_formatted = ""; @@ -366,7 +368,10 @@ class Article extends Handler_Protected { return $rv; } - static function _get_tags($id, $owner_uid = 0, $tag_cache = false) { + /** + * @return array + */ + static function _get_tags(int $id, int $owner_uid = 0, ?string $tag_cache = null): array { $a_id = $id; @@ -383,12 +388,14 @@ class Article extends Handler_Protected { /* check cache first */ - if ($tag_cache === false) { + if (!$tag_cache) { $csth = $pdo->prepare("SELECT tag_cache FROM ttrss_user_entries WHERE ref_id = ? AND owner_uid = ?"); $csth->execute([$id, $owner_uid]); - if ($row = $csth->fetch()) $tag_cache = $row["tag_cache"]; + if ($row = $csth->fetch()) { + $tag_cache = $row["tag_cache"]; + } } if ($tag_cache) { @@ -416,7 +423,7 @@ class Article extends Handler_Protected { return $tags; } - function getmetadatabyid() { + function getmetadatabyid(): void { $article = ORM::for_table('ttrss_entries') ->join('ttrss_user_entries', ['ref_id', '=', 'id'], 'ue') ->where('ue.owner_uid', $_SESSION['uid']) @@ -429,7 +436,10 @@ class Article extends Handler_Protected { } } - static function _get_enclosures($id) { + /** + * @return array> + */ + static function _get_enclosures(int $id): array { $encs = ORM::for_table('ttrss_enclosures') ->where('post_id', $id) ->find_many(); @@ -452,7 +462,7 @@ class Article extends Handler_Protected { } - static function _purge_orphans() { + static function _purge_orphans(): void { // purge orphaned posts in main content table @@ -471,7 +481,11 @@ class Article extends Handler_Protected { } } - static function _catchup_by_id($ids, $cmode, $owner_uid = false) { + /** + * @param array $ids + * @param Article::CATCHUP_MODE_* $cmode + */ + static function _catchup_by_id($ids, int $cmode, ?int $owner_uid = null): void { if (!$owner_uid) $owner_uid = $_SESSION["uid"]; @@ -479,11 +493,11 @@ class Article extends Handler_Protected { $ids_qmarks = arr_qmarks($ids); - if ($cmode == 1) { + if ($cmode == Article::CATCHUP_MODE_MARK_AS_UNREAD) { $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = true WHERE ref_id IN ($ids_qmarks) AND owner_uid = ?"); - } else if ($cmode == 2) { + } else if ($cmode == Article::CATCHUP_MODE_TOGGLE) { $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = NOT unread,last_read = NOW() WHERE ref_id IN ($ids_qmarks) AND owner_uid = ?"); @@ -496,7 +510,10 @@ class Article extends Handler_Protected { $sth->execute(array_merge($ids, [$owner_uid])); } - static function _get_labels($id, $owner_uid = false) { + /** + * @return array> + */ + static function _get_labels(int $id, ?int $owner_uid = null): array { $rv = array(); if (!$owner_uid) $owner_uid = $_SESSION["uid"]; @@ -543,6 +560,12 @@ class Article extends Handler_Protected { return $rv; } + /** + * @param array> $enclosures + * @param array $headline + * + * @return array + */ static function _get_image(array $enclosures, string $content, string $site_url, array $headline) { $article_image = ""; @@ -603,14 +626,14 @@ class Article extends Handler_Protected { } if ($article_image) { - $article_image = rewrite_relative_url($site_url, $article_image); + $article_image = UrlHelper::rewrite_relative($site_url, $article_image); if (!$article_kind && (count($enclosures) > 1 || (isset($elems) && $elems->length > 1))) $article_kind = Article::ARTICLE_KIND_ALBUM; } if ($article_stream) - $article_stream = rewrite_relative_url($site_url, $article_stream); + $article_stream = UrlHelper::rewrite_relative($site_url, $article_stream); } $cache = new DiskCache("images"); @@ -624,7 +647,12 @@ class Article extends Handler_Protected { return [$article_image, $article_stream, $article_kind]; } - // only cached, returns label ids (not label feed ids) + /** + * only cached, returns label ids (not label feed ids) + * + * @param array $article_ids + * @return array + */ static function _labels_of(array $article_ids) { if (count($article_ids) == 0) return []; @@ -651,6 +679,10 @@ class Article extends Handler_Protected { return array_unique($rv); } + /** + * @param array $article_ids + * @return array + */ static function _feeds_of(array $article_ids) { if (count($article_ids) == 0) return []; -- cgit v1.2.3-54-g00ecf From 9db5e402a0283deaae7d06496f410e9ab8deb1b4 Mon Sep 17 00:00:00 2001 From: wn_ Date: Fri, 12 Nov 2021 05:42:55 +0000 Subject: Address PHPStan warnings in 'classes/rpc.php'. Also a couple minor fixes in 'classes/article.php' and 'classes/labels.php'. --- classes/article.php | 2 +- classes/labels.php | 2 +- classes/rpc.php | 76 ++++++++++++++++++++++++++++++++++------------------- 3 files changed, 51 insertions(+), 29 deletions(-) (limited to 'classes/article.php') diff --git a/classes/article.php b/classes/article.php index 4af36d1c0..b4f28dc28 100755 --- a/classes/article.php +++ b/classes/article.php @@ -483,7 +483,7 @@ class Article extends Handler_Protected { /** * @param array $ids - * @param Article::CATCHUP_MODE_* $cmode + * @param int $cmode Article::CATCHUP_MODE_* */ static function _catchup_by_id($ids, int $cmode, ?int $owner_uid = null): void { diff --git a/classes/labels.php b/classes/labels.php index d78f92139..5a17d665e 100644 --- a/classes/labels.php +++ b/classes/labels.php @@ -71,7 +71,7 @@ class Labels } /** - * @param array> $labels + * @param array>> $labels * * @see Article::_get_labels() */ diff --git a/classes/rpc.php b/classes/rpc.php index 60119a605..75d008b8b 100755 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -7,7 +7,10 @@ class RPC extends Handler_Protected { return array_search($method, $csrf_ignored) !== false; }*/ - private function _translations_as_array() { + /** + * @return array + */ + private function _translations_as_array(): array { global $text_domains; @@ -37,7 +40,7 @@ class RPC extends Handler_Protected { } - function togglepref() { + function togglepref(): void { $key = clean($_REQUEST["key"]); set_pref($key, !get_pref($key)); $value = get_pref($key); @@ -45,7 +48,7 @@ class RPC extends Handler_Protected { print json_encode(array("param" =>$key, "value" => $value)); } - function setpref() { + function setpref(): void { // set_pref escapes input, so no need to double escape it here $key = clean($_REQUEST['key']); $value = $_REQUEST['value']; @@ -55,7 +58,7 @@ class RPC extends Handler_Protected { print json_encode(array("param" =>$key, "value" => $value)); } - function mark() { + function mark(): void { $mark = clean($_REQUEST["mark"]); $id = clean($_REQUEST["id"]); @@ -68,7 +71,7 @@ class RPC extends Handler_Protected { print json_encode(array("message" => "UPDATE_COUNTERS")); } - function delete() { + function delete(): void { $ids = explode(",", clean($_REQUEST["ids"])); $ids_qmarks = arr_qmarks($ids); @@ -81,7 +84,7 @@ class RPC extends Handler_Protected { print json_encode(array("message" => "UPDATE_COUNTERS")); } - function publ() { + function publ(): void { $pub = clean($_REQUEST["pub"]); $id = clean($_REQUEST["id"]); @@ -94,7 +97,7 @@ class RPC extends Handler_Protected { print json_encode(array("message" => "UPDATE_COUNTERS")); } - function getRuntimeInfo() { + function getRuntimeInfo(): void { $reply = [ 'runtime-info' => $this->_make_runtime_info() ]; @@ -102,7 +105,7 @@ class RPC extends Handler_Protected { print json_encode($reply); } - function getAllCounters() { + function getAllCounters(): void { @$seq = (int) $_REQUEST['seq']; $feed_id_count = (int)$_REQUEST["feed_id_count"]; @@ -133,7 +136,7 @@ class RPC extends Handler_Protected { } /* GET["cmode"] = 0 - mark as read, 1 - as unread, 2 - toggle */ - function catchupSelected() { + function catchupSelected(): void { $ids = array_map("intval", clean($_REQUEST["ids"] ?? [])); $cmode = (int)clean($_REQUEST["cmode"]); @@ -145,7 +148,7 @@ class RPC extends Handler_Protected { "feeds" => Article::_feeds_of($ids)]); } - function markSelected() { + function markSelected(): void { $ids = array_map("intval", clean($_REQUEST["ids"] ?? [])); $cmode = (int)clean($_REQUEST["cmode"]); @@ -157,7 +160,7 @@ class RPC extends Handler_Protected { "feeds" => Article::_feeds_of($ids)]); } - function publishSelected() { + function publishSelected(): void { $ids = array_map("intval", clean($_REQUEST["ids"] ?? [])); $cmode = (int)clean($_REQUEST["cmode"]); @@ -169,7 +172,7 @@ class RPC extends Handler_Protected { "feeds" => Article::_feeds_of($ids)]); } - function sanityCheck() { + function sanityCheck(): void { $_SESSION["hasSandbox"] = clean($_REQUEST["hasSandbox"]) === "true"; $_SESSION["clientTzOffset"] = clean($_REQUEST["clientTzOffset"]); @@ -220,7 +223,7 @@ class RPC extends Handler_Protected { print ""; }*/ - function catchupFeed() { + function catchupFeed(): void { $feed_id = clean($_REQUEST['feed_id']); $is_cat = clean($_REQUEST['is_cat']) == "true"; $mode = clean($_REQUEST['mode'] ?? ''); @@ -235,7 +238,7 @@ class RPC extends Handler_Protected { //print json_encode(array("message" => "UPDATE_COUNTERS")); } - function setWidescreen() { + function setWidescreen(): void { $wide = (int) clean($_REQUEST["wide"]); set_pref(Prefs::WIDESCREEN_MODE, $wide); @@ -243,7 +246,7 @@ class RPC extends Handler_Protected { print json_encode(["wide" => $wide]); } - static function updaterandomfeed_real() { + static function updaterandomfeed_real(): void { $default_interval = (int) Prefs::get_default(Prefs::DEFAULT_UPDATE_INTERVAL); @@ -336,11 +339,14 @@ class RPC extends Handler_Protected { } - function updaterandomfeed() { + function updaterandomfeed(): void { self::updaterandomfeed_real(); } - private function markArticlesById($ids, $cmode) { + /** + * @param array $ids + */ + private function markArticlesById(array $ids, int $cmode): void { $ids_qmarks = arr_qmarks($ids); @@ -361,7 +367,10 @@ class RPC extends Handler_Protected { $sth->execute(array_merge($ids, [$_SESSION['uid']])); } - private function publishArticlesById($ids, $cmode) { + /** + * @param array $ids + */ + private function publishArticlesById(array $ids, int $cmode): void { $ids_qmarks = arr_qmarks($ids); @@ -382,7 +391,7 @@ class RPC extends Handler_Protected { $sth->execute(array_merge($ids, [$_SESSION['uid']])); } - function log() { + function log(): void { $msg = clean($_REQUEST['msg'] ?? ""); $file = basename(clean($_REQUEST['file'] ?? "")); $line = (int) clean($_REQUEST['line'] ?? 0); @@ -396,7 +405,7 @@ class RPC extends Handler_Protected { } } - function checkforupdates() { + function checkforupdates(): void { $rv = ["changeset" => [], "plugins" => []]; $version = Config::get_version(false); @@ -425,7 +434,10 @@ class RPC extends Handler_Protected { print json_encode($rv); } - private function _make_init_params() { + /** + * @return array + */ + private function _make_init_params(): array { $params = array(); foreach ([Prefs::ON_CATCHUP_SHOW_NEXT_FEED, Prefs::HIDE_READ_FEEDS, @@ -481,7 +493,7 @@ class RPC extends Handler_Protected { return $params; } - private function image_to_base64($filename) { + private function image_to_base64(string $filename): string { if (file_exists($filename)) { $ext = pathinfo($filename, PATHINFO_EXTENSION); @@ -493,7 +505,10 @@ class RPC extends Handler_Protected { } } - static function _make_runtime_info() { + /** + * @return array + */ + static function _make_runtime_info(): array { $data = array(); $pdo = Db::pdo(); @@ -562,7 +577,10 @@ class RPC extends Handler_Protected { return $data; } - static function get_hotkeys_info() { + /** + * @return array> + */ + static function get_hotkeys_info(): array { $hotkeys = array( __("Navigation") => array( "next_feed" => __("Open next feed"), @@ -642,8 +660,12 @@ class RPC extends Handler_Protected { return $hotkeys; } - // {3} - 3 panel mode only - // {C} - combined mode only + /** + * {3} - 3 panel mode only + * {C} - combined mode only + * + * @return array{0: array, 1: array} $prefixes, $hotkeys + */ static function get_hotkeys_map() { $hotkeys = array( "k" => "next_feed", @@ -728,7 +750,7 @@ class RPC extends Handler_Protected { return array($prefixes, $hotkeys); } - function hotkeyHelp() { + function hotkeyHelp(): void { $info = self::get_hotkeys_info(); $imap = self::get_hotkeys_map(); $omap = array(); -- cgit v1.2.3-54-g00ecf From b37a03fb31cf1c394e36ccf082bb5d3359f3a1fb Mon Sep 17 00:00:00 2001 From: wn_ Date: Sat, 13 Nov 2021 14:41:22 +0000 Subject: Fix the type of Labels::update_cache() --- classes/article.php | 2 ++ classes/labels.php | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'classes/article.php') diff --git a/classes/article.php b/classes/article.php index b4f28dc28..b720971b9 100755 --- a/classes/article.php +++ b/classes/article.php @@ -553,6 +553,8 @@ class Article extends Handler_Protected { } if (count($rv) > 0) + // PHPStan has issues with the shape of $rv for some reason (array vs non-empty-array). + // @phpstan-ignore-next-line Labels::update_cache($owner_uid, $id, $rv); else Labels::update_cache($owner_uid, $id, array("no-labels" => 1)); diff --git a/classes/labels.php b/classes/labels.php index 5a17d665e..026e6621f 100644 --- a/classes/labels.php +++ b/classes/labels.php @@ -71,7 +71,8 @@ class Labels } /** - * @param array>> $labels + * @param array{'no-labels': 1}|array> $labels + * [label_id, caption, fg_color, bg_color] * * @see Article::_get_labels() */ -- cgit v1.2.3-54-g00ecf From 78acf18b70e3d6ba22e2c2db950e132cfb5d35be Mon Sep 17 00:00:00 2001 From: wn_ Date: Mon, 15 Nov 2021 02:40:45 +0000 Subject: Address PHPStan warnings in FeedItem classes. --- classes/article.php | 2 +- classes/feeditem.php | 30 +++++++++++++++--------- classes/feeditem/atom.php | 57 +++++++++++++++++++++++++++++++-------------- classes/feeditem/common.php | 50 ++++++++++++++++++++++++++++----------- classes/feeditem/rss.php | 41 +++++++++++++++++++++++++------- classes/rssutils.php | 2 +- 6 files changed, 129 insertions(+), 53 deletions(-) (limited to 'classes/article.php') diff --git a/classes/article.php b/classes/article.php index b720971b9..4e25498bc 100755 --- a/classes/article.php +++ b/classes/article.php @@ -189,7 +189,7 @@ class Article extends Handler_Protected { //$tags_str = clean($_REQUEST["tags_str"]); //$tags = array_unique(array_map('trim', explode(",", $tags_str))); - $tags = FeedItem_Common::normalize_categories(explode(",", clean($_REQUEST["tags_str"]))); + $tags = FeedItem_Common::normalize_categories(explode(",", clean($_REQUEST["tags_str"] ?? ""))); $this->pdo->beginTransaction(); diff --git a/classes/feeditem.php b/classes/feeditem.php index 3a5e5dc09..fd7c54883 100644 --- a/classes/feeditem.php +++ b/classes/feeditem.php @@ -1,16 +1,24 @@ */ + abstract function get_categories(): array; + + /** @return array */ + abstract function get_enclosures(): array; + + abstract function get_author(): string; + abstract function get_language(): string; } diff --git a/classes/feeditem/atom.php b/classes/feeditem/atom.php index 51358f36c..36a2e91f5 100755 --- a/classes/feeditem/atom.php +++ b/classes/feeditem/atom.php @@ -2,7 +2,7 @@ class FeedItem_Atom extends FeedItem_Common { const NS_XML = "http://www.w3.org/XML/1998/namespace"; - function get_id() { + function get_id(): string { $id = $this->elem->getElementsByTagName("id")->item(0); if ($id) { @@ -12,6 +12,9 @@ class FeedItem_Atom extends FeedItem_Common { } } + /** + * @return int|false a timestamp on success, false otherwise + */ function get_date() { $updated = $this->elem->getElementsByTagName("updated")->item(0); @@ -30,10 +33,13 @@ class FeedItem_Atom extends FeedItem_Common { if ($date) { return strtotime($date->nodeValue); } + + // consistent with strtotime failing to parse + return false; } - function get_link() { + function get_link(): string { $links = $this->elem->getElementsByTagName("link"); foreach ($links as $link) { @@ -44,24 +50,27 @@ class FeedItem_Atom extends FeedItem_Common { $base = $this->xpath->evaluate("string(ancestor-or-self::*[@xml:base][1]/@xml:base)", $link); if ($base) - return rewrite_relative_url($base, clean(trim($link->getAttribute("href")))); + return UrlHelper::rewrite_relative($base, clean(trim($link->getAttribute("href")))); else return clean(trim($link->getAttribute("href"))); - } } + + return ''; } - function get_title() { + function get_title(): string { $title = $this->elem->getElementsByTagName("title")->item(0); - - if ($title) { - return clean(trim($title->nodeValue)); - } + return $title ? clean(trim($title->nodeValue)) : ''; } - /** $base is optional (returns $content if $base is null), $content is an HTML string */ - private function rewrite_content_to_base($base, $content) { + /** + * @param string|null $base optional (returns $content if $base is null) + * @param string $content an HTML string + * + * @return string the rewritten XML or original $content + */ + private function rewrite_content_to_base(?string $base = null, string $content) { if (!empty($base) && !empty($content)) { @@ -81,14 +90,17 @@ class FeedItem_Atom extends FeedItem_Common { } } - return $tmpdoc->saveXML(); + // Fall back to $content if saveXML somehow fails (i.e. returns false) + $modified_content = $tmpdoc->saveXML(); + return $modified_content !== false ? $modified_content : $content; } } return $content; } - function get_content() { + function get_content(): string { + /** @var DOMElement|null */ $content = $this->elem->getElementsByTagName("content")->item(0); if ($content) { @@ -108,10 +120,13 @@ class FeedItem_Atom extends FeedItem_Common { return $this->rewrite_content_to_base($base, $this->subtree_or_text($content)); } + + return ''; } // TODO: duplicate code should be merged with get_content() - function get_description() { + function get_description(): string { + /** @var DOMElement|null */ $content = $this->elem->getElementsByTagName("summary")->item(0); if ($content) { @@ -132,9 +147,13 @@ class FeedItem_Atom extends FeedItem_Common { return $this->rewrite_content_to_base($base, $this->subtree_or_text($content)); } + return ''; } - function get_categories() { + /** + * @return array + */ + function get_categories(): array { $categories = $this->elem->getElementsByTagName("category"); $cats = []; @@ -152,7 +171,10 @@ class FeedItem_Atom extends FeedItem_Common { return $this->normalize_categories($cats); } - function get_enclosures() { + /** + * @return array + */ + function get_enclosures(): array { $links = $this->elem->getElementsByTagName("link"); $encs = []; @@ -182,7 +204,7 @@ class FeedItem_Atom extends FeedItem_Common { return $encs; } - function get_language() { + function get_language(): string { $lang = $this->elem->getAttributeNS(self::NS_XML, "lang"); if (!empty($lang)) { @@ -195,5 +217,6 @@ class FeedItem_Atom extends FeedItem_Common { } } } + return ''; } } diff --git a/classes/feeditem/common.php b/classes/feeditem/common.php index 18afeaa94..6a9be8aca 100755 --- a/classes/feeditem/common.php +++ b/classes/feeditem/common.php @@ -1,16 +1,20 @@ elem = $elem; $this->xpath = $xpath; $this->doc = $doc; try { - $source = $elem->getElementsByTagName("source")->item(0); // we don't need element @@ -21,11 +25,12 @@ abstract class FeedItem_Common extends FeedItem { } } - function get_element() { + function get_element(): DOMElement { return $this->elem; } - function get_author() { + function get_author(): string { + /** @var DOMElement|null */ $author = $this->elem->getElementsByTagName("author")->item(0); if ($author) { @@ -51,7 +56,7 @@ abstract class FeedItem_Common extends FeedItem { return implode(", ", $authors); } - function get_comments_url() { + function get_comments_url(): string { //RSS only. Use a query here to avoid namespace clashes (e.g. with slash). //might give a wrong result if a default namespace was declared (possible with XPath 2.0) $com_url = $this->xpath->query("comments", $this->elem)->item(0); @@ -65,20 +70,28 @@ abstract class FeedItem_Common extends FeedItem { if ($com_url) return clean($com_url->nodeValue); + + return ''; } - function get_comments_count() { + function get_comments_count(): int { //also query for ATE stuff here $query = "slash:comments|thread:total|atom:link[@rel='replies']/@thread:count"; $comments = $this->xpath->query($query, $this->elem)->item(0); - if ($comments) { - return clean($comments->nodeValue); + if ($comments && is_numeric($comments->nodeValue)) { + return (int) clean($comments->nodeValue); } + + return 0; } - // this is common for both Atom and RSS types and deals with various media: elements - function get_enclosures() { + /** + * this is common for both Atom and RSS types and deals with various 'media:' elements + * + * @return array + */ + function get_enclosures(): array { $encs = []; $enclosures = $this->xpath->query("media:content", $this->elem); @@ -108,6 +121,7 @@ abstract class FeedItem_Common extends FeedItem { foreach ($enclosures as $enclosure) { $enc = new FeedEnclosure(); + /** @var DOMElement|null */ $content = $this->xpath->query("media:content", $enclosure)->item(0); if ($content) { @@ -150,11 +164,14 @@ abstract class FeedItem_Common extends FeedItem { return $encs; } - function count_children($node) { + function count_children(DOMElement $node): int { return $node->getElementsByTagName("*")->length; } - function subtree_or_text($node) { + /** + * @return false|string false on failure, otherwise string contents + */ + function subtree_or_text(DOMElement $node) { if ($this->count_children($node) == 0) { return $node->nodeValue; } else { @@ -162,7 +179,12 @@ abstract class FeedItem_Common extends FeedItem { } } - static function normalize_categories($cats) { + /** + * @param array $cats + * + * @return array + */ + static function normalize_categories(array $cats): array { $tmp = []; diff --git a/classes/feeditem/rss.php b/classes/feeditem/rss.php index 1f7953c51..7017d04e9 100755 --- a/classes/feeditem/rss.php +++ b/classes/feeditem/rss.php @@ -1,6 +1,6 @@ elem->getElementsByTagName("guid")->item(0); if ($id) { @@ -10,6 +10,9 @@ class FeedItem_RSS extends FeedItem_Common { } } + /** + * @return int|false a timestamp on success, false otherwise + */ function get_date() { $pubDate = $this->elem->getElementsByTagName("pubDate")->item(0); @@ -22,9 +25,12 @@ class FeedItem_RSS extends FeedItem_Common { if ($date) { return strtotime($date->nodeValue); } + + // consistent with strtotime failing to parse + return false; } - function get_link() { + function get_link(): string { $links = $this->xpath->query("atom:link", $this->elem); foreach ($links as $link) { @@ -37,6 +43,7 @@ class FeedItem_RSS extends FeedItem_Common { } } + /** @var DOMElement|null */ $link = $this->elem->getElementsByTagName("guid")->item(0); if ($link && $link->hasAttributes() && $link->getAttribute("isPermaLink") == "true") { @@ -48,9 +55,11 @@ class FeedItem_RSS extends FeedItem_Common { if ($link) { return clean(trim($link->nodeValue)); } + + return ''; } - function get_title() { + function get_title(): string { $title = $this->xpath->query("title", $this->elem)->item(0); if ($title) { @@ -64,10 +73,15 @@ class FeedItem_RSS extends FeedItem_Common { if ($title) { return clean(trim($title->nodeValue)); } + + return ''; } - function get_content() { + function get_content(): string { + /** @var DOMElement|null */ $contentA = $this->xpath->query("content:encoded", $this->elem)->item(0); + + /** @var DOMElement|null */ $contentB = $this->elem->getElementsByTagName("description")->item(0); if ($contentA && !$contentB) { @@ -85,17 +99,24 @@ class FeedItem_RSS extends FeedItem_Common { return mb_strlen($resultA) > mb_strlen($resultB) ? $resultA : $resultB; } + + return ''; } - function get_description() { + function get_description(): string { $summary = $this->elem->getElementsByTagName("description")->item(0); if ($summary) { return $summary->nodeValue; } + + return ''; } - function get_categories() { + /** + * @return array + */ + function get_categories(): array { $categories = $this->elem->getElementsByTagName("category"); $cats = []; @@ -112,7 +133,10 @@ class FeedItem_RSS extends FeedItem_Common { return $this->normalize_categories($cats); } - function get_enclosures() { + /** + * @return array + */ + function get_enclosures(): array { $enclosures = $this->elem->getElementsByTagName("enclosure"); $encs = array(); @@ -134,7 +158,7 @@ class FeedItem_RSS extends FeedItem_Common { return $encs; } - function get_language() { + function get_language(): string { $languages = $this->doc->getElementsByTagName('language'); if (count($languages) == 0) { @@ -143,5 +167,4 @@ class FeedItem_RSS extends FeedItem_Common { return clean($languages[0]->textContent); } - } diff --git a/classes/rssutils.php b/classes/rssutils.php index 3815b3ca1..baace6b20 100755 --- a/classes/rssutils.php +++ b/classes/rssutils.php @@ -687,7 +687,7 @@ class RSSUtils { } $entry_comments = mb_substr(strip_tags($item->get_comments_url()), 0, 245); - $num_comments = (int) $item->get_comments_count(); + $num_comments = $item->get_comments_count(); $entry_author = strip_tags($item->get_author()); $entry_guid = mb_substr($entry_guid, 0, 245); -- cgit v1.2.3-54-g00ecf From aa924d9ee7674cfe649d498ce3cbcdb093bca956 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Nov 2021 08:26:02 +0300 Subject: deal with several DOMElement-related errors --- classes/article.php | 1 + classes/feedparser.php | 8 +++++--- plugins/af_comics/filters/af_comics_comicpress.php | 2 +- plugins/af_comics/filters/af_comics_dilbert.php | 2 +- plugins/af_comics/filters/af_comics_gocomics.php | 1 + 5 files changed, 9 insertions(+), 5 deletions(-) (limited to 'classes/article.php') diff --git a/classes/article.php b/classes/article.php index 4e25498bc..baeea059b 100755 --- a/classes/article.php +++ b/classes/article.php @@ -602,6 +602,7 @@ class Article extends Handler_Protected { } else if ($e->nodeName == "video") { $article_image = $e->getAttribute("poster"); + /** @var DOMElement|false $src */ $src = $tmpxpath->query("//source[@src]", $e)->item(0); if ($src) { diff --git a/classes/feedparser.php b/classes/feedparser.php index abf1545f8..dd58df941 100644 --- a/classes/feedparser.php +++ b/classes/feedparser.php @@ -65,10 +65,12 @@ class FeedParser { $this->xpath = $xpath; - $root = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)"); + $root_list = $xpath->query("(//atom03:feed|//atom:feed|//channel|//rdf:rdf|//rdf:RDF)"); - if (!empty($root) && $root->length > 0) { - $root = $root->item(0); + if (!empty($root_list) && $root_list->length > 0) { + + /** @var DOMElement|false $root */ + $root = $root_list->item(0); if ($root) { switch (mb_strtolower($root->tagName)) { diff --git a/plugins/af_comics/filters/af_comics_comicpress.php b/plugins/af_comics/filters/af_comics_comicpress.php index 741d59672..93bfde7e7 100755 --- a/plugins/af_comics/filters/af_comics_comicpress.php +++ b/plugins/af_comics/filters/af_comics_comicpress.php @@ -32,7 +32,7 @@ class Af_Comics_ComicPress extends Af_ComicFilter { return true; } - // buni-specific + /** @var DOMElement|false $webtoon_link (buni specific) */ $webtoon_link = $xpath->query("//a[contains(@href,'www.webtoons.com')]")->item(0); if ($webtoon_link) { diff --git a/plugins/af_comics/filters/af_comics_dilbert.php b/plugins/af_comics/filters/af_comics_dilbert.php index 49fa54cfa..80a8a0221 100644 --- a/plugins/af_comics/filters/af_comics_dilbert.php +++ b/plugins/af_comics/filters/af_comics_dilbert.php @@ -22,7 +22,7 @@ class Af_Comics_Dilbert extends Af_ComicFilter { if ($res && $doc->loadHTML($res)) { $xpath = new DOMXPath($doc); - // Get the image container + /** @var DOMElement|false $basenode (image container) */ $basenode = $xpath->query('(//div[@class="img-comic-container"]/a[@class="img-comic-link"])')->item(0); // Get the comic title diff --git a/plugins/af_comics/filters/af_comics_gocomics.php b/plugins/af_comics/filters/af_comics_gocomics.php index 71d387918..f474312ae 100644 --- a/plugins/af_comics/filters/af_comics_gocomics.php +++ b/plugins/af_comics/filters/af_comics_gocomics.php @@ -50,6 +50,7 @@ class Af_Comics_Gocomics extends Af_ComicFilter { if (@$doc->loadHTML($body)) { $xpath = new DOMXPath($doc); + /** @var DOMElement|false $node */ $node = $xpath->query('//picture[contains(@class, "item-comic-image")]/img')->item(0); if ($node) { -- cgit v1.2.3-54-g00ecf From 109b702ed0cd31a0dc8466b8127882d263705d8d Mon Sep 17 00:00:00 2001 From: wn_ Date: Mon, 15 Nov 2021 12:24:38 +0000 Subject: Minor fix to DOMNodeList#item() potential type (null vs false) --- classes/article.php | 2 +- classes/feedparser.php | 2 +- plugins/af_comics/filters/af_comics_comicpress.php | 2 +- plugins/af_comics/filters/af_comics_dilbert.php | 2 +- plugins/af_comics/filters/af_comics_gocomics.php | 2 +- plugins/af_redditimgur/init.php | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'classes/article.php') diff --git a/classes/article.php b/classes/article.php index baeea059b..1f97f0e16 100755 --- a/classes/article.php +++ b/classes/article.php @@ -602,7 +602,7 @@ class Article extends Handler_Protected { } else if ($e->nodeName == "video") { $article_image = $e->getAttribute("poster"); - /** @var DOMElement|false $src */ + /** @var DOMElement|null $src */ $src = $tmpxpath->query("//source[@src]", $e)->item(0); if ($src) { diff --git a/classes/feedparser.php b/classes/feedparser.php index dd58df941..f5649d2f8 100644 --- a/classes/feedparser.php +++ b/classes/feedparser.php @@ -69,7 +69,7 @@ class FeedParser { if (!empty($root_list) && $root_list->length > 0) { - /** @var DOMElement|false $root */ + /** @var DOMElement|null $root */ $root = $root_list->item(0); if ($root) { diff --git a/plugins/af_comics/filters/af_comics_comicpress.php b/plugins/af_comics/filters/af_comics_comicpress.php index 93bfde7e7..89837d074 100755 --- a/plugins/af_comics/filters/af_comics_comicpress.php +++ b/plugins/af_comics/filters/af_comics_comicpress.php @@ -32,7 +32,7 @@ class Af_Comics_ComicPress extends Af_ComicFilter { return true; } - /** @var DOMElement|false $webtoon_link (buni specific) */ + /** @var DOMElement|null $webtoon_link (buni specific) */ $webtoon_link = $xpath->query("//a[contains(@href,'www.webtoons.com')]")->item(0); if ($webtoon_link) { diff --git a/plugins/af_comics/filters/af_comics_dilbert.php b/plugins/af_comics/filters/af_comics_dilbert.php index 80a8a0221..a1c59b94c 100644 --- a/plugins/af_comics/filters/af_comics_dilbert.php +++ b/plugins/af_comics/filters/af_comics_dilbert.php @@ -22,7 +22,7 @@ class Af_Comics_Dilbert extends Af_ComicFilter { if ($res && $doc->loadHTML($res)) { $xpath = new DOMXPath($doc); - /** @var DOMElement|false $basenode (image container) */ + /** @var DOMElement|null $basenode (image container) */ $basenode = $xpath->query('(//div[@class="img-comic-container"]/a[@class="img-comic-link"])')->item(0); // Get the comic title diff --git a/plugins/af_comics/filters/af_comics_gocomics.php b/plugins/af_comics/filters/af_comics_gocomics.php index f474312ae..732f7d0b8 100644 --- a/plugins/af_comics/filters/af_comics_gocomics.php +++ b/plugins/af_comics/filters/af_comics_gocomics.php @@ -50,7 +50,7 @@ class Af_Comics_Gocomics extends Af_ComicFilter { if (@$doc->loadHTML($body)) { $xpath = new DOMXPath($doc); - /** @var DOMElement|false $node */ + /** @var DOMElement|null $node */ $node = $xpath->query('//picture[contains(@class, "item-comic-image")]/img')->item(0); if ($node) { diff --git a/plugins/af_redditimgur/init.php b/plugins/af_redditimgur/init.php index aeb75df3a..f40d21d35 100755 --- a/plugins/af_redditimgur/init.php +++ b/plugins/af_redditimgur/init.php @@ -287,7 +287,7 @@ class Af_RedditImgur extends Plugin { $this->generated_enclosures = []; - /** @var DOMElement|false $anchor -- embed anchor element, before reddit post layout */ + /** @var DOMElement|null $anchor -- embed anchor element, before reddit
post layout */ $anchor = $xpath->query('//body/*')->item(0); // deal with json-provided media content first -- cgit v1.2.3-54-g00ecf From d78ba7b3a9201b7c9a17d376ac9d2629d761ce5a Mon Sep 17 00:00:00 2001 From: wn_ Date: Tue, 16 Nov 2021 02:14:31 +0000 Subject: Minor fix in 'classes/articles.php'. It looks like these functions are dead code, though. Adding comments for future review. --- classes/article.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'classes/article.php') diff --git a/classes/article.php b/classes/article.php index 1f97f0e16..d14236ea2 100755 --- a/classes/article.php +++ b/classes/article.php @@ -257,18 +257,21 @@ class Article extends Handler_Protected { print ""; }*/ + // TODO: dead code? function assigntolabel(): void { $this->_label_ops(true); } + // TODO: dead code? function removefromlabel(): void { $this->_label_ops(false); } + // TODO: dead code? private function _label_ops(bool $assign): void { $reply = array(); - $ids = array_map("intval", explode(",", clean($_REQUEST["ids"] ?? []))); + $ids = array_map("intval", array_filter(explode(",", clean($_REQUEST["ids"] ?? "")), "strlen")); $label_id = clean($_REQUEST["lid"]); $label = Labels::find_caption($label_id, $_SESSION["uid"]); -- cgit v1.2.3-54-g00ecf From ad30d39e2a910a420f3116ade1bbe8b5f7f9df88 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Tue, 16 Nov 2021 15:45:35 +0300 Subject: not dead: Article.assigntolabel etc are exported methods called by frontend (Headlines.js) --- classes/article.php | 3 --- 1 file changed, 3 deletions(-) (limited to 'classes/article.php') diff --git a/classes/article.php b/classes/article.php index d14236ea2..e113ed219 100755 --- a/classes/article.php +++ b/classes/article.php @@ -257,17 +257,14 @@ class Article extends Handler_Protected { print ""; }*/ - // TODO: dead code? function assigntolabel(): void { $this->_label_ops(true); } - // TODO: dead code? function removefromlabel(): void { $this->_label_ops(false); } - // TODO: dead code? private function _label_ops(bool $assign): void { $reply = array(); -- cgit v1.2.3-54-g00ecf