summaryrefslogtreecommitdiff
path: root/app/Models/Search.php
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2025-12-24 01:19:06 +0100
committerGravatar GitHub <noreply@github.com> 2025-12-24 01:19:06 +0100
commit00c61cf34c3f9a59b4dc16a4accd7cf85945a5a6 (patch)
tree78cb9940bc1ea860cc261a503f0baf686def7660 /app/Models/Search.php
parent3cd716861259c6d6a984041618c06c146aba4a2d (diff)
Fix serialisation of dates in searches (#8341)
Dates should not be expanded/resolved in string serialisations of search expressions, as it otherwise break relative user queries such as `P30D`. Fix of https://github.com/FreshRSS/FreshRSS/pull/8293
Diffstat (limited to 'app/Models/Search.php')
-rw-r--r--app/Models/Search.php125
1 files changed, 69 insertions, 56 deletions
diff --git a/app/Models/Search.php b/app/Models/Search.php
index 2b207134c..80db5a58c 100644
--- a/app/Models/Search.php
+++ b/app/Models/Search.php
@@ -35,18 +35,15 @@ class FreshRSS_Search implements \Stringable {
private ?array $intext = null;
/** @var list<string>|null */
private ?array $intext_regex = null;
- /** @var int|false|null */
- private $min_date = null;
- /** @var int|false|null */
- private $max_date = null;
- /** @var int|false|null */
- 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;
+ private ?string $input_date = null;
+ private int|false|null $min_date = null;
+ private int|false|null $max_date = null;
+ private ?string $input_pubdate = null;
+ private int|false|null $min_pubdate = null;
+ private int|false|null $max_pubdate = null;
+ private ?string $input_userdate = null;
+ private int|false|null $min_userdate = null;
+ private int|false|null $max_userdate = null;
/** @var list<string>|null */
private ?array $inurl = null;
/** @var list<string>|null */
@@ -82,18 +79,15 @@ class FreshRSS_Search implements \Stringable {
private ?array $not_intext = null;
/** @var list<string>|null */
private ?array $not_intext_regex = null;
- /** @var int|false|null */
- private $not_min_date = null;
- /** @var int|false|null */
- private $not_max_date = null;
- /** @var int|false|null */
- 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;
+ private ?string $input_not_date = null;
+ private int|false|null $not_min_date = null;
+ private int|false|null $not_max_date = null;
+ private ?string $input_not_pubdate = null;
+ private int|false|null $not_min_pubdate = null;
+ private int|false|null $not_max_pubdate = null;
+ private ?string $input_not_userdate = null;
+ private int|false|null $not_min_userdate = null;
+ private int|false|null $not_max_userdate = null;
/** @var list<string>|null */
private ?array $not_inurl = null;
/** @var list<string>|null */
@@ -161,26 +155,27 @@ class FreshRSS_Search implements \Stringable {
return $s;
}
- private static function dateIntervalToString(int|false|null $min, int|false|null $max): string {
- if ($min === false) {
- $min = null;
- }
- if ($max === false) {
- $max = null;
- }
- if ($min === null && $max === null) {
- return '';
- }
- $s = '';
- if ($min !== null) {
- $s .= date('Y-m-d\\TH:i:s', $min);
- }
- $s .= '/';
- if ($max !== null) {
- $s .= date('Y-m-d\\TH:i:s', $max);
- }
- return $s;
- }
+ // TODO: Reuse as option for a string representation resolving and expanding date intervals
+ // private static function dateIntervalToString(int|false|null $min, int|false|null $max): string {
+ // if ($min === false) {
+ // $min = null;
+ // }
+ // if ($max === false) {
+ // $max = null;
+ // }
+ // if ($min === null && $max === null) {
+ // return '';
+ // }
+ // $s = '';
+ // if ($min !== null) {
+ // $s .= date('Y-m-d\\TH:i:s', $min);
+ // }
+ // $s .= '/';
+ // if ($max !== null) {
+ // $s .= date('Y-m-d\\TH:i:s', $max);
+ // }
+ // return $s;
+ // }
/**
* Return true if both searches have the same constraint parameters (even if the values differ), false otherwise.
@@ -287,14 +282,14 @@ class FreshRSS_Search implements \Stringable {
}
}
- if ($this->min_userdate !== null || $this->max_userdate !== null) {
- $result .= ' userdate:' . self::dateIntervalToString($this->min_userdate, $this->max_userdate);
+ if ($this->input_userdate !== null) {
+ $result .= ' userdate:' . $this->input_userdate;
}
- if ($this->min_pubdate !== null || $this->max_pubdate !== null) {
- $result .= ' pubdate:' . self::dateIntervalToString($this->min_pubdate, $this->max_pubdate);
+ if ($this->input_pubdate !== null) {
+ $result .= ' pubdate:' . $this->input_pubdate;
}
- if ($this->min_date !== null || $this->max_date !== null) {
- $result .= ' date:' . self::dateIntervalToString($this->min_date, $this->max_date);
+ if ($this->input_date !== null) {
+ $result .= ' date:' . $this->input_date;
}
if ($this->intitle_regex !== null) {
@@ -378,14 +373,14 @@ class FreshRSS_Search implements \Stringable {
}
}
- if ($this->not_min_userdate !== null || $this->not_max_userdate !== null) {
- $result .= ' -userdate:' . self::dateIntervalToString($this->not_min_userdate, $this->not_max_userdate);
+ if ($this->input_not_userdate !== null) {
+ $result .= ' -userdate:' . $this->input_not_userdate;
}
- if ($this->not_min_pubdate !== null || $this->not_max_pubdate !== null) {
- $result .= ' -pubdate:' . self::dateIntervalToString($this->not_min_pubdate, $this->not_max_pubdate);
+ if ($this->input_not_pubdate !== null) {
+ $result .= ' -pubdate:' . $this->input_not_pubdate;
}
- if ($this->not_min_date !== null || $this->not_max_date !== null) {
- $result .= ' -date:' . self::dateIntervalToString($this->not_min_date, $this->not_max_date);
+ if ($this->input_not_date !== null) {
+ $result .= ' -date:' . $this->input_not_date;
}
if ($this->not_intitle_regex !== null) {
@@ -1069,6 +1064,9 @@ class FreshRSS_Search implements \Stringable {
$dates = self::removeEmptyValues($matches['search']);
if (!empty($dates[0])) {
[$this->min_date, $this->max_date] = parseDateInterval($dates[0]);
+ if (is_int($this->min_date) || is_int($this->max_date)) {
+ $this->input_date = $dates[0];
+ }
}
}
return $input;
@@ -1080,6 +1078,9 @@ class FreshRSS_Search implements \Stringable {
$dates = self::removeEmptyValues($matches['search']);
if (!empty($dates[0])) {
[$this->not_min_date, $this->not_max_date] = parseDateInterval($dates[0]);
+ if (is_int($this->not_min_date) || is_int($this->not_max_date)) {
+ $this->input_not_date = $dates[0];
+ }
}
}
return $input;
@@ -1096,6 +1097,9 @@ class FreshRSS_Search implements \Stringable {
$dates = self::removeEmptyValues($matches['search']);
if (!empty($dates[0])) {
[$this->min_pubdate, $this->max_pubdate] = parseDateInterval($dates[0]);
+ if (is_int($this->min_pubdate) || is_int($this->max_pubdate)) {
+ $this->input_pubdate = $dates[0];
+ }
}
}
return $input;
@@ -1107,6 +1111,9 @@ class FreshRSS_Search implements \Stringable {
$dates = self::removeEmptyValues($matches['search']);
if (!empty($dates[0])) {
[$this->not_min_pubdate, $this->not_max_pubdate] = parseDateInterval($dates[0]);
+ if (is_int($this->not_min_pubdate) || is_int($this->not_max_pubdate)) {
+ $this->input_not_pubdate = $dates[0];
+ }
}
}
return $input;
@@ -1122,6 +1129,9 @@ class FreshRSS_Search implements \Stringable {
$dates = self::removeEmptyValues($matches['search']);
if (!empty($dates[0])) {
[$this->min_userdate, $this->max_userdate] = parseDateInterval($dates[0]);
+ if (is_int($this->min_userdate) || is_int($this->max_userdate)) {
+ $this->input_userdate = $dates[0];
+ }
}
}
return $input;
@@ -1133,6 +1143,9 @@ class FreshRSS_Search implements \Stringable {
$dates = self::removeEmptyValues($matches['search']);
if (!empty($dates[0])) {
[$this->not_min_userdate, $this->not_max_userdate] = parseDateInterval($dates[0]);
+ if (is_int($this->not_min_userdate) || is_int($this->not_max_userdate)) {
+ $this->input_not_userdate = $dates[0];
+ }
}
}
return $input;