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

Abandon the new marking method

It was less accurate and turned out to be more complex rather than less.
This commit is contained in:
J. King 2023-02-16 23:32:04 -05:00
parent 4d0ce01acb
commit 4b3cfba495
6 changed files with 166 additions and 170 deletions

View file

@ -1524,7 +1524,7 @@ class Database {
* If an empty column list is supplied, a count of articles matching the context is queried instead * If an empty column list is supplied, a count of articles matching the context is queried instead
* *
* @param string $user The user whose articles are to be queried * @param string $user The user whose articles are to be queried
* @param RootContext $context The search context * @param Context|UnionContext $context The search context
* @param array $cols The columns to request in the result set * @param array $cols The columns to request in the result set
*/ */
protected function articleQuery(string $user, RootContext $context, array $cols = ["id"]): Query { protected function articleQuery(string $user, RootContext $context, array $cols = ["id"]): Query {
@ -1643,7 +1643,8 @@ class Database {
return $q; return $q;
} }
protected function articleFilter(Context $context, QueryFilter $q = null) { /** Transforms a selection context for articles into a set of terms for an SQL "where" clause */
protected function articleFilter(Context $context, QueryFilter $q = null): QueryFilter {
$q = $q ?? new QueryFilter; $q = $q ?? new QueryFilter;
$colDefs = $this->articleColumns(); $colDefs = $this->articleColumns();
// handle the simple context options // handle the simple context options
@ -1919,11 +1920,10 @@ class Database {
* *
* @param string $user The user who owns the articles to be modified * @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 array $data An associative array of properties to modify. Anything not specified will remain unchanged
* @param RootContext $context The query context to match articles against * @param Context|UnionContext $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 * @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, RootContext $context = null, bool $updateTimestamp = true): int {
// normalize requested marks
$data = [ $data = [
'read' => $data['read'] ?? null, 'read' => $data['read'] ?? null,
'starred' => $data['starred'] ?? null, 'starred' => $data['starred'] ?? null,
@ -1931,94 +1931,102 @@ class Database {
'note' => $data['note'] ?? null, 'note' => $data['note'] ?? null,
]; ];
if (!isset($data['read']) && !isset($data['starred']) && !isset($data['hidden']) && !isset($data['note'])) { if (!isset($data['read']) && !isset($data['starred']) && !isset($data['hidden']) && !isset($data['note'])) {
// no changes were requested
return 0; return 0;
} }
// begin a transaction
$tr = $this->begin();
$context = $context ?? new Context; $context = $context ?? new Context;
if ($context instanceof UnionContext) { $tr = $this->begin();
$out = 0; $out = 0;
// if we were provided a union context, mark each context in series; if (isset($data['read']) && (isset($data['starred']) || isset($data['hidden']) || isset($data['note'])) && ($context->edition() || $context->editions())) {
// this is atomic (due to the transaction already begun), but may // if marking by edition both read and something else, do separate marks for starred, hidden, and note than for read
// result in multiple timestamps as well as an inaccurate output // marking as read is ignored if the edition is not the latest, but the same is not true of the other two marks
// integer as articles may be in multiple contexts
// TODO: The above quirks could be fixed by resolving the union
// context to a single list of article IDs noting which are
// valid read marks (if editions were selected in any of the child
// contexts); this functionality is not needed yet, however
foreach ($context as $c) {
$out += $this->articleMark($user, $data, $c, $updateTimestamp);
}
$tr->commit();
return $out;
}
// prepare the subquery which selects the articles to act on
$subq = $this->articleQuery($user, $context); $subq = $this->articleQuery($user, $context);
$subq->setWhere("(arsse_articles.note <> coalesce(?,arsse_articles.note) or arsse_articles.starred <> coalesce(?,arsse_articles.starred) or arsse_articles.read <> coalesce(?,arsse_articles.read) or arsse_articles.hidden <> coalesce(?,arsse_articles.hidden))", ["str", "bool", "bool", "bool"], [$data['note'], $data['starred'], $data['read'], $data['hidden']]); $subq->setWhere("arsse_articles.read <> coalesce(?,arsse_articles.read)", "bool", $data['read']);
// if we're marking as read/unread by edition, we have to use a different query so that we only mark read/unread if the edition is the latest for the article $q = new Query(
if (isset($data['read']) && ($context->edition() || $context->editions())) {
// set up the "SET" clause for the update
$setData = array_filter($data, function($v, $k) {
// filter out anyhing with a value of null (no change), as well as the "rea" key as it required special handling
return isset($v) && $k !== "read";
}, \ARRAY_FILTER_USE_BOTH);
[$set, $setTypes, $setValues] = $this->generateSet($setData, ['read' => "bool", 'starred' => "bool", 'hidden' => "bool", 'note' => "str"]);
$set = $set ? "$set, " : "";
$set .= "read = case when id in (select article from valid_read) then ? else \"read\" end";
$setTypes[] = "bool";
$setValues[] = $data['read'];
if ($updateTimestamp) {
$set .= ", marked = CURRENT_TIMESTAMP";
}
// prepare the rest of the query
[$inClause, $inTypes, $inValues] = $this->generateIn($context->editions ?: (array) $context->edition, "int");
$out = $this->db->prepare(
"WITH RECURSIVE "WITH RECURSIVE
target_articles as ( target_articles(article) as (
{$subq->getQuery()} {$subq->getQuery()}
),
valid_read as (
select selected_editions.article from (
select max(id) as edition, article from arsse_editions where id in ($inClause) group by article
) as selected_editions join (
SELECT max(id) as edition, article from arsse_editions group by article
) as latest_editions on selected_editions.edition = latest_editions.edition
) )
update arsse_articles update arsse_articles
set set
\"read\" = ?,
touched = 1
where
id in (select article from target_articles)",
[$subq->getTypes(), "bool"],
[$subq->getValues(), $data['read']]
);
$this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues());
// get the articles associated with the requested editions
if ($context->edition()) {
$context->article($this->articleValidateEdition($user, $context->edition)['article'])->edition(null);
} else {
$context->articles($this->editionArticle(...$context->editions))->editions(null);
}
// set starred, hidden, and/or note marks (unless all requested editions actually do not exist)
if ($context->article || $context->articles) {
$setData = array_filter($data, function($v) {
return isset($v);
});
[$set, $setTypes, $setValues] = $this->generateSet($setData, ['starred' => "bool", 'hidden' => "bool", 'note' => "str"]);
$subq = $this->articleQuery($user, $context);
$subq->setWhere("(arsse_articles.note <> coalesce(?,arsse_articles.note) or arsse_articles.starred <> coalesce(?,arsse_articles.starred) or arsse_articles.hidden <> coalesce(?,arsse_articles.hidden))", ["str", "bool", "bool"], [$data['note'], $data['starred'], $data['hidden']]);
$q = new Query(
"WITH RECURSIVE
target_articles(article) as (
{$subq->getQuery()}
)
update arsse_articles
set
touched = 1,
$set $set
where where
id in (select id from target_articles)", id in (select article from target_articles)",
$subq->getTypes(), $inTypes, $setTypes [$subq->getTypes(), $setTypes],
)->run( [$subq->getValues(), $setValues]
$subq->getValues(), $inValues, $setValues );
)->changes(); $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues());
}
// finally set the modification date for all touched marks and return the number of affected marks
if ($updateTimestamp) {
$out = $this->db->query("UPDATE arsse_articles set marked = CURRENT_TIMESTAMP, touched = 0 where touched = 1")->changes();
} else { } else {
// set up the "SET" clause for the update $out = $this->db->query("UPDATE arsse_articles set touched = 0 where touched = 1")->changes();
}
} else {
if (!isset($data['read']) && ($context->edition() || $context->editions())) {
// get the articles associated with the requested editions
if ($context->edition()) {
$context->article($this->articleValidateEdition($user, $context->edition)['article'])->edition(null);
} else {
$context->articles($this->editionArticle(...$context->editions))->editions(null);
}
if (!$context->article && !$context->articles) {
return 0;
}
}
$setData = array_filter($data, function($v) { $setData = array_filter($data, function($v) {
// filter out anyhing with a value of null (no change)
return isset($v); return isset($v);
}); });
[$set, $setTypes, $setValues] = $this->generateSet($setData, ['read' => "bool", 'starred' => "bool", 'hidden' => "bool", 'note' => "str"]); [$set, $setTypes, $setValues] = $this->generateSet($setData, ['read' => "bool", 'starred' => "bool", 'hidden' => "bool", 'note' => "str"]);
if ($updateTimestamp) { if ($updateTimestamp) {
$set .= ", marked = CURRENT_TIMESTAMP"; $set .= ", marked = CURRENT_TIMESTAMP";
} }
// prepare the rest of the query $subq = $this->articleQuery($user, $context);
$out = $this->db->prepare( $subq->setWhere("(arsse_articles.note <> coalesce(?,arsse_articles.note) or arsse_articles.starred <> coalesce(?,arsse_articles.starred) or arsse_articles.read <> coalesce(?,arsse_articles.read) or arsse_articles.hidden <> coalesce(?,arsse_articles.hidden))", ["str", "bool", "bool", "bool"], [$data['note'], $data['starred'], $data['read'], $data['hidden']]);
$q = new Query(
"WITH RECURSIVE "WITH RECURSIVE
target_articles as ( target_articles(article) as (
{$subq->getQuery()} {$subq->getQuery()}
) )
update arsse_articles update arsse_articles
set set
$set $set
where where
id in (select id from target_articles)", id in (select article from target_articles)",
$subq->getTypes(), $setTypes [$subq->getTypes(), $setTypes],
)->run( [$subq->getValues(), $setValues]
$subq->getValues(), $setValues );
)->changes(); $out = $this->db->prepare($q->getQuery(), $q->getTypes())->run($q->getValues())->changes();
} }
$tr->commit(); $tr->commit();
return $out; return $out;

View file

@ -38,6 +38,7 @@ alter table arsse_articles add column subscription bigint unsigned;
alter table arsse_articles add column "read" smallint not null default 0; alter table arsse_articles add column "read" smallint not null default 0;
alter table arsse_articles add column starred smallint not null default 0; alter table arsse_articles add column starred smallint not null default 0;
alter table arsse_articles add column hidden smallint not null default 0; alter table arsse_articles add column hidden smallint not null default 0;
alter table arsse_articles add column touched smallint not null default 0;
alter table arsse_articles add column marked datetime(0); alter table arsse_articles add column marked datetime(0);
alter table arsse_articles add column note longtext; alter table arsse_articles add column note longtext;

View file

@ -35,6 +35,7 @@ alter table arsse_articles add column subscription bigint references arsse_subsc
alter table arsse_articles add column read smallint not null default 0; alter table arsse_articles add column read smallint not null default 0;
alter table arsse_articles add column starred smallint not null default 0; alter table arsse_articles add column starred smallint not null default 0;
alter table arsse_articles add column hidden smallint not null default 0; alter table arsse_articles add column hidden smallint not null default 0;
alter table arsse_articles add column touched smallint not null default 0;
alter table arsse_articles add column marked timestamp(0) without time zone; alter table arsse_articles add column marked timestamp(0) without time zone;
alter table arsse_articles add column note text collate "und-x-icu" not null default ''; alter table arsse_articles add column note text collate "und-x-icu" not null default '';

View file

@ -48,6 +48,7 @@ create table arsse_articles_new(
url_title_hash text not null, -- hash of URL + title; used when checking for updates and for identification if there is no guid url_title_hash text not null, -- hash of URL + title; used when checking for updates and for identification if there is no guid
url_content_hash text not null, -- hash of URL + content + enclosure URL + enclosure content type; used when checking for updates and for identification if there is no guid url_content_hash text not null, -- hash of URL + content + enclosure URL + enclosure content type; used when checking for updates and for identification if there is no guid
title_content_hash text not null, -- hash of title + content + enclosure URL + enclosure content type; used when checking for updates and for identification if there is no guid title_content_hash text not null, -- hash of title + content + enclosure URL + enclosure content type; used when checking for updates and for identification if there is no guid
touched int not null default 0, -- field used internally while marking; should normally be left as 0
note text not null default '' -- Tiny Tiny RSS freeform user note note text not null default '' -- Tiny Tiny RSS freeform user note
); );
insert into arsse_articles_new insert into arsse_articles_new
@ -68,6 +69,7 @@ insert into arsse_articles_new
a.url_title_hash, a.url_title_hash,
a.url_content_hash, a.url_content_hash,
a.title_content_hash, a.title_content_hash,
0,
coalesce(m.note,'') coalesce(m.note,'')
from arsse_articles_map as i from arsse_articles_map as i
left join arsse_articles as a on a.id = i.article left join arsse_articles as a on a.id = i.article

View file

@ -515,11 +515,20 @@ trait SeriesArticle {
103 => 103, 103 => 103,
104 => 104, 104 => 104,
105 => 105, 105 => 105,
119 => 119,
120 => 120,
202 => 102, 202 => 102,
203 => 103, 203 => 103,
204 => 104, 204 => 104,
205 => 105, 205 => 105,
305 => 105, 305 => 105,
501 => 501,
502 => 502,
519 => 519,
520 => 520,
801 => 801,
802 => 802,
902 => 802,
1001 => 20, 1001 => 20,
]; ];
$act = Arsse::$db->editionArticle(...range(1, 1001)); $act = Arsse::$db->editionArticle(...range(1, 1001));
@ -580,9 +589,9 @@ trait SeriesArticle {
$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_articles']['rows'][20][1] = 0; $state['arsse_articles']['rows'][20][1] = 0;
$state['arsse_articles']['rows'][9][4] = $now; $state['arsse_articles']['rows'][20][4] = $now;
$state['arsse_articles']['rows'][22][1] = 0; $state['arsse_articles']['rows'][22][1] = 0;
$state['arsse_articles']['rows'][11][4] = $now; $state['arsse_articles']['rows'][22][4] = $now;
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -590,14 +599,12 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['read' => true]); Arsse::$db->articleMark($this->user, ['read' => true]);
$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_articles']['rows'][8][2] = 1; $state['arsse_articles']['rows'][19] = [119,1,0,0,$now,"ook"];
$state['arsse_articles']['rows'][8][4] = $now; $state['arsse_articles']['rows'][21] = [203,1,1,0,$now,"ack"];
$state['arsse_articles']['rows'][10][2] = 1; $state['arsse_articles']['rows'][23] = [205,1,0,0,$now,""];
$state['arsse_articles']['rows'][10][4] = $now; $state['arsse_articles']['rows'][24] = [206,1,0,0,$now,""];
$state['arsse_articles']['rows'][] = [13,5,1,0,$now,'',0]; $state['arsse_articles']['rows'][25] = [207,1,0,0,$now,""];
$state['arsse_articles']['rows'][] = [13,6,1,0,$now,'',0]; $state['arsse_articles']['rows'][26] = [208,1,0,0,$now,""];
$state['arsse_articles']['rows'][] = [14,7,1,0,$now,'',0];
$state['arsse_articles']['rows'][] = [14,8,1,0,$now,'',0];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -605,10 +612,10 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['starred' => false]); Arsse::$db->articleMark($this->user, ['starred' => false]);
$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_articles']['rows'][10][3] = 0; $state['arsse_articles']['rows'][21][2] = 0;
$state['arsse_articles']['rows'][10][4] = $now; $state['arsse_articles']['rows'][21][4] = $now;
$state['arsse_articles']['rows'][11][3] = 0; $state['arsse_articles']['rows'][22][2] = 0;
$state['arsse_articles']['rows'][11][4] = $now; $state['arsse_articles']['rows'][22][4] = $now;
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -616,14 +623,12 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['starred' => true]); Arsse::$db->articleMark($this->user, ['starred' => true]);
$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_articles']['rows'][8][3] = 1; $state['arsse_articles']['rows'][19] = [119,0,1,0,$now,"ook"];
$state['arsse_articles']['rows'][8][4] = $now; $state['arsse_articles']['rows'][20] = [120,1,1,0,$now,"eek"];
$state['arsse_articles']['rows'][9][3] = 1; $state['arsse_articles']['rows'][23] = [205,0,1,0,$now,""];
$state['arsse_articles']['rows'][9][4] = $now; $state['arsse_articles']['rows'][24] = [206,0,1,0,$now,""];
$state['arsse_articles']['rows'][] = [13,5,0,1,$now,'',0]; $state['arsse_articles']['rows'][25] = [207,0,1,0,$now,""];
$state['arsse_articles']['rows'][] = [13,6,0,1,$now,'',0]; $state['arsse_articles']['rows'][26] = [208,0,1,0,$now,""];
$state['arsse_articles']['rows'][] = [14,7,0,1,$now,'',0];
$state['arsse_articles']['rows'][] = [14,8,0,1,$now,'',0];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -631,13 +636,9 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['read' => false,'starred' => false]); Arsse::$db->articleMark($this->user, ['read' => false,'starred' => false]);
$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_articles']['rows'][9][2] = 0; $state['arsse_articles']['rows'][20] = [120,0,0,0,$now,"eek"];
$state['arsse_articles']['rows'][9][4] = $now; $state['arsse_articles']['rows'][21] = [203,0,0,0,$now,"ack"];
$state['arsse_articles']['rows'][10][3] = 0; $state['arsse_articles']['rows'][22] = [204,0,0,0,$now,"ach"];
$state['arsse_articles']['rows'][10][4] = $now;
$state['arsse_articles']['rows'][11][2] = 0;
$state['arsse_articles']['rows'][11][3] = 0;
$state['arsse_articles']['rows'][11][4] = $now;
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -645,17 +646,13 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['read' => true,'starred' => true]); Arsse::$db->articleMark($this->user, ['read' => true,'starred' => true]);
$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_articles']['rows'][8][2] = 1; $state['arsse_articles']['rows'][19] = [119,1,1,0,$now,"ook"];
$state['arsse_articles']['rows'][8][3] = 1; $state['arsse_articles']['rows'][20] = [120,1,1,0,$now,"eek"];
$state['arsse_articles']['rows'][8][4] = $now; $state['arsse_articles']['rows'][21] = [203,1,1,0,$now,"ack"];
$state['arsse_articles']['rows'][9][3] = 1; $state['arsse_articles']['rows'][23] = [205,1,1,0,$now,""];
$state['arsse_articles']['rows'][9][4] = $now; $state['arsse_articles']['rows'][24] = [206,1,1,0,$now,""];
$state['arsse_articles']['rows'][10][2] = 1; $state['arsse_articles']['rows'][25] = [207,1,1,0,$now,""];
$state['arsse_articles']['rows'][10][4] = $now; $state['arsse_articles']['rows'][26] = [208,1,1,0,$now,""];
$state['arsse_articles']['rows'][] = [13,5,1,1,$now,'',0];
$state['arsse_articles']['rows'][] = [13,6,1,1,$now,'',0];
$state['arsse_articles']['rows'][] = [14,7,1,1,$now,'',0];
$state['arsse_articles']['rows'][] = [14,8,1,1,$now,'',0];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -663,17 +660,13 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true]); Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true]);
$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_articles']['rows'][8][3] = 1; $state['arsse_articles']['rows'][19] = [119,0,1,0,$now,"ook"];
$state['arsse_articles']['rows'][8][4] = $now; $state['arsse_articles']['rows'][20] = [120,0,1,0,$now,"eek"];
$state['arsse_articles']['rows'][9][2] = 0; $state['arsse_articles']['rows'][22] = [204,0,1,0,$now,"ach"];
$state['arsse_articles']['rows'][9][3] = 1; $state['arsse_articles']['rows'][23] = [205,0,1,0,$now,""];
$state['arsse_articles']['rows'][9][4] = $now; $state['arsse_articles']['rows'][24] = [206,0,1,0,$now,""];
$state['arsse_articles']['rows'][11][2] = 0; $state['arsse_articles']['rows'][25] = [207,0,1,0,$now,""];
$state['arsse_articles']['rows'][11][4] = $now; $state['arsse_articles']['rows'][26] = [208,0,1,0,$now,""];
$state['arsse_articles']['rows'][] = [13,5,0,1,$now,'',0];
$state['arsse_articles']['rows'][] = [13,6,0,1,$now,'',0];
$state['arsse_articles']['rows'][] = [14,7,0,1,$now,'',0];
$state['arsse_articles']['rows'][] = [14,8,0,1,$now,'',0];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -681,17 +674,13 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['read' => true,'starred' => false]); Arsse::$db->articleMark($this->user, ['read' => true,'starred' => false]);
$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_articles']['rows'][8][2] = 1; $state['arsse_articles']['rows'][19] = [119,1,0,0,$now,"ook"];
$state['arsse_articles']['rows'][8][4] = $now; $state['arsse_articles']['rows'][21] = [203,1,0,0,$now,"ack"];
$state['arsse_articles']['rows'][10][2] = 1; $state['arsse_articles']['rows'][22] = [204,1,0,0,$now,"ach"];
$state['arsse_articles']['rows'][10][3] = 0; $state['arsse_articles']['rows'][23] = [205,1,0,0,$now,""];
$state['arsse_articles']['rows'][10][4] = $now; $state['arsse_articles']['rows'][24] = [206,1,0,0,$now,""];
$state['arsse_articles']['rows'][11][3] = 0; $state['arsse_articles']['rows'][25] = [207,1,0,0,$now,""];
$state['arsse_articles']['rows'][11][4] = $now; $state['arsse_articles']['rows'][26] = [208,1,0,0,$now,""];
$state['arsse_articles']['rows'][] = [13,5,1,0,$now,'',0];
$state['arsse_articles']['rows'][] = [13,6,1,0,$now,'',0];
$state['arsse_articles']['rows'][] = [14,7,1,0,$now,'',0];
$state['arsse_articles']['rows'][] = [14,8,1,0,$now,'',0];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -699,18 +688,14 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['note' => "New note"]); Arsse::$db->articleMark($this->user, ['note' => "New note"]);
$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_articles']['rows'][8][5] = "New note"; $state['arsse_articles']['rows'][19] = [119,0,0,0,$now,"New note"];
$state['arsse_articles']['rows'][8][4] = $now; $state['arsse_articles']['rows'][20] = [120,1,0,0,$now,"New note"];
$state['arsse_articles']['rows'][9][5] = "New note"; $state['arsse_articles']['rows'][21] = [203,0,1,0,$now,"New note"];
$state['arsse_articles']['rows'][9][4] = $now; $state['arsse_articles']['rows'][22] = [204,1,1,0,$now,"New note"];
$state['arsse_articles']['rows'][10][5] = "New note"; $state['arsse_articles']['rows'][23] = [205,0,0,0,$now,"New note"];
$state['arsse_articles']['rows'][10][4] = $now; $state['arsse_articles']['rows'][24] = [206,0,0,0,$now,"New note"];
$state['arsse_articles']['rows'][11][5] = "New note"; $state['arsse_articles']['rows'][25] = [207,0,0,0,$now,"New note"];
$state['arsse_articles']['rows'][11][4] = $now; $state['arsse_articles']['rows'][26] = [208,0,0,0,$now,"New note"];
$state['arsse_articles']['rows'][] = [13,5,0,0,$now,'New note',0];
$state['arsse_articles']['rows'][] = [13,6,0,0,$now,'New note',0];
$state['arsse_articles']['rows'][] = [14,7,0,0,$now,'New note',0];
$state['arsse_articles']['rows'][] = [14,8,0,0,$now,'New note',0];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -718,10 +703,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_articles']['rows'][] = [13,5,1,0,$now,'',0]; $state['arsse_articles']['rows'][23] = [205,1,0,0,$now,""];
$state['arsse_articles']['rows'][] = [13,6,1,0,$now,'',0]; $state['arsse_articles']['rows'][24] = [206,1,0,0,$now,""];
$state['arsse_articles']['rows'][] = [14,7,1,0,$now,'',0]; $state['arsse_articles']['rows'][25] = [207,1,0,0,$now,""];
$state['arsse_articles']['rows'][] = [14,8,1,0,$now,'',0]; $state['arsse_articles']['rows'][26] = [208,1,0,0,$now,""];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -729,8 +714,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_articles']['rows'][] = [13,5,1,0,$now,'',0]; $state['arsse_articles']['rows'][23] = [205,1,0,0,$now,""];
$state['arsse_articles']['rows'][] = [13,6,1,0,$now,'',0]; $state['arsse_articles']['rows'][24] = [206,1,0,0,$now,""];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -743,8 +728,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_articles']['rows'][] = [13,5,1,0,$now,'',0]; $state['arsse_articles']['rows'][23] = [205,1,0,0,$now,""];
$state['arsse_articles']['rows'][] = [13,6,1,0,$now,'',0]; $state['arsse_articles']['rows'][24] = [206,1,0,0,$now,""];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -757,18 +742,17 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->article(120)); Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->article(120));
$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_articles']['rows'][20][3] = 1; $state['arsse_articles']['rows'][20][2] = 1;
$state['arsse_articles']['rows'][20][4] = $now; $state['arsse_articles']['rows'][20][4] = $now;
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
public function testMarkMultipleArticles(): void { public function testMarkMultipleArticles(): void {
Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->articles([2,4,7,20])); Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->articles([202,204,207,120]));
$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_articles']['rows'][9][3] = 1; $state['arsse_articles']['rows'][20] = [120,1,1,0,$now,"eek"];
$state['arsse_articles']['rows'][9][4] = $now; $state['arsse_articles']['rows'][25] = [207,0,1,0,$now,""];
$state['arsse_articles']['rows'][] = [14,7,0,1,$now,'',0];
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -787,7 +771,7 @@ trait SeriesArticle {
public function testMarkTooManyMultipleArticles(): void { public function testMarkTooManyMultipleArticles(): void {
$setSize = (new \ReflectionClassConstant(Database::class, "LIMIT_SET_SIZE"))->getValue(); $setSize = (new \ReflectionClassConstant(Database::class, "LIMIT_SET_SIZE"))->getValue();
$this->assertSame(7, Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true], (new Context)->articles(range(1, $setSize * 3)))); $this->assertSame(7, Arsse::$db->articleMark($this->user, ['read' => false,'starred' => true], (new Context)->articles(range(119, $setSize * 3))));
} }
public function testMarkAMissingArticle(): void { public function testMarkAMissingArticle(): void {
@ -799,8 +783,8 @@ trait SeriesArticle {
Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->edition(1101)); Arsse::$db->articleMark($this->user, ['starred' => true], (new Context)->edition(1101));
$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_articles']['rows'][9][3] = 1; $state['arsse_articles']['rows'][20][2] = 1;
$state['arsse_articles']['rows'][9][4] = $now; $state['arsse_articles']['rows'][20][4] = $now;
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }
@ -1097,8 +1081,8 @@ trait SeriesArticle {
Arsse::$db->articleMark("jane.doe@example.com", ['hidden' => true], (new Context)->edition(520)); Arsse::$db->articleMark("jane.doe@example.com", ['hidden' => true], (new Context)->edition(520));
$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_articles']['rows'][3][6] = 1; $state['arsse_articles']['rows'][13][3] = 1;
$state['arsse_articles']['rows'][3][4] = $now; $state['arsse_articles']['rows'][13][4] = $now;
$this->compareExpectations(static::$drv, $state); $this->compareExpectations(static::$drv, $state);
} }

