diff --git a/lib/REST/TinyTinyRSS/API.php b/lib/REST/TinyTinyRSS/API.php index d2147095..e1c744cd 100644 --- a/lib/REST/TinyTinyRSS/API.php +++ b/lib/REST/TinyTinyRSS/API.php @@ -1520,7 +1520,8 @@ class API extends \JKingWeb\Arsse\REST\AbstractHandler { } // handle the search string, if any if (isset($data['search'])) { - $c = Search::parse($data['search'], $c); + $tz = Arsse::$db->userPropertiesGet(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 return new ResultEmpty; diff --git a/lib/REST/TinyTinyRSS/Search.php b/lib/REST/TinyTinyRSS/Search.php index 966ea205..447808f7 100644 --- a/lib/REST/TinyTinyRSS/Search.php +++ b/lib/REST/TinyTinyRSS/Search.php @@ -32,7 +32,7 @@ class Search { "" => "searchTerms", ]; - public static function parse(string $search, Context $context = null): ?Context { + public static function parse(string $search, string $tz, Context $context = null): ?Context { // normalize the input $search = strtolower(trim(preg_replace("<\s+>", " ", $search))); // set initial state @@ -88,7 +88,7 @@ class Search { continue 3; case '"': if (($pos + 1 == $stop) || $search[$pos + 1] === " ") { - $context = self::processToken($context, $buffer, $tag, $flag_negative, false); + $context = self::processToken($context, $buffer, $tag, $flag_negative); $state = self::STATE_BEFORE_TOKEN; $flag_negative = false; $buffer = $tag = ""; @@ -135,7 +135,7 @@ class Search { while ($pos < $stop && $search[$pos] !== " ") { $buffer .= $search[$pos++]; } - $context = self::processToken($context, $buffer, $tag, $flag_negative, true); + $context = self::processToken($context, $buffer, $tag, $flag_negative, $tz); $state = self::STATE_BEFORE_TOKEN; $flag_negative = false; $buffer = $tag = ""; @@ -145,7 +145,7 @@ class Search { case "": case '"': if (($pos + 1 >= $stop) || $search[$pos + 1] === " ") { - $context = self::processToken($context, $buffer, $tag, $flag_negative, true); + $context = self::processToken($context, $buffer, $tag, $flag_negative, $tz); $state = self::STATE_BEFORE_TOKEN; $flag_negative = false; $buffer = $tag = ""; @@ -178,7 +178,7 @@ class Search { if (!strlen($tag)) { $buffer = ":".$buffer; } - $context = self::processToken($context, $buffer, $tag, $flag_negative, false); + $context = self::processToken($context, $buffer, $tag, $flag_negative); $state = self::STATE_BEFORE_TOKEN; $flag_negative = false; $buffer = $tag = ""; @@ -191,7 +191,7 @@ class Search { if (!strlen($tag)) { $buffer = ":".$buffer; } - $context = self::processToken($context, $buffer, $tag, $flag_negative, false); + $context = self::processToken($context, $buffer, $tag, $flag_negative); $state = self::STATE_BEFORE_TOKEN; $flag_negative = false; $buffer = $tag = ""; @@ -221,7 +221,7 @@ class Search { switch ($char) { case "": case " ": - $context = self::processToken($context, $buffer, $tag, $flag_negative, false); + $context = self::processToken($context, $buffer, $tag, $flag_negative); $state = self::STATE_BEFORE_TOKEN; $flag_negative = false; $buffer = $tag = ""; @@ -241,7 +241,7 @@ class Search { case "": case '"': if (($pos + 1 >= $stop) || $search[$pos + 1] === " ") { - $context = self::processToken($context, $buffer, $tag, $flag_negative, false); + $context = self::processToken($context, $buffer, $tag, $flag_negative); $state = self::STATE_BEFORE_TOKEN; $flag_negative = false; $buffer = $tag = ""; @@ -282,7 +282,7 @@ class Search { return $context; } - protected static function processToken(Context $c, string $value, string $tag, bool $neg, bool $date): Context { + protected static function processToken(Context $c, string $value, string $tag, bool $neg, string $tz = null): Context { if (!strlen($value) && !strlen($tag)) { return $c; } elseif (!strlen($value)) { @@ -290,8 +290,8 @@ class Search { $value = "$tag:"; $tag = ""; } - if ($date) { - return self::setDate($value, $c, $neg); + if ($tz !== null) { + return self::setDate($value, $c, $neg, $tz); } elseif (isset(self::FIELDS_BOOLEAN[$tag])) { return self::setBoolean($tag, $value, $c, $neg); } else { @@ -309,15 +309,15 @@ class Search { return $c->$type(array_merge($c->$type ?? [], [$value])); } - protected static function setDate(string $value, Context $c, bool $neg): Context { + protected static function setDate(string $value, Context $c, bool $neg, string $tz): Context { $spec = Date::normalize($value); // TTRSS treats invalid dates as the start of the Unix epoch; we ignore them instead if (!$spec) { return $c; } $day = $spec->format("Y-m-d"); - $start = $day."T00:00:00+00:00"; - $end = $day."T23:59:59+00:00"; + $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()) { diff --git a/tests/cases/REST/TinyTinyRSS/TestSearch.php b/tests/cases/REST/TinyTinyRSS/TestSearch.php index 84ca2005..c2e8c604 100644 --- a/tests/cases/REST/TinyTinyRSS/TestSearch.php +++ b/tests/cases/REST/TinyTinyRSS/TestSearch.php @@ -119,7 +119,7 @@ class TestSearch extends \JKingWeb\Arsse\Test\AbstractTest { /** @dataProvider provideSearchStrings */ public function testApplySearchToContext(string $search, $exp): void { - $act = Search::parse($search); + $act = Search::parse($search, "UTC"); $this->assertEquals($exp, $act); } }