Browse Source

More sub soft-delete fixes

redup
J. King 1 year ago
parent
commit
de6760d5d7
  1. 40
      lib/Database.php
  2. 22
      tests/cases/Database/SeriesArticle.php
  3. 25
      tests/cases/Database/SeriesFolder.php
  4. 15
      tests/cases/Database/SeriesIcon.php
  5. 48
      tests/cases/Database/SeriesLabel.php

40
lib/Database.php

@ -566,7 +566,7 @@ class Database {
coalesce(feeds,0) as feeds
from arsse_folders
left join (select parent,count(id) as children from arsse_folders group by parent) as child_stats on child_stats.parent = arsse_folders.id
left join (select folder,count(id) as feeds from arsse_subscriptions group by folder) as sub_stats on sub_stats.folder = arsse_folders.id",
left join (select folder,count(id) as feeds from arsse_subscriptions where deleted = 0 group by folder) as sub_stats on sub_stats.folder = arsse_folders.id",
["str", "strict int"],
[$user, $parent]
);
@ -1139,7 +1139,7 @@ class Database {
return V::normalize($out, V::T_DATE | V::M_NULL, "sql");
}
/** Evalutes the filter rules specified for a subscription against every article associated with the subscription's feed
/** Evalutes the filter rules specified for a subscription against every article associated with the subscription
*
* @param string $user The user who owns the subscription
* @param integer $id The identifier of the subscription whose rules are to be evaluated
@ -1458,7 +1458,7 @@ class Database {
* @param string $user The user whose subscription icons are to be retrieved
*/
public function iconList(string $user): Db\Result {
return $this->db->prepare("SELECT distinct i.id, i.url, i.type, i.data from arsse_icons as i join arsse_subscriptions as s on s.icon = i.id where s.owner = ?", "str")->run($user);
return $this->db->prepare("SELECT distinct i.id, i.url, i.type, i.data from arsse_icons as i join arsse_subscriptions as s on s.icon = i.id where s.owner = ? and s.deleted = 0", "str")->run($user);
}
/** Deletes orphaned icons from the database
@ -1571,7 +1571,7 @@ class Database {
select
$outColumns
from arsse_articles
join arsse_subscriptions on arsse_subscriptions.id = arsse_articles.subscription and arsse_subscriptions.owner = ? and deleted = 0
join arsse_subscriptions on arsse_subscriptions.id = arsse_articles.subscription and arsse_subscriptions.owner = ? and arsse_subscriptions.deleted = 0
left join arsse_article_contents on arsse_article_contents.id = arsse_articles.id
left join folder_data on arsse_subscriptions.folder = folder_data.id
left join arsse_enclosures on arsse_enclosures.article = arsse_articles.id
@ -1884,10 +1884,10 @@ class Database {
*
* @param string $user The user who owns the articles to be modified
* @param array $data An associative array of properties to modify. Anything not specified will remain unchanged
* @param Context|UnionContext $context The query context to match articles against
* @param Context $context The query context to match articles against
* @param bool $updateTimestamp Whether to also update the timestamp. This should only be false if a mark is changed as a result of an automated action not taken by the user
*/
public function articleMark(string $user, array $data, RootContext $context = null, bool $updateTimestamp = true): int {
public function articleMark(string $user, array $data, Context $context = null, bool $updateTimestamp = true): int {
$data = [
'read' => $data['read'] ?? null,
'starred' => $data['starred'] ?? null,
@ -2011,7 +2011,7 @@ class Database {
coalesce(sum(abs(\"read\" - 1)),0) as unread,
coalesce(sum(\"read\"),0) as \"read\"
FROM (
select \"read\" from arsse_articles where starred = 1 and hidden <> 1 and subscription in (select id from arsse_subscriptions where owner = ?)
select \"read\" from arsse_articles where starred = 1 and hidden <> 1 and subscription in (select id from arsse_subscriptions where owner = ? and deleted = 0)
) as starred_data",
"str"
)->run($user)->getRow();
@ -2148,7 +2148,7 @@ class Database {
join arsse_articles on arsse_articles.id = arsse_editions.article
join arsse_subscriptions on arsse_subscriptions.id = arsse_articles.subscription
join (select article, max(id) as edition from arsse_editions group by article) as edition_stats on edition_stats.article = arsse_editions.article
where arsse_editions.id = ? and arsse_subscriptions.owner = ?",
where arsse_editions.id = ? and arsse_subscriptions.owner = ? and arsse_subscriptions.deleted = 0",
["int", "str"]
)->run($id, $user)->getRow();
if (!$out) {
@ -2211,7 +2211,13 @@ class Database {
cast(coalesce(marked, 0) as $integerType) as \"read\" -- this cast is required for MySQL for unclear reasons
from arsse_labels
left join (
SELECT label, sum(assigned) as articles from arsse_label_members group by label
SELECT
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
group by label
) as label_stats on label_stats.label = arsse_labels.id
left join (
SELECT
@ -2221,7 +2227,7 @@ class Database {
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
where arsse_subscriptions.owner = ?
where arsse_subscriptions.owner = ? and arsse_subscriptions.deleted = 0
group by label
) as mark_stats on mark_stats.label = arsse_labels.id
WHERE owner = ?
@ -2275,7 +2281,13 @@ class Database {
coalesce(marked, 0) as \"read\"
FROM arsse_labels
left join (
SELECT label, sum(assigned) as articles from arsse_label_members group by label
SELECT
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
group by label
) as label_stats on label_stats.label = arsse_labels.id
left join (
SELECT
@ -2285,7 +2297,7 @@ class Database {
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
where arsse_subscriptions.owner = ?
where arsse_subscriptions.owner = ? and arsse_subscriptions.deleted = 0
group by label
) as mark_stats on mark_stats.label = arsse_labels.id
WHERE $field = ? and owner = ?",
@ -2374,7 +2386,7 @@ class Database {
if (!sizeof($articles)) {
if ($mode == self::ASSOC_REPLACE) {
// replacing with an empty set means setting everything to zero
return $this->db->prepare("UPDATE arsse_label_members set assigned = 0, modified = CURRENT_TIMESTAMP where label = ? and assigned = 1", "int")->run($id)->changes();
return $this->db->prepare("UPDATE arsse_label_members set assigned = 0, modified = CURRENT_TIMESTAMP where label = ? and assigned = 1 and article not in (select id from arsse_articles where subscription in (select id from arsse_subscriptions where deleted = 1))", "int")->run($id)->changes();
} else {
// adding or removing is a no-op
return 0;
@ -2384,7 +2396,7 @@ class Database {
}
// prepare up to three queries: removing requires one, adding two, and replacing three
[$inClause, $inTypes, $inValues] = $this->generateIn($articles, "int");
$updateQ = "UPDATE arsse_label_members set assigned = ?, modified = CURRENT_TIMESTAMP where label = ? and assigned <> ? and article %in% ($inClause)";
$updateQ = "UPDATE arsse_label_members set assigned = ?, modified = CURRENT_TIMESTAMP where label = ? and assigned <> ? and article %in% ($inClause) and article not in (select id from arsse_articles where subscription in (select id from arsse_subscriptions where deleted = 1))";
$updateT = ["bool", "int", "bool", $inTypes];
$insertQ = "INSERT INTO arsse_label_members(label,article) SELECT ?,a.id from arsse_articles as a join arsse_subscriptions as s on a.subscription = s.id where s.owner = ? and a.id not in (select article from arsse_label_members where label = ?) and a.id in ($inClause)";
$insertT = ["int", "str", "int", $inTypes];

22
tests/cases/Database/SeriesArticle.php

@ -129,7 +129,7 @@ trait SeriesArticle {
[208,14,null, null, null, null, null, null, "", "", "", "2010-01-01 00:00:00",0,0,0,null, ''],
[801,15,'http://example.com/1','Article title 1','', '2000-01-01 00:00:00','2000-01-01 00:00:01','e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda','f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6','fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4','18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207','2000-01-01 01:00:00',0,0,0,null, ''],
[802,15,'http://example.com/2','Article title 2','', '2000-01-02 00:00:00','2000-01-02 00:00:02','5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7','0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153','13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9','2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e','2000-01-02 02:00:00',0,0,0,null, ''],
[999,16,null, null, null, null, null, null, "", "", "", "2000-01-01 00:00:00",0,0,0,null, ''],
[999,16,null, null, null, null, null, null, "", "", "", "2000-01-01 00:00:00",0,1,0,null, ''],
],
],
'arsse_article_contents' => [
@ -208,7 +208,6 @@ trait SeriesArticle {
[ 802,802],
[ 902,802],
[ 999,999],
[9999,999],
],
],
'arsse_enclosures' => [
@ -250,14 +249,15 @@ trait SeriesArticle {
'arsse_label_members' => [
'columns' => ["label", "article", "assigned", "modified"],
'rows' => [
[1, 1,1,'2000-01-01 00:00:00'],
[2, 1,1,'2000-01-01 00:00:00'],
[1,19,1,'2000-01-01 00:00:00'],
[2,20,1,'2000-01-01 00:00:00'],
[1, 5,0,'2000-01-01 00:00:00'],
[2, 5,1,'2000-01-01 00:00:00'],
[4, 7,0,'2000-01-01 00:00:00'],
[4, 8,1,'2015-01-01 00:00:00'],
[1, 1,1,'2000-01-01 00:00:00'],
[2, 1,1,'2000-01-01 00:00:00'],
[1, 19,1,'2000-01-01 00:00:00'],
[2, 20,1,'2000-01-01 00:00:00'],
[1, 5,0,'2000-01-01 00:00:00'],
[2, 5,1,'2000-01-01 00:00:00'],
[4, 7,0,'2000-01-01 00:00:00'],
[4, 8,1,'2015-01-01 00:00:00'],
[1,999,1,'2000-01-01 00:00:00'],
],
],
];
@ -889,7 +889,7 @@ trait SeriesArticle {
public function testMarkAnEditionOfADeletedSubscription(): void {
$this->assertException("subjectMissing", "Db", "ExceptionInput");
Arsse::$db->articleMark("john.doe@example.com", ['starred' => true], (new Context)->edition(9999));
Arsse::$db->articleMark("john.doe@example.com", ['starred' => false], (new Context)->edition(999));
}
public function testMarkByOldestEdition(): void {

25
tests/cases/Database/SeriesFolder.php

@ -42,19 +42,20 @@ trait SeriesFolder {
],
],
'arsse_subscriptions' => [
'columns' => ["id", "owner", "url", "title", "folder"],
'columns' => ["id", "owner", "url", "title", "folder", "deleted"],
'rows' => [
[1, "john.doe@example.com","http://example.com/1", "Feed 1", null],
[2, "john.doe@example.com","http://example.com/2", "Feed 2", null],
[3, "john.doe@example.com","http://example.com/3", "Feed 3", 1],
[4, "john.doe@example.com","http://example.com/4", "Feed 4", 6],
[5, "john.doe@example.com","http://example.com/5", "Feed 5", 5],
[6, "john.doe@example.com","http://example.com/10", "Feed 10", 5],
[7, "jane.doe@example.com","http://example.com/1", "Feed 1", null],
[8, "jane.doe@example.com","http://example.com/10", "Feed 10",null],
[9, "jane.doe@example.com","http://example.com/2", "Feed 2", 4],
[10,"jane.doe@example.com","http://example.com/3", "Feed 3", 4],
[11,"jane.doe@example.com","http://example.com/4", "Feed 4", 4],
[1, "john.doe@example.com", "http://example.com/1", "Feed 1", null, 0],
[2, "john.doe@example.com", "http://example.com/2", "Feed 2", null, 0],
[3, "john.doe@example.com", "http://example.com/3", "Feed 3", 1, 0],
[4, "john.doe@example.com", "http://example.com/4", "Feed 4", 6, 0],
[5, "john.doe@example.com", "http://example.com/5", "Feed 5", 5, 0],
[6, "john.doe@example.com", "http://example.com/10", "Feed 10", 5, 0],
[101, "john.doe@example.com", "http://example.com/101", "Feed 101", 1, 1],
[7, "jane.doe@example.com", "http://example.com/1", "Feed 1", null, 0],
[8, "jane.doe@example.com", "http://example.com/10", "Feed 10", null, 0],
[9, "jane.doe@example.com", "http://example.com/2", "Feed 2", 4, 0],
[10, "jane.doe@example.com", "http://example.com/3", "Feed 3", 4, 0],
[11, "jane.doe@example.com", "http://example.com/4", "Feed 4", 4, 0],
],
],
];

15
tests/cases/Database/SeriesIcon.php

@ -31,14 +31,15 @@ trait SeriesIcon {
],
],
'arsse_subscriptions' => [
'columns' => ["id", "owner", "url", "title", "icon"],
'columns' => ["id", "owner", "url", "title", "icon", "deleted"],
'rows' => [
[1,'john.doe@example.com',"http://localhost:8000/Feed/Matching/3", "Ook", 1],
[2,'john.doe@example.com',"http://localhost:8000/Feed/Matching/1", "Eek", 2],
[3,'john.doe@example.com',"http://localhost:8000/Feed/Fetching/Error?code=404", "Ack", 3],
[4,'john.doe@example.com',"http://localhost:8000/Feed/NextFetch/NotModified?t=".time(), "Ooook", null],
[5,'john.doe@example.com',"http://localhost:8000/Feed/Parsing/Valid", "Ooook", 2],
[6,'jane.doe@example.com',"http://localhost:8000/Feed/Parsing/Valid", "Ooook", 2],
[1,'john.doe@example.com',"http://localhost:8000/Feed/Matching/3", "Ook", 1, 0],
[2,'john.doe@example.com',"http://localhost:8000/Feed/Matching/1", "Eek", 2, 0],
[3,'john.doe@example.com',"http://localhost:8000/Feed/Fetching/Error?code=404", "Ack", 3, 0],
[4,'john.doe@example.com',"http://localhost:8000/Feed/NextFetch/NotModified?t=".time(), "Ooook", null, 0],
[5,'john.doe@example.com',"http://localhost:8000/Feed/Parsing/Valid", "Ooook", 2, 0],
[6,'john.doe@example.com',"http://localhost:8000/Feed/Discovery/Valid", "Aaack", 4, 1],
[7,'jane.doe@example.com',"http://localhost:8000/Feed/Parsing/Valid", "Ooook", 2, 0],
],
],
];

48
tests/cases/Database/SeriesLabel.php

@ -40,22 +40,23 @@ trait SeriesLabel {
],
],
'arsse_subscriptions' => [
'columns' => ["id", "owner", "url", "folder"],
'columns' => ["id", "owner", "url", "folder", "deleted"],
'rows' => [
[1, "john.doe@example.com","http://example.com/1",null],
[2, "john.doe@example.com","http://example.com/2",null],
[3, "john.doe@example.com","http://example.com/3",1],
[4, "john.doe@example.com","http://example.com/4",6],
[5, "john.doe@example.com","http://example.com/10",5],
[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",9],
[13,"john.doe@example.net","http://example.com/3",8],
[14,"john.doe@example.net","http://example.com/4",7],
[1, "john.doe@example.com", "http://example.com/1", null, 0],
[2, "john.doe@example.com", "http://example.com/2", null, 0],
[3, "john.doe@example.com", "http://example.com/3", 1, 0],
[4, "john.doe@example.com", "http://example.com/4", 6, 0],
[5, "john.doe@example.com", "http://example.com/10" ,5, 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", 9, 0],
[13, "john.doe@example.net", "http://example.com/3", 8, 0],
[14, "john.doe@example.net", "http://example.com/4", 7, 0],
[16, "john.doe@example.com", "http://example.com/16", null, 1],
],
],
'arsse_articles' => [
@ -92,6 +93,7 @@ trait SeriesLabel {
[206,13,null, null, "Jane Doe",null, null, null, "", "", "", "2010-01-01 00:00:00",0,0,0,null, ''],
[207,14,null, null, "Jane Doe",null, null, null, "", "", "", "2000-01-01 00:00:00",0,0,0,null, ''],
[208,14,null, null, null, null, null, null, "", "", "", "2010-01-01 00:00:00",0,0,0,null, ''],
[999,16,null, null, null, null, null, null, "", "", "", "2000-01-01 00:00:00",1,1,0,null, ''],
],
],
'arsse_article_contents' => [
@ -204,13 +206,15 @@ trait SeriesLabel {
'arsse_label_members' => [
'columns' => ["label", "article", "assigned"],
'rows' => [
[1, 1,1],
[2, 1,1],
[1,19,1],
[2,20,1],
[1, 5,0],
[2, 5,1],
[2, 8,1],
[1, 1,1],
[2, 1,1],
[1, 19,1],
[2, 20,1],
[1, 5,0],
[2, 5,1],
[2, 8,1],
[1,999,1],
[2,999,1],
],
],
];

Loading…
Cancel
Save