aboutsummaryrefslogtreecommitdiff
path: root/app/Models/Entry.php
diff options
context:
space:
mode:
authorGravatar Alexandre Alapetite <alexandre@alapetite.fr> 2022-06-02 08:41:08 +0200
committerGravatar GitHub <noreply@github.com> 2022-06-02 08:41:08 +0200
commitf85c510ed49be031145f6b35e815ce890cd4f9aa (patch)
treec7ac947ba5ddacf85dc5d97330f38f7d91b0964c /app/Models/Entry.php
parentf988b996ab69104bc45b222fa88d34b5c78f98b3 (diff)
New search engine (#4378)
* New possibility to invoke user queries from a search expression From the search field: `S:"My query"`. Can be combined with other filters such as `S:"My query" date:P3d` as long as the user queries do not contain `OR`. A use-case is to have an RSS filter with a stable address or an external API call with the ability to update the user query. * Draft of parenthesis logic * More draft * Working parenthesis (a OR b) (c OR d) * Working (A) OR (B) * Support nested parentheses + unit tests + documentation * search:MySearch and S:3
Diffstat (limited to 'app/Models/Entry.php')
-rw-r--r--app/Models/Entry.php178
1 files changed, 93 insertions, 85 deletions
diff --git a/app/Models/Entry.php b/app/Models/Entry.php
index c3cb337fe..57b0e0b60 100644
--- a/app/Models/Entry.php
+++ b/app/Models/Entry.php
@@ -325,108 +325,116 @@ class FreshRSS_Entry extends Minz_Model {
}
public function matches(FreshRSS_BooleanSearch $booleanSearch): bool {
- if (count($booleanSearch->searches()) <= 0) {
- return true;
- }
+ $ok = true;
foreach ($booleanSearch->searches() as $filter) {
- $ok = true;
- if ($filter->getMinDate()) {
- $ok &= strnatcmp($this->id, $filter->getMinDate() . '000000') >= 0;
- }
- if ($ok && $filter->getNotMinDate()) {
- $ok &= strnatcmp($this->id, $filter->getNotMinDate() . '000000') < 0;
- }
- if ($ok && $filter->getMaxDate()) {
- $ok &= strnatcmp($this->id, $filter->getMaxDate() . '000000') <= 0;
- }
- if ($ok && $filter->getNotMaxDate()) {
- $ok &= strnatcmp($this->id, $filter->getNotMaxDate() . '000000') > 0;
- }
- if ($ok && $filter->getMinPubdate()) {
- $ok &= $this->date >= $filter->getMinPubdate();
- }
- if ($ok && $filter->getNotMinPubdate()) {
- $ok &= $this->date < $filter->getNotMinPubdate();
- }
- if ($ok && $filter->getMaxPubdate()) {
- $ok &= $this->date <= $filter->getMaxPubdate();
- }
- if ($ok && $filter->getNotMaxPubdate()) {
- $ok &= $this->date > $filter->getNotMaxPubdate();
- }
- if ($ok && $filter->getFeedIds()) {
- $ok &= in_array($this->feedId, $filter->getFeedIds());
- }
- if ($ok && $filter->getNotFeedIds()) {
- $ok &= !in_array($this->feedId, $filter->getFeedIds());
- }
- if ($ok && $filter->getAuthor()) {
- foreach ($filter->getAuthor() as $author) {
- $ok &= stripos(implode(';', $this->authors), $author) !== false;
+ if ($filter instanceof FreshRSS_BooleanSearch) {
+ // BooleanSearches are combined by AND (default) or OR (special case) operator and are recursive
+ if ($filter->operator() === 'OR') {
+ $ok |= $this->matches($filter);
+ } else {
+ $ok &= $this->matches($filter);
}
- }
- if ($ok && $filter->getNotAuthor()) {
- foreach ($filter->getNotAuthor() as $author) {
- $ok &= stripos(implode(';', $this->authors), $author) === false;
+ } elseif ($filter instanceof FreshRSS_Search) {
+ // Searches are combined by OR and are not recursive
+ $ok = true;
+ if ($filter->getMinDate()) {
+ $ok &= strnatcmp($this->id, $filter->getMinDate() . '000000') >= 0;
}
- }
- if ($ok && $filter->getIntitle()) {
- foreach ($filter->getIntitle() as $title) {
- $ok &= stripos($this->title, $title) !== false;
+ if ($ok && $filter->getNotMinDate()) {
+ $ok &= strnatcmp($this->id, $filter->getNotMinDate() . '000000') < 0;
}
- }
- if ($ok && $filter->getNotIntitle()) {
- foreach ($filter->getNotIntitle() as $title) {
- $ok &= stripos($this->title, $title) === false;
+ if ($ok && $filter->getMaxDate()) {
+ $ok &= strnatcmp($this->id, $filter->getMaxDate() . '000000') <= 0;
}
- }
- if ($ok && $filter->getTags()) {
- foreach ($filter->getTags() as $tag2) {
- $found = false;
- foreach ($this->tags as $tag1) {
- if (strcasecmp($tag1, $tag2) === 0) {
- $found = true;
+ if ($ok && $filter->getNotMaxDate()) {
+ $ok &= strnatcmp($this->id, $filter->getNotMaxDate() . '000000') > 0;
+ }
+ if ($ok && $filter->getMinPubdate()) {
+ $ok &= $this->date >= $filter->getMinPubdate();
+ }
+ if ($ok && $filter->getNotMinPubdate()) {
+ $ok &= $this->date < $filter->getNotMinPubdate();
+ }
+ if ($ok && $filter->getMaxPubdate()) {
+ $ok &= $this->date <= $filter->getMaxPubdate();
+ }
+ if ($ok && $filter->getNotMaxPubdate()) {
+ $ok &= $this->date > $filter->getNotMaxPubdate();
+ }
+ if ($ok && $filter->getFeedIds()) {
+ $ok &= in_array($this->feedId, $filter->getFeedIds());
+ }
+ if ($ok && $filter->getNotFeedIds()) {
+ $ok &= !in_array($this->feedId, $filter->getFeedIds());
+ }
+ if ($ok && $filter->getAuthor()) {
+ foreach ($filter->getAuthor() as $author) {
+ $ok &= stripos(implode(';', $this->authors), $author) !== false;
+ }
+ }
+ if ($ok && $filter->getNotAuthor()) {
+ foreach ($filter->getNotAuthor() as $author) {
+ $ok &= stripos(implode(';', $this->authors), $author) === false;
+ }
+ }
+ if ($ok && $filter->getIntitle()) {
+ foreach ($filter->getIntitle() as $title) {
+ $ok &= stripos($this->title, $title) !== false;
+ }
+ }
+ if ($ok && $filter->getNotIntitle()) {
+ foreach ($filter->getNotIntitle() as $title) {
+ $ok &= stripos($this->title, $title) === false;
+ }
+ }
+ if ($ok && $filter->getTags()) {
+ foreach ($filter->getTags() as $tag2) {
+ $found = false;
+ foreach ($this->tags as $tag1) {
+ if (strcasecmp($tag1, $tag2) === 0) {
+ $found = true;
+ }
}
+ $ok &= $found;
}
- $ok &= $found;
}
- }
- if ($ok && $filter->getNotTags()) {
- foreach ($filter->getNotTags() as $tag2) {
- $found = false;
- foreach ($this->tags as $tag1) {
- if (strcasecmp($tag1, $tag2) === 0) {
- $found = true;
+ if ($ok && $filter->getNotTags()) {
+ foreach ($filter->getNotTags() as $tag2) {
+ $found = false;
+ foreach ($this->tags as $tag1) {
+ if (strcasecmp($tag1, $tag2) === 0) {
+ $found = true;
+ }
}
+ $ok &= !$found;
}
- $ok &= !$found;
}
- }
- if ($ok && $filter->getInurl()) {
- foreach ($filter->getInurl() as $url) {
- $ok &= stripos($this->link, $url) !== false;
+ if ($ok && $filter->getInurl()) {
+ foreach ($filter->getInurl() as $url) {
+ $ok &= stripos($this->link, $url) !== false;
+ }
}
- }
- if ($ok && $filter->getNotInurl()) {
- foreach ($filter->getNotInurl() as $url) {
- $ok &= stripos($this->link, $url) === false;
+ if ($ok && $filter->getNotInurl()) {
+ foreach ($filter->getNotInurl() as $url) {
+ $ok &= stripos($this->link, $url) === false;
+ }
}
- }
- if ($ok && $filter->getSearch()) {
- foreach ($filter->getSearch() as $needle) {
- $ok &= (stripos($this->title, $needle) !== false || stripos($this->content, $needle) !== false);
+ if ($ok && $filter->getSearch()) {
+ foreach ($filter->getSearch() as $needle) {
+ $ok &= (stripos($this->title, $needle) !== false || stripos($this->content, $needle) !== false);
+ }
}
- }
- if ($ok && $filter->getNotSearch()) {
- foreach ($filter->getNotSearch() as $needle) {
- $ok &= (stripos($this->title, $needle) === false && stripos($this->content, $needle) === false);
+ if ($ok && $filter->getNotSearch()) {
+ foreach ($filter->getNotSearch() as $needle) {
+ $ok &= (stripos($this->title, $needle) === false && stripos($this->content, $needle) === false);
+ }
+ }
+ if ($ok) {
+ return true;
}
- }
- if ($ok) {
- return true;
}
}
- return false;
+ return $ok;
}
public function applyFilterActions(array $titlesAsRead = []) {