From 65b1bb4fcd5f2e2dd7370cd77230e1d21c1a6029 Mon Sep 17 00:00:00 2001 From: "J. King" Date: Tue, 26 Apr 2022 17:13:16 -0400 Subject: [PATCH] Allow multiple dates in TT-RSS searches --- CHANGELOG | 2 ++ .../020_Tiny_Tiny_RSS.md | 2 +- lib/REST/TinyTinyRSS/API.php | 2 +- lib/REST/TinyTinyRSS/Search.php | 13 ++---------- tests/cases/REST/TinyTinyRSS/TestSearch.php | 20 ++++++++++++------- 5 files changed, 19 insertions(+), 20 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 67c3cab..4663d69 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,8 @@ Version 0.1?.? (2022-??-??) =========================== Bug fixes: +- Allow multiple date ranges in search strings in Tiny Tiny RSS +- Honour user time zone when interpreting search strings in Tiny Tiny RSS - Perform MySQL table maintenance more reliably Version 0.10.2 (2022-04-04) diff --git a/docs/en/030_Supported_Protocols/020_Tiny_Tiny_RSS.md b/docs/en/030_Supported_Protocols/020_Tiny_Tiny_RSS.md index e34ca45..5d62a32 100644 --- a/docs/en/030_Supported_Protocols/020_Tiny_Tiny_RSS.md +++ b/docs/en/030_Supported_Protocols/020_Tiny_Tiny_RSS.md @@ -37,7 +37,7 @@ The Arsse does not currently support the entire protocol. Notably missing featur - Processing of the `search` parameter of the `getHeadlines` operation differs in the following ways: - Values other than `"true"` or `"false"` for the `unread`, `star`, and `pub` special keywords treat the entire token as a search term rather than as `"false"` - Invalid dates are ignored rather than assumed to be `"1970-01-01"` - - Only a single negative date is allowed (this is a known bug rather than intentional) + - Specifying multiple non-negative dates usually returns no results as articles must match all specified dates simultaneously; The Arsse instead returns articles matching any of the specified dates - Dates are always relative to UTC - Full-text search is not yet employed with any database, including PostgreSQL - Article hashes are normally SHA1; The Arsse uses SHA256 hashes diff --git a/lib/REST/TinyTinyRSS/API.php b/lib/REST/TinyTinyRSS/API.php index e1c744c..e167fa4 100644 --- a/lib/REST/TinyTinyRSS/API.php +++ b/lib/REST/TinyTinyRSS/API.php @@ -1520,7 +1520,7 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { } // handle the search string, if any if (isset($data['search'])) { - $tz = Arsse::$db->userPropertiesGet(Arsse::$user->id, false)['tz'] ?? "UTC"; + $tz = Arsse::$user->propertiesGet(Arsse::$user->id, false)['tz'] ?? "UTC"; $c = Search::parse($data['search'], $tz, $c); if (!$c) { // the search string inherently returns an empty result, either directly or interacting with other input diff --git a/lib/REST/TinyTinyRSS/Search.php b/lib/REST/TinyTinyRSS/Search.php index 447808f..3ddd24e 100644 --- a/lib/REST/TinyTinyRSS/Search.php +++ b/lib/REST/TinyTinyRSS/Search.php @@ -318,18 +318,9 @@ class Search { $day = $spec->format("Y-m-d"); $start = $day."T00:00:00 $tz"; $end = $day."T23:59:59 $tz"; - // if a date is already set, the same date is a no-op; anything else is a contradiction $cc = $neg ? $c->not : $c; - if ($cc->modifiedRange()) { - if (!$cc->modifiedRange[0] || !$cc->modifiedRange[1] || $cc->modifiedRange[0]->format("c") !== $start || $cc->modifiedRange[1]->format("c") !== $end) { - // FIXME: multiple negative dates should be allowed, but the design of the Context class does not support this - throw new Exception; - } else { - return $c; - } - } - $cc->modifiedRange($start, $end); - return $c; + // NOTE: TTRSS treats multiple positive dates as contradictory; we instead treat them as complimentary instead, because it makes more sense + return $cc->modifiedRanges(array_merge($cc->modifiedRanges, [[$start, $end]])); } protected static function setBoolean(string $tag, string $value, Context $c, bool $neg): Context { diff --git a/tests/cases/REST/TinyTinyRSS/TestSearch.php b/tests/cases/REST/TinyTinyRSS/TestSearch.php index c2e8c60..47683f5 100644 --- a/tests/cases/REST/TinyTinyRSS/TestSearch.php +++ b/tests/cases/REST/TinyTinyRSS/TestSearch.php @@ -101,19 +101,19 @@ class TestSearch extends \JKingWeb\Arsse\Test\AbstractTest { 'Doubled boolean' => ['unread:true unread:true', (new Context)->unread(true)], 'Bare blank date' => ['@', new Context], 'Quoted blank date' => ['"@"', new Context], - 'Bare ISO date' => ['@2019-03-01', (new Context)->modifiedRange("2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z")], - 'Quoted ISO date' => ['"@March 1st, 2019"', (new Context)->modifiedRange("2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z")], - 'Bare negative ISO date' => ['-@2019-03-01', (new Context)->not->modifiedRange("2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z")], - 'Quoted negative English date' => ['"-@March 1st, 2019"', (new Context)->not->modifiedRange("2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z")], + 'Bare ISO date' => ['@2019-03-01', (new Context)->modifiedRanges([["2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z"]])], + 'Quoted ISO date' => ['"@March 1st, 2019"', (new Context)->modifiedRanges([["2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z"]])], + 'Bare negative ISO date' => ['-@2019-03-01', (new Context)->not->modifiedRanges([["2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z"]])], + 'Quoted negative English date' => ['"-@March 1st, 2019"', (new Context)->not->modifiedRanges([["2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z"]])], 'Invalid date' => ['@Bugaboo', new Context], 'Escaped quoted date 1' => ['"@""Yesterday" and today', (new Context)->searchTerms(["and", "today"])], 'Escaped quoted date 2' => ['"@\\"Yesterday" and today', (new Context)->searchTerms(["and", "today"])], 'Escaped quoted date 3' => ['"@Yesterday\\', new Context], 'Escaped quoted date 4' => ['"@Yesterday\\and today', new Context], 'Escaped quoted date 5' => ['"@Yesterday"and today', (new Context)->searchTerms(["today"])], - 'Contradictory dates' => ['@Yesterday @Today', null], - 'Doubled date' => ['"@March 1st, 2019" @2019-03-01', (new Context)->modifiedRange("2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z")], - 'Doubled negative date' => ['"-@March 1st, 2019" -@2019-03-01', (new Context)->not->modifiedRange("2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z")], + 'Contradictory dates' => ['@2010-01-01 @2015-01-01', (new Context)->modifiedRanges([["2010-01-01T00:00:00Z", "2010-01-01T23:59:59Z"], ["2015-01-01T00:00:00Z", "2015-01-01T23:59:59Z"]])], // This differs from TTRSS' behaviour + 'Doubled date' => ['"@March 1st, 2019" @2019-03-01', (new Context)->modifiedRanges([["2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z"]])], + 'Doubled negative date' => ['"-@March 1st, 2019" -@2019-03-01', (new Context)->not->modifiedRanges([["2019-03-01T00:00:00Z", "2019-03-01T23:59:59Z"]])], ]; } @@ -122,4 +122,10 @@ class TestSearch extends \JKingWeb\Arsse\Test\AbstractTest { $act = Search::parse($search, "UTC"); $this->assertEquals($exp, $act); } + + public function testApplySearchToContextWithTimeZone() { + $act = Search::parse("@2022-02-02", "America/Toronto"); + $exp = (new Context)->modifiedRanges([["2022-02-02T05:00:00Z", "2022-02-03T04:59:59Z"]]); + $this->assertEquals($exp, $act); + } }