1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-22 21:22:40 +00:00

Changed foreign key on marks table

Previously arsse_marks had a reference to arsse_users along with arsse_articles; the former has now changed to arsse_subscriptions.

Consequently deleting a subscription now deletes marks. Tests have been simplified as a consequence.

This change was understaken to simplify counting valid marks on articles for the purposes of article cleanup; now all marks are valid marks
This commit is contained in:
J. King 2017-08-14 17:18:18 -04:00
parent 3b018c89d1
commit 67203679aa
5 changed files with 166 additions and 143 deletions

View file

@ -271,7 +271,7 @@ class Database {
} else { } else {
return $this->db->prepare( return $this->db->prepare(
"WITH RECURSIVE folders(id) as (SELECT id from arsse_folders where owner is ? and parent is ? union select arsse_folders.id from arsse_folders join folders on arsse_folders.parent=folders.id) ". "WITH RECURSIVE folders(id) as (SELECT id from arsse_folders where owner is ? and parent is ? union select arsse_folders.id from arsse_folders join folders on arsse_folders.parent=folders.id) ".
"SELECT id,name,parent from arsse_folders where id in(SELECT id from folders) order by name", "SELECT id,name,parent from arsse_folders where id in (SELECT id from folders) order by name",
"str", "int")->run($user, $parent); "str", "int")->run($user, $parent);
} }
} }
@ -404,7 +404,7 @@ class Database {
url,favicon,source,folder,pinned,err_count,err_msg,order_type,added, url,favicon,source,folder,pinned,err_count,err_msg,order_type,added,
topmost.top as top_folder, topmost.top as top_folder,
coalesce(arsse_subscriptions.title, arsse_feeds.title) as title, coalesce(arsse_subscriptions.title, arsse_feeds.title) as title,
(SELECT count(*) from arsse_articles where feed is arsse_subscriptions.feed) - (SELECT count(*) from arsse_marks join user on user is owner join arsse_articles on article = arsse_articles.id where feed is arsse_feeds.id and read is 1) as unread (SELECT count(*) from arsse_articles where feed is arsse_subscriptions.feed) - (SELECT count(*) from arsse_marks where subscription is arsse_subscriptions.id and read is 1) as unread
from arsse_subscriptions from arsse_subscriptions
join user on user is owner join user on user is owner
join arsse_feeds on feed = arsse_feeds.id join arsse_feeds on feed = arsse_feeds.id
@ -678,10 +678,10 @@ class Database {
edited as edited_date, edited as edited_date,
max( max(
modified, modified,
coalesce((select modified from arsse_marks join user on user is owner where article is arsse_articles.id),'') coalesce((select modified from arsse_marks where article is arsse_articles.id and subscription in (select sub from subscribed_feeds)),'')
) as modified_date, ) as modified_date,
NOT (select count(*) from arsse_marks join user on user is owner where article is arsse_articles.id and read is 1) as unread, NOT (select count(*) from arsse_marks where article is arsse_articles.id and read is 1 and subscription in (select sub from subscribed_feeds)) as unread,
(select count(*) from arsse_marks join user on user is owner where article is arsse_articles.id and starred is 1) as starred, (select count(*) from arsse_marks where article is arsse_articles.id and starred is 1 and subscription in (select sub from subscribed_feeds)) as starred,
(select max(id) from arsse_editions where article is arsse_articles.id) as edition, (select max(id) from arsse_editions where article is arsse_articles.id) as edition,
subscribed_feeds.sub as subscription, subscribed_feeds.sub as subscription,
url_title_hash||':'||url_content_hash||':'||title_content_hash as fingerprint, url_title_hash||':'||url_content_hash||':'||title_content_hash as fingerprint,
@ -756,11 +756,11 @@ class Database {
starred = coalesce((select starred from target_values),starred), starred = coalesce((select starred from target_values),starred),
modified = CURRENT_TIMESTAMP modified = CURRENT_TIMESTAMP
WHERE WHERE
owner is (select user from user) subscription in (select sub from subscribed_feeds)
and article in (select id from target_articles where to_insert is 0 and (honour_read is 1 or honour_star is 1))", and article in (select id from target_articles where to_insert is 0 and (honour_read is 1 or honour_star is 1))",
"INSERT INTO arsse_marks(owner,article,read,starred) "INSERT INTO arsse_marks(subscription,article,read,starred)
select select
(select user from user), (select id from arsse_subscriptions join user on user is owner where arsse_subscriptions.feed is target_articles.feed),
id, id,
coalesce((select read from target_values) * honour_read,0), coalesce((select read from target_values) * honour_read,0),
coalesce((select starred from target_values),0) coalesce((select starred from target_values),0)
@ -787,26 +787,21 @@ class Database {
$q = new Query( $q = new Query(
"SELECT "SELECT
arsse_articles.id as id, arsse_articles.id as id,
feed,
(select max(id) from arsse_editions where article is arsse_articles.id) as edition, (select max(id) from arsse_editions where article is arsse_articles.id) as edition,
max(arsse_articles.modified, max(arsse_articles.modified,
coalesce((select modified from arsse_marks join user on user is owner where article is arsse_articles.id),'') coalesce((select modified from arsse_marks where article is arsse_articles.id and subscription in (select sub from subscribed_feeds)),'')
) as modified_date, ) as modified_date,
(not exists(select id from arsse_marks join user on user is owner where article is arsse_articles.id)) as to_insert, (not exists(select article from arsse_marks where article is arsse_articles.id and subscription in (select sub from subscribed_feeds))) as to_insert,
((select read from target_values) is not null and (select read from target_values) is not (coalesce((select read from arsse_marks join user on user is owner where article is arsse_articles.id),0)) and (not exists(select * from requested_articles) or (select max(id) from arsse_editions where article is arsse_articles.id) in (select edition from requested_articles))) as honour_read, ((select read from target_values) is not null and (select read from target_values) is not (coalesce((select read from arsse_marks where article is arsse_articles.id and subscription in (select sub from subscribed_feeds)),0)) and (not exists(select * from requested_articles) or (select max(id) from arsse_editions where article is arsse_articles.id) in (select edition from requested_articles))) as honour_read,
((select starred from target_values) is not null and (select starred from target_values) is not (coalesce((select starred from arsse_marks join user on user is owner where article is arsse_articles.id),0))) as honour_star ((select starred from target_values) is not null and (select starred from target_values) is not (coalesce((select starred from arsse_marks where article is arsse_articles.id and subscription in (select sub from subscribed_feeds)),0))) as honour_star
FROM arsse_articles" FROM arsse_articles"
); );
// common table expression for the affected user // common table expression for the affected user
$q->setCTE("user(user)", "SELECT ?", "str", $user); $q->setCTE("user(user)", "SELECT ?", "str", $user);
// common table expression with the values to set // common table expression with the values to set
$q->setCTE("target_values(read,starred)", "SELECT ?,?", ["bool","bool"], $values); $q->setCTE("target_values(read,starred)", "SELECT ?,?", ["bool","bool"], $values);
if($context->edition()) { if($context->subscription()) {
// if an edition is specified, filter for its previously identified article
$q->setWhere("arsse_articles.id is ?", "int", $edition['article']);
} else if($context->article()) {
// if an article is specified, filter for it (it has already been validated above)
$q->setWhere("arsse_articles.id is ?", "int", $context->article);
} else if($context->subscription()) {
// if a subscription is specified, make sure it exists // if a subscription is specified, make sure it exists
$id = $this->subscriptionValidateId($user, $context->subscription)['feed']; $id = $this->subscriptionValidateId($user, $context->subscription)['feed'];
// add a basic CTE that will join in only the requested subscription // add a basic CTE that will join in only the requested subscription
@ -822,6 +817,13 @@ class Database {
// otherwise add a CTE for all the user's subscriptions // otherwise add a CTE for all the user's subscriptions
$q->setCTE("subscribed_feeds(id,sub)", "SELECT feed,id from arsse_subscriptions join user on user is owner", [], [], "join subscribed_feeds on feed is subscribed_feeds.id"); $q->setCTE("subscribed_feeds(id,sub)", "SELECT feed,id from arsse_subscriptions join user on user is owner", [], [], "join subscribed_feeds on feed is subscribed_feeds.id");
} }
if($context->edition()) {
// if an edition is specified, filter for its previously identified article
$q->setWhere("arsse_articles.id is ?", "int", $edition['article']);
} else if($context->article()) {
// if an article is specified, filter for it (it has already been validated above)
$q->setWhere("arsse_articles.id is ?", "int", $context->article);
}
if($context->editions()) { if($context->editions()) {
// if multiple specific editions have been requested, prepare a CTE to list them and their articles // if multiple specific editions have been requested, prepare a CTE to list them and their articles
if(!$context->editions) { if(!$context->editions) {
@ -869,7 +871,7 @@ class Database {
$q->setWhere("modified_date <= ?", "datetime", $context->notModifiedSince); $q->setWhere("modified_date <= ?", "datetime", $context->notModifiedSince);
} }
// push the current query onto the CTE stack and execute the query we're actually interested in // push the current query onto the CTE stack and execute the query we're actually interested in
$q->pushCTE("target_articles(id,edition,modified_date,to_insert,honour_read,honour_star)"); $q->pushCTE("target_articles(id,feed,edition,modified_date,to_insert,honour_read,honour_star)");
$q->setBody($query); $q->setBody($query);
$out += $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->changes(); $out += $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->changes();
} }
@ -878,21 +880,11 @@ class Database {
return (bool) $out; return (bool) $out;
} }
public function articleStarredCount(string $user, array $context = []): int { public function articleStarredCount(string $user): int {
if(!Arsse::$user->authorize($user, __FUNCTION__)) { if(!Arsse::$user->authorize($user, __FUNCTION__)) {
throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]); throw new User\ExceptionAuthz("notAuthorized", ["action" => __FUNCTION__, "user" => $user]);
} }
return $this->db->prepare( return $this->db->prepare("SELECT count(*) from arsse_marks where starred is 1 and subscription in (select id from arsse_subscriptions where owner is ?)", "str")->run($user)->getValue();
"WITH RECURSIVE
user(user) as (SELECT ?),
subscribed_feeds(id,sub) as (SELECT feed,id from arsse_subscriptions join user on user is owner) ".
"SELECT count(*) from arsse_marks
join user on user is owner
join arsse_articles on arsse_marks.article is arsse_articles.id
join subscribed_feeds on arsse_articles.feed is subscribed_feeds.id
where starred is 1",
"str"
)->run($user)->getValue();
} }
protected function articleValidateId(string $user, int $id): array { protected function articleValidateId(string $user, int $id): array {

View file

@ -94,13 +94,12 @@ create table arsse_enclosures(
-- users' actions on newsfeed entries -- users' actions on newsfeed entries
create table arsse_marks( create table arsse_marks(
id integer primary key,
article integer not null references arsse_articles(id) on delete cascade, article integer not null references arsse_articles(id) on delete cascade,
owner text not null references arsse_users(id) on delete cascade on update cascade, subscription integer not null references arsse_subscriptions(id) on delete cascade on update cascade,
read boolean not null default 0, read boolean not null default 0,
starred boolean not null default 0, starred boolean not null default 0,
modified text not null default CURRENT_TIMESTAMP, modified text not null default CURRENT_TIMESTAMP,
unique(article,owner) primary key(article,subscription)
); );
-- IDs for specific editions of articles (required for at least NextCloud News) -- IDs for specific editions of articles (required for at least NextCloud News)

View file

@ -80,7 +80,7 @@ trait SeriesArticle {
[4,"john.doe@example.com",4,6], [4,"john.doe@example.com",4,6],
[5,"john.doe@example.com",10,5], [5,"john.doe@example.com",10,5],
[6,"jane.doe@example.com",1,null], [6,"jane.doe@example.com",1,null],
[7,"jane.doe@example.com",9,null], [7,"jane.doe@example.com",10,null],
[8,"john.doe@example.org",11,null], [8,"john.doe@example.org",11,null],
[9,"john.doe@example.org",12,null], [9,"john.doe@example.org",12,null],
[10,"john.doe@example.org",13,null], [10,"john.doe@example.org",13,null],
@ -106,7 +106,27 @@ trait SeriesArticle {
'title_content_hash' => "str", 'title_content_hash' => "str",
'modified' => "datetime", 'modified' => "datetime",
], ],
'rows' => [ // lower IDs are filled by series setup 'rows' => [
[1,1,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[2,1,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[3,2,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[4,2,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[5,3,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[6,3,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[7,4,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[8,4,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[9,5,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[10,5,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[11,6,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[12,6,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[13,7,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[14,7,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[15,8,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[16,8,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[17,9,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[18,9,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[19,10,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"],
[20,10,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"],
[101,11,'http://example.com/1','Article title 1','','2000-01-01 00:00:00','2000-01-01 00:00:01','<p>Article content 1</p>','e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda','f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6','fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4','18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207','2000-01-01 01:00:00'], [101,11,'http://example.com/1','Article title 1','','2000-01-01 00:00:00','2000-01-01 00:00:01','<p>Article content 1</p>','e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda','f5cb8bfc1c7396dc9816af212a3e2ac5221585c2a00bf7ccb6aabd95dcfcd6a6','fb0bc8f8cb08913dc5a497db700e327f1d34e4987402687d494a5891f24714d4','18fdd4fa93d693128c43b004399e5c9cea6c261ddfa002518d3669f55d8c2207','2000-01-01 01:00:00'],
[102,11,'http://example.com/2','Article title 2','','2000-01-02 00:00:00','2000-01-02 00:00:02','<p>Article content 2</p>','5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7','0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153','13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9','2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e','2000-01-02 02:00:00'], [102,11,'http://example.com/2','Article title 2','','2000-01-02 00:00:00','2000-01-02 00:00:02','<p>Article content 2</p>','5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7','0e86d2de822a174fe3c44a466953e63ca1f1a58a19cbf475fce0855d4e3d5153','13075894189c47ffcfafd1dfe7fbb539f7c74a69d35a399b3abf8518952714f9','2abd0a8cba83b8214a66c8f0293ba63e467d720540e29ff8ddcdab069d4f1c9e','2000-01-02 02:00:00'],
[103,12,'http://example.com/3','Article title 3','','2000-01-03 00:00:00','2000-01-03 00:00:03','<p>Article content 3</p>','31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92','f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b','b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406','ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b','2000-01-03 03:00:00'], [103,12,'http://example.com/3','Article title 3','','2000-01-03 00:00:00','2000-01-03 00:00:03','<p>Article content 3</p>','31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92','f74b06b240bd08abf4d3fdfc20dba6a6f6eb8b4f1a00e9a617efd63a87180a4b','b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406','ad622b31e739cd3a3f3c788991082cf4d2f7a8773773008e75f0572e58cd373b','2000-01-03 03:00:00'],
@ -133,7 +153,27 @@ trait SeriesArticle {
'id' => "int", 'id' => "int",
'article' => "int", 'article' => "int",
], ],
'rows' => [ // lower IDs are filled by series setup 'rows' => [
[1,1],
[2,2],
[3,3],
[4,4],
[5,5],
[6,6],
[7,7],
[8,8],
[9,9],
[10,10],
[11,11],
[12,12],
[13,13],
[14,14],
[15,15],
[16,16],
[17,17],
[18,18],
[19,19],
[20,20],
[101,101], [101,101],
[102,102], [102,102],
[103,103], [103,103],
@ -149,26 +189,25 @@ trait SeriesArticle {
], ],
'arsse_marks' => [ 'arsse_marks' => [
'columns' => [ 'columns' => [
'owner' => "str", 'subscription' => "int",
'article' => "int", 'article' => "int",
'read' => "bool", 'read' => "bool",
'starred' => "bool", 'starred' => "bool",
'modified' => "datetime" 'modified' => "datetime"
], ],
'rows' => [ 'rows' => [
["john.doe@example.com", 1,1,1,'2000-01-01 00:00:00'], [1, 1,1,1,'2000-01-01 00:00:00'],
["john.doe@example.com", 19,1,0,'2000-01-01 00:00:00'], [5, 19,1,0,'2000-01-01 00:00:00'],
["john.doe@example.com", 20,0,1,'2010-01-01 00:00:00'], [5, 20,0,1,'2010-01-01 00:00:00'],
["jane.doe@example.com", 20,1,0,'2010-01-01 00:00:00'], [7, 20,1,0,'2010-01-01 00:00:00'],
["john.doe@example.org",102,1,0,'2000-01-02 02:00:00'], [8, 102,1,0,'2000-01-02 02:00:00'],
["john.doe@example.org",103,0,1,'2000-01-03 03:00:00'], [9, 103,0,1,'2000-01-03 03:00:00'],
["john.doe@example.org",104,1,1,'2000-01-04 04:00:00'], [9, 104,1,1,'2000-01-04 04:00:00'],
["john.doe@example.org",105,0,0,'2000-01-05 05:00:00'], [10,105,0,0,'2000-01-05 05:00:00'],
["john.doe@example.net", 19,0,0,'2017-01-01 00:00:00'], [11, 19,0,0,'2017-01-01 00:00:00'],
["john.doe@example.net", 20,1,0,'2017-01-01 00:00:00'], [11, 20,1,0,'2017-01-01 00:00:00'],
["john.doe@example.net", 3,0,1,'2017-01-01 00:00:00'], [12, 3,0,1,'2017-01-01 00:00:00'],
["john.doe@example.net", 4,1,1,'2017-01-01 00:00:00'], [12, 4,1,1,'2017-01-01 00:00:00'],
["john.doe@example.net", 12,0,1,'2017-01-01 00:00:00'], // user is no longer subscribed to this article's feed; the star should not be counted in articleStarredCount
] ]
], ],
]; ];
@ -266,14 +305,7 @@ trait SeriesArticle {
]; ];
function setUpSeries() { function setUpSeries() {
for($a = 0, $b = 1; $b <= 10; $b++) { $this->checkTables = ['arsse_marks' => ["subscription","article","read","starred","modified"],];
// add two generic articles per feed, and matching initial editions
$this->data['arsse_articles']['rows'][] = [++$a,$b,null,null,null,null,null,null,null,"","","","2000-01-01T00:00:00Z"];
$this->data['arsse_editions']['rows'][] = [$a,$a];
$this->data['arsse_articles']['rows'][] = [++$a,$b,null,null,null,null,null,null,null,"","","","2010-01-01T00:00:00Z"];
$this->data['arsse_editions']['rows'][] = [$a,$a];
}
$this->checkTables = ['arsse_marks' => ["owner","article","read","starred","modified"],];
$this->user = "john.doe@example.net"; $this->user = "john.doe@example.net";
} }
@ -369,10 +401,10 @@ trait SeriesArticle {
$state['arsse_marks']['rows'][8][4] = $now; $state['arsse_marks']['rows'][8][4] = $now;
$state['arsse_marks']['rows'][10][2] = 1; $state['arsse_marks']['rows'][10][2] = 1;
$state['arsse_marks']['rows'][10][4] = $now; $state['arsse_marks']['rows'][10][4] = $now;
$state['arsse_marks']['rows'][] = [$this->user,5,1,0,$now]; $state['arsse_marks']['rows'][] = [13,5,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,1,0,$now]; $state['arsse_marks']['rows'][] = [13,6,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,7,1,0,$now]; $state['arsse_marks']['rows'][] = [14,7,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,8,1,0,$now]; $state['arsse_marks']['rows'][] = [14,8,1,0,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -395,10 +427,10 @@ trait SeriesArticle {
$state['arsse_marks']['rows'][8][4] = $now; $state['arsse_marks']['rows'][8][4] = $now;
$state['arsse_marks']['rows'][9][3] = 1; $state['arsse_marks']['rows'][9][3] = 1;
$state['arsse_marks']['rows'][9][4] = $now; $state['arsse_marks']['rows'][9][4] = $now;
$state['arsse_marks']['rows'][] = [$this->user,5,0,1,$now]; $state['arsse_marks']['rows'][] = [13,5,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,0,1,$now]; $state['arsse_marks']['rows'][] = [13,6,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,7,0,1,$now]; $state['arsse_marks']['rows'][] = [14,7,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,8,0,1,$now]; $state['arsse_marks']['rows'][] = [14,8,0,1,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -427,10 +459,10 @@ trait SeriesArticle {
$state['arsse_marks']['rows'][9][4] = $now; $state['arsse_marks']['rows'][9][4] = $now;
$state['arsse_marks']['rows'][10][2] = 1; $state['arsse_marks']['rows'][10][2] = 1;
$state['arsse_marks']['rows'][10][4] = $now; $state['arsse_marks']['rows'][10][4] = $now;
$state['arsse_marks']['rows'][] = [$this->user,5,1,1,$now]; $state['arsse_marks']['rows'][] = [13,5,1,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,1,1,$now]; $state['arsse_marks']['rows'][] = [13,6,1,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,7,1,1,$now]; $state['arsse_marks']['rows'][] = [14,7,1,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,8,1,1,$now]; $state['arsse_marks']['rows'][] = [14,8,1,1,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -445,10 +477,10 @@ trait SeriesArticle {
$state['arsse_marks']['rows'][9][4] = $now; $state['arsse_marks']['rows'][9][4] = $now;
$state['arsse_marks']['rows'][11][2] = 0; $state['arsse_marks']['rows'][11][2] = 0;
$state['arsse_marks']['rows'][11][4] = $now; $state['arsse_marks']['rows'][11][4] = $now;
$state['arsse_marks']['rows'][] = [$this->user,5,0,1,$now]; $state['arsse_marks']['rows'][] = [13,5,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,0,1,$now]; $state['arsse_marks']['rows'][] = [13,6,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,7,0,1,$now]; $state['arsse_marks']['rows'][] = [14,7,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,8,0,1,$now]; $state['arsse_marks']['rows'][] = [14,8,0,1,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -463,10 +495,10 @@ trait SeriesArticle {
$state['arsse_marks']['rows'][10][4] = $now; $state['arsse_marks']['rows'][10][4] = $now;
$state['arsse_marks']['rows'][11][3] = 0; $state['arsse_marks']['rows'][11][3] = 0;
$state['arsse_marks']['rows'][11][4] = $now; $state['arsse_marks']['rows'][11][4] = $now;
$state['arsse_marks']['rows'][] = [$this->user,5,1,0,$now]; $state['arsse_marks']['rows'][] = [13,5,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,1,0,$now]; $state['arsse_marks']['rows'][] = [13,6,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,7,1,0,$now]; $state['arsse_marks']['rows'][] = [14,7,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,8,1,0,$now]; $state['arsse_marks']['rows'][] = [14,8,1,0,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -474,10 +506,10 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(7)); Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(7));
$now = Date::transform(time(), "sql"); $now = Date::transform(time(), "sql");
$state = $this->primeExpectations($this->data, $this->checkTables); $state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][] = [$this->user,5,1,0,$now]; $state['arsse_marks']['rows'][] = [13,5,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,1,0,$now]; $state['arsse_marks']['rows'][] = [13,6,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,7,1,0,$now]; $state['arsse_marks']['rows'][] = [14,7,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,8,1,0,$now]; $state['arsse_marks']['rows'][] = [14,8,1,0,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -485,8 +517,8 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(8)); Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(8));
$now = Date::transform(time(), "sql"); $now = Date::transform(time(), "sql");
$state = $this->primeExpectations($this->data, $this->checkTables); $state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][] = [$this->user,5,1,0,$now]; $state['arsse_marks']['rows'][] = [13,5,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,1,0,$now]; $state['arsse_marks']['rows'][] = [13,6,1,0,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -499,8 +531,8 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->subscription(13)); Arsse::$db->articleMark($this->user, ['read'=>true], (new Context)->subscription(13));
$now = Date::transform(time(), "sql"); $now = Date::transform(time(), "sql");
$state = $this->primeExpectations($this->data, $this->checkTables); $state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][] = [$this->user,5,1,0,$now]; $state['arsse_marks']['rows'][] = [13,5,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,1,0,$now]; $state['arsse_marks']['rows'][] = [13,6,1,0,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -524,7 +556,7 @@ trait SeriesArticle {
$state = $this->primeExpectations($this->data, $this->checkTables); $state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][9][3] = 1; $state['arsse_marks']['rows'][9][3] = 1;
$state['arsse_marks']['rows'][9][4] = $now; $state['arsse_marks']['rows'][9][4] = $now;
$state['arsse_marks']['rows'][] = [$this->user,7,0,1,$now]; $state['arsse_marks']['rows'][] = [14,7,0,1,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -537,7 +569,7 @@ trait SeriesArticle {
$state['arsse_marks']['rows'][9][4] = $now; $state['arsse_marks']['rows'][9][4] = $now;
$state['arsse_marks']['rows'][11][2] = 0; $state['arsse_marks']['rows'][11][2] = 0;
$state['arsse_marks']['rows'][11][4] = $now; $state['arsse_marks']['rows'][11][4] = $now;
$state['arsse_marks']['rows'][] = [$this->user,7,0,1,$now]; $state['arsse_marks']['rows'][] = [14,7,0,1,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -571,7 +603,7 @@ trait SeriesArticle {
$state = $this->primeExpectations($this->data, $this->checkTables); $state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][9][3] = 1; $state['arsse_marks']['rows'][9][3] = 1;
$state['arsse_marks']['rows'][9][4] = $now; $state['arsse_marks']['rows'][9][4] = $now;
$state['arsse_marks']['rows'][] = [$this->user,7,0,1,$now]; $state['arsse_marks']['rows'][] = [14,7,0,1,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -603,7 +635,7 @@ trait SeriesArticle {
$state['arsse_marks']['rows'][9][4] = $now; $state['arsse_marks']['rows'][9][4] = $now;
$state['arsse_marks']['rows'][11][2] = 0; $state['arsse_marks']['rows'][11][2] = 0;
$state['arsse_marks']['rows'][11][4] = $now; $state['arsse_marks']['rows'][11][4] = $now;
$state['arsse_marks']['rows'][] = [$this->user,7,0,1,$now]; $state['arsse_marks']['rows'][] = [14,7,0,1,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -669,10 +701,10 @@ trait SeriesArticle {
$state = $this->primeExpectations($this->data, $this->checkTables); $state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][8][3] = 1; $state['arsse_marks']['rows'][8][3] = 1;
$state['arsse_marks']['rows'][8][4] = $now; $state['arsse_marks']['rows'][8][4] = $now;
$state['arsse_marks']['rows'][] = [$this->user,5,0,1,$now]; $state['arsse_marks']['rows'][] = [13,5,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,0,1,$now]; $state['arsse_marks']['rows'][] = [13,6,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,7,0,1,$now]; $state['arsse_marks']['rows'][] = [14,7,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,8,0,1,$now]; $state['arsse_marks']['rows'][] = [14,8,0,1,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }
@ -691,8 +723,8 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->notModifiedSince('2000-01-01T00:00:00Z')); Arsse::$db->articleMark($this->user, ['starred'=>true], (new Context)->notModifiedSince('2000-01-01T00:00:00Z'));
$now = Date::transform(time(), "sql"); $now = Date::transform(time(), "sql");
$state = $this->primeExpectations($this->data, $this->checkTables); $state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][] = [$this->user,5,0,1,$now]; $state['arsse_marks']['rows'][] = [13,5,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,7,0,1,$now]; $state['arsse_marks']['rows'][] = [14,7,0,1,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
} }

View file

@ -75,18 +75,21 @@ trait SeriesFeed {
], ],
'arsse_subscriptions' => [ 'arsse_subscriptions' => [
'columns' => [ 'columns' => [
'id' => "int",
'owner' => "str", 'owner' => "str",
'feed' => "int", 'feed' => "int",
], ],
'rows' => [ 'rows' => [
// the first five feeds need at least one subscription so they are not involved in the cleanup test // the first five feeds need at least one subscription so they are not involved in the cleanup test
['john.doe@example.com',1], [1,'john.doe@example.com',1],
['john.doe@example.com',2], [2,'john.doe@example.com',2],
['john.doe@example.com',3], [3,'john.doe@example.com',3],
['john.doe@example.com',4], [4,'john.doe@example.com',4],
['john.doe@example.com',5], [5,'john.doe@example.com',5],
// Jane also needs a subscription to the first feed, for marks
[6,'jane.doe@example.com',1],
// one feed previously marked for deletion has a subscription again, and so should not be deleted // one feed previously marked for deletion has a subscription again, and so should not be deleted
['jane.doe@example.com',6], [7,'jane.doe@example.com',6],
] ]
], ],
'arsse_articles' => [ 'arsse_articles' => [
@ -131,22 +134,23 @@ trait SeriesFeed {
], ],
'arsse_marks' => [ 'arsse_marks' => [
'columns' => [ 'columns' => [
'id' => "int", 'article' => "int",
'article' => "int", 'subscription' => "int",
'owner' => "str", 'read' => "bool",
'read' => "bool", 'starred' => "bool",
'starred' => "bool", 'modified' => "datetime",
'modified' => "datetime",
], ],
'rows' => [ 'rows' => [
[1,1,"jane.doe@example.com",1,0,$past], // Jane's marks
[2,2,"jane.doe@example.com",1,0,$past], [1,6,1,0,$past],
[3,3,"jane.doe@example.com",1,1,$past], [2,6,1,0,$past],
[4,4,"jane.doe@example.com",1,0,$past], [3,6,1,1,$past],
[5,5,"jane.doe@example.com",1,1,$past], [4,6,1,0,$past],
[9, 1,"john.doe@example.com",1,0,$past], [5,6,1,1,$past],
[10,3,"john.doe@example.com",1,0,$past], // John's marks
[11,4,"john.doe@example.com",0,1,$past], [1,1,1,0,$past],
[3,1,1,0,$past],
[4,1,0,1,$past],
] ]
], ],
'arsse_enclosures' => [ 'arsse_enclosures' => [
@ -193,7 +197,7 @@ trait SeriesFeed {
$state = $this->primeExpectations($this->data, [ $state = $this->primeExpectations($this->data, [
'arsse_articles' => ["id", "feed","url","title","author","published","edited","content","guid","url_title_hash","url_content_hash","title_content_hash","modified"], 'arsse_articles' => ["id", "feed","url","title","author","published","edited","content","guid","url_title_hash","url_content_hash","title_content_hash","modified"],
'arsse_editions' => ["id","article","modified"], 'arsse_editions' => ["id","article","modified"],
'arsse_marks' => ["id","article","read","starred","modified"], 'arsse_marks' => ["subscription","article","read","starred","modified"],
]); ]);
$state['arsse_articles']['rows'][2] = [3,1,'http://example.com/3','Article title 3 (updated)','','2000-01-03 00:00:00','2000-01-03 00:00:00','<p>Article content 3</p>','31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92','6cc99be662ef3486fef35a890123f18d74c29a32d714802d743c5b4ef713315a','b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406','d5faccc13bf8267850a1e8e61f95950a0f34167df2c8c58011c0aaa6367026ac',$now]; $state['arsse_articles']['rows'][2] = [3,1,'http://example.com/3','Article title 3 (updated)','','2000-01-03 00:00:00','2000-01-03 00:00:00','<p>Article content 3</p>','31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92','6cc99be662ef3486fef35a890123f18d74c29a32d714802d743c5b4ef713315a','b278380e984cefe63f0e412b88ffc9cb0befdfa06fdc00bace1da99a8daff406','d5faccc13bf8267850a1e8e61f95950a0f34167df2c8c58011c0aaa6367026ac',$now];
$state['arsse_articles']['rows'][3] = [4,1,'http://example.com/4','Article title 4','','2000-01-04 00:00:00','2000-01-04 00:00:01','<p>Article content 4</p>','804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8','f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3','ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9',$now]; $state['arsse_articles']['rows'][3] = [4,1,'http://example.com/4','Article title 4','','2000-01-04 00:00:00','2000-01-04 00:00:01','<p>Article content 4</p>','804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180','f3615c7f16336d3ea242d35cf3fc17dbc4ee3afb78376bf49da2dd7a5a25dec8','f11c2b4046f207579aeb9c69a8c20ca5461cef49756ccfa5ba5e2344266da3b3','ab2da63276acce431250b18d3d49b988b226a99c7faadf275c90b751aee05be9',$now];
@ -203,9 +207,9 @@ trait SeriesFeed {
[7,3,$now], [7,3,$now],
[8,4,$now], [8,4,$now],
]); ]);
$state['arsse_marks']['rows'][2] = [3,3,0,1,$now]; $state['arsse_marks']['rows'][2] = [6,3,0,1,$now];
$state['arsse_marks']['rows'][3] = [4,4,0,0,$now]; $state['arsse_marks']['rows'][3] = [6,4,0,0,$now];
$state['arsse_marks']['rows'][6] = [10,3,0,0,$now]; $state['arsse_marks']['rows'][6] = [1,3,0,0,$now];
$this->compareExpectations($state); $this->compareExpectations($state);
// update a valid feed which previously had an error // update a valid feed which previously had an error
Arsse::$db->feedUpdate(2); Arsse::$db->feedUpdate(2);

View file

@ -85,24 +85,20 @@ trait SeriesSubscription {
], ],
'arsse_marks' => [ 'arsse_marks' => [
'columns' => [ 'columns' => [
'id' => "int", 'article' => "int",
'article' => "int", 'subscription' => "int",
'owner' => "str", 'read' => "bool",
'read' => "bool", 'starred' => "bool",
'starred' => "bool",
], ],
'rows' => [ 'rows' => [
[1,1,"jane.doe@example.com",1,0], [1,2,1,0],
[2,2,"jane.doe@example.com",1,0], [2,2,1,0],
[3,3,"jane.doe@example.com",1,0], [3,2,1,0],
[4,4,"jane.doe@example.com",1,0], [4,2,1,0],
[5,5,"jane.doe@example.com",1,0], [5,2,1,0],
[6,6,"jane.doe@example.com",1,0], [1,1,1,0],
[7,7,"jane.doe@example.com",1,0], [7,3,1,0],
[8,8,"jane.doe@example.com",1,0], [8,3,0,0],
[9, 1,"john.doe@example.com",1,0],
[10,7,"john.doe@example.com",1,0],
[11,8,"john.doe@example.com",0,0],
] ]
], ],
]; ];