diff --git a/lib/Database.php b/lib/Database.php index 5db259c..a6b967d 100644 --- a/lib/Database.php +++ b/lib/Database.php @@ -2215,8 +2215,8 @@ class Database { label, sum(assigned) as articles from arsse_label_members - join arsse_articles on arsse_articles.id = arsse_label_members.article - join arsse_subscriptions on arsse_articles.subscription = arsse_subscriptions.id and arsse_subscriptions.deleted = 0 + join arsse_articles on arsse_articles.id = arsse_label_members.article + join arsse_subscriptions on arsse_articles.subscription = arsse_subscriptions.id and arsse_subscriptions.deleted = 0 group by label ) as label_stats on label_stats.label = arsse_labels.id left join ( @@ -2295,8 +2295,8 @@ class Database { sum(hidden) as hidden, sum(case when \"read\" = 1 and hidden = 0 then 1 else 0 end) as marked from arsse_articles - join arsse_subscriptions on arsse_subscriptions.id = arsse_articles.subscription - join arsse_label_members on arsse_label_members.article = arsse_articles.id + join arsse_subscriptions on arsse_subscriptions.id = arsse_articles.subscription + join arsse_label_members on arsse_label_members.article = arsse_articles.id where arsse_subscriptions.owner = ? and arsse_subscriptions.deleted = 0 group by label ) as mark_stats on mark_stats.label = arsse_labels.id @@ -2512,7 +2512,7 @@ class Database { tag, sum(assigned) as subscriptions from arsse_tag_members - --join arsse_subscriptions on arsse_subscriptions.id = arsse_tag_members.subscription and arsse_subscriptions.deleted = 0 + join arsse_subscriptions on arsse_subscriptions.id = arsse_tag_members.subscription and arsse_subscriptions.deleted = 0 group by tag ) as tag_stats on tag_stats.tag = arsse_tags.id WHERE owner = ? @@ -2528,8 +2528,7 @@ class Database { * * - "tag_id": The tag's numeric identifier * - "tag_name" The tag's textual name - * - "subscription_id": The numeric identifier of the associated subscription - * - "subscription_name" The subscription's textual name + * - "subscription": The numeric identifier of the associated subscription * * @param string $user The user whose tags are to be listed */ @@ -2541,6 +2540,7 @@ class Database { arsse_tag_members.subscription as subscription FROM arsse_tag_members join arsse_tags on arsse_tags.id = arsse_tag_members.tag + join arsse_subscriptions on arsse_subscriptions.id = arsse_tag_members.subscription and arsse_subscriptions.deleted = 0 WHERE arsse_tags.owner = ? and assigned = 1", ["str"] )->run($user); @@ -2583,10 +2583,19 @@ class Database { $type = $byName ? "str" : "int"; $out = $this->db->prepareArray( "SELECT - id,name,coalesce(subscriptions,0) as subscriptions + id, + name, + coalesce(subscriptions,0) as subscriptions FROM arsse_tags - left join (SELECT tag, sum(assigned) as subscriptions from arsse_tag_members group by tag) as tag_stats on tag_stats.tag = arsse_tags.id - WHERE $field = ? and owner = ?", + left join ( + SELECT + tag, + sum(assigned) as subscriptions + from arsse_tag_members + join arsse_subscriptions on arsse_subscriptions.id = arsse_tag_members.subscription and arsse_subscriptions.deleted = 0 + group by tag + ) as tag_stats on tag_stats.tag = arsse_tags.id + WHERE $field = ? and arsse_tags.owner = ?", [$type, "str"] )->run($id, $user)->getRow(); if (!$out) { @@ -2633,9 +2642,18 @@ class Database { public function tagSubscriptionsGet(string $user, $id, bool $byName = false): array { // just do a syntactic check on the tag ID $this->tagValidateId($user, $id, $byName, false); - $field = !$byName ? "id" : "name"; + $field = !$byName ? "t.id" : "t.name"; $type = !$byName ? "int" : "str"; - $out = $this->db->prepare("SELECT subscription from arsse_tag_members join arsse_tags on tag = id where assigned = 1 and $field = ? and owner = ? order by subscription", $type, "str")->run($id, $user)->getAll(); + $out = $this->db->prepare( + "SELECT + subscription + from arsse_tag_members as m + join arsse_tags as t on m.tag = t.id + join arsse_subscriptions as s on m.subscription = s.id and s.deleted = 0 + where assigned = 1 and $field = ? and t.owner = ? + order by subscription", + $type, "str" + )->run($id, $user)->getAll(); if (!$out) { // if no results were returned, do a full validation on the tag ID $this->tagValidateId($user, $id, $byName, true, true); @@ -2663,7 +2681,7 @@ class Database { if (!sizeof($subscriptions)) { if ($mode == self::ASSOC_REPLACE) { // replacing with an empty set means setting everything to zero - return $this->db->prepare("UPDATE arsse_tag_members set assigned = 0, modified = CURRENT_TIMESTAMP where tag = ? and assigned = 1", "int")->run($id)->changes(); + return $this->db->prepare("UPDATE arsse_tag_members set assigned = 0, modified = CURRENT_TIMESTAMP where tag = ? and assigned = 1 and subscription not in (select id from arsse_subscriptions where deleted = 1)", "int")->run($id)->changes(); } else { // adding or removing is a no-op return 0; @@ -2671,7 +2689,7 @@ class Database { } // prepare up to three queries: removing requires one, adding two, and replacing three [$inClause, $inTypes, $inValues] = $this->generateIn($subscriptions, "int"); - $updateQ = "UPDATE arsse_tag_members set assigned = ?, modified = CURRENT_TIMESTAMP where tag = ? and assigned <> ? and subscription in (select id from arsse_subscriptions where owner = ? and id %in% ($inClause))"; + $updateQ = "UPDATE arsse_tag_members set assigned = ?, modified = CURRENT_TIMESTAMP where tag = ? and assigned <> ? and subscription in (select id from arsse_subscriptions where owner = ? and id %in% ($inClause) and id not in (select id from arsse_subscriptions where deleted = 1))"; $updateT = ["bool", "int", "bool", "str", $inTypes]; $insertQ = "INSERT INTO arsse_tag_members(tag,subscription) SELECT ?,id from arsse_subscriptions where id not in (select subscription from arsse_tag_members where tag = ?) and owner = ? and id in ($inClause)"; $insertT = ["int", "int", "str", $inTypes]; diff --git a/tests/cases/Database/SeriesTag.php b/tests/cases/Database/SeriesTag.php index 69b932b..39d83c0 100644 --- a/tests/cases/Database/SeriesTag.php +++ b/tests/cases/Database/SeriesTag.php @@ -27,22 +27,23 @@ trait SeriesTag { ], ], 'arsse_subscriptions' => [ - 'columns' => ["id", "owner", "url", "feed_title", "title"], + 'columns' => ["id", "owner", "url", "feed_title", "title", "deleted"], 'rows' => [ - [1, "john.doe@example.com", "http://example.com/1", "", "Lord of Carrots"], - [2, "john.doe@example.com", "http://example.com/2", "", null], - [3, "john.doe@example.com", "http://example.com/3", "Feed Title", "Subscription Title"], - [4, "john.doe@example.com", "http://example.com/4", "", null], - [5, "john.doe@example.com", "http://example.com/10", "", null], - [6, "jane.doe@example.com", "http://example.com/1", "", null], - [7, "jane.doe@example.com", "http://example.com/10", "", null], - [8, "john.doe@example.org", "http://example.com/11", "", null], - [9, "john.doe@example.org", "http://example.com/12", "", null], - [10, "john.doe@example.org", "http://example.com/13", "", null], - [11, "john.doe@example.net", "http://example.com/10", "", null], - [12, "john.doe@example.net", "http://example.com/2", "", null], - [13, "john.doe@example.net", "http://example.com/3", "Feed Title", null], - [14, "john.doe@example.net", "http://example.com/4", "", null], + [1, "john.doe@example.com", "http://example.com/1", "", "Lord of Carrots", 0], + [2, "john.doe@example.com", "http://example.com/2", "", null, 0], + [3, "john.doe@example.com", "http://example.com/3", "Feed Title", "Subscription Title", 0], + [4, "john.doe@example.com", "http://example.com/4", "", null, 0], + [5, "john.doe@example.com", "http://example.com/10", "", null, 0], + [6, "jane.doe@example.com", "http://example.com/1", "", null, 0], + [7, "jane.doe@example.com", "http://example.com/10", "", null, 0], + [8, "john.doe@example.org", "http://example.com/11", "", null, 0], + [9, "john.doe@example.org", "http://example.com/12", "", null, 0], + [10, "john.doe@example.org", "http://example.com/13", "", null, 0], + [11, "john.doe@example.net", "http://example.com/10", "", null, 0], + [12, "john.doe@example.net", "http://example.com/2", "", null, 0], + [13, "john.doe@example.net", "http://example.com/3", "Feed Title", null, 0], + [14, "john.doe@example.net", "http://example.com/4", "", null, 0], + [16, "john.doe@example.com", "http://example.com/16", "", null, 1], ], ], 'arsse_tags' => [ @@ -57,12 +58,14 @@ trait SeriesTag { 'arsse_tag_members' => [ 'columns' => ["tag", "subscription", "assigned"], 'rows' => [ - [1,1,1], - [1,3,0], - [1,5,1], - [2,1,1], - [2,3,1], - [2,5,1], + [1, 1,1], + [1, 3,0], + [1, 5,1], + [2, 1,1], + [2, 3,1], + [2, 5,1], + [1,16,1], + [2,16,1], ], ], ]; @@ -106,13 +109,13 @@ trait SeriesTag { public function testListTags(): void { $exp = [ - ['id' => 2, 'name' => "Fascinating"], - ['id' => 1, 'name' => "Interesting"], - ['id' => 4, 'name' => "Lonely"], + ['id' => 2, 'name' => "Fascinating", 'subscriptions' => 3], + ['id' => 1, 'name' => "Interesting", 'subscriptions' => 2], + ['id' => 4, 'name' => "Lonely", 'subscriptions' => 0], ]; $this->assertResult($exp, Arsse::$db->tagList("john.doe@example.com")); $exp = [ - ['id' => 3, 'name' => "Boring"], + ['id' => 3, 'name' => "Boring", 'subscriptions' => 0], ]; $this->assertResult($exp, Arsse::$db->tagList("jane.doe@example.com")); $exp = [];