Browse Source

Last of marking context tests

microsub
J. King 7 years ago
parent
commit
d78318bed7
  1. 24
      lib/Database.php
  2. 7
      lib/Misc/DateFormatter.php
  3. 169
      tests/lib/Database/SeriesArticle.php

24
lib/Database.php

@ -622,12 +622,12 @@ class Database {
arsse_articles.id as id,
arsse_articles.url as url,
title,author,content,guid,
DATEFORMAT(?, published) as published,
DATEFORMAT(?, edited) as edited,
DATEFORMAT(?, published) as published_date,
DATEFORMAT(?, edited) as edited_date,
DATEFORMAT(?, max(
modified,
coalesce((select modified from arsse_marks join user on user is owner where article is arsse_articles.id),'')
)) as modified,
)) 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,
(select count(*) from arsse_marks join user on user is owner where article is arsse_articles.id and starred is 1) as starred,
(select max(id) from arsse_editions where article is arsse_articles.id) as edition,
@ -665,8 +665,8 @@ class Database {
if($context->oldestEdition()) $q->setWhere("edition >= ?", "int", $context->oldestEdition);
if($context->latestEdition()) $q->setWhere("edition <= ?", "int", $context->latestEdition);
// filter based on lastmod time
if($context->modifiedSince()) $q->setWhere("modified >= ?", "datetime", $context->modifiedSince);
if($context->notModifiedSince()) $q->setWhere("modified <= ?", "datetime", $context->notModifiedSince);
if($context->modifiedSince()) $q->setWhere("modified_date >= ?", "datetime", $context->modifiedSince);
if($context->notModifiedSince()) $q->setWhere("modified_date <= ?", "datetime", $context->notModifiedSince);
// filter for un/read and un/starred status if specified
if($context->unread()) $q->setWhere("unread is ?", "bool", $context->unread);
if($context->starred()) $q->setWhere("starred is ?", "bool", $context->starred);
@ -707,8 +707,8 @@ class Database {
if($context->edition()) {
// make sure the edition exists
$edition = $this->articleValidateEdition($user, $context->edition);
// if the edition is not the latest, make no marks and return
if(!$edition['current']) return false;
// if the edition is not the latest, do not mark the read flag
if(!$edition['current']) $values[0] = null;
} else if($context->article()) {
// otherwise if an article context is specified, make sure it's valid
$this->articleValidateId($user, $context->article);
@ -722,7 +722,7 @@ class Database {
(select max(id) from arsse_editions where article is arsse_articles.id) as edition,
max(arsse_articles.modified,
coalesce((select modified from arsse_marks join user on user is owner where article is arsse_articles.id),'')
) as modified,
) as modified_date,
(
not exists(select id from arsse_marks join user on user is owner where article is arsse_articles.id)
and exists(select * from target_values where read is 1 or starred is 1)
@ -744,8 +744,10 @@ class Database {
// common table expression with the values to set
$q->setCTE("target_values(read,starred) as (select ?,?)", ["bool","bool"], $values);
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);
} else if($context->subscription()) {
// if a subscription is specified, make sure it exists
@ -767,8 +769,8 @@ class Database {
if($context->oldestEdition()) $q->setWhere("edition >= ?", "int", $context->oldestEdition);
if($context->latestEdition()) $q->setWhere("edition <= ?", "int", $context->latestEdition);
// filter based on lastmod time
if($context->modifiedSince()) $q->setWhere("modified >= ?", "datetime", $context->modifiedSince);
if($context->notModifiedSince()) $q->setWhere("modified <= ?", "datetime", $context->notModifiedSince);
if($context->modifiedSince()) $q->setWhere("modified_date >= ?", "datetime", $context->modifiedSince);
if($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
$q->pushCTE(
"target_articles(id,edition,modified,to_insert,to_update)", // CTE table specification
@ -799,7 +801,7 @@ class Database {
return $out;
}
public function articleValidateEdition(string $user, int $id): array {
protected function articleValidateEdition(string $user, int $id): array {
$out = $this->db->prepare(
"SELECT
arsse_editions.id as edition,

7
lib/Misc/DateFormatter.php

@ -32,8 +32,11 @@ trait DateFormatter {
} else if($date===null) {
return null;
} else if(is_string($date)) {
$time = strtotime($date);
if($time===false) return null;
try {
$time = (new \DateTime($date, new \DateTimeZone("UTC")))->getTimestamp();
} catch(\Throwable $e) {
return null;
}
} else if (is_bool($date)) {
return null;
} else {

169
tests/lib/Database/SeriesArticle.php

@ -178,9 +178,9 @@ trait SeriesArticle {
'author' => '',
'content' => '<p>Article content 1</p>',
'guid' => 'e433653cef2e572eee4215fa299a4a5af9137b2cefd6283c85bd69a32915beda',
'published' => 946684800,
'edited' => 946684801,
'modified' => 946688400,
'published_date' => 946684800,
'edited_date' => 946684801,
'modified_date' => 946688400,
'unread' => 1,
'starred' => 0,
'edition' => 101,
@ -196,9 +196,9 @@ trait SeriesArticle {
'author' => '',
'content' => '<p>Article content 2</p>',
'guid' => '5be8a5a46ecd52ed132191c8d27fb1af6b3d4edc00234c5d9f8f0e10562ed3b7',
'published' => 946771200,
'edited' => 946771202,
'modified' => 946778400,
'published_date' => 946771200,
'edited_date' => 946771202,
'modified_date' => 946778400,
'unread' => 0,
'starred' => 0,
'edition' => 202,
@ -214,9 +214,9 @@ trait SeriesArticle {
'author' => '',
'content' => '<p>Article content 3</p>',
'guid' => '31a6594500a48b59fcc8a075ce82b946c9c3c782460d088bd7b8ef3ede97ad92',
'published' => 946857600,
'edited' => 946857603,
'modified' => 946868400,
'published_date' => 946857600,
'edited_date' => 946857603,
'modified_date' => 946868400,
'unread' => 1,
'starred' => 1,
'edition' => 203,
@ -232,9 +232,9 @@ trait SeriesArticle {
'author' => '',
'content' => '<p>Article content 4</p>',
'guid' => '804e517d623390e71497982c77cf6823180342ebcd2e7d5e32da1e55b09dd180',
'published' => 946944000,
'edited' => 946944004,
'modified' => 946958400,
'published_date' => 946944000,
'edited_date' => 946944004,
'modified_date' => 946958400,
'unread' => 0,
'starred' => 1,
'edition' => 204,
@ -250,9 +250,9 @@ trait SeriesArticle {
'author' => '',
'content' => '<p>Article content 5</p>',
'guid' => 'db3e736c2c492f5def5c5da33ddcbea1824040e9ced2142069276b0a6e291a41',
'published' => 947030400,
'edited' => 947030405,
'modified' => 947048400,
'published_date' => 947030400,
'edited_date' => 947030405,
'modified_date' => 947048400,
'unread' => 1,
'starred' => 0,
'edition' => 305,
@ -271,9 +271,17 @@ trait SeriesArticle {
$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";
}
protected function compareIds(array $exp, Context $c) {
$ids = array_column($ids = Data::$db->articleList($this->user, $c)->getAll(), "id");
sort($ids);
sort($exp);
$this->assertEquals($exp, $ids);
}
function testListArticlesCheckingContext() {
$this->user = "john.doe@example.com";
// get all items for user
@ -328,9 +336,7 @@ trait SeriesArticle {
function testMarkAllArticlesUnread() {
Data::$db->articleMark($this->user, ['read'=>false]);
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][9][2] = 0;
$state['arsse_marks']['rows'][9][4] = $now;
$state['arsse_marks']['rows'][11][2] = 0;
@ -341,9 +347,7 @@ trait SeriesArticle {
function testMarkAllArticlesRead() {
Data::$db->articleMark($this->user, ['read'=>true]);
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][8][2] = 1;
$state['arsse_marks']['rows'][8][4] = $now;
$state['arsse_marks']['rows'][10][2] = 1;
@ -358,9 +362,7 @@ trait SeriesArticle {
function testMarkAllArticlesUnstarred() {
Data::$db->articleMark($this->user, ['starred'=>false]);
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][10][3] = 0;
$state['arsse_marks']['rows'][10][4] = $now;
$state['arsse_marks']['rows'][11][3] = 0;
@ -371,9 +373,7 @@ trait SeriesArticle {
function testMarkAllArticlesStarred() {
Data::$db->articleMark($this->user, ['starred'=>true]);
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][8][3] = 1;
$state['arsse_marks']['rows'][8][4] = $now;
$state['arsse_marks']['rows'][9][3] = 1;
@ -388,9 +388,7 @@ trait SeriesArticle {
function testMarkAllArticlesUnreadAndUnstarred() {
Data::$db->articleMark($this->user, ['read'=>false,'starred'=>false]);
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][9][2] = 0;
$state['arsse_marks']['rows'][9][4] = $now;
$state['arsse_marks']['rows'][10][3] = 0;
@ -404,9 +402,7 @@ trait SeriesArticle {
function testMarkAllArticlesReadAndStarred() {
Data::$db->articleMark($this->user, ['read'=>true,'starred'=>true]);
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][8][2] = 1;
$state['arsse_marks']['rows'][8][3] = 1;
$state['arsse_marks']['rows'][8][4] = $now;
@ -424,9 +420,7 @@ trait SeriesArticle {
function testMarkAllArticlesUnreadAndStarred() {
Data::$db->articleMark($this->user, ['read'=>false,'starred'=>true]);
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][8][3] = 1;
$state['arsse_marks']['rows'][8][4] = $now;
$state['arsse_marks']['rows'][9][2] = 0;
@ -444,9 +438,7 @@ trait SeriesArticle {
function testMarkAllArticlesReadAndUnstarred() {
Data::$db->articleMark($this->user, ['read'=>true,'starred'=>false]);
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][8][2] = 1;
$state['arsse_marks']['rows'][8][4] = $now;
$state['arsse_marks']['rows'][10][2] = 1;
@ -464,9 +456,7 @@ trait SeriesArticle {
function testMarkATreeFolder() {
Data::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(7));
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][] = [$this->user,5,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,7,1,0,$now];
@ -477,9 +467,7 @@ trait SeriesArticle {
function testMarkALeafFolder() {
Data::$db->articleMark($this->user, ['read'=>true], (new Context)->folder(8));
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][] = [$this->user,5,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,1,0,$now];
$this->compareExpectations($state);
@ -493,9 +481,7 @@ trait SeriesArticle {
function testMarkASubscription() {
Data::$db->articleMark($this->user, ['read'=>true], (new Context)->subscription(13));
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][] = [$this->user,5,1,0,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,1,0,$now];
$this->compareExpectations($state);
@ -509,9 +495,7 @@ trait SeriesArticle {
function testMarkAnArticle() {
Data::$db->articleMark($this->user, ['starred'=>true], (new Context)->article(20));
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][9][3] = 1;
$state['arsse_marks']['rows'][9][4] = $now;
$this->compareExpectations($state);
@ -525,19 +509,39 @@ trait SeriesArticle {
function testMarkAnEdition() {
Data::$db->articleMark($this->user, ['starred'=>true], (new Context)->edition(1001));
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][9][3] = 1;
$state['arsse_marks']['rows'][9][4] = $now;
$this->compareExpectations($state);
}
function testMarkAStaleEdition() {
Data::$db->articleMark($this->user, ['starred'=>true], (new Context)->edition(20)); // no changes occur
$state = $this->primeExpectations($this->data, [
'arsse_marks' => ["owner","article","read","starred","modified"],
]);
function testMarkAStaleEditionUnread() {
Data::$db->articleMark($this->user, ['read'=>false], (new Context)->edition(20)); // no changes occur
$state = $this->primeExpectations($this->data, $this->checkTables);
$this->compareExpectations($state);
}
function testMarkAStaleEditionStarred() {
Data::$db->articleMark($this->user, ['starred'=>true], (new Context)->edition(20));
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][9][3] = 1;
$state['arsse_marks']['rows'][9][4] = $now;
$this->compareExpectations($state);
}
function testMarkAStaleEditionUnreadAndStarred() {
Data::$db->articleMark($this->user, ['read'=>false,'starred'=>true], (new Context)->edition(20)); // only starred is changed
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][9][3] = 1;
$state['arsse_marks']['rows'][9][4] = $now;
$this->compareExpectations($state);
}
function testMarkAStaleEditionUnreadAndUnstarred() {
Data::$db->articleMark($this->user, ['read'=>false,'starred'=>false], (new Context)->edition(20)); // no changes occur
$state = $this->primeExpectations($this->data, $this->checkTables);
$this->compareExpectations($state);
}
@ -546,10 +550,47 @@ trait SeriesArticle {
Data::$db->articleMark($this->user, ['starred'=>true], (new Context)->edition(2));
}
protected function compareIds(array $exp, Context $c) {
$ids = array_column($ids = Data::$db->articleList($this->user, $c)->getAll(), "id");
sort($ids);
sort($exp);
$this->assertEquals($exp, $ids);
function testMarkByOldestEdition() {
Data::$db->articleMark($this->user, ['starred'=>true], (new Context)->oldestEdition(19));
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][8][3] = 1;
$state['arsse_marks']['rows'][8][4] = $now;
$state['arsse_marks']['rows'][9][3] = 1;
$state['arsse_marks']['rows'][9][4] = $now;
$this->compareExpectations($state);
}
function testMarkByLatestEdition() {
Data::$db->articleMark($this->user, ['starred'=>true], (new Context)->latestEdition(20));
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][8][3] = 1;
$state['arsse_marks']['rows'][8][4] = $now;
$state['arsse_marks']['rows'][] = [$this->user,5,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,6,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,7,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,8,0,1,$now];
$this->compareExpectations($state);
}
function testMarkByLastModified() {
Data::$db->articleMark($this->user, ['starred'=>true], (new Context)->modifiedSince('2017-01-01T00:00:00Z'));
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][8][3] = 1;
$state['arsse_marks']['rows'][8][4] = $now;
$state['arsse_marks']['rows'][9][3] = 1;
$state['arsse_marks']['rows'][9][4] = $now;
$this->compareExpectations($state);
}
function testMarkByNotLastModified() {
Data::$db->articleMark($this->user, ['starred'=>true], (new Context)->notModifiedSince('2000-01-01T00:00:00Z'));
$now = $this->dateTransform(time(), "sql");
$state = $this->primeExpectations($this->data, $this->checkTables);
$state['arsse_marks']['rows'][] = [$this->user,5,0,1,$now];
$state['arsse_marks']['rows'][] = [$this->user,7,0,1,$now];
$this->compareExpectations($state);
}
}
Loading…
Cancel
Save