View file

@ -295,14 +295,14 @@ QUERY_TEXT
] ]
], ],
'arsse_articles' => [ 'arsse_articles' => [
'columns' => ["id", "subscription", "read", "starred", "hidden", "published", "edited", "modified", "marked", "url", "title", "author", "guid", "url_title_hash", "url_content_hash", "title_content_hash", "note"], 'columns' => ["id", "subscription", "read", "starred", "hidden", "touched", "published", "edited", "modified", "marked", "url", "title", "author", "guid", "url_title_hash", "url_content_hash", "title_content_hash", "note"],
'rows' => [ 'rows' => [
[1, 1, 1, 1, 0, "2001-11-08 22:07:55", "2002-11-08 07:51:12", "2001-11-08 23:44:56", "2002-11-08 00:37:22", "https://example.com/1", "Article 1", "John Doe", "GUID1", "UTHASH1", "UCHASH1", "TCHASH1", "Note 1"], [1, 1, 1, 1, 0, 0, "2001-11-08 22:07:55", "2002-11-08 07:51:12", "2001-11-08 23:44:56", "2002-11-08 00:37:22", "https://example.com/1", "Article 1", "John Doe", "GUID1", "UTHASH1", "UCHASH1", "TCHASH1", "Note 1"],
[2, 1, 0, 0, 0, "2001-11-09 22:07:55", "2002-11-09 07:51:12", "2001-11-09 23:44:56", null, "https://example.com/2", "Article 2", "Jane Doe", "GUID2", "UTHASH2", "UCHASH2", "TCHASH2", ""], [2, 1, 0, 0, 0, 0, "2001-11-09 22:07:55", "2002-11-09 07:51:12", "2001-11-09 23:44:56", null, "https://example.com/2", "Article 2", "Jane Doe", "GUID2", "UTHASH2", "UCHASH2", "TCHASH2", ""],
[7, 4, 1, 0, 0, "2001-11-12 22:07:55", "2002-11-12 07:51:12", "2001-11-12 23:44:56", "2002-11-12 00:37:22", "https://example.net/1", "Article 5", "Adam Doe", "GUID5", "UTHASH5", "UCHASH5", "TCHASH5", "Note 5"], [7, 4, 1, 0, 0, 0, "2001-11-12 22:07:55", "2002-11-12 07:51:12", "2001-11-12 23:44:56", "2002-11-12 00:37:22", "https://example.net/1", "Article 5", "Adam Doe", "GUID5", "UTHASH5", "UCHASH5", "TCHASH5", "Note 5"],
[8, 6, 0, 1, 0, "2001-11-12 22:07:55", "2002-11-12 07:51:12", "2001-11-12 23:44:56", "2002-12-12 00:37:22", "https://example.net/1", "Article 5", "Adam Doe", "GUID5", "UTHASH5", "UCHASH5", "TCHASH5", ""], [8, 6, 0, 1, 0, 0, "2001-11-12 22:07:55", "2002-11-12 07:51:12", "2001-11-12 23:44:56", "2002-12-12 00:37:22", "https://example.net/1", "Article 5", "Adam Doe", "GUID5", "UTHASH5", "UCHASH5", "TCHASH5", ""],
[9, 4, 0, 0, 0, "2001-11-13 22:07:55", "2002-11-13 07:51:12", "2001-11-13 23:44:56", null, "https://example.net/2", "Article 6", "Evie Doe", "GUID6", "UTHASH6", "UCHASH6", "TCHASH6", ""], [9, 4, 0, 0, 0, 0, "2001-11-13 22:07:55", "2002-11-13 07:51:12", "2001-11-13 23:44:56", null, "https://example.net/2", "Article 6", "Evie Doe", "GUID6", "UTHASH6", "UCHASH6", "TCHASH6", ""],
[10, 6, 0, 0, 1, "2001-11-13 22:07:55", "2002-11-13 07:51:12", "2001-11-13 23:44:56", "2002-12-13 00:37:22", "https://example.net/2", "Article 6", "Evie Doe", "GUID6", "UTHASH6", "UCHASH6", "TCHASH6", "Note 6"], [10, 6, 0, 0, 1, 0, "2001-11-13 22:07:55", "2002-11-13 07:51:12", "2001-11-13 23:44:56", "2002-12-13 00:37:22", "https://example.net/2", "Article 6", "Evie Doe", "GUID6", "UTHASH6", "UCHASH6", "TCHASH6", "Note 6"],
] ]
], ],
'arsse_article_contents' => [ 'arsse_article_contents' => [