From 020f062a76746a313fae9c82fbcf9b37fcc9d459 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Feb 2021 15:43:07 +0300 Subject: feeds: unify naming --- classes/counters.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'classes/counters.php') diff --git a/classes/counters.php b/classes/counters.php index 59605df18..29ced3d6c 100644 --- a/classes/counters.php +++ b/classes/counters.php @@ -25,8 +25,8 @@ class Counters { while ($line = $sth->fetch()) { list ($tmp_unread, $tmp_marked) = self::getCategoryChildrenCounters($line["id"], $owner_uid); - $unread += $tmp_unread + Feeds::getCategoryUnread($line["id"], $owner_uid); - $marked += $tmp_marked + Feeds::getCategoryMarked($line["id"], $owner_uid); + $unread += $tmp_unread + Feeds::_get_cat_unread($line["id"], $owner_uid); + $marked += $tmp_marked + Feeds::_get_cat_marked($line["id"], $owner_uid); } return [$unread, $marked]; @@ -38,7 +38,7 @@ class Counters { /* Labels category */ $cv = array("id" => -2, "kind" => "cat", - "counter" => Feeds::getCategoryUnread(-2)); + "counter" => Feeds::_get_cat_unread(-2)); array_push($ret, $cv); @@ -114,8 +114,8 @@ class Counters { $last_error = htmlspecialchars($line["last_error"]); $last_updated = TimeHelper::make_local_datetime($line['last_updated'], false); - if (Feeds::feedHasIcon($id)) { - $has_img = filemtime(Feeds::getIconFile($id)); + if (Feeds::_has_icon($id)) { + $has_img = filemtime(Feeds::_get_icon_file($id)); } else { $has_img = false; } @@ -149,7 +149,7 @@ class Counters { $ret = []; if ($global_unread == -1) { - $global_unread = Feeds::getGlobalUnread(); + $global_unread = Feeds::_get_global_unread(); } $cv = [ @@ -187,7 +187,7 @@ class Counters { $count = getFeedUnread($i); if ($i == 0 || $i == -1 || $i == -2) - $auxctr = Feeds::getFeedArticles($i, false); + $auxctr = Feeds::_get_counters($i, false); else $auxctr = 0; -- cgit v1.2.3-54-g00ecf From 5704deb460f740ed56be5ae4dbddbf5296a9c603 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Feb 2021 16:00:54 +0300 Subject: counters: unify naming --- classes/api.php | 4 ++-- classes/counters.php | 22 +++++++++++----------- classes/rpc.php | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) (limited to 'classes/counters.php') diff --git a/classes/api.php b/classes/api.php index 4d1c15598..62ce1764c 100755 --- a/classes/api.php +++ b/classes/api.php @@ -102,7 +102,7 @@ class API extends Handler { /* Method added for ttrss-reader for Android */ function getCounters() { - $this->wrap(self::STATUS_OK, Counters::getAllCounters()); + $this->wrap(self::STATUS_OK, Counters::get_all()); } function getFeeds() { @@ -510,7 +510,7 @@ class API extends Handler { /* API only: -4 All feeds, including virtual feeds */ if ($cat_id == -4 || $cat_id == -2) { - $counters = Counters::getLabelCounters(true); + $counters = Counters::get_labels(true); foreach (array_values($counters) as $cv) { diff --git a/classes/counters.php b/classes/counters.php index 29ced3d6c..e8c179a95 100644 --- a/classes/counters.php +++ b/classes/counters.php @@ -1,13 +1,13 @@ Counters::getAllCounters(), + 'counters' => Counters::get_all(), 'seq' => $seq ]; @@ -222,7 +222,7 @@ class RPC extends Handler_Protected { Feeds::_catchup($feed_id, $is_cat, false, $mode, [$search_query, $search_lang]); // return counters here synchronously so that frontend can figure out next unread feed properly - print json_encode(['counters' => Counters::getAllCounters()]); + print json_encode(['counters' => Counters::get_all()]); //print json_encode(array("message" => "UPDATE_COUNTERS")); } -- cgit v1.2.3-54-g00ecf From 71f2f4288f33152653f759755f351a200506b80a Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Feb 2021 16:14:48 +0300 Subject: counters: one more --- classes/counters.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'classes/counters.php') diff --git a/classes/counters.php b/classes/counters.php index e8c179a95..8392df32f 100644 --- a/classes/counters.php +++ b/classes/counters.php @@ -12,7 +12,7 @@ class Counters { return $data; } - static private function getCategoryChildrenCounters($cat_id, $owner_uid) { + static private function get_cat_children($cat_id, $owner_uid) { $pdo = Db::pdo(); $sth = $pdo->prepare("SELECT id FROM ttrss_feed_categories WHERE parent_cat = ? @@ -23,7 +23,7 @@ class Counters { $marked = 0; while ($line = $sth->fetch()) { - list ($tmp_unread, $tmp_marked) = self::getCategoryChildrenCounters($line["id"], $owner_uid); + list ($tmp_unread, $tmp_marked) = self::get_cat_children($line["id"], $owner_uid); $unread += $tmp_unread + Feeds::_get_cat_unread($line["id"], $owner_uid); $marked += $tmp_marked + Feeds::_get_cat_marked($line["id"], $owner_uid); @@ -68,7 +68,7 @@ class Counters { while ($line = $sth->fetch()) { if ($line["num_children"] > 0) { - list ($child_counter, $child_marked_counter) = self::getCategoryChildrenCounters($line["id"], $_SESSION["uid"]); + list ($child_counter, $child_marked_counter) = self::get_cat_children($line["id"], $_SESSION["uid"]); } else { $child_counter = 0; $child_marked_counter = 0; -- cgit v1.2.3-54-g00ecf From d4157b9e4e494e737038f6a00e921bc93b234780 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Mon, 15 Feb 2021 17:01:05 +0300 Subject: counters: just merge everything at once --- classes/counters.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'classes/counters.php') diff --git a/classes/counters.php b/classes/counters.php index 8392df32f..fb2553ec2 100644 --- a/classes/counters.php +++ b/classes/counters.php @@ -2,14 +2,13 @@ class Counters { static function get_all() { - $data = self::get_global(); - - $data = array_merge($data, self::get_virt(), + return array_merge( + self::get_global(), + self::get_virt(), self::get_labels(), self::get_feeds(), - self::get_cats()); - - return $data; + self::get_cats() + ); } static private function get_cat_children($cat_id, $owner_uid) { -- cgit v1.2.3-54-g00ecf From d6203bf3508ba77e3943ddc412eb562edb327f22 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Wed, 24 Feb 2021 09:47:26 +0300 Subject: try to calculate counters conditionally based on feed ids --- classes/article.php | 16 +++++++ classes/counters.php | 126 ++++++++++++++++++++++++++++++++++++--------------- classes/feeds.php | 26 ++++++++++- classes/rpc.php | 32 +++++++++---- js/App.js | 4 +- js/Feeds.js | 10 ++-- js/Headlines.js | 18 ++++---- 7 files changed, 170 insertions(+), 62 deletions(-) (limited to 'classes/counters.php') diff --git a/classes/article.php b/classes/article.php index a2a38118b..4bf563c4b 100755 --- a/classes/article.php +++ b/classes/article.php @@ -640,4 +640,20 @@ class Article extends Handler_Protected { return [$article_image, $article_stream, $article_kind]; } + static function _feeds_of(array $article_ids) { + $id_qmarks = arr_qmarks($article_ids); + + $sth = DB::pdo()->prepare("SELECT DISTINCT feed_id FROM ttrss_entries e, ttrss_user_entries ue + WHERE ue.ref_id = e.id AND id IN ($id_qmarks)"); + + $sth->execute($article_ids); + + $rv = []; + + while ($row = $sth->fetch()) { + array_push($rv, $row["feed_id"]); + } + + return $rv; + } } diff --git a/classes/counters.php b/classes/counters.php index fb2553ec2..b4309cf7b 100644 --- a/classes/counters.php +++ b/classes/counters.php @@ -11,6 +11,15 @@ class Counters { ); } + static function get_for_feeds($feed_ids) { + return array_merge( + self::get_global(), + self::get_virt(), + self::get_labels(), + self::get_feeds($feed_ids), + self::get_cats(Feeds::_cats_of($feed_ids, $_SESSION["uid"], true))); + } + static private function get_cat_children($cat_id, $owner_uid) { $pdo = Db::pdo(); @@ -31,7 +40,7 @@ class Counters { return [$unread, $marked]; } - private static function get_cats() { + private static function get_cats(array $cat_ids = []) { $ret = []; /* Labels category */ @@ -43,27 +52,57 @@ class Counters { $pdo = Db::pdo(); - $sth = $pdo->prepare("SELECT fc.id, - SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, - SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked, - (SELECT COUNT(id) FROM ttrss_feed_categories fcc - WHERE fcc.parent_cat = fc.id) AS num_children - FROM ttrss_feed_categories fc - LEFT JOIN ttrss_feeds f ON (f.cat_id = fc.id) - LEFT JOIN ttrss_user_entries ue ON (ue.feed_id = f.id) - WHERE fc.owner_uid = :uid - GROUP BY fc.id - UNION - SELECT 0, - SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, - SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked, - 0 - FROM ttrss_feeds f, ttrss_user_entries ue - WHERE f.cat_id IS NULL AND - ue.feed_id = f.id AND - ue.owner_uid = :uid"); - - $sth->execute(["uid" => $_SESSION['uid']]); + if (count($cat_ids) == 0) { + $sth = $pdo->prepare("SELECT fc.id, + SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, + SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked, + (SELECT COUNT(id) FROM ttrss_feed_categories fcc + WHERE fcc.parent_cat = fc.id) AS num_children + FROM ttrss_feed_categories fc + LEFT JOIN ttrss_feeds f ON (f.cat_id = fc.id) + LEFT JOIN ttrss_user_entries ue ON (ue.feed_id = f.id) + WHERE fc.owner_uid = :uid + GROUP BY fc.id + UNION + SELECT 0, + SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, + SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked, + 0 + FROM ttrss_feeds f, ttrss_user_entries ue + WHERE f.cat_id IS NULL AND + ue.feed_id = f.id AND + ue.owner_uid = :uid"); + + $sth->execute(["uid" => $_SESSION['uid']]); + } else { + $cat_ids_qmarks = arr_qmarks($cat_ids); + + $sth = $pdo->prepare("SELECT fc.id, + SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, + SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked, + (SELECT COUNT(id) FROM ttrss_feed_categories fcc + WHERE fcc.parent_cat = fc.id) AS num_children + FROM ttrss_feed_categories fc + LEFT JOIN ttrss_feeds f ON (f.cat_id = fc.id) + LEFT JOIN ttrss_user_entries ue ON (ue.feed_id = f.id) + WHERE fc.owner_uid = ? AND fc.id IN ($cat_ids_qmarks) + GROUP BY fc.id + UNION + SELECT 0, + SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, + SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked, + 0 + FROM ttrss_feeds f, ttrss_user_entries ue + WHERE f.cat_id IS NULL AND + ue.feed_id = f.id AND + ue.owner_uid = ?"); + + $sth->execute(array_merge( + [$_SESSION['uid']], + $cat_ids, + [$_SESSION['uid']] + )); + } while ($line = $sth->fetch()) { if ($line["num_children"] > 0) { @@ -83,29 +122,42 @@ class Counters { array_push($ret, $cv); } - array_push($ret, $cv); - return $ret; } - - private static function get_feeds($active_feed = false) { + private static function get_feeds(array $feed_ids = []) { $ret = []; $pdo = Db::pdo(); - $sth = $pdo->prepare("SELECT f.id, - f.title, - ".SUBSTRING_FOR_DATE."(f.last_updated,1,19) AS last_updated, - f.last_error, - SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, - SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked - FROM ttrss_feeds f, ttrss_user_entries ue - WHERE f.id = ue.feed_id AND ue.owner_uid = :uid - GROUP BY f.id"); - - $sth->execute(["uid" => $_SESSION['uid']]); + if (count($feed_ids) == 0) { + $sth = $pdo->prepare("SELECT f.id, + f.title, + ".SUBSTRING_FOR_DATE."(f.last_updated,1,19) AS last_updated, + f.last_error, + SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, + SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked + FROM ttrss_feeds f, ttrss_user_entries ue + WHERE f.id = ue.feed_id AND ue.owner_uid = :uid + GROUP BY f.id"); + + $sth->execute(["uid" => $_SESSION['uid']]); + } else { + $feed_ids_qmarks = arr_qmarks($feed_ids); + + $sth = $pdo->prepare("SELECT f.id, + f.title, + ".SUBSTRING_FOR_DATE."(f.last_updated,1,19) AS last_updated, + f.last_error, + SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, + SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked + FROM ttrss_feeds f, ttrss_user_entries ue + WHERE f.id = ue.feed_id AND ue.owner_uid = ? AND f.id IN ($feed_ids_qmarks) + GROUP BY f.id"); + + $sth->execute(array_merge([$_SESSION['uid']], $feed_ids)); + } while ($line = $sth->fetch()) { diff --git a/classes/feeds.php b/classes/feeds.php index a38cbae97..453c8aa0f 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -1765,7 +1765,7 @@ class Feeds extends Handler_Protected { $sth->execute([$cat, $owner_uid]); while ($line = $sth->fetch()) { - array_push($rv, $line["parent_cat"]); + array_push($rv, (int)$line["parent_cat"]); $rv = array_merge($rv, self::_get_parent_cats($line["parent_cat"], $owner_uid)); } @@ -1789,6 +1789,30 @@ class Feeds extends Handler_Protected { return $rv; } + static function _cats_of(array $feeds, int $owner_uid, bool $with_parents = false) { + $pdo = Db::pdo(); + + $feeds_qmarks = arr_qmarks($feeds); + + $sth = $pdo->prepare("SELECT DISTINCT cat_id FROM ttrss_feeds + WHERE id IN ($feeds_qmarks)"); + $sth->execute($feeds); + + $rv = []; + + if ($row = $sth->fetch()) { + array_push($rv, (int)$row["cat_id"]); + + if ($with_parents) + $rv = array_merge($rv, + self::_get_parent_cats($row["cat_id"], $owner_uid)); + } + + $rv = array_unique($rv); + + return $rv; + } + static function _cat_of_feed($feed) { $pdo = Db::pdo(); diff --git a/classes/rpc.php b/classes/rpc.php index d0388a066..7caf37cf0 100755 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -73,14 +73,21 @@ class RPC extends Handler_Protected { } function getAllCounters() { + $feed_ids = array_map("intval", + explode(",", + clean($_REQUEST["feed_ids"]))); + @$seq = (int) $_REQUEST['seq']; + // @phpstan-ignore-next-line + $counters = count($feed_ids) > 0 ? Counters::get_for_feeds($feed_ids) : Counters::get_all(); + $reply = [ - 'counters' => Counters::get_all(), + 'counters' => $counters, 'seq' => $seq ]; - if ($seq % 2 == 0) + if ($seq % 2) $reply['runtime-info'] = $this->make_runtime_info(); print json_encode($reply); @@ -88,30 +95,39 @@ class RPC extends Handler_Protected { /* GET["cmode"] = 0 - mark as read, 1 - as unread, 2 - toggle */ function catchupSelected() { - $ids = explode(",", clean($_REQUEST["ids"])); + $ids = array_map("intval", + explode(",", + clean($_REQUEST["ids"]))); + $cmode = (int)clean($_REQUEST["cmode"]); Article::_catchup_by_id($ids, $cmode); - print json_encode(array("message" => "UPDATE_COUNTERS", "ids" => $ids)); + print json_encode(["message" => "UPDATE_COUNTERS", "feeds" => Article::_feeds_of($ids)]); } function markSelected() { - $ids = explode(",", clean($_REQUEST["ids"])); + $ids = array_map("intval", + explode(",", + clean($_REQUEST["ids"]))); + $cmode = (int)clean($_REQUEST["cmode"]); $this->markArticlesById($ids, $cmode); - print json_encode(array("message" => "UPDATE_COUNTERS")); + print json_encode(["message" => "UPDATE_COUNTERS", "feeds" => Article::_feeds_of($ids)]); } function publishSelected() { - $ids = explode(",", clean($_REQUEST["ids"])); + $ids = array_map("intval", + explode(",", + clean($_REQUEST["ids"]))); + $cmode = (int)clean($_REQUEST["cmode"]); $this->publishArticlesById($ids, $cmode); - print json_encode(array("message" => "UPDATE_COUNTERS")); + print json_encode(["message" => "UPDATE_COUNTERS", "feeds" => Article::_feeds_of($ids)]); } function sanityCheck() { diff --git a/js/App.js b/js/App.js index 6cad062f0..3c940d8a6 100644 --- a/js/App.js +++ b/js/App.js @@ -421,8 +421,8 @@ const App = { // not in preferences if (typeof Feeds != "undefined") { if (message == "UPDATE_COUNTERS") { - console.log("need to refresh counters..."); - Feeds.requestCounters(true); + console.log("need to refresh counters for", reply.feeds); + Feeds.requestCounters(reply.feeds); } if (counters) diff --git a/js/Feeds.js b/js/Feeds.js index a8f08e623..e40d31087 100644 --- a/js/Feeds.js +++ b/js/Feeds.js @@ -133,8 +133,8 @@ const Feeds = { this._search_query = ""; this.reloadCurrent(); }, - requestCounters: function() { - xhr.json("backend.php", {op: "rpc", method: "getAllCounters", seq: App.next_seq()}, () => { + requestCounters: function(feed_ids = null) { + xhr.json("backend.php", {op: "rpc", method: "getAllCounters", feed_ids: feed_ids, seq: App.next_seq()}, () => { // }); }, @@ -264,10 +264,10 @@ const Feeds = { // bw_limit disables timeout() so we request initial counters separately if (App.getInitParam("bw_limit")) { - this.requestCounters(true); + this.requestCounters(); } else { setTimeout(() => { - this.requestCounters(true); + this.requestCounters(); setInterval(() => { this.requestCounters(); }, 60 * 1000) }, 250); } @@ -396,7 +396,7 @@ const Feeds = { Notify.progress("Marking all feeds as read..."); xhr.post("backend.php", {op: "feeds", method: "catchupAll"}, () => { - this.requestCounters(true); + this.requestCounters(); this.reloadCurrent(); }); diff --git a/js/Headlines.js b/js/Headlines.js index abb96d4ce..1ba52a6b8 100755 --- a/js/Headlines.js +++ b/js/Headlines.js @@ -7,7 +7,7 @@ const Headlines = { vgroup_last_feed: undefined, _headlines_scroll_timeout: 0, - _observer_counters_timeout: 0, + //_observer_counters_timeout: 0, headlines: [], current_first_id: 0, _scroll_reset_timeout: false, @@ -149,38 +149,38 @@ const Headlines = { const promises = []; if (ops.tmark.length != 0) - promises.push(xhr.post("backend.php", + promises.push(xhr.json("backend.php", {op: "rpc", method: "markSelected", ids: ops.tmark.toString(), cmode: 2})); if (ops.tpub.length != 0) - promises.push(xhr.post("backend.php", + promises.push(xhr.json("backend.php", {op: "rpc", method: "publishSelected", ids: ops.tpub.toString(), cmode: 2})); if (ops.read.length != 0) - promises.push(xhr.post("backend.php", + promises.push(xhr.json("backend.php", {op: "rpc", method: "catchupSelected", ids: ops.read.toString(), cmode: 0})); if (ops.unread.length != 0) - promises.push(xhr.post("backend.php", + promises.push(xhr.json("backend.php", {op: "rpc", method: "catchupSelected", ids: ops.unread.toString(), cmode: 1})); const scores = Object.keys(ops.rescore); if (scores.length != 0) { scores.forEach((score) => { - promises.push(xhr.post("backend.php", + promises.push(xhr.json("backend.php", {op: "article", method: "setScore", id: ops.rescore[score].toString(), score: score})); }); } - if (promises.length > 0) + /*if (promises.length > 0) Promise.all([promises]).then(() => { window.clearTimeout(this._observer_counters_timeout); this._observer_counters_timeout = setTimeout(() => { - Feeds.requestCounters(true); + Feeds.requestCounters(); }, 1000); - }); + });*/ }, click: function (event, id, in_body) { -- cgit v1.2.3-54-g00ecf From 9313ebf2e745731263a8e24d19473adb70dfee47 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Wed, 24 Feb 2021 13:25:26 +0300 Subject: fix warning in counters::get_feeds() --- classes/counters.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'classes/counters.php') diff --git a/classes/counters.php b/classes/counters.php index b4309cf7b..1c75e009e 100644 --- a/classes/counters.php +++ b/classes/counters.php @@ -162,7 +162,6 @@ class Counters { while ($line = $sth->fetch()) { $id = $line["id"]; - $last_error = htmlspecialchars($line["last_error"]); $last_updated = TimeHelper::make_local_datetime($line['last_updated'], false); if (Feeds::_has_icon($id)) { @@ -183,11 +182,8 @@ class Counters { "has_img" => (int) $has_img ]; - if ($last_error) - $cv["error"] = $last_error; - - if ($active_feed && $id == $active_feed) - $cv["title"] = truncate_string($line["title"], 30); + $cv["error"] = $line["last_error"]; + $cv["title"] = truncate_string($line["title"], 30); array_push($ret, $cv); -- cgit v1.2.3-54-g00ecf From 553548b6897f8ef292ab56af9dcc196ef8ee0cb3 Mon Sep 17 00:00:00 2001 From: Andrew Dolgov Date: Wed, 24 Feb 2021 15:07:31 +0300 Subject: request label counters conditionally --- classes/api.php | 2 +- classes/article.php | 33 +++++++++++++++- classes/counters.php | 107 +++++++++++++++++++++++++++++++-------------------- classes/feeds.php | 3 ++ classes/rpc.php | 32 ++++++++++++--- js/Feeds.js | 13 +++++-- js/Headlines.js | 9 ++++- 7 files changed, 144 insertions(+), 55 deletions(-) (limited to 'classes/counters.php') diff --git a/classes/api.php b/classes/api.php index 1b3ee7d92..18f9c83b5 100755 --- a/classes/api.php +++ b/classes/api.php @@ -520,7 +520,7 @@ class API extends Handler { /* API only: -4 All feeds, including virtual feeds */ if ($cat_id == -4 || $cat_id == -2) { - $counters = Counters::get_labels(true); + $counters = Counters::get_labels(); foreach (array_values($counters) as $cv) { diff --git a/classes/article.php b/classes/article.php index f77275122..6baf8f068 100755 --- a/classes/article.php +++ b/classes/article.php @@ -640,10 +640,41 @@ class Article extends Handler_Protected { return [$article_image, $article_stream, $article_kind]; } + // only cached, returns label ids (not label feed ids) + static function _labels_of(array $article_ids) { + if (count($article_ids) == 0) + return []; + + $id_qmarks = arr_qmarks($article_ids); + + $sth = Db::pdo()->prepare("SELECT DISTINCT label_cache FROM ttrss_entries e, ttrss_user_entries ue + WHERE ue.ref_id = e.id AND id IN ($id_qmarks)"); + + $sth->execute($article_ids); + + $rv = []; + + while ($row = $sth->fetch()) { + $labels = json_decode($row["label_cache"]); + + if (isset($labels) && is_array($labels)) { + foreach ($labels as $label) { + if (empty($label["no-labels"])) + array_push($rv, Labels::feed_to_label_id($label[0])); + } + } + } + + return array_unique($rv); + } + static function _feeds_of(array $article_ids) { + if (count($article_ids) == 0) + return []; + $id_qmarks = arr_qmarks($article_ids); - $sth = DB::pdo()->prepare("SELECT DISTINCT feed_id FROM ttrss_entries e, ttrss_user_entries ue + $sth = Db::pdo()->prepare("SELECT DISTINCT feed_id FROM ttrss_entries e, ttrss_user_entries ue WHERE ue.ref_id = e.id AND id IN ($id_qmarks)"); $sth->execute($article_ids); diff --git a/classes/counters.php b/classes/counters.php index 1c75e009e..b4602825c 100644 --- a/classes/counters.php +++ b/classes/counters.php @@ -11,13 +11,14 @@ class Counters { ); } - static function get_for_feeds($feed_ids) { + static function get_conditional(array $feed_ids = null, array $label_ids = null) { return array_merge( self::get_global(), self::get_virt(), - self::get_labels(), + self::get_labels($label_ids), self::get_feeds($feed_ids), - self::get_cats(Feeds::_cats_of($feed_ids, $_SESSION["uid"], true))); + self::get_cats(is_array($feed_ids) ? Feeds::_cats_of($feed_ids, $_SESSION["uid"], true) : null) + ); } static private function get_cat_children($cat_id, $owner_uid) { @@ -40,7 +41,7 @@ class Counters { return [$unread, $marked]; } - private static function get_cats(array $cat_ids = []) { + private static function get_cats(array $cat_ids = null) { $ret = []; /* Labels category */ @@ -52,7 +53,12 @@ class Counters { $pdo = Db::pdo(); - if (count($cat_ids) == 0) { + if (is_array($cat_ids)) { + if (count($cat_ids) == 0) + return []; + + $cat_ids_qmarks = arr_qmarks($cat_ids); + $sth = $pdo->prepare("SELECT fc.id, SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked, @@ -61,7 +67,7 @@ class Counters { FROM ttrss_feed_categories fc LEFT JOIN ttrss_feeds f ON (f.cat_id = fc.id) LEFT JOIN ttrss_user_entries ue ON (ue.feed_id = f.id) - WHERE fc.owner_uid = :uid + WHERE fc.owner_uid = ? AND fc.id IN ($cat_ids_qmarks) GROUP BY fc.id UNION SELECT 0, @@ -71,12 +77,15 @@ class Counters { FROM ttrss_feeds f, ttrss_user_entries ue WHERE f.cat_id IS NULL AND ue.feed_id = f.id AND - ue.owner_uid = :uid"); + ue.owner_uid = ?"); - $sth->execute(["uid" => $_SESSION['uid']]); - } else { - $cat_ids_qmarks = arr_qmarks($cat_ids); + $sth->execute(array_merge( + [$_SESSION['uid']], + $cat_ids, + [$_SESSION['uid']] + )); + } else { $sth = $pdo->prepare("SELECT fc.id, SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked, @@ -85,7 +94,7 @@ class Counters { FROM ttrss_feed_categories fc LEFT JOIN ttrss_feeds f ON (f.cat_id = fc.id) LEFT JOIN ttrss_user_entries ue ON (ue.feed_id = f.id) - WHERE fc.owner_uid = ? AND fc.id IN ($cat_ids_qmarks) + WHERE fc.owner_uid = :uid GROUP BY fc.id UNION SELECT 0, @@ -95,13 +104,9 @@ class Counters { FROM ttrss_feeds f, ttrss_user_entries ue WHERE f.cat_id IS NULL AND ue.feed_id = f.id AND - ue.owner_uid = ?"); + ue.owner_uid = :uid"); - $sth->execute(array_merge( - [$_SESSION['uid']], - $cat_ids, - [$_SESSION['uid']] - )); + $sth->execute(["uid" => $_SESSION['uid']]); } while ($line = $sth->fetch()) { @@ -125,13 +130,18 @@ class Counters { return $ret; } - private static function get_feeds(array $feed_ids = []) { + private static function get_feeds(array $feed_ids = null) { $ret = []; $pdo = Db::pdo(); - if (count($feed_ids) == 0) { + if (is_array($feed_ids)) { + if (count($feed_ids) == 0) + return []; + + $feed_ids_qmarks = arr_qmarks($feed_ids); + $sth = $pdo->prepare("SELECT f.id, f.title, ".SUBSTRING_FOR_DATE."(f.last_updated,1,19) AS last_updated, @@ -139,13 +149,11 @@ class Counters { SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked FROM ttrss_feeds f, ttrss_user_entries ue - WHERE f.id = ue.feed_id AND ue.owner_uid = :uid + WHERE f.id = ue.feed_id AND ue.owner_uid = ? AND f.id IN ($feed_ids_qmarks) GROUP BY f.id"); - $sth->execute(["uid" => $_SESSION['uid']]); + $sth->execute(array_merge([$_SESSION['uid']], $feed_ids)); } else { - $feed_ids_qmarks = arr_qmarks($feed_ids); - $sth = $pdo->prepare("SELECT f.id, f.title, ".SUBSTRING_FOR_DATE."(f.last_updated,1,19) AS last_updated, @@ -153,10 +161,10 @@ class Counters { SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked FROM ttrss_feeds f, ttrss_user_entries ue - WHERE f.id = ue.feed_id AND ue.owner_uid = ? AND f.id IN ($feed_ids_qmarks) + WHERE f.id = ue.feed_id AND ue.owner_uid = :uid GROUP BY f.id"); - $sth->execute(array_merge([$_SESSION['uid']], $feed_ids)); + $sth->execute(["uid" => $_SESSION['uid']]); } while ($line = $sth->fetch()) { @@ -269,23 +277,42 @@ class Counters { return $ret; } - static function get_labels($descriptions = false) { + static function get_labels(array $label_ids = null) { $ret = []; $pdo = Db::pdo(); - $sth = $pdo->prepare("SELECT id, - caption, - SUM(CASE WHEN u1.unread = true THEN 1 ELSE 0 END) AS count_unread, - SUM(CASE WHEN u1.marked = true THEN 1 ELSE 0 END) AS count_marked, - COUNT(u1.unread) AS total - FROM ttrss_labels2 LEFT JOIN ttrss_user_labels2 ON - (ttrss_labels2.id = label_id) - LEFT JOIN ttrss_user_entries AS u1 ON u1.ref_id = article_id AND u1.owner_uid = :uid - WHERE ttrss_labels2.owner_uid = :uid - GROUP BY ttrss_labels2.id, ttrss_labels2.caption"); - $sth->execute([":uid" => $_SESSION['uid']]); + if (is_array($label_ids)) { + if (count($label_ids) == 0) + return []; + + $label_ids_qmarks = arr_qmarks($label_ids); + + $sth = $pdo->prepare("SELECT id, + caption, + SUM(CASE WHEN u1.unread = true THEN 1 ELSE 0 END) AS count_unread, + SUM(CASE WHEN u1.marked = true THEN 1 ELSE 0 END) AS count_marked, + COUNT(u1.unread) AS total + FROM ttrss_labels2 LEFT JOIN ttrss_user_labels2 ON + (ttrss_labels2.id = label_id) + LEFT JOIN ttrss_user_entries AS u1 ON u1.ref_id = article_id AND u1.owner_uid = ? + WHERE ttrss_labels2.owner_uid = ? AND ttrss_labels2.id IN ($label_ids_qmarks) + GROUP BY ttrss_labels2.id, ttrss_labels2.caption"); + $sth->execute(array_merge([$_SESSION["uid"], $_SESSION["uid"]], $label_ids)); + } else { + $sth = $pdo->prepare("SELECT id, + caption, + SUM(CASE WHEN u1.unread = true THEN 1 ELSE 0 END) AS count_unread, + SUM(CASE WHEN u1.marked = true THEN 1 ELSE 0 END) AS count_marked, + COUNT(u1.unread) AS total + FROM ttrss_labels2 LEFT JOIN ttrss_user_labels2 ON + (ttrss_labels2.id = label_id) + LEFT JOIN ttrss_user_entries AS u1 ON u1.ref_id = article_id AND u1.owner_uid = :uid + WHERE ttrss_labels2.owner_uid = :uid + GROUP BY ttrss_labels2.id, ttrss_labels2.caption"); + $sth->execute([":uid" => $_SESSION['uid']]); + } while ($line = $sth->fetch()) { @@ -295,12 +322,10 @@ class Counters { "id" => $id, "counter" => (int) $line["count_unread"], "auxcounter" => (int) $line["total"], - "markedcounter" => (int) $line["count_marked"] + "markedcounter" => (int) $line["count_marked"], + "description" => $line["caption"] ]; - if ($descriptions) - $cv["description"] = $line["caption"]; - array_push($ret, $cv); } diff --git a/classes/feeds.php b/classes/feeds.php index 87fdc0bfe..ba2719f48 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -1792,6 +1792,9 @@ class Feeds extends Handler_Protected { } static function _cats_of(array $feeds, int $owner_uid, bool $with_parents = false) { + if (count($feeds) == 0) + return []; + $pdo = Db::pdo(); $feeds_qmarks = arr_qmarks($feeds); diff --git a/classes/rpc.php b/classes/rpc.php index b9fd492fa..2cc2e3879 100755 --- a/classes/rpc.php +++ b/classes/rpc.php @@ -73,11 +73,26 @@ class RPC extends Handler_Protected { } function getAllCounters() { - $feed_ids = array_map("intval", clean($_REQUEST["feed_ids"] ?? [])); @$seq = (int) $_REQUEST['seq']; + $feed_id_count = (int)$_REQUEST["feed_id_count"]; + $label_id_count = (int)$_REQUEST["label_id_count"]; + + // it seems impossible to distinguish empty array [] from a null - both become unset in $_REQUEST + // so, count is >= 0 means we had an array, -1 means null + // we need null because it means "return all counters"; [] would return nothing + if ($feed_id_count == -1) + $feed_ids = null; + else + $feed_ids = array_map("intval", clean($_REQUEST["feed_ids"] ?? [])); + + if ($label_id_count == -1) + $label_ids = null; + else + $label_ids = array_map("intval", clean($_REQUEST["label_ids"] ?? [])); + // @phpstan-ignore-next-line - $counters = count($feed_ids) > 0 ? Counters::get_for_feeds($feed_ids) : Counters::get_all(); + $counters = is_array($feed_ids) ? Counters::get_conditional($feed_ids, $label_ids) : Counters::get_all(); $reply = [ 'counters' => $counters, @@ -95,16 +110,20 @@ class RPC extends Handler_Protected { $ids = array_map("intval", clean($_REQUEST["ids"] ?? [])); $cmode = (int)clean($_REQUEST["cmode"]); - Article::_catchup_by_id($ids, $cmode); + if (count($ids) > 0) + Article::_catchup_by_id($ids, $cmode); - print json_encode(["message" => "UPDATE_COUNTERS", "feeds" => Article::_feeds_of($ids)]); + print json_encode(["message" => "UPDATE_COUNTERS", + "labels" => Article::_labels_of($ids), + "feeds" => Article::_feeds_of($ids)]); } function markSelected() { $ids = array_map("intval", clean($_REQUEST["ids"] ?? [])); $cmode = (int)clean($_REQUEST["cmode"]); - $this->markArticlesById($ids, $cmode); + if (count($ids) > 0) + $this->markArticlesById($ids, $cmode); print json_encode(["message" => "UPDATE_COUNTERS", "feeds" => Article::_feeds_of($ids)]); } @@ -113,7 +132,8 @@ class RPC extends Handler_Protected { $ids = array_map("intval", clean($_REQUEST["ids"] ?? [])); $cmode = (int)clean($_REQUEST["cmode"]); - $this->publishArticlesById($ids, $cmode); + if (count($ids) > 0) + $this->publishArticlesById($ids, $cmode); print json_encode(["message" => "UPDATE_COUNTERS", "feeds" => Article::_feeds_of($ids)]); } diff --git a/js/Feeds.js b/js/Feeds.js index 5d64b77ee..3767f8b65 100644 --- a/js/Feeds.js +++ b/js/Feeds.js @@ -133,10 +133,15 @@ const Feeds = { this._search_query = ""; this.reloadCurrent(); }, - requestCounters: function(feed_ids = null) { - xhr.json("backend.php", {op: "rpc", method: "getAllCounters", "feed_ids[]": feed_ids, seq: App.next_seq()}, () => { - // - }); + // null = get all data, [] would give empty response for specific type + requestCounters: function(feed_ids = null, label_ids = null) { + xhr.json("backend.php", {op: "rpc", + method: "getAllCounters", + "feed_ids[]": feed_ids, + "feed_id_count": feed_ids ? feed_ids.length : -1, + "label_ids[]": label_ids, + "label_id_count": label_ids ? label_ids.length : -1, + seq: App.next_seq()}); }, reload: function() { try { diff --git a/js/Headlines.js b/js/Headlines.js index d44866d94..6dbe24918 100755 --- a/js/Headlines.js +++ b/js/Headlines.js @@ -175,6 +175,7 @@ const Headlines = { Promise.all(promises).then((results) => { let feeds = []; + let labels = []; results.forEach((res) => { if (res) { @@ -183,6 +184,10 @@ const Headlines = { if (obj.feeds) feeds = feeds.concat(obj.feeds); + + if (obj.labels) + labels = labels.concat(obj.labels); + } catch (e) { console.warn(e, res); } @@ -190,8 +195,8 @@ const Headlines = { }); if (feeds.length > 0) { - console.log('requesting counters for', feeds); - Feeds.requestCounters(feeds); + console.log('requesting counters for', feeds, labels); + Feeds.requestCounters(feeds, labels); } }); }, -- cgit v1.2.3-54-g00ecf