diff options
| author | 2025-10-15 00:12:19 +0200 | |
|---|---|---|
| committer | 2025-10-15 00:12:19 +0200 | |
| commit | 7e72033859f60f529d4d985da1e9cac0a691b2dc (patch) | |
| tree | a37d63b30afaf78e259c065a367ed8ddeee22755 /app/Models/Search.php | |
| parent | e070c3ed2bec4ea4a6c2a216a5c836d1e02ab381 (diff) | |
Filter on last user modified (#8093)
Example: `userdate:PT1H` to select only articles modified by user during the last hour
Fix https://github.com/FreshRSS/FreshRSS/issues/4280#issuecomment-3393078024
Useful for instance to bulk mark as unread recently marked articles by error:
1. Click on the toggle button to show the read articles (making sure the toggle for the unread articles is off)
2. Sort by *User modified 9→1*
3. Filter by *user modified date*, for instance to the last 3 hours by typing `userdate:PT3H`
4. Click in the drop-down menu *Mark selection as unread*
P.S.: I have added at the same time a bunch of unit tests for date-related logic
Diffstat (limited to 'app/Models/Search.php')
| -rw-r--r-- | app/Models/Search.php | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/app/Models/Search.php b/app/Models/Search.php index e88f745ce..a14f1bf1a 100644 --- a/app/Models/Search.php +++ b/app/Models/Search.php @@ -43,6 +43,10 @@ class FreshRSS_Search implements \Stringable { private $min_pubdate = null; /** @var int|false|null */ private $max_pubdate = null; + /** @var int|false|null */ + private $min_userdate = null; + /** @var int|false|null */ + private $max_userdate = null; /** @var list<string>|null */ private ?array $inurl = null; /** @var list<string>|null */ @@ -86,6 +90,10 @@ class FreshRSS_Search implements \Stringable { private $not_min_pubdate = null; /** @var int|false|null */ private $not_max_pubdate = null; + /** @var int|false|null */ + private $not_min_userdate = null; + /** @var int|false|null */ + private $not_max_userdate = null; /** @var list<string>|null */ private ?array $not_inurl = null; /** @var list<string>|null */ @@ -115,6 +123,7 @@ class FreshRSS_Search implements \Stringable { $input = $this->parseNotLabelIds($input); $input = $this->parseNotLabelNames($input); + $input = $this->parseNotUserdateSearch($input); $input = $this->parseNotPubdateSearch($input); $input = $this->parseNotDateSearch($input); @@ -130,6 +139,7 @@ class FreshRSS_Search implements \Stringable { $input = $this->parseLabelIds($input); $input = $this->parseLabelNames($input); + $input = $this->parseUserdateSearch($input); $input = $this->parsePubdateSearch($input); $input = $this->parseDateSearch($input); @@ -265,6 +275,20 @@ class FreshRSS_Search implements \Stringable { return $this->not_max_pubdate ?: null; } + public function getMinUserdate(): ?int { + return $this->min_userdate ?: null; + } + public function getNotMinUserdate(): ?int { + return $this->not_min_userdate ?: null; + } + + public function getMaxUserdate(): ?int { + return $this->max_userdate ?: null; + } + public function getNotMaxUserdate(): ?int { + return $this->not_max_userdate ?: null; + } + /** @return list<string>|null */ public function getInurl(): ?array { return $this->inurl; @@ -799,6 +823,32 @@ class FreshRSS_Search implements \Stringable { } /** + * Parse the search string to find userdate keyword and the search related to it. + * The search is the first word following the keyword. + */ + private function parseUserdateSearch(string $input): string { + if (preg_match_all('/\\buserdate:(?P<search>[^\\s]*)/', $input, $matches)) { + $input = str_replace($matches[0], '', $input); + $dates = self::removeEmptyValues($matches['search']); + if (!empty($dates[0])) { + [$this->min_userdate, $this->max_userdate] = parseDateInterval($dates[0]); + } + } + return $input; + } + + private function parseNotUserdateSearch(string $input): string { + if (preg_match_all('/(?<=[\\s(]|^)[!-]userdate:(?P<search>[^\\s]*)/', $input, $matches)) { + $input = str_replace($matches[0], '', $input); + $dates = self::removeEmptyValues($matches['search']); + if (!empty($dates[0])) { + [$this->not_min_userdate, $this->not_max_userdate] = parseDateInterval($dates[0]); + } + } + return $input; + } + + /** * Parse the search string to find tags keyword (# followed by a word) * and the search related to it. * The search is the first word following the #. |
