request label counters conditionally

master
Andrew Dolgov 4 years ago
parent 9313ebf2e7
commit 553548b689

@ -520,7 +520,7 @@ class API extends Handler {
/* API only: -4 All feeds, including virtual feeds */ /* API only: -4 All feeds, including virtual feeds */
if ($cat_id == -4 || $cat_id == -2) { if ($cat_id == -4 || $cat_id == -2) {
$counters = Counters::get_labels(true); $counters = Counters::get_labels();
foreach (array_values($counters) as $cv) { foreach (array_values($counters) as $cv) {

@ -640,10 +640,41 @@ class Article extends Handler_Protected {
return [$article_image, $article_stream, $article_kind]; 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) { static function _feeds_of(array $article_ids) {
if (count($article_ids) == 0)
return [];
$id_qmarks = arr_qmarks($article_ids); $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)"); WHERE ue.ref_id = e.id AND id IN ($id_qmarks)");
$sth->execute($article_ids); $sth->execute($article_ids);

@ -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( return array_merge(
self::get_global(), self::get_global(),
self::get_virt(), self::get_virt(),
self::get_labels(), self::get_labels($label_ids),
self::get_feeds($feed_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) { static private function get_cat_children($cat_id, $owner_uid) {
@ -40,7 +41,7 @@ class Counters {
return [$unread, $marked]; return [$unread, $marked];
} }
private static function get_cats(array $cat_ids = []) { private static function get_cats(array $cat_ids = null) {
$ret = []; $ret = [];
/* Labels category */ /* Labels category */
@ -52,7 +53,12 @@ class Counters {
$pdo = Db::pdo(); $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, $sth = $pdo->prepare("SELECT fc.id,
SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count,
SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked, SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked,
@ -61,7 +67,7 @@ class Counters {
FROM ttrss_feed_categories fc FROM ttrss_feed_categories fc
LEFT JOIN ttrss_feeds f ON (f.cat_id = fc.id) LEFT JOIN ttrss_feeds f ON (f.cat_id = fc.id)
LEFT JOIN ttrss_user_entries ue ON (ue.feed_id = f.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 GROUP BY fc.id
UNION UNION
SELECT 0, SELECT 0,
@ -71,12 +77,15 @@ class Counters {
FROM ttrss_feeds f, ttrss_user_entries ue FROM ttrss_feeds f, ttrss_user_entries ue
WHERE f.cat_id IS NULL AND WHERE f.cat_id IS NULL AND
ue.feed_id = f.id AND ue.feed_id = f.id AND
ue.owner_uid = :uid"); ue.owner_uid = ?");
$sth->execute(["uid" => $_SESSION['uid']]); $sth->execute(array_merge(
} else { [$_SESSION['uid']],
$cat_ids_qmarks = arr_qmarks($cat_ids); $cat_ids,
[$_SESSION['uid']]
));
} else {
$sth = $pdo->prepare("SELECT fc.id, $sth = $pdo->prepare("SELECT fc.id,
SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count, SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count,
SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked, SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked,
@ -85,7 +94,7 @@ class Counters {
FROM ttrss_feed_categories fc FROM ttrss_feed_categories fc
LEFT JOIN ttrss_feeds f ON (f.cat_id = fc.id) LEFT JOIN ttrss_feeds f ON (f.cat_id = fc.id)
LEFT JOIN ttrss_user_entries ue ON (ue.feed_id = f.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 GROUP BY fc.id
UNION UNION
SELECT 0, SELECT 0,
@ -95,13 +104,9 @@ class Counters {
FROM ttrss_feeds f, ttrss_user_entries ue FROM ttrss_feeds f, ttrss_user_entries ue
WHERE f.cat_id IS NULL AND WHERE f.cat_id IS NULL AND
ue.feed_id = f.id AND ue.feed_id = f.id AND
ue.owner_uid = ?"); ue.owner_uid = :uid");
$sth->execute(array_merge( $sth->execute(["uid" => $_SESSION['uid']]);
[$_SESSION['uid']],
$cat_ids,
[$_SESSION['uid']]
));
} }
while ($line = $sth->fetch()) { while ($line = $sth->fetch()) {
@ -125,13 +130,18 @@ class Counters {
return $ret; return $ret;
} }
private static function get_feeds(array $feed_ids = []) { private static function get_feeds(array $feed_ids = null) {
$ret = []; $ret = [];
$pdo = Db::pdo(); $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, $sth = $pdo->prepare("SELECT f.id,
f.title, f.title,
".SUBSTRING_FOR_DATE."(f.last_updated,1,19) AS last_updated, ".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 unread THEN 1 ELSE 0 END) AS count,
SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked
FROM ttrss_feeds f, ttrss_user_entries ue 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"); GROUP BY f.id");
$sth->execute(["uid" => $_SESSION['uid']]); $sth->execute(array_merge([$_SESSION['uid']], $feed_ids));
} else { } else {
$feed_ids_qmarks = arr_qmarks($feed_ids);
$sth = $pdo->prepare("SELECT f.id, $sth = $pdo->prepare("SELECT f.id,
f.title, f.title,
".SUBSTRING_FOR_DATE."(f.last_updated,1,19) AS last_updated, ".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 unread THEN 1 ELSE 0 END) AS count,
SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS count_marked
FROM ttrss_feeds f, ttrss_user_entries ue 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"); GROUP BY f.id");
$sth->execute(array_merge([$_SESSION['uid']], $feed_ids)); $sth->execute(["uid" => $_SESSION['uid']]);
} }
while ($line = $sth->fetch()) { while ($line = $sth->fetch()) {
@ -269,23 +277,42 @@ class Counters {
return $ret; return $ret;
} }
static function get_labels($descriptions = false) { static function get_labels(array $label_ids = null) {
$ret = []; $ret = [];
$pdo = Db::pdo(); $pdo = Db::pdo();
$sth = $pdo->prepare("SELECT id, if (is_array($label_ids)) {
caption, if (count($label_ids) == 0)
SUM(CASE WHEN u1.unread = true THEN 1 ELSE 0 END) AS count_unread, return [];
SUM(CASE WHEN u1.marked = true THEN 1 ELSE 0 END) AS count_marked,
COUNT(u1.unread) AS total $label_ids_qmarks = arr_qmarks($label_ids);
FROM ttrss_labels2 LEFT JOIN ttrss_user_labels2 ON
(ttrss_labels2.id = label_id) $sth = $pdo->prepare("SELECT id,
LEFT JOIN ttrss_user_entries AS u1 ON u1.ref_id = article_id AND u1.owner_uid = :uid caption,
WHERE ttrss_labels2.owner_uid = :uid SUM(CASE WHEN u1.unread = true THEN 1 ELSE 0 END) AS count_unread,
GROUP BY ttrss_labels2.id, ttrss_labels2.caption"); SUM(CASE WHEN u1.marked = true THEN 1 ELSE 0 END) AS count_marked,
$sth->execute([":uid" => $_SESSION['uid']]); 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()) { while ($line = $sth->fetch()) {
@ -295,12 +322,10 @@ class Counters {
"id" => $id, "id" => $id,
"counter" => (int) $line["count_unread"], "counter" => (int) $line["count_unread"],
"auxcounter" => (int) $line["total"], "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); array_push($ret, $cv);
} }

@ -1792,6 +1792,9 @@ class Feeds extends Handler_Protected {
} }
static function _cats_of(array $feeds, int $owner_uid, bool $with_parents = false) { static function _cats_of(array $feeds, int $owner_uid, bool $with_parents = false) {
if (count($feeds) == 0)
return [];
$pdo = Db::pdo(); $pdo = Db::pdo();
$feeds_qmarks = arr_qmarks($feeds); $feeds_qmarks = arr_qmarks($feeds);

@ -73,11 +73,26 @@ class RPC extends Handler_Protected {
} }
function getAllCounters() { function getAllCounters() {
$feed_ids = array_map("intval", clean($_REQUEST["feed_ids"] ?? []));
@$seq = (int) $_REQUEST['seq']; @$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 // @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 = [ $reply = [
'counters' => $counters, 'counters' => $counters,
@ -95,16 +110,20 @@ class RPC extends Handler_Protected {
$ids = array_map("intval", clean($_REQUEST["ids"] ?? [])); $ids = array_map("intval", clean($_REQUEST["ids"] ?? []));
$cmode = (int)clean($_REQUEST["cmode"]); $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() { function markSelected() {
$ids = array_map("intval", clean($_REQUEST["ids"] ?? [])); $ids = array_map("intval", clean($_REQUEST["ids"] ?? []));
$cmode = (int)clean($_REQUEST["cmode"]); $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)]); 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"] ?? [])); $ids = array_map("intval", clean($_REQUEST["ids"] ?? []));
$cmode = (int)clean($_REQUEST["cmode"]); $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)]); print json_encode(["message" => "UPDATE_COUNTERS", "feeds" => Article::_feeds_of($ids)]);
} }

@ -133,10 +133,15 @@ const Feeds = {
this._search_query = ""; this._search_query = "";
this.reloadCurrent(); this.reloadCurrent();
}, },
requestCounters: function(feed_ids = null) { // null = get all data, [] would give empty response for specific type
xhr.json("backend.php", {op: "rpc", method: "getAllCounters", "feed_ids[]": feed_ids, seq: App.next_seq()}, () => { 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() { reload: function() {
try { try {

@ -175,6 +175,7 @@ const Headlines = {
Promise.all(promises).then((results) => { Promise.all(promises).then((results) => {
let feeds = []; let feeds = [];
let labels = [];
results.forEach((res) => { results.forEach((res) => {
if (res) { if (res) {
@ -183,6 +184,10 @@ const Headlines = {
if (obj.feeds) if (obj.feeds)
feeds = feeds.concat(obj.feeds); feeds = feeds.concat(obj.feeds);
if (obj.labels)
labels = labels.concat(obj.labels);
} catch (e) { } catch (e) {
console.warn(e, res); console.warn(e, res);
} }
@ -190,8 +195,8 @@ const Headlines = {
}); });
if (feeds.length > 0) { if (feeds.length > 0) {
console.log('requesting counters for', feeds); console.log('requesting counters for', feeds, labels);
Feeds.requestCounters(feeds); Feeds.requestCounters(feeds, labels);
} }
}); });
}, },

Loading…
Cancel
Save