diff options
Diffstat (limited to 'classes')
-rwxr-xr-x | classes/api.php | 12 | ||||
-rwxr-xr-x | classes/article.php | 73 | ||||
-rw-r--r-- | classes/ccache.php | 211 | ||||
-rw-r--r-- | classes/counters.php | 257 | ||||
-rw-r--r-- | classes/dlg.php | 5 | ||||
-rwxr-xr-x | classes/feeds.php | 100 | ||||
-rwxr-xr-x | classes/handler/public.php | 93 | ||||
-rw-r--r-- | classes/opml.php | 2 | ||||
-rwxr-xr-x | classes/pref/feeds.php | 14 | ||||
-rw-r--r-- | classes/pref/prefs.php | 233 | ||||
-rwxr-xr-x | classes/rssutils.php | 20 |
11 files changed, 396 insertions, 624 deletions
diff --git a/classes/api.php b/classes/api.php index 6fb87d04f..339e9eef1 100755 --- a/classes/api.php +++ b/classes/api.php @@ -40,7 +40,7 @@ class API extends Handler { } function getVersion() { - $rv = array("version" => VERSION); + $rv = array("version" => get_version()); $this->wrap(self::STATUS_OK, $rv); } @@ -300,16 +300,6 @@ class API extends Handler { $num_updated = $sth->rowCount(); - if ($num_updated > 0 && $field == "unread") { - $sth = $this->pdo->prepare("SELECT DISTINCT feed_id FROM ttrss_user_entries - WHERE ref_id IN ($article_qmarks)"); - $sth->execute($article_ids); - - while ($line = $sth->fetch()) { - CCache::update($line["feed_id"], $_SESSION["uid"]); - } - } - $this->wrap(self::STATUS_OK, array("status" => "OK", "updated" => $num_updated)); diff --git a/classes/article.php b/classes/article.php index fc81838ed..74dbdae53 100755 --- a/classes/article.php +++ b/classes/article.php @@ -27,69 +27,6 @@ class Article extends Handler_Protected { } } - /* - function view() { - $id = clean($_REQUEST["id"]); - $cids = explode(",", clean($_REQUEST["cids"])); - $mode = clean($_REQUEST["mode"]); - - // in prefetch mode we only output requested cids, main article - // just gets marked as read (it already exists in client cache) - - $articles = array(); - - if ($mode == "") { - array_push($articles, $this->format_article($id, false)); - } else if ($mode == "zoom") { - array_push($articles, $this->format_article($id, true, true)); - } else if ($mode == "raw") { - if (isset($_REQUEST['html'])) { - header("Content-Type: text/html"); - print '<link rel="stylesheet" type="text/css" href="css/default.css"/>'; - } - - $article = $this->format_article($id, false, isset($_REQUEST["zoom"])); - print $article['content']; - return; - } - - $this->catchupArticleById($id, 0); - - if (!$_SESSION["bw_limit"]) { - foreach ($cids as $cid) { - if ($cid) { - array_push($articles, $this->format_article($cid, false, false)); - } - } - } - - print json_encode($articles); - } */ - - /* - private function catchupArticleById($id, $cmode) { - - if ($cmode == 0) { - $sth = $this->pdo->prepare("UPDATE ttrss_user_entries SET - unread = false,last_read = NOW() - WHERE ref_id = ? AND owner_uid = ?"); - } else if ($cmode == 1) { - $sth = $this->pdo->prepare("UPDATE ttrss_user_entries SET - unread = true - WHERE ref_id = ? AND owner_uid = ?"); - } else { - $sth = $this->pdo->prepare("UPDATE ttrss_user_entries SET - unread = NOT unread,last_read = NOW() - WHERE ref_id = ? AND owner_uid = ?"); - } - - $sth->execute([$id, $_SESSION['uid']]); - - $feed_id = $this->getArticleFeed($id); - CCache::update($feed_id, $_SESSION["uid"]); - } - */ - static function create_published_article($title, $url, $content, $labels_str, $owner_uid) { @@ -718,16 +655,6 @@ class Article extends Handler_Protected { } $sth->execute(array_merge($ids, [$owner_uid])); - - /* update ccache */ - - $sth = $pdo->prepare("SELECT DISTINCT feed_id FROM ttrss_user_entries - WHERE ref_id IN ($ids_qmarks) AND owner_uid = ?"); - $sth->execute(array_merge($ids, [$owner_uid])); - - while ($line = $sth->fetch()) { - CCache::update($line["feed_id"], $owner_uid); - } } static function getLastArticleId() { diff --git a/classes/ccache.php b/classes/ccache.php deleted file mode 100644 index 2f19140e0..000000000 --- a/classes/ccache.php +++ /dev/null @@ -1,211 +0,0 @@ -<?php -class CCache { - static function zero_all($owner_uid) { - $pdo = Db::pdo(); - - $sth = $pdo->prepare("UPDATE ttrss_counters_cache SET - value = 0 WHERE owner_uid = ?"); - $sth->execute([$owner_uid]); - - $sth = $pdo->prepare("UPDATE ttrss_cat_counters_cache SET - value = 0 WHERE owner_uid = ?"); - $sth->execute([$owner_uid]); - } - - static function remove($feed_id, $owner_uid, $is_cat = false) { - - $feed_id = (int) $feed_id; - - if (!$is_cat) { - $table = "ttrss_counters_cache"; - } else { - $table = "ttrss_cat_counters_cache"; - } - - $pdo = Db::pdo(); - - $sth = $pdo->prepare("DELETE FROM $table WHERE - feed_id = ? AND owner_uid = ?"); - $sth->execute([$feed_id, $owner_uid]); - - } - - static function update_all($owner_uid) { - - $pdo = Db::pdo(); - - if (get_pref('ENABLE_FEED_CATS', $owner_uid)) { - - $sth = $pdo->prepare("SELECT feed_id FROM ttrss_cat_counters_cache - WHERE feed_id > 0 AND owner_uid = ?"); - $sth->execute([$owner_uid]); - - while ($line = $sth->fetch()) { - CCache::update($line["feed_id"], $owner_uid, true); - } - - /* We have to manually include category 0 */ - - CCache::update(0, $owner_uid, true); - - } else { - $sth = $pdo->prepare("SELECT feed_id FROM ttrss_counters_cache - WHERE feed_id > 0 AND owner_uid = ?"); - $sth->execute([$owner_uid]); - - while ($line = $sth->fetch()) { - print CCache::update($line["feed_id"], $owner_uid); - - } - - } - } - - static function find($feed_id, $owner_uid, $is_cat = false, - $no_update = false) { - - // "" (null) is valid and should be cast to 0 (uncategorized) - // everything else i.e. tags are not - if (!is_numeric($feed_id) && $feed_id) - return; - - $feed_id = (int) $feed_id; - - if (!$is_cat) { - $table = "ttrss_counters_cache"; - } else { - $table = "ttrss_cat_counters_cache"; - } - - $pdo = Db::pdo(); - - $sth = $pdo->prepare("SELECT value FROM $table - WHERE owner_uid = ? AND feed_id = ? - LIMIT 1"); - - $sth->execute([$owner_uid, $feed_id]); - - if ($row = $sth->fetch()) { - return $row["value"]; - } else { - if ($no_update) { - return -1; - } else { - return CCache::update($feed_id, $owner_uid, $is_cat); - } - } - - } - - static function update($feed_id, $owner_uid, $is_cat = false, - $update_pcat = true, $pcat_fast = false) { - - // "" (null) is valid and should be cast to 0 (uncategorized) - // everything else i.e. tags are not - if (!is_numeric($feed_id) && $feed_id) - return; - - $feed_id = (int) $feed_id; - - $prev_unread = CCache::find($feed_id, $owner_uid, $is_cat, true); - - /* When updating a label, all we need to do is recalculate feed counters - * because labels are not cached */ - - if ($feed_id < 0) { - CCache::update_all($owner_uid); - return; - } - - if (!$is_cat) { - $table = "ttrss_counters_cache"; - } else { - $table = "ttrss_cat_counters_cache"; - } - - $pdo = Db::pdo(); - - if ($is_cat && $feed_id >= 0) { - /* Recalculate counters for child feeds */ - - if (!$pcat_fast) { - $sth = $pdo->prepare("SELECT id FROM ttrss_feeds - WHERE owner_uid = :uid AND - (cat_id = :cat OR (:cat = 0 AND cat_id IS NULL))"); - $sth->execute([":uid" => $owner_uid, ":cat" => $feed_id]); - - while ($line = $sth->fetch()) { - CCache::update((int)$line["id"], $owner_uid, false, false); - } - } - - $sth = $pdo->prepare("SELECT SUM(value) AS sv - FROM ttrss_counters_cache, ttrss_feeds - WHERE ttrss_feeds.id = feed_id AND - (cat_id = :cat OR (:cat = 0 AND cat_id IS NULL)) AND - ttrss_counters_cache.owner_uid = :uid AND - ttrss_feeds.owner_uid = :uid"); - $sth->execute([":uid" => $owner_uid, ":cat" => $feed_id]); - $row = $sth->fetch(); - - $unread = (int) $row["sv"]; - - } else { - $unread = (int) Feeds::getFeedArticles($feed_id, $is_cat, true, $owner_uid); - } - - $tr_in_progress = false; - - try { - $pdo->beginTransaction(); - } catch (Exception $e) { - $tr_in_progress = true; - } - - $sth = $pdo->prepare("SELECT feed_id FROM $table - WHERE owner_uid = ? AND feed_id = ? LIMIT 1"); - $sth->execute([$owner_uid, $feed_id]); - - if ($sth->fetch()) { - - $sth = $pdo->prepare("UPDATE $table SET - value = ?, updated = NOW() WHERE - feed_id = ? AND owner_uid = ?"); - - $sth->execute([$unread, $feed_id, $owner_uid]); - - } else { - $sth = $pdo->prepare("INSERT INTO $table - (feed_id, value, owner_uid, updated) - VALUES - (?, ?, ?, NOW())"); - $sth->execute([$feed_id, $unread, $owner_uid]); - } - - if (!$tr_in_progress) $pdo->commit(); - - if ($feed_id > 0 && $prev_unread != $unread) { - - if (!$is_cat) { - - /* Update parent category */ - - if ($update_pcat) { - - $sth = $pdo->prepare("SELECT cat_id FROM ttrss_feeds - WHERE owner_uid = ? AND id = ?"); - $sth->execute([$owner_uid, $feed_id]); - - if ($row = $sth->fetch()) { - CCache::update((int)$row["cat_id"], $owner_uid, true, true, true); - } - } - } - } else if ($feed_id < 0) { - CCache::update_all($owner_uid); - } - - return $unread; - } - -}
\ No newline at end of file diff --git a/classes/counters.php b/classes/counters.php index cee901304..d8ed27621 100644 --- a/classes/counters.php +++ b/classes/counters.php @@ -12,63 +12,151 @@ class Counters { return $data; } + static private function getCategoryChildrenCounters($cat_id, $owner_uid) { + $pdo = Db::pdo(); + + $sth = $pdo->prepare("SELECT id FROM ttrss_feed_categories WHERE parent_cat = ? + AND owner_uid = ?"); + $sth->execute([$cat_id, $owner_uid]); + + $unread = 0; + $marked = 0; + + while ($line = $sth->fetch()) { + list ($tmp_unread, $tmp_marked) = Counters::getCategoryChildrenCounters($line["id"], $owner_uid); + + $unread += $tmp_unread + Feeds::getCategoryUnread($line["id"], $owner_uid); + $marked += $tmp_marked + Feeds::getCategoryMarked($line["id"], $owner_uid); + } + + return [$unread, $marked]; + } + static function getCategoryCounters() { - $ret_arr = array(); + $ret = []; /* Labels category */ $cv = array("id" => -2, "kind" => "cat", "counter" => Feeds::getCategoryUnread(-2)); - array_push($ret_arr, $cv); + array_push($ret, $cv); $pdo = DB::pdo(); - $sth = $pdo->prepare("SELECT ttrss_feed_categories.id AS cat_id, value AS unread, - (SELECT COUNT(id) FROM ttrss_feed_categories AS c2 - WHERE c2.parent_cat = ttrss_feed_categories.id) AS num_children - FROM ttrss_feed_categories, ttrss_cat_counters_cache - WHERE ttrss_cat_counters_cache.feed_id = ttrss_feed_categories.id AND - ttrss_cat_counters_cache.owner_uid = ttrss_feed_categories.owner_uid AND - ttrss_feed_categories.owner_uid = ?"); - $sth->execute([$_SESSION['uid']]); + $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']]); while ($line = $sth->fetch()) { - $line["cat_id"] = (int) $line["cat_id"]; - if ($line["num_children"] > 0) { - $child_counter = Feeds::getCategoryChildrenUnread($line["cat_id"], $_SESSION["uid"]); + list ($child_counter, $child_marked_counter) = Counters::getCategoryChildrenCounters($line["id"], $_SESSION["uid"]); } else { $child_counter = 0; + $child_marked_counter = 0; } - $cv = array("id" => $line["cat_id"], "kind" => "cat", - "counter" => $line["unread"] + $child_counter); + $cv = [ + "id" => (int)$line["id"], + "kind" => "cat", + "markedcounter" => (int) $line["count_marked"] + $child_marked_counter, + "counter" => (int) $line["count"] + $child_counter + ]; - array_push($ret_arr, $cv); + array_push($ret, $cv); } - /* Special case: NULL category doesn't actually exist in the DB */ + array_push($ret, $cv); + + return $ret; + } + + + static function getFeedCounters($active_feed = false) { - $cv = array("id" => 0, "kind" => "cat", - "counter" => (int) CCache::find(0, $_SESSION["uid"], true)); + $ret = []; - array_push($ret_arr, $cv); + $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']]); + + while ($line = $sth->fetch()) { + + $id = $line["id"]; + $last_error = htmlspecialchars($line["last_error"]); + $last_updated = make_local_datetime($line['last_updated'], false); + + if (Feeds::feedHasIcon($id)) { + $has_img = filemtime(Feeds::getIconFile($id)); + } else { + $has_img = false; + } + + if (date('Y') - date('Y', strtotime($line['last_updated'])) > 2) + $last_updated = ''; + + $cv = [ + "id" => $id, + "updated" => $last_updated, + "counter" => (int) $line["count"], + "markedcounter" => (int) $line["count_marked"], + "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); - return $ret_arr; + array_push($ret, $cv); + + } + + return $ret; } static function getGlobalCounters($global_unread = -1) { - $ret_arr = array(); + $ret = []; if ($global_unread == -1) { $global_unread = Feeds::getGlobalUnread(); } - $cv = array("id" => "global-unread", - "counter" => (int) $global_unread); + $cv = [ + "id" => "global-unread", + "counter" => (int) $global_unread + ]; - array_push($ret_arr, $cv); + array_push($ret, $cv); $pdo = Db::pdo(); @@ -79,17 +167,19 @@ class Counters { $subscribed_feeds = $row["fn"]; - $cv = array("id" => "subscribed-feeds", - "counter" => (int) $subscribed_feeds); + $cv = [ + "id" => "subscribed-feeds", + "counter" => (int) $subscribed_feeds + ]; - array_push($ret_arr, $cv); + array_push($ret, $cv); - return $ret_arr; + return $ret; } static function getVirtCounters() { - $ret_arr = array(); + $ret = []; for ($i = 0; $i >= -4; $i--) { @@ -100,117 +190,72 @@ class Counters { else $auxctr = 0; - $cv = array("id" => $i, + $cv = [ + "id" => $i, "counter" => (int) $count, - "auxcounter" => (int) $auxctr); + "auxcounter" => (int) $auxctr + ]; -// if (get_pref('EXTENDED_FEEDLIST')) -// $cv["xmsg"] = getFeedArticles($i)." ".__("total"); + if ($i == -1) + $cv["markedcounter"] = $auxctr; - array_push($ret_arr, $cv); + array_push($ret, $cv); } $feeds = PluginHost::getInstance()->get_feeds(-1); if (is_array($feeds)) { foreach ($feeds as $feed) { - $cv = array("id" => PluginHost::pfeed_to_feed_id($feed['id']), - "counter" => $feed['sender']->get_unread($feed['id'])); + $cv = [ + "id" => PluginHost::pfeed_to_feed_id($feed['id']), + "counter" => $feed['sender']->get_unread($feed['id']) + ]; if (method_exists($feed['sender'], 'get_total')) $cv["auxcounter"] = $feed['sender']->get_total($feed['id']); - array_push($ret_arr, $cv); + array_push($ret, $cv); } } - return $ret_arr; + return $ret; } static function getLabelCounters($descriptions = false) { - $ret_arr = array(); + $ret = []; $pdo = Db::pdo(); - $sth = $pdo->prepare("SELECT id,caption,SUM(CASE WHEN u1.unread = true THEN 1 ELSE 0 END) AS unread, COUNT(u1.unread) AS total + $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 - WHERE ttrss_labels2.owner_uid = :uid AND u1.owner_uid = :uid - GROUP BY ttrss_labels2.id, - ttrss_labels2.caption"); + LEFT JOIN ttrss_user_entries AS u1 ON u1.ref_id = article_id + WHERE ttrss_labels2.owner_uid = :uid AND u1.owner_uid = :uid + GROUP BY ttrss_labels2.id, ttrss_labels2.caption"); $sth->execute([":uid" => $_SESSION['uid']]); while ($line = $sth->fetch()) { $id = Labels::label_to_feed_id($line["id"]); - $cv = array("id" => $id, - "counter" => (int) $line["unread"], - "auxcounter" => (int) $line["total"]); + $cv = [ + "id" => $id, + "counter" => (int) $line["count_unread"], + "auxcounter" => (int) $line["total"], + "markedcounter" => (int) $line["count_marked"] + ]; if ($descriptions) $cv["description"] = $line["caption"]; - array_push($ret_arr, $cv); - } - - return $ret_arr; - } - - static function getFeedCounters($active_feed = false) { - - $ret_arr = array(); - - $pdo = Db::pdo(); - - $sth = $pdo->prepare("SELECT ttrss_feeds.id, - ttrss_feeds.title, - ".SUBSTRING_FOR_DATE."(ttrss_feeds.last_updated,1,19) AS last_updated, - last_error, value AS count - FROM ttrss_feeds, ttrss_counters_cache - WHERE ttrss_feeds.owner_uid = ? - AND ttrss_counters_cache.owner_uid = ttrss_feeds.owner_uid - AND ttrss_counters_cache.feed_id = ttrss_feeds.id"); - $sth->execute([$_SESSION['uid']]); - - while ($line = $sth->fetch()) { - - $id = $line["id"]; - $count = $line["count"]; - $last_error = htmlspecialchars($line["last_error"]); - - $last_updated = make_local_datetime($line['last_updated'], false); - - if (Feeds::feedHasIcon($id)) { - $has_img = filemtime(Feeds::getIconFile($id)); - } else { - $has_img = false; - } - - if (date('Y') - date('Y', strtotime($line['last_updated'])) > 2) - $last_updated = ''; - - $cv = array("id" => $id, - "updated" => $last_updated, - "counter" => (int) $count, - "has_img" => (int) $has_img); - - if ($last_error) - $cv["error"] = $last_error; - -// if (get_pref('EXTENDED_FEEDLIST')) -// $cv["xmsg"] = getFeedArticles($id)." ".__("total"); - - if ($active_feed && $id == $active_feed) - $cv["title"] = truncate_string($line["title"], 30); - - array_push($ret_arr, $cv); - + array_push($ret, $cv); } - return $ret_arr; + return $ret; } - -}
\ No newline at end of file +} diff --git a/classes/dlg.php b/classes/dlg.php index d3e82ee59..8873a0cb9 100644 --- a/classes/dlg.php +++ b/classes/dlg.php @@ -196,10 +196,11 @@ class Dlg extends Handler_Protected { print_warning(__("You are using default tt-rss password. Please change it in the Preferences (Personal data / Authentication).")); print "<footer class='text-center'>"; - print "<button dojoType='dijit.form.Button' onclick=\"document.location.href = 'prefs.php'\">". + print "<button dojoType='dijit.form.Button' class='alt-primary' + onclick=\"document.location.href = 'prefs.php'\">". __('Open Preferences')."</button> "; print "<button dojoType='dijit.form.Button' - onclick=\"return CommonDialogs.closeInfoBox()\">". + onclick=\"return dijit.byId('defaultPasswordDlg').hide();\">". __('Close this window')."</button>"; print "</footeer>"; } diff --git a/classes/feeds.php b/classes/feeds.php index e1478a696..77add790e 100755 --- a/classes/feeds.php +++ b/classes/feeds.php @@ -457,8 +457,6 @@ class Feeds extends Handler_Protected { $sth = $this->pdo->prepare("UPDATE ttrss_user_entries SET last_read = NOW(), unread = false WHERE unread = true AND owner_uid = ?"); $sth->execute([$_SESSION['uid']]); - - CCache::zero_all($_SESSION["uid"]); } function view() { @@ -512,13 +510,6 @@ class Feeds extends Handler_Protected { return; } - /* Updating a label ccache means recalculating all of the caches - * so for performance reasons we don't do that here */ - - if ($feed >= 0) { - CCache::update($feed, $_SESSION["uid"], $cat_view); - } - set_pref("_DEFAULT_VIEW_MODE", $view_mode); set_pref("_DEFAULT_VIEW_ORDER_BY", $order_by); @@ -791,16 +782,25 @@ class Feeds extends Handler_Protected { <!DOCTYPE html> <html> <head> - <?php echo stylesheet_tag("css/default.css") ?> <title>Feed Debugger</title> + <style type='text/css'> + @media (prefers-color-scheme: dark) { + body { + background : #222; + } + } + body.css_loading * { + display : none; + } + </style> <?php - echo stylesheet_tag("css/default.css"); echo javascript_tag("lib/prototype.js"); + echo javascript_tag("js/utility.js"); echo javascript_tag("lib/dojo/dojo.js"); echo javascript_tag("lib/dojo/tt-rss-layer.js"); ?> </head> - <body class="flat ttrss_utility feed_debugger"> + <body class="flat ttrss_utility feed_debugger css_loading"> <script type="text/javascript"> require(['dojo/parser', "dojo/ready", 'dijit/form/Button','dijit/form/CheckBox', 'dijit/form/Form', 'dijit/form/Select','dijit/form/TextBox','dijit/form/ValidationTextBox'],function(parser, ready){ @@ -1004,8 +1004,6 @@ class Feeds extends Handler_Protected { } - CCache::update($feed, $owner_uid, $cat_view); - } else { // tag $sth = $pdo->prepare("UPDATE ttrss_user_entries SET unread = false, last_read = NOW() WHERE ref_id IN @@ -1292,7 +1290,8 @@ class Feeds extends Handler_Protected { } } - static function getCategoryUnread($cat, $owner_uid = false) { + // only real cats + static function getCategoryMarked($cat, $owner_uid = false) { if (!$owner_uid) $owner_uid = $_SESSION["uid"]; @@ -1300,46 +1299,48 @@ class Feeds extends Handler_Protected { if ($cat >= 0) { - if (!$cat) $cat = null; - - $sth = $pdo->prepare("SELECT id FROM ttrss_feeds + $sth = $pdo->prepare("SELECT SUM(CASE WHEN marked THEN 1 ELSE 0 END) AS marked + FROM ttrss_user_entries + WHERE feed_id IN (SELECT id FROM ttrss_feeds WHERE (cat_id = :cat OR (:cat IS NULL AND cat_id IS NULL)) - AND owner_uid = :uid"); + AND owner_uid = :uid) + AND owner_uid = :uid"); + $sth->execute(["cat" => $cat ? $cat : null, "uid" => $owner_uid]); + $row = $sth->fetch(); - $sth->execute([":cat" => $cat, ":uid" => $owner_uid]); + return $row["marked"]; + } else { + return 0; + } + } - $cat_feeds = array(); - while ($line = $sth->fetch()) { - array_push($cat_feeds, "feed_id = " . (int)$line["id"]); - } + static function getCategoryUnread($cat, $owner_uid = false) { - if (count($cat_feeds) == 0) return 0; + if (!$owner_uid) $owner_uid = $_SESSION["uid"]; - $match_part = implode(" OR ", $cat_feeds); + $pdo = Db::pdo(); - $sth = $pdo->prepare("SELECT COUNT(int_id) AS unread - FROM ttrss_user_entries - WHERE unread = true AND ($match_part) - AND owner_uid = ?"); - $sth->execute([$owner_uid]); + if ($cat >= 0) { - $unread = 0; + $sth = $pdo->prepare("SELECT SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS unread + FROM ttrss_user_entries + WHERE feed_id IN (SELECT id FROM ttrss_feeds + WHERE (cat_id = :cat OR (:cat IS NULL AND cat_id IS NULL)) + AND owner_uid = :uid) + AND owner_uid = :uid"); + $sth->execute(["cat" => $cat ? $cat : null, "uid" => $owner_uid]); + $row = $sth->fetch(); - # this needs to be rewritten - while ($line = $sth->fetch()) { - $unread += $line["unread"]; - } + return $row["unread"]; - return $unread; } else if ($cat == -1) { - return getFeedUnread(-1) + getFeedUnread(-2) + getFeedUnread(-3) + getFeedUnread(0); + return 0; } else if ($cat == -2) { - $sth = $pdo->prepare("SELECT COUNT(unread) AS unread FROM - ttrss_user_entries, ttrss_user_labels2 - WHERE article_id = ref_id AND unread = true - AND ttrss_user_entries.owner_uid = ?"); - $sth->execute([$owner_uid]); + $sth = $pdo->prepare("SELECT COUNT(DISTINCT article_id) AS unread + FROM ttrss_user_entries ue, ttrss_user_labels2 l + WHERE article_id = ref_id AND unread IS true AND ue.owner_uid = :uid"); + $sth->execute(["uid" => $owner_uid]); $row = $sth->fetch(); return $row["unread"]; @@ -1372,12 +1373,14 @@ class Feeds extends Handler_Protected { $pdo = Db::pdo(); - $sth = $pdo->prepare("SELECT SUM(value) AS c_id FROM ttrss_counters_cache - WHERE owner_uid = ? AND feed_id > 0"); + $sth = $pdo->prepare("SELECT SUM(CASE WHEN unread THEN 1 ELSE 0 END) AS count + FROM ttrss_user_entries ue + WHERE ue.owner_uid = ?"); + $sth->execute([$user_id]); $row = $sth->fetch(); - return $row["c_id"]; + return $row["count"]; } static function getCategoryTitle($cat_id) { @@ -2107,9 +2110,6 @@ class Feeds extends Handler_Protected { } if ($purge_interval == -1 || !$purge_interval) { - if ($owner_uid) { - CCache::update($feed_id, $owner_uid); - } return; } @@ -2154,8 +2154,6 @@ class Feeds extends Handler_Protected { $rows = $sth->rowCount(); - CCache::update($feed_id, $owner_uid); - Debug::log("Purged feed $feed_id ($purge_interval): deleted $rows articles"); return $rows; diff --git a/classes/handler/public.php b/classes/handler/public.php index 67c188142..8c2700012 100755 --- a/classes/handler/public.php +++ b/classes/handler/public.php @@ -111,6 +111,8 @@ class Handler_Public extends Handler { $content = sanitize($line["content"], false, $owner_uid, $feed_site_url, false, $line["id"]); + $content = DiskCache::rewriteUrls($content); + if ($line['note']) { $content = "<div style=\"$note_style\">Article note: " . $line['note'] . "</div>" . $content; @@ -364,7 +366,18 @@ class Handler_Public extends Handler { <html><head> <meta http-equiv='Content-Type' content='text/html; charset=utf-8'/> <title>".$line["title"]."</title>". - stylesheet_tag("css/default.css")." + javascript_tag("lib/prototype.js"). + javascript_tag("js/utility.js")." + <style type='text/css'> + @media (prefers-color-scheme: dark) { + body { + background : #222; + } + } + body.css_loading * { + display : none; + } + </style> <link rel='shortcut icon' type='image/png' href='images/favicon.png'> <link rel='icon' type='image/png' sizes='72x72' href='images/favicon-72px.png'>"; @@ -387,7 +400,7 @@ class Handler_Public extends Handler { $rv .= "<meta property='og:image' content=\"" . htmlspecialchars($og_image) . "\"/>"; } - $rv .= "<body class='flat ttrss_utility ttrss_zoom'>"; + $rv .= "<body class='flat ttrss_utility ttrss_zoom css_loading'>"; $rv .= "<div class='container'>"; if ($line["link"]) { @@ -510,28 +523,43 @@ class Handler_Public extends Handler { <head> <title><?php echo __("Share with Tiny Tiny RSS") ?></title> <?php - echo stylesheet_tag("css/default.css"); echo javascript_tag("lib/prototype.js"); echo javascript_tag("lib/dojo/dojo.js"); + echo javascript_tag("js/utility.js"); echo javascript_tag("lib/dojo/tt-rss-layer.js"); echo javascript_tag("lib/scriptaculous/scriptaculous.js?load=effects,controls") ?> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <link rel="shortcut icon" type="image/png" href="images/favicon.png"> <link rel="icon" type="image/png" sizes="72x72" href="images/favicon-72px.png"> + <style type="text/css"> + @media (prefers-color-scheme: dark) { + body { + background : #303030; + } + } + + body.css_loading * { + display : none; + } + </style> </head> - <body class='flat ttrss_utility share_popup'> + <body class='flat ttrss_utility share_popup css_loading'> <script type="text/javascript"> - require(['dojo/parser', "dojo/ready", 'dijit/form/Button','dijit/form/CheckBox', 'dijit/form/Form', - 'dijit/form/Select','dijit/form/TextBox','dijit/form/ValidationTextBox'],function(parser, ready){ - ready(function() { - parser.parse(); - - new Ajax.Autocompleter('labels_value', 'labels_choices', - "backend.php?op=rpc&method=completeLabels", - { tokens: ',', paramName: "search" }); - }); - }); + const UtilityApp = { + init: function() { + require(['dojo/parser', "dojo/ready", 'dijit/form/Button','dijit/form/CheckBox', 'dijit/form/Form', + 'dijit/form/Select','dijit/form/TextBox','dijit/form/ValidationTextBox'], function(parser, ready){ + ready(function() { + parser.parse(); + + new Ajax.Autocompleter('labels_value', 'labels_choices', + "backend.php?op=rpc&method=completeLabels", + { tokens: ',', paramName: "search" }); + }); + }); + } + }; </script> <div class="content"> @@ -718,23 +746,38 @@ class Handler_Public extends Handler { <head> <title>Tiny Tiny RSS</title> <?php - echo stylesheet_tag("css/default.css"); echo javascript_tag("lib/prototype.js"); + echo javascript_tag("js/utility.js"); echo javascript_tag("lib/dojo/dojo.js"); echo javascript_tag("lib/dojo/tt-rss-layer.js"); ?> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <link rel="shortcut icon" type="image/png" href="images/favicon.png"> <link rel="icon" type="image/png" sizes="72x72" href="images/favicon-72px.png"> + <style type="text/css"> + @media (prefers-color-scheme: dark) { + body { + background : #303030; + } + } + + body.css_loading * { + display : none; + } + </style> </head> - <body class='flat ttrss_utility'> + <body class='flat ttrss_utility css_loading'> <script type="text/javascript"> - require(['dojo/parser', "dojo/ready", 'dijit/form/Button','dijit/form/CheckBox', 'dijit/form/Form', - 'dijit/form/Select','dijit/form/TextBox','dijit/form/ValidationTextBox'],function(parser, ready){ - ready(function() { - parser.parse(); - }); - }); + const UtilityApp = { + init: function() { + require(['dojo/parser', "dojo/ready", 'dijit/form/Button','dijit/form/CheckBox', 'dijit/form/Form', + 'dijit/form/Select','dijit/form/TextBox','dijit/form/ValidationTextBox'], function(parser, ready){ + ready(function() { + parser.parse(); + }); + }); + } + }; </script> <div class="container"> <h1><?php echo __("Subscribe to feed...") ?></h1> @@ -860,7 +903,7 @@ class Handler_Public extends Handler { <link rel="icon" type="image/png" sizes="72x72" href="images/favicon-72px.png"> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <?php - echo stylesheet_tag("css/default.css"); + echo stylesheet_tag("themes/light.css"); echo javascript_tag("lib/prototype.js"); echo javascript_tag("lib/dojo/dojo.js"); echo javascript_tag("lib/dojo/tt-rss-layer.js"); @@ -1061,11 +1104,11 @@ class Handler_Public extends Handler { <head> <title>Database Updater</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> - <?php echo stylesheet_tag("css/default.css") ?> + <?php echo stylesheet_tag("themes/light.css") ?> <link rel="shortcut icon" type="image/png" href="images/favicon.png"> <link rel="icon" type="image/png" sizes="72x72" href="images/favicon-72px.png"> <?php - echo stylesheet_tag("css/default.css"); + echo stylesheet_tag("themes/light.css"); echo javascript_tag("lib/prototype.js"); echo javascript_tag("lib/dojo/dojo.js"); echo javascript_tag("lib/dojo/tt-rss-layer.js"); diff --git a/classes/opml.php b/classes/opml.php index 6982aea27..48db9a8a3 100644 --- a/classes/opml.php +++ b/classes/opml.php @@ -24,7 +24,7 @@ class Opml extends Handler_Protected { print "<html> <head> - ".stylesheet_tag("css/default.css")." + ".stylesheet_tag("themes/light.css")." <title>".__("OPML Utility")."</title> <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/> </head> diff --git a/classes/pref/feeds.php b/classes/pref/feeds.php index f672a0375..6d7295beb 100755 --- a/classes/pref/feeds.php +++ b/classes/pref/feeds.php @@ -1389,17 +1389,11 @@ class Pref_Feeds extends Handler_Protected { $obj = array(); $cat_id = (int) $cat_id; - if ($cat_id > 0) { - $cat_unread = CCache::find($cat_id, $_SESSION["uid"], true); - } else if ($cat_id == 0 || $cat_id == -2) { - $cat_unread = Feeds::getCategoryUnread($cat_id); - } - $obj['id'] = 'CAT:' . $cat_id; $obj['items'] = array(); $obj['name'] = Feeds::getCategoryTitle($cat_id); $obj['type'] = 'category'; - $obj['unread'] = (int) $cat_unread; + $obj['unread'] = -1; //(int) Feeds::getCategoryUnread($cat_id); $obj['bare_id'] = $cat_id; return $obj; @@ -1562,12 +1556,9 @@ class Pref_Feeds extends Handler_Protected { } private function remove_feed_category($id, $owner_uid) { - $sth = $this->pdo->prepare("DELETE FROM ttrss_feed_categories WHERE id = ? AND owner_uid = ?"); $sth->execute([$id, $owner_uid]); - - CCache::remove($id, $owner_uid, true); } static function remove_feed($id, $owner_uid) { @@ -1640,11 +1631,8 @@ class Pref_Feeds extends Handler_Protected { unlink(ICONS_DIR . "/$id.ico"); } - CCache::remove($id, $owner_uid); - } else { Labels::remove(Labels::feed_to_label_id($id), $owner_uid); - //CCache::remove($id, $owner_uid); don't think labels are cached } } diff --git a/classes/pref/prefs.php b/classes/pref/prefs.php index 4214ac6a8..ac16b5971 100644 --- a/classes/pref/prefs.php +++ b/classes/pref/prefs.php @@ -327,7 +327,6 @@ class Pref_Prefs extends Handler_Protected { print "</form>"; print "</div>"; # content pane - print "<div dojoType='dijit.layout.ContentPane' title=\"".__('Password')."\">"; if ($_SESSION["auth_module"]) { $authenticator = PluginHost::getInstance()->get_plugin($_SESSION["auth_module"]); @@ -335,6 +334,8 @@ class Pref_Prefs extends Handler_Protected { $authenticator = false; } + print "<div dojoType='dijit.layout.ContentPane' title=\"" . __('Password') . "\">"; + if ($authenticator && method_exists($authenticator, "change_password")) { print "<div style='display : none' id='pwd_change_infobox'></div>"; @@ -375,17 +376,17 @@ class Pref_Prefs extends Handler_Protected { } print "<fieldset>"; - print "<label>".__("Old password:")."</label>"; + print "<label>" . __("Old password:") . "</label>"; print "<input dojoType='dijit.form.ValidationTextBox' type='password' required='1' name='old_password'>"; print "</fieldset>"; print "<fieldset>"; - print "<label>".__("New password:")."</label>"; + print "<label>" . __("New password:") . "</label>"; print "<input dojoType='dijit.form.ValidationTextBox' type='password' required='1' name='new_password'>"; print "</fieldset>"; print "<fieldset>"; - print "<label>".__("Confirm password:")."</label>"; + print "<label>" . __("Confirm password:") . "</label>"; print "<input dojoType='dijit.form.ValidationTextBox' type='password' required='1' name='confirm_password'>"; print "</fieldset>"; @@ -394,152 +395,156 @@ class Pref_Prefs extends Handler_Protected { print "<hr/>"; - print "<button dojoType='dijit.form.Button' type='submit' class='alt-primary'>". - __("Change password")."</button>"; + print "<button dojoType='dijit.form.Button' type='submit' class='alt-primary'>" . + __("Change password") . "</button>"; print "</form>"; - print "</div>"; # content pane + } else { + print_notice(T_sprintf("Authentication module used for this session (<b>%s</b>) does not provide an ability to set passwords.", + $_SESSION["auth_module"])); + } - if ($_SESSION["auth_module"] == "auth_internal") { + print "</div>"; # content pane - print "<div dojoType='dijit.layout.ContentPane' title=\"" . __('App passwords') . "\">"; + print "<div dojoType='dijit.layout.ContentPane' title=\"" . __('App passwords') . "\">"; - print_notice("You can create separate passwords for API clients. Using one is required if you enable OTP."); + print_notice("You can create separate passwords for API clients. Using one is required if you enable OTP."); - print "<div id='app_passwords_holder'>"; - $this->appPasswordList(); - print "</div>"; + print "<div id='app_passwords_holder'>"; + $this->appPasswordList(); + print "</div>"; - print "<hr>"; + print "<hr>"; - print "<button style='float : left' class='alt-primary' dojoType='dijit.form.Button' - onclick=\"Helpers.AppPasswords.generate()\">" . - __('Generate new password') . "</button> "; + print "<button style='float : left' class='alt-primary' dojoType='dijit.form.Button' + onclick=\"Helpers.AppPasswords.generate()\">" . + __('Generate new password') . "</button> "; - print "<button style='float : left' class='alt-danger' dojoType='dijit.form.Button' - onclick=\"Helpers.AppPasswords.removeSelected()\">" . - __('Remove selected passwords') . "</button>"; + print "<button style='float : left' class='alt-danger' dojoType='dijit.form.Button' + onclick=\"Helpers.AppPasswords.removeSelected()\">" . + __('Remove selected passwords') . "</button>"; - print "</div>"; # content pane - } + print "</div>"; # content pane - print "<div dojoType='dijit.layout.ContentPane' title=\"".__('One time passwords / Authenticator')."\">"; + print "<div dojoType='dijit.layout.ContentPane' title=\"".__('One time passwords / Authenticator')."\">"; - if ($_SESSION["auth_module"] == "auth_internal") { + if ($_SESSION["auth_module"] == "auth_internal") { - if ($otp_enabled) { + if ($otp_enabled) { - print_warning("One time passwords are currently enabled. Enter your current password below to disable."); + print_warning("One time passwords are currently enabled. Enter your current password below to disable."); + + print "<form dojoType='dijit.form.Form'>"; + + print "<script type='dojo/method' event='onSubmit' args='evt'> + evt.preventDefault(); + if (this.validate()) { + Notify.progress('Disabling OTP', true); + + new Ajax.Request('backend.php', { + parameters: dojo.objectToQuery(this.getValues()), + onComplete: function(transport) { + Notify.close(); + if (transport.responseText.indexOf('ERROR: ') == 0) { + Notify.error(transport.responseText.replace('ERROR: ', '')); + } else { + window.location.reload(); + } + }}); + this.reset(); + } + </script>"; - print "<form dojoType='dijit.form.Form'>"; + print "<fieldset>"; + print "<label>".__("Your password:")."</label>"; + print "<input dojoType='dijit.form.ValidationTextBox' type='password' required='1' name='password'>"; + print "</fieldset>"; - print "<script type='dojo/method' event='onSubmit' args='evt'> - evt.preventDefault(); - if (this.validate()) { - Notify.progress('Disabling OTP', true); + print_hidden("op", "pref-prefs"); + print_hidden("method", "otpdisable"); - new Ajax.Request('backend.php', { - parameters: dojo.objectToQuery(this.getValues()), - onComplete: function(transport) { - Notify.close(); - if (transport.responseText.indexOf('ERROR: ') == 0) { - Notify.error(transport.responseText.replace('ERROR: ', '')); - } else { - window.location.reload(); - } - }}); - this.reset(); - } - </script>"; + print "<hr/>"; - print "<fieldset>"; - print "<label>".__("Your password:")."</label>"; - print "<input dojoType='dijit.form.ValidationTextBox' type='password' required='1' name='password'>"; - print "</fieldset>"; + print "<button dojoType='dijit.form.Button' type='submit'>". + __("Disable OTP")."</button>"; - print_hidden("op", "pref-prefs"); - print_hidden("method", "otpdisable"); + print "</form>"; - print "<hr/>"; + } else { - print "<button dojoType='dijit.form.Button' type='submit'>". - __("Disable OTP")."</button>"; + print_warning("You will need a compatible Authenticator to use this. Changing your password would automatically disable OTP."); + print_notice("You will need to generate app passwords for the API clients if you enable OTP."); - print "</form>"; + if (function_exists("imagecreatefromstring")) { + print "<h3>" . __("Scan the following code by the Authenticator application or copy the key manually") . "</h3>"; + $csrf_token = $_SESSION["csrf_token"]; + print "<img alt='otp qr-code' src='backend.php?op=pref-prefs&method=otpqrcode&csrf_token=$csrf_token'>"; } else { + print_error("PHP GD functions are required to generate QR codes."); + print "<h3>" . __("Use the following OTP key with a compatible Authenticator application") . "</h3>"; + } - print_warning("You will need a compatible Authenticator to use this. Changing your password would automatically disable OTP."); - print_notice("You will need to generate app passwords for the API clients if you enable OTP."); - - if (function_exists("imagecreatefromstring")) { - print "<h3>" . __("Scan the following code by the Authenticator application or copy the key manually") . "</h3>"; - - $csrf_token = $_SESSION["csrf_token"]; - print "<img alt='otp qr-code' src='backend.php?op=pref-prefs&method=otpqrcode&csrf_token=$csrf_token'>"; - } else { - print_error("PHP GD functions are required to generate QR codes."); - print "<h3>" . __("Use the following OTP key with a compatible Authenticator application") . "</h3>"; - } - - print "<form dojoType='dijit.form.Form' id='changeOtpForm'>"; + print "<form dojoType='dijit.form.Form' id='changeOtpForm'>"; - $otp_secret = $this->otpsecret(); + $otp_secret = $this->otpsecret(); - print "<fieldset>"; - print "<label>".__("OTP Key:")."</label>"; - print "<input dojoType='dijit.form.ValidationTextBox' disabled='disabled' value='$otp_secret' size='32'>"; - print "</fieldset>"; + print "<fieldset>"; + print "<label>".__("OTP Key:")."</label>"; + print "<input dojoType='dijit.form.ValidationTextBox' disabled='disabled' value='$otp_secret' size='32'>"; + print "</fieldset>"; - print_hidden("op", "pref-prefs"); - print_hidden("method", "otpenable"); - - print "<script type='dojo/method' event='onSubmit' args='evt'> - evt.preventDefault(); - if (this.validate()) { - Notify.progress('Saving data...', true); - - new Ajax.Request('backend.php', { - parameters: dojo.objectToQuery(this.getValues()), - onComplete: function(transport) { - Notify.close(); - if (transport.responseText.indexOf('ERROR:') == 0) { - Notify.error(transport.responseText.replace('ERROR:', '')); - } else { - window.location.reload(); - } - } }); + print_hidden("op", "pref-prefs"); + print_hidden("method", "otpenable"); + + print "<script type='dojo/method' event='onSubmit' args='evt'> + evt.preventDefault(); + if (this.validate()) { + Notify.progress('Saving data...', true); + + new Ajax.Request('backend.php', { + parameters: dojo.objectToQuery(this.getValues()), + onComplete: function(transport) { + Notify.close(); + if (transport.responseText.indexOf('ERROR:') == 0) { + Notify.error(transport.responseText.replace('ERROR:', '')); + } else { + window.location.reload(); + } + } }); - } - </script>"; + } + </script>"; - print "<fieldset>"; - print "<label>".__("Your password:")."</label>"; - print "<input dojoType='dijit.form.ValidationTextBox' type='password' required='1' - name='password'>"; - print "</fieldset>"; + print "<fieldset>"; + print "<label>".__("Your password:")."</label>"; + print "<input dojoType='dijit.form.ValidationTextBox' type='password' required='1' + name='password'>"; + print "</fieldset>"; - print "<fieldset>"; - print "<label>".__("One time password:")."</label>"; - print "<input dojoType='dijit.form.ValidationTextBox' autocomplete='off' - required='1' name='otp'>"; - print "</fieldset>"; + print "<fieldset>"; + print "<label>".__("One time password:")."</label>"; + print "<input dojoType='dijit.form.ValidationTextBox' autocomplete='off' + required='1' name='otp'>"; + print "</fieldset>"; - print "<hr/>"; - print "<button dojoType='dijit.form.Button' type='submit' class='alt-primary'>". - __("Enable OTP")."</button>"; + print "<hr/>"; + print "<button dojoType='dijit.form.Button' type='submit' class='alt-primary'>". + __("Enable OTP")."</button>"; - print "</form>"; + print "</form>"; - } } - print "</div>"; # content pane - print "</div>"; # tab container - + } else { + print_notice("OTP is only available when using <b>auth_internal</b> authentication module."); } + print "</div>"; # content pane + + print "</div>"; # tab container + PluginHost::getInstance()->run_hooks(PluginHost::HOOK_PREFS_TAB_SECTION, "hook_prefs_tab_section", "prefPrefsAuth"); @@ -669,12 +674,12 @@ class Pref_Prefs extends Handler_Protected { $themes = array_filter($themes, "theme_exists"); asort($themes); - if (!theme_exists($value)) $value = "default.php"; + if (!theme_exists($value)) $value = ""; print "<select name='$pref_name' id='$pref_name' dojoType='fox.form.Select'>"; - $issel = $value == "default.php" ? "selected='selected'" : ""; - print "<option $issel value='default.php'>".__("default")."</option>"; + $issel = $value == "" ? "selected='selected'" : ""; + print "<option $issel value=''>".__("default")."</option>"; foreach ($themes as $theme) { $issel = $value == $theme ? "selected='selected'" : ""; diff --git a/classes/rssutils.php b/classes/rssutils.php index 66008899b..831ac1baf 100755 --- a/classes/rssutils.php +++ b/classes/rssutils.php @@ -1469,26 +1469,12 @@ class RSSUtils { mb_strtolower(strip_tags($title), 'utf-8')); } + /* counter cache is no longer used, if called truncate leftover data */ static function cleanup_counters_cache() { $pdo = Db::pdo(); - $res = $pdo->query("DELETE FROM ttrss_counters_cache - WHERE feed_id > 0 AND - (SELECT COUNT(id) FROM ttrss_feeds WHERE - id = feed_id AND - ttrss_counters_cache.owner_uid = ttrss_feeds.owner_uid) = 0"); - - $frows = $res->rowCount(); - - $res = $pdo->query("DELETE FROM ttrss_cat_counters_cache - WHERE feed_id > 0 AND - (SELECT COUNT(id) FROM ttrss_feed_categories WHERE - id = feed_id AND - ttrss_cat_counters_cache.owner_uid = ttrss_feed_categories.owner_uid) = 0"); - - $crows = $res->rowCount(); - - Debug::log("Removed $frows (feeds) $crows (cats) orphaned counter cache entries."); + $pdo->query("DELETE FROM ttrss_counters_cache"); + $pdo->query("DELETE FROM ttrss_cat_counters_cache"); } static function housekeeping_user($owner_uid) { |